@ziggs-ai/api-client 0.28.1 → 0.30.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/agreements.d.ts +3 -2
- package/dist/capabilities/agreements.js +30 -5
- package/dist/capabilities/chat.js +13 -9
- package/dist/capabilities/context.js +14 -6
- package/dist/capabilities/index.d.ts +1 -0
- package/dist/capabilities/index.js +1 -0
- package/dist/capabilities/nextCall.d.ts +4 -2
- package/dist/capabilities/resourceActions.d.ts +3 -0
- package/dist/capabilities/resourceActions.js +9 -0
- package/dist/http/AgreementClient.d.ts +23 -2
- package/dist/http/AgreementClient.js +9 -4
- package/dist/http/ContextOpenClient.d.ts +19 -8
- package/dist/http/ContextReadClient.d.ts +2 -0
- package/dist/http/agreementFlows.d.ts +2 -1
- package/dist/http/agreementFlows.js +2 -2
- package/dist/http/index.d.ts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/types.d.ts +5 -0
- package/package.json +1 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { ClaimedKind } from '../http/AgreementClient.js';
|
|
1
|
+
import type { ClaimedKind, ClaimRoom } from '../http/AgreementClient.js';
|
|
2
2
|
import type { Agreement } from '../types.js';
|
|
3
3
|
import { type NextCallOutcome, type WorkContext } from './nextCall.js';
|
|
4
4
|
import { type CapabilityDefinition, type CapabilityEnv } from './types.js';
|
|
@@ -7,12 +7,13 @@ import { type CapabilityDefinition, type CapabilityEnv } from './types.js';
|
|
|
7
7
|
* return `{agreement, kind}` while MCP returned `{status, kind, message,
|
|
8
8
|
* agreement}` — same HTTP call, two answers.
|
|
9
9
|
*/
|
|
10
|
-
export declare function presentClaimResult(agreement: Agreement, kind: ClaimedKind, env: CapabilityEnv): {
|
|
10
|
+
export declare function presentClaimResult(agreement: Agreement, kind: ClaimedKind, env: CapabilityEnv, room?: ClaimRoom): {
|
|
11
11
|
status: string;
|
|
12
12
|
outcome: NextCallOutcome;
|
|
13
13
|
kind: ClaimedKind;
|
|
14
14
|
message: string;
|
|
15
15
|
agreement: Agreement;
|
|
16
|
+
room?: ClaimRoom;
|
|
16
17
|
workContext?: WorkContext;
|
|
17
18
|
};
|
|
18
19
|
/**
|
|
@@ -16,7 +16,28 @@ function claimedWhat(kind) {
|
|
|
16
16
|
* return `{agreement, kind}` while MCP returned `{status, kind, message,
|
|
17
17
|
* agreement}` — same HTTP call, two answers.
|
|
18
18
|
*/
|
|
19
|
-
export function presentClaimResult(agreement, kind, env) {
|
|
19
|
+
export function presentClaimResult(agreement, kind, env, room) {
|
|
20
|
+
const out = presentClaim(agreement, kind, env);
|
|
21
|
+
if (!room)
|
|
22
|
+
return out;
|
|
23
|
+
return { ...out, message: `${out.message} ${roomWords(room)}`, room };
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* The room the hire was made in, in words. "Ready" is said only
|
|
27
|
+
* when the agent is in; a failure says the hire and its charge stand and names
|
|
28
|
+
* the call that resumes admission.
|
|
29
|
+
*/
|
|
30
|
+
function roomWords(room) {
|
|
31
|
+
if (room.status === 'ready') {
|
|
32
|
+
return `The agent is in room ${room.chatId} now.`;
|
|
33
|
+
}
|
|
34
|
+
if (room.status === 'awaiting_approval') {
|
|
35
|
+
return `Once it is approved, the agent joins room ${room.chatId} with no further step; the room shows the proposal to the person who can answer it.`;
|
|
36
|
+
}
|
|
37
|
+
const retry = room.recovery ? ` Resume with ${room.recovery.method} ${room.recovery.path}.` : '';
|
|
38
|
+
return `The hire is active, but the agent is not in room ${room.chatId} yet${room.message ? ` (${room.message})` : ''}. Do not claim again.${retry}`;
|
|
39
|
+
}
|
|
40
|
+
function presentClaim(agreement, kind, env) {
|
|
20
41
|
const workContext = workContextFromEnv(env);
|
|
21
42
|
if (kind === 'link') {
|
|
22
43
|
return {
|
|
@@ -68,8 +89,8 @@ export const agreementClaimCapability = {
|
|
|
68
89
|
names: { sdk: 'agreement_claim', mcp: 'ziggs_agreement_claim' },
|
|
69
90
|
title: 'Claim a posted agreement',
|
|
70
91
|
descriptions: {
|
|
71
|
-
sdk: 'Claim an open broadcast agreement by id — the DEFAULT way to engage: terms are already posted, consent is the claim and there are no negotiation turns. Claims a request (you do the work, the publisher pays), a standing offer (you buy, the publisher works), a hand-off (providerPinned: the publisher\'s hired agent works FOR you — you become the customer, and the payer when it is priced), or a link invite (bilateral trust forms immediately). You become the open party. It activates at once when you can consent for your own side — an agent claiming help for a job it is already doing should name that job with mandateAgreementId; without it the formation waits on your human before anything can be spawned under it. A hand-off is claimable only after its provider has accepted (409 until then). Find requests/offers with marketplace_view; listings are take-it-or-leave-it — never counter one. Direct proposals are approved with agreement_respond instead, not claimed.',
|
|
72
|
-
mcp: 'Claim an open broadcast agreement by id — the DEFAULT way to engage: terms are already posted, consent is the claim and there are no negotiation turns. Claims a request (you do the work, the publisher pays), a standing offer (you buy, the publisher works), a hand-off (providerPinned: the publisher\'s hired agent works FOR you — you become the customer, and the payer when it is priced), or a link invite (bilateral trust forms immediately). You become the open party. It activates at once when you can consent for your own side — an agent claiming help for a job it is already doing should name that job with mandateAgreementId; without it the formation waits on your human before anything can be spawned under it. A hand-off is claimable only after its provider has accepted (409 until then). Find requests/offers with ziggs_marketplace_view; listings are take-it-or-leave-it — never counter one. Direct proposals are approved with ziggs_agreement_respond instead, not claimed. You cannot claim your own broadcast.',
|
|
92
|
+
sdk: 'Claim an open broadcast agreement by id — the DEFAULT way to engage: terms are already posted, consent is the claim and there are no negotiation turns. Claims a request (you do the work, the publisher pays), a standing offer (you buy, the publisher works), a hand-off (providerPinned: the publisher\'s hired agent works FOR you — you become the customer, and the payer when it is priced), or a link invite (bilateral trust forms immediately). You become the open party. It activates at once when you can consent for your own side — an agent claiming help for a job it is already doing should name that job with mandateAgreementId; without it the formation waits on your human before anything can be spawned under it. A hand-off is claimable only after its provider has accepted (409 until then). Find requests/offers with marketplace_view; listings are take-it-or-leave-it — never counter one. Direct proposals are approved with agreement_respond instead, not claimed. To hire an agent into a room, claim its listing with that room\'s chatId.',
|
|
93
|
+
mcp: 'Claim an open broadcast agreement by id — the DEFAULT way to engage: terms are already posted, consent is the claim and there are no negotiation turns. Claims a request (you do the work, the publisher pays), a standing offer (you buy, the publisher works), a hand-off (providerPinned: the publisher\'s hired agent works FOR you — you become the customer, and the payer when it is priced), or a link invite (bilateral trust forms immediately). You become the open party. It activates at once when you can consent for your own side — an agent claiming help for a job it is already doing should name that job with mandateAgreementId; without it the formation waits on your human before anything can be spawned under it. A hand-off is claimable only after its provider has accepted (409 until then). Find requests/offers with ziggs_marketplace_view; listings are take-it-or-leave-it — never counter one. Direct proposals are approved with ziggs_agreement_respond instead, not claimed. You cannot claim your own broadcast. To hire an agent into a room, claim its listing with that room\'s chatId.',
|
|
73
94
|
},
|
|
74
95
|
annotation: 'write',
|
|
75
96
|
params: {
|
|
@@ -88,12 +109,16 @@ export const agreementClaimCapability = {
|
|
|
88
109
|
type: 'string',
|
|
89
110
|
description: 'The active agreement whose work this claim is part of — the job you are doing. Claiming for a job your human already approved needs no second approval from them, but you have to name the job: the server checks you are a party to it, and a wrong name simply earns nothing. Leave it out when the claim belongs to no job.',
|
|
90
111
|
},
|
|
112
|
+
chatId: {
|
|
113
|
+
type: 'string',
|
|
114
|
+
description: 'The room this hire is for — only when claiming an agent\'s listing. When the hire activates the agent joins that exact room, with no invitation and no second approval; if it waits for a yes, the room shows it as a proposal. You must be in the room. The answer\'s room.status says where it stands.',
|
|
115
|
+
},
|
|
91
116
|
},
|
|
92
117
|
needsAgentId: true,
|
|
93
118
|
handler: async (args, env) => {
|
|
94
119
|
const declaredMandate = args['mandateAgreementId'];
|
|
95
|
-
const { agreement, kind } = await claimOpenAgreement(args['agreementId'], fullCreds(env), { ...(typeof declaredMandate === 'string' && declaredMandate ? { mandateAgreementId: declaredMandate } : {}), ...(typeof args['parentAgreementId'] === 'string' ? { parentAgreementId: args['parentAgreementId'] } : {}) });
|
|
96
|
-
return presentClaimResult(agreement, kind, env);
|
|
120
|
+
const { agreement, kind, room } = await claimOpenAgreement(args['agreementId'], fullCreds(env), { ...(typeof declaredMandate === 'string' && declaredMandate ? { mandateAgreementId: declaredMandate } : {}), ...(typeof args['parentAgreementId'] === 'string' ? { parentAgreementId: args['parentAgreementId'] } : {}), ...(typeof args['chatId'] === 'string' && args['chatId'] ? { chatId: args['chatId'] } : {}) });
|
|
121
|
+
return presentClaimResult(agreement, kind, env, room);
|
|
97
122
|
},
|
|
98
123
|
};
|
|
99
124
|
export const AGREEMENT_CAPABILITIES = [agreementClaimCapability];
|
|
@@ -54,8 +54,8 @@ export const openConversationCapability = {
|
|
|
54
54
|
names: { sdk: 'chat_open', mcp: 'ziggs_chat_open' },
|
|
55
55
|
title: 'Start or reuse a conversation',
|
|
56
56
|
descriptions: {
|
|
57
|
-
sdk: 'Open a conversation or explicitly invite people to a room. participantId opens/reuses the acting agent’s pair conversation with one person or agent; newChat opens a separate subject. participantIds creates a separate group with the acting caller and those people; include a stable idempotencyKey for retries. chatId plus participantIds invites people into that exact room, requiring room access and admission authority. Every person needs a valid contact basis: shared organization membership, a link, or an applicable agreement. Each participant keeps their own agent and work relationships; opening a group selects no service agreement. Group creation never expands an existing private DM. Invited teammates read from admission onward.
|
|
58
|
-
mcp: 'Open a conversation or explicitly invite people to a room. participantId opens/reuses the acting agent’s pair conversation with one person or agent; newChat opens a separate subject. participantIds creates a separate group with the acting caller and those people; include a stable idempotencyKey for retries. chatId plus participantIds invites people into that exact room, requiring room access and admission authority. Every person needs a valid contact basis: shared organization membership, a link, or an applicable agreement. Each participant keeps their own agent and work relationships; opening a group selects no service agreement. Group creation never expands an existing private DM. Invited teammates read from admission onward.
|
|
57
|
+
sdk: 'Open a conversation or explicitly invite people to a room. participantId opens/reuses the acting agent’s pair conversation with one person or agent; newChat opens a separate subject. participantIds creates a separate group with the acting caller and those people; include a stable idempotencyKey for retries. chatId plus participantIds invites people into that exact room, requiring room access and admission authority. Every person needs a valid contact basis: shared organization membership, a link, or an applicable agreement. Each participant keeps their own agent and work relationships; opening a group selects no service agreement. Group creation never expands an existing private DM. Invited teammates read from admission onward. participantIds may name agents, when creating a group or inviting into one: each must be reachable (your own, one of your company, published, or already engaged). An agent you add joins at once if your person gave you approval authority; otherwise it is a proposal in the room, and the first person in the room to say yes admits it. The result lists each id as added, already-here or pending. To bring in an agent you would hire, claim its listing with the room\'s chatId instead. Your own missing seat is asked for with access_request. Reach another person through their user id, not an unpublished agent of theirs. If you cannot reach someone your person knows, ask your person to introduce you in a room. Opening does not send a message; chat_send must name its intended receiverId to guarantee a target. To list accessible rooms, use grant_list with scopeKind ["chat"].',
|
|
58
|
+
mcp: 'Open a conversation or explicitly invite people to a room. participantId opens/reuses the acting agent’s pair conversation with one person or agent; newChat opens a separate subject. participantIds creates a separate group with the acting caller and those people; include a stable idempotencyKey for retries. chatId plus participantIds invites people into that exact room, requiring room access and admission authority. Every person needs a valid contact basis: shared organization membership, a link, or an applicable agreement. Each participant keeps their own agent and work relationships; opening a group selects no service agreement. Group creation never expands an existing private DM. Invited teammates read from admission onward. participantIds may name agents, when creating a group or inviting into one: each must be reachable (your own, one of your company, published, or already engaged). An agent you add joins at once if your person gave you approval authority; otherwise it is a proposal in the room, and the first person in the room to say yes admits it. The result lists each id as added, already-here or pending. To bring in an agent you would hire, claim its listing with the room\'s chatId instead. Your own missing seat is asked for with ziggs_access_request. Reach another person through their user id, not an unpublished agent of theirs. For missing access to a known room, use ziggs_access_request; opening another room does not recover its history. Opening does not send a message; ziggs_chat_send must name its intended receiverId to guarantee a target.',
|
|
59
59
|
},
|
|
60
60
|
annotation: 'write',
|
|
61
61
|
params: {
|
|
@@ -63,7 +63,7 @@ export const openConversationCapability = {
|
|
|
63
63
|
type: 'string',
|
|
64
64
|
description: 'Known user or agent id from search, a directory, a chat, or an agreement. For a teammate or a linked person, their user id, not an agent of theirs. No existing chat is required; do not guess ids.',
|
|
65
65
|
},
|
|
66
|
-
participantIds: { type: 'array', items: { type: 'string' }, description: '1–20 known ids.
|
|
66
|
+
participantIds: { type: 'array', items: { type: 'string' }, description: '1–20 known ids. With or without chatId, people and agents; an agent without your approval authority waits for one person in the room to say yes. Use instead of participantId. Each invitation is authorized separately.' },
|
|
67
67
|
chatId: { type: 'string', description: 'Existing room to invite participantIds into. Never creates another room. Omit creation options and agreementId.' },
|
|
68
68
|
idempotencyKey: { type: 'string', description: 'Required for group creation: a unique key for this conversation, reused unchanged on retries. A different participant set needs a new key.' },
|
|
69
69
|
name: { type: 'string', description: 'Name for a new group, 1–80 characters. Pair rooms and team channels take no name. A retry of the same idempotencyKey keeps the first name. Rename later is PATCH /chats/:chatId by someone who can admit people.' },
|
|
@@ -120,13 +120,17 @@ export const openConversationCapability = {
|
|
|
120
120
|
// withheld it — worse than silence, because the agent cannot even tell
|
|
121
121
|
// there is something to look up. A backend too old to report it keeps the
|
|
122
122
|
// old both-cases wording, and `reused` is simply absent from the result.
|
|
123
|
+
// A new group that named agents reports each of them too.
|
|
124
|
+
const created = reused === false ? 'Created a new conversation with the named participants, so there is no history to catch up on.' : null;
|
|
123
125
|
const outcomeNote = args.chatId
|
|
124
126
|
? inviteNote(invited)
|
|
125
|
-
:
|
|
126
|
-
?
|
|
127
|
-
: reused ===
|
|
128
|
-
? '
|
|
129
|
-
:
|
|
127
|
+
: created && invited?.length
|
|
128
|
+
? `${created} ${inviteNote(invited)}`
|
|
129
|
+
: reused === true
|
|
130
|
+
? 'Reused the conversation you already had with the named participants, so it may already hold history — read it before you speak.'
|
|
131
|
+
: reused === false
|
|
132
|
+
? 'Created a new conversation with the named participants, so there is no history to catch up on.'
|
|
133
|
+
: 'Conversation is open (or reused).';
|
|
130
134
|
return {
|
|
131
135
|
chatId,
|
|
132
136
|
actingAgentId: fullCreds(env).agentId,
|
|
@@ -149,7 +153,7 @@ function inviteNote(invited) {
|
|
|
149
153
|
if (ids('already-here').length)
|
|
150
154
|
parts.push(`Already in the room: ${ids('already-here').join(', ')}.`);
|
|
151
155
|
if (ids('pending').length) {
|
|
152
|
-
parts.push(`
|
|
156
|
+
parts.push(`Proposed in the room, waiting for one person there to say yes: ${ids('pending').join(', ')}. The first answer decides; the agent cannot read or write here until then, and asking again does not make a second request.`);
|
|
153
157
|
}
|
|
154
158
|
return `${parts.join(' ')} Invited people read from now on.`;
|
|
155
159
|
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { presentResourceActions } from './resourceActions.js';
|
|
1
2
|
import { ContextReadClient, CONTEXT_READ_TYPES, CONTEXT_READ_VIA, parseVia, viaHint, } from '../http/ContextReadClient.js';
|
|
2
3
|
import { ContextOpenClient } from '../http/ContextOpenClient.js';
|
|
3
4
|
import { ContextGrantsClient, } from '../http/ContextGrantsClient.js';
|
|
@@ -306,9 +307,16 @@ function presentOpenResult(result, env) {
|
|
|
306
307
|
});
|
|
307
308
|
return {
|
|
308
309
|
...result,
|
|
309
|
-
actions: result.
|
|
310
|
+
actions: result.actions
|
|
311
|
+
? [...presentResourceActions(result.actions, env.surface),
|
|
312
|
+
...resumeActions.map(a => ({ ...a, action: 'resume', state: 'not_evaluated' }))]
|
|
313
|
+
: result.access.continuation?.request
|
|
314
|
+
? [requestAccessAction(result.access.continuation.request, env)]
|
|
315
|
+
: result.ref.kind === 'artifact' && result.outcome === 'unreadable'
|
|
316
|
+
? [requestAccessAction({ scopeKind: 'artifact', scopeId: result.ref.id, permission: 'read', durationHours: 24 }, env)]
|
|
317
|
+
: resumeActions,
|
|
310
318
|
actingAgentId: fullCreds(env).agentId,
|
|
311
|
-
...(result.ref.kind === 'artifact' && result.outcome !== 'ok' ? {
|
|
319
|
+
...(!result.actions && result.ref.kind === 'artifact' && result.outcome !== 'ok' ? {
|
|
312
320
|
requestAccessHint: `If a source you already read supplied this artifact reference and its human owner, ${requestTool} scopeKind=artifact can ask that owner for temporary read access without a prior grant. It needs a conversation with the owner; ${chatTool} can open or reuse one, subject to authorization. Discover the request tool's schema before calling it. This response does not confirm existence or ownership. A request grants no access until the human owner approves.`,
|
|
313
321
|
} : {}),
|
|
314
322
|
};
|
|
@@ -318,8 +326,8 @@ export const openCapability = {
|
|
|
318
326
|
names: { sdk: 'open', mcp: 'ziggs_open' },
|
|
319
327
|
title: 'Open a returned resource',
|
|
320
328
|
descriptions: {
|
|
321
|
-
sdk: '
|
|
322
|
-
mcp: '
|
|
329
|
+
sdk: 'Read a returned resource: pass exactly one of artifactId, chatId, taskId, agreementId. The backend resolves access and returns scoped actions with required inputs and recovery calls. Opening executes none of those actions. Extraction pending/failed is not an empty document.',
|
|
330
|
+
mcp: 'Read a returned artifact, chat, task, or agreement: pass exactly one corresponding id. No preliminary grant lookup. The backend returns scoped actions, required inputs and recovery calls; this read executes none of them. Hidden and unknown look the same. Extraction pending/failed is not an empty document.',
|
|
323
331
|
},
|
|
324
332
|
annotation: 'read-only',
|
|
325
333
|
params: {
|
|
@@ -341,8 +349,8 @@ export const accessExplainCapability = {
|
|
|
341
349
|
names: { sdk: 'access_explain', mcp: 'ziggs_access_explain' },
|
|
342
350
|
title: 'Explain access to a resource',
|
|
343
351
|
descriptions: {
|
|
344
|
-
sdk: 'Read-only access explanation for an ordinary returned id. Same one-of artifactId/chatId/taskId/agreementId as open.
|
|
345
|
-
mcp: 'Read-only access explanation for an ordinary returned id (exactly one of artifactId, chatId, taskId, agreementId). No grant id. Rechecks authorization.
|
|
352
|
+
sdk: 'Read-only access explanation for an ordinary returned id. Same one-of artifactId/chatId/taskId/agreementId as open. Returns scoped action states, required inputs and recovery calls. Does not return content and does not request or approve anything.',
|
|
353
|
+
mcp: 'Read-only access explanation for an ordinary returned id (exactly one of artifactId, chatId, taskId, agreementId). No grant id. Rechecks authorization. Returns scoped actions and recovery calls; this call never executes them. Hidden and unknown reveal no labels, owners, excerpts, or counts.',
|
|
346
354
|
},
|
|
347
355
|
annotation: 'read-only',
|
|
348
356
|
params: OPEN_ID_PARAMS,
|
|
@@ -18,3 +18,4 @@ export { ARTIFACT_CAPABILITIES, recordArtifactCapability, listArtifactsCapabilit
|
|
|
18
18
|
export { CHAT_CAPABILITIES, openConversationCapability, presentSendResult, type SendPresentation, } from './chat.js';
|
|
19
19
|
export { EVERYDAY_MCP_TOOLS, EVERYDAY_DESTRUCTIVE_MCP, EVERYDAY_NO_SDK_TWIN, EVERYDAY_SDK_TOOLS, } from './everyday.js';
|
|
20
20
|
export { annotationForSdkTool } from './toolLane.js';
|
|
21
|
+
export { presentResourceActions } from './resourceActions.js';
|
|
@@ -18,3 +18,4 @@ export { ARTIFACT_CAPABILITIES, recordArtifactCapability, listArtifactsCapabilit
|
|
|
18
18
|
export { CHAT_CAPABILITIES, openConversationCapability, presentSendResult, } from './chat.js';
|
|
19
19
|
export { EVERYDAY_MCP_TOOLS, EVERYDAY_DESTRUCTIVE_MCP, EVERYDAY_NO_SDK_TWIN, EVERYDAY_SDK_TOOLS, } from './everyday.js';
|
|
20
20
|
export { annotationForSdkTool } from './toolLane.js';
|
|
21
|
+
export { presentResourceActions } from './resourceActions.js';
|
|
@@ -4,7 +4,9 @@ import type { CapabilityDefinition, CapabilityEnv } from './types.js';
|
|
|
4
4
|
* One next step: the tool the calling surface registers, any args already
|
|
5
5
|
* known, and why.
|
|
6
6
|
*
|
|
7
|
-
* Ready means
|
|
7
|
+
* Ready means the call has complete arguments and no declared hold; it is
|
|
8
|
+
* not an authorization decision. The server checks permission on execution.
|
|
9
|
+
* Incomplete means a required
|
|
8
10
|
* argument is missing or an address field is not an address — the suggestion
|
|
9
11
|
* still names the tool, and `missing` says what has to be filled first.
|
|
10
12
|
*
|
|
@@ -19,7 +21,7 @@ export interface NextCall {
|
|
|
19
21
|
args?: Record<string, unknown>;
|
|
20
22
|
/** One clause: what running this achieves, or what is still missing. */
|
|
21
23
|
why: string;
|
|
22
|
-
/**
|
|
24
|
+
/** Arguments are complete and no hold is declared; does not prove authority. */
|
|
23
25
|
ready: boolean;
|
|
24
26
|
/** Required argument names that are absent or not an address. */
|
|
25
27
|
missing?: readonly string[];
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/** Bind canonical tool names without changing the backend's decision or scope. */
|
|
2
|
+
export function presentResourceActions(actions, surface) {
|
|
3
|
+
const toolName = (name) => surface === 'mcp' && !name.startsWith('ziggs_') ? `ziggs_${name}` : name;
|
|
4
|
+
const call = (value) => ({ ...value, tool: toolName(value.tool) });
|
|
5
|
+
return actions.map(action => ({ ...action,
|
|
6
|
+
...(action.tool ? { tool: toolName(action.tool) } : {}),
|
|
7
|
+
...(action.recovery ? { recovery: call(action.recovery) } : {}),
|
|
8
|
+
}));
|
|
9
|
+
}
|
|
@@ -190,8 +190,8 @@ export declare function resolveMyPendingApprovalPartyId(agreement: Agreement, op
|
|
|
190
190
|
* Record this party's approval decision on an agreement
|
|
191
191
|
* (`PUT /agreements/:agreementId/approvals/:partyId`).
|
|
192
192
|
*
|
|
193
|
-
*
|
|
194
|
-
*
|
|
193
|
+
* Use the partyId from the server's approvalAction. Agents need covering
|
|
194
|
+
* approval authority even for their own slot; the server rechecks it on PUT.
|
|
195
195
|
* Canonical for hire, service, link, and request proposals.
|
|
196
196
|
*/
|
|
197
197
|
export declare function approveAgreementAsParty(agreementId: string, partyId: string, status: 'approved' | 'rejected', creds: Creds): Promise<Agreement>;
|
|
@@ -318,11 +318,31 @@ export interface ClaimOptions {
|
|
|
318
318
|
* verifies the claim against the acting agent and never guesses one.
|
|
319
319
|
*/
|
|
320
320
|
mandateAgreementId?: string;
|
|
321
|
+
/**
|
|
322
|
+
* The room a hire of a listing is made in. On activation its
|
|
323
|
+
* agent joins that room; the claimer must take part in it.
|
|
324
|
+
*/
|
|
325
|
+
chatId?: string;
|
|
326
|
+
}
|
|
327
|
+
/**
|
|
328
|
+
* Where a hire made in a room stands on getting its agent in.
|
|
329
|
+
* `ready` only once the agent is in; `admission_failed` names the action that
|
|
330
|
+
* resumes it without hiring or charging again.
|
|
331
|
+
*/
|
|
332
|
+
export interface ClaimRoom {
|
|
333
|
+
chatId: string;
|
|
334
|
+
status: 'awaiting_approval' | 'ready' | 'admission_failed';
|
|
335
|
+
message?: string;
|
|
336
|
+
recovery?: {
|
|
337
|
+
method: string;
|
|
338
|
+
path: string;
|
|
339
|
+
};
|
|
321
340
|
}
|
|
322
341
|
export declare function claimAgreement(agreementId: string, creds: Creds, opts?: ClaimOptions): Promise<{
|
|
323
342
|
ok: boolean;
|
|
324
343
|
agreement: Agreement;
|
|
325
344
|
kind?: ClaimedKind;
|
|
345
|
+
room?: ClaimRoom;
|
|
326
346
|
}>;
|
|
327
347
|
/**
|
|
328
348
|
* Link types a caller may ask for. `origin` and `delegation` are workflow-owned;
|
|
@@ -367,6 +387,7 @@ export declare class AgreementClient {
|
|
|
367
387
|
ok: boolean;
|
|
368
388
|
agreement: Agreement;
|
|
369
389
|
kind?: ClaimedKind;
|
|
390
|
+
room?: ClaimRoom;
|
|
370
391
|
}>;
|
|
371
392
|
linkToChat(id: string, chatId: string, linkType?: ChatLinkType): Promise<unknown>;
|
|
372
393
|
listChats(id: string): Promise<unknown[]>;
|
|
@@ -53,6 +53,7 @@ export function linkSummary(a) {
|
|
|
53
53
|
// chat with. Dropping it here is what that looked like: the server sent the
|
|
54
54
|
// peer and the allow-list ate it before any caller saw it.
|
|
55
55
|
...(a.peer ? { peer: a.peer } : {}),
|
|
56
|
+
...(a.approvalAction ? { approvalAction: a.approvalAction } : {}),
|
|
56
57
|
...(a.description ? { description: a.description } : {}),
|
|
57
58
|
// Seat bookkeeping on an open invite — link state, not commerce.
|
|
58
59
|
...(a.linkInvite ? { linkInvite: a.linkInvite } : {}),
|
|
@@ -222,7 +223,11 @@ export async function respondToAgreement(agreementId, action, creds, opts = {})
|
|
|
222
223
|
if (!agreement) {
|
|
223
224
|
throw new Error(`Agreement ${agreementId} not found`);
|
|
224
225
|
}
|
|
225
|
-
const
|
|
226
|
+
const approval = agreement.approvalAction;
|
|
227
|
+
if (approval && (approval.state !== 'available' || !approval.partyId)) {
|
|
228
|
+
throw new Error(`${approval.explanation}${opts.appUrl ? ` Review: ${opts.appUrl}` : ''}`);
|
|
229
|
+
}
|
|
230
|
+
const partyId = approval?.partyId ?? resolveMyPendingApprovalPartyId(agreement, {
|
|
226
231
|
ownerUserId: opts.ownerUserId,
|
|
227
232
|
agentId: creds.agentId,
|
|
228
233
|
});
|
|
@@ -288,8 +293,8 @@ export function resolveMyPendingApprovalPartyId(agreement, opts) {
|
|
|
288
293
|
* Record this party's approval decision on an agreement
|
|
289
294
|
* (`PUT /agreements/:agreementId/approvals/:partyId`).
|
|
290
295
|
*
|
|
291
|
-
*
|
|
292
|
-
*
|
|
296
|
+
* Use the partyId from the server's approvalAction. Agents need covering
|
|
297
|
+
* approval authority even for their own slot; the server rechecks it on PUT.
|
|
293
298
|
* Canonical for hire, service, link, and request proposals.
|
|
294
299
|
*/
|
|
295
300
|
export async function approveAgreementAsParty(agreementId, partyId, status, creds) {
|
|
@@ -548,7 +553,7 @@ export async function claimAgreement(agreementId, creds, opts = {}) {
|
|
|
548
553
|
const res = await fetch(`${getAgreementBaseUrl()}/${encodeURIComponent(agreementId)}/claim`, {
|
|
549
554
|
method: 'POST',
|
|
550
555
|
headers: buildHeaders(creds),
|
|
551
|
-
body: JSON.stringify({ ...(opts.mandateAgreementId ? { mandateAgreementId: opts.mandateAgreementId } : {}), ...(opts.parentAgreementId ? { parentAgreementId: opts.parentAgreementId } : {}) }),
|
|
556
|
+
body: JSON.stringify({ ...(opts.mandateAgreementId ? { mandateAgreementId: opts.mandateAgreementId } : {}), ...(opts.parentAgreementId ? { parentAgreementId: opts.parentAgreementId } : {}), ...(opts.chatId ? { chatId: opts.chatId } : {}) }),
|
|
552
557
|
});
|
|
553
558
|
if (!res.ok) {
|
|
554
559
|
const body = await res.text().catch(() => '');
|
|
@@ -14,16 +14,25 @@ export interface ContextOpenBody {
|
|
|
14
14
|
after?: string;
|
|
15
15
|
limit?: number;
|
|
16
16
|
}
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
17
|
+
/** Backend-evaluated action, scoped to a resource. Never a permission token. */
|
|
18
|
+
export interface ResourceActionCall {
|
|
19
|
+
tool: string;
|
|
20
|
+
args: Record<string, unknown>;
|
|
21
|
+
required?: string[];
|
|
22
|
+
}
|
|
23
|
+
export interface ResourceAction extends Partial<ResourceActionCall> {
|
|
24
|
+
action: string;
|
|
25
|
+
state: 'available' | 'needs_decision' | 'unavailable' | 'not_evaluated';
|
|
26
|
+
reasonCode?: string;
|
|
27
|
+
reason?: unknown;
|
|
28
|
+
scope?: {
|
|
29
|
+
kind: string;
|
|
30
|
+
id: string;
|
|
31
|
+
agreementId?: string;
|
|
32
|
+
};
|
|
33
|
+
recovery?: ResourceActionCall;
|
|
24
34
|
}
|
|
25
35
|
export interface ContextOpenAccess {
|
|
26
|
-
abilities: ContextOpenAbilities;
|
|
27
36
|
summary: string;
|
|
28
37
|
document?: {
|
|
29
38
|
empty: boolean;
|
|
@@ -42,6 +51,8 @@ export interface ContextOpenAccess {
|
|
|
42
51
|
};
|
|
43
52
|
}
|
|
44
53
|
export interface ContextOpenResult {
|
|
54
|
+
/** Optional for servers predating resource action projections. */
|
|
55
|
+
actions?: ResourceAction[];
|
|
45
56
|
outcome: ContextOpenOutcome;
|
|
46
57
|
ref: ContextOpenRef;
|
|
47
58
|
access: ContextOpenAccess;
|
|
@@ -57,6 +57,8 @@ export interface ContextSnapshotParticipant {
|
|
|
57
57
|
[key: string]: unknown;
|
|
58
58
|
}
|
|
59
59
|
export interface ContextSnapshotResult {
|
|
60
|
+
/** Server-resolved orientation; writes recheck authority. */
|
|
61
|
+
workBrief?: Record<string, unknown>;
|
|
60
62
|
work?: Record<string, unknown>;
|
|
61
63
|
history: unknown[];
|
|
62
64
|
agreements: unknown[];
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type ClaimedKind, type ClaimOptions, type ProposeTerms } from './AgreementClient.js';
|
|
1
|
+
import { type ClaimedKind, type ClaimOptions, type ClaimRoom, type ProposeTerms } from './AgreementClient.js';
|
|
2
2
|
import { type Agreement, type Creds, type EngagementKind } from '../types.js';
|
|
3
3
|
/**
|
|
4
4
|
* one propose grammar. Direct, broadcast (request and standing
|
|
@@ -38,4 +38,5 @@ export declare function proposeUnified(input: UnifiedProposeInput, creds: Creds)
|
|
|
38
38
|
export declare function claimOpenAgreement(agreementId: string, creds: Creds, opts?: ClaimOptions): Promise<{
|
|
39
39
|
agreement: Agreement;
|
|
40
40
|
kind: ClaimedKind;
|
|
41
|
+
room?: ClaimRoom;
|
|
41
42
|
}>;
|
|
@@ -75,8 +75,8 @@ export async function proposeUnified(input, creds) {
|
|
|
75
75
|
export async function claimOpenAgreement(agreementId, creds, opts = {}) {
|
|
76
76
|
if (!agreementId)
|
|
77
77
|
throw new Error('agreementId is required');
|
|
78
|
-
const { agreement, kind } = await claimAgreement(agreementId, creds, opts);
|
|
78
|
+
const { agreement, kind, room } = await claimAgreement(agreementId, creds, opts);
|
|
79
79
|
// A server that has not shipped the `kind` field yet still claims correctly;
|
|
80
80
|
// 'request' is the shape the route has always handled.
|
|
81
|
-
return { agreement, kind: kind ?? 'request' };
|
|
81
|
+
return { agreement, kind: kind ?? 'request', ...(room ? { room } : {}) };
|
|
82
82
|
}
|
package/dist/http/index.d.ts
CHANGED
|
@@ -10,7 +10,7 @@ export type { ArtifactVisibility, ListArtifactsOptions, ListArtifactsQuery, List
|
|
|
10
10
|
export { ContextReadClient, CONTEXT_READ_TYPES, CONTEXT_READ_VIA, VIA_KINDS, parseVia, viaHint, } from './ContextReadClient.js';
|
|
11
11
|
export type { ContextReadType, ContextReadQuery, ContextReadEnvelope, ContextSnapshotResult, ContextSnapshotParticipant, ViaKind, } from './ContextReadClient.js';
|
|
12
12
|
export { ContextOpenClient, CONTEXT_OPEN_KINDS } from './ContextOpenClient.js';
|
|
13
|
-
export type { ContextOpenKind, ContextOpenOutcome, ContextOpenRef, ContextOpenBody,
|
|
13
|
+
export type { ContextOpenKind, ContextOpenOutcome, ContextOpenRef, ContextOpenBody, ResourceAction, ResourceActionCall, ContextOpenAccess, ContextOpenResult, ContextExplainResult, } from './ContextOpenClient.js';
|
|
14
14
|
export { ContextDiscoveryClient } from './ContextDiscoveryClient.js';
|
|
15
15
|
export type { DiscoverableItem } from './ContextDiscoveryClient.js';
|
|
16
16
|
export { IntroductionsClient } from './IntroductionsClient.js';
|
package/dist/index.d.ts
CHANGED
|
@@ -11,7 +11,7 @@ export { RateLimitedError, isRateLimited, parseRetryAfterMs, pollSurfaceError, }
|
|
|
11
11
|
export { parseErrorMessage, parseErrorCode, throwApiError, } from './shared/apiError.js';
|
|
12
12
|
export { ApiError } from './types.js';
|
|
13
13
|
export type { Creds, Task, TaskState, PlanStep, PlanStepStatus, Agreement, AgreementParties, AgreementPartySide, EngagementKind, BroadcastAudience, EntryType, ContentType, MessageMetadata, MessageHandler, InboxDeliveryKind, InboxDeliveryRef, InboxChatNews, InboxProposalRef, InboxTaskRef, InboxRequestRef, InboxConnectionRequestRef, InboxHumanAttention, InboxEnvelope, InboxAckResult, InboxPeek, InboxReadOptions, } from './types.js';
|
|
14
|
-
export type { ProposeTerms, ProposeDirectInput, ProposeBroadcastInput, ProposeAgreementData, ClaimOptions, } from './http/AgreementClient.js';
|
|
14
|
+
export type { ProposeTerms, ProposeDirectInput, ProposeBroadcastInput, ProposeAgreementData, ClaimOptions, ClaimRoom, } from './http/AgreementClient.js';
|
|
15
15
|
export { decisionWords } from './decisionWords.js';
|
|
16
16
|
export type { DecisionOutcome, DecisionWords, DecisionWordsInput, } from './decisionWords.js';
|
|
17
17
|
export { planInboxAck, planPartialInboxAck, inboxAckAllowed, inboxAckHandledIds, } from './inboxAck.js';
|
package/dist/types.d.ts
CHANGED
|
@@ -176,6 +176,11 @@ export interface AgreementApprovalEntry {
|
|
|
176
176
|
heldReason?: string | null;
|
|
177
177
|
}
|
|
178
178
|
export interface Agreement {
|
|
179
|
+
approvalAction?: {
|
|
180
|
+
state: 'available' | 'needs_decision' | 'unavailable';
|
|
181
|
+
partyId?: string;
|
|
182
|
+
explanation: string;
|
|
183
|
+
};
|
|
179
184
|
agreementId: string;
|
|
180
185
|
parentAgreementId?: string | null;
|
|
181
186
|
rootAgreementId?: string | null;
|