@withpica/mcp-sdk 3.7.2 → 3.10.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 CHANGED
@@ -9,6 +9,46 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
9
9
  > matching entry here in the same commit. See the project's "npm publish
10
10
  > discipline" memory entry for the enforcement rationale.
11
11
 
12
+ ## [Unreleased]
13
+
14
+ ## [3.10.0] - 2026-07-27
15
+
16
+ ### Added
17
+
18
+ - `DocumentsResource.read()` accepts `row_offset` / `row_limit` — parsed
19
+ spreadsheet rows now page independently of content chars (ops 41ff656c:
20
+ `parsed_data.rows` previously rode whole on every page, so an xlsx read
21
+ could never complete under the 100KB MCP response cap).
22
+
23
+ ## [3.9.0] - 2026-07-24
24
+
25
+ ### Added
26
+
27
+ - **`AudioFilesResource.bulkAssignSuggested()`** — one-call attach of ALL
28
+ orphan audio whose suggested match is ISRC-high and non-ambiguous
29
+ (`POST /admin/audio-files/bulk-assign-suggested`; pairings recomputed
30
+ server-side, `possible` never bulk-attached). Returns the
31
+ `BulkAssignSuggestedResult` counts + `attached_ids`. Backs the new
32
+ `pica_audio_bulk_assign_suggested` MCP tool (agent feedback 20f592ff —
33
+ an agent hand-looped `pica_audio_assign` over a 74-file queue).
34
+ - **`AudioFilesResource.dismissMatch(id, recordingId)`** — reject a
35
+ suggested audio→recording pairing so it never resurfaces (repeat
36
+ dismissals are server-side no-op successes). Backs the new
37
+ `pica_audio_dismiss_match` MCP tool.
38
+
39
+ ## [3.8.0] - 2026-07-24
40
+
41
+ ### Added
42
+
43
+ - **`PaginatedResult.recovery_hint`** — `requestPaginated` now carries the
44
+ server's zero-result guidance through instead of silently dropping it.
45
+ `GET /admin/recordings/search` has emitted a `recovery_hint` on empty
46
+ result sets since the unified-catalog-search work (e.g. "N recordings
47
+ have a null primary artist — try ISRC or title"), but the SDK envelope
48
+ unwrap discarded it, so agents saw a bare empty list and read it as "no
49
+ recordings exist" (ops_issue 689a8e9a — an agent nearly created duplicate
50
+ recordings). Optional field; only present when the server sent one.
51
+
12
52
  ## [3.7.2] - 2026-07-16
13
53
 
14
54
  ### Fixed
package/dist/index.d.ts CHANGED
@@ -259,6 +259,15 @@ interface PaginatedResult<T> {
259
259
  data: T[];
260
260
  total: number;
261
261
  hasMore: boolean;
262
+ /**
263
+ * Server-provided next-step guidance when a search legitimately returns
264
+ * zero rows (e.g. GET /admin/recordings/search explains that N recordings
265
+ * have no primary artist and suggests ISRC/title search). Optional — only
266
+ * routes that build one emit it, and only on empty result sets. Dropping
267
+ * this on the wire was ops_issue 689a8e9a: an agent read a silent empty as
268
+ * "no recordings exist" and nearly created duplicates.
269
+ */
270
+ recovery_hint?: string;
262
271
  }
263
272
  /**
264
273
  * Society registration record returned on work and recording read results
@@ -402,6 +411,23 @@ interface PicaScore {
402
411
  topActions: string[];
403
412
  calculatedAt: string;
404
413
  }
414
+ /**
415
+ * Outcome of a server-recomputed bulk attach of high-confidence orphan-audio
416
+ * matches (POST /admin/audio-files/bulk-assign-suggested). Mirrors
417
+ * `BulkAssignResult` in the app's audio-match service; `attached_ids` always
418
+ * has exactly `attached` entries (shape-locked by the api-audio-bulk-assign
419
+ * holdout).
420
+ */
421
+ export interface BulkAssignSuggestedResult {
422
+ attached: number;
423
+ skipped_ambiguous: number;
424
+ skipped_possible: number;
425
+ failed: number;
426
+ attached_ids: string[];
427
+ /** Present and true when the run was a dry-run preview (nothing persisted;
428
+ * `attached`/`attached_ids` mean WOULD-attach). */
429
+ dry_run?: boolean;
430
+ }
405
431
  interface AudioFile {
406
432
  id: string;
407
433
  work_id: string | null;
@@ -1366,6 +1392,32 @@ declare class AudioFilesResource extends BaseResource {
1366
1392
  limit?: number;
1367
1393
  }): Promise<AudioFile[]>;
1368
1394
  get(id: string): Promise<AudioFile>;
1395
+ /**
1396
+ * Attach ALL orphan audio files whose suggested match is ISRC-high and
1397
+ * non-ambiguous, in one call. Pairings are recomputed server-side at
1398
+ * execution time — nothing is sent, so stale suggestions can't be applied
1399
+ * and dismissed pairs stay excluded; `possible` (title-tier) matches are
1400
+ * never bulk-attached. Wraps POST /admin/audio-files/bulk-assign-suggested
1401
+ * (the route behind the /inspect "attach all high" strip; agent feedback
1402
+ * 20f592ff asked for the same action tool-side).
1403
+ *
1404
+ * NB the route responds `{ success, result }` with no `data` key, so
1405
+ * `request()`'s `.data || whole` unwrap yields the full envelope — read
1406
+ * `.result` here rather than typing against a payload that isn't there
1407
+ * (the ADR-265 double-unwrap lesson).
1408
+ */
1409
+ bulkAssignSuggested(params?: {
1410
+ /** Preview: same server-side classification, nothing persisted;
1411
+ * `attached`/`attached_ids` mean WOULD-attach. */
1412
+ dry_run?: boolean;
1413
+ }): Promise<BulkAssignSuggestedResult>;
1414
+ /**
1415
+ * Reject a suggested (audio_file → recording) match so the pair never
1416
+ * resurfaces in suggestions or bulk attach. The file stays an orphan —
1417
+ * only THIS pairing is suppressed. Repeat dismissals are no-op successes
1418
+ * server-side. Wraps POST /admin/audio-files/{id}/dismiss-match.
1419
+ */
1420
+ dismissMatch(id: string, recordingId: string): Promise<void>;
1369
1421
  update(id: string, body: {
1370
1422
  work_id?: string | null;
1371
1423
  recording_id?: string | null;
@@ -3162,6 +3214,8 @@ declare class DocumentsResource extends BaseResource {
3162
3214
  read(id: string, params?: {
3163
3215
  offset?: number;
3164
3216
  max_chars?: number;
3217
+ row_offset?: number;
3218
+ row_limit?: number;
3165
3219
  }): Promise<Record<string, unknown>>;
3166
3220
  link(id: string, entity_type: string, entity_id: string): Promise<unknown>;
3167
3221
  /**