@ziggs-ai/api-client 0.10.4 → 0.12.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 +9 -2
- package/dist/capabilities/agreementVerbs.js +61 -21
- package/dist/capabilities/agreements.d.ts +1 -1
- package/dist/capabilities/agreements.js +18 -6
- package/dist/capabilities/artifacts.d.ts +4 -2
- package/dist/capabilities/artifacts.js +168 -33
- package/dist/capabilities/chat.d.ts +2 -3
- package/dist/capabilities/chat.js +5 -6
- package/dist/capabilities/connections.js +1 -1
- package/dist/capabilities/context.js +3 -0
- package/dist/capabilities/grants.d.ts +7 -6
- package/dist/capabilities/grants.js +9 -8
- package/dist/capabilities/index.d.ts +4 -4
- package/dist/capabilities/index.js +4 -4
- package/dist/capabilities/links.d.ts +17 -6
- package/dist/capabilities/links.js +71 -86
- package/dist/capabilities/marketplace.js +23 -17
- package/dist/capabilities/nextCall.d.ts +36 -5
- package/dist/capabilities/nextCall.js +53 -7
- package/dist/capabilities/payments.d.ts +24 -8
- package/dist/capabilities/payments.js +28 -392
- package/dist/capabilities/proposeProviderId.d.ts +1 -1
- package/dist/capabilities/proposeProviderId.js +1 -1
- package/dist/http/AgreementClient.d.ts +63 -27
- package/dist/http/AgreementClient.js +51 -39
- package/dist/http/ChatClient.d.ts +1 -0
- package/dist/http/ChatClient.js +4 -1
- package/dist/http/ConnectionsClient.js +12 -1
- package/dist/http/ContextGrantsClient.d.ts +15 -1
- package/dist/http/ContextGrantsClient.js +2 -0
- package/dist/http/ContextReadClient.d.ts +14 -5
- package/dist/http/GrantsClient.d.ts +14 -0
- package/dist/http/GrantsClient.js +18 -2
- package/dist/http/InboxClient.js +4 -0
- package/dist/http/MarketplaceClient.d.ts +6 -8
- package/dist/http/MarketplaceClient.js +11 -30
- package/dist/http/TaskClient.d.ts +5 -0
- package/dist/http/TaskClient.js +4 -7
- package/dist/http/agreementFlows.d.ts +6 -7
- package/dist/http/agreementFlows.js +14 -20
- package/dist/http/grants.d.ts +28 -0
- package/dist/http/index.d.ts +2 -2
- package/dist/index.d.ts +3 -3
- package/dist/index.js +1 -1
- package/dist/instanceIdentity.d.ts +4 -0
- package/dist/instanceIdentity.js +44 -0
- package/dist/relay/provisionRelayWorkers.d.ts +2 -2
- package/dist/relay/provisionRelayWorkers.js +5 -5
- package/dist/types.d.ts +80 -31
- package/dist/types.js +18 -0
- package/package.json +1 -1
|
@@ -14,19 +14,65 @@ export function nextCall(env, capabilityKey, args, why) {
|
|
|
14
14
|
};
|
|
15
15
|
}
|
|
16
16
|
/**
|
|
17
|
-
* The other
|
|
17
|
+
* The other PRINCIPAL in a two-party agreement, from the perspective of
|
|
18
|
+
* `selfId`.
|
|
19
|
+
*
|
|
20
|
+
* This was `peerAgentId`, and it read the `actor` columns — the agents that
|
|
21
|
+
* carried the paperwork. Those became courier info when a link was re-keyed to
|
|
22
|
+
* the two people it belongs to, and on most links they are null, so the hint it
|
|
23
|
+
* fed either pre-filled a call with an agent that is no longer a door or
|
|
24
|
+
* silently vanished because the helper returned nothing.
|
|
25
|
+
*
|
|
26
|
+
* Named for the SLOT, not for what a link happens to put in it. On a link both
|
|
27
|
+
* principals are guaranteed to be people, because links are person-only and
|
|
28
|
+
* both sides are userIds by construction — but the same slots hold an org or an
|
|
29
|
+
* agent on other engagement kinds, so a caller who read "person" here and
|
|
30
|
+
* trusted it on a hire would be wrong. The person guarantee is a link-only
|
|
31
|
+
* property; ask the kind before relying on it.
|
|
18
32
|
*
|
|
19
33
|
* Returns null rather than guessing when the row does not identify one, because
|
|
20
34
|
* a pre-filled call naming the wrong counterparty is worse than no pre-filled
|
|
21
35
|
* call: the caller would run it, and it would do something they did not ask for.
|
|
22
36
|
*/
|
|
23
|
-
export function
|
|
37
|
+
export function peerPrincipalId(parties, selfId) {
|
|
24
38
|
if (!parties || !selfId)
|
|
25
39
|
return null;
|
|
26
|
-
const
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
40
|
+
const creator = parties.creator?.principal;
|
|
41
|
+
const provider = parties.provider?.principal;
|
|
42
|
+
if (creator && creator !== selfId)
|
|
43
|
+
return creator;
|
|
44
|
+
if (provider && provider !== selfId)
|
|
45
|
+
return provider;
|
|
31
46
|
return null;
|
|
32
47
|
}
|
|
48
|
+
/**
|
|
49
|
+
* The peer's principal, located by finding MY side rather than by knowing my
|
|
50
|
+
* own principal id.
|
|
51
|
+
*
|
|
52
|
+
* An agent knows its own agent id and not the id of the person it answers for,
|
|
53
|
+
* so it cannot ask {@link peerPrincipalId} which of two people it is. What it
|
|
54
|
+
* CAN recognise is its own courier stamp: if my agent id is in one side's
|
|
55
|
+
* `actor`, that side is mine and the other side's principal is the peer.
|
|
56
|
+
*
|
|
57
|
+
* Note the difference from the bug this replaced. Reading the peer's `actor` as
|
|
58
|
+
* the peer's address was wrong — those slots are courier info, null on most
|
|
59
|
+
* links, and never a door. Reading MY OWN `actor` to work out which side I am on
|
|
60
|
+
* is sound, because I am comparing against an id I hold.
|
|
61
|
+
*
|
|
62
|
+
* Returns null when neither side carries my stamp, which is the common case for
|
|
63
|
+
* a link two people formed from the web. No pre-filled call is the right answer
|
|
64
|
+
* there: naming the wrong counterparty would get run.
|
|
65
|
+
*/
|
|
66
|
+
export function peerPrincipalForCourier(parties, myAgentId) {
|
|
67
|
+
if (!parties || !myAgentId)
|
|
68
|
+
return null;
|
|
69
|
+
const mineIsCreator = parties.creator?.actor === myAgentId;
|
|
70
|
+
const mineIsProvider = parties.provider?.actor === myAgentId;
|
|
71
|
+
// Both sides stamped with me is one estate on both ends, not a peer.
|
|
72
|
+
if (mineIsCreator === mineIsProvider)
|
|
73
|
+
return null;
|
|
74
|
+
const peer = mineIsCreator
|
|
75
|
+
? parties.provider?.principal
|
|
76
|
+
: parties.creator?.principal;
|
|
77
|
+
return peer && peer !== myAgentId ? peer : null;
|
|
78
|
+
}
|
|
@@ -1,11 +1,27 @@
|
|
|
1
1
|
import { type CapabilityDefinition } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Reading the balance is the whole rail on an agent surface.
|
|
4
|
+
*
|
|
5
|
+
* What left this surface is every verb that moved value on its own:
|
|
6
|
+
* `payment_transfer`, `payment_hold`, `payment_release`,
|
|
7
|
+
* `payment_wait_for_approval` and `payment_resolve_wallet`, plus the three
|
|
8
|
+
* grant mutations (issue / attenuate / revoke), which are now the wallet
|
|
9
|
+
* owner's to make in the web app rather than an agent's to make on their
|
|
10
|
+
* behalf. An agent holding a free-standing "move value from A to B" verb is
|
|
11
|
+
* what reads as transferring a financial asset between third parties, and it
|
|
12
|
+
* is the shape assistant-store connector policy rejects.
|
|
13
|
+
*
|
|
14
|
+
* What did NOT change: agreements still settle in points. The hold on
|
|
15
|
+
* activation, the transfer in `settleCompletedTask` and the settle on fulfill
|
|
16
|
+
* all stay exactly as they were, and priced agreements keep moving points
|
|
17
|
+
* between org wallets. That double-entry IS the meter — the chain and the
|
|
18
|
+
* middleman margins are the measurement we want — so removing the verbs costs
|
|
19
|
+
* no capability: nothing an agent could do through them was load-bearing for
|
|
20
|
+
* getting paid under an agreement.
|
|
21
|
+
*
|
|
22
|
+
* Balance stays readable, because "see your points" is the intended
|
|
23
|
+
* experience. Note that `ZIGGS_MCP_CORE_ONLY` gates this whole group off
|
|
24
|
+
* including balance, so it is not the lever for this on its own.
|
|
25
|
+
*/
|
|
2
26
|
export declare const paymentBalanceCapability: CapabilityDefinition;
|
|
3
|
-
export declare const paymentResolveWalletCapability: CapabilityDefinition;
|
|
4
|
-
export declare const paymentTransferCapability: CapabilityDefinition;
|
|
5
|
-
export declare const paymentWaitForApprovalCapability: CapabilityDefinition;
|
|
6
|
-
export declare const paymentHoldCapability: CapabilityDefinition;
|
|
7
|
-
export declare const paymentReleaseCapability: CapabilityDefinition;
|
|
8
|
-
export declare const paymentIssueGrantCapability: CapabilityDefinition;
|
|
9
|
-
export declare const paymentAttenuateGrantCapability: CapabilityDefinition;
|
|
10
|
-
export declare const paymentRevokeGrantCapability: CapabilityDefinition;
|
|
11
27
|
export declare const PAYMENT_CAPABILITIES: CapabilityDefinition[];
|
|
@@ -6,36 +6,37 @@ function client(env) {
|
|
|
6
6
|
throw new Error('operatorKey missing from tool context');
|
|
7
7
|
return new PaymentsClient(operatorKey, agentId, env.baseUrl);
|
|
8
8
|
}
|
|
9
|
-
/**
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
9
|
+
/**
|
|
10
|
+
* Reading the balance is the whole rail on an agent surface.
|
|
11
|
+
*
|
|
12
|
+
* What left this surface is every verb that moved value on its own:
|
|
13
|
+
* `payment_transfer`, `payment_hold`, `payment_release`,
|
|
14
|
+
* `payment_wait_for_approval` and `payment_resolve_wallet`, plus the three
|
|
15
|
+
* grant mutations (issue / attenuate / revoke), which are now the wallet
|
|
16
|
+
* owner's to make in the web app rather than an agent's to make on their
|
|
17
|
+
* behalf. An agent holding a free-standing "move value from A to B" verb is
|
|
18
|
+
* what reads as transferring a financial asset between third parties, and it
|
|
19
|
+
* is the shape assistant-store connector policy rejects.
|
|
20
|
+
*
|
|
21
|
+
* What did NOT change: agreements still settle in points. The hold on
|
|
22
|
+
* activation, the transfer in `settleCompletedTask` and the settle on fulfill
|
|
23
|
+
* all stay exactly as they were, and priced agreements keep moving points
|
|
24
|
+
* between org wallets. That double-entry IS the meter — the chain and the
|
|
25
|
+
* middleman margins are the measurement we want — so removing the verbs costs
|
|
26
|
+
* no capability: nothing an agent could do through them was load-bearing for
|
|
27
|
+
* getting paid under an agreement.
|
|
28
|
+
*
|
|
29
|
+
* Balance stays readable, because "see your points" is the intended
|
|
30
|
+
* experience. Note that `ZIGGS_MCP_CORE_ONLY` gates this whole group off
|
|
31
|
+
* including balance, so it is not the lever for this on its own.
|
|
32
|
+
*/
|
|
32
33
|
export const paymentBalanceCapability = {
|
|
33
34
|
key: 'payment_balance',
|
|
34
35
|
names: { sdk: 'payment_balance', mcp: 'ziggs_payment_balance' },
|
|
35
|
-
title: 'Check your
|
|
36
|
+
title: 'Check your points',
|
|
36
37
|
descriptions: {
|
|
37
|
-
sdk: "Check the caller's
|
|
38
|
-
mcp: "Check the caller's
|
|
38
|
+
sdk: "Check the caller's points balance and available balance (total minus points held against active agreements). Points move as a consequence of an agreement settling.",
|
|
39
|
+
mcp: "Check the caller's points balance and available balance (total minus points held against active agreements). Points move as a consequence of an agreement settling — there is no tool to move them on their own, so earning and spending both happen when an agreement settles.",
|
|
39
40
|
},
|
|
40
41
|
annotation: 'read-only',
|
|
41
42
|
params: {},
|
|
@@ -44,375 +45,10 @@ export const paymentBalanceCapability = {
|
|
|
44
45
|
return await client(env).balance();
|
|
45
46
|
}
|
|
46
47
|
catch (e) {
|
|
47
|
-
rethrowWithContext(e, 'Failed to
|
|
48
|
-
}
|
|
49
|
-
},
|
|
50
|
-
};
|
|
51
|
-
export const paymentResolveWalletCapability = {
|
|
52
|
-
key: 'payment_resolve_wallet',
|
|
53
|
-
names: { sdk: 'payment_resolve_wallet', mcp: 'ziggs_payment_resolve_wallet' },
|
|
54
|
-
title: 'Look up a wallet',
|
|
55
|
-
descriptions: {
|
|
56
|
-
sdk: 'Look up a walletId by userId or agentId. Use before a transfer when you only know the recipient by their platform ID.',
|
|
57
|
-
mcp: 'Look up a walletId by userId or agentId. Use before a transfer when you only know the recipient by their platform ID.',
|
|
58
|
-
},
|
|
59
|
-
annotation: 'read-only',
|
|
60
|
-
params: {
|
|
61
|
-
userId: { type: 'string', description: 'User to resolve' },
|
|
62
|
-
agentId: { type: 'string', description: 'Agent to resolve' },
|
|
63
|
-
},
|
|
64
|
-
handler: async (args, env) => {
|
|
65
|
-
if (!args['userId'] && !args['agentId'])
|
|
66
|
-
throw new Error('Provide userId or agentId to resolve a wallet');
|
|
67
|
-
try {
|
|
68
|
-
const wallet = await client(env).resolve({
|
|
69
|
-
userId: args['userId'],
|
|
70
|
-
agentId: args['agentId'],
|
|
71
|
-
});
|
|
72
|
-
return {
|
|
73
|
-
walletId: wallet?.walletId || null,
|
|
74
|
-
ownerId: wallet?.ownerId || null,
|
|
75
|
-
currency: wallet?.currency || 'pez',
|
|
76
|
-
status: wallet?.status || null,
|
|
77
|
-
};
|
|
78
|
-
}
|
|
79
|
-
catch (e) {
|
|
80
|
-
rethrowWithContext(e, 'Failed to resolve wallet');
|
|
81
|
-
}
|
|
82
|
-
},
|
|
83
|
-
};
|
|
84
|
-
export const paymentTransferCapability = {
|
|
85
|
-
key: 'payment_transfer',
|
|
86
|
-
names: { sdk: 'payment_transfer', mcp: 'ziggs_payment_transfer' },
|
|
87
|
-
title: 'Transfer funds',
|
|
88
|
-
descriptions: {
|
|
89
|
-
sdk: 'Transfer funds to another wallet. Amounts are integer cents. Transfers above the wallet owner\'s policy pause with status "approval_required" — wait inline with payment_wait_for_approval when you expect a quick decision.',
|
|
90
|
-
mcp: 'Transfer funds to another wallet. Amounts are integer cents. As a delegate you spend under a payment grant the wallet owner issued (paymentGrantId — find yours via ziggs_grant_list scopeKind=wallet). Transfers above the owner\'s policy pause with status "approval_required": the human approves on the wallet page (it also shows in ziggs_pending_decisions) — you can wait inline with ziggs_payment_wait_for_approval, and you must NEVER approve your own transfer.',
|
|
91
|
-
},
|
|
92
|
-
annotation: 'write',
|
|
93
|
-
params: {
|
|
94
|
-
toWalletId: {
|
|
95
|
-
type: 'string',
|
|
96
|
-
required: true,
|
|
97
|
-
description: 'Destination wal_... id — or a userId/agentId to auto-resolve',
|
|
98
|
-
},
|
|
99
|
-
amount: { type: 'number', required: true, description: 'Amount in integer cents, > 0' },
|
|
100
|
-
description: { type: 'string', description: 'Human-readable transfer memo' },
|
|
101
|
-
idempotencyKey: {
|
|
102
|
-
type: 'string',
|
|
103
|
-
description: 'Client-supplied key to make retries safe (auto-generated when omitted)',
|
|
104
|
-
},
|
|
105
|
-
paymentGrantId: {
|
|
106
|
-
type: 'string',
|
|
107
|
-
description: 'Payment grant to spend under (required for agent-impersonated transfers)',
|
|
108
|
-
},
|
|
109
|
-
},
|
|
110
|
-
handler: async (args, env) => {
|
|
111
|
-
if (!args['toWalletId'])
|
|
112
|
-
throw new Error('toWalletId is required');
|
|
113
|
-
const amount = args['amount'];
|
|
114
|
-
if (!amount || amount <= 0)
|
|
115
|
-
throw new Error('amount must be positive');
|
|
116
|
-
let result;
|
|
117
|
-
try {
|
|
118
|
-
result = await client(env).transfer({
|
|
119
|
-
to: args['toWalletId'],
|
|
120
|
-
amount: Math.round(amount),
|
|
121
|
-
description: args['description'] || 'Agent-initiated transfer',
|
|
122
|
-
idempotencyKey: args['idempotencyKey'],
|
|
123
|
-
paymentGrantId: args['paymentGrantId'],
|
|
124
|
-
});
|
|
125
|
-
}
|
|
126
|
-
catch (e) {
|
|
127
|
-
rethrowWithContext(e, 'Transfer failed');
|
|
128
|
-
}
|
|
129
|
-
if (result.status === 'approval_required') {
|
|
130
|
-
const base = {
|
|
131
|
-
status: 'approval_required',
|
|
132
|
-
approvalId: result.approvalId,
|
|
133
|
-
expiresAt: result.expiresAt,
|
|
134
|
-
reason: result.reason,
|
|
135
|
-
amount,
|
|
136
|
-
toWalletId: result.toWalletId,
|
|
137
|
-
};
|
|
138
|
-
// Same pause, surface-local guidance: the MCP delegate must surface the
|
|
139
|
-
// pending approval to the human (pull-only MCP has no push); the SDK
|
|
140
|
-
// runtime routes via structured next_actions.
|
|
141
|
-
if (env.surface === 'mcp') {
|
|
142
|
-
return {
|
|
143
|
-
...base,
|
|
144
|
-
note: 'Transfer paused: the wallet owner must approve this amount on the wallet page (also listed by ziggs_pending_decisions). Tell the human now (pull-only MCP has no push). ' +
|
|
145
|
-
'Wait inline with ziggs_payment_wait_for_approval when you expect a quick decision (≤2 min).',
|
|
146
|
-
};
|
|
147
|
-
}
|
|
148
|
-
return {
|
|
149
|
-
...base,
|
|
150
|
-
message: 'Transfer paused: the wallet owner must approve this amount.',
|
|
151
|
-
next_actions: [
|
|
152
|
-
{
|
|
153
|
-
tool: 'payment_wait_for_approval',
|
|
154
|
-
when: 'You expect a quick decision (≤2 min) and can wait inline.',
|
|
155
|
-
args: { approvalId: result.approvalId, timeoutMs: 120000 },
|
|
156
|
-
},
|
|
157
|
-
{
|
|
158
|
-
tool: 'task_update_plan_step',
|
|
159
|
-
when: 'You want to abandon the transfer and route around it.',
|
|
160
|
-
},
|
|
161
|
-
],
|
|
162
|
-
};
|
|
163
|
-
}
|
|
164
|
-
return {
|
|
165
|
-
status: 'transferred',
|
|
166
|
-
transactionId: result.transactionId,
|
|
167
|
-
amount,
|
|
168
|
-
toWalletId: result.toWalletId,
|
|
169
|
-
};
|
|
170
|
-
},
|
|
171
|
-
};
|
|
172
|
-
export const paymentWaitForApprovalCapability = {
|
|
173
|
-
key: 'payment_wait_for_approval',
|
|
174
|
-
names: { sdk: 'payment_wait_for_approval', mcp: 'ziggs_payment_wait_for_approval' },
|
|
175
|
-
title: 'Wait on a payment approval',
|
|
176
|
-
descriptions: {
|
|
177
|
-
sdk: 'Poll a paused transfer (status "approval_required") until the human decides or the timeout passes. Returns executed | rejected | expired | timeout | gone.',
|
|
178
|
-
mcp: 'Poll a paused transfer (status "approval_required") until the human decides or the timeout passes. Returns executed | rejected | expired | timeout | gone. Use for quick decisions (≤2 min); for longer waits, stop and check again next session.',
|
|
179
|
-
},
|
|
180
|
-
annotation: 'read-only',
|
|
181
|
-
params: {
|
|
182
|
-
approvalId: {
|
|
183
|
-
type: 'string',
|
|
184
|
-
required: true,
|
|
185
|
-
description: 'Approval to wait on (from the paused transfer)',
|
|
186
|
-
},
|
|
187
|
-
timeoutMs: { type: 'number', description: 'Max wait, default 120000' },
|
|
188
|
-
pollMs: { type: 'number', description: 'Poll interval, default 3000 (min 500)' },
|
|
189
|
-
},
|
|
190
|
-
handler: async (args, env) => {
|
|
191
|
-
if (!args['approvalId'])
|
|
192
|
-
throw new Error('approvalId is required');
|
|
193
|
-
try {
|
|
194
|
-
const result = await client(env).waitForApproval(args['approvalId'], {
|
|
195
|
-
timeoutMs: args['timeoutMs'],
|
|
196
|
-
pollMs: args['pollMs'],
|
|
197
|
-
});
|
|
198
|
-
const loose = result;
|
|
199
|
-
return {
|
|
200
|
-
status: result.status,
|
|
201
|
-
approvalId: args['approvalId'],
|
|
202
|
-
transactionId: loose['transactionId'] || null,
|
|
203
|
-
approval: loose['approval'] || null,
|
|
204
|
-
};
|
|
205
|
-
}
|
|
206
|
-
catch (e) {
|
|
207
|
-
rethrowWithContext(e, 'wait_for_approval failed');
|
|
208
|
-
}
|
|
209
|
-
},
|
|
210
|
-
};
|
|
211
|
-
export const paymentHoldCapability = {
|
|
212
|
-
key: 'payment_hold',
|
|
213
|
-
names: { sdk: 'payment_hold', mcp: 'ziggs_payment_hold' },
|
|
214
|
-
title: 'Hold funds in escrow',
|
|
215
|
-
descriptions: {
|
|
216
|
-
sdk: 'Pre-authorize (escrow) funds without moving them. Use to reserve payment at agreement formation; release with payment_release once work is complete or to refund if work is cancelled.',
|
|
217
|
-
mcp: "Pre-authorize (escrow) funds without moving them. Use to reserve payment at agreement formation; release with ziggs_payment_release once work is complete, or refund if it's cancelled.",
|
|
218
|
-
},
|
|
219
|
-
annotation: 'write',
|
|
220
|
-
params: {
|
|
221
|
-
amount: { type: 'number', required: true, description: 'Amount in integer cents, > 0' },
|
|
222
|
-
description: { type: 'string', description: 'Human-readable hold memo' },
|
|
223
|
-
idempotencyKey: { type: 'string', description: 'Client-supplied retry-safety key' },
|
|
224
|
-
paymentGrantId: {
|
|
225
|
-
type: 'string',
|
|
226
|
-
description: 'Payment grant authorizing this hold (required for agent actors; auto-picks an active wallet grant when omitted)',
|
|
227
|
-
},
|
|
228
|
-
},
|
|
229
|
-
handler: async (args, env) => {
|
|
230
|
-
const amount = args['amount'];
|
|
231
|
-
if (!amount || amount <= 0)
|
|
232
|
-
throw new Error('amount must be positive');
|
|
233
|
-
try {
|
|
234
|
-
const result = await client(env).hold({
|
|
235
|
-
amount: Math.round(amount),
|
|
236
|
-
description: args['description'] || 'Agent escrow hold',
|
|
237
|
-
idempotencyKey: args['idempotencyKey'],
|
|
238
|
-
paymentGrantId: args['paymentGrantId'],
|
|
239
|
-
});
|
|
240
|
-
return {
|
|
241
|
-
status: 'held',
|
|
242
|
-
transactionId: result.transaction?.transactionId || null,
|
|
243
|
-
amount,
|
|
244
|
-
};
|
|
245
|
-
}
|
|
246
|
-
catch (e) {
|
|
247
|
-
rethrowWithContext(e, 'Hold failed');
|
|
248
|
-
}
|
|
249
|
-
},
|
|
250
|
-
};
|
|
251
|
-
export const paymentReleaseCapability = {
|
|
252
|
-
key: 'payment_release',
|
|
253
|
-
names: { sdk: 'payment_release', mcp: 'ziggs_payment_release' },
|
|
254
|
-
title: 'Settle or refund a hold',
|
|
255
|
-
descriptions: {
|
|
256
|
-
sdk: "Settle or refund an escrow hold. Use action='complete' to transfer held funds to toWalletId (work done), or action='refund' to return funds to the sender (work cancelled).",
|
|
257
|
-
mcp: "Settle or refund an escrow hold. action='complete' transfers held funds to toWalletId (work done); action='refund' returns funds to the sender (work cancelled).",
|
|
258
|
-
},
|
|
259
|
-
annotation: 'write',
|
|
260
|
-
params: {
|
|
261
|
-
holdId: {
|
|
262
|
-
type: 'string',
|
|
263
|
-
required: true,
|
|
264
|
-
description: 'Hold to settle (transactionId from the hold)',
|
|
265
|
-
},
|
|
266
|
-
action: {
|
|
267
|
-
type: 'string',
|
|
268
|
-
required: true,
|
|
269
|
-
enum: ['complete', 'refund'],
|
|
270
|
-
description: 'complete = pay out, refund = return',
|
|
271
|
-
},
|
|
272
|
-
toWalletId: { type: 'string', description: 'Destination wallet — required when action=complete' },
|
|
273
|
-
idempotencyKey: { type: 'string', description: 'Client-supplied retry-safety key' },
|
|
274
|
-
},
|
|
275
|
-
handler: async (args, env) => {
|
|
276
|
-
if (!args['holdId'])
|
|
277
|
-
throw new Error('holdId is required');
|
|
278
|
-
const action = args['action'];
|
|
279
|
-
if (action !== 'complete' && action !== 'refund')
|
|
280
|
-
throw new Error("action must be 'complete' or 'refund'");
|
|
281
|
-
if (action === 'complete' && !args['toWalletId'])
|
|
282
|
-
throw new Error('toWalletId is required when action=complete');
|
|
283
|
-
try {
|
|
284
|
-
const result = await client(env).release({
|
|
285
|
-
holdId: args['holdId'],
|
|
286
|
-
action,
|
|
287
|
-
toWalletId: args['toWalletId'],
|
|
288
|
-
idempotencyKey: args['idempotencyKey'],
|
|
289
|
-
});
|
|
290
|
-
return {
|
|
291
|
-
status: action === 'complete' ? 'settled' : 'refunded',
|
|
292
|
-
transactionId: result.transaction?.transactionId || null,
|
|
293
|
-
holdId: args['holdId'],
|
|
294
|
-
action,
|
|
295
|
-
};
|
|
296
|
-
}
|
|
297
|
-
catch (e) {
|
|
298
|
-
rethrowWithContext(e, 'Release failed');
|
|
299
|
-
}
|
|
300
|
-
},
|
|
301
|
-
};
|
|
302
|
-
export const paymentIssueGrantCapability = {
|
|
303
|
-
key: 'payment_issue_grant',
|
|
304
|
-
names: { sdk: 'payment_issue_grant', mcp: 'ziggs_payment_issue_grant' },
|
|
305
|
-
title: 'Issue a spend grant',
|
|
306
|
-
descriptions: {
|
|
307
|
-
sdk: "Issue a payment grant delegating bounded spend from the operator's wallet to an agent holder. Caveats bound what the holder can do (max_amount, daily_budget, allowed_recipients, expiry). The holder spends by passing the grantId as paymentGrantId on transfers.",
|
|
308
|
-
mcp: "Issue a payment grant delegating bounded spend from the operator's wallet to an agent holder. Caveats bound what the holder can do (max_amount, daily_budget, allowed_recipients, expiry). The holder spends by passing the grantId as paymentGrantId on transfers.",
|
|
309
|
-
},
|
|
310
|
-
annotation: 'write',
|
|
311
|
-
params: {
|
|
312
|
-
holderId: { type: 'string', required: true, description: 'Agent that will hold the grant' },
|
|
313
|
-
...grantCaveatParams,
|
|
314
|
-
},
|
|
315
|
-
handler: async (args, env) => {
|
|
316
|
-
if (!args['holderId'])
|
|
317
|
-
throw new Error('holderId is required');
|
|
318
|
-
try {
|
|
319
|
-
const caveats = buildCaveats(args);
|
|
320
|
-
const { grant } = await client(env).issueGrant({
|
|
321
|
-
holderId: args['holderId'],
|
|
322
|
-
caveats,
|
|
323
|
-
});
|
|
324
|
-
return {
|
|
325
|
-
grantId: grant?.grantId || null,
|
|
326
|
-
holderId: grant?.holderId || args['holderId'],
|
|
327
|
-
caveats: grant?.caveats || caveats,
|
|
328
|
-
expiresAt: grant?.expiresAt || null,
|
|
329
|
-
};
|
|
330
|
-
}
|
|
331
|
-
catch (e) {
|
|
332
|
-
rethrowWithContext(e, 'Failed to issue payment grant');
|
|
333
|
-
}
|
|
334
|
-
},
|
|
335
|
-
};
|
|
336
|
-
export const paymentAttenuateGrantCapability = {
|
|
337
|
-
key: 'payment_attenuate_grant',
|
|
338
|
-
names: { sdk: 'payment_attenuate_grant', mcp: 'ziggs_payment_attenuate_grant' },
|
|
339
|
-
title: 'Pass on a tighter spend grant',
|
|
340
|
-
descriptions: {
|
|
341
|
-
sdk: 'Re-delegate a payment grant you hold to another agent with TIGHTER caveats (narrowing only — the child can never exceed the parent). Use to pass a bounded spend slice to a sub-agent.',
|
|
342
|
-
mcp: 'Re-delegate a payment grant you hold to another agent with TIGHTER caveats (narrowing only — the child can never exceed the parent). Use to pass a bounded spend slice to a sub-agent.',
|
|
343
|
-
},
|
|
344
|
-
annotation: 'write',
|
|
345
|
-
params: {
|
|
346
|
-
grantId: { type: 'string', required: true, description: 'Parent grant to attenuate' },
|
|
347
|
-
holderId: {
|
|
348
|
-
type: 'string',
|
|
349
|
-
required: true,
|
|
350
|
-
description: 'Agent that will hold the narrowed grant',
|
|
351
|
-
},
|
|
352
|
-
...grantCaveatParams,
|
|
353
|
-
},
|
|
354
|
-
handler: async (args, env) => {
|
|
355
|
-
const grantId = args['grantId'];
|
|
356
|
-
if (!grantId)
|
|
357
|
-
throw new Error('grantId is required');
|
|
358
|
-
if (!args['holderId'])
|
|
359
|
-
throw new Error('holderId is required');
|
|
360
|
-
try {
|
|
361
|
-
const caveats = buildCaveats(args);
|
|
362
|
-
const { grant } = await client(env).attenuateGrant({
|
|
363
|
-
grantId,
|
|
364
|
-
holderId: args['holderId'],
|
|
365
|
-
caveats,
|
|
366
|
-
});
|
|
367
|
-
return {
|
|
368
|
-
grantId: grant?.grantId || null,
|
|
369
|
-
parentGrantId: grant?.parentGrantId || grantId,
|
|
370
|
-
holderId: grant?.holderId || args['holderId'],
|
|
371
|
-
caveats: grant?.caveats || caveats,
|
|
372
|
-
expiresAt: grant?.expiresAt || null,
|
|
373
|
-
};
|
|
374
|
-
}
|
|
375
|
-
catch (e) {
|
|
376
|
-
rethrowWithContext(e, 'Failed to attenuate payment grant');
|
|
377
|
-
}
|
|
378
|
-
},
|
|
379
|
-
};
|
|
380
|
-
export const paymentRevokeGrantCapability = {
|
|
381
|
-
key: 'payment_revoke_grant',
|
|
382
|
-
names: { sdk: 'payment_revoke_grant', mcp: 'ziggs_payment_revoke_grant' },
|
|
383
|
-
title: 'Revoke a spend grant',
|
|
384
|
-
descriptions: {
|
|
385
|
-
sdk: 'Revoke a payment grant (and its attenuated children). The holder can no longer spend under it.',
|
|
386
|
-
mcp: 'Revoke a payment grant (and its attenuated children). The holder can no longer spend under it.',
|
|
387
|
-
},
|
|
388
|
-
annotation: 'destructive',
|
|
389
|
-
params: {
|
|
390
|
-
grantId: { type: 'string', required: true, description: 'Grant to revoke' },
|
|
391
|
-
},
|
|
392
|
-
handler: async (args, env) => {
|
|
393
|
-
const grantId = args['grantId'];
|
|
394
|
-
if (!grantId)
|
|
395
|
-
throw new Error('grantId is required');
|
|
396
|
-
try {
|
|
397
|
-
const result = await client(env).revokeGrant(grantId);
|
|
398
|
-
return { status: 'revoked', grantId, revoked: result?.revoked ?? null };
|
|
399
|
-
}
|
|
400
|
-
catch (e) {
|
|
401
|
-
rethrowWithContext(e, 'Failed to revoke payment grant');
|
|
48
|
+
rethrowWithContext(e, 'Failed to read points balance');
|
|
402
49
|
}
|
|
403
50
|
},
|
|
404
51
|
};
|
|
405
|
-
// payment_list_grants stays retired; the wallet rail is part of the
|
|
406
|
-
// unified grant_list capability (scopeKind: 'wallet'). Grant *mutations* stay
|
|
407
|
-
// on the payment rail above.
|
|
408
52
|
export const PAYMENT_CAPABILITIES = [
|
|
409
53
|
paymentBalanceCapability,
|
|
410
|
-
paymentTransferCapability,
|
|
411
|
-
paymentWaitForApprovalCapability,
|
|
412
|
-
paymentHoldCapability,
|
|
413
|
-
paymentReleaseCapability,
|
|
414
|
-
paymentResolveWalletCapability,
|
|
415
|
-
paymentIssueGrantCapability,
|
|
416
|
-
paymentAttenuateGrantCapability,
|
|
417
|
-
paymentRevokeGrantCapability,
|
|
418
54
|
];
|
|
@@ -3,4 +3,4 @@
|
|
|
3
3
|
* tools. Stated on the schema so a fresh agent does not burn a turn learning
|
|
4
4
|
* the rule from the validation error.
|
|
5
5
|
*/
|
|
6
|
-
export declare const AGREEMENT_PROPOSE_PROVIDER_ID_DESCRIPTION = "REQUIRED on a direct proposal: name who does the work \u2014 your own id (you are offering to work) or the proposedTo id (you are commissioning the recipient). Do not omit it when proposedTo is a person/agent id. Broadcast (proposedTo everyone/org): omit for a
|
|
6
|
+
export declare const AGREEMENT_PROPOSE_PROVIDER_ID_DESCRIPTION = "REQUIRED on a direct proposal: name who does the work \u2014 your own id (you are offering to work) or the proposedTo id (you are commissioning the recipient). Do not omit it when proposedTo is a person/agent id. Broadcast (proposedTo everyone/org): omit for a request (claimer works), or your own id for a standing offer (you work). A third-party id brokers and needs a matching published offer. Payer is always the non-providing side.";
|
|
@@ -3,4 +3,4 @@
|
|
|
3
3
|
* tools. Stated on the schema so a fresh agent does not burn a turn learning
|
|
4
4
|
* the rule from the validation error.
|
|
5
5
|
*/
|
|
6
|
-
export const AGREEMENT_PROPOSE_PROVIDER_ID_DESCRIPTION = 'REQUIRED on a direct proposal: name who does the work — your own id (you are offering to work) or the proposedTo id (you are commissioning the recipient). Do not omit it when proposedTo is a person/agent id. Broadcast (proposedTo everyone/org): omit for a
|
|
6
|
+
export const AGREEMENT_PROPOSE_PROVIDER_ID_DESCRIPTION = 'REQUIRED on a direct proposal: name who does the work — your own id (you are offering to work) or the proposedTo id (you are commissioning the recipient). Do not omit it when proposedTo is a person/agent id. Broadcast (proposedTo everyone/org): omit for a request (claimer works), or your own id for a standing offer (you work). A third-party id brokers and needs a matching published offer. Payer is always the non-providing side.';
|