@ziggs-ai/agent-sdk 0.4.1 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. package/dist/AgentHost.d.ts +21 -0
  2. package/dist/AgentHost.js +61 -13
  3. package/dist/agent/Agent.d.ts +9 -0
  4. package/dist/agent/ClaudeSdkAgent.d.ts +1 -1
  5. package/dist/agent/ClaudeSdkAgent.js +47 -12
  6. package/dist/agent/claudeSdkTools.js +1 -1
  7. package/dist/defineAgent.d.ts +10 -5
  8. package/dist/defineAgent.js +16 -9
  9. package/dist/runtime/runTurn.js +12 -2
  10. package/dist/runtime/taskIntake.d.ts +18 -0
  11. package/dist/runtime/taskIntake.js +113 -0
  12. package/dist/server/ConnectionPool.d.ts +9 -2
  13. package/dist/server/ConnectionPool.js +18 -2
  14. package/dist/server/inboxLoop.d.ts +31 -11
  15. package/dist/server/inboxLoop.js +134 -104
  16. package/dist/server/runLauncher.js +9 -3
  17. package/dist/server/staleBacklogGate.d.ts +9 -5
  18. package/dist/server/staleBacklogGate.js +17 -37
  19. package/dist/server/tools/tier1/protocolTools.js +2 -2
  20. package/dist/server/tools/tier2/artifactTools.d.ts +1 -1
  21. package/dist/server/tools/tier2/artifactTools.js +7 -82
  22. package/dist/server/tools/tier2/chatTools.d.ts +1 -1
  23. package/dist/server/tools/tier2/chatTools.js +7 -37
  24. package/dist/server/tools/tier2/connectionTools.d.ts +1 -1
  25. package/dist/server/tools/tier2/connectionTools.js +20 -94
  26. package/dist/server/tools/tier2/contextTools.d.ts +2 -2
  27. package/dist/server/tools/tier2/contextTools.js +10 -139
  28. package/dist/server/tools/tier2/discoveryTools.d.ts +1 -1
  29. package/dist/server/tools/tier2/discoveryTools.js +7 -24
  30. package/dist/server/tools/tier2/grantsTools.d.ts +1 -1
  31. package/dist/server/tools/tier2/grantsTools.js +6 -81
  32. package/dist/server/tools/tier2/linkTools.d.ts +1 -1
  33. package/dist/server/tools/tier2/linkTools.js +12 -156
  34. package/dist/server/tools/tier2/paymentTools.d.ts +2 -2
  35. package/dist/server/tools/tier2/paymentTools.js +16 -161
  36. package/dist/tools/capabilityAdapter.d.ts +11 -0
  37. package/dist/tools/capabilityAdapter.js +30 -0
  38. package/dist/types.d.ts +3 -2
  39. package/package.json +2 -2
