@ziggs-ai/agent-sdk 0.1.12 → 0.2.1
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/CHANGELOG.md +14 -0
- package/README.md +41 -2
- package/dist/AgentHost.d.ts +201 -0
- package/dist/AgentHost.js +652 -0
- package/dist/adapters/AnthropicAdapter.d.ts +39 -0
- package/dist/adapters/AnthropicAdapter.js +200 -0
- package/dist/adapters/McpAdapter.d.ts +199 -0
- package/dist/adapters/McpAdapter.js +468 -0
- package/dist/adapters/OpenAIAdapter.d.ts +26 -0
- package/dist/adapters/OpenAIAdapter.js +158 -0
- package/dist/adapters/index.js +2 -0
- package/dist/agent/Agent.d.ts +78 -0
- package/dist/agent/Agent.js +58 -0
- package/dist/agent/ClaudeSdkAgent.d.ts +38 -0
- package/dist/agent/ClaudeSdkAgent.js +322 -0
- package/dist/agent/claudeCognition.d.ts +67 -0
- package/dist/agent/claudeCognition.js +103 -0
- package/dist/agent/claudeSdkProtocol.d.ts +11 -0
- package/dist/agent/claudeSdkTools.d.ts +19 -0
- package/dist/agent/claudeSdkTools.js +57 -0
- package/dist/agent/hostedAgentConnection.d.ts +15 -0
- package/dist/agent/hostedAgentConnection.js +29 -0
- package/dist/agent/toolManagerToSdkMcp.d.ts +12 -0
- package/dist/agent/toolManagerToSdkMcp.js +123 -0
- package/dist/brain/index.d.ts +50 -0
- package/dist/brain/index.js +45 -0
- package/dist/cognition/validateContext.d.ts +11 -0
- package/dist/cognition/validateContext.js +117 -0
- package/dist/context/applyEffects.d.ts +2 -0
- package/dist/context/applyEffects.js +89 -0
- package/dist/context/batch.d.ts +2 -0
- package/dist/context/batch.js +18 -0
- package/dist/context/classifyEnvelope.d.ts +1 -0
- package/dist/context/classifyEnvelope.js +58 -0
- package/dist/context/routingLabels.d.ts +4 -0
- package/dist/context/routingLabels.js +48 -0
- package/dist/defineAgent.d.ts +14 -0
- package/dist/defineAgent.js +68 -0
- package/dist/formatters/AgreementFormatter.d.ts +18 -0
- package/dist/formatters/AgreementFormatter.js +130 -0
- package/dist/formatters/HistoryFormatter.d.ts +26 -0
- package/dist/formatters/HistoryFormatter.js +173 -0
- package/dist/formatters/index.js +2 -0
- package/{src/index.ts → dist/index.d.ts} +7 -53
- package/dist/index.js +66 -0
- package/dist/ingress/normalizeIncoming.d.ts +65 -0
- package/dist/ingress/normalizeIncoming.js +88 -0
- package/dist/memory/MemoryStore.d.ts +55 -0
- package/dist/memory/MemoryStore.js +78 -0
- package/dist/pricing/fleetDefaults.d.ts +46 -0
- package/dist/pricing/fleetDefaults.js +168 -0
- package/dist/pricing/fleetEvalFree.d.ts +7 -0
- package/dist/pricing/fleetEvalFree.js +24 -0
- package/dist/pricing/fleetFreeTierA.gen.d.ts +6 -0
- package/{src/pricing/fleetFreeTierA.gen.ts → dist/pricing/fleetFreeTierA.gen.js} +5 -6
- package/dist/pricing/fleetTierByAgentId.gen.d.ts +7 -0
- package/dist/pricing/fleetTierByAgentId.gen.js +768 -0
- package/dist/runtime/AgentMachine.d.ts +143 -0
- package/dist/runtime/AgentMachine.js +400 -0
- package/dist/runtime/PromptBuilder.d.ts +96 -0
- package/dist/runtime/PromptBuilder.js +439 -0
- package/{src/runtime/bootstrapCtx.ts → dist/runtime/bootstrapCtx.d.ts} +1 -22
- package/dist/runtime/bootstrapCtx.js +37 -0
- package/dist/runtime/buildOutcome.d.ts +68 -0
- package/dist/runtime/buildOutcome.js +464 -0
- package/dist/runtime/defaults.d.ts +54 -0
- package/dist/runtime/defaults.js +47 -0
- package/dist/runtime/deriveRespondsToProposals.d.ts +9 -0
- package/dist/runtime/deriveRespondsToProposals.js +38 -0
- package/dist/runtime/kickoff.d.ts +15 -0
- package/dist/runtime/kickoff.js +112 -0
- package/dist/runtime/runMechanical.d.ts +25 -0
- package/dist/runtime/runMechanical.js +74 -0
- package/dist/runtime/runTurn.d.ts +63 -0
- package/dist/runtime/runTurn.js +800 -0
- package/dist/runtime/validateWorkflow.d.ts +17 -0
- package/dist/runtime/validateWorkflow.js +209 -0
- package/dist/server/ConnectionPool.d.ts +68 -0
- package/dist/server/ConnectionPool.js +166 -0
- package/dist/server/EventQueue.d.ts +33 -0
- package/dist/server/EventQueue.js +98 -0
- package/dist/server/InboxCatchUp.d.ts +24 -0
- package/dist/server/InboxCatchUp.js +214 -0
- package/dist/server/OutboxBuffer.d.ts +33 -0
- package/dist/server/OutboxBuffer.js +68 -0
- package/dist/server/SeenMessages.d.ts +13 -0
- package/dist/server/SeenMessages.js +31 -0
- package/dist/server/StateTimers.d.ts +34 -0
- package/dist/server/StateTimers.js +70 -0
- package/dist/server/ZiggsEffectHandler.d.ts +79 -0
- package/dist/server/ZiggsEffectHandler.js +319 -0
- package/dist/server/agreements/AgreementService.d.ts +50 -0
- package/dist/server/agreements/AgreementService.js +85 -0
- package/dist/server/createHealthServer.d.ts +7 -0
- package/dist/server/createHealthServer.js +75 -0
- package/dist/server/proactive/ProactiveTrigger.d.ts +33 -0
- package/dist/server/proactive/ProactiveTrigger.js +71 -0
- package/dist/server/runLauncher.d.ts +28 -0
- package/dist/server/runLauncher.js +93 -0
- package/dist/server/tasks/TaskService.d.ts +25 -0
- package/dist/server/tasks/TaskService.js +103 -0
- package/dist/server/tasks/index.js +1 -0
- package/dist/server/telemetryIngest.d.ts +24 -0
- package/dist/server/telemetryIngest.js +62 -0
- package/dist/server/tools/index.d.ts +24 -0
- package/{src/server/tools/index.ts → dist/server/tools/index.js} +4 -24
- package/dist/server/tools/tier1/protocolRunner.d.ts +39 -0
- package/dist/server/tools/tier1/protocolRunner.js +288 -0
- package/dist/server/tools/tier1/protocolTools.d.ts +12 -0
- package/dist/server/tools/tier1/protocolTools.js +37 -0
- package/dist/server/tools/tier2/connectionTools.d.ts +4 -0
- package/dist/server/tools/tier2/connectionTools.js +63 -0
- package/dist/server/tools/tier2/contextTools.d.ts +4 -0
- package/dist/server/tools/tier2/contextTools.js +46 -0
- package/dist/server/tools/tier2/discoveryTools.d.ts +4 -0
- package/dist/server/tools/tier2/discoveryTools.js +25 -0
- package/dist/server/tools/tier2/marketplaceTools.d.ts +3 -0
- package/dist/server/tools/tier2/marketplaceTools.js +22 -0
- package/dist/server/tools/tier2/paymentTools.d.ts +12 -0
- package/dist/server/tools/tier2/paymentTools.js +165 -0
- package/dist/server/ziggsconnect/ZiggsConnectClient.d.ts +35 -0
- package/dist/server/ziggsconnect/ZiggsConnectClient.js +95 -0
- package/dist/server/ziggscontext/ZiggsContextClient.d.ts +53 -0
- package/dist/server/ziggscontext/ZiggsContextClient.js +124 -0
- package/dist/server/ziggspay/ZiggsPayClient.d.ts +82 -0
- package/dist/server/ziggspay/ZiggsPayClient.js +203 -0
- package/dist/shared/ids.d.ts +1 -0
- package/dist/shared/ids.js +3 -0
- package/dist/shared/runtimeLog.d.ts +18 -0
- package/dist/shared/runtimeLog.js +68 -0
- package/dist/shared/types.d.ts +22 -0
- package/dist/shared/types.js +23 -0
- package/dist/tasks/protocolRegistry.d.ts +16 -0
- package/dist/tasks/protocolRegistry.js +20 -0
- package/dist/tools/ToolManager.d.ts +12 -0
- package/dist/tools/ToolManager.js +74 -0
- package/dist/tools/ToolProvider.d.ts +6 -0
- package/dist/tools/ToolProvider.js +21 -0
- package/dist/tools/defineTool.d.ts +27 -0
- package/dist/tools/defineTool.js +62 -0
- package/{src/tools/index.ts → dist/tools/index.d.ts} +0 -1
- package/dist/tools/index.js +6 -0
- package/dist/tools/recordReport.d.ts +41 -0
- package/dist/tools/recordReport.js +30 -0
- package/dist/types.d.ts +466 -0
- package/dist/types.js +7 -0
- package/dist/utils/jsonExtractor.d.ts +2 -0
- package/dist/utils/jsonExtractor.js +111 -0
- package/package.json +14 -6
- package/src/AgentHost.ts +0 -814
- package/src/adapters/AnthropicAdapter.ts +0 -238
- package/src/adapters/McpAdapter.ts +0 -678
- package/src/adapters/OpenAIAdapter.ts +0 -194
- package/src/agent/Agent.ts +0 -112
- package/src/agent/ClaudeSdkAgent.ts +0 -401
- package/src/agent/claudeCognition.ts +0 -139
- package/src/agent/claudeSdkTools.ts +0 -81
- package/src/agent/hostedAgentConnection.ts +0 -41
- package/src/agent/toolManagerToSdkMcp.ts +0 -136
- package/src/cognition/validateContext.ts +0 -95
- package/src/context/applyEffects.ts +0 -80
- package/src/context/batch.ts +0 -19
- package/src/context/classifyEnvelope.ts +0 -38
- package/src/context/routingLabels.ts +0 -46
- package/src/defineAgent.ts +0 -77
- package/src/formatters/AgreementFormatter.ts +0 -111
- package/src/formatters/HistoryFormatter.ts +0 -172
- package/src/ingress/normalizeIncoming.ts +0 -162
- package/src/memory/MemoryStore.ts +0 -104
- package/src/pricing/fleetDefaults.ts +0 -225
- package/src/pricing/fleetEvalFree.ts +0 -24
- package/src/pricing/fleetTierByAgentId.gen.ts +0 -775
- package/src/runtime/AgentMachine.ts +0 -484
- package/src/runtime/PromptBuilder.ts +0 -522
- package/src/runtime/buildOutcome.ts +0 -563
- package/src/runtime/defaults.ts +0 -86
- package/src/runtime/deriveRespondsToProposals.ts +0 -35
- package/src/runtime/kickoff.ts +0 -117
- package/src/runtime/runMechanical.ts +0 -106
- package/src/runtime/runTurn.ts +0 -870
- package/src/runtime/validateWorkflow.ts +0 -221
- package/src/server/ConnectionPool.ts +0 -206
- package/src/server/EventQueue.ts +0 -133
- package/src/server/InboxCatchUp.ts +0 -291
- package/src/server/OutboxBuffer.ts +0 -90
- package/src/server/SeenMessages.ts +0 -27
- package/src/server/StateTimers.ts +0 -85
- package/src/server/ZiggsEffectHandler.ts +0 -427
- package/src/server/agreements/AgreementService.ts +0 -118
- package/src/server/createHealthServer.ts +0 -85
- package/src/server/proactive/ProactiveTrigger.ts +0 -83
- package/src/server/runLauncher.ts +0 -146
- package/src/server/tasks/TaskService.ts +0 -111
- package/src/server/telemetryIngest.ts +0 -91
- package/src/server/tools/tier1/protocolRunner.ts +0 -353
- package/src/server/tools/tier1/protocolTools.ts +0 -114
- package/src/server/tools/tier2/connectionTools.ts +0 -75
- package/src/server/tools/tier2/contextTools.ts +0 -63
- package/src/server/tools/tier2/discoveryTools.ts +0 -34
- package/src/server/tools/tier2/marketplaceTools.ts +0 -27
- package/src/server/tools/tier2/paymentTools.ts +0 -170
- package/src/server/ziggsconnect/ZiggsConnectClient.ts +0 -126
- package/src/server/ziggscontext/ZiggsContextClient.ts +0 -129
- package/src/server/ziggspay/ZiggsPayClient.ts +0 -193
- package/src/shared/ids.ts +0 -3
- package/src/shared/runtimeLog.ts +0 -72
- package/src/shared/types.ts +0 -29
- package/src/tasks/protocolRegistry.ts +0 -25
- package/src/tools/ToolManager.ts +0 -95
- package/src/tools/ToolProvider.ts +0 -19
- package/src/tools/defineTool.ts +0 -90
- package/src/tools/recordReport.ts +0 -82
- package/src/types.ts +0 -483
- package/src/utils/jsonExtractor.ts +0 -100
- /package/{src/adapters/index.ts → dist/adapters/index.d.ts} +0 -0
- /package/{src/agent/claudeSdkProtocol.ts → dist/agent/claudeSdkProtocol.js} +0 -0
- /package/{src/formatters/index.ts → dist/formatters/index.d.ts} +0 -0
- /package/{src/server/tasks/index.ts → dist/server/tasks/index.d.ts} +0 -0
|
@@ -1,170 +0,0 @@
|
|
|
1
|
-
import { defineTool, type ToolDefinition } from '../../../tools/defineTool.js';
|
|
2
|
-
import { ZiggsPayClient } from '../../ziggspay/ZiggsPayClient.js';
|
|
3
|
-
|
|
4
|
-
type Ctx = Record<string, unknown>;
|
|
5
|
-
type AnyObj = Record<string, unknown>;
|
|
6
|
-
|
|
7
|
-
function clientFor(ctx: Ctx): ZiggsPayClient {
|
|
8
|
-
const operatorKey = ctx?.['operatorKey'] as string | undefined;
|
|
9
|
-
if (!operatorKey) throw new Error('operatorKey missing from tool context');
|
|
10
|
-
return new ZiggsPayClient({ operatorKey, actAsAgentId: (ctx?.['agentId'] as string) || undefined });
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
interface PayError extends Error { status?: number; body?: string; }
|
|
14
|
-
|
|
15
|
-
function rethrowWithContext(error: unknown, prefix: string): never {
|
|
16
|
-
const e = error as PayError;
|
|
17
|
-
const wrapped = new Error(`${prefix}: ${e.message}`) as PayError;
|
|
18
|
-
if (e.status !== undefined) wrapped.status = e.status;
|
|
19
|
-
if (e.body !== undefined) wrapped.body = e.body;
|
|
20
|
-
(wrapped as unknown as AnyObj)['cause'] = error;
|
|
21
|
-
throw wrapped;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
function buildCaveats(args: AnyObj): AnyObj[] {
|
|
25
|
-
const caveats: AnyObj[] = [];
|
|
26
|
-
if (args['maxAmount'] != null) caveats.push({ type: 'max_amount', value: args['maxAmount'] });
|
|
27
|
-
if (args['dailyBudget'] != null) caveats.push({ type: 'daily_budget', value: args['dailyBudget'] });
|
|
28
|
-
if (args['allowedRecipients'] != null) caveats.push({ type: 'allowed_recipients', value: args['allowedRecipients'] });
|
|
29
|
-
if (args['expiresInSeconds'] != null) caveats.push({ type: 'expires_at', value: Date.now() + (args['expiresInSeconds'] as number) * 1000 });
|
|
30
|
-
return caveats;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
export const paymentBalanceTool: ToolDefinition = defineTool('payment_balance', {},
|
|
34
|
-
async (_args, ctx) => {
|
|
35
|
-
try { return await clientFor(ctx as Ctx).balance(); }
|
|
36
|
-
catch (e) { rethrowWithContext(e, 'Failed to get balance'); }
|
|
37
|
-
},
|
|
38
|
-
{ description: "Check the caller's current wallet balance and available balance (total minus active holds). Use before a transfer to confirm sufficient funds." },
|
|
39
|
-
);
|
|
40
|
-
|
|
41
|
-
export const paymentTransferTool: ToolDefinition = defineTool('payment_transfer',
|
|
42
|
-
{ toWalletId: { type: 'string', required: true }, amount: { type: 'number', required: true }, description: 'string', idempotencyKey: 'string', paymentGrantId: 'string' },
|
|
43
|
-
async (args, ctx) => {
|
|
44
|
-
if (!args['toWalletId']) throw new Error('toWalletId is required');
|
|
45
|
-
if (!args['amount'] || (args['amount'] as number) <= 0) throw new Error('amount must be positive');
|
|
46
|
-
const client = clientFor(ctx as Ctx);
|
|
47
|
-
let result: AnyObj;
|
|
48
|
-
try {
|
|
49
|
-
result = await client.transfer({ to: args['toWalletId'] as string, amount: Math.round(args['amount'] as number), description: (args['description'] as string) || 'Agent-initiated transfer', idempotencyKey: args['idempotencyKey'] as string | undefined, paymentGrantId: args['paymentGrantId'] as string | undefined }) as AnyObj;
|
|
50
|
-
} catch (e) { rethrowWithContext(e, 'Transfer failed'); }
|
|
51
|
-
if (result!['status'] === 'approval_required') {
|
|
52
|
-
return { status: 'approval_required', approvalId: result!['approvalId'] || null, expiresAt: result!['expiresAt'] || null, reason: result!['reason'] || null, amount: args['amount'], toWalletId: result!['toWalletId'],
|
|
53
|
-
message: 'Transfer paused: the wallet owner must approve this amount.',
|
|
54
|
-
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.' }] };
|
|
55
|
-
}
|
|
56
|
-
return { status: 'transferred', transactionId: result!['transactionId'] || null, amount: args['amount'], toWalletId: result!['toWalletId'] };
|
|
57
|
-
},
|
|
58
|
-
);
|
|
59
|
-
|
|
60
|
-
export const paymentWaitForApprovalTool: ToolDefinition = defineTool('payment_wait_for_approval',
|
|
61
|
-
{ approvalId: { type: 'string', required: true }, timeoutMs: 'number', pollMs: 'number' },
|
|
62
|
-
async (args, ctx) => {
|
|
63
|
-
if (!args['approvalId']) throw new Error('approvalId is required');
|
|
64
|
-
try {
|
|
65
|
-
const result = await clientFor(ctx as Ctx).waitForApproval(args['approvalId'] as string, { timeoutMs: args['timeoutMs'] as number | undefined, pollMs: args['pollMs'] as number | undefined }) as AnyObj;
|
|
66
|
-
return { status: result['status'], approvalId: args['approvalId'], transactionId: result['transactionId'] || null, approval: result['approval'] || null };
|
|
67
|
-
} catch (e) { rethrowWithContext(e, 'wait_for_approval failed'); }
|
|
68
|
-
},
|
|
69
|
-
);
|
|
70
|
-
|
|
71
|
-
export const paymentResolveWalletTool: ToolDefinition = defineTool('payment_resolve_wallet',
|
|
72
|
-
{ userId: 'string', agentId: 'string' },
|
|
73
|
-
async (args, ctx) => {
|
|
74
|
-
if (!args['userId'] && !args['agentId']) throw new Error('Provide userId or agentId to resolve a wallet');
|
|
75
|
-
try {
|
|
76
|
-
const wallet = await clientFor(ctx as Ctx).resolve({ userId: args['userId'] as string | undefined, agentId: args['agentId'] as string | undefined }) as AnyObj | null;
|
|
77
|
-
return { walletId: wallet?.['walletId'] || null, ownerId: wallet?.['ownerId'] || null, currency: wallet?.['currency'] || 'pez', status: wallet?.['status'] || null };
|
|
78
|
-
} catch (e) { rethrowWithContext(e, 'Failed to resolve wallet'); }
|
|
79
|
-
},
|
|
80
|
-
{ description: 'Look up a walletId by userId or agentId. Use before a transfer when you only know the recipient by their platform ID.' },
|
|
81
|
-
);
|
|
82
|
-
|
|
83
|
-
export const paymentHoldTool: ToolDefinition = defineTool('payment_hold',
|
|
84
|
-
{ amount: { type: 'number', required: true }, description: 'string', idempotencyKey: 'string' },
|
|
85
|
-
async (args, ctx) => {
|
|
86
|
-
if (!args['amount'] || (args['amount'] as number) <= 0) throw new Error('amount must be positive');
|
|
87
|
-
try {
|
|
88
|
-
const result = await clientFor(ctx as Ctx).hold({ amount: Math.round(args['amount'] as number), description: (args['description'] as string) || 'Agent escrow hold', idempotencyKey: args['idempotencyKey'] as string | undefined }) as AnyObj;
|
|
89
|
-
return { status: 'held', transactionId: (result['transaction'] as AnyObj | undefined)?.['transactionId'] || null, amount: args['amount'] };
|
|
90
|
-
} catch (e) { rethrowWithContext(e, 'Hold failed'); }
|
|
91
|
-
},
|
|
92
|
-
{ 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.' },
|
|
93
|
-
);
|
|
94
|
-
|
|
95
|
-
export const paymentReleaseTool: ToolDefinition = defineTool('payment_release',
|
|
96
|
-
{ holdId: { type: 'string', required: true }, action: { type: 'string', required: true }, toWalletId: 'string', idempotencyKey: 'string' },
|
|
97
|
-
async (args, ctx) => {
|
|
98
|
-
if (!args['holdId']) throw new Error('holdId is required');
|
|
99
|
-
if (args['action'] !== 'complete' && args['action'] !== 'refund') throw new Error("action must be 'complete' or 'refund'");
|
|
100
|
-
if (args['action'] === 'complete' && !args['toWalletId']) throw new Error('toWalletId is required when action=complete');
|
|
101
|
-
try {
|
|
102
|
-
const result = await clientFor(ctx as Ctx).release({ holdId: args['holdId'] as string, action: args['action'] as string, toWalletId: args['toWalletId'] as string | undefined, idempotencyKey: args['idempotencyKey'] as string | undefined }) as AnyObj;
|
|
103
|
-
return { status: args['action'] === 'complete' ? 'settled' : 'refunded', transactionId: (result['transaction'] as AnyObj | undefined)?.['transactionId'] || null, holdId: args['holdId'], action: args['action'] };
|
|
104
|
-
} catch (e) { rethrowWithContext(e, 'Release failed'); }
|
|
105
|
-
},
|
|
106
|
-
{ 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)." },
|
|
107
|
-
);
|
|
108
|
-
|
|
109
|
-
const issueGrantHandler = async (args: AnyObj, ctx: Ctx) => {
|
|
110
|
-
if (!args['holderId']) throw new Error('holderId is required');
|
|
111
|
-
try {
|
|
112
|
-
const caveats = buildCaveats(args);
|
|
113
|
-
const result = await clientFor(ctx).issueGrant({ holderId: args['holderId'] as string, caveats }) as AnyObj;
|
|
114
|
-
const grant = result['grant'] as AnyObj | undefined;
|
|
115
|
-
return { grantId: grant?.['grantId'] || null, holderId: grant?.['holderId'] || args['holderId'], caveats: grant?.['caveats'] || caveats, expiresAt: grant?.['expiresAt'] || null };
|
|
116
|
-
} catch (e) { rethrowWithContext(e, 'Failed to issue payment grant'); }
|
|
117
|
-
};
|
|
118
|
-
|
|
119
|
-
export const paymentIssueGrantTool: ToolDefinition = defineTool('payment_issue_grant',
|
|
120
|
-
{ holderId: { type: 'string', required: true }, maxAmount: 'number', dailyBudget: 'number', allowedRecipients: ['string'], expiresInSeconds: 'number' },
|
|
121
|
-
issueGrantHandler,
|
|
122
|
-
);
|
|
123
|
-
|
|
124
|
-
const attenuateGrantHandler = async (args: AnyObj, ctx: Ctx) => {
|
|
125
|
-
const grantId = args['grantId'] as string;
|
|
126
|
-
if (!grantId) throw new Error('grantId is required');
|
|
127
|
-
if (!args['holderId']) throw new Error('holderId is required');
|
|
128
|
-
try {
|
|
129
|
-
const caveats = buildCaveats(args);
|
|
130
|
-
const result = await clientFor(ctx).attenuateGrant({ grantId, holderId: args['holderId'] as string, caveats }) as AnyObj;
|
|
131
|
-
const grant = result['grant'] as AnyObj | undefined;
|
|
132
|
-
return { grantId: grant?.['grantId'] || null, parentGrantId: grant?.['parentGrantId'] || grantId, holderId: grant?.['holderId'] || args['holderId'], caveats: grant?.['caveats'] || caveats, expiresAt: grant?.['expiresAt'] || null };
|
|
133
|
-
} catch (e) { rethrowWithContext(e, 'Failed to attenuate payment grant'); }
|
|
134
|
-
};
|
|
135
|
-
|
|
136
|
-
export const paymentAttenuateGrantTool: ToolDefinition = defineTool('payment_attenuate_grant',
|
|
137
|
-
{ grantId: { type: 'string', required: true }, holderId: { type: 'string', required: true }, maxAmount: 'number', dailyBudget: 'number', allowedRecipients: ['string'], expiresInSeconds: 'number' },
|
|
138
|
-
attenuateGrantHandler,
|
|
139
|
-
);
|
|
140
|
-
|
|
141
|
-
const revokeGrantHandler = async (args: AnyObj, ctx: Ctx) => {
|
|
142
|
-
const grantId = args['grantId'] as string;
|
|
143
|
-
if (!grantId) throw new Error('grantId is required');
|
|
144
|
-
try {
|
|
145
|
-
const result = await clientFor(ctx).revokeGrant(grantId) as AnyObj;
|
|
146
|
-
return { status: 'revoked', grantId, revoked: result['revoked'] ?? null };
|
|
147
|
-
} catch (e) { rethrowWithContext(e, 'Failed to revoke payment grant'); }
|
|
148
|
-
};
|
|
149
|
-
|
|
150
|
-
export const paymentRevokeGrantTool: ToolDefinition = defineTool('payment_revoke_grant',
|
|
151
|
-
{ grantId: { type: 'string', required: true } },
|
|
152
|
-
revokeGrantHandler,
|
|
153
|
-
);
|
|
154
|
-
|
|
155
|
-
const listGrantsHandler = async (_args: AnyObj, ctx: Ctx) => {
|
|
156
|
-
try {
|
|
157
|
-
const result = await clientFor(ctx).listGrants();
|
|
158
|
-
return { grants: result || [] };
|
|
159
|
-
} catch (e) { rethrowWithContext(e, 'Failed to list payment grants'); }
|
|
160
|
-
};
|
|
161
|
-
|
|
162
|
-
export const paymentListGrantsTool: ToolDefinition = defineTool('payment_list_grants', {},
|
|
163
|
-
listGrantsHandler,
|
|
164
|
-
);
|
|
165
|
-
|
|
166
|
-
export const PAYMENT_TOOLS: ToolDefinition[] = [
|
|
167
|
-
paymentBalanceTool, paymentTransferTool, paymentWaitForApprovalTool,
|
|
168
|
-
paymentHoldTool, paymentReleaseTool, paymentResolveWalletTool,
|
|
169
|
-
paymentIssueGrantTool, paymentAttenuateGrantTool, paymentRevokeGrantTool, paymentListGrantsTool,
|
|
170
|
-
];
|
|
@@ -1,126 +0,0 @@
|
|
|
1
|
-
import 'dotenv/config';
|
|
2
|
-
|
|
3
|
-
function getDefaultBaseUrl(): string {
|
|
4
|
-
return process.env.BACKEND_URL || process.env.ZIGGS_BACKEND_URL || 'http://localhost:3000';
|
|
5
|
-
}
|
|
6
|
-
|
|
7
|
-
function parseError(text: string, fallback: string): string {
|
|
8
|
-
if (!text) return fallback;
|
|
9
|
-
try {
|
|
10
|
-
const parsed = JSON.parse(text) as Record<string, unknown>;
|
|
11
|
-
return (parsed['message'] as string) || (parsed['error'] as string) || text;
|
|
12
|
-
} catch {
|
|
13
|
-
return text;
|
|
14
|
-
}
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
interface ConnectError extends Error {
|
|
18
|
-
status?: number;
|
|
19
|
-
body?: string;
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
export interface ZiggsConnectClientOptions {
|
|
23
|
-
operatorKey: string;
|
|
24
|
-
actAsAgentId?: string;
|
|
25
|
-
baseUrl?: string;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
export interface ProxyParams {
|
|
29
|
-
connectionId: string;
|
|
30
|
-
grantId: string;
|
|
31
|
-
action: string;
|
|
32
|
-
payload?: unknown;
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
export class ZiggsConnectClient {
|
|
36
|
-
private operatorKey: string;
|
|
37
|
-
private actAsAgentId: string | null;
|
|
38
|
-
private baseUrl: string;
|
|
39
|
-
|
|
40
|
-
constructor({ operatorKey, actAsAgentId, baseUrl }: ZiggsConnectClientOptions) {
|
|
41
|
-
if (!operatorKey || typeof operatorKey !== 'string') {
|
|
42
|
-
throw new Error('ZiggsConnectClient requires an operatorKey');
|
|
43
|
-
}
|
|
44
|
-
this.operatorKey = operatorKey;
|
|
45
|
-
this.actAsAgentId = actAsAgentId || null;
|
|
46
|
-
this.baseUrl = baseUrl || getDefaultBaseUrl();
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
/**
|
|
50
|
-
* Present a ConnectionGrant to the broker and perform a provider action.
|
|
51
|
-
* Returns the provider result — never the raw OAuth token.
|
|
52
|
-
*/
|
|
53
|
-
async proxy({ connectionId, grantId, action, payload }: ProxyParams): Promise<unknown> {
|
|
54
|
-
if (!connectionId) throw new Error('proxy: connectionId is required');
|
|
55
|
-
if (!grantId) throw new Error('proxy: grantId is required');
|
|
56
|
-
if (!action) throw new Error('proxy: action is required');
|
|
57
|
-
if (!this.actAsAgentId) {
|
|
58
|
-
throw new Error(
|
|
59
|
-
'proxy: actAsAgentId is required — connection broker calls must impersonate the grant holder agent',
|
|
60
|
-
);
|
|
61
|
-
}
|
|
62
|
-
const res = (await this._post(`/connections/${encodeURIComponent(connectionId)}/proxy`, {
|
|
63
|
-
grantId,
|
|
64
|
-
action,
|
|
65
|
-
payload: payload ?? {},
|
|
66
|
-
})) as Record<string, unknown>;
|
|
67
|
-
return res['result'] ?? res;
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
/**
|
|
71
|
-
* List ConnectionGrants held by this agent for a connection.
|
|
72
|
-
* Requires actAsAgentId; filters server rows to holderId === agent.
|
|
73
|
-
*/
|
|
74
|
-
async listGrants({ connectionId }: { connectionId: string }): Promise<unknown[]> {
|
|
75
|
-
if (!connectionId) throw new Error('listGrants: connectionId is required');
|
|
76
|
-
if (!this.actAsAgentId) {
|
|
77
|
-
throw new Error(
|
|
78
|
-
'listGrants: actAsAgentId is required — grants are scoped to the impersonated agent',
|
|
79
|
-
);
|
|
80
|
-
}
|
|
81
|
-
const res = (await this._get(
|
|
82
|
-
`/connections/${encodeURIComponent(connectionId)}/grants`,
|
|
83
|
-
)) as Record<string, unknown>;
|
|
84
|
-
const grants = (res['grants'] as Array<Record<string, unknown>>) || [];
|
|
85
|
-
return grants.filter((g) => g['holderId'] === this.actAsAgentId);
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
private _buildHeaders(extra: Record<string, string> = {}): Record<string, string> {
|
|
89
|
-
const h: Record<string, string> = { Authorization: `Bearer ${this.operatorKey}`, ...extra };
|
|
90
|
-
if (this.actAsAgentId) h['X-Agent-Id'] = this.actAsAgentId;
|
|
91
|
-
return h;
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
private async _request(method: string, path: string, body: unknown): Promise<unknown> {
|
|
95
|
-
const init: RequestInit = {
|
|
96
|
-
method,
|
|
97
|
-
headers: this._buildHeaders(
|
|
98
|
-
body !== undefined ? { 'content-type': 'application/json' } : {},
|
|
99
|
-
),
|
|
100
|
-
};
|
|
101
|
-
if (body !== undefined) init.body = JSON.stringify(body);
|
|
102
|
-
const response = await fetch(`${this.baseUrl}${path}`, init);
|
|
103
|
-
const text = await response.text();
|
|
104
|
-
if (!response.ok) {
|
|
105
|
-
const err = new Error(parseError(text, `HTTP ${response.status}`)) as ConnectError;
|
|
106
|
-
err.status = response.status;
|
|
107
|
-
err.body = text;
|
|
108
|
-
throw err;
|
|
109
|
-
}
|
|
110
|
-
return text ? JSON.parse(text) : null;
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
private _get(path: string): Promise<unknown> {
|
|
114
|
-
return this._request('GET', path, undefined);
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
private _post(path: string, body: unknown): Promise<unknown> {
|
|
118
|
-
return this._request('POST', path, body ?? {});
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
export function createZiggsConnectClient(
|
|
123
|
-
opts: ZiggsConnectClientOptions,
|
|
124
|
-
): ZiggsConnectClient {
|
|
125
|
-
return new ZiggsConnectClient(opts);
|
|
126
|
-
}
|
|
@@ -1,129 +0,0 @@
|
|
|
1
|
-
import 'dotenv/config';
|
|
2
|
-
|
|
3
|
-
function getDefaultBaseUrl(): string {
|
|
4
|
-
return process.env.BACKEND_URL || process.env.ZIGGS_BACKEND_URL || 'http://localhost:3000';
|
|
5
|
-
}
|
|
6
|
-
|
|
7
|
-
function parseError(text: string, fallback: string): string {
|
|
8
|
-
if (!text) return fallback;
|
|
9
|
-
try {
|
|
10
|
-
const parsed = JSON.parse(text) as Record<string, unknown>;
|
|
11
|
-
return (parsed['message'] as string) || (parsed['error'] as string) || text;
|
|
12
|
-
} catch {
|
|
13
|
-
return text;
|
|
14
|
-
}
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
interface ContextError extends Error {
|
|
18
|
-
status?: number;
|
|
19
|
-
body?: string;
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
export interface ZiggsContextClientOptions {
|
|
23
|
-
operatorKey: string;
|
|
24
|
-
actAsAgentId?: string;
|
|
25
|
-
baseUrl?: string;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
export interface ContextReachDescriptor {
|
|
29
|
-
grantId: string;
|
|
30
|
-
scope: { kind: 'chat' | 'agreement' | 'org'; id: string };
|
|
31
|
-
temporal: 'from-now' | 'from-start';
|
|
32
|
-
watermarkAt: string;
|
|
33
|
-
expiresAt: string | null;
|
|
34
|
-
parentGrantId: string | null;
|
|
35
|
-
createdAt: string;
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
export interface DelegateContextGrantParams {
|
|
39
|
-
parentGrantId: string;
|
|
40
|
-
holderId: string;
|
|
41
|
-
scope: { kind: 'chat' | 'agreement' | 'org'; id: string };
|
|
42
|
-
temporal: 'from-now' | 'from-start';
|
|
43
|
-
expiresAt?: string | null;
|
|
44
|
-
watermarkAt?: string;
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
/**
|
|
48
|
-
* HTTP client for context grants (ZIG-413).
|
|
49
|
-
* Presentation model (signed bytes vs grant id) is intentionally not baked in here.
|
|
50
|
-
*/
|
|
51
|
-
export class ZiggsContextClient {
|
|
52
|
-
private operatorKey: string;
|
|
53
|
-
private actAsAgentId: string | null;
|
|
54
|
-
private baseUrl: string;
|
|
55
|
-
|
|
56
|
-
constructor({ operatorKey, actAsAgentId, baseUrl }: ZiggsContextClientOptions) {
|
|
57
|
-
if (!operatorKey || typeof operatorKey !== 'string') {
|
|
58
|
-
throw new Error('ZiggsContextClient requires an operatorKey');
|
|
59
|
-
}
|
|
60
|
-
this.operatorKey = operatorKey;
|
|
61
|
-
this.actAsAgentId = actAsAgentId || null;
|
|
62
|
-
this.baseUrl = baseUrl || getDefaultBaseUrl();
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
/** ZIG-412: scope descriptors for what this agent can reach (no content). */
|
|
66
|
-
async discover(): Promise<ContextReachDescriptor[]> {
|
|
67
|
-
this.requireActAsAgent('discover');
|
|
68
|
-
const res = (await this._get('/context/discovery')) as Record<string, unknown>;
|
|
69
|
-
return (res['reach'] as ContextReachDescriptor[]) || [];
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
/** Holder delegates a narrower child grant. */
|
|
73
|
-
async delegate(params: DelegateContextGrantParams): Promise<unknown> {
|
|
74
|
-
this.requireActAsAgent('delegate');
|
|
75
|
-
if (!params.parentGrantId) throw new Error('delegate: parentGrantId is required');
|
|
76
|
-
if (!params.holderId) throw new Error('delegate: holderId is required');
|
|
77
|
-
if (!params.scope?.kind || !params.scope?.id) {
|
|
78
|
-
throw new Error('delegate: scope { kind, id } is required');
|
|
79
|
-
}
|
|
80
|
-
return this._post(`/context/grants/${encodeURIComponent(params.parentGrantId)}/delegate`, {
|
|
81
|
-
holderId: params.holderId,
|
|
82
|
-
scope: params.scope,
|
|
83
|
-
temporal: params.temporal,
|
|
84
|
-
expiresAt: params.expiresAt,
|
|
85
|
-
watermarkAt: params.watermarkAt,
|
|
86
|
-
});
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
private requireActAsAgent(method: string): void {
|
|
90
|
-
if (!this.actAsAgentId) {
|
|
91
|
-
throw new Error(
|
|
92
|
-
`${method}: actAsAgentId is required — context grant calls must impersonate the grant holder agent`,
|
|
93
|
-
);
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
private _buildHeaders(extra: Record<string, string> = {}): Record<string, string> {
|
|
98
|
-
const h: Record<string, string> = { Authorization: `Bearer ${this.operatorKey}`, ...extra };
|
|
99
|
-
if (this.actAsAgentId) h['X-Agent-Id'] = this.actAsAgentId;
|
|
100
|
-
return h;
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
private async _request(method: string, path: string, body: unknown): Promise<unknown> {
|
|
104
|
-
const init: RequestInit = {
|
|
105
|
-
method,
|
|
106
|
-
headers: this._buildHeaders(
|
|
107
|
-
body !== undefined ? { 'content-type': 'application/json' } : {},
|
|
108
|
-
),
|
|
109
|
-
};
|
|
110
|
-
if (body !== undefined) init.body = JSON.stringify(body);
|
|
111
|
-
const res = await fetch(`${this.baseUrl}${path}`, init);
|
|
112
|
-
const text = await res.text();
|
|
113
|
-
if (!res.ok) {
|
|
114
|
-
const err = new Error(parseError(text, `${method} ${path} failed (${res.status})`)) as ContextError;
|
|
115
|
-
err.status = res.status;
|
|
116
|
-
err.body = text;
|
|
117
|
-
throw err;
|
|
118
|
-
}
|
|
119
|
-
return text ? JSON.parse(text) : {};
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
private _get(path: string): Promise<unknown> {
|
|
123
|
-
return this._request('GET', path, undefined);
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
private _post(path: string, body: unknown): Promise<unknown> {
|
|
127
|
-
return this._request('POST', path, body);
|
|
128
|
-
}
|
|
129
|
-
}
|
|
@@ -1,193 +0,0 @@
|
|
|
1
|
-
import 'dotenv/config';
|
|
2
|
-
|
|
3
|
-
function getDefaultBaseUrl(): string {
|
|
4
|
-
return process.env.BACKEND_URL || process.env.ZIGGS_BACKEND_URL || 'http://localhost:3000';
|
|
5
|
-
}
|
|
6
|
-
|
|
7
|
-
function randomIdempotencyKey(prefix = 'op'): string {
|
|
8
|
-
return `${prefix}_${Date.now().toString(36)}_${Math.random().toString(36).slice(2, 10)}`;
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
function parseError(text: string, fallback: string): string {
|
|
12
|
-
if (!text) return fallback;
|
|
13
|
-
try {
|
|
14
|
-
const parsed = JSON.parse(text) as Record<string, unknown>;
|
|
15
|
-
return (parsed['error'] as string) || (parsed['message'] as string) || text;
|
|
16
|
-
} catch { return text; }
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
interface PayError extends Error { status?: number; body?: string; }
|
|
20
|
-
|
|
21
|
-
export interface ZiggsPayClientOptions {
|
|
22
|
-
operatorKey: string;
|
|
23
|
-
actAsAgentId?: string;
|
|
24
|
-
baseUrl?: string;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
export class ZiggsPayClient {
|
|
28
|
-
private operatorKey: string;
|
|
29
|
-
private actAsAgentId: string | null;
|
|
30
|
-
private baseUrl: string;
|
|
31
|
-
|
|
32
|
-
constructor({ operatorKey, actAsAgentId, baseUrl }: ZiggsPayClientOptions) {
|
|
33
|
-
if (!operatorKey || typeof operatorKey !== 'string') throw new Error('ZiggsPayClient requires an operatorKey');
|
|
34
|
-
this.operatorKey = operatorKey;
|
|
35
|
-
this.actAsAgentId = actAsAgentId || null;
|
|
36
|
-
this.baseUrl = baseUrl || getDefaultBaseUrl();
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
async balance(): Promise<{ walletId: string | null; currency: string; balance: number; availableBalance: number }> {
|
|
40
|
-
const w = await this._get('/payments/wallet') as Record<string, unknown>;
|
|
41
|
-
const wallet = w['wallet'] as Record<string, unknown> | undefined;
|
|
42
|
-
return { walletId: (wallet?.['walletId'] as string) || null, currency: (wallet?.['currency'] as string) || 'pez', balance: (w['balance'] as number) ?? 0, availableBalance: (w['availableBalance'] as number) ?? 0 };
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
async resolve({ userId, agentId }: { userId?: string; agentId?: string } = {}): Promise<unknown> {
|
|
46
|
-
if (!userId && !agentId) throw new Error('resolve: provide userId or agentId');
|
|
47
|
-
const params = new URLSearchParams();
|
|
48
|
-
if (userId) params.set('userId', userId);
|
|
49
|
-
if (agentId) params.set('agentId', agentId);
|
|
50
|
-
const res = await this._get(`/payments/wallets/resolve?${params}`) as Record<string, unknown>;
|
|
51
|
-
return res['wallet'] || null;
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
async transfer({ to, amount, idempotencyKey, description, paymentGrantId }: { to: string; amount: number; idempotencyKey?: string; description?: string; paymentGrantId?: string }): Promise<unknown> {
|
|
55
|
-
if (!to) throw new Error('transfer: `to` is required');
|
|
56
|
-
if (!(Number.isInteger(amount) && amount > 0)) throw new Error('transfer: `amount` must be a positive integer (cents)');
|
|
57
|
-
if (this.actAsAgentId && !paymentGrantId) throw new Error('transfer: paymentGrantId is required for agent-impersonated transfers. The wallet owner must have issued a payment grant to this agentId.');
|
|
58
|
-
let toWalletId = to;
|
|
59
|
-
if (!to.startsWith('wal_')) {
|
|
60
|
-
const w = await this.resolve(to.startsWith('agent_') ? { agentId: to } : { userId: to }) as Record<string, unknown> | null;
|
|
61
|
-
if (!w?.['walletId']) throw new Error(`transfer: could not resolve wallet for "${to}"`);
|
|
62
|
-
toWalletId = w['walletId'] as string;
|
|
63
|
-
}
|
|
64
|
-
const result = await this._post('/payments/transfer', { toWalletId, amount, idempotencyKey: idempotencyKey || randomIdempotencyKey('xfer'), description, paymentGrantId }) as Record<string, unknown>;
|
|
65
|
-
if (result?.['status'] === 'approval_required') {
|
|
66
|
-
const approval = (result['approval'] as Record<string, unknown>) || {};
|
|
67
|
-
return { status: 'approval_required', approvalId: approval['approvalId'] || null, expiresAt: approval['expiresAt'] || null, reason: approval['reason'] || 'Amount exceeds auto-approve threshold', toWalletId, amount };
|
|
68
|
-
}
|
|
69
|
-
const tx = result?.['transaction'] as Record<string, unknown> | undefined;
|
|
70
|
-
return { status: 'transferred', transactionId: tx?.['transactionId'] || null, toWalletId, amount };
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
async hold({ amount, idempotencyKey, description }: { amount: number; idempotencyKey?: string; description?: string }): Promise<unknown> {
|
|
74
|
-
if (!(Number.isInteger(amount) && amount > 0)) throw new Error('hold: `amount` must be a positive integer (cents)');
|
|
75
|
-
return this._post('/payments/hold', { amount, idempotencyKey: idempotencyKey || randomIdempotencyKey('hold'), description });
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
async release({ holdId, action = 'complete', toWalletId, idempotencyKey }: { holdId: string; action?: string; toWalletId?: string; idempotencyKey?: string }): Promise<unknown> {
|
|
79
|
-
return this._post(`/payments/release/${holdId}`, { idempotencyKey: idempotencyKey || randomIdempotencyKey('rel'), action, toWalletId });
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
async history(params: { limit?: number; offset?: number; type?: string } = {}): Promise<unknown> {
|
|
83
|
-
const q = new URLSearchParams();
|
|
84
|
-
if (params.limit != null) q.set('limit', String(params.limit));
|
|
85
|
-
if (params.offset != null) q.set('offset', String(params.offset));
|
|
86
|
-
if (params.type) q.set('type', params.type);
|
|
87
|
-
return this._get('/payments/history' + (q.toString() ? `?${q}` : ''));
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
async issueGrant({ holderId, caveats }: { holderId: string; caveats?: unknown }): Promise<unknown> {
|
|
91
|
-
return this._post('/payments/grants', { holderId, caveats });
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
async attenuateGrant({ grantId, holderId, caveats }: { grantId: string; holderId: string; caveats?: unknown }): Promise<unknown> {
|
|
95
|
-
return this._post(`/payments/grants/${grantId}/attenuate`, { holderId, caveats });
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
async revokeGrant(grantId: string): Promise<unknown> {
|
|
99
|
-
return this._request('DELETE', `/payments/grants/${grantId}`, undefined);
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
async listGrants(): Promise<unknown[]> {
|
|
103
|
-
const res = await this._get('/payments/grants') as Record<string, unknown>;
|
|
104
|
-
return (res['grants'] as unknown[]) || [];
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
async createTopUpIntent({ amount, description, currency }: { amount?: number; description?: string; currency?: string } = {}): Promise<unknown> {
|
|
108
|
-
return this._post('/payments/onramp/intent', { amount, description, currency });
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
async confirmMockIntent(intentId: string): Promise<unknown> {
|
|
112
|
-
return this._post(`/payments/onramp/mock-confirm/${intentId}`, {});
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
async faucet({ amount, description = 'Faucet', idempotencyKey }: { amount?: number; description?: string; idempotencyKey?: string } = {}): Promise<unknown> {
|
|
116
|
-
return this._post('/payments/wallet/fund', { amount, idempotencyKey: idempotencyKey || randomIdempotencyKey('faucet'), description });
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
async approvals({ status = 'pending' }: { status?: string } = {}): Promise<unknown[]> {
|
|
120
|
-
const res = await this._get(`/payments/approvals?status=${encodeURIComponent(status)}`) as Record<string, unknown>;
|
|
121
|
-
return (res['approvals'] as unknown[]) || [];
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
async getApproval(approvalId: string): Promise<unknown | null> {
|
|
125
|
-
if (!approvalId) throw new Error('getApproval: approvalId is required');
|
|
126
|
-
try {
|
|
127
|
-
const res = await this._get(`/payments/approvals/${approvalId}`) as Record<string, unknown>;
|
|
128
|
-
return res?.['approval'] || null;
|
|
129
|
-
} catch (err) {
|
|
130
|
-
if ((err as PayError).status === 404) return null;
|
|
131
|
-
throw err;
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
async decide(approvalId: string, decision: string, note = ''): Promise<unknown> {
|
|
136
|
-
return this._post(`/payments/approvals/${approvalId}/decide`, { decision, note });
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
async waitForApproval(approvalId: string, opts: { pollMs?: number; timeoutMs?: number; signal?: AbortSignal } = {}): Promise<unknown> {
|
|
140
|
-
const pollMs = Math.max(500, opts.pollMs ?? 3_000);
|
|
141
|
-
const timeoutMs = Math.max(pollMs, opts.timeoutMs ?? 120_000);
|
|
142
|
-
const signal = opts.signal;
|
|
143
|
-
const deadline = Date.now() + timeoutMs;
|
|
144
|
-
|
|
145
|
-
const sleep = (ms: number) => new Promise<void>((resolve, reject) => {
|
|
146
|
-
const timer = setTimeout(resolve, ms);
|
|
147
|
-
if (signal) {
|
|
148
|
-
if (signal.aborted) { clearTimeout(timer); reject(new Error('aborted')); return; }
|
|
149
|
-
signal.addEventListener('abort', () => { clearTimeout(timer); reject(new Error('aborted')); }, { once: true });
|
|
150
|
-
}
|
|
151
|
-
});
|
|
152
|
-
|
|
153
|
-
while (true) {
|
|
154
|
-
if (signal?.aborted) throw new Error('aborted');
|
|
155
|
-
const approval = await this.getApproval(approvalId) as Record<string, unknown> | null;
|
|
156
|
-
if (!approval) return { status: 'gone' };
|
|
157
|
-
const s = approval['status'];
|
|
158
|
-
if (s === 'executed') return { status: 'executed', approval, transactionId: approval['executedTransactionId'] || null };
|
|
159
|
-
if (s === 'rejected') return { status: 'rejected', approval };
|
|
160
|
-
if (s === 'expired') return { status: 'expired', approval };
|
|
161
|
-
const remaining = deadline - Date.now();
|
|
162
|
-
if (remaining <= 0) return { status: 'timeout', approval };
|
|
163
|
-
await sleep(Math.min(pollMs, remaining));
|
|
164
|
-
}
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
private _buildHeaders(extra: Record<string, string> = {}): Record<string, string> {
|
|
168
|
-
const h: Record<string, string> = { Authorization: `Bearer ${this.operatorKey}`, ...extra };
|
|
169
|
-
if (this.actAsAgentId) h['X-Agent-Id'] = this.actAsAgentId;
|
|
170
|
-
return h;
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
private async _request(method: string, path: string, body: unknown): Promise<unknown> {
|
|
174
|
-
const init: RequestInit = { method, headers: this._buildHeaders(body !== undefined ? { 'content-type': 'application/json' } : {}) };
|
|
175
|
-
if (body !== undefined) init.body = JSON.stringify(body);
|
|
176
|
-
const response = await fetch(`${this.baseUrl}${path}`, init);
|
|
177
|
-
const text = await response.text();
|
|
178
|
-
if (!response.ok) {
|
|
179
|
-
const err = new Error(parseError(text, `HTTP ${response.status}`)) as PayError;
|
|
180
|
-
err.status = response.status;
|
|
181
|
-
err.body = text;
|
|
182
|
-
throw err;
|
|
183
|
-
}
|
|
184
|
-
return text ? JSON.parse(text) : null;
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
private _get(path: string): Promise<unknown> { return this._request('GET', path, undefined); }
|
|
188
|
-
private _post(path: string, body: unknown): Promise<unknown> { return this._request('POST', path, body ?? {}); }
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
export function createZiggsPayClient(opts: ZiggsPayClientOptions): ZiggsPayClient {
|
|
192
|
-
return new ZiggsPayClient(opts);
|
|
193
|
-
}
|
package/src/shared/ids.ts
DELETED