@withpica/mcp-server
Version:
MCP Server for withPICA — enables AI assistants to interact with your withPICA music catalog
534 lines • 36 kB
JavaScript
// Copyright (c) 2025-2026 Withpica Ltd. All rights reserved.
import { formatAsText, formatSuccess, formatValidationError, } from "@withpica/mcp-utils";
import { withBillingGate } from "@withpica/mcp-utils";
export class ExportTools {
pica;
constructor(pica) {
this.pica = pica;
}
getTools() {
return [
{
definition: {
name: "pica_export_catalog_csv",
scope: "read:catalog",
audiences: ["stdio", "http", "public"],
tier: "read",
description: "Use when the user asks: 'export this work to PRO', 'register with my distributor', 'generate a PPL submission', 'sync one-sheet for this song'. " +
"Export a single work — or a batch of works — to an industry submission format. " +
"`format` selects the destination: `pro` (CWR-style writer/publisher registration for PRS, ASCAP, BMI, GEMA), " +
"`distributor` (DSP delivery for DistroKid, TuneCore, CD Baby), " +
"`nro` (neighbouring rights for PPL, SoundExchange), " +
"or `sync-pdf` (single-work sync one-sheet PDF). " +
"Pass exactly one of `work_id` (single export — required for `sync-pdf`) or `work_ids` (bulk export, comma-separated UUIDs — not supported for `sync-pdf`). " +
"For `pro`/`distributor`/`nro`, returns the generated CSV as inline text ({format, csv}) — there is no download URL, so present it directly " +
"(e.g. as a code block) or write it to a file; `pica_download` needs a presigned URL and does not apply here. " +
"`sync-pdf` returns structured one-sheet DATA — the rendered one-page PDF exists but is a browser download at " +
"`/api/admin/works/export?format=sync-pdf&as=pdf&workId=<id>`, which streams raw PDF bytes this transport cannot carry; " +
"hand the user that URL, or direct them to https://withpica.com/inspect. Do NOT pass `as` to this tool — it is not an input here. " +
"Direct the user to https://withpica.com/inspect for the full export UI. " +
"For a registration submission the user hands to a PRO/CMO — a ZIP with writer " +
"and writer-summary CSVs plus a CWR field mapping guide — use " +
"pica_export_song_registration instead; this tool returns one flat CSV.",
workflows: ["export-required"],
vernacular_kind: "creator-entry",
inputSchema: {
type: "object",
properties: {
format: {
type: "string",
enum: ["pro", "distributor", "nro", "sync-pdf"],
description: "Export destination format: pro (PRO/CMO registration), distributor (DSP delivery), nro (neighbouring rights), sync-pdf (single-work sync one-sheet).",
},
work_id: {
type: "string",
description: "UUID of a single work to export. Mutually exclusive with work_ids; one of the two is required. Required for sync-pdf format.",
},
work_ids: {
type: "array",
items: { type: "string" },
description: "Array of work UUIDs for bulk export. Mutually exclusive with work_id; one of the two is required. Not supported for sync-pdf format.",
},
},
// NB: the backend ALSO demands exactly one of work_id / work_ids —
// a bare {format} call 400s. JSON-Schema `anyOf` isn't expressible
// in this tool's inputSchema type (and isn't honoured uniformly by
// MCP clients), so the requirement is enforced at runtime in the
// executor below and spelled out in the description (feedback
// 2020c81a).
required: ["format"],
},
},
executor: this.exportCatalogCsv.bind(this),
},
{
definition: {
name: "pica_export_song_registration",
scope: "write:catalog",
audiences: ["stdio", "http", "public"],
tier: "write",
description: "Export works in song registration format for PRO/CMO registration. " +
"This is NOT a CWR file — the ZIP holds CSVs (works, writers, writer summary), JSON, a PDF summary " +
"and `mapping-guide.md`, which maps the CSV columns onto CWR fields for whoever does the submission. " +
"PICA has no CWR emitter; never tell the user you produced a CWR file. " +
"Returns a signed-URL JSON envelope ({ download_url, expires_at, file_size_bytes }) pointing to the generated ZIP. " +
"Filter by ISWC status: pass iswc_status='missing' to export only works that still need an ISWC " +
"(the registration-priority bucket), 'present' for works that already have one, or 'all' (default) " +
"for the entire catalog. " +
"Pass work_ids to scope to a specific set of works (UUIDs); omit for the full catalog. " +
"For a single flat CSV in a named destination format (pro / distributor / nro) " +
"rather than this multi-file bundle, use pica_export_catalog_csv instead.",
workflows: ["export-required"],
vernacular_kind: "specialist",
vernacular_reason: "Specialist context; not yet covered by the Creator Question Atlas — pending telemetry-driven addition per ADR-226 Phase 4 substrate writes.",
inputSchema: {
type: "object",
properties: {
iswc_status: {
type: "string",
enum: ["missing", "present", "all"],
description: "Filter works by ISWC assignment. 'missing' = works without an ISWC (the typical PRO-registration target), 'present' = works that already have an ISWC, 'all' = no filter (default).",
},
work_ids: {
type: "array",
items: { type: "string" },
description: "Optional list of work UUIDs to scope the export to. Omit to export the full catalog.",
},
},
},
},
executor: withBillingGate(this.pica, "song registration export", this.exportSongRegistration.bind(this)),
},
{
definition: {
name: "pica_export_industry_ready",
scope: "write:catalog",
audiences: ["stdio", "http", "public"],
tier: "write",
description: "Use when the user asks: 'export an industry-ready package', 'get a registration-ready bundle', 'export for registration'. " +
"Export industry-ready metadata package — formatted for distribution to publishers, labels, and sync agents. " +
"Returns a signed-URL JSON envelope ({ download_url, expires_at, file_size_bytes }) pointing to the generated ZIP. " +
"Set inline:true to instead receive the structured export DATA inline (no S3 URL) — use this when running in a sandbox whose allowlist can't reach the S3 download host. " +
"Pass work_ids to scope to a specific set of works (UUIDs); omit for the full catalog. " +
"This is the general-purpose hand-off bundle; when the destination is specifically " +
"a PRO/CMO registration, prefer pica_export_song_registration, which adds the " +
"writer-summary CSV and CWR field mapping a registrar needs.",
workflows: ["export-required"],
vernacular_kind: "creator-entry",
inputSchema: {
type: "object",
properties: {
work_ids: {
type: "array",
items: { type: "string" },
description: "Optional list of work UUIDs to scope the export to. Omit to export the full catalog.",
},
inline: {
type: "boolean",
description: "Return the structured export data inline instead of an S3 signed download URL. Use when a sandboxed environment can't fetch the S3 host. Large catalogs may be truncated by the response-size guard — scope with work_ids if so.",
},
},
},
},
executor: withBillingGate(this.pica, "industry-ready export", this.exportIndustryReady.bind(this)),
},
{
definition: {
name: "pica_export_catalog_asset_report",
// write:files, not write:catalog: proxy.ts floors every write under
// /api/admin/exports/* at write:files (ADMIN_SEGMENT_WRITE_FLOOR), so
// a credential holding only write:catalog was refused 403 by the proxy
// before the route ran — a scope the tool advertised and the platform
// did not accept.
scope: "write:files",
audiences: ["stdio", "http", "public"],
tier: "write",
description: "Generate a Catalog Asset Report (CAR) — a unified ZIP bundle with cover PDF, evidence folders, and integrity manifest. Maps creative portfolio data to property-lending equivalents for financial institutions, insurers, PROs, and distributors. Sections include: ownership (title deed equivalent), valuation (surveyor's report), physical assets (contents schedule), agreements (mortgage deed), catalog intelligence (condition report), and summary with equivalence map. " +
"work_ids note: ownership/valuation/agreements sections honour work_ids; assets/intelligence/placements sections remain organisation-wide (their underlying service methods are not yet scope-aware — tracked as a follow-up). " +
"This is the document for an external reader (lender, insurer, buyer). When the " +
"reader is the catalogue owner deciding what to fix next, use pica_export_snapshot " +
"instead — same underlying data, ranked as a to-do list. " +
"The report this tool returns is UNSIGNED: its declaration can only be attested by a person signed in to PICA, from the export panel. Do not tell the user it is signed, and do not sign it for them.",
workflows: ["export-required"],
vernacular_kind: "specialist",
vernacular_reason: "Specialist context; not yet covered by the Creator Question Atlas — pending telemetry-driven addition per ADR-226 Phase 4 substrate writes.",
inputSchema: {
type: "object",
properties: {
sections: {
type: "object",
description: "Which sections to include in the export. Ownership is always included.",
properties: {
valuation: {
type: "boolean",
description: "Include earnings, audio intelligence, DSP presence, completeness scores",
},
assets: {
type: "boolean",
description: "Include physical asset register with insurance and valuations",
},
agreements: {
type: "boolean",
description: "Include agreements structure and AI consent status",
},
intelligence: {
type: "boolean",
description: "Include gap analysis, carbon footprint, diligence readiness",
},
},
},
work_ids: {
type: "array",
items: { type: "string" },
description: "Optional list of work UUIDs to scope the CAR to. Omit to include the full catalog.",
},
},
},
},
executor: withBillingGate(this.pica, "catalog asset report", this.exportCatalogAssetReport.bind(this)),
},
{
definition: {
name: "pica_export_song_dossiers",
// write:files is the floor proxy.ts puts on every write under
// /api/admin/exports/* (ADMIN_SEGMENT_WRITE_FLOOR). The route also
// requires write:catalog, as the catalog-asset-report route does; a
// tool declares one scope, so the description names the second.
scope: "write:files",
audiences: ["stdio", "http", "public"],
tier: "write",
description: "Use when the user asks: 'download everything we know about these songs', 'give me the dossier for song A, C and D', 'export everything about this work', 'package these tracks up'. " +
"Builds one ZIP holding the song dossier of each work named, as a PDF and as JSON: the work, its recordings with credits and ISRCs, the releases those recordings appear on, the people credited with their identifiers, provenance, AI disclosure and consent. Includes a manifest with a SHA-256 hash of every file and a README. " +
"Returns a signed-URL JSON envelope ({ download_url, expires_at, file_size_bytes }) plus works[] saying, per work asked for, whether it was included. Give the user the download_url; it expires in an hour, the stored file in 30 days. " +
"Pass 1 to 60 work_ids (UUIDs — resolve titles with pica_works_query or pica_search_all first, and confirm the matches with the user when a title is ambiguous). More than 60, or a malformed id, is refused rather than truncated. A work that does not exist in this catalogue comes back included=false; tell the user, do not drop it silently. " +
"The credential needs both write:files and write:catalog. " +
"This downloads a file for the catalogue owner. It does not send anything to anyone: to share a work with another person use pica_share_send. " +
"For one work's dossier as structured data in this conversation, use pica_works_inspect with sections=['dossier'] instead. " +
"For a ranked list of what to fix rather than the full record of each song, use pica_export_snapshot instead.",
workflows: ["export-required"],
vernacular_kind: "creator-entry",
inputSchema: {
type: "object",
properties: {
work_ids: {
type: "array",
items: { type: "string" },
minItems: 1,
maxItems: 60,
description: "The works to bundle, as UUIDs, in the order they should appear. 1 to 60.",
},
},
required: ["work_ids"],
},
},
executor: withBillingGate(this.pica, "song dossier bundle", this.exportSongDossiers.bind(this)),
},
{
definition: {
name: "pica_export_snapshot",
scope: "write:catalog",
audiences: ["stdio", "http", "public"],
tier: "write",
description: "Use when the user asks: 'give me a snapshot of my catalogue', 'what shape is my catalogue in', 'what should I fix next'. " +
"Export the catalogue snapshot: PICA score with per-pillar detail, financial summary, ownership coverage, gaps ranked by severity each with a suggested action, physical assets, production-asset provenance (the equipment a recording was made on), and a prioritised what-to-do-next list. " +
"Scope it with scope='work' plus a single work_id for a deep dive on one work, 'selected' with several work_ids, or 'everything' (default) for the whole catalogue. " +
"For a diligence document aimed at a lender or buyer, use pica_export_catalog_asset_report instead — this one is aimed at the catalogue owner deciding what to fix. " +
"For everything PICA holds about specific songs (recordings, releases, credits, people), use pica_export_song_dossiers.",
workflows: ["export-required"],
vernacular_kind: "creator-entry",
inputSchema: {
type: "object",
properties: {
scope: {
type: "string",
enum: ["everything", "selected", "work"],
description: "everything = whole catalogue (default); selected = the given work_ids; work = exactly one work_id, a deep dive.",
},
work_ids: {
type: "array",
items: { type: "string" },
description: "Work UUIDs. Required for 'work' (exactly one) and 'selected' (one or more); ignored for 'everything'.",
},
},
},
},
executor: withBillingGate(this.pica, "catalogue snapshot export", this.exportSnapshot.bind(this)),
},
{
definition: {
name: "pica_export_ownership_record",
scope: "write:catalog",
audiences: ["stdio", "http", "public"],
tier: "write",
description: "Use when the user asks: 'who owns this catalogue?', 'send my lawyer the ownership record', 'prove who owns what'. " +
"Export the ownership record — a per-contributor and per-asset register of who owns what, with claim status, share percentages and the definitions a lawyer needs to read it (claim workflow, dispute resolution, what each status means). This is the REGISTER; pica_export_rights_proof is the EVIDENCE behind it. Both exist because they answer different questions for different readers. " +
"Returns a signed-URL JSON envelope ({ download_url, expires_at, file_size_bytes }) pointing to the generated ZIP. " +
"Pass inline=true to receive the structured data instead, for a sandboxed agent that cannot fetch a signed S3 URL.",
workflows: ["export-required"],
vernacular_kind: "specialist",
vernacular_reason: "Diligence documents are specialist context; added 2026-07-30 (ADR-303) to close a UI/MCP parity gap, not from telemetry.",
inputSchema: {
type: "object",
properties: {
inline: {
type: "boolean",
description: "Return the structured export data inline instead of a signed download URL. Use when you cannot fetch an S3 URL.",
},
},
},
},
executor: withBillingGate(this.pica, "ownership record export", this.exportOwnershipRecord.bind(this)),
},
{
definition: {
name: "pica_export_rights_proof",
scope: "write:catalog",
audiences: ["stdio", "http", "public"],
tier: "write",
description: "Use when the user asks: 'prove the chain of title', 'what evidence do we have', 'send the proof bundle to the buyer'. " +
"Export the rights proof bundle — timestamped ownership claims, contributor attestations, identity verification and evidence-integrity hashes. This is the EVIDENCE; pica_export_ownership_record is the register it supports. Use this when someone has asked you to prove ownership rather than state it. " +
"Returns a signed-URL JSON envelope ({ download_url, expires_at, file_size_bytes }) pointing to the generated ZIP. " +
"Pass inline=true to receive the structured data instead, for a sandboxed agent that cannot fetch a signed S3 URL.",
workflows: ["export-required"],
vernacular_kind: "specialist",
vernacular_reason: "Diligence documents are specialist context; added 2026-07-30 (ADR-303) to close a UI/MCP parity gap, not from telemetry.",
inputSchema: {
type: "object",
properties: {
inline: {
type: "boolean",
description: "Return the structured export data inline instead of a signed download URL. Use when you cannot fetch an S3 URL.",
},
},
},
},
executor: withBillingGate(this.pica, "rights proof export", this.exportRightsProof.bind(this)),
},
{
definition: {
name: "pica_export_diligence_pack",
scope: "write:catalog",
audiences: ["stdio", "http", "public"],
tier: "write",
description: "Use when the user asks: 'send me the diligence pack', 'what is missing before I register', 'prepare for a catalogue sale'. " +
"Export the catalogue diligence pack as a document — readiness scoring, ownership clarity, identifier completeness, uninsured insurable assets, and gaps ranked by severity with a suggested action for each. For the ANSWER rather than the document, call pica_catalog_diligence, which returns the same analysis as JSON and is cheaper; for a lender's asset report, use pica_export_catalog_asset_report. " +
"Returns a signed-URL JSON envelope for the generated ZIP. " +
"Pass inline=true for the structured data instead, when a sandboxed agent cannot fetch a signed S3 URL.",
workflows: ["export-required"],
vernacular_kind: "specialist",
vernacular_reason: "Diligence documents are specialist context; added 2026-07-30 (ADR-303) to close a UI/MCP parity gap, not from telemetry.",
inputSchema: {
type: "object",
properties: {
inline: {
type: "boolean",
description: "Return the structured export data inline instead of a signed download URL. Use when you cannot fetch an S3 URL.",
},
},
},
},
executor: withBillingGate(this.pica, "diligence pack export", this.exportDiligencePack.bind(this)),
},
{
definition: {
name: "pica_export_ai_consent",
scope: "read:catalog",
audiences: ["stdio", "http", "public"],
tier: "read",
description: "Use when the user asks: 'export my AI consent', 'send the consent file to a licensor', " +
"'give me the AI consent paperwork', 'what data have I consented to AI training?'. " +
"This produces the FILE. For the ANSWER — how much of the catalogue is clearable and " +
"who is blocking — use pica_consent_readiness instead; it is one call and returns " +
"the rollup directly. " +
"Exports the AI usage consent file: contributor-level consent status, per-asset " +
"cleared level and permitted uses, and the full grant/revoke history, bundled as a " +
"downloadable ZIP with CSVs and a PDF summary. " +
"Pass work_ids to scope the works listing to a specific set of works (UUIDs); omit for the full catalog. " +
"work_ids note: scopes the works listing but contributor and consent-history rollups remain organisation-wide. " +
"For the account holder's own personal data export, use pica_export_my_data.",
workflows: ["export-required"],
vernacular_kind: "creator-entry",
inputSchema: {
type: "object",
properties: {
work_ids: {
type: "array",
items: { type: "string" },
description: "Optional list of work UUIDs to scope the export to. Omit to export the full catalog.",
},
},
},
},
executor: this.exportAiConsent.bind(this),
},
];
}
async exportCatalogCsv(args) {
// Guard the work_id / work_ids requirement client-side so the caller gets a
// clear validation error instead of a backend 400 that reads like a data
// problem (feedback 2020c81a).
const hasWorkId = typeof args.work_id === "string" && args.work_id.length > 0;
const hasWorkIds = Array.isArray(args.work_ids) && args.work_ids.length > 0;
if (!hasWorkId && !hasWorkIds) {
return formatValidationError({
work_id: "Provide exactly one of work_id (single export) or work_ids (bulk export). The export backend requires at least one work to export.",
});
}
if (hasWorkId && hasWorkIds) {
return formatValidationError({
work_id: "Provide either work_id or work_ids, not both.",
});
}
const result = await this.pica.exports.catalogCsv({
format: args.format,
work_id: args.work_id,
work_ids: args.work_ids,
});
return formatAsText(result);
}
async exportSongRegistration(args) {
const iswcStatus = args?.iswc_status;
const workIds = args?.work_ids;
const params = {};
if (iswcStatus)
params.iswc_status = iswcStatus;
if (workIds && workIds.length > 0)
params.work_ids = workIds;
const result = await this.pica.exports.songRegistration(Object.keys(params).length > 0 ? params : undefined);
const data = result?.data ?? result;
// ADR-146: Surface export gate warnings
const parts = ["Song registration export generated"];
if (data?.exportReadiness?.blockers?.length > 0) {
parts.push(`\n--- export gate (${data.exportReadiness.mode} mode) ---`);
for (const b of data.exportReadiness.blockers) {
parts.push(`${b.type}: ${b.workTitle} — ${b.resolutionHint}`);
}
if (data.exportReadiness.mode === "advisory") {
parts.push("These issues will block export when enforcement mode is enabled.");
}
}
return formatSuccess(parts.join("\n"), data);
}
async exportIndustryReady(args) {
const workIds = args?.work_ids;
const inline = args?.inline === true;
const result = await this.pica.exports.industryReady({
...(workIds && workIds.length > 0 ? { work_ids: workIds } : {}),
// inline → format=json: the route returns the structured export DATA
// inline instead of an S3 signed URL a sandboxed agent can't fetch
// (ops_issue 8662c489). The response-size guard truncates if it ever
// exceeds the cap.
...(inline ? { format: "json" } : {}),
});
return formatSuccess(inline
? "Industry-ready export data (inline)"
: "Industry-ready export generated", result);
}
async exportCatalogAssetReport(args) {
const sections = {
ownership: true,
valuation: args.sections?.valuation ?? true,
assets: args.sections?.assets ?? true,
agreements: args.sections?.agreements ?? true,
intelligence: args.sections?.intelligence ?? true,
};
// No attestation: the declaration goes to lenders and insurers, and only a
// person signed in to PICA may make it. The route refuses one from an
// agent; this tool used to send `signer_name: "MCP Agent"` pre-accepted.
const workIds = args?.work_ids;
const result = await this.pica.exports.catalogAssetReport({
sections,
...(workIds && workIds.length > 0 ? { work_ids: workIds } : {}),
});
const data = result?.data ?? result;
let summary = [
`Catalog Asset Report generated`,
`Stage: ${data.stage ?? "unknown"}`,
`PICA Score: ${data.pica_score ?? "N/A"}${data.pica_grade ? ` (${data.pica_grade})` : ""}`,
`Sections: ownership${sections.valuation ? ", valuation" : ""}${sections.assets ? ", assets" : ""}${sections.agreements ? ", agreements" : ""}${sections.intelligence ? ", intelligence" : ""}`,
"Attestation: not signed. Only a person signed in to PICA can attest this report, from the export panel.",
data.file_size_bytes
? `Size: ${(data.file_size_bytes / 1024).toFixed(1)} KB`
: null,
data.download_url ? `Download: ${data.download_url}` : null,
]
.filter(Boolean)
.join("\n");
// ADR-146: Surface export gate warnings
if (data?.exportReadiness?.blockers?.length > 0) {
summary += `\nExport gate (${data.exportReadiness.mode} mode): ${data.exportReadiness.blockers.length} blocker(s)`;
for (const b of data.exportReadiness.blockers.slice(0, 5)) {
summary += `\n ${b.type}: ${b.workTitle} — ${b.resolutionHint}`;
}
if (data.exportReadiness.blockers.length > 5) {
summary += `\n ... and ${data.exportReadiness.blockers.length - 5} more`;
}
}
return formatSuccess(summary, data);
}
async exportSongDossiers(args) {
const workIds = Array.isArray(args?.work_ids)
? args.work_ids.filter((id) => typeof id === "string")
: [];
if (workIds.length === 0) {
return formatValidationError({
work_ids: "required: pass the UUIDs of the works to bundle (1 to 60).",
});
}
const result = await this.pica.exports.songDossiers({ work_ids: workIds });
const data = result?.data ?? result;
const works = Array.isArray(data?.works) ? data.works : [];
const missing = works.filter((w) => !w.included);
const summary = [
`Song dossier bundle generated: ${works.length - missing.length} of ${works.length} work(s) included`,
...works
.filter((w) => w.included)
.map((w) => ` ✓ ${w.title ?? w.work_id}`),
...missing.map((w) => ` ✗ ${w.work_id} — not found in this catalogue, no dossier`),
data?.file_size_bytes
? `Size: ${(data.file_size_bytes / 1024).toFixed(1)} KB`
: null,
data?.download_url
? `Download (link valid 1 hour): ${data.download_url}`
: null,
]
.filter(Boolean)
.join("\n");
return formatSuccess(summary, data);
}
async exportAiConsent(args) {
const workIds = args?.work_ids;
const result = await this.pica.exports.aiConsent(workIds && workIds.length > 0 ? { work_ids: workIds } : undefined);
return formatSuccess("AI consent declarations exported — shows disclosure level and training rights per work", result);
}
async exportOwnershipRecord(args) {
const result = await this.pica.exports.ownershipRecord(args?.inline === true ? { inline: true } : undefined);
return formatSuccess("ownership record generated", result?.data ?? result);
}
async exportRightsProof(args) {
const result = await this.pica.exports.rightsProof(args?.inline === true ? { inline: true } : undefined);
return formatSuccess("rights proof generated", result?.data ?? result);
}
async exportDiligencePack(args) {
const result = await this.pica.exports.diligencePack(args?.inline === true ? { inline: true } : undefined);
return formatSuccess("diligence pack generated", result?.data ?? result);
}
async exportSnapshot(args) {
const scope = (args?.scope ?? "everything");
const workIds = args?.work_ids;
// The route validates this too, but a 400 reaches the agent as an opaque
// failure; saying it here makes the retry obvious.
if (scope === "work" && workIds?.length !== 1) {
return formatSuccess("scope='work' needs exactly one work_id. Pass one, or use scope='selected' for several.", { error: "INVALID_SCOPE" });
}
if (scope === "selected" && !workIds?.length) {
return formatSuccess("scope='selected' needs at least one work_id. Pass some, or use scope='everything'.", { error: "INVALID_SCOPE" });
}
const result = await this.pica.exports.picaSnapshot({
scope,
...(workIds?.length ? { work_ids: workIds } : {}),
});
return formatSuccess("catalogue snapshot generated", result?.data ?? result);
}
}
//# sourceMappingURL=exports.js.map