@withpica/mcp-sdk 3.1.1 → 3.3.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 +31 -0
- package/dist/index.d.ts +287 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +301 -1
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -203,6 +203,43 @@ class BaseResource {
|
|
|
203
203
|
}
|
|
204
204
|
return (data.data || data);
|
|
205
205
|
}
|
|
206
|
+
/**
|
|
207
|
+
* Make a request whose SUCCESS body is raw text, not a JSON envelope —
|
|
208
|
+
* for routes that stream a generated file (e.g. `text/csv`) rather than
|
|
209
|
+
* `{success, data}`. `request()` unconditionally calls `response.json()`,
|
|
210
|
+
* which throws a SyntaxError parsing CSV text; every such route needs this
|
|
211
|
+
* method instead (see `ImportResource.getTemplate()` for the prior
|
|
212
|
+
* precedent this generalises).
|
|
213
|
+
*
|
|
214
|
+
* `fetchWithRetry` already throws `ApiError` for non-2xx responses (reading
|
|
215
|
+
* the body as text), so reaching here means `response.ok`. Still guard
|
|
216
|
+
* against a 2xx JSON error envelope (`{success:false}`) via content-type,
|
|
217
|
+
* since a route can commit to status 200 before a later validation step.
|
|
218
|
+
*/
|
|
219
|
+
async requestText(method, path) {
|
|
220
|
+
const url = `${this.baseUrl}${path}`;
|
|
221
|
+
const timeoutMs = getTimeoutForPath(path);
|
|
222
|
+
if (this.debug) {
|
|
223
|
+
console.error(`[PICA SDK] ${method} ${url} (timeout: ${timeoutMs}ms)`);
|
|
224
|
+
}
|
|
225
|
+
const response = await this.fetchWithRetry(url, {
|
|
226
|
+
method,
|
|
227
|
+
headers: {
|
|
228
|
+
Authorization: `Bearer ${this.apiKey}`,
|
|
229
|
+
...this.getBypassHeaders(),
|
|
230
|
+
},
|
|
231
|
+
}, timeoutMs);
|
|
232
|
+
const contentType = response.headers.get("content-type") || "";
|
|
233
|
+
if (contentType.includes("application/json")) {
|
|
234
|
+
const data = await response.json();
|
|
235
|
+
if (data && typeof data === "object" && data.success === false) {
|
|
236
|
+
const msg = typeof data.error === "string" ? data.error : "unspecified error";
|
|
237
|
+
throw new ApiError(`API returned success:false: ${msg}`, response.status, false);
|
|
238
|
+
}
|
|
239
|
+
return typeof data === "string" ? data : JSON.stringify(data);
|
|
240
|
+
}
|
|
241
|
+
return response.text();
|
|
242
|
+
}
|
|
206
243
|
/**
|
|
207
244
|
* Make a request and return paginated result with metadata
|
|
208
245
|
*/
|
|
@@ -393,6 +430,45 @@ class PeopleResource extends BaseResource {
|
|
|
393
430
|
async bulkDelete(ids) {
|
|
394
431
|
return this.request("POST", "/admin/people/bulk-delete", { ids });
|
|
395
432
|
}
|
|
433
|
+
/**
|
|
434
|
+
* List a person's artist projects — per-stage-name Spotify/YouTube
|
|
435
|
+
* identity + enrichment status (ADR-289 Wave B2 item 4, ports the
|
|
436
|
+
* bespoke assistant's `get_person_artist_projects`).
|
|
437
|
+
*/
|
|
438
|
+
async listArtistProjects(personId) {
|
|
439
|
+
return this.request("GET", `/admin/people/${personId}/artist-projects`);
|
|
440
|
+
}
|
|
441
|
+
/**
|
|
442
|
+
* Trigger enrichment for every stage name on a person — matches each
|
|
443
|
+
* against Spotify/YouTube artist identity, auto-applying confident
|
|
444
|
+
* matches and flagging ambiguous ones for disambiguation (ADR-289
|
|
445
|
+
* Wave B2 item 4, ports `enrich_artist_projects`).
|
|
446
|
+
*/
|
|
447
|
+
async enrichArtistProjects(personId) {
|
|
448
|
+
return this.request("POST", `/admin/people/${personId}/enrich-artist-projects`);
|
|
449
|
+
}
|
|
450
|
+
/**
|
|
451
|
+
* Mark one of a person's artist projects as primary (unsets any other
|
|
452
|
+
* primary project for the same person server-side) (ADR-289 Wave B2
|
|
453
|
+
* item 4, ports `set_primary_artist_project`).
|
|
454
|
+
*/
|
|
455
|
+
async setPrimaryArtistProject(artistProjectId) {
|
|
456
|
+
return this.request("PATCH", `/admin/artist-projects/${artistProjectId}/set-primary`);
|
|
457
|
+
}
|
|
458
|
+
/**
|
|
459
|
+
* Check whether an external artist name already matches an existing
|
|
460
|
+
* person — exact MusicBrainz-id match, then ISNI-via-MusicBrainz, then
|
|
461
|
+
* a fuzzy name fallback. Read-only (ADR-289 Wave B2 item 5, ports the
|
|
462
|
+
* bespoke assistant's `triangulate_artist` — verdict: NOT subsumed by
|
|
463
|
+
* `pica_resolve_person`, which requires an existing person_id and
|
|
464
|
+
* writes identifiers rather than searching for a match by bare name).
|
|
465
|
+
*/
|
|
466
|
+
async triangulate(params) {
|
|
467
|
+
const qp = new URLSearchParams({ artist_name: params.artist_name });
|
|
468
|
+
if (params.musicbrainz_id)
|
|
469
|
+
qp.set("musicbrainz_id", params.musicbrainz_id);
|
|
470
|
+
return this.request("GET", `/admin/people/triangulate?${qp.toString()}`);
|
|
471
|
+
}
|
|
396
472
|
}
|
|
397
473
|
class LicensingResource extends BaseResource {
|
|
398
474
|
/**
|
|
@@ -478,6 +554,58 @@ class LicensingResource extends BaseResource {
|
|
|
478
554
|
async updateEnquiryStatus(id, status, notes) {
|
|
479
555
|
return this.request("PATCH", `/admin/license-enquiries/${id}`, { status, your_notes: notes });
|
|
480
556
|
}
|
|
557
|
+
/**
|
|
558
|
+
* Set a counter offer on a license enquiry (ADR-289 Wave B1 item 6 —
|
|
559
|
+
* counter-offer fields on `pica_update_license_enquiry_status`, ports
|
|
560
|
+
* the bespoke assistant's `set_license_counter_offer`). Setting a counter
|
|
561
|
+
* offer also moves the enquiry to status "quoted" server-side.
|
|
562
|
+
*/
|
|
563
|
+
async setLicenseEnquiryCounterOffer(id, counterOffer, notes) {
|
|
564
|
+
return this.request("PATCH", `/admin/license-enquiries/${id}`, { counterOffer, notes });
|
|
565
|
+
}
|
|
566
|
+
}
|
|
567
|
+
/**
|
|
568
|
+
* ADR-289 Wave C1 — booking enquiries (internal-team session/production
|
|
569
|
+
* bookings, distinct from `LicensingResource`'s sync-license enquiries).
|
|
570
|
+
* Wraps `/admin/bookings` + `/admin/bookings/[id]`.
|
|
571
|
+
*/
|
|
572
|
+
class BookingsResource extends BaseResource {
|
|
573
|
+
/**
|
|
574
|
+
* List/search booking enquiries. `GET /admin/bookings` returns the raw
|
|
575
|
+
* array (not `{data, count}`) — `request()` unwraps to that array.
|
|
576
|
+
*/
|
|
577
|
+
async list(params) {
|
|
578
|
+
const qp = new URLSearchParams();
|
|
579
|
+
if (params?.status)
|
|
580
|
+
qp.set("status", params.status);
|
|
581
|
+
if (params?.priority)
|
|
582
|
+
qp.set("priority", params.priority);
|
|
583
|
+
if (params?.query)
|
|
584
|
+
qp.set("query", params.query);
|
|
585
|
+
if (params?.enquiry_type)
|
|
586
|
+
qp.set("enquiry_type", params.enquiry_type);
|
|
587
|
+
if (params?.follow_up_required !== undefined)
|
|
588
|
+
qp.set("follow_up_required", String(params.follow_up_required));
|
|
589
|
+
if (params?.limit !== undefined)
|
|
590
|
+
qp.set("limit", String(params.limit));
|
|
591
|
+
if (params?.offset !== undefined)
|
|
592
|
+
qp.set("offset", String(params.offset));
|
|
593
|
+
const qs = qp.toString();
|
|
594
|
+
return this.request("GET", `/admin/bookings${qs ? `?${qs}` : ""}`);
|
|
595
|
+
}
|
|
596
|
+
async get(id) {
|
|
597
|
+
return this.request("GET", `/admin/bookings/${encodeURIComponent(id)}`);
|
|
598
|
+
}
|
|
599
|
+
/**
|
|
600
|
+
* `PATCH /admin/bookings/[id]` only processes ONE update mode per call
|
|
601
|
+
* (status, OR responseContent+respondedBy, OR followUp — the route
|
|
602
|
+
* returns on the first matching branch). Callers needing multiple
|
|
603
|
+
* independent updates in one tool invocation must call this once per
|
|
604
|
+
* mode (mirrors the bespoke assistant's three separate handlers).
|
|
605
|
+
*/
|
|
606
|
+
async update(id, data) {
|
|
607
|
+
return this.request("PATCH", `/admin/bookings/${encodeURIComponent(id)}`, data);
|
|
608
|
+
}
|
|
481
609
|
}
|
|
482
610
|
class CreditsResource extends BaseResource {
|
|
483
611
|
async listForWork(workId) {
|
|
@@ -636,6 +764,8 @@ class AgreementsResource extends BaseResource {
|
|
|
636
764
|
queryParams.set("party_name", params.party_name);
|
|
637
765
|
if (params?.includeWorkCounts)
|
|
638
766
|
queryParams.set("includeWorkCounts", "true");
|
|
767
|
+
if (params?.awaiting_signature)
|
|
768
|
+
queryParams.set("awaiting_signature", "true");
|
|
639
769
|
if (params?.limit !== undefined)
|
|
640
770
|
queryParams.set("limit", String(params.limit));
|
|
641
771
|
if (params?.offset !== undefined)
|
|
@@ -649,6 +779,26 @@ class AgreementsResource extends BaseResource {
|
|
|
649
779
|
async create(data) {
|
|
650
780
|
return this.request("POST", "/admin/agreements", data);
|
|
651
781
|
}
|
|
782
|
+
/**
|
|
783
|
+
* ADR-289 — the entry point of the e-signature flow. Renders the named
|
|
784
|
+
* template against `variables` server-side and creates the resulting
|
|
785
|
+
* agreement in `draft` status with `required_signers` set — the ONLY
|
|
786
|
+
* route that can populate `required_signers` on create (plain `create()`
|
|
787
|
+
* above has no such field). Follow with `sendForSignature()` to email the
|
|
788
|
+
* signing links.
|
|
789
|
+
*/
|
|
790
|
+
async createFromTemplate(params) {
|
|
791
|
+
return this.request("POST", "/admin/agreements/create-from-template", {
|
|
792
|
+
templateId: params.templateId,
|
|
793
|
+
title: params.title,
|
|
794
|
+
variables: params.variables,
|
|
795
|
+
requiredSigners: params.requiredSigners,
|
|
796
|
+
agreementType: params.agreementType,
|
|
797
|
+
description: params.description,
|
|
798
|
+
expiresInDays: params.expiresInDays,
|
|
799
|
+
otherPartyName: params.otherPartyName,
|
|
800
|
+
});
|
|
801
|
+
}
|
|
652
802
|
async update(id, updates) {
|
|
653
803
|
return this.request("PATCH", `/admin/agreements/${id}`, updates);
|
|
654
804
|
}
|
|
@@ -661,6 +811,23 @@ class AgreementsResource extends BaseResource {
|
|
|
661
811
|
async linkWork(id, data) {
|
|
662
812
|
return this.request("POST", `/admin/agreements/${id}/works`, data);
|
|
663
813
|
}
|
|
814
|
+
/**
|
|
815
|
+
* Unlink (detach) a work from an agreement (ADR-289 Wave B1 item 5 —
|
|
816
|
+
* `detach` mode on `pica_agreements_link_work`, ports the bespoke
|
|
817
|
+
* assistant's `unlink_agreement_from_work`).
|
|
818
|
+
*/
|
|
819
|
+
async unlinkWork(id, workId) {
|
|
820
|
+
await this.request("DELETE", `/admin/agreements/${id}/works?work_id=${encodeURIComponent(workId)}`);
|
|
821
|
+
}
|
|
822
|
+
/**
|
|
823
|
+
* Per-signer signature status: name, signed/pending, signed_at
|
|
824
|
+
* (ADR-289 Wave B1 item 3 — backs the `signatures` section on
|
|
825
|
+
* `pica_agreements_inspect`, ports the bespoke assistant's
|
|
826
|
+
* `get_agreement_signature_status`).
|
|
827
|
+
*/
|
|
828
|
+
async getSignatureStatusWithSigners(id) {
|
|
829
|
+
return this.request("GET", `/admin/agreements/${id}/signatures`);
|
|
830
|
+
}
|
|
664
831
|
async sourceAgreementSplits(workId, agreementId, extractedSplits, confidence, confirm) {
|
|
665
832
|
return this.request("POST", `/admin/works/${workId}/agreement-source-splits`, {
|
|
666
833
|
agreement_id: agreementId,
|
|
@@ -669,6 +836,14 @@ class AgreementsResource extends BaseResource {
|
|
|
669
836
|
confirm: confirm ?? false,
|
|
670
837
|
});
|
|
671
838
|
}
|
|
839
|
+
/**
|
|
840
|
+
* ADR-289 — mint a per-signer `/sign/<token>` link and email every required
|
|
841
|
+
* signer of a draft agreement. Every signer lands in exactly one of
|
|
842
|
+
* `sent`/`skipped` (with a reason) — never silently half-done.
|
|
843
|
+
*/
|
|
844
|
+
async sendForSignature(id, params) {
|
|
845
|
+
return this.request("POST", `/admin/agreements/${id}/send-for-signature`, { expiresInDays: params?.expires_in_days });
|
|
846
|
+
}
|
|
672
847
|
}
|
|
673
848
|
// ADR-222 — sync placements as a first-class domain. REST routes implemented
|
|
674
849
|
// by W4 at /api/admin/sync-placements (paired PR on the same parent feature
|
|
@@ -785,6 +960,14 @@ class MemoryResource extends BaseResource {
|
|
|
785
960
|
async delete(id) {
|
|
786
961
|
await this.request("DELETE", `/admin/memory/${id}`);
|
|
787
962
|
}
|
|
963
|
+
// ADR-289 Wave C2 — pica_memory_update. Backing route is
|
|
964
|
+
// PATCH /admin/memory/[id] (lib/services/assistant-memory
|
|
965
|
+
// updateMemory); only content is exposed here (mirrors the retired
|
|
966
|
+
// bespoke assistant's handleUpdateMemory, which hard-coded
|
|
967
|
+
// source:"corrected" server-side).
|
|
968
|
+
async update(id, params) {
|
|
969
|
+
return this.request("PATCH", `/admin/memory/${id}`, params);
|
|
970
|
+
}
|
|
788
971
|
}
|
|
789
972
|
class NotesResource extends BaseResource {
|
|
790
973
|
async list(params) {
|
|
@@ -1862,7 +2045,20 @@ class ExportResource extends BaseResource {
|
|
|
1862
2045
|
qs.set("workId", params.work_id);
|
|
1863
2046
|
if (params.work_ids && params.work_ids.length > 0)
|
|
1864
2047
|
qs.set("workIds", params.work_ids.join(","));
|
|
1865
|
-
|
|
2048
|
+
const path = `/admin/works/export?${qs.toString()}`;
|
|
2049
|
+
// sync-pdf is the only format returning a JSON envelope
|
|
2050
|
+
// ({success, data, companyDetails}) — pro/distributor/nro stream raw
|
|
2051
|
+
// `text/csv` on success (route: app/api/admin/works/export/route.ts).
|
|
2052
|
+
// request() unconditionally calls response.json(), which throws parsing
|
|
2053
|
+
// a CSV body — every pro/distributor/nro call 500'd with INTERNAL_ERROR
|
|
2054
|
+
// (pica_export_catalog_csv: 5/5 prod errors, ops audit 2026-07-04).
|
|
2055
|
+
// requestText() mirrors the ImportResource.getTemplate() precedent for
|
|
2056
|
+
// the same response shape.
|
|
2057
|
+
if (params.format === "sync-pdf") {
|
|
2058
|
+
return this.request("GET", path);
|
|
2059
|
+
}
|
|
2060
|
+
const csv = await this.requestText("GET", path);
|
|
2061
|
+
return { format: params.format, csv };
|
|
1866
2062
|
}
|
|
1867
2063
|
async songRegistration(params) {
|
|
1868
2064
|
// Returns a signed-URL JSON envelope:
|
|
@@ -1961,6 +2157,11 @@ class SendResource extends BaseResource {
|
|
|
1961
2157
|
async resend(id) {
|
|
1962
2158
|
return this.request("POST", `/admin/send/${id}/resend`);
|
|
1963
2159
|
}
|
|
2160
|
+
// ADR-289 Wave C2 — pica_send_cancel. Backing route is
|
|
2161
|
+
// DELETE /admin/send/[id] (sendHubService.cancel).
|
|
2162
|
+
async cancel(id) {
|
|
2163
|
+
return this.request("DELETE", `/admin/send/${id}`);
|
|
2164
|
+
}
|
|
1964
2165
|
}
|
|
1965
2166
|
// --- Assets Resource (physical assets: equipment, instruments, studio gear) ---
|
|
1966
2167
|
class AssetsResource extends BaseResource {
|
|
@@ -2413,6 +2614,83 @@ class ProjectsResource extends BaseResource {
|
|
|
2413
2614
|
async attachWork(projectId, data) {
|
|
2414
2615
|
return this.request("POST", `/admin/projects/${projectId}/works`, data);
|
|
2415
2616
|
}
|
|
2617
|
+
/**
|
|
2618
|
+
* Detach (remove) a work from a project (ADR-289 Wave B2 item 2 —
|
|
2619
|
+
* `detach` mode on `pica_projects_attach_works`, ports the bespoke
|
|
2620
|
+
* assistant's `remove_work_from_project`). The work itself is not
|
|
2621
|
+
* deleted — only the `project_works` junction row.
|
|
2622
|
+
*/
|
|
2623
|
+
async detachWork(projectId, workId) {
|
|
2624
|
+
await this.request("DELETE", `/admin/projects/${projectId}/works/${encodeURIComponent(workId)}`);
|
|
2625
|
+
}
|
|
2626
|
+
// -------------------------------------------------------------------
|
|
2627
|
+
// ADR-289 Wave C1 — participants, ports the bespoke assistant's
|
|
2628
|
+
// add_participants / update_participant / remove_participant /
|
|
2629
|
+
// list_project_participants / get_participant_details trio.
|
|
2630
|
+
//
|
|
2631
|
+
// Route asymmetry (both pre-existing, not introduced here):
|
|
2632
|
+
// - PATCH /participants/[participantId] keys off the participant's
|
|
2633
|
+
// OWN row id.
|
|
2634
|
+
// - DELETE /participants/[participantId] actually keys off person_id
|
|
2635
|
+
// (route comment: "participantId here is actually the person_id
|
|
2636
|
+
// for consistency"). removeParticipant() below reproduces that
|
|
2637
|
+
// literally; callers wanting participant-id ergonomics resolve via
|
|
2638
|
+
// listParticipants() first (see ProjectsTools.manageParticipants).
|
|
2639
|
+
// -------------------------------------------------------------------
|
|
2640
|
+
async listParticipants(projectId) {
|
|
2641
|
+
return this.request("GET", `/admin/projects/${projectId}/participants`);
|
|
2642
|
+
}
|
|
2643
|
+
async addParticipant(projectId, data) {
|
|
2644
|
+
return this.request("POST", `/admin/projects/${projectId}/participants`, data);
|
|
2645
|
+
}
|
|
2646
|
+
async addParticipantsBulk(projectId, participants) {
|
|
2647
|
+
return this.request("POST", `/admin/projects/${projectId}/participants`, {
|
|
2648
|
+
participants,
|
|
2649
|
+
});
|
|
2650
|
+
}
|
|
2651
|
+
/** `participantId` is the `project_participants` row id. */
|
|
2652
|
+
async updateParticipant(projectId, participantId, data) {
|
|
2653
|
+
return this.request("PATCH", `/admin/projects/${projectId}/participants/${encodeURIComponent(participantId)}`, data);
|
|
2654
|
+
}
|
|
2655
|
+
/** `personId` — the route's `[participantId]` segment is actually person_id here. */
|
|
2656
|
+
async removeParticipant(projectId, personId) {
|
|
2657
|
+
await this.request("DELETE", `/admin/projects/${projectId}/participants/${encodeURIComponent(personId)}`);
|
|
2658
|
+
}
|
|
2659
|
+
// -------------------------------------------------------------------
|
|
2660
|
+
// ADR-289 Wave C1 — multimedia, ports the bespoke assistant's
|
|
2661
|
+
// list_project_multimedia / add_multimedia_to_project /
|
|
2662
|
+
// update_project_multimedia / remove_multimedia_from_project.
|
|
2663
|
+
//
|
|
2664
|
+
// Route asymmetry (both pre-existing, not introduced here):
|
|
2665
|
+
// - PATCH /multimedia/[multimediaId] keys off the `project_multimedia`
|
|
2666
|
+
// join row's OWN id.
|
|
2667
|
+
// - DELETE /multimedia/[multimediaId] keys off `multimedia_id` (the
|
|
2668
|
+
// underlying multimedia_items id), not the join row id. Callers
|
|
2669
|
+
// wanting join-row-id ergonomics resolve via listMultimedia() first
|
|
2670
|
+
// (see ProjectsTools.manageMultimedia).
|
|
2671
|
+
// -------------------------------------------------------------------
|
|
2672
|
+
async listMultimedia(projectId, day) {
|
|
2673
|
+
const qs = day !== undefined ? `?day=${day}` : "";
|
|
2674
|
+
return this.request("GET", `/admin/projects/${projectId}/multimedia${qs}`);
|
|
2675
|
+
}
|
|
2676
|
+
async addMultimedia(projectId, data) {
|
|
2677
|
+
return this.request("POST", `/admin/projects/${projectId}/multimedia`, data);
|
|
2678
|
+
}
|
|
2679
|
+
async addMultimediaBulk(projectId, multimediaIds, options) {
|
|
2680
|
+
return this.request("POST", `/admin/projects/${projectId}/multimedia`, {
|
|
2681
|
+
multimedia_ids: multimediaIds,
|
|
2682
|
+
project_day: options?.project_day,
|
|
2683
|
+
allow_download: options?.allow_download,
|
|
2684
|
+
});
|
|
2685
|
+
}
|
|
2686
|
+
/** `multimediaLinkId` is the `project_multimedia` join row's own id. */
|
|
2687
|
+
async updateMultimediaLink(projectId, multimediaLinkId, data) {
|
|
2688
|
+
return this.request("PATCH", `/admin/projects/${projectId}/multimedia/${encodeURIComponent(multimediaLinkId)}`, data);
|
|
2689
|
+
}
|
|
2690
|
+
/** `multimediaId` — the route's `[multimediaId]` segment on DELETE is the underlying multimedia_items id, not the join row id. */
|
|
2691
|
+
async removeMultimediaLink(projectId, multimediaId) {
|
|
2692
|
+
await this.request("DELETE", `/admin/projects/${projectId}/multimedia/${encodeURIComponent(multimediaId)}`);
|
|
2693
|
+
}
|
|
2416
2694
|
}
|
|
2417
2695
|
class SplitSheetsResource extends BaseResource {
|
|
2418
2696
|
async listForWork(workId) {
|
|
@@ -3121,6 +3399,25 @@ class TelegramResource extends BaseResource {
|
|
|
3121
3399
|
async getPreferences() {
|
|
3122
3400
|
return this.request("GET", "/admin/settings/telegram/notifications");
|
|
3123
3401
|
}
|
|
3402
|
+
// ADR-289 Wave C2 — pica_telegram_config write half. The REST route
|
|
3403
|
+
// (POST /admin/settings/telegram/notifications) speaks camelCase
|
|
3404
|
+
// (eventType/isActive/configs) — translate from the snake_case tool args
|
|
3405
|
+
// here so the tool layer stays consistent with every other tool's
|
|
3406
|
+
// snake_case convention.
|
|
3407
|
+
async setPreferences(params) {
|
|
3408
|
+
const body = {};
|
|
3409
|
+
if (params.event_type !== undefined) {
|
|
3410
|
+
body.eventType = params.event_type;
|
|
3411
|
+
body.isActive = params.is_enabled;
|
|
3412
|
+
}
|
|
3413
|
+
if (params.bulk_config) {
|
|
3414
|
+
body.configs = params.bulk_config.map((c) => ({
|
|
3415
|
+
eventType: c.event_type,
|
|
3416
|
+
isActive: c.is_enabled,
|
|
3417
|
+
}));
|
|
3418
|
+
}
|
|
3419
|
+
return this.request("POST", "/admin/settings/telegram/notifications", body);
|
|
3420
|
+
}
|
|
3124
3421
|
// ADR-159: MCP-native Telegram pairing. Wraps the pair endpoint which
|
|
3125
3422
|
// returns a magic code (or short-circuits on already-connected / live
|
|
3126
3423
|
// pending code). Rate-limited to 3 new codes per user per rolling hour.
|
|
@@ -3167,6 +3464,8 @@ export class PicaClient {
|
|
|
3167
3464
|
people;
|
|
3168
3465
|
recordings;
|
|
3169
3466
|
licensing;
|
|
3467
|
+
// ADR-289 Wave C1 — internal-team booking enquiries.
|
|
3468
|
+
bookings;
|
|
3170
3469
|
credits;
|
|
3171
3470
|
creditsBalance;
|
|
3172
3471
|
picaScore;
|
|
@@ -3274,6 +3573,7 @@ export class PicaClient {
|
|
|
3274
3573
|
this.people = new PeopleResource(baseUrl, config.apiKey, debug);
|
|
3275
3574
|
this.recordings = new RecordingsResource(baseUrl, config.apiKey, debug);
|
|
3276
3575
|
this.licensing = new LicensingResource(baseUrl, config.apiKey, debug);
|
|
3576
|
+
this.bookings = new BookingsResource(baseUrl, config.apiKey, debug);
|
|
3277
3577
|
this.credits = new CreditsResource(baseUrl, config.apiKey, debug);
|
|
3278
3578
|
this.creditsBalance = new CreditsBalanceResource(baseUrl, config.apiKey, debug);
|
|
3279
3579
|
this.picaScore = new PicaScoreResource(baseUrl, config.apiKey, debug);
|