@ziggs-ai/api-client 0.40.5 → 0.40.7

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,15 @@
2
2
 
3
3
  ## Unreleased
4
4
 
5
+ ## 0.40.7
6
+
7
+ - `BucketsClient.create` and `addMembers` go under the selected run, so the server reads the people named (addresses, and a face id it refuses by naming the address) from the run's work.
8
+ - `bucket_send` keeps the work a send is under: `agreementId` and `taskId` name it, else it is the agreement the wake is under. A send from work under a hire no longer drops its mandate and is no longer refused for it.
9
+ - `EVERYDAY_SDK_ONLY`: `bucket_create` and `bucket_send` are everyday on the hosted brain, so `EVERYDAY_SDK_TOOLS` ends with them. The MCP door's native list is unchanged.
10
+ - An agreement is no longer a bucket item: `BUCKET_ITEM_KINDS` is `message`, `artifact`, `task`. A hire brings its other side into the bucket it names (now when it starts at once, else when it does; until then they are invited), and `bucketId` on the hire verbs says so. `BucketContents.agreements` is worked out from the work in the bucket and carries `missing`; `BucketContents.invites` lists hires waiting for a yes whose people come in there.
11
+
12
+ ## 0.40.6
13
+
5
14
  ## 0.40.5
6
15
 
7
16
  - An artifact reaches people only by being added to a bucket. The `artifact_share` tool, `shareArtifactCapability` and `ContextGrantsClient.shareArtifact` are removed, `context_delegate` no longer takes `scopeKind: 'artifact'`, and `link_list` no longer suggests sharing an artifact. The server refuses artifact grants issued or passed on directly.
@@ -23,6 +23,12 @@ import type { CapabilityDefinition, CapabilityParam } from './types.js';
23
23
  * Hosted-agent tools spread this instead of keeping a shorter copy.
24
24
  */
25
25
  export declare const AGREEMENT_TERMS_PARAMS: Record<string, CapabilityParam>;
26
+ /** The bucket a hire brings its other side into. Exported for the claim verb. */
27
+ export declare const BUCKET_PARAM: CapabilityParam;
28
+ /** The named bucket off a validated arg bag, as the wire field. */
29
+ export declare function bucketFrom(args: Record<string, unknown>): {
30
+ bucketId?: string;
31
+ };
26
32
  export declare const agreementBuyCapability: CapabilityDefinition;
27
33
  export declare const agreementBidCapability: CapabilityDefinition;
28
34
  export declare const agreementBrokerCapability: CapabilityDefinition;
@@ -92,6 +92,16 @@ const MANDATE_PARAM = {
92
92
  type: 'string',
93
93
  description: 'Parent job: an active agreement you participate in. Ending it ends this work. It grants neither hiring nor representation authority.',
94
94
  };
95
+ /** The bucket a hire brings its other side into. Exported for the claim verb. */
96
+ export const BUCKET_PARAM = {
97
+ type: 'string',
98
+ description: "Bucket they join once it starts. Default: your run's bucket, else a new one.",
99
+ };
100
+ /** The named bucket off a validated arg bag, as the wire field. */
101
+ export function bucketFrom(args) {
102
+ const id = args['bucketId'];
103
+ return typeof id === 'string' && id.trim() ? { bucketId: id.trim() } : {};
104
+ }
95
105
  /** Pull the declared mandate off a validated arg bag, as the wire field. */
