@ziggs-ai/api-client 0.10.3 → 0.10.4

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.
@@ -17,7 +17,7 @@ function reportingHint(env, contentType, taskId) {
17
17
  }
18
18
  return `Reporting finished work? Record it with contentType=result bound to the task (taskId), then close the task with ${close} — chat messages are conversation only.`;
19
19
  }
20
- /** ZIG-1320 — inline body cap + escape hatch, shared by SDK/MCP descriptions. */
20
+ /** Inline body cap + escape hatch, shared by SDK/MCP descriptions. */
21
21
  const ARTIFACT_RECORD_INLINE_CAP = 'Inline text max 50000 characters. Over that: use ziggs_artifact_upload_url ' +
22
22
  '(file rail), or record an index artifact plus part artifacts and list the ' +
23
23
  'part ids in the index. The server does not auto-split.';
@@ -5,10 +5,10 @@ import { type CapabilityDefinition } from './types.js';
5
5
  * cross-session. `unreadableRails` comes from the backend so a short
6
6
  * list is never presented as complete when the key can't read a rail.
7
7
  *
8
- * HOLD, not reach. `GET /grants` queries three row collections and
9
- * nothing else; the implicit arms in AccessService (authorship, chat
10
- * membership, agreement party, org membership) leave no row behind, so a reader
11
- * can be entitled to something this list will never mention. The description
8
+ * HOLD, not reach. `GET /grants` lists granted rows and nothing else; access
9
+ * that is implicit rather than granted (authorship, chat membership, agreement
10
+ * party, org membership) leaves no row behind, so a reader can be entitled to
11
+ * something this list will never mention. The description
12
12
  * says so, because the old "the single answer" wording was read as completeness
13
13
  * and an empty list as "no access".
14
14
  */
@@ -27,10 +27,10 @@ function parseScopeKinds(raw) {
27
27
  * cross-session. `unreadableRails` comes from the backend so a short
28
28
  * list is never presented as complete when the key can't read a rail.
29
29
  *
30
- * HOLD, not reach. `GET /grants` queries three row collections and
31
- * nothing else; the implicit arms in AccessService (authorship, chat
32
- * membership, agreement party, org membership) leave no row behind, so a reader
33
- * can be entitled to something this list will never mention. The description
30
+ * HOLD, not reach. `GET /grants` lists granted rows and nothing else; access
31
+ * that is implicit rather than granted (authorship, chat membership, agreement
32
+ * party, org membership) leaves no row behind, so a reader can be entitled to
33
+ * something this list will never mention. The description
34
34
  * says so, because the old "the single answer" wording was read as completeness
35
35
  * and an empty list as "no access".
36
36
  */
@@ -36,10 +36,9 @@ export function linkIsReachOnly(env) {
36
36
  }
37
37
  const LINK_STATUSES = ['active', 'open', 'cancelled', 'all'];
38
38
  /**
39
- * Seat ceiling for one invite. ⚠️ SYNC: backend
40
- * src/agreements/agreements.service.ts MAX_LINK_INVITE_CLAIMS — the backend
41
- * rejects anything past it; this is only so the tool description says the
42
- * limit instead of letting an agent discover it by getting a 400.
39
+ * Seat ceiling for one invite. ⚠️ Mirrors the server's own ceiling, which
40
+ * rejects anything past it; this copy exists only so the tool description states
41
+ * the limit instead of letting an agent discover it by getting a 400.
43
42
  */
44
43
  const MAX_LINK_INVITE_CLAIMS = 25;
45
44
  ///1022 — the link rail shrank to two tools. Links are agreements, so
@@ -9,6 +9,46 @@ function publishHint(env) {
9
9
  `proposedTo "everyone" or "org" with no providerId broadcasts a quest (claimer works, you pay); ` +
10
10
  `the same with providerId = your own id publishes a standing offer (you work, claimer pays).`);
11
11
  }
