@ziggs-ai/api-client 0.10.4 → 0.11.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.
Files changed (42) hide show
  1. package/dist/capabilities/agreementVerbs.d.ts +2 -2
  2. package/dist/capabilities/agreementVerbs.js +19 -19
  3. package/dist/capabilities/agreements.d.ts +1 -1
  4. package/dist/capabilities/agreements.js +5 -5
  5. package/dist/capabilities/artifacts.d.ts +4 -2
  6. package/dist/capabilities/artifacts.js +168 -33
  7. package/dist/capabilities/chat.d.ts +2 -3
  8. package/dist/capabilities/chat.js +5 -6
  9. package/dist/capabilities/connections.js +1 -1
  10. package/dist/capabilities/context.js +3 -0
  11. package/dist/capabilities/grants.d.ts +7 -6
  12. package/dist/capabilities/grants.js +9 -8
  13. package/dist/capabilities/index.d.ts +2 -2
  14. package/dist/capabilities/index.js +2 -2
  15. package/dist/capabilities/links.d.ts +1 -1
  16. package/dist/capabilities/links.js +5 -7
  17. package/dist/capabilities/marketplace.js +20 -14
  18. package/dist/capabilities/payments.d.ts +24 -8
  19. package/dist/capabilities/payments.js +28 -392
  20. package/dist/capabilities/proposeProviderId.d.ts +1 -1
  21. package/dist/capabilities/proposeProviderId.js +1 -1
  22. package/dist/http/AgreementClient.d.ts +24 -19
  23. package/dist/http/AgreementClient.js +22 -14
  24. package/dist/http/ChatClient.d.ts +1 -0
  25. package/dist/http/ChatClient.js +4 -1
  26. package/dist/http/ConnectionsClient.js +12 -1
  27. package/dist/http/ContextGrantsClient.d.ts +15 -1
  28. package/dist/http/ContextGrantsClient.js +2 -0
  29. package/dist/http/ContextReadClient.d.ts +14 -5
  30. package/dist/http/GrantsClient.d.ts +14 -0
  31. package/dist/http/GrantsClient.js +18 -2
  32. package/dist/http/MarketplaceClient.d.ts +6 -6
  33. package/dist/http/MarketplaceClient.js +11 -11
  34. package/dist/http/TaskClient.d.ts +5 -0
  35. package/dist/http/TaskClient.js +2 -0
  36. package/dist/http/agreementFlows.d.ts +4 -4
  37. package/dist/http/agreementFlows.js +9 -10
  38. package/dist/http/grants.d.ts +28 -0
  39. package/dist/http/index.d.ts +2 -2
  40. package/dist/index.d.ts +1 -1
  41. package/dist/types.d.ts +44 -15
  42. package/package.json +1 -1
@@ -1,7 +1,7 @@
1
1
  import { type Creds, type Agreement, type EngagementKind, type BroadcastAudience } from '../types.js';
2
2
  /**
3
3
  * Shared proposal terms. When `engagementKind` is omitted the server defaults to `service`.
4
- * For an open buyer-broadcast quest, set `proposedTo` to a broadcast sentinel —
4
+ * For an open buyer-broadcast request, set `proposedTo` to a broadcast sentinel —
5
5
  * `OPEN_AGREEMENT_TARGET` (`"everyone"`, fully public) or `ORG_AGREEMENT_TARGET`
6
6
  * (`"org"`, scoped to your org). Prefer `proposeBroadcast({ audience })` over
7
7
  * setting `proposedTo` by hand.
@@ -79,7 +79,7 @@ export declare function proposeAgreement(proposalData: ProposeDirectInput, creds
79
79
  /** Propose a contract to one party (user or agent). Server defaults `engagementKind` to `service`. */
80
80
  export declare function proposeDirectTo(input: ProposeDirectInput, creds: Creds): Promise<Agreement>;
81
81
  /**
82
- * Propose an open quest. `audience` ('everyone' default | 'org') picks the
82
+ * Propose an open request. `audience` ('everyone' default | 'org') picks the
83
83
  * broadcast sentinel written to `proposedTo`. Server defaults `engagementKind`
84
84
  * to `service`.
85
85
  */
