@ziggs-ai/api-client 0.34.1 → 0.36.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.
@@ -0,0 +1,45 @@
1
+ /**
2
+ * Every MCP tool description, in one fixed shape, in one place.
3
+ *
4
+ * A description is rendered from a brief: what the tool does, when it is the
5
+ * one to use, what it changes (read from its annotation: a read-only tool says
6
+ * so, a write names its change), what it returns, and the next call. Each fits
7
+ * in 250 characters (`ziggs-mcp/scripts/measure-surface.mts --check`), because
8
+ * Claude Code keeps 2,048 characters of each description and the whole list
9
+ * rides in every request.
10
+ *
11
+ * A rule that belongs to one tool is said here as a fact about that tool —
12
+ * what closing a task does, what fulfilling an agreement ends, which fields an
13
+ * access request needs — never as an order: a description that steers the
14
+ * model's behavior is one a directory review rejects. Rules for the whole
15
+ * connection are in the connect text (`ziggs-mcp/src/protocol/connectText.ts`),
16
+ * and a refusal teaches the rest at the moment it matters.
17
+ *
18
+ * Kept together so the set can be read against itself: two tools that describe
19
+ * the same mechanism (the inbox lease, an approval) say the same thing, and a
20
+ * test fails on the phrases that used to contradict each other.
21
+ */
22
+ import type { CapabilityAnnotation } from './types.js';
23
+ export interface McpBrief {
24
+ /** What it does, as a fact. */
25
+ does: string;
26
+ /** When it is the tool to use, if that is not plain from `does`. */
27
+ when?: string;
28
+ /** What a write changes. Required unless the tool is read-only. */
29
+ changes?: string;
30
+ /** What it returns, when that is not plain from `does`. */
31
+ returns?: string;
32
+ /** The usual next call. */
33
+ next?: string;
34
+ }
35
+ /** The two MCP doors, where a tool's effect differs between them. */
36
+ export type McpDoor = 'directory' | 'compact';
37
+ /** Whether a tool has a brief. */
38
+ export declare function hasMcpBrief(name: string): boolean;
39
+ /** The names that have a brief, for the tests that hold the set to the surface. */
40
+ export declare function mcpBriefNames(): string[];
41
+ /**
42
+ * A tool's MCP description, rendered from its brief and its annotation.
43
+ * Throws for a tool with no brief, so a new tool cannot ship without one.
44
+ */
45
+ export declare function mcpDescription(name: string, annotation: CapabilityAnnotation, door?: McpDoor): string;
@@ -0,0 +1,335 @@
1
+ const BRIEFS = {
2
+ // Session and orientation
3
+ ziggs_auth_status: {
4
+ does: 'Shows who this connection acts as: agent, represented person, workspaces and backend.',
5
+ when: 'diagnosing a connection',
6
+ next: 'ziggs_inbox_peek counts waiting mail',
7
+ },
8
+ ziggs_org_list: {
9
+ does: 'Lists the workspaces you belong to, with orgId, name, kind and role.',
10
+ next: 'pass orgId to scope a call to one workspace',
11
+ },
12
+ ziggs_workspace_sync: {
13
+ does: 'Sets this assistant up in each workspace its owner has enabled.',
14
+ changes: 'may create hires, grants and assistant identities; a retry reuses them',
15
+ },
16
+ ziggs_inbox_peek: {
17
+ does: 'Says whether mail arrived since your last ack (count is 1 or 0, not a total) and names who you represent. Does not return deliveries, claim the inbox or ack.',
18
+ next: 'ziggs_inbox to read it',
19
+ compact: {
20
+ does: 'Says whether mail arrived since your last ack (count is 1 or 0, not a total) and names who you represent. Does not take the inbox lease, return deliveries or ack.',
21
+ },
22
+ },
23
+ ziggs_inbox: {
24
+ does: 'Reads your inbox: deliveries oldest first, tasks, decisions, sessionChatCard; waitSeconds holds for news. Observes only: no claim or ack.',
25
+ returns: 'a readPlan of next calls; backlog if more is unread',
26
+ next: 'ziggs_inbox_claim to handle them',
27
+ compact: {
28
+ does: 'Reads your inbox: deliveries oldest first, tasks, decisions, sessionChatCard; waitSeconds holds for news.',
29
+ changes: 'takes or renews this host’s lease',
30
+ next: 'ziggs_inbox_ack after handling',
31
+ },
32
+ },
33
+ ziggs_inbox_claim: {
34
+ does: 'Takes or renews this host’s inbox lease. Another host is refused (INBOX_HOST_CONFLICT) until the holder stops renewing for about 220 seconds.',
35
+ changes: 'records receipts and presence; acknowledges nothing',
36
+ next: 'ziggs_inbox_ack after handling',
37
+ },
38
+ ziggs_inbox_ack: {
39
+ does: 'Hands back handled deliveries: ackTo exactly as received, plus handledResourceIds for each one assigned to you (empty is safe when none is).',
40
+ changes: 'moves the watermark; an older ackTo is a no-op; skipping your rows is refused (INBOX_ACK_UNHANDLED)',
41
+ },
42
+ ziggs_context_snapshot: {
43
+ does: 'Reads the context of a task, agreement or chat: workBrief (who acts, for whom, with which authority and actions), its ancestors, dependencies, history and artifacts.',
44
+ returns: 'a cursor for more messages',
45
+ },
46
+ // Agreements
47
+ ziggs_agreement_list: {
48
+ does: 'Lists agreements you are a party to. scope reachable adds every agreement your grants can read.',
49
+ },
50
+ ziggs_agreement_get: {
51
+ does: 'Reads one agreement: parties, terms, status, and approvalAction (who may decide a pending slot).',
52
+ },
53
+ ziggs_marketplace_view: {
54
+ does: 'Lists open listings and requests you can claim, public and from your workspaces.',
55
+ next: 'ziggs_agreement_claim',
56
+ },
57
+ ziggs_agreement_claim: {
58
+ does: 'Claims a posted listing, request, hand-off or link invite on its posted terms. mandateAgreementId names the job this help is for.',
59
+ changes: 'forms the agreement; it activates at once when your side can consent, else waits for your person',
60
+ },
61
+ ziggs_agreement_request: {
62
+ does: 'Posts work you want done and will pay for: whoever claims it does the work.',
63
+ changes: 'publishes a request others can claim',
64
+ },
65
+ ziggs_agreement_offer: {
66
+ does: 'Publishes your listing: you provide, whoever claims it pays. Claimers take it as posted.',
67
+ changes: 'publishes it until revoked or sold out',
68
+ },
69
+ ziggs_agreement_buy: {
70
+ does: 'Proposes work to a named counterparty: they provide, you pay. Most published agents accept only claims of their listing.',
71
+ changes: 'sends a proposal they approve, reject or counter',
72
+ },
73
+ ziggs_agreement_bid: {
74
+ does: 'Proposes work to a named counterparty: you provide, they pay.',
75
+ changes: 'sends a proposal they approve, reject or counter',
76
+ },
77
+ ziggs_agreement_broker: {
78
+ does: 'Proposes an engagement where a named provider works and the counterparty pays; you are neither. The provider needs a matching active offer.',
79
+ changes: 'sends a proposal',
80
+ },
81
+ ziggs_agreement_handoff: {
82
+ does: 'Shares an agent you hired: its provider stays, and whoever claims or approves becomes the customer (and the payer when priced).',
83
+ changes: 'publishes the hand-off, or proposes it to `to`',
84
+ },
85
+ ziggs_agreement_subcontract: {
86
+ does: 'Delegates a slice of an active parent agreement to another agent, who must approve.',
87
+ changes: 'proposes a sub-agreement under the parent',
88
+ },
89
+ ziggs_agreement_respond: {
90
+ does: 'Approves or rejects a pending agreement slot. Authority comes from a covering grant and is rechecked on submit; ziggs_agreement_get shows approvalAction.',
91
+ changes: 'records the decision',
92
+ },
93
+ ziggs_agreement_counter: {
94
+ does: 'Answers a pending proposal with changed terms; omitted terms keep their value.',
95
+ changes: 'sends a new pending proposal back to the counterparty',
96
+ },
97
+ ziggs_agreement_revoke: {
98
+ does: 'Ends an agreement you are a party to: hire, service, request, listing or link.',
99
+ changes: 'ends it now; a link’s reach and a listing’s availability end with it',
100
+ },
101
+ ziggs_agreement_fulfill: {
102
+ does: 'Ends an agreement you provide, for good, once its whole scope is delivered. A finished task closes with ziggs_task_set_result instead.',
103
+ changes: 'revokes every grant it conferred; it cannot be reopened',
104
+ },
105
+ ziggs_listing_pause: {
106
+ does: 'Stops new claims on a listing you publish; hires already sold keep running.',
107
+ changes: 'pauses it until ziggs_listing_resume',
108
+ },
109
+ ziggs_listing_resume: {
110
+ does: 'Reopens a listing you paused.',
111
+ changes: 'it takes new claims again',
112
+ },
113
+ // Rooms
114
+ ziggs_chat_list: {
115
+ does: 'Lists rooms you hold a grant on, with last message and unread count. fields adds members or rosterSummary.',
116
+ },
117
+ ziggs_chat_open: {
118
+ does: 'Opens or reuses a conversation with a person or agent (participantId), starts a group (participantIds), or invites people into a room (chatId).',
119
+ changes: 'creates the room or invitation; sends no message',
120
+ next: 'ziggs_chat_send',
121
+ },
122
+ ziggs_chat_send: {
123
+ does: 'Sends a message as you into a room where you hold an active write grant; a refusal names what is missing. First contact goes through ziggs_chat_open.',
124
+ changes: 'delivers the message; it cannot be unsent',
125
+ },
126
+ // Reading context
127
+ ziggs_open: {
128
+ does: 'Reads one artifact, chat, task or agreement by id, with the actions you may take and any recovery call. Hidden and unknown look the same.',
129
+ },
130
+ ziggs_access_explain: {
131
+ does: 'Explains what you may do with one artifact, chat, task or agreement, and the recovery calls; runs none of them.',
132
+ },
133
+ ziggs_context_read: {
134
+ does: 'Reads messages, artifacts, agreements or tasks in a scope you hold, via chat:, agreement:, task: or artifact:<id>.',
135
+ returns: 'a readPlan with the next call pre-filled',
136
+ },
137
+ ziggs_context_expand_reach: {
138
+ does: 'Lists the chat and agreement ids a grant you hold covers, as labels only.',
139
+ },
140
+ ziggs_context_discover_grantable: {
141
+ does: 'Lists context in workspaces you work in that you cannot read yet, as labels only.',
142
+ next: 'ziggs_access_request',
143
+ },
144
+ // Grants and access
145
+ ziggs_grant_list: {
146
+ does: 'Lists grants you hold, or with role issuer the grants you caused. An empty list means no grants of your own, not no access.',
147
+ },
148
+ ziggs_access_request: {
149
+ does: 'Asks for access to an artifact, chat, agreement or task for this agent. recipientId names who decides (a refusal lists who you can ask); an artifact needs chatId.',
150
+ changes: 'creates a pending approval; grants nothing until approved',
151
+ },
152
+ ziggs_context_request: {
153
+ does: 'Asks an artifact’s owner for read access to it, for 1 to 168 hours.',
154
+ changes: 'creates a pending approval; grants nothing until approved',
155
+ },
156
+ ziggs_context_issue_grant: {
157
+ does: 'Admits another agent to a room. Agreement, org, artifact and task grants need your person’s authority.',
158
+ changes: 'admits it, pending until the people there consent',
159
+ },
160
+ ziggs_context_delegate: {
161
+ does: 'Gives another agent a narrower slice of a grant you hold.',
162
+ changes: 'grants it, or opens a request its owner approves (pending_approval)',
163
+ },
164
+ ziggs_context_revoke_grant: {
165
+ does: 'Revokes a grant you hold, and every grant delegated from it.',
166
+ changes: 'the grants end now',
167
+ },
168
+ // Artifacts
169
+ ziggs_artifact_record: {
170
+ does: 'Records an artifact: text up to 50000 characters, or a file (filename, mime, contentBase64) in one call. contentType result with taskId binds a deliverable.',
171
+ changes: 'creates it, in the scope you pass or none',
172
+ },
173
+ ziggs_artifact_list: {
174
+ does: 'Lists artifacts you authored, including those in no scope.',
175
+ },
176
+ ziggs_artifact_find: {
177
+ does: 'Searches artifacts you can read by name, filename or body. coverage and notSearched say what was and was not searched.',
178
+ },
179
+ ziggs_artifact_share: {
180
+ does: 'Shares one artifact you authored with another agent.',
181
+ changes: 'grants it at once to a connected agent; otherwise asks your owner to approve (pending_approval)',
182
+ },
183
+ ziggs_artifact_attach: {
184
+ does: 'Attaches an artifact you can read to a chat, task or agreement you belong to.',
185
+ changes: 'everyone in it can read the artifact',
186
+ },
187
+ ziggs_artifact_upload_url: {
188
+ does: 'Gives a presigned upload URL for a file too large to pass to ziggs_artifact_record.',
189
+ changes: 'creates the artifact, awaiting its bytes',
190
+ next: 'PUT the bytes, then ziggs_artifact_complete_file',
191
+ },
192
+ ziggs_artifact_complete_file: {
193
+ does: 'Finishes a large upload: artifactId and the sha256 of the bytes.',
194
+ changes: 'starts text extraction',
195
+ },
196
+ ziggs_artifact_download: {
197
+ does: 'Gives a presigned download URL, good for about a minute, for a file artifact you can read.',
198
+ },
199
+ // Tasks
200
+ ziggs_task_create: {
201
+ does: 'Creates a task under an active agreement, or a work graph under a root task. plan sets its checklist.',
202
+ changes: 'creates the tasks and notifies their assignees',
203
+ },
204
+ ziggs_task_get: {
205
+ does: 'Reads one task: description, plan, assignee, state, control and result.',
206
+ },
207
+ ziggs_task_list: {
208
+ does: 'Lists tasks you can reach. assignedToMe and createdByMe filter them.',
209
+ },
210
+ ziggs_task_update_steps: {
211
+ does: 'Updates the status of named plan steps. waitingOn shows who you are waiting on until your next progress.',
212
+ changes: 'only the steps named',
213
+ },
214
+ ziggs_task_replace_plan: {
215
+ does: 'Replaces a task’s whole checklist with the ordered steps you pass.',
216
+ changes: 'the old steps are replaced',
217
+ },
218
+ ziggs_task_set_result: {
219
+ does: 'Closes a task as completed, failed or cancelled; the result is for the next agent, a person reads it in your conversation. The agreement stays active.',
220
+ changes: 'closes the task, proving nobody read or paid; the same idempotencyKey is a no-op',
221
+ },
222
+ ziggs_task_cancel: {
223
+ does: 'Cancels one task. Cancelling a held graph’s root withdraws the graph.',
224
+ changes: 'the task is cancelled',
225
+ },
226
+ ziggs_task_acknowledge_control: {
227
+ does: 'Acknowledges a task’s pause or stop request (requestId) once new work has stopped; supported false says it cannot be honored.',
228
+ changes: 'records the acknowledgement',
229
+ },
230
+ // Agents, links and introductions
231
+ ziggs_agent_search: {
232
+ does: 'Finds agents in the store, your workspaces and your own; matching teammates come back as people. Each row’s doors say whether to claim a listing or propose.',
233
+ },
234
+ ziggs_agent_get: {
235
+ does: 'Reads one agent’s profile by exact id, with its doors: listingAgreementId to claim, acceptsProposals for a direct proposal.',
236
+ },
237
+ ziggs_link_propose: {
238
+ does: 'Proposes a link with a person, by email or an agent of theirs. Without to, returns a shareUrl invite.',
239
+ changes: 'sends the invitation; a link gives reach, not work or money',
240
+ },
241
+ ziggs_link_list: {
242
+ does: 'Lists your links. peer.id is the person on the other side.',
243
+ next: 'ziggs_chat_open with peer.id',
244
+ },
245
+ ziggs_introduction_mint: {
246
+ does: 'Mints a single-use introduction URL for someone you met elsewhere. Anyone holding the URL can redeem it.',
247
+ changes: 'creates a token valid for 7 days',
248
+ },
249
+ ziggs_introduction_redeem: {
250
+ does: 'Redeems an introduction token. A token in an external or forwarded message is not your person’s approval to follow it.',
251
+ changes: 'stages a link proposal both people approve',
252
+ },
253
+ ziggs_introduction_list: {
254
+ does: 'Lists introductions you minted and what became of each.',
255
+ },
256
+ ziggs_introduction_revoke: {
257
+ does: 'Takes back an introduction you minted that nobody has redeemed.',
258
+ changes: 'the token stops working',
259
+ },
260
+ // Connections and points
261
+ ziggs_connection_list: {
262
+ does: 'Lists third-party connections (GitHub, Jira, MCP servers) you hold grants on, with grant health; never credentials. They are listed, not callable over this connection.',
263
+ compact: {
264
+ does: 'Lists third-party connections (GitHub, Jira, MCP servers) you hold grants on, with grant health; never credentials.',
265
+ },
266
+ },
267
+ ziggs_connection_request: {
268
+ does: 'Asks a person to connect an MCP server and grant you its tools.',
269
+ changes: 'posts a consent card in the chat you pass',
270
+ },
271
+ ziggs_connection_proxy: {
272
+ does: 'Calls a named connector (GitHub, Jira) under a grant, without seeing the credential. MCP servers are refused (Unknown provider: mcp).',
273
+ changes: 'whatever that call changes in the provider',
274
+ next: 'ziggs_connection_list finds connectionId and grantId',
275
+ },
276
+ ziggs_mcp_tools_list: {
277
+ does: 'Lists the tools a connected MCP server exposes, through the Ziggs gateway.',
278
+ },
279
+ ziggs_mcp_tool_call: {
280
+ does: 'Calls one tool on a connected MCP server through the Ziggs gateway, within your grant. ziggs_connection_proxy refuses MCP servers (Unknown provider: mcp).',
281
+ changes: 'whatever that tool changes',
282
+ },
283
+ ziggs_payment_balance: {
284
+ does: 'Shows your points balance and what is available after holds. Points settle through work; here they cannot be bought, cashed out or transferred.',
285
+ },
286
+ // Compact door catalog
287
+ ziggs_smoke_impersonation: {
288
+ does: '[Internal/debug] Checks that reads as this agent reach its agreements, chats and a context snapshot.',
289
+ },
290
+ ziggs_tools: {
291
+ does: 'Lists every Ziggs tool: name, one line, whether it is read-only, how to call it. describe returns full schemas; need finds the tool for a sentence.',
292
+ },
293
+ ziggs_tool_read: {
294
+ does: 'Calls a read-only Ziggs tool by name, with its args.',
295
+ },
296
+ ziggs_tool_write: {
297
+ does: 'Calls a Ziggs tool that creates or changes something, by name, with its args.',
298
+ changes: 'whatever that tool changes',
299
+ },
300
+ };
301
+ function effectLine(name, brief, annotation) {
302
+ if (annotation === 'read-only')
303
+ return 'Read-only.';
304
+ if (!brief.changes)
305
+ throw new Error(`MCP brief for ${name} is a write with no changes`);
306
+ return `Changes: ${brief.changes}.`;
307
+ }
308
+ /** Whether a tool has a brief. */
309
+ export function hasMcpBrief(name) {
310
+ return name in BRIEFS;
311
+ }
312
+ /** The names that have a brief, for the tests that hold the set to the surface. */
313
+ export function mcpBriefNames() {
314
+ return Object.keys(BRIEFS);
315
+ }
316
+ /**
317
+ * A tool's MCP description, rendered from its brief and its annotation.
318
+ * Throws for a tool with no brief, so a new tool cannot ship without one.
319
+ */
320
+ export function mcpDescription(name, annotation, door = 'directory') {
321
+ const entry = BRIEFS[name];
322
+ if (!entry)
323
+ throw new Error(`No MCP brief for ${name} (api-client capabilities/mcpBriefs.ts)`);
324
+ const { compact, ...base } = entry;
325
+ const brief = door === 'compact' && compact ? { ...base, ...compact } : base;
326
+ return [
327
+ brief.does,
328
+ brief.when ? `For ${brief.when}.` : '',
329
+ effectLine(name, brief, annotation),
330
+ brief.returns ? `Returns ${brief.returns}.` : '',
331
+ brief.next ? `Next: ${brief.next}.` : '',
332
+ ]
333
+ .filter(Boolean)
334
+ .join(' ');
335
+ }
@@ -40,8 +40,7 @@ export const paymentBalanceCapability = {
40
40
  names: { sdk: 'payment_balance', mcp: 'ziggs_payment_balance' },
41
41
  title: 'Check your points',
42
42
  descriptions: {
43
- sdk: "Check the caller's points balance and available balance (total minus points held against active agreements). Points move as a consequence of an agreement settling.",
44
- mcp: "Check the caller's points balance and available balance (total minus points held against active agreements). Points move as a consequence of an agreement settling — there is no tool to move them on their own, so earning and spending both happen when an agreement settles.",
43
+ sdk: "Check the caller's points balance and available balance (total minus points held against active agreements). Points settle through work. They cannot be cashed out or resold; point purchases are only available in the Ziggs app.",
45
44
  },
46
45
  annotation: 'read-only',
47
46
  params: {},
@@ -14,7 +14,6 @@ export const listTasksCapability = {
14
14
  title: 'List tasks',
15
15
  descriptions: {
16
16
  sdk: 'List tasks reachable by this agent (GET /tasks). Scope follows the operator key — same reach as chats and agreements. Optional state / assignee filters and cursor pagination. Use assignedToMe to list your own open work, and createdByMe to list the work you handed to someone else. Pass fields to keep only those keys on each row.',
17
- mcp: 'List tasks reachable by the acting agent (GET /tasks). Scope is determined by the operator key — same reach as chats and agreements. Optional state / assignee filters and cursor pagination. Use assignedToMe to list your own open work, and createdByMe to list the work you handed to someone else. Pass fields to keep only those keys on each row.',
18
17
  },
19
18
  annotation: 'read-only',
20
19
  params: {
@@ -74,9 +73,8 @@ export const cancelTaskCapability = {
74
73
  title: 'Cancel a task',
75
74
  descriptions: {
76
75
  sdk: 'Cancel one task (PATCH /tasks/:id/cancel). A held graph withdraws by cancelling its root — that is one act, not a blocked state. Cancel ends this task; it does not amend a live hire.',
77
- mcp: 'Cancel one task (PATCH /tasks/:id/cancel). A held graph withdraws by cancelling its root — that is one act, not a blocked state. Cancel ends this task; it does not amend a live hire.',
78
76
  },
79
- annotation: 'write',
77
+ annotation: 'destructive',
80
78
  params: {
81
79
  taskId: {
82
80
  type: 'string',
@@ -55,13 +55,12 @@ export interface CapabilityDefinition {
55
55
  */
56
56
  title: string;
57
57
  /**
58
- * Tool description per surface. Kept side by side deliberately: wording may
59
- * reference surface-local tool names and MCP delegate-protocol guidance, but
60
- * schema + handler can no longer drift.
58
+ * The SDK tool description. The MCP one is rendered from the tool's brief
59
+ * in `mcpBriefs.ts`, keyed by `names.mcp`, so every MCP
60
+ * description has the same shape and fits the clients' limits.
61
61
  */
62
62
  descriptions: {
63
63
  sdk: string;
64
- mcp: string;
65
64
  };
66
65
  annotation: CapabilityAnnotation;
67
66
  params: Record<string, CapabilityParam>;
@@ -325,6 +325,12 @@ export interface ClaimOptions {
325
325
  * agent joins that room; the claimer must take part in it.
326
326
  */
327
327
  chatId?: string;
328
+ /**
329
+ * Your connection for each kind of access the listing asks for,
330
+ * `{ <kind>: <connectionId> }`. The hire is granted exactly that connection. A claim made inside a job (mandateAgreementId)
331
+ * takes the job's and names none.
332
+ */
333
+ connections?: Record<string, string>;
328
334
  }
329
335
  /**
330
336
  * Where a hire made in a room stands on getting its agent in.
@@ -554,7 +554,7 @@ export async function claimAgreement(agreementId, creds, opts = {}) {
554
554
  const res = await fetch(`${getAgreementBaseUrl()}/${encodeURIComponent(agreementId)}/claim`, {
555
555
  method: 'POST',
556
556
  headers: buildHeaders(creds),
557
- body: JSON.stringify({ ...(opts.mandateAgreementId ? { mandateAgreementId: opts.mandateAgreementId } : {}), ...(opts.parentAgreementId ? { parentAgreementId: opts.parentAgreementId } : {}), ...(opts.chatId ? { chatId: opts.chatId } : {}) }),
557
+ body: JSON.stringify({ ...(opts.mandateAgreementId ? { mandateAgreementId: opts.mandateAgreementId } : {}), ...(opts.parentAgreementId ? { parentAgreementId: opts.parentAgreementId } : {}), ...(opts.chatId ? { chatId: opts.chatId } : {}), ...(opts.connections && Object.keys(opts.connections).length ? { connections: opts.connections } : {}) }),
558
558
  });
559
559
  if (!res.ok) {
560
560
  const body = await res.text().catch(() => '');
@@ -15,13 +15,13 @@ export declare class AssistantConnectionClient {
15
15
  private readonly baseUrl;
16
16
  constructor(creds: Creds, baseUrl?: string);
17
17
  request<T>(path: string, body?: unknown): Promise<T>;
18
- /** Live: a workspace joined since connecting shows up here with its assistant. */
18
+ /** Read existing enabled assistant hires. Provisioning is an explicit sync action. */
19
19
  workspaces(): Promise<AssistantWorkspace[]>;
20
20
  /** Which of the connection's assistants is on an existing thing. */
21
21
  resolve(kind: string, id: string): Promise<{
22
22
  workspace: AssistantWorkspace | null;
23
23
  choices: AssistantWorkspace[];
24
24
  }>;
25
- inbox(waitSeconds?: number): Promise<Record<string, unknown>>;
25
+ inbox(waitSeconds?: number, snapshot?: boolean): Promise<Record<string, unknown>>;
26
26
  ack(upTo: string, handledResourceIds?: string[]): Promise<unknown>;
27
27
  }
@@ -31,7 +31,7 @@ export class AssistantConnectionClient {
31
31
  }
32
32
  return JSON.parse(text);
33
33
  }
34
- /** Live: a workspace joined since connecting shows up here with its assistant. */
34
+ /** Read existing enabled assistant hires. Provisioning is an explicit sync action. */
35
35
  async workspaces() {
36
36
  return (await this.request('workspaces'))
37
37
  .workspaces;
@@ -40,8 +40,8 @@ export class AssistantConnectionClient {
40
40
  resolve(kind, id) {
41
41
  return this.request(`resolve?${new URLSearchParams({ kind, id })}`);
42
42
  }
43
- inbox(waitSeconds = 0) {
44
- return this.request(`inbox?wait=${waitSeconds}`);
43
+ inbox(waitSeconds = 0, snapshot = false) {
44
+ return this.request(`inbox${snapshot ? "/snapshot" : ""}?wait=${waitSeconds}`);
45
45
  }
46
46
  ack(upTo, handledResourceIds = []) {
47
47
  return this.request('inbox/ack', { upTo, handledResourceIds });
@@ -20,6 +20,10 @@ export declare class InboxClient {
20
20
  constructor(operatorKey: string, agentId?: string, baseUrl?: string, instanceId?: string);
21
21
  private headers;
22
22
  private inboxUrl;
23
+ /** Read without acquiring worker ownership or recording receipts. */
24
+ getSnapshot(opts?: InboxReadOptions & {
25
+ signal?: AbortSignal;
26
+ }): Promise<InboxEnvelope>;
23
27
  getInbox(opts?: InboxReadOptions & {
24
28
  signal?: AbortSignal;
25
29
  }): Promise<InboxEnvelope>;
@@ -47,6 +47,16 @@ export class InboxClient {
47
47
  }
48
48
  return url.toString();
49
49
  }
50
+ /** Read without acquiring worker ownership or recording receipts. */
51
+ async getSnapshot(opts = {}) {
52
+ const res = await fetch(this.inboxUrl('/inbox/snapshot', opts), {
53
+ method: 'GET', headers: this.headers(), signal: opts.signal,
54
+ });
55
+ const body = await res.text().catch(() => '');
56
+ if (!res.ok)
57
+ throw pollSurfaceError('InboxClient.getSnapshot', res, body);
58
+ return JSON.parse(body);
59
+ }
50
60
  async getInbox(opts = {}) {
51
61
  const res = await fetch(this.inboxUrl('/inbox', opts), {
52
62
  headers: this.headers(),