@@ -1,161 +1,16 @@
1
- import { defineTool } from '../../../tools/defineTool.js';
2
- import { PaymentsClient } from '@ziggs-ai/api-client';
3
- function clientFor(ctx) {
4
- const operatorKey = ctx?.['operatorKey'];
5
- if (!operatorKey)
6
- throw new Error('operatorKey missing from tool context');
7
- // BACKEND_URL / ZIGGS_BACKEND_URL are the SDK runner's overrides; the shared
8
- // client defaults to HTTP_URL (api-client convention) when neither is set.
9
- const baseUrl = process.env.BACKEND_URL || process.env.ZIGGS_BACKEND_URL || undefined;
10
- return new PaymentsClient(operatorKey, ctx?.['agentId'] || undefined, baseUrl);
11
- }
12
- function rethrowWithContext(error, prefix) {
13
- const e = error;
14
- const wrapped = new Error(`${prefix}: ${e.message}`);
15
- if (e.status !== undefined)
16
- wrapped.status = e.status;
17
- if (e.body !== undefined)
18
- wrapped.body = e.body;
19
- wrapped['cause'] = error;
20
- throw wrapped;
21
- }
22
- function buildCaveats(args) {
23
- const caveats = [];
24
- if (args['maxAmount'] != null)
25
- caveats.push({ type: 'max_amount', value: args['maxAmount'] });
26
- if (args['dailyBudget'] != null)
27
- caveats.push({ type: 'daily_budget', value: args['dailyBudget'] });
28
- if (args['allowedRecipients'] != null)
29
- caveats.push({ type: 'allowed_recipients', value: args['allowedRecipients'] });
30
- if (args['expiresInSeconds'] != null)
31
- caveats.push({ type: 'expires_at', value: Date.now() + args['expiresInSeconds'] * 1000 });
32
- return caveats;
33
- }
34
- export const paymentBalanceTool = defineTool('payment_balance', {}, async (_args, ctx) => {
35
- try {
36
- return await clientFor(ctx).balance();
37
- }
38
- catch (e) {
39
- rethrowWithContext(e, 'Failed to get balance');
40
- }
41
- }, { description: "Check the caller's current wallet balance and available balance (total minus active holds). Use before a transfer to confirm sufficient funds." });
42
- export const paymentTransferTool = defineTool('payment_transfer', { toWalletId: { type: 'string', required: true }, amount: { type: 'number', required: true }, description: 'string', idempotencyKey: 'string', paymentGrantId: 'string' }, async (args, ctx) => {
43
- if (!args['toWalletId'])
44
- throw new Error('toWalletId is required');
45
- if (!args['amount'] || args['amount'] <= 0)
46
- throw new Error('amount must be positive');
47
- const client = clientFor(ctx);
48
- let result;
49
- try {
50
- result = await client.transfer({ to: args['toWalletId'], amount: Math.round(args['amount']), description: args['description'] || 'Agent-initiated transfer', idempotencyKey: args['idempotencyKey'], paymentGrantId: args['paymentGrantId'] });
51
- }
52
- catch (e) {
53
- rethrowWithContext(e, 'Transfer failed');
54
- }
55
- if (result['status'] === 'approval_required') {
56
- return { status: 'approval_required', approvalId: result['approvalId'] || null, expiresAt: result['expiresAt'] || null, reason: result['reason'] || null, amount: args['amount'], toWalletId: result['toWalletId'],
57
- message: 'Transfer paused: the wallet owner must approve this amount.',
58
- next_actions: [{ tool: 'payment_wait_for_approval', when: 'You expect a quick decision (≤2 min) and can wait inline.', args: { approvalId: result['approvalId'], timeoutMs: 120000 } }, { tool: 'task_update_plan_step', when: 'You want to abandon the transfer and route around it.' }] };
59
- }
60
- return { status: 'transferred', transactionId: result['transactionId'] || null, amount: args['amount'], toWalletId: result['toWalletId'] };
61
- });
62
- export const paymentWaitForApprovalTool = defineTool('payment_wait_for_approval', { approvalId: { type: 'string', required: true }, timeoutMs: 'number', pollMs: 'number' }, async (args, ctx) => {
63
- if (!args['approvalId'])
64
- throw new Error('approvalId is required');
65
- try {
66
- const result = await clientFor(ctx).waitForApproval(args['approvalId'], { timeoutMs: args['timeoutMs'], pollMs: args['pollMs'] });
67
- return { status: result['status'], approvalId: args['approvalId'], transactionId: result['transactionId'] || null, approval: result['approval'] || null };
68
- }
69
- catch (e) {
70
- rethrowWithContext(e, 'wait_for_approval failed');
71
- }
72
- });
73
- export const paymentResolveWalletTool = defineTool('payment_resolve_wallet', { userId: 'string', agentId: 'string' }, async (args, ctx) => {
74
- if (!args['userId'] && !args['agentId'])
75
- throw new Error('Provide userId or agentId to resolve a wallet');
76
- try {
77
- const wallet = await clientFor(ctx).resolve({ userId: args['userId'], agentId: args['agentId'] });
78
- return { walletId: wallet?.['walletId'] || null, ownerId: wallet?.['ownerId'] || null, currency: wallet?.['currency'] || 'pez', status: wallet?.['status'] || null };
79
- }
80
- catch (e) {
81
- rethrowWithContext(e, 'Failed to resolve wallet');
82
- }
83
- }, { description: 'Look up a walletId by userId or agentId. Use before a transfer when you only know the recipient by their platform ID.' });
84
- export const paymentHoldTool = defineTool('payment_hold', { amount: { type: 'number', required: true }, description: 'string', idempotencyKey: 'string' }, async (args, ctx) => {
85
- if (!args['amount'] || args['amount'] <= 0)
86
- throw new Error('amount must be positive');
87
- try {
88
- const result = await clientFor(ctx).hold({ amount: Math.round(args['amount']), description: args['description'] || 'Agent escrow hold', idempotencyKey: args['idempotencyKey'] });
89
- return { status: 'held', transactionId: result['transaction']?.['transactionId'] || null, amount: args['amount'] };
90
- }
91
- catch (e) {
92
- rethrowWithContext(e, 'Hold failed');
93
- }
94
- }, { description: '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.' });
95
- export const paymentReleaseTool = defineTool('payment_release', { holdId: { type: 'string', required: true }, action: { type: 'string', required: true }, toWalletId: 'string', idempotencyKey: 'string' }, async (args, ctx) => {
96
- if (!args['holdId'])
97
- throw new Error('holdId is required');
98
- if (args['action'] !== 'complete' && args['action'] !== 'refund')
99
- throw new Error("action must be 'complete' or 'refund'");
100
- if (args['action'] === 'complete' && !args['toWalletId'])
101
- throw new Error('toWalletId is required when action=complete');
102
- try {
103
- const result = await clientFor(ctx).release({ holdId: args['holdId'], action: args['action'], toWalletId: args['toWalletId'], idempotencyKey: args['idempotencyKey'] });
104
- return { status: args['action'] === 'complete' ? 'settled' : 'refunded', transactionId: result['transaction']?.['transactionId'] || null, holdId: args['holdId'], action: args['action'] };
105
- }
106
- catch (e) {
107
- rethrowWithContext(e, 'Release failed');
108
- }
109
- }, { description: "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)." });
110
- const issueGrantHandler = async (args, ctx) => {
111
- if (!args['holderId'])
112
- throw new Error('holderId is required');
113
- try {
114
- const caveats = buildCaveats(args);
115
- const result = await clientFor(ctx).issueGrant({ holderId: args['holderId'], caveats });
116
- const grant = result['grant'];
117
- return { grantId: grant?.['grantId'] || null, holderId: grant?.['holderId'] || args['holderId'], caveats: grant?.['caveats'] || caveats, expiresAt: grant?.['expiresAt'] || null };
118
- }
119
- catch (e) {
120
- rethrowWithContext(e, 'Failed to issue payment grant');
121
- }
122
- };
123
- export const paymentIssueGrantTool = defineTool('payment_issue_grant', { holderId: { type: 'string', required: true }, maxAmount: 'number', dailyBudget: 'number', allowedRecipients: ['string'], expiresInSeconds: 'number' }, issueGrantHandler);
124
- const attenuateGrantHandler = async (args, ctx) => {
125
- const grantId = args['grantId'];
126
- if (!grantId)
127
- throw new Error('grantId is required');
128
- if (!args['holderId'])
129
- throw new Error('holderId is required');
130
- try {
131
- const caveats = buildCaveats(args);
132
- const result = await clientFor(ctx).attenuateGrant({ grantId, holderId: args['holderId'], caveats });
133
- const grant = result['grant'];
134
- return { grantId: grant?.['grantId'] || null, parentGrantId: grant?.['parentGrantId'] || grantId, holderId: grant?.['holderId'] || args['holderId'], caveats: grant?.['caveats'] || caveats, expiresAt: grant?.['expiresAt'] || null };
135
- }
136
- catch (e) {
137
- rethrowWithContext(e, 'Failed to attenuate payment grant');
138
- }
139
- };
140
- export const paymentAttenuateGrantTool = defineTool('payment_attenuate_grant', { grantId: { type: 'string', required: true }, holderId: { type: 'string', required: true }, maxAmount: 'number', dailyBudget: 'number', allowedRecipients: ['string'], expiresInSeconds: 'number' }, attenuateGrantHandler);
141
- const revokeGrantHandler = async (args, ctx) => {
142
- const grantId = args['grantId'];
143
- if (!grantId)
144
- throw new Error('grantId is required');
145
- try {
146
- const result = await clientFor(ctx).revokeGrant(grantId);
147
- return { status: 'revoked', grantId, revoked: result['revoked'] ?? null };
148
- }
149
- catch (e) {
150
- rethrowWithContext(e, 'Failed to revoke payment grant');
151
- }
152
- };
153
- export const paymentRevokeGrantTool = defineTool('payment_revoke_grant', { grantId: { type: 'string', required: true } }, revokeGrantHandler);
154
- // ZIG-893 — payment_list_grants retired; the wallet rail is now part of the
155
- // unified list_grants tool (scopeKind: 'wallet'). Grant *mutations* stay on the
156
- // payment rail (issue/attenuate/revoke below).
157
- export const PAYMENT_TOOLS = [
158
- paymentBalanceTool, paymentTransferTool, paymentWaitForApprovalTool,
159
- paymentHoldTool, paymentReleaseTool, paymentResolveWalletTool,
160
- paymentIssueGrantTool, paymentAttenuateGrantTool, paymentRevokeGrantTool,
161
- ];
1
+ import { PAYMENT_CAPABILITIES, paymentBalanceCapability, paymentTransferCapability, paymentWaitForApprovalCapability, paymentHoldCapability, paymentReleaseCapability, paymentResolveWalletCapability, paymentIssueGrantCapability, paymentAttenuateGrantCapability, paymentRevokeGrantCapability, } from '@ziggs-ai/api-client';
2
+ import { toolFromCapability, toolsFromCapabilities } from '../../../tools/capabilityAdapter.js';
3
+ // ZIG-956 — the wallet toolset is defined once in api-client's shared
4
+ // capability layer; this file only adapts it onto the SDK surface. Safety is
5
+ // unchanged: money-moving calls stay policy-gated server-side, and there is
6
+ // deliberately NO approve/decide tool on the agent surface.
7
+ export const paymentBalanceTool = toolFromCapability(paymentBalanceCapability);
8
+ export const paymentTransferTool = toolFromCapability(paymentTransferCapability);
9
+ export const paymentWaitForApprovalTool = toolFromCapability(paymentWaitForApprovalCapability);
10
+ export const paymentHoldTool = toolFromCapability(paymentHoldCapability);
11
+ export const paymentReleaseTool = toolFromCapability(paymentReleaseCapability);
12
+ export const paymentResolveWalletTool = toolFromCapability(paymentResolveWalletCapability);
13
+ export const paymentIssueGrantTool = toolFromCapability(paymentIssueGrantCapability);
14
+ export const paymentAttenuateGrantTool = toolFromCapability(paymentAttenuateGrantCapability);
15
+ export const paymentRevokeGrantTool = toolFromCapability(paymentRevokeGrantCapability);
16
+ export const PAYMENT_TOOLS = toolsFromCapabilities(PAYMENT_CAPABILITIES);
@@ -0,0 +1,11 @@
1
+ import { type ToolDefinition } from './defineTool.js';
2
+ import type { CapabilityDefinition } from '@ziggs-ai/api-client';
3
+ /**
4
+ * ZIG-956 — the SDK surface adapter for shared capability definitions
5
+ * (api-client `capabilities/`). One capability (schema + handler + guidance)
6
+ * becomes a defineTool ToolDefinition: the neutral param DSL feeds defineTool's
7
+ * JSON-schema converter unchanged, and the handler runs with creds pulled from
8
+ * tool context plus the SDK runner's base-URL overrides.
9
+ */
10
+ export declare function toolFromCapability(cap: CapabilityDefinition): ToolDefinition;
11
+ export declare function toolsFromCapabilities(caps: CapabilityDefinition[]): ToolDefinition[];
@@ -0,0 +1,30 @@
1
+ import { defineTool } from './defineTool.js';
2
+ /**
3
+ * ZIG-956 — the SDK surface adapter for shared capability definitions
4
+ * (api-client `capabilities/`). One capability (schema + handler + guidance)
5
+ * becomes a defineTool ToolDefinition: the neutral param DSL feeds defineTool's
6
+ * JSON-schema converter unchanged, and the handler runs with creds pulled from
7
+ * tool context plus the SDK runner's base-URL overrides.
8
+ */
9
+ export function toolFromCapability(cap) {
10
+ return defineTool(cap.names.sdk, cap.params, async (args, ctx) => {
11
+ const operatorKey = ctx?.['operatorKey'];
12
+ const agentId = ctx?.['agentId'];
13
+ if (!operatorKey)
14
+ throw new Error('operatorKey missing from tool context');
15
+ if (cap.needsAgentId && !agentId)
16
+ throw new Error('agentId missing from tool context');
17
+ const env = {
18
+ creds: { operatorKey, ...(agentId ? { agentId } : {}) },
19
+ // BACKEND_URL / ZIGGS_BACKEND_URL are the SDK runner's overrides; the
20
+ // shared clients default to HTTP_URL (api-client convention) otherwise.
21
+ baseUrl: process.env.BACKEND_URL || process.env.ZIGGS_BACKEND_URL || undefined,
22
+ webUrl: process.env.ZIGGS_WEB_URL,
23
+ surface: 'sdk',
24
+ };
25
+ return cap.handler(args, env);
26
+ }, { description: cap.descriptions.sdk, ...(cap.sdkOptions ?? {}) });
27
+ }
28
+ export function toolsFromCapabilities(caps) {
29
+ return caps.map(toolFromCapability);
30
+ }
package/dist/types.d.ts CHANGED
@@ -313,8 +313,9 @@ export interface ContextSnapshot {
313
313
  * The session's chat no longer resolves on the backend (messages read
314
314
  * 404'd) — deleted or never visible to this agent. Message-triggered wakes
315
315
  * check this and skip the LLM instead of reasoning over a fabricated empty
316
- * history. Agreement-keyed lanes also set it (their sessionId is not a
317
- * chat), so it only gates message wakes, never task lanes.
316
+ * history. Only gates message wakes. A bare agreementId as sessionId also
317
+ * trips it (ZIG-975) — that is a mis-keyed lane, not a legitimate task lane;
318
+ * task wakes should key on the agreement's origin/notification chat.
318
319
  */
319
320
  chatMissing?: boolean;
320
321
  /** Index signature so PromptBuilder's `ServerContext` can accept it directly. */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ziggs-ai/agent-sdk",
3
- "version": "0.4.1",
3
+ "version": "0.6.0",
4
4
  "description": "Agent framework SDK for building autonomous agents on the Ziggs platform",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -26,7 +26,7 @@
26
26
  "@anthropic-ai/claude-agent-sdk": "^0.3.204",
27
27
  "@anthropic-ai/sdk": "^0.110.0",
28
28
  "@modelcontextprotocol/sdk": "^1.29.0",
29
- "@ziggs-ai/api-client": "^0.3.1",
29
+ "@ziggs-ai/api-client": "^0.5.0",
30
30
  "ajv": "^8.17.1",
31
31
  "dotenv": "^17.2.3",
32
32
  "openai": "^4.0.0",