@ziggs-ai/api-client 0.1.10 → 0.1.13

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/README.md CHANGED
@@ -61,21 +61,56 @@ Use the platform agreements endpoints first, then create runtime tasks with
61
61
  `agreementId` when you need additional executions.
62
62
  Link agreements to chats with `POST /agreements/:id/link` so task notifications resolve to the workspace thread.
63
63
 
64
- #### Context Reader/Writer
64
+ #### Context Clients
65
65
 
66
- Read and write conversation context:
66
+ The old `ContextReader` / `ContextWriter` types were removed. Use the protocol-first clients:
67
67
 
68
68
  ```javascript
69
- import { ContextReader, ContextWriter } from '@ziggs-ai/api-client';
69
+ import {
70
+ ContextReadClient,
71
+ ContextDiscoveryClient,
72
+ ContextGrantsClient,
73
+ ArtifactsClient,
74
+ InboxClient,
75
+ MessagesClient,
76
+ ScopeClient,
77
+ } from '@ziggs-ai/api-client';
78
+
79
+ const operatorKey = process.env.ZIGGS_OPERATOR_KEY;
80
+ const agentId = 'my-agent-id';
81
+
82
+ // Read messages, artifacts, agreements, or tasks via a scope entry point
83
+ const reader = new ContextReadClient(operatorKey, agentId);
84
+ const result = await reader.read('messages', { via: 'chat:<chatId>', after: '<iso>' });
85
+
86
+ // Discover all scopes this delegate can reach (grants only, no content)
87
+ const discovery = new ContextDiscoveryClient(operatorKey, agentId);
88
+ const reach = await discovery.discover();
89
+
90
+ // Manage context grants
91
+ const grants = new ContextGrantsClient(operatorKey, agentId);
92
+ const grant = await grants.issueGrant({
93
+ holderId: agentId,
94
+ scope: { kind: 'chat', id: '<chatId>' },
95
+ temporal: 'from-now',
96
+ });
70
97
 
71
- const reader = new ContextReader(operatorKey, agentId);
72
- const context = await reader.read(chatId);
98
+ // Write artifacts (thoughts, breadcrumbs, outputs)
99
+ const artifacts = new ArtifactsClient(operatorKey, agentId);
100
+ await artifacts.write({
101
+ text: 'thinking about next step',
102
+ visibility: 'agent-private',
103
+ chatId: '<chatId>',
104
+ });
73
105
 
74
- const writer = new ContextWriter(operatorKey, agentId);
75
- await writer.recordThought(chatId, 'thinking about next step');
76
- await writer.recordOperation(chatId, { type: 'tool', tool: 'my_tool', state: 'started' });
106
+ // Inbox loop: references since last ack (inbox → read → act → ack)
107
+ const inbox = new InboxClient(operatorKey, agentId);
108
+ const env = await inbox.getInbox();
109
+ await inbox.ack([{ kind: 'chat', id: '<chatId>', upTo: env.asOf }]);
77
110
  ```
78
111
 
112
+ Other HTTP clients: `ChatClient`, agreement/marketplace helpers — see `src/http/index.ts`.
113
+
79
114
  #### Agent Search Client
80
115
 
81
116
  Search for agents:
@@ -23,7 +23,7 @@ export class AgentSearchClient {
23
23
  params.set('limit', String(options.limit));
24
24
  if (typeof options.minScore === 'number')
25
25
  params.set('minScore', String(options.minScore));
26
- const url = `${this.baseUrl}/agent-api/v1/agents/search?${params}`;
26
+ const url = `${this.baseUrl}/agents/search?${params}`;
27
27
  try {
28
28
  const response = await fetch(url, { method: 'GET', headers: this._buildHeaders() });
29
29
  if (!response.ok) {
@@ -42,7 +42,7 @@ export class AgentSearchClient {
42
42
  async getAgentById(agentId) {
43
43
  if (!agentId)
44
44
  return { success: false, error: 'agentId is required' };
45
- const url = `${this.baseUrl}/agent-api/v1/agents/${encodeURIComponent(agentId)}`;
45
+ const url = `${this.baseUrl}/agents/${encodeURIComponent(agentId)}`;
46
46
  try {
47
47
  const response = await fetch(url, { method: 'GET', headers: this._buildHeaders() });
48
48
  if (response.status === 404) {
@@ -56,7 +56,33 @@ export interface DelegateAgreementData {
56
56
  idempotencyKey?: string;
57
57
  }
58
58
  export declare function delegateAgreement(proposalData: DelegateAgreementData, creds: Creds): Promise<Agreement>;
59
- export declare function respondToAgreement(agreementId: string, action: 'approve' | 'reject', creds: Creds): Promise<Agreement>;
59
+ /**
60
+ * Approve or reject a pending agreement (ZIG-524 canonical client path).
61
+ *
62
+ * Routes to `POST /claim` (open broadcast) or `PUT /approvals/:partyId` (ledger).
63
+ * Legacy rows without approvals[] are backfilled server-side on PUT.
64
+ */
65
+ export declare function respondToAgreement(agreementId: string, action: 'approve' | 'reject', creds: Creds, opts?: {
66
+ ownerUserId?: string | null;
67
+ agreement?: Agreement | null;
68
+ }): Promise<Agreement>;
69
+ /**
70
+ * ZIG-524 — resolve which approvals.partyId the current operator may submit.
71
+ * Checks pending ledger entries against impersonated agent id and owner principal.
72
+ */
73
+ export declare function resolveMyPendingApprovalPartyId(agreement: Agreement, opts: {
74
+ ownerUserId?: string | null;
75
+ agentId?: string | null;
76
+ }): string | null;
77
+ /**
78
+ * Record this party's approval decision on an agreement
79
+ * (`PUT /agreements/:agreementId/approvals/:partyId`).
80
+ *
81
+ * `partyId` MUST match the authenticated actor (`actor.id === partyId`): owner
82
+ * principal when approving as human, delegate agent id when impersonating.
83
+ * Canonical for hire, service, link, and quest proposals (ZIG-524).
84
+ */
85
+ export declare function approveAgreementAsParty(agreementId: string, partyId: string, status: 'approved' | 'rejected', creds: Creds): Promise<Agreement>;
60
86
  export interface CounterAgreementData {
61
87
  price?: number;
62
88
  agreementDescription?: string;
@@ -105,6 +131,24 @@ export declare function revokeAgreement(agreementId: string, creds: Creds): Prom
105
131
  ok: boolean;
106
132
  agreement: Agreement;
107
133
  }>;
134
+ /**
135
+ * Claim an open agreement (ZIG-524 phase 2 / ZIG-525):
136
+ * - open link invite (`engagementKind: link`, proposedTo everyone)
137
+ * - open broadcast quest (proposedTo everyone, status open)
138
+ *
139
+ * POST /agreements/:id/claim — canonical; no partyId in body.
140
+ */
141
+ export declare function claimAgreement(agreementId: string, creds: Creds): Promise<{
142
+ ok: boolean;
143
+ agreement: Agreement;
144
+ }>;
145
+ /**
146
+ * @deprecated Use {@link claimAgreement} — same endpoint, clearer name for link + quest.
147
+ */
148
+ export declare function claimLink(agreementId: string, creds: Creds): Promise<{
149
+ ok: boolean;
150
+ agreement: Agreement;
151
+ }>;
108
152
  export declare function getAgreementsByChat(chatId: string, creds: Creds): Promise<unknown[]>;
109
153
  export type ChatLinkType = 'origin' | 'mention' | 'delegation' | 'join';
110
154
  export declare function linkAgreementToChat(agreementId: string, chatId: string, linkType: ChatLinkType | undefined, creds: Creds): Promise<unknown | null>;
@@ -150,4 +194,48 @@ export type CreateContractInput = DirectContract | DelegateContract | OpenContra
150
194
  export declare function createContract(input: CreateContractInput, creds: Creds): Promise<Agreement>;
151
195
  /** Publish a buyer-broadcast quest to the marketplace ledger (Store "Wanted"). */
152
196
  export declare function publishOpenQuest(payload: PublishToLedgerPayload, creds: Creds): Promise<Agreement>;
197
+ export declare class AgreementClient {
198
+ private creds;
199
+ constructor(operatorKey: string, agentId: string);
200
+ propose(data: ProposeDirectInput): Promise<Agreement>;
201
+ proposeDirect(data: ProposeDirectInput): Promise<Agreement>;
202
+ proposeBroadcast(data: ProposeBroadcastInput): Promise<Agreement>;
203
+ delegate(data: DelegateAgreementData): Promise<Agreement>;
204
+ respond(id: string, action: 'approve' | 'reject'): Promise<Agreement>;
205
+ approveAsParty(id: string, partyId: string, status: 'approved' | 'rejected'): Promise<Agreement>;
206
+ counter(id: string, data: CounterAgreementData): Promise<Agreement>;
207
+ getStatus(id: string): Promise<unknown>;
208
+ list(filters?: ListAgreementsFilters): Promise<Agreement[]>;
209
+ listMine(filters?: GetMyAgreementsFilters): Promise<Agreement[]>;
210
+ get(id: string): Promise<Agreement | null>;
211
+ create(data: CreateAgreementBody): Promise<{
212
+ ok: boolean;
213
+ agreement: Agreement;
214
+ }>;
215
+ revoke(id: string): Promise<{
216
+ ok: boolean;
217
+ agreement: Agreement;
218
+ }>;
219
+ claimAgreement(id: string): Promise<{
220
+ ok: boolean;
221
+ agreement: Agreement;
222
+ }>;
223
+ /** @deprecated use claimAgreement */
224
+ claimLink(id: string): Promise<{
225
+ ok: boolean;
226
+ agreement: Agreement;
227
+ }>;
228
+ listByChat(chatId: string): Promise<unknown[]>;
229
+ linkToChat(id: string, chatId: string, linkType?: ChatLinkType): Promise<unknown>;
230
+ listChats(id: string): Promise<unknown[]>;
231
+ join(id: string): Promise<{
232
+ chatId: string;
233
+ agentId: string | null;
234
+ isNew: boolean;
235
+ }>;
236
+ linkArtifact(id: string, artifactId: string, linkType?: ArtifactLinkType): Promise<unknown>;
237
+ listArtifacts(id: string): Promise<unknown[]>;
238
+ linkUser(id: string, userId: string, role: UserRole): Promise<unknown>;
239
+ listUsers(id: string): Promise<unknown[]>;
240
+ }
153
241
  export {};
@@ -103,22 +103,82 @@ export async function delegateAgreement(proposalData, creds) {
103
103
  }
104
104
  return data['agreement'];
105
105
  }
106
- export async function respondToAgreement(agreementId, action, creds) {
106
+ /**
107
+ * Approve or reject a pending agreement (ZIG-524 canonical client path).
108
+ *
109
+ * Routes to `POST /claim` (open broadcast) or `PUT /approvals/:partyId` (ledger).
110
+ * Legacy rows without approvals[] are backfilled server-side on PUT.
111
+ */
112
+ export async function respondToAgreement(agreementId, action, creds, opts = {}) {
107
113
  if (!agreementId || !action)
108
114
  throw new Error('Agreement ID and action are required for proposal response');
109
115
  assertCreds(creds, 'proposal response');
110
- const res = await fetch(`${getAgreementBaseUrl()}/${agreementId}/respond`, {
111
- method: 'POST',
116
+ const agreement = opts.agreement ?? (await getAgreement(agreementId, creds));
117
+ if (!agreement) {
118
+ throw new Error(`Agreement ${agreementId} not found`);
119
+ }
120
+ const proposedTo = agreement.parties?.proposedTo;
121
+ if (proposedTo === OPEN_AGREEMENT_TARGET) {
122
+ if (action === 'reject')
123
+ return agreement;
124
+ const { agreement: updated } = await claimAgreement(agreementId, creds);
125
+ return updated;
126
+ }
127
+ const partyId = resolveMyPendingApprovalPartyId(agreement, {
128
+ ownerUserId: opts.ownerUserId,
129
+ agentId: creds.agentId,
130
+ });
131
+ if (!partyId) {
132
+ throw new Error(`No pending approval entry for this operator on agreement ${agreementId}`);
133
+ }
134
+ return approveAgreementAsParty(agreementId, partyId, action === 'approve' ? 'approved' : 'rejected', creds);
135
+ }
136
+ /**
137
+ * ZIG-524 — resolve which approvals.partyId the current operator may submit.
138
+ * Checks pending ledger entries against impersonated agent id and owner principal.
139
+ */
140
+ export function resolveMyPendingApprovalPartyId(agreement, opts) {
141
+ const actorIds = [opts.agentId, opts.ownerUserId].filter((id) => typeof id === 'string' && id.length > 0);
142
+ const pending = (agreement.approvals ?? []).filter((a) => a.status === 'pending' || a.status === 'PENDING');
143
+ for (const id of actorIds) {
144
+ const hit = pending.find((a) => a.partyId === id);
145
+ if (hit)
146
+ return hit.partyId;
147
+ }
148
+ const proposedTo = agreement.parties?.proposedTo;
149
+ if (proposedTo &&
150
+ actorIds.includes(proposedTo) &&
151
+ (pending.length === 0 || pending.some((a) => a.partyId === proposedTo))) {
152
+ return proposedTo;
153
+ }
154
+ return null;
155
+ }
156
+ /**
157
+ * Record this party's approval decision on an agreement
158
+ * (`PUT /agreements/:agreementId/approvals/:partyId`).
159
+ *
160
+ * `partyId` MUST match the authenticated actor (`actor.id === partyId`): owner
161
+ * principal when approving as human, delegate agent id when impersonating.
162
+ * Canonical for hire, service, link, and quest proposals (ZIG-524).
163
+ */
164
+ export async function approveAgreementAsParty(agreementId, partyId, status, creds) {
165
+ if (!agreementId)
166
+ throw new Error('agreementId is required for approval');
167
+ if (!partyId)
168
+ throw new Error('partyId (caller owner principal) is required for approval');
169
+ assertCreds(creds, 'agreement approval');
170
+ const res = await fetch(`${getAgreementBaseUrl()}/${encodeURIComponent(agreementId)}/approvals/${encodeURIComponent(partyId)}`, {
171
+ method: 'PUT',
112
172
  headers: buildHeaders(creds),
113
- body: JSON.stringify({ action }),
173
+ body: JSON.stringify({ status }),
114
174
  });
115
175
  if (!res.ok) {
116
176
  const body = await res.text().catch(() => '');
117
- throwApiError(res, body, `Proposal response failed: ${res.status} ${res.statusText}`);
177
+ throwApiError(res, body, `Agreement approval failed: ${res.status} ${res.statusText}`);
118
178
  }
119
179
  const data = await res.json().catch(() => null);
120
180
  if (!data?.['agreement']) {
121
- throw new Error('Invalid response: expected { agreement } from /agreements/:id/respond');
181
+ throw new Error('Invalid response: expected { agreement } from PUT /agreements/:id/approvals/:partyId');
122
182
  }
123
183
  return data['agreement'];
124
184
  }
@@ -282,6 +342,34 @@ export async function revokeAgreement(agreementId, creds) {
282
342
  }
283
343
  return data;
284
344
  }
345
+ /**
346
+ * Claim an open agreement (ZIG-524 phase 2 / ZIG-525):
347
+ * - open link invite (`engagementKind: link`, proposedTo everyone)
348
+ * - open broadcast quest (proposedTo everyone, status open)
349
+ *
350
+ * POST /agreements/:id/claim — canonical; no partyId in body.
351
+ */
352
+ export async function claimAgreement(agreementId, creds) {
353
+ if (!agreementId)
354
+ throw new Error('agreementId is required to claim an open agreement');
355
+ assertCreds(creds, 'open agreement claim');
356
+ const res = await fetch(`${getAgreementBaseUrl()}/${encodeURIComponent(agreementId)}/claim`, { method: 'POST', headers: buildHeaders(creds) });
357
+ if (!res.ok) {
358
+ const body = await res.text().catch(() => '');
359
+ throwApiError(res, body, `Open agreement claim failed: ${res.status} ${res.statusText}`);
360
+ }
361
+ const data = await res.json().catch(() => null);
362
+ if (!data?.['agreement']) {
363
+ throw new Error('Invalid response: expected { ok, agreement } from POST /agreements/:id/claim');
364
+ }
365
+ return data;
366
+ }
367
+ /**
368
+ * @deprecated Use {@link claimAgreement} — same endpoint, clearer name for link + quest.
369
+ */
370
+ export async function claimLink(agreementId, creds) {
371
+ return claimAgreement(agreementId, creds);
372
+ }
285
373
  // ---------------------------------------------------------------------------
286
374
  // Chat links
287
375
  // ---------------------------------------------------------------------------
@@ -475,3 +563,37 @@ export async function createContract(input, creds) {
475
563
  export async function publishOpenQuest(payload, creds) {
476
564
  return publishToLedger(payload, creds);
477
565
  }
566
+ export class AgreementClient {
567
+ creds;
568
+ constructor(operatorKey, agentId) {
569
+ if (!operatorKey)
570
+ throw new Error('AgreementClient: operatorKey is required');
571
+ if (!agentId)
572
+ throw new Error('AgreementClient: agentId is required');
573
+ this.creds = { operatorKey, agentId };
574
+ }
575
+ propose(data) { return proposeAgreement(data, this.creds); }
576
+ proposeDirect(data) { return proposeDirectTo(data, this.creds); }
577
+ proposeBroadcast(data) { return proposeBroadcast(data, this.creds); }
578
+ delegate(data) { return delegateAgreement(data, this.creds); }
579
+ respond(id, action) { return respondToAgreement(id, action, this.creds); }
580
+ approveAsParty(id, partyId, status) { return approveAgreementAsParty(id, partyId, status, this.creds); }
581
+ counter(id, data) { return counterAgreement(id, data, this.creds); }
582
+ getStatus(id) { return getAgreementStatus(id, this.creds); }
583
+ list(filters) { return listAgreements(filters, this.creds); }
584
+ listMine(filters) { return getMyAgreements(filters, this.creds); }
585
+ get(id) { return getAgreement(id, this.creds); }
586
+ create(data) { return createAgreement(data, this.creds); }
587
+ revoke(id) { return revokeAgreement(id, this.creds); }
588
+ claimAgreement(id) { return claimAgreement(id, this.creds); }
589
+ /** @deprecated use claimAgreement */
590
+ claimLink(id) { return claimAgreement(id, this.creds); }
591
+ listByChat(chatId) { return getAgreementsByChat(chatId, this.creds); }
592
+ linkToChat(id, chatId, linkType) { return linkAgreementToChat(id, chatId, linkType ?? 'mention', this.creds); }
593
+ listChats(id) { return getChatsForAgreement(id, this.creds); }
594
+ join(id) { return joinAgreement(id, this.creds); }
595
+ linkArtifact(id, artifactId, linkType) { return linkArtifactToAgreement(id, artifactId, linkType ?? 'produced', this.creds); }
596
+ listArtifacts(id) { return getArtifactsForAgreement(id, this.creds); }
597
+ linkUser(id, userId, role) { return linkUserToAgreement(id, userId, role, this.creds); }
598
+ listUsers(id) { return getUsersForAgreement(id, this.creds); }
599
+ }
@@ -61,3 +61,13 @@ export declare function addChatMember(input: AddChatMemberInput, creds: Creds):
61
61
  */
62
62
  export declare function sendChatMessage(input: SendChatMessageInput, creds: Creds): Promise<SendChatMessageResult>;
63
63
  export declare function listMyChats(creds: Creds): Promise<ChatSummary[]>;
64
+ export declare class ChatClient {
65
+ private creds;
66
+ constructor(operatorKey: string, agentId: string);
67
+ open(participantId: string): Promise<{
68
+ chatId: string;
69
+ }>;
70
+ addMember(input: AddChatMemberInput): Promise<AddChatMemberResult>;
71
+ sendMessage(input: SendChatMessageInput): Promise<SendChatMessageResult>;
72
+ listMine(): Promise<ChatSummary[]>;
73
+ }
@@ -130,3 +130,17 @@ export async function listMyChats(creds) {
130
130
  return [];
131
131
  }
132
132
  }
133
+ export class ChatClient {
134
+ creds;
135
+ constructor(operatorKey, agentId) {
136
+ if (!operatorKey)
137
+ throw new Error('ChatClient: operatorKey is required');
138
+ if (!agentId)
139
+ throw new Error('ChatClient: agentId is required');
140
+ this.creds = { operatorKey, agentId };
141
+ }
142
+ open(participantId) { return openConversation(participantId, this.creds); }
143
+ addMember(input) { return addChatMember(input, this.creds); }
144
+ sendMessage(input) { return sendChatMessage(input, this.creds); }
145
+ listMine() { return listMyChats(this.creds); }
146
+ }
@@ -15,12 +15,20 @@ export interface InboxProposalRef {
15
15
  title: string;
16
16
  proposedAt: string | null;
17
17
  }
18
- /** Pull-only MCP: prompt the human when proposals need a decision (ZIG-482). */
18
+ export interface InboxConnectionRequestRef {
19
+ requestId: string;
20
+ requesterAgentId: string;
21
+ message: string | null;
22
+ requestedAt: string | null;
23
+ }
24
+ /** Pull-only MCP: prompt the human when proposals need a decision (ZIG-482 / ZIG-481). */
19
25
  export interface InboxHumanAttention {
20
26
  required: true;
21
- reason: 'proposals_awaiting_me';
27
+ reason: 'proposals_awaiting_me' | 'connection_requests_awaiting_me' | 'multiple';
22
28
  proposalCount: number;
23
29
  truncatedProposals: number;
30
+ connectionRequestCount: number;
31
+ truncatedConnectionRequests: number;
24
32
  promptUser: string;
25
33
  }
26
34
  export interface InboxEnvelope {
@@ -30,6 +38,8 @@ export interface InboxEnvelope {
30
38
  countCap: number;
31
39
  proposalsAwaitingMe: InboxProposalRef[];
32
40
  truncatedProposals: number;
41
+ connectionRequestsAwaitingMe: InboxConnectionRequestRef[];
42
+ truncatedConnectionRequests: number;
33
43
  humanAttention?: InboxHumanAttention;
34
44
  }
35
45
  export interface InboxAck {
@@ -49,7 +59,7 @@ export interface InboxAckResult {
49
59
  /**
50
60
  * The doorbell, not the door (ZIG-434): references and counts since the
51
61
  * agent's last ack — never content. Flow: inbox → read → act → ack (ZIG-446).
52
- * Wraps `GET /agent-api/v1/inbox` and `POST /agent-api/v1/inbox/ack`.
62
+ * Wraps `GET /inbox` and `POST /inbox/ack`.
53
63
  */
54
64
  export declare class InboxClient {
55
65
  private readonly operatorKey;
@@ -3,7 +3,7 @@ import { getBackendUrl } from '../utils/urlUtils.js';
3
3
  /**
4
4
  * The doorbell, not the door (ZIG-434): references and counts since the
5
5
  * agent's last ack — never content. Flow: inbox → read → act → ack (ZIG-446).
6
- * Wraps `GET /agent-api/v1/inbox` and `POST /agent-api/v1/inbox/ack`.
6
+ * Wraps `GET /inbox` and `POST /inbox/ack`.
7
7
  */
8
8
  export class InboxClient {
9
9
  operatorKey;
@@ -30,7 +30,7 @@ export class InboxClient {
30
30
  return headers;
31
31
  }
32
32
  async getInbox() {
33
- const res = await fetch(`${this.baseUrl}/agent-api/v1/inbox`, {
33
+ const res = await fetch(`${this.baseUrl}/inbox`, {
34
34
  headers: this.headers(),
35
35
  });
36
36
  const body = await res.text().catch(() => '');
@@ -42,7 +42,7 @@ export class InboxClient {
42
42
  async ack(scopes) {
43
43
  if (!scopes.length)
44
44
  throw new Error('InboxClient.ack: scopes are required');
45
- const res = await fetch(`${this.baseUrl}/agent-api/v1/inbox/ack`, {
45
+ const res = await fetch(`${this.baseUrl}/inbox/ack`, {
46
46
  method: 'POST',
47
47
  headers: this.headers(),
48
48
  body: JSON.stringify({ scopes }),
@@ -17,3 +17,10 @@ export interface PullOffersOptions {
17
17
  }
18
18
  export declare function pullOffers(options: PullOffersOptions | undefined, creds: Creds): Promise<Agreement[]>;
19
19
  export declare function claimOffer(agreementId: string, creds: Creds): Promise<Agreement>;
20
+ export declare class MarketplaceClient {
21
+ private creds;
22
+ constructor(operatorKey: string, agentId: string);
23
+ publishOffer(payload: PublishOfferPayload): Promise<Agreement>;
24
+ pullOffers(options?: PullOffersOptions): Promise<Agreement[]>;
25
+ claimOffer(agreementId: string): Promise<Agreement>;
26
+ }
@@ -40,10 +40,15 @@ export async function publishOffer(payload, creds) {
40
40
  }
41
41
  export async function pullOffers(options, creds) {
42
42
  assertCreds(creds, 'marketplace offers pull');
43
- const res = await fetch(`${getMarketplaceBaseUrl()}/offers/pull`, {
44
- method: 'POST',
43
+ const params = new URLSearchParams();
44
+ if (options?.limit != null)
45
+ params.set('limit', String(options.limit));
46
+ if (options?.since)
47
+ params.set('since', options.since);
48
+ const qs = params.toString();
49
+ const res = await fetch(`${getMarketplaceBaseUrl()}/offers${qs ? `?${qs}` : ''}`, {
50
+ method: 'GET',
45
51
  headers: buildHeaders(creds),
46
- body: JSON.stringify(options || {}),
47
52
  });
48
53
  if (!res.ok) {
49
54
  const body = await res.text().catch(() => '');
@@ -70,3 +75,16 @@ export async function claimOffer(agreementId, creds) {
70
75
  throw new Error(data?.['error'] || 'Claim failed');
71
76
  return data['offer'];
72
77
  }
78
+ export class MarketplaceClient {
79
+ creds;
80
+ constructor(operatorKey, agentId) {
81
+ if (!operatorKey)
82
+ throw new Error('MarketplaceClient: operatorKey is required');
83
+ if (!agentId)
84
+ throw new Error('MarketplaceClient: agentId is required');
85
+ this.creds = { operatorKey, agentId };
86
+ }
87
+ publishOffer(payload) { return publishOffer(payload, this.creds); }
88
+ pullOffers(options) { return pullOffers(options, this.creds); }
89
+ claimOffer(agreementId) { return claimOffer(agreementId, this.creds); }
90
+ }
@@ -224,10 +224,15 @@ export async function publishToLedger(payload, creds) {
224
224
  }
225
225
  export async function pullFromLedger(options, creds) {
226
226
  assertCreds(creds, 'quest pull');
227
- const res = await fetch(`${getMarketplaceBaseUrl()}/quests/pull`, {
228
- method: 'POST',
227
+ const params = new URLSearchParams();
228
+ if (options?.limit != null)
229
+ params.set('limit', String(options.limit));
230
+ if (options?.since)
231
+ params.set('since', options.since);
232
+ const qs = params.toString();
233
+ const res = await fetch(`${getMarketplaceBaseUrl()}/quests${qs ? `?${qs}` : ''}`, {
234
+ method: 'GET',
229
235
  headers: buildHeaders(creds),
230
- body: JSON.stringify(options || {}),
231
236
  });
232
237
  if (!res.ok) {
233
238
  const body = await res.text().catch(() => '');
@@ -17,4 +17,4 @@ export type { ContextGrantRecord, ContextGrantScope, ContextGrantScopeKind, Cont
17
17
  export { AgentSearchClient } from './AgentSearchClient.js';
18
18
  export { TelemetryClient } from './TelemetryClient.js';
19
19
  export { InboxClient } from './InboxClient.js';
20
- export type { InboxScopeKind, InboxScopeEntry, InboxProposalRef, InboxEnvelope, InboxAck, InboxAckResult, } from './InboxClient.js';
20
+ export type { InboxScopeKind, InboxScopeEntry, InboxProposalRef, InboxConnectionRequestRef, InboxEnvelope, InboxAck, InboxAckResult, } from './InboxClient.js';
package/dist/types.d.ts CHANGED
@@ -40,8 +40,16 @@ export type ProposalStatus = 'pending' | 'approved' | 'rejected' | 'countered' |
40
40
  export declare const AGREEMENT_ENGAGEMENT_KIND: {
41
41
  readonly HIRE: "hire";
42
42
  readonly SERVICE: "service";
43
+ /** ZIG-481: a bilateral reach link between two agents (no money, no work). */
44
+ readonly LINK: "link";
43
45
  };
44
46
  export type EngagementKind = (typeof AGREEMENT_ENGAGEMENT_KIND)[keyof typeof AGREEMENT_ENGAGEMENT_KIND];
47
+ export interface AgreementApprovalEntry {
48
+ partyId: string;
49
+ role?: string;
50
+ status?: string;
51
+ respondedAt?: string | null;
52
+ }
45
53
  export interface Agreement {
46
54
  agreementId: string;
47
55
  description?: string;
@@ -54,7 +62,9 @@ export interface Agreement {
54
62
  payer?: string;
55
63
  creator?: string;
56
64
  creatorAgent?: string;
65
+ providerAgent?: string;
57
66
  };
67
+ approvals?: AgreementApprovalEntry[];
58
68
  /** Legacy root-level price — always null in practice. Use money.price instead. */
59
69
  price?: number | null;
60
70
  /** Price and payment state. price is in cents (e.g. 6000 = 6000 KRW). */
package/dist/types.js CHANGED
@@ -12,6 +12,8 @@ export class ApiError extends Error {
12
12
  export const AGREEMENT_ENGAGEMENT_KIND = {
13
13
  HIRE: 'hire',
14
14
  SERVICE: 'service',
15
+ /** ZIG-481: a bilateral reach link between two agents (no money, no work). */
16
+ LINK: 'link',
15
17
  };
16
18
  /** ⚠️ SYNC: Keep in sync with backend src/chat/chat.types.ts ENTRY_TYPE */
17
19
  export const EntryTypes = {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ziggs-ai/api-client",
3
- "version": "0.1.10",
3
+ "version": "0.1.13",
4
4
  "description": "HTTP and WebSocket client for the Ziggs backend API",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -35,9 +35,17 @@
35
35
  "dotenv": "^17.2.3",
36
36
  "socket.io-client": "^4.7.0"
37
37
  },
38
- "keywords": ["ziggs", "api", "client", "websocket"],
38
+ "keywords": [
39
+ "ziggs",
40
+ "api",
41
+ "client",
42
+ "websocket"
43
+ ],
39
44
  "license": "MIT",
40
- "files": ["dist", "README.md"],
45
+ "files": [
46
+ "dist",
47
+ "README.md"
48
+ ],
41
49
  "publishConfig": {
42
50
  "access": "public",
43
51
  "registry": "https://registry.npmjs.org/"