12
+ /** A broadcast sentinel in a party slot means "open", not a counterparty. */
13
+ const BROADCASTS = new Set(['everyone', 'org']);
14
+ const named = (id) => typeof id === 'string' && id && !BROADCASTS.has(id) ? id : undefined;
15
+ /**
16
+ * One listing, as a browser needs to read it.
17
+ *
18
+ * A whole agreement document is around 30 fields and ~2KB per row, so a default
19
+ * page of 20 is 40KB of context spent mostly on storage bookkeeping — internal
20
+ * versioning, content hashes, write provenance, approval and lane bookkeeping —
21
+ * none of which helps anyone decide whether to claim. This projection is what the
22
+ * decision actually needs: what the work is, who does it, what it costs, on what
23
+ * terms, and the id to claim it with.
24
+ *
25
+ * Deliberately no `raw` escape hatch. The full document is one `agreement_get`
26
+ * away for the row you chose, and an escape hatch here would just restore the
27
+ * cost for every row you did not.
28
+ */
29
+ function toListingRow(a, kind) {
30
+ const terms = a?.terms ?? {};
31
+ const parties = a?.parties ?? {};
32
+ const requiredConnections = terms.requiredConnections ?? [];
33
+ return {
34
+ agreementId: a?.agreementId,
35
+ kind,
36
+ description: terms.description ?? '',
37
+ price: a?.money?.price ?? 0,
38
+ engagementKind: a?.engagementKind,
39
+ lifecycle: terms.lifecycle,
40
+ ...(terms.expiresAt ? { expiresAt: terms.expiresAt } : {}),
41
+ ...(terms.maxExecutions != null ? { maxExecutions: terms.maxExecutions } : {}),
42
+ // Who does the work on an offer, who is paying on a quest. The other slot is
43
+ // the open one you would be filling by claiming, so it carries no name yet.
44
+ ...(named(parties.providerAgent) ? { providerAgent: parties.providerAgent } : {}),
45
+ ...(named(parties.provider) ? { provider: parties.provider } : {}),
46
+ ...(named(parties.payer) ? { payer: parties.payer } : {}),
47
+ // Access the job cannot be done without — worth knowing before claiming it.
48
+ ...(requiredConnections.length ? { requiredConnections } : {}),
49
+ createdAt: a?.createdAt,
50
+ };
51
+ }
12
52
  /**
13
53
  * the marketplace read on both surfaces. Publishing and claiming
14
54
  * ride the agreement grammar (propose-with-audience / agreement_claim); this
@@ -48,8 +88,12 @@ export const marketplaceViewCapability = {
48
88
  kind === 'quests' ? Promise.resolve([]) : pullOffers(options, creds),
49
89
  ]);
50
90
  return {
51
- ...(kind !== 'offers' ? { quests, questCount: quests.length } : {}),
52
- ...(kind !== 'quests' ? { offers, offerCount: offers.length } : {}),
91
+ ...(kind !== 'offers'
92
+ ? { quests: quests.map((q) => toListingRow(q, 'quest')), questCount: quests.length }
93
+ : {}),
94
+ ...(kind !== 'quests'
95
+ ? { offers: offers.map((o) => toListingRow(o, 'offer')), offerCount: offers.length }
96
+ : {}),
53
97
  // Claiming is the move after browsing, and the id is in the row the
54
98
  // caller just received. The prose hint stays for the publish side, which
55
99
  // is a choice rather than a call.
@@ -49,8 +49,9 @@ export type ProposeBroadcastInput = Omit<ProposeDirectInput, 'proposedTo'> & {
49
49
  * A trust link's agreement, as every caller sees it.
50
50
  *
51
51
  * A link is reach, not commerce: it carries no money, no escrow, no execution
52
- * state and no approvals ledger. Handing the raw document over anyway put Mongo
53
- * bookkeeping in front of an LLM, which is what forbade.
52
+ * state and no approvals ledger. Handing the raw document over anyway puts
53
+ * storage bookkeeping in front of an LLM, which is what this summary exists to
54
+ * prevent.
54
55
  *
55
56
  * Lives here rather than in `capabilities/links.ts` because this is where the
56
57
  * rule is applied; that module re-exports it so the public name is
@@ -208,7 +209,7 @@ export declare function fulfillAgreement(agreementId: string, creds: Creds): Pro
208
209
  ok: boolean;
209
210
  agreement: Agreement;
210
211
  }>;
211
- /** What an open-broadcast claim turned out to be. ⚠️ SYNC: backend AgreementOpenService. */
212
+ /** What an open-broadcast claim resolved to. ⚠️ Mirrors the server; it is authoritative. */
212
213
  export type ClaimedKind = 'link' | 'offer' | 'quest' | 'hand-off';
