@ziggs-ai/api-client 0.40.9 → 0.41.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
@@ -2,6 +2,12 @@
2
2
 
3
3
  ## Unreleased
4
4
 
5
+ ## 0.41.0
6
+
7
+ - Short handles name a task (T…), an agreement (A…) or an artifact (F…); `HandleKind` drops `address`. A C… handle or a 24-letter room id is still refused locally on open as a retired room reference.
8
+ - Rooms are gone, and the client no longer names one. `agreement_buy`, `agreement_bid` and `agreement_broker` drop their `addressId` parameter, and `proposeUnified`, `proposeDirectTo` and the broadcast proposals no longer send one. The inbox types drop `chats` and `InboxChatNews`, and a delivery no longer carries `addressId`. Engagement guides no longer carry `addressId`, and `strangerBriefGuide` takes only the environment.
9
+ - Tool descriptions and hints say conversation, bucket or work where they said room. Opaque `rpb_*` references are gone; a reply without a receiver answers the sender of the message it replies to.
10
+
5
11
  ## 0.40.9
6
12
 
7
13
  - Same code as 0.40.8, released again so every package of this set is published.
package/README.md CHANGED
@@ -74,8 +74,7 @@ const message = await messages.get('<messageId>');
74
74
  const reach = await new ContextDiscoveryClient(operatorKey, agentId).discover();
