@ziggs-ai/api-client 0.19.0 → 0.21.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/capabilities/agreementVerbs.d.ts +7 -0
- package/dist/capabilities/agreementVerbs.js +84 -1
- package/dist/capabilities/agreements.d.ts +3 -0
- package/dist/capabilities/agreements.js +9 -1
- package/dist/capabilities/artifacts.d.ts +38 -0
- package/dist/capabilities/artifacts.js +148 -7
- package/dist/capabilities/chat.d.ts +31 -1
- package/dist/capabilities/chat.js +39 -0
- package/dist/capabilities/context.d.ts +3 -0
- package/dist/capabilities/context.js +125 -1
- package/dist/capabilities/index.d.ts +6 -6
- package/dist/capabilities/index.js +6 -6
- package/dist/capabilities/introductions.js +5 -10
- package/dist/capabilities/links.js +1 -0
- package/dist/capabilities/marketplace.js +15 -6
- package/dist/capabilities/nextCall.d.ts +72 -14
- package/dist/capabilities/nextCall.js +279 -4
- package/dist/capabilities/tasks.d.ts +68 -1
- package/dist/capabilities/tasks.js +112 -3
- package/dist/engagementGuide.d.ts +148 -0
- package/dist/engagementGuide.js +349 -0
- package/dist/http/AgreementClient.d.ts +2 -1
- package/dist/http/AgreementClient.js +4 -0
- package/dist/http/ArtifactsClient.d.ts +47 -0
- package/dist/http/ArtifactsClient.js +33 -0
- package/dist/http/ChatClient.d.ts +28 -2
- package/dist/http/ChatClient.js +7 -0
- package/dist/http/ContextGrantsClient.d.ts +17 -1
- package/dist/http/ContextGrantsClient.js +26 -2
- package/dist/http/ContextOpenClient.d.ts +70 -0
- package/dist/http/ContextOpenClient.js +52 -0
- package/dist/http/InboxClient.d.ts +8 -0
- package/dist/http/InboxClient.js +18 -0
- package/dist/http/TaskClient.d.ts +2 -0
- package/dist/http/TaskClient.js +1 -0
- package/dist/http/index.d.ts +2 -0
- package/dist/http/index.js +1 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +2 -0
- package/dist/instanceIdentity.d.ts +1 -1
- package/dist/instanceIdentity.js +2 -2
- package/dist/sessionOrientation.d.ts +50 -0
- package/dist/sessionOrientation.js +43 -0
- package/dist/types.d.ts +11 -0
- package/package.json +2 -2
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { ContextReadClient, CONTEXT_READ_TYPES, CONTEXT_READ_VIA, parseVia, viaHint, } from '../http/ContextReadClient.js';
|
|
2
|
+
import { ContextOpenClient } from '../http/ContextOpenClient.js';
|
|
2
3
|
import { ContextGrantsClient, } from '../http/ContextGrantsClient.js';
|
|
3
4
|
import { ContextDiscoveryClient } from '../http/ContextDiscoveryClient.js';
|
|
4
5
|
import { grantCaveat, CONTEXT_GRANT_SCOPE_KINDS, } from '../http/grants.js';
|
|
@@ -194,6 +195,10 @@ export const contextDelegateCapability = {
|
|
|
194
195
|
type: 'string',
|
|
195
196
|
description: 'from-now watermark ISO-8601 (optional; server may default)',
|
|
196
197
|
},
|
|
198
|
+
idempotencyKey: {
|
|
199
|
+
type: 'string',
|
|
200
|
+
description: 'Replay the same delegate. Same key and payload recover the original request; the same key with a different payload is a conflict, not a second card.',
|
|
201
|
+
},
|
|
197
202
|
},
|
|
198
203
|
needsAgentId: true,
|
|
199
204
|
handler: async (args, env) => {
|
|
@@ -221,11 +226,18 @@ export const contextDelegateCapability = {
|
|
|
221
226
|
temporal: temporal,
|
|
222
227
|
expiresAt: args['expiresAt'] ?? undefined,
|
|
223
228
|
watermarkAt: args['watermarkAt'],
|
|
229
|
+
}, {
|
|
230
|
+
idempotencyKey: typeof args['idempotencyKey'] === 'string'
|
|
231
|
+
? args['idempotencyKey']
|
|
232
|
+
: undefined,
|
|
224
233
|
});
|
|
225
234
|
if (result.status === 'pending_approval') {
|
|
226
235
|
return {
|
|
227
236
|
status: 'pending_approval',
|
|
228
|
-
|
|
237
|
+
state: 'requested',
|
|
238
|
+
outcome: 'pending',
|
|
239
|
+
recoverable: true,
|
|
240
|
+
message: "Requested, not granted — this grant's original owner must approve. Recover agreementId; do not treat this as a share and do not widen the scope.",
|
|
229
241
|
parentGrantId: args['parentGrantId'],
|
|
230
242
|
agreementId: result.agreementId,
|
|
231
243
|
ownerId: result.ownerId,
|
|
@@ -234,15 +246,127 @@ export const contextDelegateCapability = {
|
|
|
234
246
|
const grant = result.grant;
|
|
235
247
|
return {
|
|
236
248
|
status: 'delegated',
|
|
249
|
+
outcome: 'ok',
|
|
237
250
|
parentGrantId: args['parentGrantId'],
|
|
238
251
|
grant,
|
|
239
252
|
bounds: contextBounds(grant),
|
|
240
253
|
};
|
|
241
254
|
},
|
|
242
255
|
};
|
|
256
|
+
const OPEN_ID_PARAMS = {
|
|
257
|
+
artifactId: {
|
|
258
|
+
type: 'string',
|
|
259
|
+
description: 'Artifact id from a prior response. Pass exactly one id field.',
|
|
260
|
+
},
|
|
261
|
+
chatId: {
|
|
262
|
+
type: 'string',
|
|
263
|
+
description: 'Chat id from a prior response. Pass exactly one id field.',
|
|
264
|
+
},
|
|
265
|
+
taskId: {
|
|
266
|
+
type: 'string',
|
|
267
|
+
description: 'Task id from a prior response. Pass exactly one id field.',
|
|
268
|
+
},
|
|
269
|
+
agreementId: {
|
|
270
|
+
type: 'string',
|
|
271
|
+
description: 'Agreement id from a prior response. Pass exactly one id field.',
|
|
272
|
+
},
|
|
273
|
+
};
|
|
274
|
+
function openBodyFromArgs(args) {
|
|
275
|
+
const body = {};
|
|
276
|
+
for (const key of ['artifactId', 'chatId', 'taskId', 'agreementId']) {
|
|
277
|
+
const value = args[key];
|
|
278
|
+
if (typeof value === 'string' && value.trim())
|
|
279
|
+
body[key] = value.trim();
|
|
280
|
+
}
|
|
281
|
+
if (typeof args['cursor'] === 'string')
|
|
282
|
+
body.cursor = args['cursor'];
|
|
283
|
+
if (typeof args['after'] === 'string')
|
|
284
|
+
body.after = args['after'];
|
|
285
|
+
if (typeof args['limit'] === 'number')
|
|
286
|
+
body.limit = args['limit'];
|
|
287
|
+
return body;
|
|
288
|
+
}
|
|
289
|
+
function presentOpenResult(result) {
|
|
290
|
+
// Never attach a ready write. An unreadable row already carries
|
|
291
|
+
// access.continuation (owner-decision); this call must not execute it.
|
|
292
|
+
return { ...result, actions: [] };
|
|
293
|
+
}
|
|
294
|
+
export const openCapability = {
|
|
295
|
+
key: 'open',
|
|
296
|
+
names: { sdk: 'open', mcp: 'ziggs_open' },
|
|
297
|
+
title: 'Open a returned resource',
|
|
298
|
+
descriptions: {
|
|
299
|
+
sdk: 'Open an artifact, chat, task, or agreement you were given an id for. Pass exactly one of artifactId, chatId, taskId, agreementId. Do not pick a grant id or reconstruct type/via — the server resolves the read path and rechecks authorization every time. Read-only: this never requests access or records an approval. Reading is not reply, share, delegate, approve, or original-file download. Extraction pending/failed is not an empty document.',
|
|
300
|
+
mcp: 'Open an artifact, chat, task, or agreement from an ordinary returned id (inbox, find, task result). Pass exactly one of artifactId, chatId, taskId, agreementId. Do not call ziggs_grant_list first, do not pick a grant id, and do not reconstruct type/via — the server resolves the path and rechecks every call. A saved id is not authority. Read-only: never requests access or approves. Hidden and unknown look the same; a discoverable-but-unreadable row names an owner-decision, which this call does not execute. Text access is not a file download. Extraction pending/failed is not an empty document.',
|
|
301
|
+
},
|
|
302
|
+
annotation: 'read-only',
|
|
303
|
+
params: {
|
|
304
|
+
...OPEN_ID_PARAMS,
|
|
305
|
+
cursor: { type: 'string', description: 'Opaque cursor from a prior open page' },
|
|
306
|
+
after: { type: 'string', description: 'ISO timestamp for a forward-delta' },
|
|
307
|
+
limit: { type: 'number', description: 'Page size' },
|
|
308
|
+
},
|
|
309
|
+
needsAgentId: true,
|
|
310
|
+
handler: async (args, env) => {
|
|
311
|
+
const creds = fullCreds(env);
|
|
312
|
+
const client = new ContextOpenClient(creds.operatorKey, creds.agentId, env.baseUrl, creds.laneId);
|
|
313
|
+
return presentOpenResult(await client.open(openBodyFromArgs(args)));
|
|
314
|
+
},
|
|
315
|
+
};
|
|
316
|
+
export const accessExplainCapability = {
|
|
317
|
+
key: 'access_explain',
|
|
318
|
+
names: { sdk: 'access_explain', mcp: 'ziggs_access_explain' },
|
|
319
|
+
title: 'Explain access to a resource',
|
|
320
|
+
descriptions: {
|
|
321
|
+
sdk: 'Read-only access explanation for an ordinary returned id. Same one-of artifactId/chatId/taskId/agreementId as open. Says whether you can read, and that reading does not imply reply, share, delegate, approve, or download. Does not return content and does not request or approve anything.',
|
|
322
|
+
mcp: 'Read-only access explanation for an ordinary returned id (exactly one of artifactId, chatId, taskId, agreementId). No grant id. Rechecks authorization. Names the owner-decision route when you cannot read a discoverable resource; this call never executes that request. Hidden and unknown reveal no labels, owners, excerpts, or counts.',
|
|
323
|
+
},
|
|
324
|
+
annotation: 'read-only',
|
|
325
|
+
params: OPEN_ID_PARAMS,
|
|
326
|
+
needsAgentId: true,
|
|
327
|
+
handler: async (args, env) => {
|
|
328
|
+
const creds = fullCreds(env);
|
|
329
|
+
const client = new ContextOpenClient(creds.operatorKey, creds.agentId, env.baseUrl, creds.laneId);
|
|
330
|
+
const result = await client.explain(openBodyFromArgs(args));
|
|
331
|
+
return presentOpenResult(result);
|
|
332
|
+
},
|
|
333
|
+
};
|
|
243
334
|
export const CONTEXT_CAPABILITIES = [
|
|
244
335
|
contextReadCapability,
|
|
336
|
+
openCapability,
|
|
337
|
+
accessExplainCapability,
|
|
245
338
|
contextDelegateCapability,
|
|
246
339
|
contextExpandReachCapability,
|
|
247
340
|
contextDiscoverGrantableCapability,
|
|
248
341
|
];
|
|
342
|
+
export const contextRequestCapability = {
|
|
343
|
+
key: 'context_request',
|
|
344
|
+
names: { sdk: 'context_request', mcp: 'ziggs_context_request' },
|
|
345
|
+
title: 'Ask an owner for artifact access',
|
|
346
|
+
descriptions: {
|
|
347
|
+
sdk: 'Ask a human owner for temporary read-only access to one artifact you were given a reference for. Use your existing chat with that owner. Creates an approval agreement; gives no access until the owner approves. You are the only recipient. After approval, open the original artifact. Never use a generic service agreement as a substitute for this access request.',
|
|
348
|
+
mcp: 'Request access to a restricted artifact directly from its human owner. Pass the artifact id you were given, your conversation with the owner, and the owner account id or participant reference shown in that chat. This creates a pending approval agreement, NOT a grant. No prior grant is needed. The human approves at the agreement link. After approval, ziggs_open the original artifact. Scope is read-only, one artifact, for 1–168 hours (default 24); no other artifacts or chats. Include the intended summary recipient in reason. Keep polling for the decision when asked to wait. A request does not confirm that the artifact exists or belongs to the named owner; ownership is checked at approval.',
|
|
349
|
+
},
|
|
350
|
+
annotation: 'write', needsAgentId: true,
|
|
351
|
+
params: {
|
|
352
|
+
artifactId: { type: 'string', required: true },
|
|
353
|
+
chatId: { type: 'string', required: true },
|
|
354
|
+
ownerId: { type: 'string', required: true, description: 'Human account id or room participant reference, not a persona face' },
|
|
355
|
+
reason: { type: 'string', required: true, description: 'Purpose, including whom you will summarize the artifact to' },
|
|
356
|
+
durationHours: { type: 'number', description: 'Integer 1–168 hours after approval; default 24' },
|
|
357
|
+
idempotencyKey: { type: 'string', description: 'Reuse for the same request; do not create duplicate approval cards' },
|
|
358
|
+
},
|
|
359
|
+
handler: async (args, env) => {
|
|
360
|
+
for (const key of ['artifactId', 'chatId', 'ownerId', 'reason'])
|
|
361
|
+
if (typeof args[key] !== 'string' || !String(args[key]).trim())
|
|
362
|
+
throw new Error(`${key} is required`);
|
|
363
|
+
const durationHours = args.durationHours === undefined ? 24 : Number(args.durationHours);
|
|
364
|
+
if (!Number.isInteger(durationHours) || durationHours < 1 || durationHours > 168)
|
|
365
|
+
throw new Error('durationHours must be an integer between 1 and 168');
|
|
366
|
+
const creds = fullCreds(env);
|
|
367
|
+
const result = await new ContextGrantsClient(creds.operatorKey, creds.agentId, env.baseUrl).requestArtifactAccess(args.artifactId, {
|
|
368
|
+
chatId: args.chatId, ownerId: args.ownerId, reason: args.reason, durationHours,
|
|
369
|
+
}, { idempotencyKey: args.idempotencyKey, laneId: creds.laneId });
|
|
370
|
+
return { ...result, outcome: 'pending', state: 'requested', appUrl: `${(env.webUrl ?? 'https://ziggsai.com').replace(/\/$/, '')}/app/agreements/${encodeURIComponent(result.agreementId)}`, note: 'Waiting for the artifact owner. No access granted yet; open the original artifact only after approval.' };
|
|
371
|
+
},
|
|
372
|
+
};
|
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
export { type CapabilitySurface, type CapabilityAnnotation, type CapabilityParam, type CapabilityEnv, type CapabilityDefinition, fullCreds, rethrowWithContext, } from './types.js';
|
|
2
|
-
export { nextCall, peerPrincipalId, type NextCall, } from './nextCall.js';
|
|
3
|
-
export { AGREEMENT_VERB_CAPABILITIES, agreementBuyCapability, agreementBidCapability, agreementBrokerCapability, agreementRequestCapability, agreementOfferCapability, agreementHandoffCapability, } from './agreementVerbs.js';
|
|
2
|
+
export { nextCall, nextCallsFromUntrustedContent, isStaleAdvertisedAction, peerPrincipalId, isPersonaFace, workContextFromEnv, type NextCall, type NextCallOutcome, type NextCallEffects, type NextCallHold, type NextCallOptions, type WorkContext, } from './nextCall.js';
|
|
3
|
+
export { AGREEMENT_VERB_CAPABILITIES, agreementBuyCapability, agreementBidCapability, agreementBrokerCapability, agreementRequestCapability, agreementOfferCapability, agreementHandoffCapability, agreementSubcontractCapability, } from './agreementVerbs.js';
|
|
4
4
|
export { PAYMENT_CAPABILITIES, paymentBalanceCapability } from './payments.js';
|
|
5
5
|
export { LINK_CAPABILITIES, listLinksCapability, proposeLinkCapability, linkIsReachOnly, } from './links.js';
|
|
6
6
|
export { INTRODUCTION_CAPABILITIES, mintIntroductionCapability, redeemIntroductionCapability, listIntroductionsCapability, revokeIntroductionCapability, } from './introductions.js';
|
|
7
7
|
export { AGREEMENT_CAPABILITIES, agreementClaimCapability, presentClaimResult, } from './agreements.js';
|
|
8
8
|
export { LIST_FIELDS_PARAM, parseListFields, pickListedRow, pickListedRows, } from './listedFields.js';
|
|
9
|
-
export { TASK_CAPABILITIES, listTasksCapability } from './tasks.js';
|
|
9
|
+
export { TASK_CAPABILITIES, listTasksCapability, cancelTaskCapability, presentTaskOutcome, type TaskOutcomeEffects, type TaskOutcomePresentation, } from './tasks.js';
|
|
10
10
|
export { AGREEMENT_PROPOSE_PROVIDER_ID_DESCRIPTION } from './proposeProviderId.js';
|
|
11
11
|
export { MARKETPLACE_CAPABILITIES, marketplaceViewCapability } from './marketplace.js';
|
|
12
12
|
export { GRANTS_CAPABILITIES, listGrantsCapability } from './grants.js';
|
|
13
|
-
export { CONTEXT_CAPABILITIES, contextReadCapability, contextDelegateCapability, contextExpandReachCapability, contextDiscoverGrantableCapability, contextBounds, resolveOrgScopeId, } from './context.js';
|
|
13
|
+
export { CONTEXT_CAPABILITIES, contextReadCapability, openCapability, accessExplainCapability, contextDelegateCapability, contextRequestCapability, contextExpandReachCapability, contextDiscoverGrantableCapability, contextBounds, resolveOrgScopeId, } from './context.js';
|
|
14
14
|
export { CONNECTION_CAPABILITIES, connectionProxyCapability, requestConnectionCapability, } from './connections.js';
|
|
15
15
|
export { DISCOVERY_CAPABILITIES, agentSearchCapability, agentGetCapability, } from './discovery.js';
|
|
16
|
-
export { ARTIFACT_CAPABILITIES, recordArtifactCapability, listArtifactsCapability, shareArtifactCapability, attachArtifactCapability, uploadArtifactUrlCapability, completeArtifactFileCapability, downloadArtifactCapability, reextractArtifactCapability, } from './artifacts.js';
|
|
17
|
-
export { CHAT_CAPABILITIES, openConversationCapability } from './chat.js';
|
|
16
|
+
export { ARTIFACT_CAPABILITIES, recordArtifactCapability, listArtifactsCapability, findArtifactsCapability, type UnsearchedContext, shareArtifactCapability, attachArtifactCapability, uploadArtifactUrlCapability, completeArtifactFileCapability, downloadArtifactCapability, reextractArtifactCapability, } from './artifacts.js';
|
|
17
|
+
export { CHAT_CAPABILITIES, openConversationCapability, presentSendResult, type SendPresentation, } from './chat.js';
|
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
export { fullCreds, rethrowWithContext, } from './types.js';
|
|
2
|
-
export { nextCall, peerPrincipalId, } from './nextCall.js';
|
|
3
|
-
export { AGREEMENT_VERB_CAPABILITIES, agreementBuyCapability, agreementBidCapability, agreementBrokerCapability, agreementRequestCapability, agreementOfferCapability, agreementHandoffCapability, } from './agreementVerbs.js';
|
|
2
|
+
export { nextCall, nextCallsFromUntrustedContent, isStaleAdvertisedAction, peerPrincipalId, isPersonaFace, workContextFromEnv, } from './nextCall.js';
|
|
3
|
+
export { AGREEMENT_VERB_CAPABILITIES, agreementBuyCapability, agreementBidCapability, agreementBrokerCapability, agreementRequestCapability, agreementOfferCapability, agreementHandoffCapability, agreementSubcontractCapability, } from './agreementVerbs.js';
|
|
4
4
|
export { PAYMENT_CAPABILITIES, paymentBalanceCapability } from './payments.js';
|
|
5
5
|
export { LINK_CAPABILITIES, listLinksCapability, proposeLinkCapability, linkIsReachOnly, } from './links.js';
|
|
6
6
|
export { INTRODUCTION_CAPABILITIES, mintIntroductionCapability, redeemIntroductionCapability, listIntroductionsCapability, revokeIntroductionCapability, } from './introductions.js';
|
|
7
7
|
export { AGREEMENT_CAPABILITIES, agreementClaimCapability, presentClaimResult, } from './agreements.js';
|
|
8
8
|
export { LIST_FIELDS_PARAM, parseListFields, pickListedRow, pickListedRows, } from './listedFields.js';
|
|
9
|
-
export { TASK_CAPABILITIES, listTasksCapability } from './tasks.js';
|
|
9
|
+
export { TASK_CAPABILITIES, listTasksCapability, cancelTaskCapability, presentTaskOutcome, } from './tasks.js';
|
|
10
10
|
export { AGREEMENT_PROPOSE_PROVIDER_ID_DESCRIPTION } from './proposeProviderId.js';
|
|
11
11
|
export { MARKETPLACE_CAPABILITIES, marketplaceViewCapability } from './marketplace.js';
|
|
12
12
|
export { GRANTS_CAPABILITIES, listGrantsCapability } from './grants.js';
|
|
13
|
-
export { CONTEXT_CAPABILITIES, contextReadCapability, contextDelegateCapability, contextExpandReachCapability, contextDiscoverGrantableCapability, contextBounds, resolveOrgScopeId, } from './context.js';
|
|
13
|
+
export { CONTEXT_CAPABILITIES, contextReadCapability, openCapability, accessExplainCapability, contextDelegateCapability, contextRequestCapability, contextExpandReachCapability, contextDiscoverGrantableCapability, contextBounds, resolveOrgScopeId, } from './context.js';
|
|
14
14
|
export { CONNECTION_CAPABILITIES, connectionProxyCapability, requestConnectionCapability, } from './connections.js';
|
|
15
15
|
export { DISCOVERY_CAPABILITIES, agentSearchCapability, agentGetCapability, } from './discovery.js';
|
|
16
|
-
export { ARTIFACT_CAPABILITIES, recordArtifactCapability, listArtifactsCapability, shareArtifactCapability, attachArtifactCapability, uploadArtifactUrlCapability, completeArtifactFileCapability, downloadArtifactCapability, reextractArtifactCapability, } from './artifacts.js';
|
|
17
|
-
export { CHAT_CAPABILITIES, openConversationCapability } from './chat.js';
|
|
16
|
+
export { ARTIFACT_CAPABILITIES, recordArtifactCapability, listArtifactsCapability, findArtifactsCapability, shareArtifactCapability, attachArtifactCapability, uploadArtifactUrlCapability, completeArtifactFileCapability, downloadArtifactCapability, reextractArtifactCapability, } from './artifacts.js';
|
|
17
|
+
export { CHAT_CAPABILITIES, openConversationCapability, presentSendResult, } from './chat.js';
|
|
@@ -79,6 +79,7 @@ export const redeemIntroductionCapability = {
|
|
|
79
79
|
const staged = intro.outcome === 'link_pending';
|
|
80
80
|
return {
|
|
81
81
|
introduction: intro,
|
|
82
|
+
outcome: staged ? 'pending' : 'ok',
|
|
82
83
|
message: staged
|
|
83
84
|
? `Redeemed. A pending link with org ${intro.from.orgId} (${intro.from.agentId ?? 'no agent id'}) is staged (${intro.agreementId}). The display name they claimed is self-chosen and unverified. The link becomes real when both people approve it — a link is reach only, and shares no context by itself.`
|
|
84
85
|
: intro.outcome === 'already_teammates'
|
|
@@ -88,6 +89,9 @@ export const redeemIntroductionCapability = {
|
|
|
88
89
|
// relationship exists, so the next move is simply to talk. Leaving the
|
|
89
90
|
// plan empty there read as "nothing to do" on the branch a returning
|
|
90
91
|
// counterparty is most likely to land on.
|
|
92
|
+
//
|
|
93
|
+
// A staged redeem is not a live hire: do not advertise a ready chat_open
|
|
94
|
+
// or a ready agreement_respond the agent can run. The human signs.
|
|
91
95
|
readPlan: !staged
|
|
92
96
|
? intro.counterparty?.agentId
|
|
93
97
|
? [
|
|
@@ -95,16 +99,7 @@ export const redeemIntroductionCapability = {
|
|
|
95
99
|
]
|
|
96
100
|
: []
|
|
97
101
|
: [
|
|
98
|
-
nextCall(env, 'agreement_respond', intro.agreementId ? { agreementId: intro.agreementId } : undefined, 'the link is pending — your human must approve it; do not sign on their behalf'),
|
|
99
|
-
// The minter's AGENT, not their principal. A link's party principal
|
|
100
|
-
// can be a persona face, which the chat rail refuses as an address
|
|
101
|
-
// ("a face is display state and names no single party") — so the
|
|
102
|
-
// door to that person is the agent that carried the introduction.
|
|
103
|
-
...(intro.from.agentId
|
|
104
|
-
? [
|
|
105
|
-
nextCall(env, 'chat_open', { participantId: intro.from.agentId }, 'once the link is live, this is the door to the agent that introduced itself'),
|
|
106
|
-
]
|
|
107
|
-
: []),
|
|
102
|
+
nextCall(env, 'agreement_respond', intro.agreementId ? { agreementId: intro.agreementId } : undefined, 'the link is pending — your human must approve it; do not sign on their behalf', { hold: 'human_approval' }),
|
|
108
103
|
],
|
|
109
104
|
};
|
|
110
105
|
},
|
|
@@ -1,14 +1,16 @@
|
|
|
1
|
+
import { marketplaceFormation } from '../engagementGuide.js';
|
|
1
2
|
import { pullOffers, pullRequests } from '../http/MarketplaceClient.js';
|
|
2
3
|
import { fullCreds } from './types.js';
|
|
3
4
|
import { nextCall } from './nextCall.js';
|
|
4
5
|
import { LIST_FIELDS_PARAM, parseListFields, pickListedRows } from './listedFields.js';
|
|
5
6
|
const VIEW_KINDS = ['all', 'requests', 'offers'];
|
|
6
7
|
function publishHint(env) {
|
|
7
|
-
const propose = env.surface === 'mcp' ? 'ziggs_agreement_request' : 'agreement_request';
|
|
8
8
|
const claim = env.surface === 'mcp' ? 'ziggs_agreement_claim' : 'agreement_claim';
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
9
|
+
const publish = env.surface === 'mcp'
|
|
10
|
+
? 'Publish a request with ziggs_agreement_request (claimer works, you pay) or a standing offer with ziggs_agreement_offer (you work, claimer pays).'
|
|
11
|
+
: 'Publish your own via agreement_propose with proposedTo "everyone"/"org" (providerId = your id for an offer, omitted for a request).';
|
|
12
|
+
return (`Reuse an active agreement that already covers the work. Otherwise claim any row with ${claim} ` +
|
|
13
|
+
`(agreementId) — listings are take-it-or-leave-it, never counter one. ${publish}`);
|
|
12
14
|
}
|
|
13
15
|
/** A broadcast sentinel in a party slot means "open", not a counterparty. */
|
|
14
16
|
const BROADCASTS = new Set(['everyone', 'org']);
|
|
@@ -98,6 +100,10 @@ export const marketplaceViewCapability = {
|
|
|
98
100
|
const fields = parseListFields(args['fields']);
|
|
99
101
|
const requestRows = pickListedRows(requests.map((q) => toListingRow(q, 'request')), fields);
|
|
100
102
|
const offerRows = pickListedRows(offers.map((o) => toListingRow(o, 'offer')), fields);
|
|
103
|
+
const listingAgreementIds = [...requests, ...offers]
|
|
104
|
+
.map((row) => row.agreementId)
|
|
105
|
+
.filter((id) => typeof id === 'string' && id.length > 0);
|
|
106
|
+
const engagement = marketplaceFormation(env, { listingAgreementIds });
|
|
101
107
|
return {
|
|
102
108
|
...(kind !== 'offers'
|
|
103
109
|
? { requests: requestRows, requestCount: requests.length }
|
|
@@ -105,13 +111,16 @@ export const marketplaceViewCapability = {
|
|
|
105
111
|
...(kind !== 'requests'
|
|
106
112
|
? { offers: offerRows, offerCount: offers.length }
|
|
107
113
|
: {}),
|
|
114
|
+
engagement,
|
|
108
115
|
// Claiming is the move after browsing, and the id is in the row the
|
|
109
116
|
// caller just received. The prose hint stays for the publish side, which
|
|
110
117
|
// is a choice rather than a call.
|
|
111
118
|
readPlan: [
|
|
112
|
-
...(
|
|
119
|
+
...(listingAgreementIds.length
|
|
113
120
|
? [
|
|
114
|
-
nextCall(env, 'agreement_claim',
|
|
121
|
+
nextCall(env, 'agreement_claim', listingAgreementIds.length === 1
|
|
122
|
+
? { agreementId: listingAgreementIds[0] }
|
|
123
|
+
: undefined, 'claim a listing from this view by passing its agreementId — listings are take-it-or-leave-it, never countered'),
|
|
115
124
|
]
|
|
116
125
|
: []),
|
|
117
126
|
],
|
|
@@ -1,28 +1,72 @@
|
|
|
1
1
|
import type { AgreementParties } from '../types.js';
|
|
2
|
-
import type { CapabilityEnv } from './types.js';
|
|
2
|
+
import type { CapabilityDefinition, CapabilityEnv } from './types.js';
|
|
3
3
|
/**
|
|
4
|
-
* One
|
|
4
|
+
* One next step: the tool the calling surface registers, any args already
|
|
5
|
+
* known, and why.
|
|
5
6
|
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
* response body it just received.
|
|
7
|
+
* Ready means a caller can run it verbatim. Incomplete means a required
|
|
8
|
+
* argument is missing or an address field is not an address — the suggestion
|
|
9
|
+
* still names the tool, and `missing` says what has to be filled first.
|
|
10
10
|
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
* still right when the next move is not a call at all (a human has to decide
|
|
15
|
-
* something); it is wrong when the call and its arguments are both already
|
|
16
|
-
* known here.
|
|
11
|
+
* `http` is the same invocation on the published HTTP surface, bound from the
|
|
12
|
+
* capability key rather than a second implementation. Profile is not a field
|
|
13
|
+
* here: assistant vs worker is not a transport.
|
|
17
14
|
*/
|
|
18
15
|
export interface NextCall {
|
|
19
16
|
/** Registered tool name on the calling surface. */
|
|
20
17
|
tool: string;
|
|
21
18
|
/** Arguments, filled in from what the response already carries. */
|
|
22
19
|
args?: Record<string, unknown>;
|
|
23
|
-
/** One clause: what running this achieves. */
|
|
20
|
+
/** One clause: what running this achieves, or what is still missing. */
|
|
24
21
|
why: string;
|
|
22
|
+
/** True only when every required argument is present and addressable. */
|
|
23
|
+
ready: boolean;
|
|
24
|
+
/** Required argument names that are absent or not an address. */
|
|
25
|
+
missing?: readonly string[];
|
|
26
|
+
/** Published HTTP method/path for the same capability, when we have one. */
|
|
27
|
+
http?: {
|
|
28
|
+
method: string;
|
|
29
|
+
path: string;
|
|
30
|
+
};
|
|
31
|
+
/**
|
|
32
|
+
* Whether this step is a finished action, a parked human decision, a
|
|
33
|
+
* half-filled suggestion, or something this surface cannot run.
|
|
34
|
+
*/
|
|
35
|
+
outcome: NextCallOutcome;
|
|
36
|
+
/** Material effects of running this, when the verb has any. */
|
|
37
|
+
effects?: NextCallEffects;
|
|
38
|
+
/** Who would run it, from the env — never a caller-chosen principal. */
|
|
39
|
+
workContext?: WorkContext;
|
|
40
|
+
/** Why a complete-looking call is still not runnable. */
|
|
41
|
+
hold?: NextCallHold;
|
|
25
42
|
}
|
|
43
|
+
export type NextCallOutcome = 'ok' | 'pending' | 'partial' | 'unavailable';
|
|
44
|
+
export type NextCallHold = 'human_approval' | 'relationship';
|
|
45
|
+
export interface NextCallEffects {
|
|
46
|
+
disclosure?: string;
|
|
47
|
+
commitment?: string;
|
|
48
|
+
metering?: string;
|
|
49
|
+
relationship?: string;
|
|
50
|
+
}
|
|
51
|
+
export interface WorkContext {
|
|
52
|
+
actingAgentId?: string;
|
|
53
|
+
laneId?: string;
|
|
54
|
+
}
|
|
55
|
+
export interface NextCallOptions {
|
|
56
|
+
/** Live capability schema — required args come from here when present. */
|
|
57
|
+
definition?: Pick<CapabilityDefinition, 'params'>;
|
|
58
|
+
outcome?: NextCallOutcome;
|
|
59
|
+
effects?: NextCallEffects;
|
|
60
|
+
/**
|
|
61
|
+
* Args may be complete but the caller must not run it: a human signs, or
|
|
62
|
+
* a relationship is not live yet.
|
|
63
|
+
*/
|
|
64
|
+
hold?: NextCallHold;
|
|
65
|
+
}
|
|
66
|
+
/** A persona face (`psn_…`) is display state, not a message address. */
|
|
67
|
+
export declare function isPersonaFace(id: unknown): boolean;
|
|
68
|
+
/** Acting agent and lane from the env. Never a caller-chosen principal. */
|
|
69
|
+
export declare function workContextFromEnv(env: CapabilityEnv): WorkContext | undefined;
|
|
26
70
|
/**
|
|
27
71
|
* Build a next step naming the tool as the calling surface registers it.
|
|
28
72
|
*
|
|
@@ -31,7 +75,21 @@ export interface NextCall {
|
|
|
31
75
|
* the 31 capability definitions follows that one rule, so the key is enough and
|
|
32
76
|
* a caller cannot accidentally emit a name the surface does not have.
|
|
33
77
|
*/
|
|
34
|
-
export declare function nextCall(env: CapabilityEnv, capabilityKey: string, args: Record<string, unknown> | undefined, why: string): NextCall;
|
|
78
|
+
export declare function nextCall(env: CapabilityEnv, capabilityKey: string, args: Record<string, unknown> | undefined, why: string, opts?: NextCallOptions): NextCall;
|
|
79
|
+
/**
|
|
80
|
+
* E23: messages, artifacts, and agreement prose are data. They cannot mint
|
|
81
|
+
* a server action. The only legal parse is "none".
|
|
82
|
+
*/
|
|
83
|
+
export declare function nextCallsFromUntrustedContent(_content: unknown): NextCall[];
|
|
84
|
+
/**
|
|
85
|
+
* E22: a next call advertised against an earlier snapshot is stale when the
|
|
86
|
+
* row is no longer in the state that action assumed. Execution still has to
|
|
87
|
+
* hit the existing precondition (claim 400, respond refuse) — this is the
|
|
88
|
+
* client-side invalidation so a caller does not treat the suggestion as live.
|
|
89
|
+
*/
|
|
90
|
+
export declare function isStaleAdvertisedAction(advertised: Pick<NextCall, 'tool' | 'args'>, current: {
|
|
91
|
+
status?: string | null;
|
|
92
|
+
}): boolean;
|
|
35
93
|
/**
|
|
36
94
|
* The other PRINCIPAL in a two-party agreement, from the perspective of
|
|
37
95
|
* `selfId`.
|