botanary-mcp 0.4.2 → 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.
- package/dist/bin/botanary-mcp.d.ts +3 -0
- package/dist/bin/botanary-mcp.d.ts.map +1 -0
- package/dist/bin/botanary-mcp.js +0 -0
- package/dist/src/agent-actions.d.ts +44 -0
- package/dist/src/agent-actions.d.ts.map +1 -0
- package/dist/src/agent-actions.js +244 -0
- package/dist/src/agent-actions.js.map +1 -0
- package/dist/src/agent-grant-helpers.d.ts +13 -0
- package/dist/src/agent-grant-helpers.d.ts.map +1 -0
- package/dist/src/agent-grant-helpers.js +36 -0
- package/dist/src/agent-grant-helpers.js.map +1 -0
- package/dist/src/api-client.d.ts +57 -0
- package/dist/src/api-client.d.ts.map +1 -0
- package/dist/src/app-link.d.ts +33 -0
- package/dist/src/app-link.d.ts.map +1 -0
- package/dist/src/cli.d.ts +14 -0
- package/dist/src/cli.d.ts.map +1 -0
- package/dist/src/diagnose.d.ts +37 -0
- package/dist/src/diagnose.d.ts.map +1 -0
- package/dist/src/identity/backends/exec.d.ts +18 -0
- package/dist/src/identity/backends/exec.d.ts.map +1 -0
- package/dist/src/identity/backends/file-fallback.d.ts +6 -0
- package/dist/src/identity/backends/file-fallback.d.ts.map +1 -0
- package/dist/src/identity/backends/libsecret.d.ts +4 -0
- package/dist/src/identity/backends/libsecret.d.ts.map +1 -0
- package/dist/src/identity/backends/macos-keychain.d.ts +4 -0
- package/dist/src/identity/backends/macos-keychain.d.ts.map +1 -0
- package/dist/src/identity/backends/select.d.ts +16 -0
- package/dist/src/identity/backends/select.d.ts.map +1 -0
- package/dist/src/identity/backends/types.d.ts +41 -0
- package/dist/src/identity/backends/types.d.ts.map +1 -0
- package/dist/src/identity/backends/windows-dpapi.d.ts +4 -0
- package/dist/src/identity/backends/windows-dpapi.d.ts.map +1 -0
- package/dist/src/identity/fingerprint.d.ts +21 -0
- package/dist/src/identity/fingerprint.d.ts.map +1 -0
- package/dist/src/identity/keypair.d.ts +33 -0
- package/dist/src/identity/keypair.d.ts.map +1 -0
- package/dist/src/identity/pairing-code.d.ts +41 -0
- package/dist/src/identity/pairing-code.d.ts.map +1 -0
- package/dist/src/identity/redact.d.ts +8 -0
- package/dist/src/identity/redact.d.ts.map +1 -0
- package/dist/src/identity/store.d.ts +67 -0
- package/dist/src/identity/store.d.ts.map +1 -0
- package/dist/src/identity/types.d.ts +34 -0
- package/dist/src/identity/types.d.ts.map +1 -0
- package/dist/src/index.d.ts +24 -0
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/index.js +16 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/package-version.d.ts +21 -0
- package/dist/src/package-version.d.ts.map +1 -0
- package/dist/src/paths.d.ts +14 -0
- package/dist/src/paths.d.ts.map +1 -0
- package/dist/src/runtime.d.ts +336 -0
- package/dist/src/runtime.d.ts.map +1 -0
- package/dist/src/runtime.js +7 -3
- package/dist/src/runtime.js.map +1 -1
- package/dist/src/server.d.ts +7 -0
- package/dist/src/server.d.ts.map +1 -0
- package/dist/src/tools.d.ts +67 -0
- package/dist/src/tools.d.ts.map +1 -0
- package/dist/src/tools.js +16 -586
- package/dist/src/tools.js.map +1 -1
- package/dist/src/wallet/api-get.d.ts +36 -0
- package/dist/src/wallet/api-get.d.ts.map +1 -0
- package/dist/src/wallet/browser.d.ts +35 -0
- package/dist/src/wallet/browser.d.ts.map +1 -0
- package/dist/src/wallet/composites.d.ts +22 -0
- package/dist/src/wallet/composites.d.ts.map +1 -0
- package/dist/src/wallet/freshness.d.ts +72 -0
- package/dist/src/wallet/freshness.d.ts.map +1 -0
- package/dist/src/wallet/login.d.ts +74 -0
- package/dist/src/wallet/login.d.ts.map +1 -0
- package/dist/src/wallet/login.js +4 -0
- package/dist/src/wallet/login.js.map +1 -1
- package/dist/src/wallet/payloads.d.ts +57 -0
- package/dist/src/wallet/payloads.d.ts.map +1 -0
- package/dist/src/wallet/routes.manifest.d.ts +21 -0
- package/dist/src/wallet/routes.manifest.d.ts.map +1 -0
- package/dist/src/wallet/send-orchestration.d.ts +140 -0
- package/dist/src/wallet/send-orchestration.d.ts.map +1 -0
- package/dist/src/wallet/send-orchestration.js +314 -0
- package/dist/src/wallet/send-orchestration.js.map +1 -0
- package/dist/src/wallet/send.d.ts +127 -0
- package/dist/src/wallet/send.d.ts.map +1 -0
- package/dist/src/wallet/send.js +1 -0
- package/dist/src/wallet/send.js.map +1 -1
- package/dist/src/wallet/session-store.d.ts +43 -0
- package/dist/src/wallet/session-store.d.ts.map +1 -0
- package/package.json +4 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"botanary-mcp.d.ts","sourceRoot":"","sources":["../../bin/botanary-mcp.ts"],"names":[],"mappings":""}
|
package/dist/bin/botanary-mcp.js
CHANGED
|
File without changes
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import type { AgentRuntime } from './runtime.js';
|
|
2
|
+
export interface ProposePaymentInput {
|
|
3
|
+
recipient: string;
|
|
4
|
+
amount: number;
|
|
5
|
+
tokenSymbol: string;
|
|
6
|
+
chainId: number;
|
|
7
|
+
}
|
|
8
|
+
export interface ProposeSwapInput {
|
|
9
|
+
tokenIn: string;
|
|
10
|
+
tokenOut: string;
|
|
11
|
+
amountIn: number;
|
|
12
|
+
chainId: number;
|
|
13
|
+
maxSlippageBps?: number;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Build and relay a payment under this agent's OWN grant. Reads the grant's bounds and permissionId from
|
|
17
|
+
* the backend (GET /agents/me) FIRST: when there is no grant, the grant is not active, it is on a
|
|
18
|
+
* different chain, or the amount would exceed its remaining budget or per-action cap, this refuses with
|
|
19
|
+
* the backend's own numbers rather than attempting anything - it never pretends to send a payment it did
|
|
20
|
+
* not send. Otherwise it builds the delegated action (POST /delegations/{delegationId}/actions - the ONLY
|
|
21
|
+
* build lane a session-key signature can validate; never the owner-lane /money/send/build) against THIS
|
|
22
|
+
* agent's own grant id, then relays it signed with the grant's own session key (POST /userops), returning
|
|
23
|
+
* the backend's real relay result. This client-side bounds check is a convenience, never the check - the
|
|
24
|
+
* chain is what actually enforces the grant.
|
|
25
|
+
*/
|
|
26
|
+
export declare function proposePayment(runtime: AgentRuntime, input: ProposePaymentInput): Promise<Record<string, unknown>>;
|
|
27
|
+
/**
|
|
28
|
+
* Build and relay a SWAP under this agent's OWN grant - sell one token for another, in the account's own
|
|
29
|
+
* name, without the owner signing. Reads the grant's bounds and permissionId from the backend
|
|
30
|
+
* (GET /agents/me) FIRST: when there is no grant, the grant is not active, it is on a different chain,
|
|
31
|
+
* the grant names NO swap venue at all (a transfer-only grant has no allowance action for a swap to
|
|
32
|
+
* validate against), the token being sold is not the one token its venue pins, or the amount exceeds
|
|
33
|
+
* that venue's per-swap allowance ceiling, this refuses with the backend's own numbers rather than
|
|
34
|
+
* attempting anything - it never pretends to have swapped what it did not. Otherwise it builds the
|
|
35
|
+
* delegated action (POST /delegations/{delegationId}/actions with action: 'swap' - the ONLY build lane a
|
|
36
|
+
* session-key signature can validate; never the owner-lane /money/swap/build) against THIS agent's own
|
|
37
|
+
* grant id, then relays it signed with the grant's own session key (POST /userops), returning the
|
|
38
|
+
* backend's real relay result. The ROUTE is the backend's to choose and the grant pins exactly one
|
|
39
|
+
* router, so a best route through any other router is declined there, by name - this never picks a venue.
|
|
40
|
+
* This client-side bounds check is a convenience, never the check - the chain is what actually enforces
|
|
41
|
+
* the grant.
|
|
42
|
+
*/
|
|
43
|
+
export declare function proposeSwap(runtime: AgentRuntime, input: ProposeSwapInput): Promise<Record<string, unknown>>;
|
|
44
|
+
//# sourceMappingURL=agent-actions.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agent-actions.d.ts","sourceRoot":"","sources":["../../src/agent-actions.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAKjD,MAAM,WAAW,mBAAmB;IAClC,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,cAAc,CAAC,OAAO,EAAE,YAAY,EAAE,KAAK,EAAE,mBAAmB,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CA8GxH;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAsB,WAAW,CAAC,OAAO,EAAE,YAAY,EAAE,KAAK,EAAE,gBAAgB,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAqIlH"}
|
|
@@ -0,0 +1,244 @@
|
|
|
1
|
+
import { describeGrant, findBudgetMeter, missingModuleOf } from './agent-grant-helpers.js';
|
|
2
|
+
import { settleRelayedOp } from './wallet/send-orchestration.js';
|
|
3
|
+
import { setupUrl } from './app-link.js';
|
|
4
|
+
/**
|
|
5
|
+
* Build and relay a payment under this agent's OWN grant. Reads the grant's bounds and permissionId from
|
|
6
|
+
* the backend (GET /agents/me) FIRST: when there is no grant, the grant is not active, it is on a
|
|
7
|
+
* different chain, or the amount would exceed its remaining budget or per-action cap, this refuses with
|
|
8
|
+
* the backend's own numbers rather than attempting anything - it never pretends to send a payment it did
|
|
9
|
+
* not send. Otherwise it builds the delegated action (POST /delegations/{delegationId}/actions - the ONLY
|
|
10
|
+
* build lane a session-key signature can validate; never the owner-lane /money/send/build) against THIS
|
|
11
|
+
* agent's own grant id, then relays it signed with the grant's own session key (POST /userops), returning
|
|
12
|
+
* the backend's real relay result. This client-side bounds check is a convenience, never the check - the
|
|
13
|
+
* chain is what actually enforces the grant.
|
|
14
|
+
*/
|
|
15
|
+
export async function proposePayment(runtime, input) {
|
|
16
|
+
const { recipient, amount, tokenSymbol, chainId } = input;
|
|
17
|
+
const self = await runtime.me();
|
|
18
|
+
if (!self.grant) {
|
|
19
|
+
return { proposed: false, reason: 'no_grant', message: `${describeGrant(self)} Nothing was built or sent.` };
|
|
20
|
+
}
|
|
21
|
+
const grant = self.grant;
|
|
22
|
+
if (grant.status !== 'active') {
|
|
23
|
+
return {
|
|
24
|
+
proposed: false,
|
|
25
|
+
reason: 'grant_not_active',
|
|
26
|
+
message: `This grant is "${grant.status}", not active, so it cannot be spent under. Nothing was ` +
|
|
27
|
+
'built or sent. Use request_approval to ask the owner directly.',
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
if (grant.chainId !== chainId) {
|
|
31
|
+
return {
|
|
32
|
+
proposed: false,
|
|
33
|
+
reason: 'wrong_chain',
|
|
34
|
+
message: `This grant is on chain ${grant.chainId} (${grant.chain}), not chain ${chainId}. Nothing ` +
|
|
35
|
+
'was built or sent. Use request_approval if this payment genuinely needs that chain.',
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
const meter = findBudgetMeter(grant, tokenSymbol);
|
|
39
|
+
if (!meter) {
|
|
40
|
+
return {
|
|
41
|
+
proposed: false,
|
|
42
|
+
reason: 'token_not_budgeted',
|
|
43
|
+
message: `This grant has no budget for ${tokenSymbol}. Budgeted tokens: ` +
|
|
44
|
+
`${grant.policySet.budgets.map((b) => b.token.symbol).join(', ') || 'none'}. Nothing was ` +
|
|
45
|
+
'built or sent. Use request_approval instead.',
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
if (amount > meter.remaining) {
|
|
49
|
+
return {
|
|
50
|
+
proposed: false,
|
|
51
|
+
reason: 'over_budget',
|
|
52
|
+
message: `This grant has ${meter.remaining} ${tokenSymbol} remaining (of ${meter.limit} total); ` +
|
|
53
|
+
`${amount} ${tokenSymbol} would exceed it. Nothing was built or sent. Use request_approval ` +
|
|
54
|
+
'to ask the owner for this specific payment.',
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
const perActionMax = grant.policySet.perActionMax;
|
|
58
|
+
if (perActionMax && perActionMax.token.symbol.toUpperCase() === tokenSymbol.toUpperCase() && amount > perActionMax.amount) {
|
|
59
|
+
return {
|
|
60
|
+
proposed: false,
|
|
61
|
+
reason: 'over_per_action_max',
|
|
62
|
+
message: `This grant caps a single action at ${perActionMax.amount} ${tokenSymbol}; ${amount} ` +
|
|
63
|
+
'exceeds it. Nothing was built or sent. Use request_approval instead.',
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
// Within the client-read bounds - build the delegated action AGAINST THIS AGENT'S OWN GRANT ID
|
|
67
|
+
// (grant.id, from GET /agents/me - never invented, never another agent's), then relay it signed
|
|
68
|
+
// with the grant's own session key. This check is a convenience, never the check: Smart Sessions'
|
|
69
|
+
// own on-chain policies are what actually enforce the grant when the relay lands, and the backend
|
|
70
|
+
// itself refuses (403, named reason) a delegation id that does not name this agent.
|
|
71
|
+
let build;
|
|
72
|
+
try {
|
|
73
|
+
build = await runtime.buildDelegatedAction({ delegationId: grant.id, recipient, amount, token: tokenSymbol });
|
|
74
|
+
}
|
|
75
|
+
catch (e) {
|
|
76
|
+
// The one refusal with a remedy the OWNER can act on in a browser and this agent cannot act on
|
|
77
|
+
// at all. Hand back the address of that remedy rather than a bare "cannot succeed" - and say
|
|
78
|
+
// plainly that retrying is pointless, because nothing about a retry installs a module.
|
|
79
|
+
const missing = missingModuleOf(e);
|
|
80
|
+
if (!missing)
|
|
81
|
+
throw e;
|
|
82
|
+
return {
|
|
83
|
+
proposed: false,
|
|
84
|
+
reason: 'account_setup_required',
|
|
85
|
+
missingModule: missing,
|
|
86
|
+
setupUrl: setupUrl(runtime.apiBaseUrl, grant.chainId),
|
|
87
|
+
message: `This account is missing ${missing} on chain ${grant.chainId} (${grant.chain}), so a ` +
|
|
88
|
+
'payment under this grant cannot succeed. Nothing was built or sent, and retrying will ' +
|
|
89
|
+
'fail identically - installing a module is an authority change only the owner can sign, ' +
|
|
90
|
+
'and a session key cannot do it. Open the setupUrl above in a browser, sign the one-time ' +
|
|
91
|
+
'setup, then ask me to try this payment again.',
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
const token = await runtime.ensureSession();
|
|
95
|
+
const relay = await runtime.spendUnderGrant(build.userOp, build.userOpHash, grant.permissionId, token, build.intentType);
|
|
96
|
+
// Follow the op rather than reporting a bare `pending` and going quiet. The op id comes from the
|
|
97
|
+
// backend's own relay response - never invented here.
|
|
98
|
+
const opId = typeof relay?.id === 'string' ? relay.id : null;
|
|
99
|
+
if (!opId)
|
|
100
|
+
return { proposed: true, settled: false, userOpHash: build.userOpHash, relay };
|
|
101
|
+
// THE RELAY HAS ALREADY SUCCEEDED by this line - the backend holds the signed op and gave us its
|
|
102
|
+
// id. Everything below is FOLLOW-UP, so a throw there (a 500 on the status read, a session re-mint
|
|
103
|
+
// that fails, a dropped connection) is not a failed payment and must never be reported as one.
|
|
104
|
+
// Unwrapped, it would propagate as a bare error carrying neither the opId nor the do-not-resend
|
|
105
|
+
// instruction - and the agent's natural next move, resending, would move real money twice. That
|
|
106
|
+
// whole discipline lives in `settleRelayedOp`, shared with `proposeSwap` so the two can never
|
|
107
|
+
// drift into describing the same three outcomes differently.
|
|
108
|
+
return settleRelayedOp(runtime, opId, build.userOpHash, 'payment', { amount, token: tokenSymbol }, `NOTHING moved: no ${tokenSymbol} left the account, the recipient received nothing, ` +
|
|
109
|
+
'and the grant budget was not spent.');
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Build and relay a SWAP under this agent's OWN grant - sell one token for another, in the account's own
|
|
113
|
+
* name, without the owner signing. Reads the grant's bounds and permissionId from the backend
|
|
114
|
+
* (GET /agents/me) FIRST: when there is no grant, the grant is not active, it is on a different chain,
|
|
115
|
+
* the grant names NO swap venue at all (a transfer-only grant has no allowance action for a swap to
|
|
116
|
+
* validate against), the token being sold is not the one token its venue pins, or the amount exceeds
|
|
117
|
+
* that venue's per-swap allowance ceiling, this refuses with the backend's own numbers rather than
|
|
118
|
+
* attempting anything - it never pretends to have swapped what it did not. Otherwise it builds the
|
|
119
|
+
* delegated action (POST /delegations/{delegationId}/actions with action: 'swap' - the ONLY build lane a
|
|
120
|
+
* session-key signature can validate; never the owner-lane /money/swap/build) against THIS agent's own
|
|
121
|
+
* grant id, then relays it signed with the grant's own session key (POST /userops), returning the
|
|
122
|
+
* backend's real relay result. The ROUTE is the backend's to choose and the grant pins exactly one
|
|
123
|
+
* router, so a best route through any other router is declined there, by name - this never picks a venue.
|
|
124
|
+
* This client-side bounds check is a convenience, never the check - the chain is what actually enforces
|
|
125
|
+
* the grant.
|
|
126
|
+
*/
|
|
127
|
+
export async function proposeSwap(runtime, input) {
|
|
128
|
+
const { tokenIn, tokenOut, amountIn, chainId, maxSlippageBps } = input;
|
|
129
|
+
// BOUNDS FIRST, exactly as proposePayment does, and for the same reason: the refusals below are
|
|
130
|
+
// the ones this side can make honestly from backend-reported facts, and making them here means an
|
|
131
|
+
// out-of-grant swap costs no build, no signature and no relay.
|
|
132
|
+
const self = await runtime.me();
|
|
133
|
+
if (!self.grant) {
|
|
134
|
+
return { proposed: false, reason: 'no_grant', message: `${describeGrant(self)} Nothing was built or sent.` };
|
|
135
|
+
}
|
|
136
|
+
const grant = self.grant;
|
|
137
|
+
if (grant.status !== 'active') {
|
|
138
|
+
return {
|
|
139
|
+
proposed: false,
|
|
140
|
+
reason: 'grant_not_active',
|
|
141
|
+
message: `This grant is "${grant.status}", not active, so it cannot be spent under. Nothing was ` +
|
|
142
|
+
'built or sent. Use request_approval to ask the owner directly.',
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
if (grant.chainId !== chainId) {
|
|
146
|
+
return {
|
|
147
|
+
proposed: false,
|
|
148
|
+
reason: 'wrong_chain',
|
|
149
|
+
message: `This grant is on chain ${grant.chainId} (${grant.chain}), not chain ${chainId}. Nothing ` +
|
|
150
|
+
'was built or sent. A grant\'s allowance, meter and session are per-chain storage on one ' +
|
|
151
|
+
'account, so there is nothing on another chain for it to bound. Use request_approval if ' +
|
|
152
|
+
'this swap genuinely needs that chain.',
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
// THE REFUSAL THAT IS NOT A BUDGET CHECK. A grant compiled with no `swapVenue` carries only the
|
|
156
|
+
// transfer action - its session has no allowance entrypoint at all, so a swap op under it is not
|
|
157
|
+
// "over budget", it is unvalidatable. The backend records the venue on the grant precisely so
|
|
158
|
+
// this is answerable without a chain read: a compiled session cannot be read back from a
|
|
159
|
+
// permissionId, and inventing an answer here would mean relaying an op that always reverts.
|
|
160
|
+
const venue = grant.policySet.swapVenue;
|
|
161
|
+
if (!venue) {
|
|
162
|
+
return {
|
|
163
|
+
proposed: false,
|
|
164
|
+
reason: 'no_swap_venue',
|
|
165
|
+
message: 'This grant was given for transfers only - it names no swap venue, so its session carries ' +
|
|
166
|
+
'no allowance action for a swap to validate against, and no amount is small enough to ' +
|
|
167
|
+
'change that. Nothing was built or sent. Ask the owner for a new grant naming the router ' +
|
|
168
|
+
'and token it may swap, or use request_approval for this one swap.',
|
|
169
|
+
};
|
|
170
|
+
}
|
|
171
|
+
if (venue.token.symbol.toUpperCase() !== tokenIn.toUpperCase()) {
|
|
172
|
+
return {
|
|
173
|
+
proposed: false,
|
|
174
|
+
reason: 'token_not_venue_token',
|
|
175
|
+
message: `This grant may only swap ${venue.token.symbol}, not ${tokenIn} - its session pins the ` +
|
|
176
|
+
'sold token exactly, and any other would be refused in validation. Nothing was built or ' +
|
|
177
|
+
'sent. Use request_approval instead.',
|
|
178
|
+
};
|
|
179
|
+
}
|
|
180
|
+
if (amountIn > venue.maxAllowance) {
|
|
181
|
+
return {
|
|
182
|
+
proposed: false,
|
|
183
|
+
reason: 'over_venue_allowance',
|
|
184
|
+
message: `This grant allows at most ${venue.maxAllowance} ${venue.token.symbol} per swap; ` +
|
|
185
|
+
`${amountIn} ${tokenIn} exceeds it. Nothing was built or sent. Use request_approval to ask ` +
|
|
186
|
+
'the owner for this specific swap.',
|
|
187
|
+
};
|
|
188
|
+
}
|
|
189
|
+
// The grant's ordinary spend meter applies TOO - the venue ceiling caps one swap, the budget caps
|
|
190
|
+
// the lifetime - so a swap within the ceiling but over what is left is still refused here, with
|
|
191
|
+
// the backend's own remaining figure rather than a guess.
|
|
192
|
+
const meter = findBudgetMeter(grant, tokenIn);
|
|
193
|
+
if (meter && amountIn > meter.remaining) {
|
|
194
|
+
return {
|
|
195
|
+
proposed: false,
|
|
196
|
+
reason: 'over_budget',
|
|
197
|
+
message: `This grant has ${meter.remaining} ${tokenIn} remaining (of ${meter.limit} total); ` +
|
|
198
|
+
`${amountIn} ${tokenIn} would exceed it. Nothing was built or sent. Use request_approval ` +
|
|
199
|
+
'to ask the owner for this specific swap.',
|
|
200
|
+
};
|
|
201
|
+
}
|
|
202
|
+
// Within the client-read bounds - build AGAINST THIS AGENT'S OWN GRANT ID (grant.id, from
|
|
203
|
+
// GET /agents/me), then relay it signed with the grant's own session key. The router is the
|
|
204
|
+
// BACKEND's to resolve: it quotes the route, checks it against the one router the venue pins, and
|
|
205
|
+
// declines by name when they disagree. This side never picks a venue.
|
|
206
|
+
let build;
|
|
207
|
+
try {
|
|
208
|
+
build = await runtime.buildDelegatedSwap({
|
|
209
|
+
delegationId: grant.id,
|
|
210
|
+
tokenIn,
|
|
211
|
+
tokenOut,
|
|
212
|
+
amountIn,
|
|
213
|
+
...(maxSlippageBps != null ? { maxSlippageBps } : {}),
|
|
214
|
+
});
|
|
215
|
+
}
|
|
216
|
+
catch (e) {
|
|
217
|
+
// Same one refusal with an owner-only remedy the payment lane has - see its comment. A session
|
|
218
|
+
// key cannot install a module, so retrying is pointless and saying so is the honest answer.
|
|
219
|
+
const missing = missingModuleOf(e);
|
|
220
|
+
if (!missing)
|
|
221
|
+
throw e;
|
|
222
|
+
return {
|
|
223
|
+
proposed: false,
|
|
224
|
+
reason: 'account_setup_required',
|
|
225
|
+
missingModule: missing,
|
|
226
|
+
setupUrl: setupUrl(runtime.apiBaseUrl, grant.chainId),
|
|
227
|
+
message: `This account is missing ${missing} on chain ${grant.chainId} (${grant.chain}), so a ` +
|
|
228
|
+
'swap under this grant cannot succeed. Nothing was built or sent, and retrying will ' +
|
|
229
|
+
'fail identically - installing a module is an authority change only the owner can sign, ' +
|
|
230
|
+
'and a session key cannot do it. Open the setupUrl above in a browser, sign the one-time ' +
|
|
231
|
+
'setup, then ask me to try this swap again.',
|
|
232
|
+
};
|
|
233
|
+
}
|
|
234
|
+
const token = await runtime.ensureSession();
|
|
235
|
+
const relay = await runtime.spendUnderGrant(build.userOp, build.userOpHash, grant.permissionId, token, build.intentType);
|
|
236
|
+
const opId = typeof relay?.id === 'string' ? relay.id : null;
|
|
237
|
+
if (!opId)
|
|
238
|
+
return { proposed: true, settled: false, userOpHash: build.userOpHash, relay };
|
|
239
|
+
// THE RELAY HAS ALREADY SUCCEEDED by this line - see `settleRelayedOp`, which owns the three
|
|
240
|
+
// outcomes from here and is the SAME code proposePayment settles through.
|
|
241
|
+
return settleRelayedOp(runtime, opId, build.userOpHash, 'swap', { amount: amountIn, token: tokenIn }, `NOTHING moved: no ${tokenIn} left the account, no ${tokenOut} was received, ` +
|
|
242
|
+
'and the grant budget was not spent.');
|
|
243
|
+
}
|
|
244
|
+
//# sourceMappingURL=agent-actions.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agent-actions.js","sourceRoot":"","sources":["../../src/agent-actions.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { AgentGrantView, AgentSelf, SpendMeterView } from './runtime.js';
|
|
2
|
+
/** The backend names a missing setup module in structured `details.missingModule` - see
|
|
3
|
+
* `BotanaryApiError.details`. Null for every other failure, so callers fall through to normal handling. */
|
|
4
|
+
export declare function missingModuleOf(e: unknown): string | null;
|
|
5
|
+
/** Plain-English rendering of `GET /agents/me`'s `grant` field - built entirely from backend-reported
|
|
6
|
+
* data (never a fabricated number), shared by `what_may_i_do` and the `propose_payment`/`propose_swap`
|
|
7
|
+
* refusal paths so no two tools describe the same grant two different ways. */
|
|
8
|
+
export declare function describeGrant(self: AgentSelf): string;
|
|
9
|
+
/** The spend meter for `tokenSymbol` on this grant, or undefined when the grant budgets no such token -
|
|
10
|
+
* `spentToDate` is "one meter per budget, in the SAME order as policySet.budgets" (backend's own
|
|
11
|
+
* invariant, `Delegation.spentToDate`'s doc comment), which is what makes this a plain index lookup. */
|
|
12
|
+
export declare function findBudgetMeter(grant: AgentGrantView, tokenSymbol: string): SpendMeterView | undefined;
|
|
13
|
+
//# sourceMappingURL=agent-grant-helpers.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agent-grant-helpers.d.ts","sourceRoot":"","sources":["../../src/agent-grant-helpers.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,SAAS,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAE9E;4GAC4G;AAC5G,wBAAgB,eAAe,CAAC,CAAC,EAAE,OAAO,GAAG,MAAM,GAAG,IAAI,CAIzD;AAED;;gFAEgF;AAChF,wBAAgB,aAAa,CAAC,IAAI,EAAE,SAAS,GAAG,MAAM,CAqBrD;AAED;;yGAEyG;AACzG,wBAAgB,eAAe,CAAC,KAAK,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,GAAG,cAAc,GAAG,SAAS,CAGtG"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/** The backend names a missing setup module in structured `details.missingModule` - see
|
|
2
|
+
* `BotanaryApiError.details`. Null for every other failure, so callers fall through to normal handling. */
|
|
3
|
+
export function missingModuleOf(e) {
|
|
4
|
+
const details = e?.details;
|
|
5
|
+
const name = details?.missingModule;
|
|
6
|
+
return typeof name === 'string' && name.length > 0 ? name : null;
|
|
7
|
+
}
|
|
8
|
+
/** Plain-English rendering of `GET /agents/me`'s `grant` field - built entirely from backend-reported
|
|
9
|
+
* data (never a fabricated number), shared by `what_may_i_do` and the `propose_payment`/`propose_swap`
|
|
10
|
+
* refusal paths so no two tools describe the same grant two different ways. */
|
|
11
|
+
export function describeGrant(self) {
|
|
12
|
+
const boundTo = self.accountAddress ? ` on account ${self.accountAddress}` : '';
|
|
13
|
+
if (!self.grant) {
|
|
14
|
+
return (`Nothing yet - this agent is connected${boundTo} but has not been granted anything. It can read ` +
|
|
15
|
+
`balances and draft a payment (propose_payment will explain exactly why it refuses to relay one), ` +
|
|
16
|
+
`but it cannot spend. Ask your owner to create a grant naming this agent's address ` +
|
|
17
|
+
`(${self.address}) in Botanary, or call request_approval to ask for one specific payment right ` +
|
|
18
|
+
`now.${self.accountAddress
|
|
19
|
+
? ` If ${self.accountAddress} is not the account you have open in Botanary, you are signed in ` +
|
|
20
|
+
`as a different owner - that, not a missing grant, is why this agent is not in your list.`
|
|
21
|
+
: ''}`);
|
|
22
|
+
}
|
|
23
|
+
const g = self.grant;
|
|
24
|
+
const meters = g.spentToDate
|
|
25
|
+
.map((m) => `${m.remaining} ${m.token.symbol} remaining of ${m.limit}${m.expiresAt ? ` (until ${m.expiresAt})` : ''}`)
|
|
26
|
+
.join('; ');
|
|
27
|
+
return `Grant status: ${g.status}. ${g.humanSummary}${meters ? ` Remaining: ${meters}.` : ''}`;
|
|
28
|
+
}
|
|
29
|
+
/** The spend meter for `tokenSymbol` on this grant, or undefined when the grant budgets no such token -
|
|
30
|
+
* `spentToDate` is "one meter per budget, in the SAME order as policySet.budgets" (backend's own
|
|
31
|
+
* invariant, `Delegation.spentToDate`'s doc comment), which is what makes this a plain index lookup. */
|
|
32
|
+
export function findBudgetMeter(grant, tokenSymbol) {
|
|
33
|
+
const idx = grant.policySet.budgets.findIndex((b) => b.token.symbol.toUpperCase() === tokenSymbol.toUpperCase());
|
|
34
|
+
return idx === -1 ? undefined : grant.spentToDate[idx];
|
|
35
|
+
}
|
|
36
|
+
//# sourceMappingURL=agent-grant-helpers.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agent-grant-helpers.js","sourceRoot":"","sources":["../../src/agent-grant-helpers.ts"],"names":[],"mappings":"AAEA;4GAC4G;AAC5G,MAAM,UAAU,eAAe,CAAC,CAAU;IACxC,MAAM,OAAO,GAAI,CAAyD,EAAE,OAAO,CAAC;IACpF,MAAM,IAAI,GAAG,OAAO,EAAE,aAAa,CAAC;IACpC,OAAO,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC;AACnE,CAAC;AAED;;gFAEgF;AAChF,MAAM,UAAU,aAAa,CAAC,IAAe;IAC3C,MAAM,OAAO,GAAG,IAAI,CAAC,cAAc,CAAC,CAAC,CAAC,eAAe,IAAI,CAAC,cAAc,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;IAChF,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC;QAChB,OAAO,CACL,wCAAwC,OAAO,kDAAkD;YACjG,mGAAmG;YACnG,oFAAoF;YACpF,IAAI,IAAI,CAAC,OAAO,gFAAgF;YAChG,OACE,IAAI,CAAC,cAAc;gBACjB,CAAC,CAAC,OAAO,IAAI,CAAC,cAAc,mEAAmE;oBAC7F,0FAA0F;gBAC5F,CAAC,CAAC,EACN,EAAE,CACH,CAAC;IACJ,CAAC;IACD,MAAM,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC;IACrB,MAAM,MAAM,GAAG,CAAC,CAAC,WAAW;SACzB,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC,SAAS,IAAI,CAAC,CAAC,KAAK,CAAC,MAAM,iBAAiB,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,SAAS,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;SACrH,IAAI,CAAC,IAAI,CAAC,CAAC;IACd,OAAO,iBAAiB,CAAC,CAAC,MAAM,KAAK,CAAC,CAAC,YAAY,GAAG,MAAM,CAAC,CAAC,CAAC,eAAe,MAAM,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;AACjG,CAAC;AAED;;yGAEyG;AACzG,MAAM,UAAU,eAAe,CAAC,KAAqB,EAAE,WAAmB;IACxE,MAAM,GAAG,GAAG,KAAK,CAAC,SAAS,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,WAAW,EAAE,KAAK,WAAW,CAAC,WAAW,EAAE,CAAC,CAAC;IACjH,OAAO,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;AACzD,CAAC"}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/** Thrown for any non-2xx response, carrying the HTTP status alongside the SERVER's own message (never a
|
|
2
|
+
* generic one - whoever built this agent needs the reason, §6-40 one layer up from the chain). The
|
|
3
|
+
* status is what lets `AgentRuntime` tell "this session token is stale, re-mint and retry" (401) apart
|
|
4
|
+
* from every other failure, which it should surface as-is. */
|
|
5
|
+
export declare class BotanaryApiError extends Error {
|
|
6
|
+
readonly status: number;
|
|
7
|
+
/**
|
|
8
|
+
* The backend's own `error.details` blob, carried through rather than flattened into the message.
|
|
9
|
+
* Some refusals are ACTIONABLE and say so in structured fields - `missingModule` names a setup module
|
|
10
|
+
* the account lacks - and a tool that can only read prose has to pattern-match on wording to notice.
|
|
11
|
+
* Keeping the object means a handler keys off a field the backend guarantees instead of a sentence it
|
|
12
|
+
* is free to reword. Null whenever the response carried none.
|
|
13
|
+
*/
|
|
14
|
+
readonly details: Record<string, unknown> | null;
|
|
15
|
+
/**
|
|
16
|
+
* The `Retry-After` header's value in SECONDS, when the server sent one (429/503 carry it). Null
|
|
17
|
+
* otherwise. Kept as a first-class field because a caller that wants to survive a rate limit -
|
|
18
|
+
* `wallet/login.ts`'s poll loop is the one that must - cannot see response headers otherwise, and
|
|
19
|
+
* guessing a backoff when the server told you the exact number is how a retry storm starts.
|
|
20
|
+
* Only the numeric (delta-seconds) form is parsed; the HTTP-date form yields null, and the caller
|
|
21
|
+
* falls back to its own backoff rather than mis-parsing a date as a duration.
|
|
22
|
+
*/
|
|
23
|
+
readonly retryAfterSeconds: number | null;
|
|
24
|
+
constructor(message: string, status: number,
|
|
25
|
+
/**
|
|
26
|
+
* The backend's own `error.details` blob, carried through rather than flattened into the message.
|
|
27
|
+
* Some refusals are ACTIONABLE and say so in structured fields - `missingModule` names a setup module
|
|
28
|
+
* the account lacks - and a tool that can only read prose has to pattern-match on wording to notice.
|
|
29
|
+
* Keeping the object means a handler keys off a field the backend guarantees instead of a sentence it
|
|
30
|
+
* is free to reword. Null whenever the response carried none.
|
|
31
|
+
*/
|
|
32
|
+
details?: Record<string, unknown> | null,
|
|
33
|
+
/**
|
|
34
|
+
* The `Retry-After` header's value in SECONDS, when the server sent one (429/503 carry it). Null
|
|
35
|
+
* otherwise. Kept as a first-class field because a caller that wants to survive a rate limit -
|
|
36
|
+
* `wallet/login.ts`'s poll loop is the one that must - cannot see response headers otherwise, and
|
|
37
|
+
* guessing a backoff when the server told you the exact number is how a retry storm starts.
|
|
38
|
+
* Only the numeric (delta-seconds) form is parsed; the HTTP-date form yields null, and the caller
|
|
39
|
+
* falls back to its own backoff rather than mis-parsing a date as a duration.
|
|
40
|
+
*/
|
|
41
|
+
retryAfterSeconds?: number | null);
|
|
42
|
+
}
|
|
43
|
+
/** JSON in and out, throwing the SERVER's own message rather than a generic one - whoever built this
|
|
44
|
+
* agent needs the reason, not "request failed" (§6-40, one layer up from the chain). */
|
|
45
|
+
export declare class BotanaryApiClient {
|
|
46
|
+
#private;
|
|
47
|
+
private readonly baseUrl;
|
|
48
|
+
private readonly fetchImpl;
|
|
49
|
+
constructor(baseUrl: string, fetchImpl?: typeof fetch);
|
|
50
|
+
post<T>(path: string, body: unknown, token?: string): Promise<T>;
|
|
51
|
+
/** GET has no body - a query string, when one is needed, belongs in `path` itself (callers below never
|
|
52
|
+
* put a token or anything secret there; see test/no-leak.spec.ts). */
|
|
53
|
+
get<T>(path: string, token?: string): Promise<T>;
|
|
54
|
+
/** DELETE request for logout and cleanup operations. No body, authenticated with optional token. */
|
|
55
|
+
delete<T>(path: string, token?: string): Promise<T>;
|
|
56
|
+
}
|
|
57
|
+
//# sourceMappingURL=api-client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"api-client.d.ts","sourceRoot":"","sources":["../../src/api-client.ts"],"names":[],"mappings":"AAAA;;;+DAG+D;AAC/D,qBAAa,gBAAiB,SAAQ,KAAK;IAGvC,QAAQ,CAAC,MAAM,EAAE,MAAM;IACvB;;;;;;OAMG;IACH,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IAChD;;;;;;;OAOG;IACH,QAAQ,CAAC,iBAAiB,EAAE,MAAM,GAAG,IAAI;gBAlBzC,OAAO,EAAE,MAAM,EACN,MAAM,EAAE,MAAM;IACvB;;;;;;OAMG;IACM,OAAO,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAW;IACvD;;;;;;;OAOG;IACM,iBAAiB,GAAE,MAAM,GAAG,IAAW;CAKnD;AAED;yFACyF;AACzF,qBAAa,iBAAiB;;IAE1B,OAAO,CAAC,QAAQ,CAAC,OAAO;IACxB,OAAO,CAAC,QAAQ,CAAC,SAAS;gBADT,OAAO,EAAE,MAAM,EACf,SAAS,GAAE,OAAO,KAAa;IAG5C,IAAI,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC;IAItE;2EACuE;IACjE,GAAG,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC;IAItD,oGAAoG;IAC9F,MAAM,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC;CAyC1D"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Where to send an owner in their browser, derived from the API this server is configured against.
|
|
3
|
+
*
|
|
4
|
+
* ITS OWN MODULE, not a corner of `tools.ts`, because both the tool surface and `diagnose` hand out these
|
|
5
|
+
* links and `tools.ts` already imports `diagnose`. Leaving them in `tools.ts` made that a cycle.
|
|
6
|
+
*/
|
|
7
|
+
/** Derive the Botanary APP origin (what an owner's browser visits) from the API base URL this runtime
|
|
8
|
+
* is actually configured against, so a deep link lands on a LOCAL FE when this server is pointed at a
|
|
9
|
+
* local stack, rather than always hardcoding production. Recognizes two shapes:
|
|
10
|
+
* - Production/staging: the API host is `api.` + the app host (`api.app.botanary.xyz` ->
|
|
11
|
+
* `app.botanary.xyz`) - strip that one label.
|
|
12
|
+
* - The local docker-compose stack (`../../docker-compose.yml`), which pairs BE :3000 with FE :3001.
|
|
13
|
+
* Anything else - an unparseable URL, or a host this function does not recognize - falls back to the
|
|
14
|
+
* production app origin: a deep link that opens the wrong (but real) app is safer than one built from
|
|
15
|
+
* a guess that resolves nowhere. */
|
|
16
|
+
export declare function deriveAppOrigin(apiBaseUrl: string): string;
|
|
17
|
+
/**
|
|
18
|
+
* The deep link an owner opens to finish setting up their own account.
|
|
19
|
+
*
|
|
20
|
+
* WHY A LINK AT ALL. A missing setup module is the one refusal an agent can neither retry its way out of
|
|
21
|
+
* nor fix itself: installing a module is an authority change, the op must be signed by the owner's key in
|
|
22
|
+
* their browser, and a session key must never be able to grant itself new execution modules. So the honest
|
|
23
|
+
* response is a handoff - and a handoff without an address is a dead end. The owner reading this is usually
|
|
24
|
+
* the same person reading the terminal, so "ask your owner" is not an instruction, it is a shrug.
|
|
25
|
+
*
|
|
26
|
+
* WHAT IT CARRIES. Navigation only: an origin from configuration and a chain id. No signing payload, no
|
|
27
|
+
* op, no instruction - the page independently asks the backend what is missing and derives the ops from
|
|
28
|
+
* chain state. Nothing here is interpolated from model-controlled text or from a tool result, which is the
|
|
29
|
+
* same discipline the deterministic gate follows: a link an agent emits and a human then signs on must not
|
|
30
|
+
* be steerable by anything the model saw.
|
|
31
|
+
*/
|
|
32
|
+
export declare function setupUrl(apiBaseUrl: string, chainId?: number): string;
|
|
33
|
+
//# sourceMappingURL=app-link.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"app-link.d.ts","sourceRoot":"","sources":["../../src/app-link.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAMH;;;;;;;;qCAQqC;AACrC,wBAAgB,eAAe,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAc1D;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,QAAQ,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,CAGrE"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { Server } from '@modelcontextprotocol/sdk/server/index.js';
|
|
2
|
+
import type { AgentRuntime } from './runtime.js';
|
|
3
|
+
export interface CliDeps {
|
|
4
|
+
runtime: AgentRuntime;
|
|
5
|
+
createServer: (runtime: AgentRuntime) => Server;
|
|
6
|
+
createTransport: () => Parameters<Server['connect']>[0];
|
|
7
|
+
stdout?: (line: string) => void;
|
|
8
|
+
stderr?: (line: string) => void;
|
|
9
|
+
}
|
|
10
|
+
/** Runs one CLI invocation and returns the process exit code. Kept free of `process.exit`/signal
|
|
11
|
+
* handling so it's directly testable with fake deps - see test/cli.spec.ts. bin/botanary-mcp.ts is
|
|
12
|
+
* the (deliberately tiny, untested-by-inspection) shim that wires real deps and process lifecycle. */
|
|
13
|
+
export declare function runCli(argv: string[], deps: CliDeps): Promise<number>;
|
|
14
|
+
//# sourceMappingURL=cli.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../../src/cli.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,2CAA2C,CAAC;AACxE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAiBjD,MAAM,WAAW,OAAO;IACtB,OAAO,EAAE,YAAY,CAAC;IACtB,YAAY,EAAE,CAAC,OAAO,EAAE,YAAY,KAAK,MAAM,CAAC;IAChD,eAAe,EAAE,MAAM,UAAU,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACxD,MAAM,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAChC,MAAM,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;CACjC;AAED;;uGAEuG;AACvG,wBAAsB,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,IAAI,EAAE,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC,CA0B3E"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import type { AgentRuntime } from './runtime.js';
|
|
2
|
+
export type DiagnoseState = 'no_key' | 'key_unclaimed' | 'backend_unavailable' | 'connected_no_grant' | 'grant_inactive' | 'chain_unusable'
|
|
3
|
+
/** The account is missing a setup module the grant needs. Distinct from `chain_unusable` (the CHAIN
|
|
4
|
+
* cannot do this at all) and from `unfunded`/`budget_exhausted` (conditions that resolve on their own
|
|
5
|
+
* or with money): this one is permanent until an owner signs an install, so it deserves its own name
|
|
6
|
+
* rather than being folded into `degraded`. */
|
|
7
|
+
| 'setup_required'
|
|
8
|
+
/** The X402PaymentValidator is not installed on the account. Like `setup_required`, this is permanent
|
|
9
|
+
* until an owner signs an install - it is ranked BEFORE `unfunded` since installing comes first. */
|
|
10
|
+
| 'validator_not_installed' | 'unfunded'
|
|
11
|
+
/** The agent's budget for API calls has been exhausted. The owner can refill or issue a new budget. */
|
|
12
|
+
| 'budget_exhausted' | 'degraded' | 'ready';
|
|
13
|
+
export interface Blocker {
|
|
14
|
+
/** MCP-LOCAL vocabulary. Deliberately NOT the backend's `DeclineReason` names, which map 1:1 to
|
|
15
|
+
* AgentGuard revert selectors - reusing those would imply an on-chain refusal where this is only a
|
|
16
|
+
* local read. */
|
|
17
|
+
code: string;
|
|
18
|
+
severity: 'blocking' | 'warning';
|
|
19
|
+
detail: string;
|
|
20
|
+
nextAction: string;
|
|
21
|
+
}
|
|
22
|
+
export interface DiagnoseReport {
|
|
23
|
+
state: DiagnoseState;
|
|
24
|
+
summary: string;
|
|
25
|
+
blockers: Blocker[];
|
|
26
|
+
facts: Record<string, unknown>;
|
|
27
|
+
freshness: Record<string, string>;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* The cold-start question: who am I bound to, is it funded, can this chain do what my grant claims, and
|
|
31
|
+
* what is stopping the next action. Runs its checks in order and STOPS DESCENDING once the state is
|
|
32
|
+
* known - it never issues a call whose answer could not change the verdict.
|
|
33
|
+
*
|
|
34
|
+
* Never mutates and never signs. Every number it reports is the backend's own.
|
|
35
|
+
*/
|
|
36
|
+
export declare function runDiagnose(runtime: AgentRuntime): Promise<DiagnoseReport>;
|
|
37
|
+
//# sourceMappingURL=diagnose.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"diagnose.d.ts","sourceRoot":"","sources":["../../src/diagnose.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,YAAY,EAAa,MAAM,cAAc,CAAC;AAE5D,MAAM,MAAM,aAAa,GACrB,QAAQ,GACR,eAAe,GACf,qBAAqB,GACrB,oBAAoB,GACpB,gBAAgB,GAChB,gBAAgB;AAClB;;;gDAGgD;GAC9C,gBAAgB;AAClB;qGACqG;GACnG,yBAAyB,GACzB,UAAU;AACZ,uGAAuG;GACrG,kBAAkB,GAClB,UAAU,GACV,OAAO,CAAC;AAEZ,MAAM,WAAW,OAAO;IACtB;;sBAEkB;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,UAAU,GAAG,SAAS,CAAC;IACjC,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,aAAa,CAAC;IACrB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,OAAO,EAAE,CAAC;IACpB,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC/B,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACnC;AAeD;;;;;;GAMG;AACH,wBAAsB,WAAW,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,cAAc,CAAC,CA4PhF"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export interface ExecResult {
|
|
2
|
+
stdout: string;
|
|
3
|
+
stderr: string;
|
|
4
|
+
code: number;
|
|
5
|
+
}
|
|
6
|
+
export interface ExecOptions {
|
|
7
|
+
/** Piped to the child's stdin, then the stdin stream is closed. Used to hand a secret to a command
|
|
8
|
+
* WITHOUT it ever appearing on argv (and therefore never in `ps`/process-list output) - secret-tool
|
|
9
|
+
* and the Windows DPAPI helper both read the secret this way. macOS's `security` CLI has no stdin
|
|
10
|
+
* form for the password, which is a real, documented limitation - see macos-keychain.ts. */
|
|
11
|
+
input?: string;
|
|
12
|
+
}
|
|
13
|
+
export type Exec = (command: string, args: string[], options?: ExecOptions) => Promise<ExecResult>;
|
|
14
|
+
/** The real implementation: spawn a child process (no shell - argv is passed directly, so there is no
|
|
15
|
+
* shell-quoting/injection surface), capture stdout/stderr, resolve with the exit code. `spawn` (not
|
|
16
|
+
* `execFile`) because we need to write to stdin ourselves and close it explicitly. */
|
|
17
|
+
export declare const nodeExec: Exec;
|
|
18
|
+
//# sourceMappingURL=exec.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"exec.d.ts","sourceRoot":"","sources":["../../../../src/identity/backends/exec.ts"],"names":[],"mappings":"AAMA,MAAM,WAAW,UAAU;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,WAAW;IAC1B;;;iGAG6F;IAC7F,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,MAAM,IAAI,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,OAAO,CAAC,EAAE,WAAW,KAAK,OAAO,CAAC,UAAU,CAAC,CAAC;AAEnG;;uFAEuF;AACvF,eAAO,MAAM,QAAQ,EAAE,IAwBtB,CAAC"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { type KeyBackend } from './types.js';
|
|
2
|
+
export declare function createFileFallbackBackend(filePath?: string): KeyBackend;
|
|
3
|
+
/** Exposed for tests: true only if the file exists and (on POSIX) is exactly owner-rw. Windows mode
|
|
4
|
+
* bits are not meaningful via fs.stat, so callers should skip the assertion there. */
|
|
5
|
+
export declare function isPrivateFileMode(filePath: string): Promise<boolean>;
|
|
6
|
+
//# sourceMappingURL=file-fallback.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"file-fallback.d.ts","sourceRoot":"","sources":["../../../../src/identity/backends/file-fallback.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,UAAU,EAAmB,MAAM,YAAY,CAAC;AAe9D,wBAAgB,yBAAyB,CAAC,QAAQ,GAAE,MAAiC,GAAG,UAAU,CAoCjG;AAED;uFACuF;AACvF,wBAAsB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAG1E"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"libsecret.d.ts","sourceRoot":"","sources":["../../../../src/identity/backends/libsecret.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,IAAI,EAAY,MAAM,WAAW,CAAC;AAChD,OAAO,EAAgB,KAAK,UAAU,EAAiC,MAAM,YAAY,CAAC;AAY1F,wBAAgB,sBAAsB,CAAC,IAAI,GAAE,IAAe,EAAE,WAAW,GAAE,MAAqB,EAAE,WAAW,GAAE,MAAqB,GAAG,UAAU,CAiDhJ"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"macos-keychain.d.ts","sourceRoot":"","sources":["../../../../src/identity/backends/macos-keychain.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,IAAI,EAAY,MAAM,WAAW,CAAC;AAChD,OAAO,EAAgB,KAAK,UAAU,EAAiC,MAAM,YAAY,CAAC;AAgB1F,wBAAgB,0BAA0B,CAAC,IAAI,GAAE,IAAe,EAAE,WAAW,GAAE,MAAqB,EAAE,WAAW,GAAE,MAAqB,GAAG,UAAU,CA+CpJ"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { KeyBackend } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Fixed, platform-derived priority order. The SAME list is used for reads and writes (store.ts): a new
|
|
4
|
+
* key is written to the first available candidate, and every candidate is swept in this order when
|
|
5
|
+
* looking for an existing one. `file-fallback` is always last and always available, so this list can
|
|
6
|
+
* never be empty and a caller can never end up with nowhere to store a key.
|
|
7
|
+
*
|
|
8
|
+
* CRITICAL: the agent's names (SERVICE_NAME / ACCOUNT_NAME) are FROZEN for backward compatibility.
|
|
9
|
+
* Existing installs already have keys stored under these names. Wallet uses a distinct ACCOUNT_NAME
|
|
10
|
+
* to prevent collision.
|
|
11
|
+
*/
|
|
12
|
+
export declare function defaultCandidates(platform?: NodeJS.Platform, isWallet?: boolean): KeyBackend[];
|
|
13
|
+
/** Pick the first available backend from `candidates`, in order. Used only to decide where a NEW key
|
|
14
|
+
* gets written - see the KeyBackend interface doc for why reads don't use this. */
|
|
15
|
+
export declare function selectAvailable(candidates: KeyBackend[]): Promise<KeyBackend>;
|
|
16
|
+
//# sourceMappingURL=select.d.ts.map
|