75
75
  ```
76
76
 
77
- Task, agreement, artifact and permission operations use their own clients; no room
78
- is required. Selected execution headers remain in force on context reads, and a
77
+ Task, agreement, artifact and permission operations use their own clients. Selected execution headers remain in force on context reads, and a
79
78
  refusal does not retry through another scope. See `src/http/index.ts` for exports.
80
79
 
81
80
  ### Persona wire shapes
@@ -84,7 +83,7 @@ Cross-org inbox and chat payloads mask counterparties behind presentation faces:
84
83
 
85
84
  - Inbox connection requests expose `requesterRef` (`psn_*`) plus display name/org, not `requesterAgentId`.
86
85
  - Message/roster rows may carry `presentation` (`ref`, `persona`, `mode`, and `subject` only when entitled). Masked senders omit `underAgreementId` / `presentedAs`.
87
- - Opaque `psn_*` / `rpb_*` refs are **not** account ids. Do not use them for agent lookup, wake, or payment parties. Chat sends may name a masked party by its `rpb_*` as `receiverId`: the backend resolves it in-room. Leave the receiver out to write back in the room.
86
+ - Opaque `psn_*` refs are **not** account ids. Do not use them for agent lookup, wake, or payment parties. Leave the receiver out of a reply to answer the sender of the message it replies to.
88
87
 
89
88
  Helpers: `isPersonaRef`, `isRoomPresentationRef`, `isOpaquePresentationRef`.
90
89
 
@@ -55,7 +55,7 @@ export const AGREEMENT_TERMS_PARAMS = {
55
55
  description: 'ISO timestamp after which this can no longer be acted on.',
56
56
  },
57
57
  interactionMode: { type: 'string', enum: ['messages', 'tasks', 'both'], description: 'Accepted interface. Task-only services need no chat or negotiation.' },
58
- conversationAllowance: { type: 'number', description: 'Incoming messages allowed across covered rooms, shared with any helper hired under this job. Omit for unlimited; on a counter, omit to keep the current limit.' },
58
+ conversationAllowance: { type: 'number', description: 'Incoming messages allowed across covered conversations, shared with any helper hired under this job. Omit for unlimited; on a counter, omit to keep the current limit.' },
59
59
  maxExecutions: {
60
60
  type: 'number',
61
61
  description: 'End the engagement after this many tasks.',
@@ -130,28 +130,6 @@ const COUNTERPARTY_PARAM = {
130
130
  required: true,
131
131
  description: 'Agent or user id of the counterparty.',
132
132
  };
133
- /**
134
- * Optional, because the server has always accepted a proposal without one and
135
- * the client was the only thing refusing.
136
- *
137
- * The room is where a conversation about the terms happens; it is not how the
138
- * counterparty is TOLD. A directed proposal is delivered to the party slots
139
- * (the create-time agreement event targets parties, not a chat), so a chatless
140
- * proposal lands in their inbox exactly like any other. What is lost is
141
- * narrower than it sounds: the notice posted INTO a room, which is worth
142
- * nothing when there is no room.
143
- *
144
- * Requiring it here meant a bookkeeping agreement between parties who have no
145
- * conversation had to invent a chat id to exist. The lab's own self-hire did:
146
- * it passed `lab-hire-<run>`, a chat that does not exist, which the server
147
- * tolerates by falling back to the credential's tenant. A fiction the caller
148
- * was forced to write down is worse than an absent field.
149
- */
150
- const CHAT_PARAM = {
151
- type: 'string',
152
- required: false,
153
- description: 'Optional context for resolving a masked party reference. The proposal reaches its parties directly and does not share or publish into a room.',
154
- };
155
133
  /** Marketplace follow-up: a published listing is claimed, never countered. */
156
134
  function publishedNext(env) {
157
135
  return [
@@ -169,7 +147,6 @@ export const agreementBuyCapability = {
169
147
  annotation: 'destructive',
170
148
  params: {
171
149
  counterparty: COUNTERPARTY_PARAM,
172
- addressId: CHAT_PARAM,
173
150
  ...AGREEMENT_TERMS_PARAMS,
174
151
  mandateAgreementId: MANDATE_PARAM,
175
152
  bucketId: BUCKET_PARAM,
@@ -183,7 +160,6 @@ export const agreementBuyCapability = {
183
160
  ...mandateFrom(args),
184
161
  ...bucketFrom(args),
185
162
  proposedTo: counterparty,
186
- addressId: args['addressId'],
187
163
  // They provide. The payer is derived server-side as the other side.
188
164
  providerId: counterparty,
189
165
  engagementKind: engagementKindFrom(args),
@@ -202,7 +178,6 @@ export const agreementBidCapability = {
202
178
  annotation: 'destructive',
203
179
  params: {
204
180
  counterparty: COUNTERPARTY_PARAM,
205
- addressId: CHAT_PARAM,
206
181
  ...AGREEMENT_TERMS_PARAMS,
207
182
  mandateAgreementId: MANDATE_PARAM,
208
183
  bucketId: BUCKET_PARAM,
@@ -216,7 +191,6 @@ export const agreementBidCapability = {
216
191
  ...mandateFrom(args),
217
192
  ...bucketFrom(args),
218
193
  proposedTo: args['counterparty'],
219
- addressId: args['addressId'],
220
194
  // You provide, so the counterparty pays.
221
195
  providerId: creds.agentId || undefined,
222
196
  engagementKind: engagementKindFrom(args),
@@ -243,7 +217,6 @@ export const agreementBrokerCapability = {
243
217
  required: true,
244
218
  description: 'Agent id of the party who does the work.',
245
219
  },
246
- addressId: CHAT_PARAM,
247
220
  ...AGREEMENT_TERMS_PARAMS,
248
221
  mandateAgreementId: MANDATE_PARAM,
249
222
  parentAgreementId: { type: 'string', description: 'The job this work is part of; ending it ends this work. Not a link, and no spending consent.' },
@@ -254,7 +227,6 @@ export const agreementBrokerCapability = {
254
227
  ...termsFrom(args),
255
228
  ...mandateFrom(args),
256
229
  proposedTo: args['counterparty'],
257
- addressId: args['addressId'],
258
230
  providerId: args['provider'],
259
231
  engagementKind: engagementKindFrom(args),
260
232
  }, fullCreds(env));
@@ -285,7 +257,6 @@ export const agreementRequestCapability = {
285
257
  ...termsFrom(args),
286
258
  ...mandateFrom(args),
287
259
  ...bucketFrom(args),
288
- addressId: '',
289
260
  audience: args['audience'],
290
261
  engagementKind: engagementKindFrom(args),
291
262
  match: typeof args['match'] === 'string' ? args['match'] : undefined,
@@ -341,8 +312,8 @@ export const agreementHandoffCapability = {
341
312
  };
342
313
  const to = args['to'];
343
314
  const agreement = to
344
- ? await proposeDirectTo({ ...terms, proposedTo: to, addressId: '', useParentProvider: true, engagementKind: 'hire' }, creds)
345
- : await proposeBroadcast({ ...terms, addressId: '', audience: 'everyone', useParentProvider: true, engagementKind: 'hire' }, creds);
315
+ ? await proposeDirectTo({ ...terms, proposedTo: to, useParentProvider: true, engagementKind: 'hire' }, creds)
316
+ : await proposeBroadcast({ ...terms, audience: 'everyone', useParentProvider: true, engagementKind: 'hire' }, creds);
346
317
  return { agreement, ...(to ? {} : { readPlan: publishedNext(env) }) };
347
318
  },
348
319
  sdkOptions: { isAgreementCreation: true },
@@ -371,7 +342,7 @@ export const agreementSubcontractCapability = {
371
342
  names: { sdk: 'agreement_subcontract', mcp: 'ziggs_agreement_subcontract' },
372
343
  title: 'Subcontract part of your work',
373
344
  descriptions: {
374
- sdk: 'Delegate a slice of an active parent agreement to another agent. Name the parent, the worker, and the slice. The worker must approve — never impersonated. The selected agreement owns the work and its notifications; no room is required.',
345
+ sdk: 'Delegate a slice of an active parent agreement to another agent. Name the parent, the worker, and the slice. The worker must approve — never impersonated. The selected agreement owns the work and its notifications.',
375
346
  },
376
347
  annotation: 'destructive',
377
348
  params: {
@@ -38,7 +38,7 @@ export interface UnsearchedContext {
38
38
  * the question an agent actually has when it has been handed work that refers
39
39
  * to something it did not produce. The server bounds this by the agent's own
40
40
  * reach — authorship, readable containers, artifact grants it holds — under the
41
- * active lane and shared-room containment, so there is no `reach` arm to ask
41
+ * active lane and its work containment, so there is no `reach` arm to ask
42
42
  * for and the narrowing filters are refused rather than ignored.
43
43
  *
44
44
  * The response is deliberately two things that never merge: `artifacts`, which
@@ -51,7 +51,7 @@ export declare const findArtifactsCapability: CapabilityDefinition;
51
51
  *
52
52
  * The other half of "record now, decide where later". Attaching confers nothing
53
53
  * by itself: it puts the artifact inside the container, and that container's
54
- * audience can read it from then on. Use this to publish to a room, bind a
54
+ * audience can read it from then on. Use this to bind a
55
55
  * deliverable to a task, or restore agreement scope after a free-standing
56
56
  * record. To give it to someone, add it to a bucket with them.
57
57
  */
@@ -169,7 +169,7 @@ export const recordArtifactCapability = {
169
169
  },
170
170
  name: {
171
171
  type: 'string',
172
- description: 'Short name shown in lists (room, agreement, artifacts page). Pass this for a text deliverable so the other party can tell what it is without opening it. A file defaults to filename when omitted.',
172
+ description: 'Short name shown in lists (bucket, agreement, artifacts page). Pass this for a text deliverable so the other party can tell what it is without opening it. A file defaults to filename when omitted.',
173
173
  },
174
174
  filename: {
175
175
  type: 'string',
@@ -322,7 +322,6 @@ const UNSEARCHED_NOTE = 'These were NOT searched. You hold no grant on them, so
322
322
  'root grant. A human issues the grant; this never widens the scope to the ' +
323
323
  'chat, agreement, or org around one artifact.';
324
324
  const OPEN_ID_FIELD = {
325
- address: 'addressId',
326
325
  agreement: 'agreementId',
327
326
  artifact: 'artifactId',
328
327
  task: 'taskId',
@@ -379,7 +378,7 @@ async function unsearchedContext(env) {
379
378
  * the question an agent actually has when it has been handed work that refers
380
379
  * to something it did not produce. The server bounds this by the agent's own
381
380
  * reach — authorship, readable containers, artifact grants it holds — under the
382
- * active lane and shared-room containment, so there is no `reach` arm to ask
381
+ * active lane and its work containment, so there is no `reach` arm to ask
383
382
  * for and the narrowing filters are refused rather than ignored.
384
383
  *
385
384
  * The response is deliberately two things that never merge: `artifacts`, which
@@ -391,7 +390,7 @@ export const findArtifactsCapability = {
391
390
  names: { sdk: 'artifact_find', mcp: 'ziggs_artifact_find' },
392
391
  title: 'Find artifacts you can read',
393
392
  descriptions: {
394
- sdk: 'Search business artifacts you can already reach (excluding tool-operation and thought traces) — what you authored, what your readable chats/agreements/tasks hold, and what artifact grants you hold — by words in the name, filename or body. Bounded by your active lane and the rooms this wake is shared into, the same fences a point read obeys; there is no cross-customer arm and narrowing filters are refused, not ignored. Every answer carries coverage (fields searched, reach arms and their sizes, any that hit a cap), so an empty result means no match in what was searched, never that the thing does not exist. When nothing matched you also get notSearched: labels of context you hold no grant on, each with an access explanation — a human issues a root grant; this never widens. Metadata only, never contents.',
393
+ sdk: 'Search business artifacts you can already reach (excluding tool-operation and thought traces) — what you authored, what your readable chats/agreements/tasks hold, and what artifact grants you hold — by words in the name, filename or body. Bounded by your active lane and the work this wake is shared into, the same fences a point read obeys; there is no cross-customer arm and narrowing filters are refused, not ignored. Every answer carries coverage (fields searched, reach arms and their sizes, any that hit a cap), so an empty result means no match in what was searched, never that the thing does not exist. When nothing matched you also get notSearched: labels of context you hold no grant on, each with an access explanation — a human issues a root grant; this never widens. Metadata only, never contents.',
395
394
  },
396
395
  annotation: 'read-only',
397
396
  params: {
@@ -441,7 +440,7 @@ export const findArtifactsCapability = {
441
440
  *
442
441
  * The other half of "record now, decide where later". Attaching confers nothing
443
442
  * by itself: it puts the artifact inside the container, and that container's
444
- * audience can read it from then on. Use this to publish to a room, bind a
443
+ * audience can read it from then on. Use this to bind a
445
444
  * deliverable to a task, or restore agreement scope after a free-standing
446
445
  * record. To give it to someone, add it to a bucket with them.
447
446
  */
@@ -310,7 +310,7 @@ function presentOpenResult(result, env) {
310
310
  : resumeActions,
311
311
  ...(actingAgentId !== undefined ? { actingAgentId } : {}),
312
312
  ...(!result.actions && result.ref.kind === 'artifact' && result.outcome !== 'ok' ? {
313
- requestAccessHint: `If a source you already read supplied this artifact reference and its human owner, ${requestTool} scopeKind=artifact can ask that owner for temporary read access without a prior grant. The request names the exact resource and human approver; it grants no room membership. Discover the request tool's schema before calling it. This response does not confirm existence or ownership. A request grants no access until the human owner approves.`,
313
+ requestAccessHint: `If a source you already read supplied this artifact reference and its human owner, ${requestTool} scopeKind=artifact can ask that owner for temporary read access without a prior grant. The request names the exact resource and human approver; it grants no membership. Discover the request tool's schema before calling it. This response does not confirm existence or ownership. A request grants no access until the human owner approves.`,
314
314
  } : {}),