213
214
  /**
214
215
  * Claim an open agreement. Three shapes are claimable:
@@ -28,8 +28,9 @@ function assertCreds(creds, op) {
28
28
  * A trust link's agreement, as every caller sees it.
29
29
  *
30
30
  * A link is reach, not commerce: it carries no money, no escrow, no execution
31
- * state and no approvals ledger. Handing the raw document over anyway put Mongo
32
- * bookkeeping in front of an LLM, which is what forbade.
31
+ * state and no approvals ledger. Handing the raw document over anyway puts
32
+ * storage bookkeeping in front of an LLM, which is what this summary exists to
33
+ * prevent.
33
34
  *
34
35
  * Lives here rather than in `capabilities/links.ts` because this is where the
35
36
  * rule is applied; that module re-exports it so the public name is
@@ -188,7 +189,7 @@ export async function respondToAgreement(agreementId, action, creds, opts = {})
188
189
  else if (!partyId) {
189
190
  throw new Error(`No pending approval entry for this operator on agreement ${agreementId}`);
190
191
  }
191
- // ZIG-1087 / ZIG-1316 — if the slot is the principal's, the server accepts
192
+ // If the slot is the principal's, the server accepts
192
193
  // only under a live approval-authority grant (else 403). Do not pre-refuse
193
194
  // here; the PUT is the source of truth.
194
195
  return approveAgreementAsParty(agreementId, partyId, action === 'approve' ? 'approved' : 'rejected', creds);
@@ -1,10 +1,10 @@
1
1
  /**
2
2
  * Inline `POST /artifacts` body cap (matches backend
3
3
  * `ARTIFACT_PUBLIC_TEXT_MAX_CHARS`). Over this → file rail or multi-part; the
4
- * server does not auto-split (ZIG-1320).
4
+ * server does not auto-split.
5
5
  */
6
6
  export declare const ARTIFACT_INLINE_TEXT_MAX_CHARS = 50000;
7
- /** ZIG-1320 — named escape hatch for agents that hit the inline cap. */
7
+ /** Named escape hatch for agents that hit the inline cap. */
8
8
  export declare const ARTIFACT_INLINE_TEXT_OVER_LIMIT_HINT: string;
9
9
  export type ArtifactVisibility = 'chat' | 'agent-private';