@@ -146,7 +146,7 @@ export declare function resolveMyPendingApprovalPartyId(agreement: Agreement, op
146
146
  *
147
147
  * `partyId` MUST match the authenticated actor (`actor.id === partyId`): owner
148
148
  * principal when approving as human, delegate agent id when impersonating.
149
- * Canonical for hire, service, link, and quest proposals.
149
+ * Canonical for hire, service, link, and request proposals.
150
150
  */
151
151
  export declare function approveAgreementAsParty(agreementId: string, partyId: string, status: 'approved' | 'rejected', creds: Creds): Promise<Agreement>;
152
152
  export interface CounterAgreementData {
@@ -181,21 +181,26 @@ export interface GetMyAgreementsFilters {
181
181
  export declare function getMyAgreements(filters: GetMyAgreementsFilters | undefined, creds: Creds): Promise<Agreement[]>;
182
182
  /** One agreement, shaped: a link comes back as its summary. */
183
183
  export declare function getAgreement(agreementId: string, creds: Creds): Promise<Agreement | null>;
184
- export interface CreateAgreementBody {
185
- proposedToId?: string;
186
- providerId?: string;
187
- agentId?: string;
188
- price?: number;
189
- lifecycle?: string;
190
- expiresAt?: string;
191
- maxExecutions?: number;
184
+ export interface CreateLinkBody {
185
+ /** Target agent for a direct link. Omit for an open, claimable invite. */
186
+ targetAgentId?: string;
187
+ /** Message shown to whoever is asked to approve or claim it. */
192
188
  description?: string;
193
- engagementKind?: EngagementKind;
194
- /** Link invites only: how many people may claim this one link. Default 1. */
189
+ /** Open invites only: how many people may claim this one link. Default 1. */
195
190
  maxClaims?: number;
196
- metadata?: Record<string, unknown>;
191
+ /** Which of the caller's own agents stands on their side of the link. */
192
+ asAgentId?: string;
197
193
  }
198
- export declare function createAgreement(body: CreateAgreementBody, creds: Creds): Promise<{
194
+ /**
195
+ * Create a trust link — a direct proposal to one agent, or an open invite.
196
+ *
197
+ * This posts to `POST /agreements/links`. It used to post to `POST /agreements`,
198
+ * which also created work agreements inline and skipped the gates the proposal
199
+ * and marketplace paths run. Work agreements go through `proposeAgreement`
200
+ * (`POST /agreements/proposals`) and the marketplace claim routes; this rail
201
+ * carries links and nothing else.
202
+ */
203
+ export declare function createLink(body: CreateLinkBody, creds: Creds): Promise<{
199
204
  ok: boolean;
200
205
  agreement: Agreement;
201
206
  }>;
@@ -210,12 +215,12 @@ export declare function fulfillAgreement(agreementId: string, creds: Creds): Pro
210
215
  agreement: Agreement;
211
216
  }>;
212
217
  /** What an open-broadcast claim resolved to. ⚠️ Mirrors the server; it is authoritative. */
213
- export type ClaimedKind = 'link' | 'offer' | 'quest' | 'hand-off';
218
+ export type ClaimedKind = 'link' | 'offer' | 'request' | 'hand-off';
214
219
  /**
215
220
  * Claim an open agreement. Three shapes are claimable:
216
221
  * - open link invite (`engagementKind: link`, proposedTo everyone)
217
- * - open broadcast quest (proposedTo 'everyone', status open)
218
- * - org-scoped broadcast quest (proposedTo 'org') — the server rejects the
222
+ * - open broadcast request (proposedTo 'everyone', status open)
223
+ * - org-scoped broadcast request (proposedTo 'org') — the server rejects the
219
224
  * claim with 403 if the caller is not a member of the agreement's orgId
220
225
  *
221
226
  * POST /agreements/:id/claim — canonical; no partyId in body.
@@ -262,7 +267,7 @@ export declare class AgreementClient {
262
267
  list(filters?: ListAgreementsFilters): Promise<Agreement[]>;
263
268
  listMine(filters?: GetMyAgreementsFilters): Promise<Agreement[]>;
264
269
  get(id: string): Promise<Agreement | null>;
265
- create(data: CreateAgreementBody): Promise<{
270
+ createLink(data: CreateLinkBody): Promise<{
266
271
  ok: boolean;
267
272
  agreement: Agreement;
268
273
  }>;
@@ -103,7 +103,7 @@ export async function proposeDirectTo(input, creds) {
103
103
  return proposeAgreement(input, creds);
104
104
  }
105
105
  /**
106
- * Propose an open quest. `audience` ('everyone' default | 'org') picks the
106
+ * Propose an open request. `audience` ('everyone' default | 'org') picks the
107
107
  * broadcast sentinel written to `proposedTo`. Server defaults `engagementKind`
108
108
  * to `service`.
109
109
  */
@@ -172,7 +172,7 @@ export async function respondToAgreement(agreementId, action, creds, opts = {})
172
172
  const proposedTo = agreement.parties?.proposedTo;
173
173
  if (isBroadcastTarget(proposedTo) || isBroadcastTarget(agreement.parties?.payer)) {
174
174
  // respond is approve/reject on DIRECT proposals only. An open
175
- // broadcast (quest, standing offer, link invite) has no per-recipient
175
+ // broadcast (request, standing offer, link invite) has no per-recipient
176
176
  // approval slot — a BYSTANDER can neither approve nor reject it
177
177
  //; their move is to claim it, which has its own verb.
178
178
  //
@@ -232,7 +232,7 @@ export function resolveMyPendingApprovalPartyId(agreement, opts) {
232
232
  *
233
233
  * `partyId` MUST match the authenticated actor (`actor.id === partyId`): owner
234
234
  * principal when approving as human, delegate agent id when impersonating.
235
- * Canonical for hire, service, link, and quest proposals.
235
+ * Canonical for hire, service, link, and request proposals.
236
236
  */
237
237
  export async function approveAgreementAsParty(agreementId, partyId, status, creds) {
238
238
  if (!agreementId)
@@ -406,23 +406,31 @@ export async function getAgreement(agreementId, creds) {
406
406
  const agreement = await getAgreementDocument(agreementId, creds);
407
407
  return agreement ? shapeAgreement(agreement) : null;
408
408
  }
409
- export async function createAgreement(body, creds) {
409
+ /**
410
+ * Create a trust link — a direct proposal to one agent, or an open invite.
411
+ *
412
+ * This posts to `POST /agreements/links`. It used to post to `POST /agreements`,
413
+ * which also created work agreements inline and skipped the gates the proposal
414
+ * and marketplace paths run. Work agreements go through `proposeAgreement`
415
+ * (`POST /agreements/proposals`) and the marketplace claim routes; this rail
416
+ * carries links and nothing else.
417
+ */
418
+ export async function createLink(body, creds) {
410
419
  if (!body)
411
- throw new Error('Body is required for agreement creation');
412
- assertCreds(creds, 'agreement creation');
413
- // Canonical REST create: POST /agreements.
414
- const res = await fetch(getAgreementBaseUrl(), {
420
+ throw new Error('Body is required for link creation');
421
+ assertCreds(creds, 'link creation');
422
+ const res = await fetch(`${getAgreementBaseUrl()}/links`, {
415
423
  method: 'POST',
416
424
  headers: buildHeaders(creds),
417
425
  body: JSON.stringify(body),
418
426
  });
419
427
  if (!res.ok) {
420
428
  const responseBody = await res.text().catch(() => '');
421
- throwApiError(res, responseBody, `Agreement creation failed: ${res.status} ${res.statusText}`);
429
+ throwApiError(res, responseBody, `Link creation failed: ${res.status} ${res.statusText}`);
422
430
  }
423
431
  const data = await res.json().catch(() => null);
424
432
  if (!data?.['agreement']) {
425
- throw new Error('Invalid response: expected { ok, agreement } from POST /agreements');
433
+ throw new Error('Invalid response: expected { ok, agreement } from POST /agreements/links');
426
434
  }
427
435
  const envelope = data;
428
436
  return { ...envelope, agreement: shapeAgreement(envelope.agreement) };
@@ -472,8 +480,8 @@ export async function fulfillAgreement(agreementId, creds) {
472
480
  /**
473
481
  * Claim an open agreement. Three shapes are claimable:
474
482
  * - open link invite (`engagementKind: link`, proposedTo everyone)
475
- * - open broadcast quest (proposedTo 'everyone', status open)
476
- * - org-scoped broadcast quest (proposedTo 'org') — the server rejects the
483
+ * - open broadcast request (proposedTo 'everyone', status open)
484
+ * - org-scoped broadcast request (proposedTo 'org') — the server rejects the
477
485
  * claim with 403 if the caller is not a member of the agreement's orgId
478
486
  *
479
487
  * POST /agreements/:id/claim — canonical; no partyId in body.
@@ -493,7 +501,7 @@ export async function claimAgreement(agreementId, creds) {
493
501
  }
494
502
  // the route reports which kind of broadcast this turned out to be.
495
503
  // A caller cannot work it out from the row — post-claim no sentinel is left,
496
- // and a quest (you do the work) reads the same shape as a standing offer (you
504
+ // and a request (you do the work) reads the same shape as a standing offer (you
497
505
  // pay for it) unless you know which slot you landed in.
498
506
  const envelope = data;
499
507
  return { ...envelope, agreement: shapeAgreement(envelope.agreement) };
@@ -683,7 +691,7 @@ export class AgreementClient {
683
691
  list(filters) { return listAgreements(filters, this.creds); }
684
692
  listMine(filters) { return getMyAgreements(filters, this.creds); }
685
693
  get(id) { return getAgreement(id, this.creds); }
686
- create(data) { return createAgreement(data, this.creds); }
694
+ createLink(data) { return createLink(data, this.creds); }
687
695
  revoke(id) { return revokeAgreement(id, this.creds); }
688
696
  fulfill(id) { return fulfillAgreement(id, this.creds); }
689
697
  claimAgreement(id) { return claimAgreement(id, this.creds); }
@@ -21,6 +21,7 @@ export interface SendChatMessageInput {
21
21
  * Recipient id. Optional: when omitted, the backend infers the
22
22
  * receiver if the chat has exactly one other member (one agent, or one
23
23
  * other human). Provide it explicitly in chats with multiple members.
24
+ * Sent on the wire as `{ id }`; the SDK still takes a string.
24
25
  */
25
26
  receiverId?: string;
26
27
  text: string;
@@ -93,7 +93,10 @@ export async function sendChatMessage(input, creds) {
93
93
  text: input.text,
94
94
  entryType,
95
95
  contentType,
96
- receiver: input.receiverId,
96
+ // Canonical wire shape is `{ id, type? }`; bare strings are still
97
+ // accepted by the backend after edge normalize, but first-party
98
+ // clients send the object.
99
+ receiver: input.receiverId ? { id: input.receiverId } : undefined,
97
100
  underAgreementId: input.underAgreementId,
98
101
  }),
99
102
  });
@@ -93,10 +93,21 @@ export class ConnectionsClient {
93
93
  async listForHolder() {
94
94
  const grantsClient = new GrantsClient(this.operatorKey, this.agentId, this.baseUrl);
95
95
  // All pages of the agent's live connection grants (not just the first page).
96
- const items = await grantsClient.listAllGrants({
96
+ const { items, unreadableRails } = await grantsClient.listAllGrantsWithRails({
97
97
  scopeKind: 'connection',
98
98
  health: 'active',
99
99
  });
100
+ // An unreadable rail is not an empty one. Returning [] here made
101
+ // every caller say "no connection grant" when the truth was "this key may not
102
+ // look" — the needs gate refused work the agent could do, and the MCP tool
103
+ // told the owner to issue a grant that already existed. Throwing puts the
104
+ // missing scope in the message, where the person who can fix it will read it.
105
+ const railBlocked = unreadableRails.find((r) => r.rail === 'connection');
106
+ if (railBlocked && items.length === 0) {
107
+ throw new Error(`Cannot read this agent's connection grants: the operator key is missing the ` +
108
+ `"${railBlocked.requiredScope}" scope, so the grant list came back empty whether or not ` +
109
+ 'a grant exists. Re-mint the key with that scope (the "launcher-mcp-broker" preset includes it).');
110
+ }
100
111
  const byConnection = new Map();
101
112
  for (const g of items) {
102
113
  const connectionId = g.scope.id;
@@ -1,4 +1,4 @@
1
- import type { GrantView } from './grants.js';
1
+ import type { GrantAccessKind, GrantHolderKind, GrantView } from './grants.js';
2
2
  /**
3
3
  * added `artifact` — the narrowest context scope: one specific artifact,
4
4
  * shared without sharing any chat or agreement it sits in. Still the context
@@ -21,12 +21,26 @@ export interface ContextGrantScope {
21
21
  export type ContextGrantRecord = GrantView;
22
22
  export interface IssueContextGrantInput {
23
23
  holderId: string;
24
+ /**
25
+ * What kind of principal the holder is: a person, an organization, or an
26
+ * agent. Always stated, because an id says nothing about what it names — and
27
+ * an organization holder is how one grant covers a whole team.
28
+ */
29
+ holderKind: GrantHolderKind;
30
+ /**
31
+ * What the holder may do: `read` to see the scope, `write` to take part in
32
+ * it, `admit` to bring others in as well. Defaults to `write`.
33
+ */
34
+ kind?: GrantAccessKind;
24
35
  scope: ContextGrantScope;
25
36
  temporal?: ContextTemporal;
26
37
  expiresAt?: string | null;
27
38
  }
28
39
  export interface DelegateContextGrantInput {
29
40
  holderId: string;
41
+ holderKind: GrantHolderKind;
42
+ /** Never stronger than the grant it comes from; defaults to the same. */
43
+ kind?: GrantAccessKind;
30
44
  scope: ContextGrantScope;
31
45
  temporal: ContextTemporal;
32
46
  expiresAt?: string | null;
@@ -28,6 +28,8 @@ export class ContextGrantsClient {
28
28
  }),
29
29
  body: JSON.stringify({
30
30
  holderId: input.holderId,
31
+ holderKind: input.holderKind,
32
+ kind: input.kind,
31
33
  scope: input.scope,
32
34
  temporal: input.temporal,
33
35
  expiresAt: input.expiresAt,
@@ -43,17 +43,26 @@ export interface ContextReadEnvelope<T = unknown> {
43
43
  latestSequence?: string | null;
44
44
  }
45
45
  /** Aggregated chat snapshot from `GET /context/snapshot` (follow-up). */
46
+ /**
47
+ * One participant on the snapshot roster. `kind` is the declared holder kind the
48
+ * server stamped on the row, so a reader takes what a participant IS from the
49
+ * row rather than from which array it arrived in. Optional so a backend that
50
+ * predates it still parses.
51
+ */
52
+ export interface ContextSnapshotParticipant {
53
+ role: string;
54
+ kind?: string;
55
+ isYou?: boolean;
56
+ [key: string]: unknown;
57
+ }
46
58
  export interface ContextSnapshotResult {
47
59
  history: unknown[];
48
60
  agreements: unknown[];
49
- agents: Array<{
61
+ agents: Array<ContextSnapshotParticipant & {
50
62
  agentId: string;
51
- role: string;
52
- isYou: boolean;
53
63
  }>;
54
- users: Array<{
64
+ users: Array<ContextSnapshotParticipant & {
55
65
  userId: string;
56
- role: string;
57
66
  }>;
58
67
  latestSequence?: string | null;
59
68
  chatMissing?: boolean;
@@ -66,4 +66,18 @@ export declare class GrantsClient {
66
66
  * truncated. `maxPages` bounds the loop as a runaway guard.
67
67
  */
68
68
  listAllGrants(query?: Omit<ListGrantsQuery, 'cursor'>, maxPages?: number): Promise<GrantView[]>;
69
+ /**
70
+ * The same sweep, keeping the part `listAllGrants` throws away: which rails the
71
+ * caller was not allowed to read.
72
+ *
73
+ * The distinction is not cosmetic. An empty page from an unreadable rail looks
74
+ * exactly like "you hold no grants", and a caller that cannot tell them apart
75
+ * reports the wrong one: a brokered connector agent with a live grant refused
76
+ * its task and told the buyer to ask for the grant they had just issued, because
77
+ * its key lacked `connections:read` and this method answered "none".
78
+ */
79
+ listAllGrantsWithRails(query?: Omit<ListGrantsQuery, 'cursor'>, maxPages?: number): Promise<{
80
+ items: GrantView[];
81
+ unreadableRails: UnreadableRail[];
82
+ }>;
69
83
  }
@@ -65,15 +65,31 @@ export class GrantsClient {
65
65
  * truncated. `maxPages` bounds the loop as a runaway guard.
66
66
  */
67
67
  async listAllGrants(query = {}, maxPages = 50) {
68
+ return (await this.listAllGrantsWithRails(query, maxPages)).items;
69
+ }
70
+ /**
71
+ * The same sweep, keeping the part `listAllGrants` throws away: which rails the
72
+ * caller was not allowed to read.
73
+ *
74
+ * The distinction is not cosmetic. An empty page from an unreadable rail looks
75
+ * exactly like "you hold no grants", and a caller that cannot tell them apart
76
+ * reports the wrong one: a brokered connector agent with a live grant refused
77
+ * its task and told the buyer to ask for the grant they had just issued, because
78
+ * its key lacked `connections:read` and this method answered "none".
79
+ */
80
+ async listAllGrantsWithRails(query = {}, maxPages = 50) {
68
81
  const all = [];
82
+ const rails = new Map();
69
83
  let cursor;
70
84
  for (let page = 0; page < maxPages; page++) {
71
85
  const res = await this.listGrants({ ...query, cursor });
72
86
  all.push(...res.items);
87
+ for (const rail of res.unreadableRails ?? [])
88
+ rails.set(rail.rail, rail);
73
89
  if (!res.nextCursor)
74
- return all;
90
+ break;
75
91
  cursor = res.nextCursor;
76
92
  }
77
- return all;
93
+ return { items: all, unreadableRails: [...rails.values()] };
78
94
  }
79
95
  }
@@ -24,7 +24,7 @@ export interface PullOffersOptions {
24
24
  }
25
25
  export declare function pullOffers(options: PullOffersOptions | undefined, creds: Creds): Promise<Agreement[]>;
26
26
  export declare function claimOffer(agreementId: string, creds: Creds): Promise<Agreement>;
27
- export interface PublishQuestPayload {
27
+ export interface PublishRequestPayload {
28
28
  /** See PublishOfferPayload.billing. */
29
29
  billing?: 'total' | 'per_task';
30
30
  description: string;
@@ -38,12 +38,12 @@ export interface PublishQuestPayload {
38
38
  /** Broadcast audience: 'everyone' (default, fully public) or 'org' (members of your active org only). */
39
39
  audience?: BroadcastAudience;
40
40
  }
41
- export declare function publishQuest(payload: PublishQuestPayload, creds: Creds): Promise<Agreement>;
42
- export interface PullQuestsOptions {
41
+ export declare function publishRequest(payload: PublishRequestPayload, creds: Creds): Promise<Agreement>;
42
+ export interface PullRequestsOptions {
43
43
  limit?: number;
44
44
  since?: string;
45
45
  }
46
- export declare function pullQuests(options: PullQuestsOptions | undefined, creds: Creds): Promise<Agreement[]>;
46
+ export declare function pullRequests(options: PullRequestsOptions | undefined, creds: Creds): Promise<Agreement[]>;
47
47
  export declare class MarketplaceClient {
48
48
  private creds;
49
49
  /**
@@ -54,6 +54,6 @@ export declare class MarketplaceClient {
54
54
  publishOffer(payload: PublishOfferPayload): Promise<Agreement>;
55
55
  pullOffers(options?: PullOffersOptions): Promise<Agreement[]>;
56
56
  claimOffer(agreementId: string): Promise<Agreement>;
57
- publishQuest(payload: PublishQuestPayload): Promise<Agreement>;
58
- pullQuests(options?: PullQuestsOptions): Promise<Agreement[]>;
57
+ publishRequest(payload: PublishRequestPayload): Promise<Agreement>;
58
+ pullRequests(options?: PullRequestsOptions): Promise<Agreement[]>;
59
59
  }
@@ -70,37 +70,37 @@ export async function claimOffer(agreementId, creds) {
70
70
  throw new Error(data?.['error'] || 'Claim failed');
71
71
  return shapeAgreement(data['offer']);
72
72
  }
73
- export async function publishQuest(payload, creds) {
74
- assertCreds(creds, 'quest publish');
75
- const res = await fetch(`${getMarketplaceBaseUrl()}/quests/publish`, {
73
+ export async function publishRequest(payload, creds) {
74
+ assertCreds(creds, 'request publish');
75
+ const res = await fetch(`${getMarketplaceBaseUrl()}/requests/publish`, {
76
76
  method: 'POST',
77
77
  headers: buildHeaders(creds),
78
78
  body: JSON.stringify(payload || {}),
79
79
  });
80
80
  if (!res.ok) {
81
81
  const body = await res.text().catch(() => '');
82
- throwApiError(res, body, `Quest publish failed: ${res.status}`);
82
+ throwApiError(res, body, `Request publish failed: ${res.status}`);
83
83
  }
84
84
  const data = await res.json().catch(() => null);
85
85
  if (!data?.['agreement'])
86
- throw new Error('Quest publish returned no agreement');
86
+ throw new Error('Request publish returned no agreement');
87
87
  return shapeAgreement(data['agreement']);
88
88
  }
89
- export async function pullQuests(options, creds) {
90
- assertCreds(creds, 'quest pull');
89
+ export async function pullRequests(options, creds) {
90
+ assertCreds(creds, 'request pull');
91
91
  const params = new URLSearchParams();
92
92
  if (options?.limit != null)
93
93
  params.set('limit', String(options.limit));
94
94
  if (options?.since)
95
95
  params.set('since', options.since);
96
96
  const qs = params.toString();
97
- const res = await fetch(`${getMarketplaceBaseUrl()}/quests${qs ? `?${qs}` : ''}`, {
97
+ const res = await fetch(`${getMarketplaceBaseUrl()}/requests${qs ? `?${qs}` : ''}`, {
98
98
  method: 'GET',
99
99
  headers: buildHeaders(creds),
100
100
  });
101
101
  if (!res.ok) {
102
102
  const body = await res.text().catch(() => '');
103
- throwApiError(res, body, `Quest pull failed: ${res.status}`);
103
+ throwApiError(res, body, `Request pull failed: ${res.status}`);
104
104
  }
105
105
  const data = await res.json().catch(() => null);
106
106
  return data?.['agreements'] ?? [];
@@ -121,6 +121,6 @@ export class MarketplaceClient {
121
121
  publishOffer(payload) { return publishOffer(payload, this.creds); }
122
122
  pullOffers(options) { return pullOffers(options, this.creds); }
123
123
  claimOffer(agreementId) { return claimOffer(agreementId, this.creds); }
124
- publishQuest(payload) { return publishQuest(payload, this.creds); }
125
- pullQuests(options) { return pullQuests(options, this.creds); }
124
+ publishRequest(payload) { return publishRequest(payload, this.creds); }
125
+ pullRequests(options) { return pullRequests(options, this.creds); }
126
126
  }
@@ -86,6 +86,11 @@ export interface ListTasksOptions {
86
86
  limit?: number;
87
87
  /** Filter to tasks assigned to this id. */
88
88
  assignedTo?: string;
89
+ /**
90
+ * Filter to tasks CREATED by this id — what the caller handed out, as
91
+ * opposed to what was handed to it.
92
+ */
93
+ createdBy?: string;
89
94
  }
90
95
  export interface ListTasksResult {
91
96
  tasks: Task[];
@@ -345,6 +345,8 @@ export async function listTasks(options = {}, creds) {
345
345
  url.searchParams.set('limit', String(options.limit));
346
346
  if (options.assignedTo)
347
347
  url.searchParams.set('assignedTo', options.assignedTo);
348
+ if (options.createdBy)
349
+ url.searchParams.set('createdBy', options.createdBy);
348
350
  const res = await fetch(url.toString(), {
349
351
  method: 'GET',
350
352
  headers: buildHeaders(creds),
@@ -1,14 +1,14 @@
1
1
  import { type ClaimedKind, type ProposeTerms } from './AgreementClient.js';
2
2
  import { type Agreement, type Creds, type EngagementKind } from '../types.js';
3
3
  /**
4
- * one propose grammar. Direct, broadcast (quest and standing
4
+ * one propose grammar. Direct, broadcast (request and standing
5
5
  * offer), and link proposals all flow through here; the surfaces expose a
6
6
  * single propose tool instead of dedicated publish/request tools.
7
7
  *
8
8
  * Routing:
9
9
  * - engagementKind 'link' → POST /agreements (link proposal / open invite)
10
10
  * - proposedTo 'everyone' | 'org', providerId = self → seller-broadcast standing offer
11
- * - proposedTo 'everyone' | 'org', no providerId → buyer-broadcast quest
11
+ * - proposedTo 'everyone' | 'org', no providerId → buyer-broadcast request
12
12
  * - anything else → direct proposal
13
13
  */
14
14
  export interface UnifiedProposeInput extends ProposeTerms {
@@ -17,13 +17,13 @@ export interface UnifiedProposeInput extends ProposeTerms {
17
17
  chatId?: string;
18
18
  engagementKind?: EngagementKind;
19
19
  }
20
- export type ProposeShape = 'direct' | 'quest' | 'offer' | 'link';
20
+ export type ProposeShape = 'direct' | 'request' | 'offer' | 'link';
21
21
  export declare function proposeUnified(input: UnifiedProposeInput, creds: Creds): Promise<{
22
22
  agreement: Agreement;
23
23
  shape: ProposeShape;
24
24
  }>;
25
25
  /**
26
- * one claim verb for any open broadcast: link invite, quest,
26
+ * one claim verb for any open broadcast: link invite, request,
27
27
  * hand-off, or standing offer.
28
28
  *
29
29
  * One request. This used to read the agreement first to decide which endpoint to
@@ -1,4 +1,4 @@
1
- import { createAgreement, claimAgreement, proposeBroadcast, proposeDirectTo, } from './AgreementClient.js';
1
+ import { createLink, claimAgreement, proposeBroadcast, proposeDirectTo, } from './AgreementClient.js';
2
2
  import { publishOffer } from './MarketplaceClient.js';
3
3
  import { isBroadcastTarget, } from '../types.js';
4
4
  export async function proposeUnified(input, creds) {
@@ -9,9 +9,8 @@ export async function proposeUnified(input, creds) {
9
9
  // A link is an agreement, proposed to one agent (providerId) or opened as
10
10
  // an invite (proposedTo 'everyone'); no chat, no money.
11
11
  const target = isBroadcastTarget(proposedTo) ? undefined : proposedTo;
12
- const { agreement } = await createAgreement({
13
- engagementKind: 'link',
14
- ...(target ? { providerId: target } : {}),
12
+ const { agreement } = await createLink({
13
+ ...(target ? { targetAgentId: target } : {}),
15
14
  ...(terms.description ? { description: terms.description } : {}),
16
15
  }, creds);
17
16
  return { agreement, shape: 'link' };
@@ -33,16 +32,16 @@ export async function proposeUnified(input, creds) {
33
32
  return { agreement, shape: 'offer' };
34
33
  }
35
34
  if (providerId) {
36
- throw new Error('On a broadcast, providerId must be your own agent id (a standing offer: you work, the claimer pays) or omitted (a quest: the claimer works, you pay). A third-party providerId is not broadcastable.');
35
+ throw new Error('On a broadcast, providerId must be your own agent id (a standing offer: you work, the claimer pays) or omitted (a request: the claimer works, you pay). A third-party providerId is not broadcastable.');
37
36
  }
38
- // Buyer-broadcast: the claimer works, your side pays — an open quest.
37
+ // Buyer-broadcast: the claimer works, your side pays — an open request.
39
38
  const agreement = await proposeBroadcast({
40
39
  ...terms,
41
40
  chatId: chatId ?? '',
42
41
  engagementKind: engagementKind ?? 'service',
43
42
  audience,
44
43
  }, creds);
45
- return { agreement, shape: 'quest' };
44
+ return { agreement, shape: 'request' };
46
45
  }
47
46
  if (!chatId)
48
47
  throw new Error('chatId is required on a direct proposal');
@@ -56,7 +55,7 @@ export async function proposeUnified(input, creds) {
56
55
  return { agreement, shape: 'direct' };
57
56
  }
58
57
  /**
59
- * one claim verb for any open broadcast: link invite, quest,
58
+ * one claim verb for any open broadcast: link invite, request,
60
59
  * hand-off, or standing offer.
61
60
  *
62
61
  * One request. This used to read the agreement first to decide which endpoint to
@@ -74,6 +73,6 @@ export async function claimOpenAgreement(agreementId, creds) {
74
73
  throw new Error('agreementId is required');
75
74
  const { agreement, kind } = await claimAgreement(agreementId, creds);
76
75
  // A server that has not shipped the `kind` field yet still claims correctly;
77
- // 'quest' is the shape the route has always handled.
78
- return { agreement, kind: kind ?? 'quest' };
76
+ // 'request' is the shape the route has always handled.
77
+ return { agreement, kind: kind ?? 'request' };
79
78
  }
@@ -11,6 +11,23 @@
11
11
  * watermark are presented as `temporal` / `watermark_at` caveats.
12
12
  */
13
13
  export type GrantHealth = 'active' | 'expired' | 'revoked';
14
+ /**
15
+ * Who holds a grant. Declared at issuance and carried on the row — nothing
16
+ * about an id says what it names. An `org` holder is how one grant covers every
17
+ * member of that organization.
18
+ */
19
+ export type GrantHolderKind = 'user' | 'org' | 'agent';
20
+ /**
21
+ * What a grant lets its holder do. `write` implies `read`, `admit` implies
22
+ * both: `read` sees the scope, `write` takes part in it, `admit` brings others
23
+ * in as well.
24
+ */
25
+ export type GrantAccessKind = 'read' | 'write' | 'admit';
26
+ /**
27
+ * The kind of principal-authored consent object a grant rests on. Every grant
28
+ * is minted by one of these, or delegated from a parent grant that was.
29
+ */
30
+ export type GrantBasisKind = 'creation' | 'publication' | 'membership' | 'acceptance' | 'agreement';
14
31
  /**
15
32
  * The context rail's scope kinds, as VALUES — the type below is derived from
16
33
  * them, so widening the rail is one edit rather than a type change plus however
@@ -51,6 +68,17 @@ export interface GrantView {
51
68
  /** ISO-8601. */
52
69
  createdAt: string;
53
70
  health: GrantHealth;
71
+ /**
72
+ * What the holder is, what the grant lets them do, and which consent object
73
+ * authorized it. Present on rails that record them (context grants do);
74
+ * absent means the rail does not say, not that there is nothing.
75
+ */
76
+ holderKind?: GrantHolderKind;
77
+ access?: GrantAccessKind;
78
+ basis?: {
79
+ kind: GrantBasisKind;
80
+ id: string | null;
81
+ };
54
82
  }
55
83
  /** Value of the first caveat of `type` on a grant, or undefined. */
56
84
  export declare function grantCaveat(grant: GrantView, type: string): unknown | undefined;
@@ -8,7 +8,7 @@ export type { ListMessagesOptions, ListMessagesResult } from './MessagesClient.j
8
8
  export { ArtifactsClient, artifactScopeForSession, AGREEMENT_LANE_PREFIX, ARTIFACT_INLINE_TEXT_MAX_CHARS, ARTIFACT_INLINE_TEXT_OVER_LIMIT_HINT, } from './ArtifactsClient.js';
9
9
  export type { ArtifactVisibility, ListArtifactsOptions, ListArtifactsQuery, ListArtifactsResult, WriteArtifactInput, } from './ArtifactsClient.js';
10
10
  export { ContextReadClient, CONTEXT_READ_TYPES, CONTEXT_READ_VIA, VIA_KINDS, parseVia, viaHint, } from './ContextReadClient.js';
11
- export type { ContextReadType, ContextReadQuery, ContextReadEnvelope, ContextSnapshotResult, ViaKind, } from './ContextReadClient.js';
11
+ export type { ContextReadType, ContextReadQuery, ContextReadEnvelope, ContextSnapshotResult, ContextSnapshotParticipant, ViaKind, } from './ContextReadClient.js';
12
12
  export { ContextDiscoveryClient } from './ContextDiscoveryClient.js';
13
13
  export type { DiscoverableItem } from './ContextDiscoveryClient.js';
14
14
  export { GrantsClient } from './GrantsClient.js';
@@ -16,7 +16,7 @@ export type { ListGrantsQuery, ListGrantsResult, UnreadableRail } from './Grants
16
16
  export { ContextGrantsClient } from './ContextGrantsClient.js';
17
17
  export type { ContextGrantRecord, ContextGrantScope, ContextGrantScopeKind, ContextTemporal, IssueContextGrantInput, DelegateContextGrantInput, DelegateContextGrantResult, ReachEntry, GrantReachResult, } from './ContextGrantsClient.js';
18
18
  export { grantCaveat, CONTEXT_GRANT_SCOPE_KINDS, GRANT_SCOPE_KINDS, } from './grants.js';
19
- export type { GrantView, GrantScopeKind, GrantScopeView, GrantCaveatView, GrantHealth, } from './grants.js';
19
+ export type { GrantView, GrantScopeKind, GrantScopeView, GrantCaveatView, GrantHealth, GrantHolderKind, GrantAccessKind, GrantBasisKind, } from './grants.js';
20
20
  export { PaymentsClient } from './PaymentsClient.js';
21
21
  export type { PaymentsError, WalletBalance, WalletRef, PaymentTransactionView, TransferResult, HoldResult, ReleaseResult, PaymentGrantView, PaymentGrantEnvelope, RevokeGrantResult, PaymentApproval, WaitForApprovalResult, } from './PaymentsClient.js';
22
22
  export { ConnectionsClient, assertNoLeakedConnectionSecret, } from './ConnectionsClient.js';
package/dist/index.d.ts CHANGED
@@ -11,5 +11,5 @@ export { runtimeLog, resetRuntimeLogLevelCache } from './shared/runtimeLog.js';
11
11
  export { RateLimitedError, isRateLimited, parseRetryAfterMs, pollSurfaceError, } from './shared/rateLimit.js';
12
12
  export { parseErrorMessage, parseErrorCode, throwApiError, } from './shared/apiError.js';
13
13
  export { ApiError } from './types.js';
14
- export type { Creds, Task, TaskState, PlanStep, PlanStepStatus, Agreement, EngagementKind, BroadcastAudience, EntryType, ContentType, MessageMetadata, MessageHandler, InboxDeliveryKind, InboxDeliveryRef, InboxChatNews, InboxProposalRef, InboxTaskRef, InboxQuestRef, InboxConnectionRequestRef, InboxHumanAttention, InboxEnvelope, InboxAckResult, InboxReadOptions, } from './types.js';
14
+ export type { Creds, Task, TaskState, PlanStep, PlanStepStatus, Agreement, EngagementKind, BroadcastAudience, EntryType, ContentType, MessageMetadata, MessageHandler, InboxDeliveryKind, InboxDeliveryRef, InboxChatNews, InboxProposalRef, InboxTaskRef, InboxRequestRef, InboxConnectionRequestRef, InboxHumanAttention, InboxEnvelope, InboxAckResult, InboxReadOptions, } from './types.js';
15
15
  export type { ProposeTerms, ProposeDirectInput, ProposeBroadcastInput, ProposeAgreementData, } from './http/AgreementClient.js';