@withpica/mcp-server 2.97.4 → 2.98.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +152 -0
- package/README.intro.md +1 -1
- package/README.md +9 -5
- package/dist/lib/changelog.generated.d.ts +2 -2
- package/dist/lib/changelog.generated.d.ts.map +1 -1
- package/dist/lib/changelog.generated.js +2 -2
- package/dist/lib/changelog.generated.js.map +1 -1
- package/dist/prompts/creator-question-atlas.d.ts.map +1 -1
- package/dist/prompts/creator-question-atlas.js +23 -0
- package/dist/prompts/creator-question-atlas.js.map +1 -1
- package/dist/prompts/index.d.ts.map +1 -1
- package/dist/prompts/index.js +22 -25
- package/dist/prompts/index.js.map +1 -1
- package/dist/resources/agent-guide.d.ts.map +1 -1
- package/dist/resources/agent-guide.js +4 -2
- package/dist/resources/agent-guide.js.map +1 -1
- package/dist/resources/required-schemas.generated.d.ts +13 -7
- package/dist/resources/required-schemas.generated.d.ts.map +1 -1
- package/dist/resources/required-schemas.generated.js +23 -4
- package/dist/resources/required-schemas.generated.js.map +1 -1
- package/dist/resources/required-schemas.source.d.ts.map +1 -1
- package/dist/resources/required-schemas.source.js +15 -3
- package/dist/resources/required-schemas.source.js.map +1 -1
- package/dist/server-instructions.d.ts +2 -2
- package/dist/server-instructions.d.ts.map +1 -1
- package/dist/server-instructions.js +1 -1
- package/dist/skills/skills.generated.js +5 -5
- package/dist/skills/skills.generated.js.map +1 -1
- package/dist/tools/agreement-types.d.ts.map +1 -1
- package/dist/tools/agreement-types.js +3 -1
- package/dist/tools/agreement-types.js.map +1 -1
- package/dist/tools/agreements.d.ts.map +1 -1
- package/dist/tools/agreements.js +15 -6
- package/dist/tools/agreements.js.map +1 -1
- package/dist/tools/approvals.d.ts.map +1 -1
- package/dist/tools/approvals.js +14 -1
- package/dist/tools/approvals.js.map +1 -1
- package/dist/tools/arg-aliases.d.ts.map +1 -1
- package/dist/tools/arg-aliases.js +12 -0
- package/dist/tools/arg-aliases.js.map +1 -1
- package/dist/tools/audio-files.d.ts +39 -0
- package/dist/tools/audio-files.d.ts.map +1 -1
- package/dist/tools/audio-files.js +253 -12
- package/dist/tools/audio-files.js.map +1 -1
- package/dist/tools/catalog-enums.d.ts +20 -0
- package/dist/tools/catalog-enums.d.ts.map +1 -0
- package/dist/tools/catalog-enums.js +28 -0
- package/dist/tools/catalog-enums.js.map +1 -0
- package/dist/tools/credits.d.ts.map +1 -1
- package/dist/tools/credits.js +69 -8
- package/dist/tools/credits.js.map +1 -1
- package/dist/tools/custody-hints.js +2 -2
- package/dist/tools/custody-hints.js.map +1 -1
- package/dist/tools/custody.d.ts.map +1 -1
- package/dist/tools/custody.js +4 -1
- package/dist/tools/custody.js.map +1 -1
- package/dist/tools/deprecations.d.ts +2 -1
- package/dist/tools/deprecations.d.ts.map +1 -1
- package/dist/tools/deprecations.js +27 -11
- package/dist/tools/deprecations.js.map +1 -1
- package/dist/tools/directory.js +2 -2
- package/dist/tools/directory.js.map +1 -1
- package/dist/tools/discovery.d.ts.map +1 -1
- package/dist/tools/discovery.js +14 -3
- package/dist/tools/discovery.js.map +1 -1
- package/dist/tools/duplicates.d.ts.map +1 -1
- package/dist/tools/duplicates.js +66 -18
- package/dist/tools/duplicates.js.map +1 -1
- package/dist/tools/enrichment.d.ts.map +1 -1
- package/dist/tools/enrichment.js +36 -2
- package/dist/tools/enrichment.js.map +1 -1
- package/dist/tools/exports.d.ts +1 -0
- package/dist/tools/exports.d.ts.map +1 -1
- package/dist/tools/exports.js +69 -2
- package/dist/tools/exports.js.map +1 -1
- package/dist/tools/import.d.ts.map +1 -1
- package/dist/tools/import.js +19 -0
- package/dist/tools/import.js.map +1 -1
- package/dist/tools/index.d.ts.map +1 -1
- package/dist/tools/index.js +44 -4
- package/dist/tools/index.js.map +1 -1
- package/dist/tools/licensing.d.ts.map +1 -1
- package/dist/tools/licensing.js +14 -9
- package/dist/tools/licensing.js.map +1 -1
- package/dist/tools/metadata.d.ts.map +1 -1
- package/dist/tools/metadata.js +58 -12
- package/dist/tools/metadata.js.map +1 -1
- package/dist/tools/notes.d.ts.map +1 -1
- package/dist/tools/notes.js +28 -5
- package/dist/tools/notes.js.map +1 -1
- package/dist/tools/people.d.ts +5 -1
- package/dist/tools/people.d.ts.map +1 -1
- package/dist/tools/people.js +8 -1
- package/dist/tools/people.js.map +1 -1
- package/dist/tools/purchases.d.ts +2 -3
- package/dist/tools/purchases.d.ts.map +1 -1
- package/dist/tools/purchases.js.map +1 -1
- package/dist/tools/recording-attribution-hints.js +1 -1
- package/dist/tools/recording-attribution-hints.js.map +1 -1
- package/dist/tools/recording-custody.d.ts +3 -1
- package/dist/tools/recording-custody.d.ts.map +1 -1
- package/dist/tools/recording-custody.js +8 -4
- package/dist/tools/recording-custody.js.map +1 -1
- package/dist/tools/recovery-hints.d.ts +0 -6
- package/dist/tools/recovery-hints.d.ts.map +1 -1
- package/dist/tools/recovery-hints.js +98 -20
- package/dist/tools/recovery-hints.js.map +1 -1
- package/dist/tools/register.d.ts.map +1 -1
- package/dist/tools/register.js +2 -1
- package/dist/tools/register.js.map +1 -1
- package/dist/tools/releases.d.ts.map +1 -1
- package/dist/tools/releases.js +7 -4
- package/dist/tools/releases.js.map +1 -1
- package/dist/tools/rights.d.ts +45 -0
- package/dist/tools/rights.d.ts.map +1 -0
- package/dist/tools/rights.js +302 -0
- package/dist/tools/rights.js.map +1 -0
- package/dist/tools/royalties.d.ts +24 -1
- package/dist/tools/royalties.d.ts.map +1 -1
- package/dist/tools/royalties.js +99 -66
- package/dist/tools/royalties.js.map +1 -1
- package/dist/tools/section-validation.d.ts +14 -0
- package/dist/tools/section-validation.d.ts.map +1 -0
- package/dist/tools/section-validation.js +68 -0
- package/dist/tools/section-validation.js.map +1 -0
- package/dist/tools/selections.d.ts +5 -2
- package/dist/tools/selections.d.ts.map +1 -1
- package/dist/tools/selections.js +10 -4
- package/dist/tools/selections.js.map +1 -1
- package/dist/tools/settings.d.ts.map +1 -1
- package/dist/tools/settings.js +11 -7
- package/dist/tools/settings.js.map +1 -1
- package/dist/tools/share-links.d.ts.map +1 -1
- package/dist/tools/share-links.js +32 -6
- package/dist/tools/share-links.js.map +1 -1
- package/dist/tools/share-send.d.ts.map +1 -1
- package/dist/tools/share-send.js +32 -7
- package/dist/tools/share-send.js.map +1 -1
- package/dist/tools/signed-split-sheet-preview.d.ts +43 -0
- package/dist/tools/signed-split-sheet-preview.d.ts.map +1 -0
- package/dist/tools/signed-split-sheet-preview.js +67 -0
- package/dist/tools/signed-split-sheet-preview.js.map +1 -0
- package/dist/tools/split-sheets.d.ts +19 -0
- package/dist/tools/split-sheets.d.ts.map +1 -1
- package/dist/tools/split-sheets.js +108 -15
- package/dist/tools/split-sheets.js.map +1 -1
- package/dist/tools/works.d.ts +9 -1
- package/dist/tools/works.d.ts.map +1 -1
- package/dist/tools/works.js +197 -66
- package/dist/tools/works.js.map +1 -1
- package/dist/tools/write-receipt.d.ts +68 -0
- package/dist/tools/write-receipt.d.ts.map +1 -0
- package/dist/tools/write-receipt.js +64 -0
- package/dist/tools/write-receipt.js.map +1 -0
- package/package.json +4 -4
- package/scripts/build-required-schemas.ts +7 -1
- package/server.json +2 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"approvals.d.ts","sourceRoot":"","sources":["../../src/tools/approvals.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,UAAU,EAAuB,MAAM,mBAAmB,CAAC;AACpE,OAAO,EAAE,cAAc,EAAE,YAAY,EAAc,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"approvals.d.ts","sourceRoot":"","sources":["../../src/tools/approvals.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,UAAU,EAAuB,MAAM,mBAAmB,CAAC;AACpE,OAAO,EAAE,cAAc,EAAE,YAAY,EAAc,MAAM,YAAY,CAAC;AAItE,qBAAa,cAAc;IACzB,OAAO,CAAC,IAAI,CAAa;gBAEb,IAAI,EAAE,UAAU;IAI5B,QAAQ,IAAI,KAAK,CAAC;QAAE,UAAU,EAAE,cAAc,CAAC;QAAC,QAAQ,EAAE,YAAY,CAAA;KAAE,CAAC;IA6DzE;;;;;OAKG;YACW,iBAAiB;CAuDhC"}
|
package/dist/tools/approvals.js
CHANGED
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
*/
|
|
13
13
|
import { EntityNotFoundError } from "@withpica/mcp-sdk";
|
|
14
14
|
import { formatSuccess } from "@withpica/mcp-utils";
|
|
15
|
+
import { applyArgAliases } from "./arg-aliases.js";
|
|
15
16
|
export class ApprovalsTools {
|
|
16
17
|
pica;
|
|
17
18
|
constructor(pica) {
|
|
@@ -78,7 +79,19 @@ export class ApprovalsTools {
|
|
|
78
79
|
* an unknown reference without crashing its loop.
|
|
79
80
|
*/
|
|
80
81
|
async getApprovalStatus(args) {
|
|
81
|
-
|
|
82
|
+
// The deferral envelope names this value `approval_reference`, so accept
|
|
83
|
+
// that spelling on a DIRECT call too. `pica_execute` applies the same
|
|
84
|
+
// alias before dispatch; resolving it here through the one alias table
|
|
85
|
+
// (`TOOL_ARG_ALIASES.pica_approval_status`) keeps direct and wrapped calls
|
|
86
|
+
// agreeing. Without it a direct `{approval_reference}` fell into the
|
|
87
|
+
// branch below and was answered `status: "not_found"` for an approval
|
|
88
|
+
// that exists. Pinned by `execute-approval-reference.test.ts`.
|
|
89
|
+
const { args: resolved } = applyArgAliases("pica_approval_status", args, [
|
|
90
|
+
"approval_id",
|
|
91
|
+
]);
|
|
92
|
+
const approvalId = typeof resolved.approval_id === "string"
|
|
93
|
+
? resolved.approval_id.trim()
|
|
94
|
+
: "";
|
|
82
95
|
if (!approvalId) {
|
|
83
96
|
// ⚠️ An agent lands here when a person points at the "N awaiting
|
|
84
97
|
// approval" figure on /inspect and asks it to clear them. There is no
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"approvals.js","sourceRoot":"","sources":["../../src/tools/approvals.ts"],"names":[],"mappings":"AAAA,6DAA6D;AAE7D;;;;;;;;;;GAUG;AAEH,OAAO,EAAc,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAEpE,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"approvals.js","sourceRoot":"","sources":["../../src/tools/approvals.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"arg-aliases.d.ts","sourceRoot":"","sources":["../../src/tools/arg-aliases.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AAEH;;;;GAIG;AACH,eAAO,MAAM,iBAAiB,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAc/D,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,gBAAgB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,
|
|
1
|
+
{"version":3,"file":"arg-aliases.d.ts","sourceRoot":"","sources":["../../src/tools/arg-aliases.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AAEH;;;;GAIG;AACH,eAAO,MAAM,iBAAiB,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAc/D,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,gBAAgB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAyBnE,CAAC;AAEF,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC9B,OAAO,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CAC9C;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAC7B,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7B,QAAQ,EAAE,SAAS,MAAM,EAAE,GAC1B,cAAc,CA0BhB"}
|
|
@@ -70,6 +70,18 @@ export const TOOL_ARG_ALIASES = {
|
|
|
70
70
|
actionIds: "accept",
|
|
71
71
|
action_ids: "accept",
|
|
72
72
|
},
|
|
73
|
+
// A deferred write answers with a `human_approval_required` envelope that
|
|
74
|
+
// carries the id as `approval_reference` and names `pica_approval_status`
|
|
75
|
+
// as its `poll_tool` (`buildAgentResponse`, lib/services/human-approval-gate.ts)
|
|
76
|
+
// — but the poll tool's schema calls the same value `approval_id`. Agents
|
|
77
|
+
// copy the key they were just handed, so PICA's own two names for one value
|
|
78
|
+
// drew WRAPPED_ARGS_MISSING 10 times on prod, from Claude and ChatGPT alike
|
|
79
|
+
// (ops issue da9ba396, 2026-07-05 → 2026-09-28). Pinned end to end, against
|
|
80
|
+
// the real tool definition, by
|
|
81
|
+
// `src/__tests__/tools/execute-approval-reference.test.ts`.
|
|
82
|
+
pica_approval_status: {
|
|
83
|
+
approval_reference: "approval_id",
|
|
84
|
+
},
|
|
73
85
|
};
|
|
74
86
|
/**
|
|
75
87
|
* Rename a tool's own id / explicit alias to the schema's real required
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"arg-aliases.js","sourceRoot":"","sources":["../../src/tools/arg-aliases.ts"],"names":[],"mappings":"AAAA,6DAA6D;AAE7D;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AAEH;;;;GAIG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAsC;IAClE,KAAK,EAAE,CAAC,eAAe,EAAE,UAAU,EAAE,SAAS,CAAC;IAC/C,MAAM,EAAE,CAAC,WAAW,EAAE,WAAW,CAAC;IAClC,KAAK,EAAE,CAAC,SAAS,CAAC;IAClB,UAAU,EAAE,CAAC,cAAc,CAAC;IAC5B,QAAQ,EAAE,CAAC,YAAY,CAAC;IACxB,UAAU,EAAE,CAAC,cAAc,CAAC;IAC5B,QAAQ,EAAE,CAAC,YAAY,CAAC;IACxB,KAAK,EAAE,CAAC,SAAS,CAAC;IAClB,QAAQ,EAAE,CAAC,YAAY,CAAC;IACxB,SAAS,EAAE,CAAC,aAAa,CAAC;IAC1B,KAAK,EAAE,CAAC,SAAS,CAAC;IAClB,MAAM,EAAE,CAAC,UAAU,CAAC;IACpB,UAAU,EAAE,CAAC,cAAc,CAAC;CAC7B,CAAC;AAEF;;;;GAIG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAA2C;IACtE,cAAc,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE;IACrD,4EAA4E;IAC5E,2EAA2E;IAC3E,yEAAyE;IACzE,0EAA0E;IAC1E,2EAA2E;IAC3E,0EAA0E;IAC1E,8CAA8C;IAC9C,uBAAuB,EAAE;QACvB,SAAS,EAAE,QAAQ;QACnB,UAAU,EAAE,QAAQ;KACrB;CACF,CAAC;AAOF;;;;GAIG;AACH,MAAM,UAAU,eAAe,CAC7B,QAAgB,EAChB,IAA6B,EAC7B,QAA2B;IAE3B,MAAM,MAAM,GAAG,QAAQ,CAAC,OAAO,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;IAClE,MAAM,WAAW,GAAG,gBAAgB,CAAC,QAAQ,CAAC,CAAC;IAC/C,MAAM,OAAO,GAAwC,EAAE,CAAC;IACxD,MAAM,MAAM,GAA4B,EAAE,GAAG,IAAI,EAAE,CAAC;IAEpD,KAAK,MAAM,KAAK,IAAI,QAAQ,EAAE,CAAC;QAC7B,IAAI,KAAK,IAAI,MAAM;YAAE,SAAS,CAAC,oCAAoC;QAEnE,MAAM,UAAU,GACd,KAAK,KAAK,IAAI;YACZ,CAAC,CAAC,CAAC,GAAG,CAAC,iBAAiB,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC;YACxC,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,WAAW,IAAI,EAAE,CAAC;iBAC9B,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC,EAAE,KAAK,KAAK,CAAC;iBAChC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,CAAC;QAE/B,MAAM,OAAO,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,IAAI,MAAM,CAAC,CAAC;QACtD,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;YAAE,SAAS,CAAC,qCAAqC;QAEzE,MAAM,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC;QACvB,MAAM,CAAC,KAAK,CAAC,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC;QAC7B,OAAO,MAAM,CAAC,IAAI,CAAC,CAAC;QACpB,OAAO,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC;IACpC,CAAC;IAED,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC;AACnC,CAAC"}
|
|
1
|
+
{"version":3,"file":"arg-aliases.js","sourceRoot":"","sources":["../../src/tools/arg-aliases.ts"],"names":[],"mappings":"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"}
|
|
@@ -12,6 +12,44 @@ import { ToolDefinition, ToolExecutor } from "./index.js";
|
|
|
12
12
|
* not exposed over MCP. See queryAudioFiles for the measurement.
|
|
13
13
|
*/
|
|
14
14
|
export declare function toAudioListItem(row: unknown): Record<string, unknown>;
|
|
15
|
+
/**
|
|
16
|
+
* The `identification` section of pica_audio_inspect — what ACRCloud said this
|
|
17
|
+
* file is. Built from the single-file GET, which already carries the
|
|
18
|
+
* audio_analysis_results satellite flattened onto the row (findById in
|
|
19
|
+
* lib/services/audio-files/queries.ts selects `audio_analysis_results(*)`), so
|
|
20
|
+
* the section costs no extra call.
|
|
21
|
+
*
|
|
22
|
+
* Before 2026-09-26 no read tool exposed these columns: the only way an agent
|
|
23
|
+
* saw a match was the full row echoed by pica_audio_update, which #2360
|
|
24
|
+
* slimmed — leaving them unreachable (ops issue 3cf19a67).
|
|
25
|
+
*
|
|
26
|
+
* Deliberately lean: each DSP entry keeps only track_id + link (artwork,
|
|
27
|
+
* preview URLs and artist genres are dropped), and the ACRCloud AI-detection
|
|
28
|
+
* payload is cut to its headline fields (the per-stem and per-generator
|
|
29
|
+
* probability arrays are left out). Values are copied as stored, never
|
|
30
|
+
* rescaled: `identification_confidence` is ACRCloud's match score as written
|
|
31
|
+
* (25-100 across prod rows on 2026-09-26). `ai_detection.confidence` is the
|
|
32
|
+
* AI probability on 0-100 (the AiDetectionAcrcloud type). Its prod values
|
|
33
|
+
* span 0.2-96.47, which looked like mixed scales, but read against the
|
|
34
|
+
* verdict on 2026-09-26 (723 rows, one model_id): every `ai_generated` row is
|
|
35
|
+
* ≥ 61.91 and every `human` row ≤ 47.71, and all 363 values ≤ 1 are `human`
|
|
36
|
+
* — one 0-100 scale, with human tracks scoring near zero. A file never run
|
|
37
|
+
* through ACRCloud reports `identification_status: null`.
|
|
38
|
+
*/
|
|
39
|
+
export declare function toIdentificationSection(file: unknown): Record<string, unknown>;
|
|
40
|
+
/**
|
|
41
|
+
* The one-line summary of a matched pica_audio_identify.
|
|
42
|
+
*
|
|
43
|
+
* The route (app/api/admin/audio-files/[id]/identify) returns the service's
|
|
44
|
+
* IdentificationResult FLAT — `title`, `artist`, `confidence`,
|
|
45
|
+
* `externalIds.isrc[]` at the top level. Until 2026-09-26 this tool read a
|
|
46
|
+
* `result.match` object the route has never sent, so a real match never
|
|
47
|
+
* reached this branch; and it multiplied `confidence` by 100, which only a
|
|
48
|
+
* 0-1 score would need. ACRCloud's music score is 0-100 — every stored
|
|
49
|
+
* `audio_analysis_results.identification_confidence` on prod reads 25-100
|
|
50
|
+
* (2026-09-26) — so it is printed as-is.
|
|
51
|
+
*/
|
|
52
|
+
export declare function describeIdentifyMatch(result: unknown): string;
|
|
15
53
|
export declare class AudioFilesTools {
|
|
16
54
|
private pica;
|
|
17
55
|
constructor(pica: PicaClient);
|
|
@@ -29,6 +67,7 @@ export declare class AudioFilesTools {
|
|
|
29
67
|
private bulkAssignSuggested;
|
|
30
68
|
private dismissMatch;
|
|
31
69
|
private updateAudio;
|
|
70
|
+
private bulkUpdateAudio;
|
|
32
71
|
private deleteAudioFile;
|
|
33
72
|
private queryAudioFiles;
|
|
34
73
|
private inspectAudioFile;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"audio-files.d.ts","sourceRoot":"","sources":["../../src/tools/audio-files.ts"],"names":[],"mappings":"AAIA;;GAEG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC/C,OAAO,EAAE,cAAc,EAAE,YAAY,EAAc,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"audio-files.d.ts","sourceRoot":"","sources":["../../src/tools/audio-files.ts"],"names":[],"mappings":"AAIA;;GAEG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC/C,OAAO,EAAE,cAAc,EAAE,YAAY,EAAc,MAAM,YAAY,CAAC;AAwDtE;;;;;;;GAOG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,OAAO,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAQrE;AAED;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAgB,uBAAuB,CACrC,IAAI,EAAE,OAAO,GACZ,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAoDzB;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,OAAO,GAAG,MAAM,CAuB7D;AAED,qBAAa,eAAe;IAC1B,OAAO,CAAC,IAAI,CAAa;gBAEb,IAAI,EAAE,UAAU;IAI5B,QAAQ,IAAI,KAAK,CAAC;QAAE,UAAU,EAAE,cAAc,CAAC;QAAC,QAAQ,EAAE,YAAY,CAAA;KAAE,CAAC;YA8qB3D,WAAW;IA2CzB;;;;OAIG;YACW,eAAe;YA2Bf,mBAAmB;YAkCnB,YAAY;YAmBZ,WAAW;YA6CX,eAAe;YAyCf,eAAe;YAgBf,eAAe;YA6Df,gBAAgB;YAwGhB,gBAAgB;YAchB,eAAe;YAyBf,cAAc;YAgDd,iBAAiB;IAwB/B;;;OAGG;YACW,mBAAmB;CAqClC"}
|
|
@@ -7,6 +7,15 @@ import { withBillingGate } from "@withpica/mcp-utils";
|
|
|
7
7
|
// findUnassigned), so pageEnvelope's `limit` reflects what the server
|
|
8
8
|
// actually applied even when the agent didn't pass one.
|
|
9
9
|
const DEFAULT_AUDIO_QUERY_LIMIT = 50;
|
|
10
|
+
/**
|
|
11
|
+
* Caps copied from the server so the schema advertises what the route
|
|
12
|
+
* enforces: `AUDIO_QUERY_MAX_WORK_IDS` in lib/services/audio-files/urls.ts and
|
|
13
|
+
* `AUDIO_BULK_UPDATE_MAX_ITEMS` in lib/services/audio-files/bulk-update.ts.
|
|
14
|
+
* Hand-copied (this package cannot import the app); no test ties them —
|
|
15
|
+
* change both together.
|
|
16
|
+
*/
|
|
17
|
+
const AUDIO_QUERY_MAX_WORK_IDS = 100;
|
|
18
|
+
const AUDIO_BULK_UPDATE_MAX_ITEMS = 200;
|
|
10
19
|
/** Fields a LIST row carries. Everything else is pica_audio_inspect's. */
|
|
11
20
|
const AUDIO_LIST_FIELDS = [
|
|
12
21
|
"id",
|
|
@@ -53,6 +62,107 @@ export function toAudioListItem(row) {
|
|
|
53
62
|
}
|
|
54
63
|
return out;
|
|
55
64
|
}
|
|
65
|
+
/**
|
|
66
|
+
* The `identification` section of pica_audio_inspect — what ACRCloud said this
|
|
67
|
+
* file is. Built from the single-file GET, which already carries the
|
|
68
|
+
* audio_analysis_results satellite flattened onto the row (findById in
|
|
69
|
+
* lib/services/audio-files/queries.ts selects `audio_analysis_results(*)`), so
|
|
70
|
+
* the section costs no extra call.
|
|
71
|
+
*
|
|
72
|
+
* Before 2026-09-26 no read tool exposed these columns: the only way an agent
|
|
73
|
+
* saw a match was the full row echoed by pica_audio_update, which #2360
|
|
74
|
+
* slimmed — leaving them unreachable (ops issue 3cf19a67).
|
|
75
|
+
*
|
|
76
|
+
* Deliberately lean: each DSP entry keeps only track_id + link (artwork,
|
|
77
|
+
* preview URLs and artist genres are dropped), and the ACRCloud AI-detection
|
|
78
|
+
* payload is cut to its headline fields (the per-stem and per-generator
|
|
79
|
+
* probability arrays are left out). Values are copied as stored, never
|
|
80
|
+
* rescaled: `identification_confidence` is ACRCloud's match score as written
|
|
81
|
+
* (25-100 across prod rows on 2026-09-26). `ai_detection.confidence` is the
|
|
82
|
+
* AI probability on 0-100 (the AiDetectionAcrcloud type). Its prod values
|
|
83
|
+
* span 0.2-96.47, which looked like mixed scales, but read against the
|
|
84
|
+
* verdict on 2026-09-26 (723 rows, one model_id): every `ai_generated` row is
|
|
85
|
+
* ≥ 61.91 and every `human` row ≤ 47.71, and all 363 values ≤ 1 are `human`
|
|
86
|
+
* — one 0-100 scale, with human tracks scoring near zero. A file never run
|
|
87
|
+
* through ACRCloud reports `identification_status: null`.
|
|
88
|
+
*/
|
|
89
|
+
export function toIdentificationSection(file) {
|
|
90
|
+
const src = file && typeof file === "object" ? file : {};
|
|
91
|
+
const asObject = (v) => v && typeof v === "object" && !Array.isArray(v)
|
|
92
|
+
? v
|
|
93
|
+
: null;
|
|
94
|
+
const strings = (v) => Array.isArray(v) ? v.filter((x) => typeof x === "string") : [];
|
|
95
|
+
const field = (k) => src[k] ?? null;
|
|
96
|
+
const externalIds = asObject(src.identification_external_ids) ?? {};
|
|
97
|
+
const dspRaw = asObject(src.identification_dsp_ids);
|
|
98
|
+
let dspIds = null;
|
|
99
|
+
if (dspRaw) {
|
|
100
|
+
dspIds = {};
|
|
101
|
+
for (const [platform, entry] of Object.entries(dspRaw)) {
|
|
102
|
+
const e = asObject(entry);
|
|
103
|
+
if (!e)
|
|
104
|
+
continue;
|
|
105
|
+
dspIds[platform] = { track_id: e.track_id ?? null, link: e.link ?? null };
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
const ai = asObject(src.ai_detection_acrcloud);
|
|
109
|
+
const aiDetection = ai
|
|
110
|
+
? {
|
|
111
|
+
is_ai_generated: ai.is_ai_generated ?? null,
|
|
112
|
+
confidence: ai.confidence ?? null,
|
|
113
|
+
likely_source: ai.likely_source ?? null,
|
|
114
|
+
model_id: ai.model_id ?? null,
|
|
115
|
+
}
|
|
116
|
+
: null;
|
|
117
|
+
return {
|
|
118
|
+
identification_status: field("identification_status"),
|
|
119
|
+
identification_source: field("identification_source"),
|
|
120
|
+
identification_completed_at: field("identification_completed_at"),
|
|
121
|
+
confidence: field("identification_confidence"),
|
|
122
|
+
acrid: field("acrid"),
|
|
123
|
+
identified_title: field("identified_title"),
|
|
124
|
+
identified_artist: field("identified_artist"),
|
|
125
|
+
identified_album: field("identified_album"),
|
|
126
|
+
identified_label: field("identified_label"),
|
|
127
|
+
identified_release_date: field("identified_release_date"),
|
|
128
|
+
isrc: strings(externalIds.isrc),
|
|
129
|
+
upc: strings(externalIds.upc),
|
|
130
|
+
iswc: strings(externalIds.iswc),
|
|
131
|
+
dsp_ids: dspIds,
|
|
132
|
+
ai_detection: aiDetection,
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* The one-line summary of a matched pica_audio_identify.
|
|
137
|
+
*
|
|
138
|
+
* The route (app/api/admin/audio-files/[id]/identify) returns the service's
|
|
139
|
+
* IdentificationResult FLAT — `title`, `artist`, `confidence`,
|
|
140
|
+
* `externalIds.isrc[]` at the top level. Until 2026-09-26 this tool read a
|
|
141
|
+
* `result.match` object the route has never sent, so a real match never
|
|
142
|
+
* reached this branch; and it multiplied `confidence` by 100, which only a
|
|
143
|
+
* 0-1 score would need. ACRCloud's music score is 0-100 — every stored
|
|
144
|
+
* `audio_analysis_results.identification_confidence` on prod reads 25-100
|
|
145
|
+
* (2026-09-26) — so it is printed as-is.
|
|
146
|
+
*/
|
|
147
|
+
export function describeIdentifyMatch(result) {
|
|
148
|
+
const r = result && typeof result === "object"
|
|
149
|
+
? result
|
|
150
|
+
: {};
|
|
151
|
+
const ext = r.externalIds && typeof r.externalIds === "object"
|
|
152
|
+
? r.externalIds
|
|
153
|
+
: {};
|
|
154
|
+
const isrcs = Array.isArray(ext.isrc)
|
|
155
|
+
? ext.isrc.filter((x) => typeof x === "string")
|
|
156
|
+
: [];
|
|
157
|
+
const confidence = typeof r.confidence === "number"
|
|
158
|
+
? `${Math.round(r.confidence)}/100`
|
|
159
|
+
: "not reported";
|
|
160
|
+
const title = typeof r.title === "string" ? r.title : "untitled";
|
|
161
|
+
const artist = typeof r.artist === "string" ? r.artist : "unknown artist";
|
|
162
|
+
return (`Match found: "${title}" by ${artist} (ACRCloud score ${confidence}). ` +
|
|
163
|
+
`ISRC: ${isrcs.length ? isrcs.join(", ") : "none returned"}. ` +
|
|
164
|
+
"If the file is linked to a work, metadata has been propagated.");
|
|
165
|
+
}
|
|
56
166
|
export class AudioFilesTools {
|
|
57
167
|
pica;
|
|
58
168
|
constructor(pica) {
|
|
@@ -66,7 +176,7 @@ export class AudioFilesTools {
|
|
|
66
176
|
scope: "read:files",
|
|
67
177
|
audiences: ["stdio", "http", "public"],
|
|
68
178
|
tier: "read",
|
|
69
|
-
description: "Find audio files — filter by name/title (`query`), work, file type, or analysis status. " +
|
|
179
|
+
description: "Find audio files — filter by name/title (`query`), work (`work_id`, or `work_ids` for several at once), file type, or analysis status. " +
|
|
70
180
|
"Rows are a LEAN list shape (identity, size, duration, bpm/key/energy/mood, links, bucket). For one file, pica_audio_inspect adds sample rate, bit depth, danceability (sections: ['analysis']) and the waveform (sections: ['waveform']); the raw `metadata` jsonb, storage path and CDN URL are storage internals not exposed over MCP. " +
|
|
71
181
|
"→ then: pica_audio_inspect (details for a specific file), " +
|
|
72
182
|
"pica_audio_assign (attach an unassigned file to a work/recording). " +
|
|
@@ -81,6 +191,12 @@ export class AudioFilesTools {
|
|
|
81
191
|
type: "string",
|
|
82
192
|
description: "Filter by work ID to get all audio files for a specific work",
|
|
83
193
|
},
|
|
194
|
+
work_ids: {
|
|
195
|
+
type: "array",
|
|
196
|
+
items: { type: "string" },
|
|
197
|
+
maxItems: AUDIO_QUERY_MAX_WORK_IDS,
|
|
198
|
+
description: `Audio for several works in ONE call (up to ${AUDIO_QUERY_MAX_WORK_IDS} work UUIDs) — e.g. every song in a playlist. Includes files attached through a recording of those works. Pages with limit/offset like the rest of the list; combine with file_type (e.g. 'master') to narrow to that kind of file.`,
|
|
199
|
+
},
|
|
84
200
|
file_type: {
|
|
85
201
|
type: "string",
|
|
86
202
|
description: "Filter by file type",
|
|
@@ -119,7 +235,10 @@ export class AudioFilesTools {
|
|
|
119
235
|
tier: "read",
|
|
120
236
|
description: "Get details for a specific audio file, including its stored " +
|
|
121
237
|
'transcript (sections: ["transcript"]) even when the file is not ' +
|
|
122
|
-
"linked to any work
|
|
238
|
+
"linked to any work, and what ACRCloud identified it as " +
|
|
239
|
+
'(sections: ["identification"] — status, matched title/artist/' +
|
|
240
|
+
"album/label, ISRC/UPC, DSP ids, confidence, AI-detection " +
|
|
241
|
+
"summary). Omit sections for everything. " +
|
|
123
242
|
"→ then: pica_audio_analyze (run analysis), pica_audio_identify (fingerprint match), " +
|
|
124
243
|
"pica_audio_assign (link an orphaned file to its work)",
|
|
125
244
|
workflows: ["audio-upload-required"],
|
|
@@ -142,13 +261,16 @@ export class AudioFilesTools {
|
|
|
142
261
|
"waveform",
|
|
143
262
|
"status",
|
|
144
263
|
"transcript",
|
|
264
|
+
"identification",
|
|
145
265
|
],
|
|
146
266
|
},
|
|
147
267
|
description: "Which data sections to include. Omit for all sections. " +
|
|
148
268
|
"`transcript` returns the stored speech-to-text transcript " +
|
|
149
269
|
"for this file whether or not it is linked to a work — the " +
|
|
150
270
|
"only way to read one that has not been copied onto a work's " +
|
|
151
|
-
"lyrics."
|
|
271
|
+
"lyrics. `identification` returns the stored ACRCloud " +
|
|
272
|
+
"result; identification_status null means the file was " +
|
|
273
|
+
"never identified (run pica_audio_identify).",
|
|
152
274
|
},
|
|
153
275
|
},
|
|
154
276
|
required: ["id"],
|
|
@@ -240,7 +362,8 @@ export class AudioFilesTools {
|
|
|
240
362
|
},
|
|
241
363
|
file_size: {
|
|
242
364
|
type: "number",
|
|
243
|
-
|
|
365
|
+
minimum: 1,
|
|
366
|
+
description: "Exact file size in bytes (> 0). Never send 0 or a guess — if you cannot read the file, you cannot upload it from here; send the user to withpica.com/inspect.",
|
|
244
367
|
},
|
|
245
368
|
work_id: {
|
|
246
369
|
type: "string",
|
|
@@ -252,7 +375,7 @@ export class AudioFilesTools {
|
|
|
252
375
|
},
|
|
253
376
|
file_type: {
|
|
254
377
|
type: "string",
|
|
255
|
-
description: "Type of audio file (
|
|
378
|
+
description: "Type of audio file. Set it when you know it. If omitted, PICA reads the filename (instrumental / -inst / karaoke / playback / -pa → instrumental; stem(s) → stem; demo → demo; remix / radio edit / (live) / acoustic → version); with no signal in the name it stays 'master'.",
|
|
256
379
|
enum: ["master", "instrumental", "stem", "demo", "version"],
|
|
257
380
|
},
|
|
258
381
|
},
|
|
@@ -310,7 +433,7 @@ export class AudioFilesTools {
|
|
|
310
433
|
},
|
|
311
434
|
file_type: {
|
|
312
435
|
type: "string",
|
|
313
|
-
description: "Type of audio file (
|
|
436
|
+
description: "Type of audio file. Set it when you know it. If omitted, PICA reads the filename (instrumental / -inst / karaoke / playback / -pa → instrumental; stem(s) → stem; demo → demo; remix / radio edit / (live) / acoustic → version); with no signal in the name it stays 'master'.",
|
|
314
437
|
enum: ["master", "instrumental", "stem", "demo", "version"],
|
|
315
438
|
},
|
|
316
439
|
stem_label: {
|
|
@@ -582,6 +705,76 @@ export class AudioFilesTools {
|
|
|
582
705
|
},
|
|
583
706
|
executor: this.updateAudio.bind(this),
|
|
584
707
|
},
|
|
708
|
+
{
|
|
709
|
+
definition: {
|
|
710
|
+
name: "pica_audio_bulk_update",
|
|
711
|
+
scope: "write:files",
|
|
712
|
+
audiences: ["stdio", "http", "public"],
|
|
713
|
+
tier: "write",
|
|
714
|
+
description: `Update metadata on up to ${AUDIO_BULK_UPDATE_MAX_ITEMS} audio files in ONE call — each item sets any of ` +
|
|
715
|
+
"file_type (master/instrumental/stem/demo/version), stem_label, version_label, title for one file id. " +
|
|
716
|
+
"Use instead of looping pica_audio_update, e.g. to tag every file in a playlist as master or label a " +
|
|
717
|
+
"set of stems. Only this organisation's files are touched. Returns one lean result per item — " +
|
|
718
|
+
"updated, or failed with a reason (unknown id, bad file_type, nothing to set) — and never the file " +
|
|
719
|
+
"rows; a bad item does not stop the others. To attach files to a work/recording use pica_audio_assign. " +
|
|
720
|
+
"Reversible (update again). Pass dry_run:true to preview.",
|
|
721
|
+
workflows: "infrastructure",
|
|
722
|
+
vernacular_kind: "specialist",
|
|
723
|
+
vernacular_reason: "Specialist catalog-metadata action in the audio management flow, outside the Creator Question Atlas.",
|
|
724
|
+
annotations: { title: "bulk update audio" },
|
|
725
|
+
inputSchema: {
|
|
726
|
+
type: "object",
|
|
727
|
+
properties: {
|
|
728
|
+
items: {
|
|
729
|
+
type: "array",
|
|
730
|
+
minItems: 1,
|
|
731
|
+
maxItems: AUDIO_BULK_UPDATE_MAX_ITEMS,
|
|
732
|
+
description: `One entry per audio file (max ${AUDIO_BULK_UPDATE_MAX_ITEMS}). Each needs id plus at least one field to set.`,
|
|
733
|
+
items: {
|
|
734
|
+
type: "object",
|
|
735
|
+
properties: {
|
|
736
|
+
id: {
|
|
737
|
+
type: "string",
|
|
738
|
+
description: "the audio file to update",
|
|
739
|
+
},
|
|
740
|
+
file_type: {
|
|
741
|
+
type: "string",
|
|
742
|
+
enum: [
|
|
743
|
+
"master",
|
|
744
|
+
"instrumental",
|
|
745
|
+
"stem",
|
|
746
|
+
"demo",
|
|
747
|
+
"version",
|
|
748
|
+
],
|
|
749
|
+
description: "set the file type",
|
|
750
|
+
},
|
|
751
|
+
stem_label: {
|
|
752
|
+
type: "string",
|
|
753
|
+
description: "label for a stem (e.g. 'drums'); pass an empty string to clear",
|
|
754
|
+
},
|
|
755
|
+
version_label: {
|
|
756
|
+
type: "string",
|
|
757
|
+
description: "label for a version (e.g. 'radio edit'); pass an empty string to clear",
|
|
758
|
+
},
|
|
759
|
+
title: {
|
|
760
|
+
type: "string",
|
|
761
|
+
description: "set the audio file's title",
|
|
762
|
+
},
|
|
763
|
+
},
|
|
764
|
+
required: ["id"],
|
|
765
|
+
},
|
|
766
|
+
},
|
|
767
|
+
dry_run: {
|
|
768
|
+
type: "boolean",
|
|
769
|
+
description: "When true, validates every item and checks each id exists in this organisation, returning would_update / failed per item without writing anything.",
|
|
770
|
+
},
|
|
771
|
+
},
|
|
772
|
+
required: ["items"],
|
|
773
|
+
},
|
|
774
|
+
previewMode: "dry_run",
|
|
775
|
+
},
|
|
776
|
+
executor: this.bulkUpdateAudio.bind(this),
|
|
777
|
+
},
|
|
585
778
|
];
|
|
586
779
|
}
|
|
587
780
|
async assignAudio(args) {
|
|
@@ -604,7 +797,11 @@ export class AudioFilesTools {
|
|
|
604
797
|
work_id: args.work_id,
|
|
605
798
|
recording_id: args.recording_id,
|
|
606
799
|
});
|
|
607
|
-
|
|
800
|
+
// The route returns the full row — waveform_data and the flattened
|
|
801
|
+
// analysis satellite, ~8k tokens a file (ops issue 5c53049a). An agent
|
|
802
|
+
// needs to see the link it made, not the waveform: project to the same
|
|
803
|
+
// lean shape a pica_audio_query row has.
|
|
804
|
+
return formatSuccess("Audio assigned", toAudioListItem(updated));
|
|
608
805
|
}
|
|
609
806
|
catch (err) {
|
|
610
807
|
// resolve-any-ID recovery (WS5 tail): agents holding a bare id often
|
|
@@ -697,7 +894,42 @@ export class AudioFilesTools {
|
|
|
697
894
|
// via the parent repo's node_modules (stale dist). CI builds the SDK fresh.
|
|
698
895
|
const audioFiles = this.pica.audioFiles;
|
|
699
896
|
const updated = await audioFiles.update(args.id, body);
|
|
700
|
-
|
|
897
|
+
// Lean row, not the full record — see assignAudio (ops issue 5c53049a).
|
|
898
|
+
return formatSuccess("Audio updated", toAudioListItem(updated));
|
|
899
|
+
}
|
|
900
|
+
async bulkUpdateAudio(args) {
|
|
901
|
+
const items = args.items;
|
|
902
|
+
if (!Array.isArray(items) || items.length === 0) {
|
|
903
|
+
return {
|
|
904
|
+
content: [
|
|
905
|
+
{
|
|
906
|
+
type: "text",
|
|
907
|
+
text: "items must be a non-empty array of { id, file_type?, stem_label?, version_label?, title? }",
|
|
908
|
+
},
|
|
909
|
+
],
|
|
910
|
+
isError: true,
|
|
911
|
+
};
|
|
912
|
+
}
|
|
913
|
+
if (items.length > AUDIO_BULK_UPDATE_MAX_ITEMS) {
|
|
914
|
+
return {
|
|
915
|
+
content: [
|
|
916
|
+
{
|
|
917
|
+
type: "text",
|
|
918
|
+
text: `at most ${AUDIO_BULK_UPDATE_MAX_ITEMS} items per call (got ${items.length}) — split the batch`,
|
|
919
|
+
},
|
|
920
|
+
],
|
|
921
|
+
isError: true,
|
|
922
|
+
};
|
|
923
|
+
}
|
|
924
|
+
const dryRun = args.dry_run === true;
|
|
925
|
+
const result = await this.pica.audioFiles.bulkUpdate(items, dryRun ? { dry_run: true } : undefined);
|
|
926
|
+
const verb = dryRun ? "Would update" : "Updated";
|
|
927
|
+
const summary = `${verb} ${result.updated} of ${result.requested} audio file${result.requested === 1 ? "" : "s"}` +
|
|
928
|
+
(result.failed > 0
|
|
929
|
+
? ` — ${result.failed} failed (see results[].reason).`
|
|
930
|
+
: ".") +
|
|
931
|
+
(dryRun ? " Nothing was written — re-run without dry_run to apply." : "");
|
|
932
|
+
return formatSuccess(summary, result);
|
|
701
933
|
}
|
|
702
934
|
async deleteAudioFile(args) {
|
|
703
935
|
// AudioFilesResource.delete is added in this change's SDK update. In an
|
|
@@ -713,6 +945,7 @@ export class AudioFilesTools {
|
|
|
713
945
|
async queryAudioFiles(args) {
|
|
714
946
|
const raw = await this.pica.audioFiles.list({
|
|
715
947
|
work_id: args.work_id,
|
|
948
|
+
work_ids: Array.isArray(args.work_ids) ? args.work_ids : undefined,
|
|
716
949
|
file_type: args.file_type,
|
|
717
950
|
unprocessed: args.unprocessed,
|
|
718
951
|
unassigned: args.unassigned,
|
|
@@ -773,10 +1006,18 @@ export class AudioFilesTools {
|
|
|
773
1006
|
const includeWaveform = !!sections && sections.includes("waveform");
|
|
774
1007
|
const includeStatus = includeAll || sections.includes("status");
|
|
775
1008
|
const includeTranscript = includeAll || sections.includes("transcript");
|
|
1009
|
+
const includeIdentification = includeAll || sections.includes("identification");
|
|
776
1010
|
const result = {};
|
|
777
|
-
//
|
|
778
|
-
|
|
1011
|
+
// Basic, analysis, waveform and identification all come from one get —
|
|
1012
|
+
// the route flattens the analysis satellite onto the row.
|
|
1013
|
+
if (includeBasic ||
|
|
1014
|
+
includeAnalysis ||
|
|
1015
|
+
includeWaveform ||
|
|
1016
|
+
includeIdentification) {
|
|
779
1017
|
const file = await this.pica.audioFiles.get(args.id);
|
|
1018
|
+
if (includeIdentification) {
|
|
1019
|
+
result.identification = toIdentificationSection(file);
|
|
1020
|
+
}
|
|
780
1021
|
if (includeWaveform) {
|
|
781
1022
|
result.waveform = {
|
|
782
1023
|
waveform_data: file.waveform_data ??
|
|
@@ -916,8 +1157,8 @@ export class AudioFilesTools {
|
|
|
916
1157
|
if (result.alreadyIdentified) {
|
|
917
1158
|
return formatSuccess("Already identified — no credits charged. Use force: true to re-identify.", result);
|
|
918
1159
|
}
|
|
919
|
-
else if (result.status === "matched"
|
|
920
|
-
return formatSuccess(
|
|
1160
|
+
else if (result.status === "matched") {
|
|
1161
|
+
return formatSuccess(describeIdentifyMatch(result), result);
|
|
921
1162
|
}
|
|
922
1163
|
else if (result.status === "no_match") {
|
|
923
1164
|
return formatSuccess("No match found in ACRCloud database. This may be an unreleased or very rare track.", result);
|