10
10
  export interface ListArtifactsOptions {
@@ -112,7 +112,7 @@ export declare class ArtifactsClient {
112
112
  * @param agentId Required for fleet keys (sent as X-Agent-Id). Omit for agent-scoped keys.
113
113
  * @param laneId the wake's lane (chat id, or `agrn-<agreementId>`),
114
114
  * sent as X-Ziggs-Lane so `authoredBy=me` is fenced to this engagement
115
- * instead of returning every customer's deliverables in one call.
115
+ * rather than spanning every engagement the agent has authored in.
116
116
  */
117
117
  constructor(operatorKey: string, agentId?: string, laneId?: string);
118
118
  list(q: ListArtifactsQuery, opts?: ListArtifactsOptions): Promise<ListArtifactsResult>;
@@ -5,10 +5,10 @@ import { buildOperatorHeaders } from './operatorHeaders.js';
5
5
  /**
6
6
  * Inline `POST /artifacts` body cap (matches backend
7
7
  * `ARTIFACT_PUBLIC_TEXT_MAX_CHARS`). Over this → file rail or multi-part; the
8
- * server does not auto-split (ZIG-1320).
8
+ * server does not auto-split.
9
9
  */
10
10
  export const ARTIFACT_INLINE_TEXT_MAX_CHARS = 50_000;
11
- /** ZIG-1320 — named escape hatch for agents that hit the inline cap. */
11
+ /** Named escape hatch for agents that hit the inline cap. */
12
12
  export const ARTIFACT_INLINE_TEXT_OVER_LIMIT_HINT = `text exceeds ${ARTIFACT_INLINE_TEXT_MAX_CHARS} characters. ` +
13
13
  'For larger content use ziggs_artifact_upload_url (file rail), or split into ' +
14
14
  'an index artifact plus part artifacts and list the part ids in the index. ' +
@@ -55,7 +55,7 @@ export class ArtifactsClient {
55
55
  * @param agentId Required for fleet keys (sent as X-Agent-Id). Omit for agent-scoped keys.
56
56
  * @param laneId the wake's lane (chat id, or `agrn-<agreementId>`),
57
57
  * sent as X-Ziggs-Lane so `authoredBy=me` is fenced to this engagement
58
- * instead of returning every customer's deliverables in one call.
58
+ * rather than spanning every engagement the agent has authored in.
59
59
  */
60
60
  constructor(operatorKey, agentId, laneId) {
61
61
  if (!operatorKey)
@@ -134,7 +134,7 @@ export class ArtifactsClient {
134
134
  }
135
135
  this._assertScopeXor(input);
136
136
  const text = input.text.trim();
137
- // ZIG-1320: refuse before the wire so MCP/SDK get a named escape hatch
137
+ // Refuse before the wire so MCP/SDK get a named escape hatch
138
138
  // instead of a bare class-validator string.
139
139
  if (text.length > ARTIFACT_INLINE_TEXT_MAX_CHARS) {
140
140
  throw new Error(`ArtifactsClient.writeStrict: ${ARTIFACT_INLINE_TEXT_OVER_LIMIT_HINT}`);
@@ -309,10 +309,8 @@ export class ArtifactsClient {
309
309
  if (input.chatId && input.agreementId) {
310
310
  // the refusal names the recovery, because this is the one gate
311
311
  // for every caller — the exposed tool surfaces inherit it rather than each
312
- // wording their own, and a caller that used to have chatId silently
313
- // dropped here now learns what to do instead. Wording matters: a bare
314
- // "pick one" at the last step of a finished task is what the drop was
315
- // added to avoid (dogfood).
312
+ // wording their own. Wording matters: this fires at the last step of a
313
+ // finished task, where a bare "pick one" leaves the deliverable unfiled.
316
314
  throw new Error('pass at most one of chatId or agreementId — a deliverable under an ' +
317
315
  'agreement wants agreementId alone (its parties see it); use chatId ' +
318
316
  'only for a chat-scoped note. To put it in both places, record it ' +
@@ -70,9 +70,10 @@ export declare class ContextReadClient {
70
70
  /**
71
71
  * @param operatorKey Agent-scoped or fleet operator key.
72
72
  * @param agentId Required for fleet keys (sent as X-Agent-Id). Omit for agent-scoped keys.
73
- * @param laneId the wake's lane, sent as X-Ziggs-Lane. This is the
74
- * path the dogfood leak ran through: `via=artifact:<other customer's spec>`
75
- * was authorised purely because the same agent had authored it.
73
+ * @param laneId the wake's lane, sent as X-Ziggs-Lane. The server fences a
74
+ * read to the lane's parties; without it, reach falls back to a wider
75
+ * test and a read can be authorised on a weaker basis than the caller
76
+ * intended. Send it on every read made while acting on a wake.
76
77
  */
77
78
  constructor(operatorKey: string, agentId?: string, baseUrl?: string, laneId?: string);
78
79
  read<T = unknown>(type: ContextReadType, query: ContextReadQuery): Promise<ContextReadEnvelope<T>>;
@@ -60,9 +60,10 @@ export class ContextReadClient {
60
60
  /**
61
61
  * @param operatorKey Agent-scoped or fleet operator key.
62
62
  * @param agentId Required for fleet keys (sent as X-Agent-Id). Omit for agent-scoped keys.
63
- * @param laneId the wake's lane, sent as X-Ziggs-Lane. This is the
64
- * path the dogfood leak ran through: `via=artifact:<other customer's spec>`
65
- * was authorised purely because the same agent had authored it.
63
+ * @param laneId the wake's lane, sent as X-Ziggs-Lane. The server fences a
64
+ * read to the lane's parties; without it, reach falls back to a wider
65
+ * test and a read can be authorised on a weaker basis than the caller
66
+ * intended. Send it on every read made while acting on a wake.
66
67
  */
67
68
  constructor(operatorKey, agentId, baseUrl, laneId) {
68
69
  if (!operatorKey)
@@ -18,7 +18,7 @@ export declare class InboxClient {
18
18
  getInbox(opts?: InboxReadOptions): Promise<InboxEnvelope>;
19
19
  /**
20
20
  * Advance this agent's watermark — pass the envelope's `ackTo` plus every
21
- * `resourceId` handled in `(priorAck, upTo]` (ZIG-1305). Monotonic
21
+ * `resourceId` handled in `(priorAck, upTo]`. Monotonic
22
22
  * server-side: an older value is a no-op, so a replayed ack can never
23
23
  * redeliver handled work. An ack that would bury unlisted deliveries is
24
24
  * refused.
@@ -48,7 +48,7 @@ export class InboxClient {
48
48
  }
49
49
  /**
50
50
  * Advance this agent's watermark — pass the envelope's `ackTo` plus every
51
- * `resourceId` handled in `(priorAck, upTo]` (ZIG-1305). Monotonic
51
+ * `resourceId` handled in `(priorAck, upTo]`. Monotonic
52
52
  * server-side: an older value is a no-op, so a replayed ack can never
53
53
  * redeliver handled work. An ack that would bury unlisted deliveries is
54
54
  * refused.
@@ -1,6 +1,6 @@
1
1
  import { type Creds, type Task, type TaskState } from '../types.js';
2
2
  /**
3
- * ZIG-1321 — thin confirmation from task write verbs. Full object stays on
3
+ * Thin confirmation from task write verbs. Full object stays on
4
4
  * getTask / ziggs_task_get.
5
5
  */
6
6
  export interface TaskWriteConfirm {
@@ -25,6 +25,12 @@ export interface TaskWriteConfirm {
25
25
  export type PlanReviewTiming = 'with_proposal' | 'before_execution';
26
26
  export interface CreateTaskData {
27
27
  description: string;
28
+ /**
29
+ * Short label for list rows, around 60 characters, 80 max.
30
+ * Optional: a task without one lists under a trimmed description, which is a
31
+ * wall of prose at a glance. Set it whenever the task is one row among many.
32
+ */
33
+ title?: string;
28
34
  agreementId: string;
29
35
  parentTaskId?: string;
30
36
  plan?: unknown;
@@ -62,7 +68,7 @@ export interface PlanReplaceStep {
62
68
  /** Omit to use the array index. */
63
69
  order?: number;
64
70
  /**
65
- * ZIG-1313: step progress. Omit for `pending`. Send `completed` /
71
+ * Step progress. Omit for `pending`. Send `completed` /
66
72
  * `in_progress` when replacing the plan so a later task completion does not
67
73
  * rewrite finished steps as skipped.
68
74
  */
@@ -24,8 +24,8 @@ function extractTask(data) {
24
24
  if (d['task'] && typeof d['task'] === 'object' && d['task']['taskId']) {
25
25
  return d['task'];
26
26
  }
27
- // Top-level task document (GET / create). Do not treat ZIG-1321 thin write
28
- // confirms (`ok: true`, no description) as a Task.
27
+ // Top-level task document (GET / create). Do not treat thin write confirms
28
+ // (`ok: true`, no description) as a Task.
29
29
  if (typeof d['taskId'] === 'string' && d['ok'] !== true) {
30
30
  return d;
31
31
  }
package/dist/types.d.ts CHANGED
@@ -27,7 +27,8 @@ export interface Creds {
27
27
  *
28
28
  * The operator key says WHO is calling; this says ON WHOSE BEHALF, RIGHT NOW.
29
29
  * Without it an agent serving several customers carries its full authority
30
- * into every call, and one tool call reaches another customer's work.
30
+ * into every call, so a read spans every engagement it holds rather than
31
+ * staying inside the one being worked.
31
32
  *
32
33
  * Optional, and omitting it can only narrow what comes back (the backend
33
34
  * falls back to the agent's own org) — never widen it. Nothing here is
@@ -46,6 +47,13 @@ export interface PlanStep {
46
47
  export interface Task {
47
48
  taskId: string;
48
49
  description: string;
50
+ /**
51
+ * Short row label. The backend always resolves it — falling back
52
+ * to a trimmed description for tasks that never set one — so render it
53
+ * unconditionally instead of re-deriving the fallback. Optional here only
54
+ * because a server predating the field omits it.
55
+ */
56
+ title?: string;
49
57
  agentId?: string;
50
58
  executorId?: string;
51
59
  payerId?: string;
@@ -75,7 +83,7 @@ export interface Task {
75
83
  }
76
84
  export type AgreementStatus = 'pending' | 'active' | 'fulfilled' | 'cancelled' | 'rejected' | (string & {});
77
85
  export type ProposalStatus = 'pending' | 'approved' | 'rejected' | 'countered' | 'expired' | (string & {});
78
- /** ⚠️ SYNC: backend src/agreements/agreements.constants.ts AGREEMENT_ENGAGEMENT_KIND */
86
+ /** ⚠️ Mirrors the server's engagement-kind constant; the server is authoritative. */
79
87
  export declare const AGREEMENT_ENGAGEMENT_KIND: {
80
88
  readonly HIRE: "hire";
81
89
  readonly SERVICE: "service";
@@ -152,7 +160,7 @@ export interface Agreement {
152
160
  createdAt?: string;
153
161
  updatedAt?: string;
154
162
  }
155
- /** ⚠️ SYNC: Keep in sync with backend src/chat/chat.types.ts ENTRY_TYPE */
163
+ /** ⚠️ Mirrors the server's entry-type constant; the server is authoritative. */
156
164
  export declare const EntryTypes: {
157
165
  readonly MESSAGE: "message";
158
166
  readonly NOTIFICATION: "notification";
@@ -162,7 +170,7 @@ export declare const EntryTypes: {
162
170
  readonly TASK_HISTORY: "task_history";
163
171
  };
164
172
  export type EntryType = (typeof EntryTypes)[keyof typeof EntryTypes];
165
- /** ⚠️ SYNC: Keep in sync with backend src/chat/chat.types.ts CONTENT_TYPE */
173
+ /** ⚠️ Mirrors the server's content-type constant; the server is authoritative. */
166
174
  export declare const ContentTypes: {
167
175
  readonly TEXT: "text";
168
176
  readonly OPERATION: "operation";
@@ -176,11 +184,11 @@ export declare const ContentTypes: {
176
184
  readonly TASK_UPDATE: "task_update";
177
185
  };
178
186
  export type ContentType = (typeof ContentTypes)[keyof typeof ContentTypes];
179
- /** ⚠️ SYNC: Mirrors backend src/chat/chat.types.ts isValidContentType */
187
+ /** ⚠️ Mirrors the server's entry/content-type validation; the server is authoritative. */
180
188
  export declare function isValidContentType(contentType: string, entryType: string): boolean;
181
- /** ⚠️ SYNC: Keep in sync with backend agreements.constants.ts. Fully-public broadcast sentinel. */
189
+ /** ⚠️ Mirrors the server's sentinel. Fully-public broadcast target. */
182
190
  export declare const OPEN_AGREEMENT_TARGET: "everyone";
183
- /** ⚠️ SYNC: backend ORG_AGREEMENT_TARGET. Org-scoped broadcast: visible/claimable only by members of the agreement's orgId. */
191
+ /** ⚠️ Mirrors the server's sentinel. Org-scoped broadcast: visible/claimable only by members of the agreement's orgId. */
184
192
  export declare const ORG_AGREEMENT_TARGET: "org";
185
193
  /** Audience for a broadcast proposal: fully public ('everyone') or org-scoped ('org'). */
186
194
  export type BroadcastAudience = typeof OPEN_AGREEMENT_TARGET | typeof ORG_AGREEMENT_TARGET;
@@ -391,7 +399,7 @@ export interface InboxEnvelope {
391
399
  /** The chat-bearing deliveries above, folded by chat. */
392
400
  chats: InboxChatNews[];
393
401
  /**
394
- * Pass to `ack(upTo, { handledResourceIds })` after acting (ZIG-1305).
402
+ * Pass to `ack(upTo, { handledResourceIds })` after acting.
395
403
  * Null when there is nothing to ack. Ack after acting, not after reading:
396
404
  * a crash in between redelivers. Listing every handled resourceId is what
397
405
  * stops a partial triage from burying other chats.
package/dist/types.js CHANGED
@@ -27,14 +27,14 @@ export class RateLimitedError extends ApiError {
27
27
  this.retryAfterMs = retryAfterMs;
28
28
  }
29
29
  }
30
- /** ⚠️ SYNC: backend src/agreements/agreements.constants.ts AGREEMENT_ENGAGEMENT_KIND */
30
+ /** ⚠️ Mirrors the server's engagement-kind constant; the server is authoritative. */
31
31
  export const AGREEMENT_ENGAGEMENT_KIND = {
32
32
  HIRE: 'hire',
33
33
  SERVICE: 'service',
34
34
  /** a bilateral reach link between two agents (no money, no work). */
35
35
  LINK: 'link',
36
36
  };
37
- /** ⚠️ SYNC: Keep in sync with backend src/chat/chat.types.ts ENTRY_TYPE */
37
+ /** ⚠️ Mirrors the server's entry-type constant; the server is authoritative. */
38
38
  export const EntryTypes = {
39
39
  MESSAGE: 'message',
40
40
  NOTIFICATION: 'notification',
@@ -43,7 +43,7 @@ export const EntryTypes = {
43
43
  /** @deprecated legacy alias for AGREEMENT_HISTORY */
44
44
  TASK_HISTORY: 'task_history',
45
45
  };
46
- /** ⚠️ SYNC: Keep in sync with backend src/chat/chat.types.ts CONTENT_TYPE */
46
+ /** ⚠️ Mirrors the server's content-type constant; the server is authoritative. */
47
47
  export const ContentTypes = {
48
48
  TEXT: 'text',
49
49
  OPERATION: 'operation',
@@ -63,13 +63,13 @@ const VALID_CONTENT_TYPES = {
63
63
  [EntryTypes.AGREEMENT_HISTORY]: [ContentTypes.AGREEMENT_UPDATE, ContentTypes.TASK_UPDATE],
64
64
  [EntryTypes.TASK_HISTORY]: [ContentTypes.AGREEMENT_UPDATE, ContentTypes.TASK_UPDATE],
65
65
  };
66
- /** ⚠️ SYNC: Mirrors backend src/chat/chat.types.ts isValidContentType */
66
+ /** ⚠️ Mirrors the server's entry/content-type validation; the server is authoritative. */
67
67
  export function isValidContentType(contentType, entryType) {
68
68
  return VALID_CONTENT_TYPES[entryType]?.includes(contentType) ?? false;
69
69
  }
70
- /** ⚠️ SYNC: Keep in sync with backend agreements.constants.ts. Fully-public broadcast sentinel. */
70
+ /** ⚠️ Mirrors the server's sentinel. Fully-public broadcast target. */
71
71
  export const OPEN_AGREEMENT_TARGET = 'everyone';
72
- /** ⚠️ SYNC: backend ORG_AGREEMENT_TARGET. Org-scoped broadcast: visible/claimable only by members of the agreement's orgId. */
72
+ /** ⚠️ Mirrors the server's sentinel. Org-scoped broadcast: visible/claimable only by members of the agreement's orgId. */
73
73
  export const ORG_AGREEMENT_TARGET = 'org';
74
74
  /** Both broadcast sentinels — values that occupy a party slot but are NOT real principal ids. */
75
75
  export const BROADCAST_TARGETS = [OPEN_AGREEMENT_TARGET, ORG_AGREEMENT_TARGET];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ziggs-ai/api-client",
3
- "version": "0.10.3",
3
+ "version": "0.10.4",
4
4
  "description": "HTTP and WebSocket client for the Ziggs backend API",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",