315
315
  };
316
316
  }
@@ -8,7 +8,7 @@ export const agentSearchCapability = {
8
8
  names: { sdk: 'agent_search', mcp: 'ziggs_agent_search' },
9
9
  title: 'Search for agents',
10
10
  descriptions: {
11
- sdk: 'Search for agents by capability, name, or description. Returns ranked results with relevance scores. A keyword/natural-language query searches the published store, your org\'s own agents and your own agents, and it matches your teammates by name: a teammate comes back under `people` as a person to message (message_send with their userId in explicit audience and delivery), never as a list of their agents. Someone else\'s agent is reached through the person it answers for, inside your org and outside it: you message the person, which of their agents answers is theirs to decide, and their agents become known to you by turning up in rooms. A link works the same way: reach a linked person through the link itself (link_list gives their addressable peer id, then message_send). Passing an EXACT agent id resolves that one agent when you can reach it. Each row carries `doors` — its engagement doors: doors.listingAgreementId is a live listing to CLAIM (agreement_claim — the default, one hop from here) and doors.acceptsProposals says whether a direct proposal would even be accepted (most published agents are claim-only). Use returned agentId in grant/issue tools — do not guess ids. When the caller already hires an agent, that row says already hired and names the agreement id and workspace.',
11
+ sdk: 'Search for agents by capability, name, or description. Returns ranked results with relevance scores. A keyword/natural-language query searches the published store, your org\'s own agents and your own agents, and it matches your teammates by name: a teammate comes back under `people` as a person to message (message_send with their userId in explicit audience and delivery), never as a list of their agents. Someone else\'s agent is reached through the person it answers for, inside your org and outside it: you message the person, which of their agents answers is theirs to decide, and their agents become known to you by turning up in conversations. A link works the same way: reach a linked person through the link itself (link_list gives their addressable peer id, then message_send). Passing an EXACT agent id resolves that one agent when you can reach it. Each row carries `doors` — its engagement doors: doors.listingAgreementId is a live listing to CLAIM (agreement_claim — the default, one hop from here) and doors.acceptsProposals says whether a direct proposal would even be accepted (most published agents are claim-only). Use returned agentId in grant/issue tools — do not guess ids. When the caller already hires an agent, that row says already hired and names the agreement id and workspace.',
12
12
  },
13
13
  annotation: 'read-only',
14
14
  params: {
@@ -7,7 +7,7 @@ import { type CapabilityDefinition } from './types.js';
7
7
  * list is never presented as complete when the key can't read a rail.
8
8
  *
9
9
  * HOLD, not reach. `GET /grants` lists rows this holder is named on, and taking
10
- * part in a room or being party to a live agreement now IS such a row. Two kinds
10
+ * part in a bucket or being party to a live agreement now IS such a row. Two kinds
11
11
  * of access still leave none: authoring an artifact, and the org memberships
12
12
  * that make an ORG-held grant cover you (the row names the org, not you). So a
13
13
  * reader can still be entitled to something this list will never mention, and
@@ -30,7 +30,7 @@ function parseScopeKinds(raw) {
30
30
  * list is never presented as complete when the key can't read a rail.
31
31
  *
32
32
  * HOLD, not reach. `GET /grants` lists rows this holder is named on, and taking
33
- * part in a room or being party to a live agreement now IS such a row. Two kinds
33
+ * part in a bucket or being party to a live agreement now IS such a row. Two kinds
34
34
  * of access still leave none: authoring an artifact, and the org memberships
35
35
  * that make an ORG-held grant cover you (the row names the org, not you). So a
36
36
  * reader can still be entitled to something this list will never mention, and
@@ -60,7 +60,7 @@ export const mintIntroductionCapability = {
60
60
  needsAgentId: true,
61
61
  handler: async (args, env) => {
62
62
  // Half an `about` is not a smaller about: dropping it would mint a plain
63
- // link where a room or a workspace was asked for, and say nothing.
63
+ // link where a workspace was asked for, and say nothing.
64
64
  if (args['aboutKind'] && !args['aboutId']) {
65
65
  throw new Error(args['aboutKind'] === 'workspace'
66
66
  ? 'aboutId is required with aboutKind: for your current workspace, pass actingOrgId from ziggs_auth_status'
@@ -146,7 +146,7 @@ export const redeemIntroductionCapability = {
146
146
  // A staged redeem is not a live hire: do not advertise a ready chat_open
147
147
  // or a ready agreement_respond the agent can run. The human signs.
148
148
  readPlan: !staged
149
- ? [nextCall(env, 'bucket_create', undefined, 'Start a bucket with the returned references in audience, then send in it with bucket_send; opening or joining a room is unnecessary.')]
149
+ ? [nextCall(env, 'bucket_create', undefined, 'Start a bucket with the returned references in audience, then send in it with bucket_send.')]
150
150
  : [
151
151
  nextCall(env, 'agreement_respond', intro.agreementId ? { agreementId: intro.agreementId } : undefined, 'the link is pending — your human must approve it; do not sign on their behalf', { hold: 'human_approval' }),
152
152
  ],
@@ -56,7 +56,7 @@ export const listLinksCapability = {
56
56
  }, fullCreds(env));
57
57
  const active = links.filter((a) => a.status === 'active');
58
58
  // A link grants reach and nothing else, so the move after seeing one is
59
- // always the same: open a room with that peer, or share context explicitly.
59
+ // always the same: message that peer, or share context explicitly.
60
60
  //
61
61
  // The peer id comes from the server now. Two earlier attempts read it off
62
62
  // `parties` here and both were wrong: the peer's `actor` is courier info,
@@ -261,7 +261,7 @@ const BRIEFS = {
261
261
  changes: 'the token stops working',
262
262
  },
263
263
  ziggs_party_note: {
264
- does: 'Writes what your workspace knows about a person not on Ziggs yet (claimed: false in the snapshot). Shown to your workspace in every room they are in.',
264
+ does: 'Writes what your workspace knows about a person not on Ziggs yet (claimed: false in the snapshot). Shown to your workspace in every snapshot they appear in.',
265
265
  changes: 'replaces the notes; empty clears them',
266
266
  },
267
267
  // Connections and points
@@ -2,7 +2,7 @@ import { MessageRecordsClient } from '../http/MessageRecordsClient.js';
2
2
  import { fullCreds } from './types.js';
3
3
  const client = (env) => { const creds = fullCreds(env); return new MessageRecordsClient(creds.operatorKey, creds.agentId, env.baseUrl); };
4
4
  export const readMessageCapability = { key: 'message_read', names: { sdk: 'message_read', mcp: 'ziggs_message_read' }, title: 'Read exact message', descriptions: { sdk: 'Read one authorized message. Returns content, intent (fyi or request), independent readers/recipients and authorized relationships. Does not acknowledge delivery.' }, annotation: 'read-only', needsAgentId: true, params: { messageId: { type: 'string', required: true } }, handler: (args, env) => client(env).get(String(args.messageId)) };
5
- export const sendMessageCapability = { key: 'message_send', names: { sdk: 'message_send', mcp: 'ziggs_message_send' }, title: 'Send message', descriptions: { sdk: 'Send the canonical command: operationId; content:{text}; audience:{kind:"explicit",principalIds:[...]}; deliveries:{kind:"explicit",principalIds:[...]}; intent:"fyi" or "request". A request wakes the agents it is delivered to; an fyi is delivered and filed, never woken on. Nothing records whether a request was answered: a reply is a message with relationships.replyToMessageId. Optional mandate:{agreementId,taskId}, relationships:{replyToMessageId,taskIds,artifacts}, exact sources. A new conversation starts in a bucket: bucket_create with its people, then bucket_send; this tool answers a message or writes under work. Reuse operationId unchanged on retry. No room required. Refused with "Nothing authorizes giving … access to this message" means you have no contact basis for that reader (membership, a link, an agreement or a listing): ask its owner with access_request scopeKind=contact and scopeId=that reader, then send once they approve.' }, annotation: 'destructive', needsAgentId: true, params: { command: { type: 'object', required: true, description: 'MessageCommand with explicit independent audience, deliveries, intent and optional mandate.' } }, handler: (args, env) => client(env).send(args.command) };
5
+ export const sendMessageCapability = { key: 'message_send', names: { sdk: 'message_send', mcp: 'ziggs_message_send' }, title: 'Send message', descriptions: { sdk: 'Send the canonical command: operationId; content:{text}; audience:{kind:"explicit",principalIds:[...]}; deliveries:{kind:"explicit",principalIds:[...]}; intent:"fyi" or "request". A request wakes the agents it is delivered to; an fyi is delivered and filed, never woken on. Nothing records whether a request was answered: a reply is a message with relationships.replyToMessageId. Optional mandate:{agreementId,taskId}, relationships:{replyToMessageId,taskIds,artifacts}, exact sources. A new conversation starts in a bucket: bucket_create with its people, then bucket_send; this tool answers a message or writes under work. Reuse operationId unchanged on retry. Refused with "Nothing authorizes giving … access to this message" means you have no contact basis for that reader (membership, a link, an agreement or a listing): ask its owner with access_request scopeKind=contact and scopeId=that reader, then send once they approve.' }, annotation: 'destructive', needsAgentId: true, params: { command: { type: 'object', required: true, description: 'MessageCommand with explicit independent audience, deliveries, intent and optional mandate.' } }, handler: (args, env) => client(env).send(args.command) };
6
6
  export const readRepliesCapability = { key: 'message_replies', names: { sdk: 'message_replies', mcp: 'ziggs_message_replies' }, title: 'Read replies', descriptions: { sdk: 'Read currently authorized causal replies; links never grant access. Continue using nextCursor as before.' }, annotation: 'read-only', needsAgentId: true, params: { messageId: { type: 'string', required: true }, before: { type: 'string' }, limit: { type: 'number' } }, handler: (args, env) => client(env).replies(String(args.messageId), { before: args.before, limit: args.limit }) };
7
7
  export const queryMessagesCapability = { key: 'message_list', names: { sdk: 'message_list', mcp: 'ziggs_message_list' }, title: 'Query messages', descriptions: { sdk: 'Query authorized messages. Use conversationOf with an exact message id to browse messages connected by readable reply relationships; use nextCursor as before for earlier turns. Select conversationOf independently of agreementId, taskId or participantIds. History never selects authority.' }, annotation: 'read-only', needsAgentId: true, params: { conversationOf: { type: 'string', description: 'Authorized anchor message; follows readable causal links, never a reader roster. Each result still requires read access and any execution input authorization.' }, q: { type: 'string' }, senderId: { type: 'string' }, recipientIds: { type: 'array', items: { type: 'string' } }, agreementId: { type: 'string' }, taskId: { type: 'string' }, participantIds: { type: 'array', items: { type: 'string' } }, before: { type: 'string' }, limit: { type: 'number' } }, handler: (args, env) => client(env).list(args) };
8
8
  export const messageControlsCapability = { key: 'message_controls', names: { sdk: 'message_controls', mcp: 'ziggs_message_controls' }, title: 'Inspect message mandate', descriptions: { sdk: 'Discover recipients and current authority under an explicitly selected agreement/task without reading message history.' }, annotation: 'read-only', needsAgentId: true, params: { q: { type: 'string' }, senderId: { type: 'string' }, recipientIds: { type: 'array', items: { type: 'string' } }, agreementId: { type: 'string', required: true }, taskId: { type: 'string' } }, handler: (args, env) => client(env).controls(String(args.agreementId), args.taskId) };
@@ -2,7 +2,7 @@ import { type CapabilityDefinition } from './types.js';
2
2
  /**
3
3
  * What your workspace knows about a person who is not on Ziggs yet.
4
4
  *
5
- * The room snapshot names them in `users` with `claimed: false`, and carries
5
+ * The context snapshot names them in `users` with `claimed: false`, and carries
6
6
  * these notes for your workspace's readers, so the next session that wakes
7
7
  * knows who they are without asking again.
8
8
  */
@@ -3,7 +3,7 @@ import { fullCreds } from './types.js';
3
3
  /**
4
4
  * What your workspace knows about a person who is not on Ziggs yet.
5
5
  *
6
- * The room snapshot names them in `users` with `claimed: false`, and carries
6
+ * The context snapshot names them in `users` with `claimed: false`, and carries
7
7
  * these notes for your workspace's readers, so the next session that wakes
8
8
  * knows who they are without asking again.
9
9
  */
@@ -12,14 +12,14 @@ export const partyNoteCapability = {
12
12
  names: { sdk: 'party_note', mcp: 'ziggs_party_note' },
13
13
  title: 'Note who a person not on Ziggs yet is',
14
14
  descriptions: {
15
- sdk: 'Replace what your workspace knows about a person who is not on Ziggs yet: who they are, how you met, what they asked for (PUT /parties/{partyId}/notes). partyId is their userId in the room snapshot, on the entry with claimed: false. The notes show in the snapshot of every room they are in, to your workspace only. An empty string clears them; at most 2000 characters. Write what you learned, not what they said verbatim.',
15
+ sdk: 'Replace what your workspace knows about a person who is not on Ziggs yet: who they are, how you met, what they asked for (PUT /parties/{partyId}/notes). partyId is their userId in the context snapshot, on the entry with claimed: false. The notes show in every snapshot they appear in, to your workspace only. An empty string clears them; at most 2000 characters. Write what you learned, not what they said verbatim.',
16
16
  },
17
17
  annotation: 'write',
18
18
  params: {
19
19
  partyId: {
20
20
  type: 'string',
21
21
  required: true,
22
- description: 'The person: their userId in the room snapshot, where claimed is false.',
22
+ description: 'The person: their userId in the context snapshot, where claimed is false.',
23
23
  },
24
24
  notes: {
25
25
  type: 'string',
@@ -35,7 +35,7 @@ export const partyNoteCapability = {
35
35
  return {
36
36
  party: saved,
37
37
  message: saved.notes
38
- ? 'Saved. It shows in the snapshot of every room they are in, to your workspace only.'
38
+ ? 'Saved. It shows in every snapshot they appear in, to your workspace only.'
39
39
  : 'Cleared.',
40
40
  };
41
41
  },
@@ -19,7 +19,7 @@
19
19
  * A person's account id is `username:::email`. The server shows a reader
20
20
  * outside that person's org their `psn_` face instead, but an older
21
21
  * server, or a row written before that, still hands the raw id over, and the
22
- * model repeats whatever it is told into the room. So an id shaped like a
22
+ * model repeats whatever it is told into the conversation. So an id shaped like a
23
23
  * person's account is left out rather than said.
24
24
  */
25
25
  export declare function speakableActor(actorId: string | null | undefined): string | null;
@@ -19,7 +19,7 @@
19
19
  * A person's account id is `username:::email`. The server shows a reader
20
20
  * outside that person's org their `psn_` face instead, but an older
21
21
  * server, or a row written before that, still hands the raw id over, and the
22
- * model repeats whatever it is told into the room. So an id shaped like a
22
+ * model repeats whatever it is told into the conversation. So an id shaped like a
23
23
  * person's account is left out rather than said.
24
24
  */
25
25
  export function speakableActor(actorId) {
@@ -32,8 +32,6 @@ export interface EngagementGuide {
32
32
  kind: EngagementGuideKind;
33
33
  outcome: EngagementOutcome;
34
34
  summary: string;
35
- /** Room the brief arrived in — never a substitute for agreementId. */
36
- addressId?: string | null;
37
35
  agreementId?: string | null;
38
36
  taskId?: string | null;
39
37
  waitingOn?: WaitingOn | null;
@@ -105,12 +103,11 @@ export interface InboxEngagementInput {
105
103
  tasks?: EngagementTaskHint[];
106
104
  continuation?: Pick<SessionContinuation, 'canScheduleWake' | 'kind'>;
107
105
  }
108
- /** Same event twice, or a hire-room brief that already has an open task. */
106
+ /** Same event twice, or a hire brief that already has an open task. */
109
107
  export declare function isEchoOrDuplicate(inbox: Pick<InboxEnvelope, 'deliveries' | 'tasksAwaitingMe'>, agentId: string): boolean;
110
108
  /**
111
- * Assigned message under a live hire. Missing chat is not a skip — a fresh
112
- * hire without a room still runs after access to that agreement is proven.
113
- * An agrn- notification lane is not treated as a chat row.
109
+ * Assigned message under a live hire. It runs after access to that agreement
110
+ * is proven. An agrn- notification lane is not treated as a message row.
114
111
  */
115
112
  export declare function isHireWorkOrder(delivery: InboxDeliveryRef, agentId: string, tasksAwaitingMe?: readonly InboxTaskRef[]): boolean;
116
113
  export declare function waitingOnFromTask(task: EngagementTaskHint): WaitingOn | null;
@@ -138,7 +135,7 @@ export declare function marketplaceFormation(env: CapabilityEnv, input: {
138
135
  */
139
136
  export declare function contactPath(env: CapabilityEnv, input: ContactPathInput): EngagementGuide;
140
137
  export declare function hireWorkOrderGuide(env: CapabilityEnv, delivery: InboxDeliveryRef): EngagementGuide;
141
- export declare function strangerBriefGuide(env: CapabilityEnv, addressId: string | null): EngagementGuide;
138
+ export declare function strangerBriefGuide(env: CapabilityEnv): EngagementGuide;
142
139
  export declare function duplicateGuide(): EngagementGuide;
143
140
  /**
144
141
  * First engagement that matters on this envelope. Empty mail with no held
@@ -17,7 +17,7 @@ function openTasksForAgreement(tasks, agreementId) {
17
17
  function assignedToMe(delivery, agentId) {
18
18
  return Boolean(agentId) && delivery.assigneeId === agentId;
19
19
  }
20
- /** Same event twice, or a hire-room brief that already has an open task. */
20
+ /** Same event twice, or a hire brief that already has an open task. */
21
21
  export function isEchoOrDuplicate(inbox, agentId) {
22
22
  const mine = inbox.deliveries.filter((d) => assignedToMe(d, agentId));
23
23
  const eventIds = mine.map((d) => d.eventId).filter(Boolean);
@@ -38,9 +38,8 @@ export function isEchoOrDuplicate(inbox, agentId) {
38
38
  return false;
39
39
  }
40
40
  /**
41
- * Assigned message under a live hire. Missing chat is not a skip — a fresh
42
- * hire without a room still runs after access to that agreement is proven.
43
- * An agrn- notification lane is not treated as a chat row.
41
+ * Assigned message under a live hire. It runs after access to that agreement
42
+ * is proven. An agrn- notification lane is not treated as a message row.
44
43
  */
45
44
  export function isHireWorkOrder(delivery, agentId, tasksAwaitingMe) {
46
45
  if (!assignedToMe(delivery, agentId))
@@ -258,7 +257,6 @@ export function hireWorkOrderGuide(env, delivery) {
258
257
  return {
259
258
  kind: 'work_order',
260
259
  outcome: 'ok',
261
- addressId: delivery.addressId,
262
260
  agreementId,
263
261
  summary: 'A brief from the principal in this hire is a work order. Create a task on yourself under that agreement. Fill the description from the brief after you read it. When you need helpers, declare a graph — do not invent worker_next.',
264
262
  next: nextCall(env, 'task_create', {
@@ -267,11 +265,10 @@ export function hireWorkOrderGuide(env, delivery) {
267
265
  }, 'create the work order on yourself under this hire'),
268
266
  };
269
267
  }
270
- export function strangerBriefGuide(env, addressId) {
268
+ export function strangerBriefGuide(env) {
271
269
  return {
272
270
  kind: 'stranger_brief',
273
271
  outcome: 'pending',
274
- addressId,
275
272
  summary: "A stranger's brief is not a work order. They hire you through your store listing, or through an agreement you draft when you have none; do not create a task under a hire you do not have.",
276
273
  next: nextCall(env, 'agreement_request', undefined, 'draft the agreement this brief would ride', { definition: agreementRequestCapability }),
277
274
  };
@@ -311,7 +308,7 @@ export function inboxEngagement(input) {
311
308
  }
312
309
  const stranger = mine.find((d) => d.kind === 'message' && !d.agreementId);
313
310
  if (stranger) {
314
- return strangerBriefGuide(env, stranger.addressId);
311
+ return strangerBriefGuide(env);
315
312
  }
316
313
  const held = tasks.find((t) => t.heldByDeps);
317
314
  if (held) {
package/dist/handles.d.ts CHANGED
@@ -1,18 +1,24 @@
1
1
  /**
2
- * Short handles: the id of a task (T…), agreement (A…), chat (C…) or
3
- * artifact (F…). A kind letter, five to eight letters from 0-9 A-Z without
4
- * I, L, O and U, and a check letter. Read in any case; written upper case.
2
+ * Short handles: the id of a task (T…), agreement (A…) or artifact (F…).
3
+ * A kind letter, five to eight letters from 0-9 A-Z without I, L, O and U,
4
+ * and a check letter. Read in any case; written upper case.
5
5
  *
6
6
  * Mirrors the server's rule so a mistyped handle is refused here, before any
7
7
  * call. The server stays the judge of what the handle opens.
8
8
  */
9
9
  export declare const HANDLE_ALPHABET = "0123456789ABCDEFGHJKMNPQRSTVWXYZ";
10
- export type HandleKind = 'task' | 'agreement' | 'address' | 'artifact';
10
+ export type HandleKind = 'task' | 'agreement' | 'artifact';
11
11
  /** The handle's kind and its upper-case form, or null when it is not one. */
12
12
  export declare function parseHandle(raw: string): {
13
13
  kind: HandleKind;
14
14
  id: string;
15
15
  } | null;
16
+ /**
17
+ * A reference to a room: a chat handle (C…), the 24-letter room id, or an
18
+ * `address:` / `chat:` ref, alone or inside a Ziggs URL. Rooms are gone, so
19
+ * these are refused with a clear word instead of being sent to the server.
20
+ */
21
+ export declare function isRetiredRoomRef(raw: string): boolean;
16
22
  /** The shape of a handle, whether or not its check letter holds. */
17
23
  export declare function looksLikeHandle(raw: string): boolean;
18
24
  /**
package/dist/handles.js CHANGED
@@ -1,13 +1,13 @@
1
1
  /**
2
- * Short handles: the id of a task (T…), agreement (A…), chat (C…) or
3
- * artifact (F…). A kind letter, five to eight letters from 0-9 A-Z without
4
- * I, L, O and U, and a check letter. Read in any case; written upper case.
2
+ * Short handles: the id of a task (T…), agreement (A…) or artifact (F…).
3
+ * A kind letter, five to eight letters from 0-9 A-Z without I, L, O and U,
4
+ * and a check letter. Read in any case; written upper case.
5
5
  *
6
6
  * Mirrors the server's rule so a mistyped handle is refused here, before any
7
7
  * call. The server stays the judge of what the handle opens.
8
8
  */
9
9
  export const HANDLE_ALPHABET = '0123456789ABCDEFGHJKMNPQRSTVWXYZ';
10
- const LETTER_KIND = { T: 'task', A: 'agreement', C: 'address', F: 'artifact' };
10
+ const LETTER_KIND = { T: 'task', A: 'agreement', F: 'artifact' };
11
11
  const N = HANDLE_ALPHABET.length;
12
12
  function checkHolds(handle) {
13
13
  let factor = 1;
@@ -36,11 +36,21 @@ const OLD_SHAPES = [
36
36
  [/^task_[0-9a-f-]{36}$/, 'task'],
37
37
  [/^agr_[A-Za-z0-9_]+$/, 'agreement'],
38
38
  [/^(art_|org-state-)[A-Za-z0-9_-]+$/, 'artifact'],
39
- [/^[a-z]{24}$/, 'address'],
40
39
  ];
40
+ /**
41
+ * A reference to a room: a chat handle (C…), the 24-letter room id, or an
42
+ * `address:` / `chat:` ref, alone or inside a Ziggs URL. Rooms are gone, so
43
+ * these are refused with a clear word instead of being sent to the server.
44
+ */
45
+ export function isRetiredRoomRef(raw) {
46
+ const value = raw.trim();
47
+ if (/^(?:address|chat):/i.test(value))
48
+ return true;
49
+ return [value, ...value.split(/[/?#&=]/)].some((part) => /^[a-z]{24}$/.test(part) || (/^C[0-9A-Z]{6,9}$/i.test(part) && checkHolds(part.toUpperCase())));
50
+ }
41
51
  /** The shape of a handle, whether or not its check letter holds. */
42
52
  export function looksLikeHandle(raw) {
43
- return /^[TACF][0-9A-Z]{6,9}$/i.test(raw.trim());
53
+ return /^[TAF][0-9A-Z]{6,9}$/i.test(raw.trim());
44
54
  }
45
55
  function parseOne(token) {
46
56
  const trimmed = token.trim();
@@ -43,8 +43,6 @@ export interface ProposeTerms {
43
43
  /** 1:1 proposal to a specific user or agent (`proposedTo` = their id). */
44
44
  export interface ProposeDirectInput extends ProposeTerms {
45
45
  proposedTo: string;
46
- /** Optional display-reference context for resolving a masked party; does not publish or share. */
47
- addressId?: string;
48
46
  /**
49
47
  * The bucket the agreement goes into, one you are in. Left out: the bucket
50
48
  * your run works in, else a new one. The other side comes in when it starts.
@@ -155,7 +155,7 @@ export declare class ArtifactsClient {
155
155
  /**
156
156
  * `GET /artifacts/find` — lexical search over the artifacts this agent can
157
157
  * already reach: what it authored, what its readable containers hold, and
158
- * what artifact grants it holds. Bounded by the active lane and shared-room
158
+ * what artifact grants it holds. Bounded by the active lane and its work
159
159
  * containment, exactly as a point read is.
160
160
  *
161
161
  * This is not `list()` with a query string. `list()` answers "what is in this
@@ -80,7 +80,7 @@ export class ArtifactsClient {
80
80
  /**
81
81
  * `GET /artifacts/find` — lexical search over the artifacts this agent can
82
82
  * already reach: what it authored, what its readable containers hold, and
83
- * what artifact grants it holds. Bounded by the active lane and shared-room
83
+ * what artifact grants it holds. Bounded by the active lane and its work
84
84
  * containment, exactly as a point read is.
85
85
  *
86
86
  * This is not `list()` with a query string. `list()` answers "what is in this
@@ -1,4 +1,4 @@
1
- import { looksLikeHandle, parseRef } from '../handles.js';
1
+ import { isRetiredRoomRef, looksLikeHandle, parseRef } from '../handles.js';
2
2
  import { getBackendUrl } from '../utils/urlUtils.js';
3
3
  import { pollSurfaceError } from '../shared/rateLimit.js';
4
4
  import { buildOperatorHeaders } from './operatorHeaders.js';
@@ -63,7 +63,7 @@ export function normalizeContextOpenBody(args) {
63
63
  if (!raw)
64
64
  throw invalid(`${key} must be a non-empty resource reference`);
65
65
  const ref = parseRef(raw);
66
- if (ref?.kind === 'address' || /^(?:address|chat):/.test(raw))
66
+ if (isRetiredRoomRef(raw))
67
67
  throw invalid('Room references are retired; select an exact artifact, task or agreement');
68
68
  if (!ref && looksLikeHandle(raw))
69
69
  throw invalid(`${raw} is not a handle: its check letter does not match. Check it for a typo`);
@@ -1,9 +1,7 @@
1
1
  export declare const CONTEXT_READ_TYPES: readonly ["artifacts", "agreements", "tasks"];
2
2
  export type ContextReadType = (typeof CONTEXT_READ_TYPES)[number];
3
3
  /**
4
- * Retained resource entry points for context reads and snapshots.
5
- * The server still accepts legacy room entries until coordinated removal;
6
- * new callers use only the domain resources below.
4
+ * Resource entry points for context reads and snapshots.
7
5
  */
8
6
  export declare const VIA_KINDS: readonly ["agreement", "task", "artifact", "message"];
9
7
  export type ViaKind = (typeof VIA_KINDS)[number];
@@ -57,7 +55,7 @@ export interface ContextSnapshotParticipant {
57
55
  [key: string]: unknown;
58
56
  }
59
57
  export interface ContextSnapshotQuery {
60
- /** Exact message, task, agreement, or artifact entry; no implicit room. */
58
+ /** Exact message, task, agreement, or artifact entry. */
61
59
  via: string;
62
60
  agreementId?: string;
63
61
  artifactId?: string;
@@ -7,9 +7,7 @@ export const CONTEXT_READ_TYPES = [
7
7
  'tasks',
8
8
  ];
9
9
  /**
10
- * Retained resource entry points for context reads and snapshots.
11
- * The server still accepts legacy room entries until coordinated removal;
12
- * new callers use only the domain resources below.
10
+ * Resource entry points for context reads and snapshots.
13
11
  */
14
12
  export const VIA_KINDS = [
15
13
  'agreement',
@@ -12,8 +12,6 @@ import { type Agreement, type Creds, type EngagementKind } from '../types.js';
12
12
  */
13
13
  export interface UnifiedProposeInput extends ProposeTerms {
14
14
  proposedTo: string;
15
- /** Required on direct proposals; optional on broadcasts/links. */
16
- addressId?: string;
17
15
  engagementKind?: EngagementKind;
18
16
  }
19
17
  export type ProposeShape = 'direct' | 'request' | 'offer';
@@ -2,7 +2,7 @@ import { claimAgreement, proposeBroadcast, proposeDirectTo, } from './AgreementC
2
2
  import { publishOffer } from './MarketplaceClient.js';
3
3
  import { isBroadcastTarget, } from '../types.js';
4
4
  export async function proposeUnified(input, creds) {
5
- const { proposedTo, addressId, engagementKind, providerId, ...terms } = input;
5
+ const { proposedTo, engagementKind, providerId, ...terms } = input;
6
6
  if (!proposedTo)
7
7
  throw new Error('proposedTo is required (a user/agent id, or "everyone"/"org"/"company" to broadcast)');
8
8
  // The 'link' arm is gone. A link is not a proposal shape: it has no
@@ -34,24 +34,16 @@ export async function proposeUnified(input, creds) {
34
34
  // Buyer-broadcast: the claimer works, your side pays — an open request.
35
35
  const agreement = await proposeBroadcast({
36
36
  ...terms,
37
- addressId: addressId ?? '',
38
37
  engagementKind: engagementKind ?? 'service',
39
38
  audience,
40
39
  }, creds);
41
40
  return { agreement, shape: 'request' };
42
41
  }
43
- // No room is a shape, not an error. The server has always accepted a direct
44
- // proposal without one, and this throw was the only thing that made the answer
45
- // depend on which client you used: an agreement between parties who have no
46
- // conversation had to invent a chat id to be created. Delivery does not go
47
- // through the room — the create-time event targets the party slots — so the
48
- // counterparty is told either way.
42
+ // A direct proposal is delivered to the party slots, so the counterparty is
43
+ // told whether or not the parties have talked before.
49
44
  const agreement = await proposeDirectTo({
50
45
  ...terms,
51
46
  proposedTo,
52
- // Omitted rather than sent empty: an absent field says "no room", and an
53
- // empty string is one more fiction for the server to interpret.
54
- ...(addressId ? { addressId } : {}),
55
47
  providerId: providerId?.trim() || proposedTo,
56
48
  engagementKind: engagementKind ?? 'service',
57
49
  }, creds);
package/dist/index.d.ts CHANGED
@@ -13,7 +13,7 @@ export type { DelegateEnv, ResolvedDelegateCreds, } from './shared/delegateCreds
13
13
  export { RateLimitedError, isRateLimited, parseRetryAfterMs, pollSurfaceError, } from './shared/rateLimit.js';
14
14
  export { parseErrorMessage, parseErrorCode, throwApiError, } from './shared/apiError.js';
15
15
  export { ApiError } from './types.js';
16
- export type { Creds, Task, TaskState, PlanStep, PlanStepStatus, Agreement, AgreementParties, AgreementPartySide, EngagementKind, BroadcastAudience, EntryType, ContentType, InboxDeliveryKind, InboxDeliveryRef, InboxChatNews, InboxProposalRef, InboxTaskRef, InboxRequestRef, InboxPlanAckRef, InboxConnectionRequestRef, InboxHumanAttention, InboxEnvelope, InboxAckResult, InboxPeek, InboxReadOptions, } from './types.js';
16
+ export type { Creds, Task, TaskState, PlanStep, PlanStepStatus, Agreement, AgreementParties, AgreementPartySide, EngagementKind, BroadcastAudience, EntryType, ContentType, InboxDeliveryKind, InboxDeliveryRef, InboxProposalRef, InboxTaskRef, InboxRequestRef, InboxPlanAckRef, InboxConnectionRequestRef, InboxHumanAttention, InboxEnvelope, InboxAckResult, InboxPeek, InboxReadOptions, } from './types.js';
17
17
  export type { ProposeTerms, ProposeDirectInput, ProposeBroadcastInput, ProposeAgreementData, ClaimOptions, } from './http/AgreementClient.js';
18
18
  export { decisionWords, speakableActor } from './decisionWords.js';
19
19
  export type { DecisionOutcome, DecisionWords, DecisionWordsInput, } from './decisionWords.js';
@@ -11,7 +11,7 @@ const SCOPE_DENIED_HINT = 'For missing access to a returned artifact, chat, agre
11
11
  'a pending access approval agreement; it grants no access. After approval, ' +
12
12
  'ziggs_open the same resource using the same agent identity. For earlier chat ' +
13
13
  'messages request temporal=from-start; replying also requires permission=reply. ' +
14
- 'Do not issue yourself a grant. A new room does not show this room\'s history.';
14
+ 'Do not issue yourself a grant. A new bucket does not show another conversation\'s history.';
15
15
  // a human-authority denial is not "try again with more scope": no
16
16
  // retry by this caller can ever pass it, because the guard refuses on being an
17
17
  // agent at all, before it looks at what was asked. Without a next action the
package/dist/types.d.ts CHANGED
@@ -319,12 +319,6 @@ export interface InboxSourceRef {
319
319
  }
320
320
  /** One delivery in a mailbox, as the wire carries it. */
321
321
  export type { InboxDeliveryRef };
322
- /** Message/artifact deliveries folded by chat, so you can open chats directly. */
323
- export interface InboxChatNews {
324
- addressId: string;
325
- count: number;
326
- latestAt: string;
327
- }
328
322
  export interface InboxProposalRef {
329
323
  executionContext?: import('@ziggs-ai/contracts').WorkExecutionContext;
330
324
  executionBlocked?: import('@ziggs-ai/contracts').ExecutionBlock;
@@ -456,8 +450,6 @@ export interface InboxEnvelope extends InboxRequestChannel, Partial<InboxPlanAck
456
450
  /** The last row IN this window; everything after it is the backlog. */
457
451
  windowEndsAt: string;
458
452
  } | null;
459
- /** This agent's ASSIGNED chat mail, folded by chat. */
460
- chats: InboxChatNews[];
461
453
  /**
462
454
  * Opaque watermark bundle. Pass to `ack(upTo, { handledDeliveryIds })`
463
455
  * VERBATIM after acting — never construct or parse one; the per-mailbox
@@ -519,7 +511,7 @@ export interface InboxChangesResult {
519
511
  cursor: string;
520
512
  expiresAt: string;
521
513
  hasMore: boolean;
522
- deliveries: Array<Pick<InboxDeliveryRef, 'eventId' | 'kind' | 'resourceId' | 'addressId' | 'taskId' | 'agreementId' | 'assigneeId' | 'needsHuman' | 'ts'> & {
514
+ deliveries: Array<Pick<InboxDeliveryRef, 'eventId' | 'kind' | 'resourceId' | 'taskId' | 'agreementId' | 'assigneeId' | 'needsHuman' | 'ts'> & {
523
515
  orgId?: string | null;
524
516
  }>;
525
517
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ziggs-ai/api-client",
3
- "version": "0.40.9",
3
+ "version": "0.41.0",
4
4
  "description": "HTTP and WebSocket client for the Ziggs backend API",
5
5
  "homepage": "https://ziggsai.com/docs",
6
6
  "bugs": {