96
106
  function mandateFrom(args) {
97
107
  const declared = args['parentAgreementId'] ?? args['mandateAgreementId'];
@@ -162,6 +172,7 @@ export const agreementBuyCapability = {
162
172
  addressId: CHAT_PARAM,
163
173
  ...AGREEMENT_TERMS_PARAMS,
164
174
  mandateAgreementId: MANDATE_PARAM,
175
+ bucketId: BUCKET_PARAM,
165
176
  parentAgreementId: { type: 'string', description: 'The job this work is part of; ending it ends this work. Not a link, and no spending consent.' },
166
177
  },
167
178
  needsAgentId: true,
@@ -170,6 +181,7 @@ export const agreementBuyCapability = {
170
181
  const agreement = await proposeDirectTo({
171
182
  ...termsFrom(args),
172
183
  ...mandateFrom(args),
184
+ ...bucketFrom(args),
173
185
  proposedTo: counterparty,
174
186
  addressId: args['addressId'],
175
187
  // They provide. The payer is derived server-side as the other side.
@@ -193,6 +205,7 @@ export const agreementBidCapability = {
193
205
  addressId: CHAT_PARAM,
194
206
  ...AGREEMENT_TERMS_PARAMS,
195
207
  mandateAgreementId: MANDATE_PARAM,
208
+ bucketId: BUCKET_PARAM,
196
209
  parentAgreementId: { type: 'string', description: 'The job this work is part of; ending it ends this work. Not a link, and no spending consent.' },
197
210
  },
198
211
  needsAgentId: true,
@@ -201,6 +214,7 @@ export const agreementBidCapability = {
201
214
  const agreement = await proposeDirectTo({
202
215
  ...termsFrom(args),
203
216
  ...mandateFrom(args),
217
+ ...bucketFrom(args),
204
218
  proposedTo: args['counterparty'],
205
219
  addressId: args['addressId'],
206
220
  // You provide, so the counterparty pays.
@@ -262,6 +276,7 @@ export const agreementRequestCapability = {
262
276
  ...AGREEMENT_TERMS_PARAMS,
263
277
  match: MATCH_PARAM,
264
278
  mandateAgreementId: MANDATE_PARAM,
279
+ bucketId: BUCKET_PARAM,
265
280
  parentAgreementId: { type: 'string', description: 'The job this work is part of; ending it ends this work. Not a link, and no spending consent.' },
266
281
  },
267
282
  needsAgentId: true,
@@ -269,6 +284,7 @@ export const agreementRequestCapability = {
269
284
  const agreement = await proposeBroadcast({
270
285
  ...termsFrom(args),
271
286
  ...mandateFrom(args),
287
+ ...bucketFrom(args),
272
288
  addressId: '',
273
289
  audience: args['audience'],
274
290
  engagementKind: engagementKindFrom(args),
@@ -392,6 +408,7 @@ export const agreementSubcontractCapability = {
392
408
  type: 'string',
393
409
  description: 'Who pays for the subcontracted work. Defaults to the delegating side.',
394
410
  },
411
+ bucketId: BUCKET_PARAM,
395
412
  },
396
413
  needsAgentId: true,
397
414
  handler: async (args, env) => {
@@ -417,6 +434,7 @@ export const agreementSubcontractCapability = {
417
434
  ...(args['payerId'] === undefined
418
435
  ? {}
419
436
  : { payerId: args['payerId'] }),
437
+ ...bucketFrom(args),
420
438
  }, fullCreds(env));
421
439
  return { agreement };
422
440
  },
@@ -1,6 +1,7 @@
1
1
  import { agreementAppUrl } from '../utils/appUrls.js';
2
2
  import { claimOpenAgreement } from '../http/agreementFlows.js';
3
3
  import { linkIsReachOnly, webAppOrigin } from './links.js';
4
+ import { BUCKET_PARAM, bucketFrom } from './agreementVerbs.js';
4
5
  import { workContextFromEnv } from './nextCall.js';
5
6
  import { fullCreds } from './types.js';
6
7
  /** Plain outcome once the hire is active. `kind` stays on the result, not in this sentence. */
@@ -86,11 +87,12 @@ export const agreementClaimCapability = {
86
87
  enum: ['me', 'workspace'],
87
88
  description: "Listing hire: me (default) keeps work private; workspace shares with that workspace. Ask your person if unclear.",
88
89
  },
90
+ bucketId: BUCKET_PARAM,
89
91
  },
90
92
  needsAgentId: true,
91
93
  handler: async (args, env) => {
92
94
  const declaredMandate = args['mandateAgreementId'];
93
- const { agreement, kind } = await claimOpenAgreement(args['agreementId'], fullCreds(env), { ...(typeof declaredMandate === 'string' && declaredMandate ? { mandateAgreementId: declaredMandate } : {}), ...(typeof args['parentAgreementId'] === 'string' ? { parentAgreementId: args['parentAgreementId'] } : {}), ...(claimConnections(args['connections']) ?? {}), ...(args['hireFor'] === 'workspace' ? { hireFor: 'workspace' } : {}) });
95
+ const { agreement, kind } = await claimOpenAgreement(args['agreementId'], fullCreds(env), { ...(typeof declaredMandate === 'string' && declaredMandate ? { mandateAgreementId: declaredMandate } : {}), ...(typeof args['parentAgreementId'] === 'string' ? { parentAgreementId: args['parentAgreementId'] } : {}), ...(claimConnections(args['connections']) ?? {}), ...(args['hireFor'] === 'workspace' ? { hireFor: 'workspace' } : {}), ...bucketFrom(args) });
94
96
  return presentClaimResult(agreement, kind, env);
95
97
  },
96
98
  };
@@ -266,10 +266,19 @@ export const bucketSendCapability = {
266
266
  params: {
267
267
  bucketId: BUCKET_ID,
268
268
  text: { type: 'string', required: true },
269
- recipients: { type: 'array', items: { type: 'string' } },
269
+ recipients: {
270
+ type: 'array',
271
+ items: { type: 'string' },
272
+ description: 'Who is told, among the bucket\'s people. Under work, name at least one person the work is with.',
273
+ },
270
274
  intent: { type: 'string', enum: ['fyi', 'request'] },
271
275
  replyTo: { type: 'string' },
272
276
  operationId: { type: 'string', description: 'Reuse on retry.' },
277
+ agreementId: {
278
+ type: 'string',
279
+ description: 'The work this is under. Defaults to the agreement your wake is under.',
280
+ },
281
+ taskId: { type: 'string', description: 'The task under agreementId this is about.' },
273
282
  },
274
283
  handler: (args, env) => run('bucket_send', () => {
275
284
  const text = args['text'];
@@ -288,9 +297,23 @@ export const bucketSendCapability = {
288
297
  deliveries: { kind: 'explicit', principalIds: principals(args['recipients'], 'recipients') ?? [] },
289
298
  intent,
290
299
  ...(typeof replyTo === 'string' ? { relationships: { replyToMessageId: replyTo.trim() } } : {}),
300
+ ...mandateOf(args, env),
291
301
  });
292
302
  }),
293
303
  };
304
+ /**
305
+ * The work a send is under. Work under a hire keeps its mandate: the server
306
+ * refuses a run's send that drops it. Named in the call, else the agreement
307
+ * the wake is under.
308
+ */
309
+ function mandateOf(args, env) {
310
+ const named = typeof args['agreementId'] === 'string' ? args['agreementId'].trim() : '';
311
+ const agreementId = named || env.serviceAgreementId;
312
+ if (!agreementId)
313
+ return {};
314
+ const taskId = typeof args['taskId'] === 'string' && args['taskId'].trim() ? args['taskId'].trim() : undefined;
315
+ return { mandate: { agreementId, ...(taskId ? { taskId } : {}) } };
316
+ }
294
317
  export const bucketRemoveMemberCapability = {
295
318
  key: 'bucket_remove_member',
296
319
  names: { sdk: 'bucket_remove_member', mcp: 'ziggs_bucket_remove_member' },
@@ -15,5 +15,12 @@
15
15
  export declare const EVERYDAY_MCP_TOOLS: readonly ["ziggs_inbox", "ziggs_inbox_peek", "ziggs_inbox_ack", "ziggs_open", "ziggs_context_read", "ziggs_message_send", "ziggs_task_set_result", "ziggs_agreement_revoke", "ziggs_context_revoke_grant"];
16
16
  /** Everyday MCP tools the hosted brain does not register. */
17
17
  export declare const EVERYDAY_NO_SDK_TWIN: readonly ["ziggs_inbox", "ziggs_inbox_peek", "ziggs_inbox_ack", "ziggs_context_revoke_grant"];
18
- /** SDK names of the everyday set. Same order as the MCP list, twins only. */
18
+ /**
19
+ * Everyday on the hosted brain only. A new conversation starts in a bucket
20
+ * made on purpose, so a hosted agent loads creating one and sending inside it
21
+ * with their schemas. The MCP door keeps its size: there they stay in the
22
+ * catalog.
23
+ */
24
+ export declare const EVERYDAY_SDK_ONLY: readonly ["bucket_create", "bucket_send"];
25
+ /** SDK names of the everyday set: the MCP list's twins in its order, then the hosted-only ones. */
19
26
  export declare const EVERYDAY_SDK_TOOLS: readonly string[];
@@ -38,7 +38,17 @@ export const EVERYDAY_NO_SDK_TWIN = [
38
38
  'ziggs_context_revoke_grant',
39
39
  ];
40
40
  const noSdkTwin = new Set(EVERYDAY_NO_SDK_TWIN);
41
- /** SDK names of the everyday set. Same order as the MCP list, twins only. */
42
- export const EVERYDAY_SDK_TOOLS = EVERYDAY_MCP_TOOLS
43
- .filter((name) => !noSdkTwin.has(name))
44
- .map((name) => name.slice('ziggs_'.length));
41
+ /**
42
+ * Everyday on the hosted brain only. A new conversation starts in a bucket
43
+ * made on purpose, so a hosted agent loads creating one and sending inside it
44
+ * with their schemas. The MCP door keeps its size: there they stay in the
45
+ * catalog.
46
+ */
47
+ export const EVERYDAY_SDK_ONLY = ['bucket_create', 'bucket_send'];
48
+ /** SDK names of the everyday set: the MCP list's twins in its order, then the hosted-only ones. */
49
+ export const EVERYDAY_SDK_TOOLS = [
50
+ ...EVERYDAY_MCP_TOOLS
51
+ .filter((name) => !noSdkTwin.has(name))
52
+ .map((name) => name.slice('ziggs_'.length)),
53
+ ...EVERYDAY_SDK_ONLY,
54
+ ];
@@ -18,7 +18,7 @@ export { CONTEXT_CAPABILITIES, contextReadCapability, openCapability, accessExpl
18
18
  export { CONNECTION_CAPABILITIES, connectionProxyCapability, requestConnectionCapability, } from './connections.js';
19
19
  export { DISCOVERY_CAPABILITIES, agentSearchCapability, agentGetCapability, } from './discovery.js';
20
20
  export { ARTIFACT_CAPABILITIES, recordArtifactCapability, listArtifactsCapability, findArtifactsCapability, type UnsearchedContext, attachArtifactCapability, reviewArtifactContributionCapability, contributeArtifactCapability, uploadArtifactUrlCapability, completeArtifactFileCapability, downloadArtifactCapability, reextractArtifactCapability, } from './artifacts.js';
21
- export { EVERYDAY_MCP_TOOLS, EVERYDAY_NO_SDK_TWIN, EVERYDAY_SDK_TOOLS, } from './everyday.js';
21
+ export { EVERYDAY_MCP_TOOLS, EVERYDAY_NO_SDK_TWIN, EVERYDAY_SDK_ONLY, EVERYDAY_SDK_TOOLS, } from './everyday.js';
22
22
  export { annotationForSdkTool } from './toolLane.js';
23
23
  export { presentResourceActions } from './resourceActions.js';
24
24
  export * from './messaging.js';
@@ -18,7 +18,7 @@ export { CONTEXT_CAPABILITIES, contextReadCapability, openCapability, accessExpl
18
18
  export { CONNECTION_CAPABILITIES, connectionProxyCapability, requestConnectionCapability, } from './connections.js';
19
19
  export { DISCOVERY_CAPABILITIES, agentSearchCapability, agentGetCapability, } from './discovery.js';
20
20
  export { ARTIFACT_CAPABILITIES, recordArtifactCapability, listArtifactsCapability, findArtifactsCapability, attachArtifactCapability, reviewArtifactContributionCapability, contributeArtifactCapability, uploadArtifactUrlCapability, completeArtifactFileCapability, downloadArtifactCapability, reextractArtifactCapability, } from './artifacts.js';
21
- export { EVERYDAY_MCP_TOOLS, EVERYDAY_NO_SDK_TWIN, EVERYDAY_SDK_TOOLS, } from './everyday.js';
21
+ export { EVERYDAY_MCP_TOOLS, EVERYDAY_NO_SDK_TWIN, EVERYDAY_SDK_ONLY, EVERYDAY_SDK_TOOLS, } from './everyday.js';
22
22
  export { annotationForSdkTool } from './toolLane.js';
23
23
  export { presentResourceActions } from './resourceActions.js';
24
24
  export * from './messaging.js';
@@ -45,6 +45,11 @@ export interface ProposeDirectInput extends ProposeTerms {
45
45
  proposedTo: string;
46
46
  /** Optional display-reference context for resolving a masked party; does not publish or share. */
47
47
  addressId?: string;
48
+ /**
49
+ * The bucket the agreement goes into, one you are in. Left out: the bucket
50
+ * your run works in, else a new one. The other side comes in when it starts.
51
+ */
52
+ bucketId?: string;
48
53
  }
49
54
  /**
50
55
  * Open buyer-broadcast. `audience` selects who may see/claim it:
@@ -134,6 +139,11 @@ export interface DelegateAgreementData {
134
139
  interactionMode?: 'messages' | 'tasks' | 'both';
135
140
  agreementDescription?: string;
136
141
  payerId?: string;
142
+ /**
143
+ * The bucket the sub-agreement goes into, one you are in. Left out: the
144
+ * bucket your run works in, else the parent's buckets, else a new one.
145
+ */
146
+ bucketId?: string;
137
147
  idempotencyKey?: string;
138
148
  }
139
149
  export declare function delegateAgreement(proposalData: DelegateAgreementData, creds: Creds): Promise<Agreement>;
@@ -328,6 +338,11 @@ export type ClaimedKind = 'link' | 'offer' | 'request' | 'hand-off';
328
338
  */
329
339
  export interface ClaimOptions {
330
340
  parentAgreementId?: string;
341
+ /**
342
+ * The bucket the hire goes into, one you are in. Left out: the bucket your
343
+ * run works in, else a new one. The other side comes in when it starts.
344
+ */
345
+ bucketId?: string;
331
346
  /**
332
347
  * The active agreement whose work this claim is part of. An agent acting
333
348
  * inside a job its human approved does not need a second consent for the
@@ -559,7 +559,7 @@ export async function claimAgreement(agreementId, creds, opts = {}) {
559
559
  const res = await fetch(`${getAgreementBaseUrl()}/${encodeURIComponent(agreementId)}/claim`, {
560
560
  method: 'POST',
561
561
  headers: buildHeaders(creds),
562
- body: JSON.stringify({ ...(opts.mandateAgreementId ? { mandateAgreementId: opts.mandateAgreementId } : {}), ...(opts.parentAgreementId ? { parentAgreementId: opts.parentAgreementId } : {}), ...(opts.connections && Object.keys(opts.connections).length ? { connections: opts.connections } : {}), ...(opts.hireFor === 'workspace' ? { hireFor: 'workspace' } : {}) }),
562
+ body: JSON.stringify({ ...(opts.mandateAgreementId ? { mandateAgreementId: opts.mandateAgreementId } : {}), ...(opts.parentAgreementId ? { parentAgreementId: opts.parentAgreementId } : {}), ...(opts.connections && Object.keys(opts.connections).length ? { connections: opts.connections } : {}), ...(opts.hireFor === 'workspace' ? { hireFor: 'workspace' } : {}), ...(opts.bucketId ? { bucketId: opts.bucketId } : {}) }),
563
563
  });
564
564
  if (!res.ok) {
565
565
  const body = await res.text().catch(() => '');
@@ -1,6 +1,10 @@
1
1
  import type { MessageCommand, MessageCommandResult } from '@ziggs-ai/contracts';
2
- /** What a bucket can hold. Each item is a pointer, never a copy. */
3
- export declare const BUCKET_ITEM_KINDS: readonly ["message", "artifact", "task", "agreement"];
2
+ /**
3
+ * What a bucket can hold: the work. Each item is a pointer, never a copy. An
4
+ * agreement is not an item: it decides who is in a bucket (a hire brings its
5
+ * other side in, or invites them until it starts), never what is in it.
6
+ */
7
+ export declare const BUCKET_ITEM_KINDS: readonly ["message", "artifact", "task"];
4
8
  export type BucketItemKind = (typeof BUCKET_ITEM_KINDS)[number];
5
9
  export interface BucketItemRef {
6
10
  kind: BucketItemKind;
@@ -109,10 +113,18 @@ export interface BucketContents {
109
113
  title: string;
110
114
  state: string;
111
115
  }>;
116
+ /** The agreements the work here is under, worked out from the work; `missing`: sides not in the bucket. */
112
117
  agreements: Array<{
113
118
  agreementId: string;
114
119
  title: string;
115
120
  status: string;
121
+ missing: string[];
122
+ }>;
123
+ /** Hires waiting for a yes whose people come in here when they start. */
124
+ invites: Array<{
125
+ agreementId: string;
126
+ title: string | null;
127
+ waitingFor: string[];
116
128
  }>;
117
129
  /** Items held that the reader cannot read here, as they ask now. */
118
130
  outOfReach: number;
@@ -1,8 +1,12 @@
1
1
  import { getBackendUrl } from '../utils/urlUtils.js';
2
2
  import { throwApiError } from '../shared/apiError.js';
3
3
  import { buildOperatorHeaders, withoutExecution } from './operatorHeaders.js';
4
- /** What a bucket can hold. Each item is a pointer, never a copy. */
5
- export const BUCKET_ITEM_KINDS = ['message', 'artifact', 'task', 'agreement'];
4
+ /**
5
+ * What a bucket can hold: the work. Each item is a pointer, never a copy. An
6
+ * agreement is not an item: it decides who is in a bucket (a hire brings its
7
+ * other side in, or invites them until it starts), never what is in it.
8
+ */
9
+ export const BUCKET_ITEM_KINDS = ['message', 'artifact', 'task'];
6
10
  /**
7
11
  * The bucket operations (`/buckets`). A bucket is pointers to items and to who
8
12
  * it is for; it stores no permission. Whether everyone can read each item is
@@ -28,7 +32,8 @@ export class BucketsClient {
28
32
  throw new Error('BucketsClient: operatorKey is required');
29
33
  }
30
34
  create(input) {
31
- return this.request('POST', '/buckets', input, 'bucket create');
35
+ // Under the selected run: the server reads the people named from its work.
36
+ return this.request('POST', '/buckets', input, 'bucket create', { inRun: true });
32
37
  }
33
38
  /** The buckets you are in; given an item, those holding it, in the order it went in. */
34
39
  listMine(item) {
@@ -80,7 +85,7 @@ export class BucketsClient {
80
85
  return this.request('POST', `${this.path(bucketId)}/split`, input, 'bucket split');
81
86
  }
82
87
  addMembers(bucketId, principalIds, opts = {}) {
83
- return this.request('POST', `${this.path(bucketId)}/members`, { principalIds, ...(opts.onMisfit ? { onMisfit: opts.onMisfit } : {}) }, 'bucket add members');
88
+ return this.request('POST', `${this.path(bucketId)}/members`, { principalIds, ...(opts.onMisfit ? { onMisfit: opts.onMisfit } : {}) }, 'bucket add members', { inRun: true });
84
89
  }
85
90
  removeMember(bucketId, principalId) {
86
91
  return this.request('DELETE', `${this.path(bucketId)}/members/${encodeURIComponent(principalId)}`, undefined, 'bucket remove member');
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ziggs-ai/api-client",
3
- "version": "0.40.5",
3
+ "version": "0.40.7",
4
4
  "description": "HTTP and WebSocket client for the Ziggs backend API",
5
5
  "homepage": "https://ziggsai.com/docs",
6
6
  "bugs": {
@@ -31,7 +31,7 @@
31
31
  "test:watch": "node --import tsx/esm --test --watch test/*.test.ts"
32
32
  },
33
33
  "dependencies": {
34
- "@ziggs-ai/contracts": "0.48.0",
34
+ "@ziggs-ai/contracts": "0.48.1",
35
35
  "socket.io-client": "^4.7.0"
36
36
  },
37
37
  "keywords": [