botanary 0.1.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/README.md +39 -0
- package/dist/bin/botanary.js +12 -0
- package/dist/bin/botanary.js.map +1 -0
- package/dist/package.json +41 -0
- package/dist/src/cli.js +57 -0
- package/dist/src/cli.js.map +1 -0
- package/dist/src/commands/agent.js +178 -0
- package/dist/src/commands/agent.js.map +1 -0
- package/dist/src/commands/mcp.js +19 -0
- package/dist/src/commands/mcp.js.map +1 -0
- package/dist/src/commands/system.js +38 -0
- package/dist/src/commands/system.js.map +1 -0
- package/dist/src/commands/wallet.js +223 -0
- package/dist/src/commands/wallet.js.map +1 -0
- package/dist/src/context.js +9 -0
- package/dist/src/context.js.map +1 -0
- package/dist/src/mcp-snippets.js +21 -0
- package/dist/src/mcp-snippets.js.map +1 -0
- package/dist/src/parser.js +65 -0
- package/dist/src/parser.js.map +1 -0
- package/dist/src/render/banner.js +17 -0
- package/dist/src/render/banner.js.map +1 -0
- package/dist/src/render/colors.js +50 -0
- package/dist/src/render/colors.js.map +1 -0
- package/dist/src/render/json-mode.js +10 -0
- package/dist/src/render/json-mode.js.map +1 -0
- package/dist/src/render/redact.js +23 -0
- package/dist/src/render/redact.js.map +1 -0
- package/dist/src/render/table.js +16 -0
- package/dist/src/render/table.js.map +1 -0
- package/dist/src/repl.js +128 -0
- package/dist/src/repl.js.map +1 -0
- package/package.json +41 -0
package/README.md
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# botanary
|
|
2
|
+
|
|
3
|
+
Botanary from your terminal - a guided CLI over the same wallet and agent lanes `botanary-mcp` exposes to
|
|
4
|
+
a coding agent. Shares its identity/session storage (`~/.botanary-mcp`, override with
|
|
5
|
+
`BOTANARY_MCP_HOME`): log in once, from either surface, and both see it.
|
|
6
|
+
|
|
7
|
+
## Install
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npx botanary # zero-install, always latest
|
|
11
|
+
npm i -g botanary # resident on PATH
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
## Use
|
|
15
|
+
|
|
16
|
+
Run `botanary` with no arguments for a guided REPL, or run any command directly:
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
botanary login
|
|
20
|
+
botanary balance
|
|
21
|
+
botanary send --amount 25 --token usdc --recipient 0xAb12...9F3 --chain-id 8453
|
|
22
|
+
botanary agent whoami
|
|
23
|
+
botanary mcp config claude
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
Every command works both ways: answer prompts interactively, or pass flags and add `--json` for scripts
|
|
27
|
+
and CI. `--json` also auto-enables whenever stdout is piped or redirected.
|
|
28
|
+
|
|
29
|
+
## Development
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
pnpm install
|
|
33
|
+
pnpm build
|
|
34
|
+
pnpm test
|
|
35
|
+
pnpm dev # run bin/botanary.ts directly, watching for changes
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
`BOTANARY_MCP_HOME` and `BOTANARY_API_URL` behave exactly as documented in `botanary-mcp`'s own README -
|
|
39
|
+
this package depends on that one as its engine and adds no storage or network logic of its own.
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { createDefaultRuntime } from 'botanary-mcp';
|
|
3
|
+
import { runCli } from '../src/cli.js';
|
|
4
|
+
// Deliberately the only file in this package that is not unit tested directly - mirrors
|
|
5
|
+
// botanary-mcp's own bin/botanary-mcp.ts, which wires the real runtime into runCli and nothing else.
|
|
6
|
+
const packageJson = await import('../package.json', { with: { type: 'json' } });
|
|
7
|
+
const exitCode = await runCli(process.argv.slice(2), {
|
|
8
|
+
runtime: createDefaultRuntime(),
|
|
9
|
+
cliVersion: packageJson.default.version,
|
|
10
|
+
});
|
|
11
|
+
process.exit(exitCode);
|
|
12
|
+
//# sourceMappingURL=botanary.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"botanary.js","sourceRoot":"","sources":["../../bin/botanary.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAC;AACpD,OAAO,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AAEvC,wFAAwF;AACxF,qGAAqG;AACrG,MAAM,WAAW,GAAG,MAAM,MAAM,CAAC,iBAAiB,EAAE,EAAE,IAAI,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,CAAC,CAAC;AAChF,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE;IACnD,OAAO,EAAE,oBAAoB,EAAE;IAC/B,UAAU,EAAE,WAAW,CAAC,OAAO,CAAC,OAAiB;CAClD,CAAC,CAAC;AACH,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "botanary",
|
|
3
|
+
"type": "module",
|
|
4
|
+
"version": "0.1.0",
|
|
5
|
+
"description": "Botanary from your terminal - a guided CLI over the same wallet and agent lanes botanary-mcp exposes to a coding agent.",
|
|
6
|
+
"license": "UNLICENSED",
|
|
7
|
+
"homepage": "https://docs.botanary.xyz",
|
|
8
|
+
"keywords": ["botanary", "cli", "wallet"],
|
|
9
|
+
"bin": {
|
|
10
|
+
"botanary": "dist/bin/botanary.js"
|
|
11
|
+
},
|
|
12
|
+
"files": ["dist", "README.md"],
|
|
13
|
+
"engines": {
|
|
14
|
+
"node": ">=22.0.0"
|
|
15
|
+
},
|
|
16
|
+
"scripts": {
|
|
17
|
+
"build": "tsc -p tsconfig.build.json",
|
|
18
|
+
"prepare": "tsc -p tsconfig.build.json",
|
|
19
|
+
"dev": "node --watch -r @swc-node/register bin/botanary.ts",
|
|
20
|
+
"start": "node dist/bin/botanary.js",
|
|
21
|
+
"typecheck": "tsc -p tsconfig.json --noEmit",
|
|
22
|
+
"test": "vitest run",
|
|
23
|
+
"test:watch": "vitest"
|
|
24
|
+
},
|
|
25
|
+
"dependencies": {
|
|
26
|
+
"botanary-mcp": "^0.5.0",
|
|
27
|
+
"commander": "^13.1.0",
|
|
28
|
+
"@clack/prompts": "^0.9.1",
|
|
29
|
+
"picocolors": "^1.1.1",
|
|
30
|
+
"gradient-string": "^3.0.0",
|
|
31
|
+
"figlet": "^1.7.0",
|
|
32
|
+
"cli-table3": "^0.6.5"
|
|
33
|
+
},
|
|
34
|
+
"devDependencies": {
|
|
35
|
+
"@swc-node/register": "^1.10.9",
|
|
36
|
+
"@types/figlet": "^1.7.0",
|
|
37
|
+
"@types/node": "^22.10.5",
|
|
38
|
+
"typescript": "^5.7.3",
|
|
39
|
+
"vitest": "^2.1.8"
|
|
40
|
+
}
|
|
41
|
+
}
|
package/dist/src/cli.js
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { CommanderError } from 'commander';
|
|
2
|
+
import { createContext } from './context.js';
|
|
3
|
+
import { createProgram } from './parser.js';
|
|
4
|
+
import { registerWalletCommands } from './commands/wallet.js';
|
|
5
|
+
import { registerAgentCommands } from './commands/agent.js';
|
|
6
|
+
import { registerMcpCommands } from './commands/mcp.js';
|
|
7
|
+
import { registerSystemCommands } from './commands/system.js';
|
|
8
|
+
import { runRepl } from './repl.js';
|
|
9
|
+
import { setColorEnabled } from './render/colors.js';
|
|
10
|
+
import { isJsonMode } from './render/json-mode.js';
|
|
11
|
+
export async function runCli(argv, deps) {
|
|
12
|
+
const stderr = deps.stderr ?? ((line) => process.stderr.write(`${line}\n`));
|
|
13
|
+
const program = createProgram();
|
|
14
|
+
program.version(deps.cliVersion, '-V, --version', 'Print the installed botanary-cli version');
|
|
15
|
+
registerWalletCommands(program);
|
|
16
|
+
registerAgentCommands(program);
|
|
17
|
+
registerMcpCommands(program);
|
|
18
|
+
registerSystemCommands(program, deps.cliVersion);
|
|
19
|
+
program.exitOverride();
|
|
20
|
+
try {
|
|
21
|
+
program.parseOptions(argv);
|
|
22
|
+
const opts = program.opts();
|
|
23
|
+
// colors.ts's own default (pc.isColorSupported) already correctly auto-detects whether stdout is
|
|
24
|
+
// a real color-capable terminal - only override it to force OFF when the user explicitly opted
|
|
25
|
+
// out (--no-color, which commander surfaces as opts.color === false - not merely "falsy", since
|
|
26
|
+
// commander defaults opts.color to true when the flag isn't passed) or set NO_COLOR. Never force
|
|
27
|
+
// it ON: that was the bug - it made every ordinary invocation ignore the real TTY/pipe state.
|
|
28
|
+
if (opts.color === false || process.env.NO_COLOR) {
|
|
29
|
+
setColorEnabled(false);
|
|
30
|
+
}
|
|
31
|
+
const ctx = createContext(deps.runtime, {
|
|
32
|
+
...opts,
|
|
33
|
+
json: isJsonMode({ json: opts.json }, process.stdout),
|
|
34
|
+
interactive: opts.interactive === false ? false : !!process.stdin.isTTY && !!process.stdout.isTTY,
|
|
35
|
+
});
|
|
36
|
+
program.opts = () => ({ ...opts, __ctx: ctx });
|
|
37
|
+
if (argv.length === 0 && process.stdout.isTTY && !ctx.noInteractive) {
|
|
38
|
+
const session = await deps.runtime.walletSession();
|
|
39
|
+
const hasAgent = await deps.runtime.store.hasIdentity();
|
|
40
|
+
await runRepl(program, { loggedIn: !!session, hasAgent });
|
|
41
|
+
return 0;
|
|
42
|
+
}
|
|
43
|
+
await program.parseAsync(argv, { from: 'user' });
|
|
44
|
+
return 0;
|
|
45
|
+
}
|
|
46
|
+
catch (e) {
|
|
47
|
+
if (e instanceof CommanderError) {
|
|
48
|
+
if (e.exitCode !== 0) {
|
|
49
|
+
stderr(e.message);
|
|
50
|
+
}
|
|
51
|
+
return e.exitCode;
|
|
52
|
+
}
|
|
53
|
+
stderr(e instanceof Error ? e.message : String(e));
|
|
54
|
+
return 1;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
//# sourceMappingURL=cli.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../../src/cli.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
import * as clack from '@clack/prompts';
|
|
2
|
+
import { proposePayment, proposeSwap, describeGrant, botanaryMcpHome } from 'botanary-mcp';
|
|
3
|
+
import { randomBytes } from 'node:crypto';
|
|
4
|
+
import { mkdir, readFile, rm, writeFile } from 'node:fs/promises';
|
|
5
|
+
import { join } from 'node:path';
|
|
6
|
+
import { glyphs } from '../render/colors.js';
|
|
7
|
+
function printResult(ctx, data) {
|
|
8
|
+
console.log(ctx.json ? JSON.stringify(data) : JSON.stringify(data, null, 2));
|
|
9
|
+
}
|
|
10
|
+
export function registerAgentCommands(program) {
|
|
11
|
+
const agent = program.command('agent').description('This machine\'s own agent identity, grant, and spend under it');
|
|
12
|
+
agent
|
|
13
|
+
.command('whoami')
|
|
14
|
+
.description('This agent\'s address, public key, and fingerprint (get_identity)')
|
|
15
|
+
.action(async () => {
|
|
16
|
+
const ctx = program.opts().__ctx;
|
|
17
|
+
const identity = await ctx.runtime.identity();
|
|
18
|
+
printResult(ctx, { address: identity.address, publicKey: identity.publicKey, fingerprint: identity.fingerprint, keyStorage: identity.backend });
|
|
19
|
+
});
|
|
20
|
+
agent
|
|
21
|
+
.command('pair')
|
|
22
|
+
.description('Show (or rotate) the pairing code and register it with Botanary')
|
|
23
|
+
.option('--regenerate', 'Rotate to a fresh code')
|
|
24
|
+
.action(async (opts) => {
|
|
25
|
+
const ctx = program.opts().__ctx;
|
|
26
|
+
const identity = await ctx.runtime.identity();
|
|
27
|
+
const pairing = opts.regenerate ? await ctx.runtime.regeneratePairingCode() : await ctx.runtime.pair();
|
|
28
|
+
if (!ctx.json) {
|
|
29
|
+
console.log(glyphs.info(`Pairing code: ${pairing.code}`));
|
|
30
|
+
console.log('In Botanary, open Connected agents and enter this code.');
|
|
31
|
+
}
|
|
32
|
+
printResult(ctx, { ...pairing, address: identity.address });
|
|
33
|
+
});
|
|
34
|
+
agent
|
|
35
|
+
.command('grant')
|
|
36
|
+
.description('This agent\'s current grant, rendered in plain terms (what_may_i_do)')
|
|
37
|
+
.action(async () => {
|
|
38
|
+
const ctx = program.opts().__ctx;
|
|
39
|
+
const self = await ctx.runtime.me();
|
|
40
|
+
const description = describeGrant(self);
|
|
41
|
+
if (!ctx.json)
|
|
42
|
+
console.log(description);
|
|
43
|
+
else
|
|
44
|
+
printResult(ctx, { description, grant: self.grant });
|
|
45
|
+
});
|
|
46
|
+
agent
|
|
47
|
+
.command('requests')
|
|
48
|
+
.description('Every approval request this agent has filed, and the owner\'s verdict on each (list_requests)')
|
|
49
|
+
.action(async () => {
|
|
50
|
+
const ctx = program.opts().__ctx;
|
|
51
|
+
printResult(ctx, await ctx.runtime.listRequests());
|
|
52
|
+
});
|
|
53
|
+
agent
|
|
54
|
+
.command('spend')
|
|
55
|
+
.description('Spend under this agent\'s own grant, unattended (propose_payment)')
|
|
56
|
+
.option('--recipient <address>')
|
|
57
|
+
.option('--amount <amount>')
|
|
58
|
+
.option('--token <symbol>')
|
|
59
|
+
.option('--chain-id <chainId>')
|
|
60
|
+
.action(async (opts) => {
|
|
61
|
+
const ctx = program.opts().__ctx;
|
|
62
|
+
let { recipient, amount, token: tokenSymbol, chainId } = opts;
|
|
63
|
+
if (!ctx.noInteractive && (!recipient || !amount || !tokenSymbol || !chainId)) {
|
|
64
|
+
const answers = await clack.group({
|
|
65
|
+
amount: () => clack.text({ message: 'Amount?', initialValue: amount }),
|
|
66
|
+
token: () => clack.text({ message: 'Token?', initialValue: tokenSymbol }),
|
|
67
|
+
recipient: () => clack.text({ message: 'To?', initialValue: recipient }),
|
|
68
|
+
chainId: () => clack.text({ message: 'Chain ID?', initialValue: chainId }),
|
|
69
|
+
}, { onCancel: () => { clack.cancel('Cancelled.'); process.exit(0); } });
|
|
70
|
+
({ recipient, amount, token: tokenSymbol, chainId } = answers);
|
|
71
|
+
}
|
|
72
|
+
if (!recipient || !amount || !tokenSymbol || !chainId) {
|
|
73
|
+
throw new Error('Missing required input: --recipient, --amount, --token, --chain-id (or run interactively).');
|
|
74
|
+
}
|
|
75
|
+
const result = await proposePayment(ctx.runtime, { recipient, amount: Number(amount), tokenSymbol, chainId: Number(chainId) });
|
|
76
|
+
printResult(ctx, result);
|
|
77
|
+
});
|
|
78
|
+
agent
|
|
79
|
+
.command('swap')
|
|
80
|
+
.description('Swap under this agent\'s own grant, unattended (propose_swap)')
|
|
81
|
+
.option('--token-in <symbol>')
|
|
82
|
+
.option('--token-out <symbol>')
|
|
83
|
+
.option('--amount-in <amount>')
|
|
84
|
+
.option('--chain-id <chainId>')
|
|
85
|
+
.option('--max-slippage-bps <bps>')
|
|
86
|
+
.action(async (opts) => {
|
|
87
|
+
const ctx = program.opts().__ctx;
|
|
88
|
+
const { tokenIn, tokenOut, amountIn, chainId, maxSlippageBps } = opts;
|
|
89
|
+
if (!tokenIn || !tokenOut || !amountIn || !chainId) {
|
|
90
|
+
throw new Error('Missing required input: --token-in, --token-out, --amount-in, --chain-id.');
|
|
91
|
+
}
|
|
92
|
+
const result = await proposeSwap(ctx.runtime, {
|
|
93
|
+
tokenIn,
|
|
94
|
+
tokenOut,
|
|
95
|
+
amountIn: Number(amountIn),
|
|
96
|
+
chainId: Number(chainId),
|
|
97
|
+
...(maxSlippageBps ? { maxSlippageBps: Number(maxSlippageBps) } : {}),
|
|
98
|
+
});
|
|
99
|
+
printResult(ctx, result);
|
|
100
|
+
});
|
|
101
|
+
agent
|
|
102
|
+
.command('status <opId>')
|
|
103
|
+
.description('Check on a pending action this agent relayed (get_action_status)')
|
|
104
|
+
.action(async (opId) => {
|
|
105
|
+
const ctx = program.opts().__ctx;
|
|
106
|
+
printResult(ctx, await ctx.runtime.getUserOp(opId));
|
|
107
|
+
});
|
|
108
|
+
agent
|
|
109
|
+
.command('apis')
|
|
110
|
+
.description('Paid (x402) third-party API endpoints this agent may call, with live price and remaining budget (list_apis)')
|
|
111
|
+
.requiredOption('--chain-id <chainId>')
|
|
112
|
+
.action(async (opts) => {
|
|
113
|
+
const ctx = program.opts().__ctx;
|
|
114
|
+
printResult(ctx, await ctx.runtime.listApis(Number(opts.chainId)));
|
|
115
|
+
});
|
|
116
|
+
agent
|
|
117
|
+
.command('pay <endpointId>')
|
|
118
|
+
.description('Call a paid API endpoint and pay for it inside the owner-committed on-chain budget (call_api)')
|
|
119
|
+
.requiredOption('--chain-id <chainId>')
|
|
120
|
+
.requiredOption('--provider-id <providerId>')
|
|
121
|
+
.requiredOption('--url <url>')
|
|
122
|
+
.action(async (endpointId, opts) => {
|
|
123
|
+
const ctx = program.opts().__ctx;
|
|
124
|
+
printResult(ctx, await ctx.runtime.callApi({ chainId: Number(opts.chainId), providerId: opts.providerId, endpointId, url: opts.url }));
|
|
125
|
+
});
|
|
126
|
+
agent
|
|
127
|
+
.command('budget')
|
|
128
|
+
.description('Remaining authorizations, per-call max, expiry and epoch for this agent on a chain (get_api_budget)')
|
|
129
|
+
.requiredOption('--chain-id <chainId>')
|
|
130
|
+
.action(async (opts) => {
|
|
131
|
+
const ctx = program.opts().__ctx;
|
|
132
|
+
printResult(ctx, await ctx.runtime.getApiBudget(Number(opts.chainId)));
|
|
133
|
+
});
|
|
134
|
+
const FORGET_TOKEN_TTL_MS = 5 * 60 * 1000;
|
|
135
|
+
const pendingForgetPath = () => join(botanaryMcpHome(), '.cli-forget-pending.json');
|
|
136
|
+
agent
|
|
137
|
+
.command('forget')
|
|
138
|
+
.description('Step 1 of 2: preview what forgetting the local identity would destroy')
|
|
139
|
+
.action(async () => {
|
|
140
|
+
const ctx = program.opts().__ctx;
|
|
141
|
+
const hadIdentity = await ctx.runtime.store.hasIdentity();
|
|
142
|
+
if (!hadIdentity) {
|
|
143
|
+
printResult(ctx, { hadIdentity: false, message: 'No agent identity is stored on this machine - nothing to delete.' });
|
|
144
|
+
return;
|
|
145
|
+
}
|
|
146
|
+
const confirmationToken = randomBytes(16).toString('hex');
|
|
147
|
+
await mkdir(botanaryMcpHome(), { recursive: true });
|
|
148
|
+
await writeFile(pendingForgetPath(), JSON.stringify({ token: confirmationToken, expiresAt: Date.now() + FORGET_TOKEN_TTL_MS }), 'utf8');
|
|
149
|
+
printResult(ctx, {
|
|
150
|
+
hadIdentity: true,
|
|
151
|
+
confirmationToken,
|
|
152
|
+
message: `Run \`botanary agent confirm-forget ${confirmationToken}\` within 5 minutes to actually delete the key from this machine.`,
|
|
153
|
+
});
|
|
154
|
+
});
|
|
155
|
+
agent
|
|
156
|
+
.command('confirm-forget <token>')
|
|
157
|
+
.description('Step 2 of 2: actually delete the agent key from this machine, given the token from forget')
|
|
158
|
+
.action(async (token) => {
|
|
159
|
+
const ctx = program.opts().__ctx;
|
|
160
|
+
let pending = null;
|
|
161
|
+
try {
|
|
162
|
+
pending = JSON.parse(await readFile(pendingForgetPath(), 'utf8'));
|
|
163
|
+
}
|
|
164
|
+
catch {
|
|
165
|
+
pending = null;
|
|
166
|
+
}
|
|
167
|
+
const valid = !!pending && pending.token === token && pending.expiresAt > Date.now();
|
|
168
|
+
if (!valid) {
|
|
169
|
+
throw new Error('No matching, unexpired confirmation token - run `botanary agent forget` first, then pass the ' +
|
|
170
|
+
'token it prints to `confirm-forget` within 5 minutes.');
|
|
171
|
+
}
|
|
172
|
+
await rm(pendingForgetPath(), { force: true });
|
|
173
|
+
await ctx.runtime.store.forget();
|
|
174
|
+
ctx.runtime.reset();
|
|
175
|
+
console.log(glyphs.success('Deleted the agent key from this machine.'));
|
|
176
|
+
});
|
|
177
|
+
}
|
|
178
|
+
//# sourceMappingURL=agent.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agent.js","sourceRoot":"","sources":["../../../src/commands/agent.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { MCP_SNIPPETS } from '../mcp-snippets.js';
|
|
2
|
+
export function registerMcpCommands(program) {
|
|
3
|
+
const mcp = program.command('mcp').description('Connect a coding agent to Botanary via botanary-mcp');
|
|
4
|
+
mcp
|
|
5
|
+
.command('config [client]')
|
|
6
|
+
.description('Print the install snippet for a client: claude, codex, cursor, claude-desktop')
|
|
7
|
+
.action((client) => {
|
|
8
|
+
if (!client) {
|
|
9
|
+
console.log('Usage: botanary mcp config <claude|codex|cursor|claude-desktop>');
|
|
10
|
+
return;
|
|
11
|
+
}
|
|
12
|
+
const entry = MCP_SNIPPETS[client];
|
|
13
|
+
if (!entry) {
|
|
14
|
+
throw new Error(`Unknown client "${client}". Choose one of: ${Object.keys(MCP_SNIPPETS).join(', ')}.`);
|
|
15
|
+
}
|
|
16
|
+
console.log(`${entry.label}:\n\n${entry.snippet}`);
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
//# sourceMappingURL=mcp.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mcp.js","sourceRoot":"","sources":["../../../src/commands/mcp.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAElD,MAAM,UAAU,mBAAmB,CAAC,OAAgB;IAClD,MAAM,GAAG,GAAG,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,WAAW,CAAC,qDAAqD,CAAC,CAAC;IACtG,GAAG;SACA,OAAO,CAAC,iBAAiB,CAAC;SAC1B,WAAW,CAAC,+EAA+E,CAAC;SAC5F,MAAM,CAAC,CAAC,MAAe,EAAE,EAAE;QAC1B,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,OAAO,CAAC,GAAG,CAAC,iEAAiE,CAAC,CAAC;YAC/E,OAAO;QACT,CAAC;QACD,MAAM,KAAK,GAAG,YAAY,CAAC,MAAM,CAAC,CAAC;QACnC,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,MAAM,IAAI,KAAK,CAAC,mBAAmB,MAAM,qBAAqB,MAAM,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACzG,CAAC;QACD,OAAO,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC,KAAK,QAAQ,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;IACrD,CAAC,CAAC,CAAC;AACP,CAAC"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { runDiagnose, botanaryMcpHome } from 'botanary-mcp';
|
|
2
|
+
import { renderTable } from '../render/table.js';
|
|
3
|
+
import { glyphs } from '../render/colors.js';
|
|
4
|
+
export function registerSystemCommands(program, cliVersion) {
|
|
5
|
+
program
|
|
6
|
+
.command('diagnose')
|
|
7
|
+
.description('START HERE when anything is unclear or an action failed - one call answers what is blocking the next step')
|
|
8
|
+
.action(async () => {
|
|
9
|
+
const ctx = program.opts().__ctx;
|
|
10
|
+
const report = await runDiagnose(ctx.runtime);
|
|
11
|
+
if (ctx.json) {
|
|
12
|
+
console.log(JSON.stringify(report));
|
|
13
|
+
return;
|
|
14
|
+
}
|
|
15
|
+
console.log(report.summary);
|
|
16
|
+
for (const blocker of report.blockers) {
|
|
17
|
+
console.log(blocker.severity === 'blocking' ? glyphs.danger(blocker.detail) : glyphs.warning(blocker.detail));
|
|
18
|
+
console.log(` ${blocker.nextAction}`);
|
|
19
|
+
}
|
|
20
|
+
});
|
|
21
|
+
program
|
|
22
|
+
.command('config')
|
|
23
|
+
.description('Where identity/session live and which env vars are active - unauthenticated, safe')
|
|
24
|
+
.action(() => {
|
|
25
|
+
const ctx = program.opts().__ctx;
|
|
26
|
+
const rows = [
|
|
27
|
+
['home', botanaryMcpHome()],
|
|
28
|
+
['BOTANARY_API_URL', process.env.BOTANARY_API_URL ?? '(not set, defaults to https://api.app.botanary.xyz)'],
|
|
29
|
+
['cli-version', cliVersion],
|
|
30
|
+
];
|
|
31
|
+
if (ctx.json) {
|
|
32
|
+
console.log(JSON.stringify(Object.fromEntries(rows)));
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
console.log(renderTable(rows));
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
//# sourceMappingURL=system.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"system.js","sourceRoot":"","sources":["../../../src/commands/system.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAE5D,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAE7C,MAAM,UAAU,sBAAsB,CAAC,OAAgB,EAAE,UAAkB;IACzE,OAAO;SACJ,OAAO,CAAC,UAAU,CAAC;SACnB,WAAW,CAAC,2GAA2G,CAAC;SACxH,MAAM,CAAC,KAAK,IAAI,EAAE;QACjB,MAAM,GAAG,GAAe,OAAO,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC;QAC7C,MAAM,MAAM,GAAG,MAAM,WAAW,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;QAC9C,IAAI,GAAG,CAAC,IAAI,EAAE,CAAC;YACb,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC;YACpC,OAAO;QACT,CAAC;QACD,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;QAC5B,KAAK,MAAM,OAAO,IAAI,MAAM,CAAC,QAAQ,EAAE,CAAC;YACtC,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,QAAQ,KAAK,UAAU,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC;YAC9G,OAAO,CAAC,GAAG,CAAC,KAAK,OAAO,CAAC,UAAU,EAAE,CAAC,CAAC;QACzC,CAAC;IACH,CAAC,CAAC,CAAC;IAEL,OAAO;SACJ,OAAO,CAAC,QAAQ,CAAC;SACjB,WAAW,CAAC,mFAAmF,CAAC;SAChG,MAAM,CAAC,GAAG,EAAE;QACX,MAAM,GAAG,GAAe,OAAO,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC;QAC7C,MAAM,IAAI,GAAuB;YAC/B,CAAC,MAAM,EAAE,eAAe,EAAE,CAAC;YAC3B,CAAC,kBAAkB,EAAE,OAAO,CAAC,GAAG,CAAC,gBAAgB,IAAI,qDAAqD,CAAC;YAC3G,CAAC,aAAa,EAAE,UAAU,CAAC;SAC5B,CAAC;QACF,IAAI,GAAG,CAAC,IAAI,EAAE,CAAC;YACb,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YACtD,OAAO;QACT,CAAC;QACD,OAAO,CAAC,GAAG,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC;IACjC,CAAC,CAAC,CAAC;AACP,CAAC"}
|
|
@@ -0,0 +1,223 @@
|
|
|
1
|
+
import * as clack from '@clack/prompts';
|
|
2
|
+
import { fetchComposite, walletApiGet, runLogin, openBrowser, portfolioFreshness, walletSend, resolveMandateForSend, signUnderMandateReal, createSignRequestReal, getSignRequestReal, preflightReal, scopedToAccount, } from 'botanary-mcp';
|
|
3
|
+
import { colors, glyphs } from '../render/colors.js';
|
|
4
|
+
import { renderTable } from '../render/table.js';
|
|
5
|
+
import { redactForDisplay } from '../render/redact.js';
|
|
6
|
+
function printResult(ctx, data) {
|
|
7
|
+
if (ctx.json) {
|
|
8
|
+
console.log(JSON.stringify(data));
|
|
9
|
+
}
|
|
10
|
+
else {
|
|
11
|
+
console.log(typeof data === 'string' ? data : JSON.stringify(data, null, 2));
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
/** A WalletSession carries `sessionToken` - redact it in any printed output unless --reveal, the same
|
|
15
|
+
* redact-by-default rule the design spec commits to everywhere. Anything that prints a session (status,
|
|
16
|
+
* accounts use) must route through this rather than printResult directly. */
|
|
17
|
+
function printSessionResult(ctx, data) {
|
|
18
|
+
const session = data?.session ?? data;
|
|
19
|
+
const token = session?.sessionToken;
|
|
20
|
+
printResult(ctx, redactForDisplay(data, token, ctx.reveal));
|
|
21
|
+
}
|
|
22
|
+
async function requireWalletToken(ctx) {
|
|
23
|
+
const session = await ctx.runtime.walletSession();
|
|
24
|
+
if (!session) {
|
|
25
|
+
throw new Error('Not logged in - run `botanary login` first.');
|
|
26
|
+
}
|
|
27
|
+
return session.sessionToken;
|
|
28
|
+
}
|
|
29
|
+
export function registerWalletCommands(program) {
|
|
30
|
+
program
|
|
31
|
+
.command('login')
|
|
32
|
+
.description('Owner session: device-style browser login')
|
|
33
|
+
.action(async () => {
|
|
34
|
+
const ctx = program.opts().__ctx;
|
|
35
|
+
const result = await runLogin({
|
|
36
|
+
api: ctx.runtime.api,
|
|
37
|
+
store: ctx.runtime.walletSessionStore,
|
|
38
|
+
openBrowser,
|
|
39
|
+
now: () => Date.now(),
|
|
40
|
+
sleep: (ms) => new Promise((r) => setTimeout(r, ms)),
|
|
41
|
+
});
|
|
42
|
+
if (result.status === 'authorized') {
|
|
43
|
+
console.log(glyphs.success(`Logged in${result.session ? ` (account ${result.session.accountId ?? 'default'})` : ''}`));
|
|
44
|
+
}
|
|
45
|
+
else {
|
|
46
|
+
console.log(glyphs.danger(`Login ${result.status}`));
|
|
47
|
+
}
|
|
48
|
+
});
|
|
49
|
+
program
|
|
50
|
+
.command('logout')
|
|
51
|
+
.description('Owner session: revoke and clear the stored session')
|
|
52
|
+
.action(async () => {
|
|
53
|
+
const ctx = program.opts().__ctx;
|
|
54
|
+
await ctx.runtime.walletLogout();
|
|
55
|
+
console.log(glyphs.success('Logged out.'));
|
|
56
|
+
});
|
|
57
|
+
program
|
|
58
|
+
.command('status')
|
|
59
|
+
.description('Owner session and this machine\'s agent binding, side by side')
|
|
60
|
+
.action(async () => {
|
|
61
|
+
const ctx = program.opts().__ctx;
|
|
62
|
+
const session = await ctx.runtime.walletSession();
|
|
63
|
+
const hasAgent = await ctx.runtime.store.hasIdentity();
|
|
64
|
+
const rows = [
|
|
65
|
+
['wallet', session ? colors.success(`logged in (account ${session.accountId ?? 'default'})`) : colors.muted('not logged in')],
|
|
66
|
+
['agent', hasAgent ? colors.success('identity present') : colors.muted('not paired')],
|
|
67
|
+
];
|
|
68
|
+
if (ctx.json)
|
|
69
|
+
return printSessionResult(ctx, { session, hasAgent });
|
|
70
|
+
console.log(renderTable(rows));
|
|
71
|
+
});
|
|
72
|
+
program
|
|
73
|
+
.command('balance')
|
|
74
|
+
.description('Owner\'s balances across chains (wallet_portfolio)')
|
|
75
|
+
.action(async () => {
|
|
76
|
+
const ctx = program.opts().__ctx;
|
|
77
|
+
const token = await requireWalletToken(ctx);
|
|
78
|
+
const result = await fetchComposite(ctx.runtime.api, token, [
|
|
79
|
+
{ key: 'balance', path: '/v1/balance' },
|
|
80
|
+
{ key: 'chains', path: '/v1/chains' },
|
|
81
|
+
]);
|
|
82
|
+
const freshness = portfolioFreshness(result.data.balance);
|
|
83
|
+
printResult(ctx, { ...result.data, freshness });
|
|
84
|
+
});
|
|
85
|
+
program
|
|
86
|
+
.command('send')
|
|
87
|
+
.description('Send tokens from the owner\'s own account (lane arbitration decides who signs)')
|
|
88
|
+
.option('--recipient <address>')
|
|
89
|
+
.option('--amount <amount>')
|
|
90
|
+
.option('--token <symbol>')
|
|
91
|
+
.option('--chain-id <chainId>')
|
|
92
|
+
.action(async (opts) => {
|
|
93
|
+
const ctx = program.opts().__ctx;
|
|
94
|
+
let { recipient, amount, token: tokenSymbol, chainId } = opts;
|
|
95
|
+
if (!ctx.noInteractive && (!recipient || !amount || !tokenSymbol || !chainId)) {
|
|
96
|
+
const answers = await clack.group({
|
|
97
|
+
amount: () => clack.text({ message: 'Amount?', placeholder: '25', initialValue: amount }),
|
|
98
|
+
token: () => clack.text({ message: 'Token?', placeholder: 'USDC', initialValue: tokenSymbol }),
|
|
99
|
+
recipient: () => clack.text({ message: 'To?', placeholder: '0xAb12...9F3', initialValue: recipient }),
|
|
100
|
+
chainId: () => clack.text({ message: 'Chain ID?', placeholder: '8453', initialValue: chainId }),
|
|
101
|
+
}, { onCancel: () => { clack.cancel('Cancelled.'); process.exit(0); } });
|
|
102
|
+
({ recipient, amount, token: tokenSymbol, chainId } = answers);
|
|
103
|
+
}
|
|
104
|
+
if (!recipient || !amount || !tokenSymbol || !chainId) {
|
|
105
|
+
throw new Error('Missing required input: --recipient, --amount, --token, --chain-id (or run interactively).');
|
|
106
|
+
}
|
|
107
|
+
const chainIdNum = Number(chainId);
|
|
108
|
+
const input = {
|
|
109
|
+
recipient,
|
|
110
|
+
amount: Number(amount),
|
|
111
|
+
tokenSymbol,
|
|
112
|
+
chainId: chainIdNum,
|
|
113
|
+
chainKey: String(chainIdNum),
|
|
114
|
+
};
|
|
115
|
+
const walletToken = await requireWalletToken(ctx);
|
|
116
|
+
const session = await ctx.runtime.walletSession();
|
|
117
|
+
const mandate = await resolveMandateForSend(ctx.runtime, input);
|
|
118
|
+
const result = await walletSend({
|
|
119
|
+
mandateAccountId: mandate.accountId,
|
|
120
|
+
mandateInBounds: mandate.inBounds,
|
|
121
|
+
mandateBoundsReason: mandate.reason,
|
|
122
|
+
walletAccountId: session?.accountId ?? '',
|
|
123
|
+
signUnderMandate: (i) => signUnderMandateReal(ctx.runtime, mandate.grant, i),
|
|
124
|
+
createSignRequest: createSignRequestReal(ctx.runtime, walletToken),
|
|
125
|
+
getSignRequest: getSignRequestReal(ctx.runtime, walletToken),
|
|
126
|
+
openBrowser,
|
|
127
|
+
now: () => Date.now(),
|
|
128
|
+
sleep: (ms) => new Promise((r) => setTimeout(r, ms)),
|
|
129
|
+
preflight: preflightReal(ctx.runtime, walletToken),
|
|
130
|
+
}, input);
|
|
131
|
+
printResult(ctx, result);
|
|
132
|
+
});
|
|
133
|
+
program
|
|
134
|
+
.command('activity')
|
|
135
|
+
.description('Owner\'s recent sends, swaps, and yield transactions (wallet_activity)')
|
|
136
|
+
.action(async () => {
|
|
137
|
+
const ctx = program.opts().__ctx;
|
|
138
|
+
const token = await requireWalletToken(ctx);
|
|
139
|
+
const session = await ctx.runtime.walletSession();
|
|
140
|
+
const result = await fetchComposite(ctx.runtime.api, token, [
|
|
141
|
+
{ key: 'history', path: scopedToAccount('/v1/history', session?.accountId ?? null) },
|
|
142
|
+
]);
|
|
143
|
+
printResult(ctx, result.data);
|
|
144
|
+
});
|
|
145
|
+
program
|
|
146
|
+
.command('markets')
|
|
147
|
+
.description('Public market data - prices and symbols (wallet_markets)')
|
|
148
|
+
.action(async () => {
|
|
149
|
+
const ctx = program.opts().__ctx;
|
|
150
|
+
const token = await requireWalletToken(ctx);
|
|
151
|
+
const result = await fetchComposite(ctx.runtime.api, token, [{ key: 'tokens', path: '/v1/markets/tokens' }]);
|
|
152
|
+
printResult(ctx, result.data);
|
|
153
|
+
});
|
|
154
|
+
program
|
|
155
|
+
.command('yield')
|
|
156
|
+
.description('Yield pools, a shortlist, and this account\'s farm positions (wallet_yield)')
|
|
157
|
+
.action(async () => {
|
|
158
|
+
const ctx = program.opts().__ctx;
|
|
159
|
+
const token = await requireWalletToken(ctx);
|
|
160
|
+
const session = await ctx.runtime.walletSession();
|
|
161
|
+
const result = await fetchComposite(ctx.runtime.api, token, [
|
|
162
|
+
{ key: 'pools', path: '/v1/yield/pools' },
|
|
163
|
+
{ key: 'shortlist', path: '/v1/yield/shortlist' },
|
|
164
|
+
{ key: 'positions', path: scopedToAccount('/v1/farm/positions', session?.accountId ?? null) },
|
|
165
|
+
]);
|
|
166
|
+
printResult(ctx, {
|
|
167
|
+
...result.data,
|
|
168
|
+
scopeCaveats: 'shortlist is ranked off your own holdings server-side and is not scoped by accounts use.',
|
|
169
|
+
});
|
|
170
|
+
});
|
|
171
|
+
program
|
|
172
|
+
.command('mandates')
|
|
173
|
+
.description(`What the agent lane may spend unattended (wallet_mandates). ${colors.warning('Testnet only, pre-mainnet.')}`)
|
|
174
|
+
.action(async () => {
|
|
175
|
+
const ctx = program.opts().__ctx;
|
|
176
|
+
const token = await requireWalletToken(ctx);
|
|
177
|
+
const session = await ctx.runtime.walletSession();
|
|
178
|
+
const result = await fetchComposite(ctx.runtime.api, token, [
|
|
179
|
+
{ key: 'delegations', path: scopedToAccount('/v1/delegations', session?.accountId ?? null) },
|
|
180
|
+
{ key: 'mandates', path: scopedToAccount('/v1/mandates', session?.accountId ?? null) },
|
|
181
|
+
]);
|
|
182
|
+
if (!ctx.json)
|
|
183
|
+
console.log(glyphs.warning('Mandates are testnet-only and pre-mainnet - nothing here is enforced on mainnet yet.'));
|
|
184
|
+
printResult(ctx, result.data);
|
|
185
|
+
});
|
|
186
|
+
program
|
|
187
|
+
.command('agents')
|
|
188
|
+
.description('Connected agents and any pending approval requests (wallet_agents)')
|
|
189
|
+
.action(async () => {
|
|
190
|
+
const ctx = program.opts().__ctx;
|
|
191
|
+
const token = await requireWalletToken(ctx);
|
|
192
|
+
const session = await ctx.runtime.walletSession();
|
|
193
|
+
const result = await fetchComposite(ctx.runtime.api, token, [
|
|
194
|
+
{ key: 'agents', path: scopedToAccount('/v1/agents', session?.accountId ?? null) },
|
|
195
|
+
{ key: 'requests', path: scopedToAccount('/v1/agents/requests', session?.accountId ?? null) },
|
|
196
|
+
]);
|
|
197
|
+
printResult(ctx, result.data);
|
|
198
|
+
});
|
|
199
|
+
const accounts = program.command('accounts').description('Manage which owner account subsequent commands use');
|
|
200
|
+
accounts
|
|
201
|
+
.command('use <accountId>')
|
|
202
|
+
.description('Switch the active account (wallet_use_account)')
|
|
203
|
+
.action(async (accountId) => {
|
|
204
|
+
const ctx = program.opts().__ctx;
|
|
205
|
+
const token = await requireWalletToken(ctx);
|
|
206
|
+
const list = await ctx.runtime.api.get('/v1/accounts', token);
|
|
207
|
+
if (!Array.isArray(list) || !list.some((a) => a.id === accountId)) {
|
|
208
|
+
throw new Error(`No such account id: ${accountId}`);
|
|
209
|
+
}
|
|
210
|
+
const session = await ctx.runtime.walletSessionStore.switchAccount(accountId);
|
|
211
|
+
printSessionResult(ctx, { session });
|
|
212
|
+
});
|
|
213
|
+
program
|
|
214
|
+
.command('api <path>')
|
|
215
|
+
.description('Read any GET endpoint in the frozen OpenAPI contract, authenticated as the owner (wallet_api_get)')
|
|
216
|
+
.action(async (path) => {
|
|
217
|
+
const ctx = program.opts().__ctx;
|
|
218
|
+
const token = await requireWalletToken(ctx);
|
|
219
|
+
const result = await walletApiGet({ api: ctx.runtime.api, token }, path, 'GET');
|
|
220
|
+
printResult(ctx, result);
|
|
221
|
+
});
|
|
222
|
+
}
|
|
223
|
+
//# sourceMappingURL=wallet.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"wallet.js","sourceRoot":"","sources":["../../../src/commands/wallet.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context.js","sourceRoot":"","sources":["../../src/context.ts"],"names":[],"mappings":"AAmBA,MAAM,UAAU,aAAa,CAAC,OAAqB,EAAE,UAAsB;IACzE,OAAO;QACL,OAAO;QACP,IAAI,EAAE,CAAC,CAAC,UAAU,CAAC,IAAI;QACvB,aAAa,EAAE,UAAU,CAAC,WAAW,KAAK,KAAK;QAC/C,MAAM,EAAE,CAAC,CAAC,UAAU,CAAC,MAAM;KAC5B,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/** Mirrors tools/botanary-mcp/README.md's "Add it to your agent" section. Keep these in sync by hand
|
|
2
|
+
* when that section changes - there is no build-time link between the two READMEs' packages. */
|
|
3
|
+
export const MCP_SNIPPETS = {
|
|
4
|
+
claude: {
|
|
5
|
+
label: 'Claude Code',
|
|
6
|
+
snippet: 'claude mcp add --transport stdio botanary -- npx -y botanary-mcp',
|
|
7
|
+
},
|
|
8
|
+
codex: {
|
|
9
|
+
label: 'Codex',
|
|
10
|
+
snippet: 'codex mcp add botanary -- npx -y botanary-mcp',
|
|
11
|
+
},
|
|
12
|
+
cursor: {
|
|
13
|
+
label: 'Cursor (.cursor/mcp.json)',
|
|
14
|
+
snippet: JSON.stringify({ mcpServers: { botanary: { command: 'npx', args: ['-y', 'botanary-mcp'] } } }, null, 2),
|
|
15
|
+
},
|
|
16
|
+
'claude-desktop': {
|
|
17
|
+
label: 'Claude Desktop (claude_desktop_config.json)',
|
|
18
|
+
snippet: JSON.stringify({ mcpServers: { botanary: { command: 'npx', args: ['-y', 'botanary-mcp'], env: { BOTANARY_API_URL: 'https://api.app.botanary.xyz' } } } }, null, 2),
|
|
19
|
+
},
|
|
20
|
+
};
|
|
21
|
+
//# sourceMappingURL=mcp-snippets.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mcp-snippets.js","sourceRoot":"","sources":["../../src/mcp-snippets.ts"],"names":[],"mappings":"AAAA;iGACiG;AACjG,MAAM,CAAC,MAAM,YAAY,GAAuD;IAC9E,MAAM,EAAE;QACN,KAAK,EAAE,aAAa;QACpB,OAAO,EAAE,kEAAkE;KAC5E;IACD,KAAK,EAAE;QACL,KAAK,EAAE,OAAO;QACd,OAAO,EAAE,+CAA+C;KACzD;IACD,MAAM,EAAE;QACN,KAAK,EAAE,2BAA2B;QAClC,OAAO,EAAE,IAAI,CAAC,SAAS,CACrB,EAAE,UAAU,EAAE,EAAE,QAAQ,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,IAAI,EAAE,cAAc,CAAC,EAAE,EAAE,EAAE,EAC9E,IAAI,EACJ,CAAC,CACF;KACF;IACD,gBAAgB,EAAE;QAChB,KAAK,EAAE,6CAA6C;QACpD,OAAO,EAAE,IAAI,CAAC,SAAS,CACrB,EAAE,UAAU,EAAE,EAAE,QAAQ,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,IAAI,EAAE,cAAc,CAAC,EAAE,GAAG,EAAE,EAAE,gBAAgB,EAAE,8BAA8B,EAAE,EAAE,EAAE,EAAE,EACzI,IAAI,EACJ,CAAC,CACF;KACF;CACF,CAAC"}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { Command } from 'commander';
|
|
2
|
+
import { colors } from './render/colors.js';
|
|
3
|
+
/** Alchemy-style grouped help: commander's default help lists commands flat, so this overrides the
|
|
4
|
+
* formatter to print grouped section headers instead. Groups match the design spec's command table. */
|
|
5
|
+
const GROUPS = [
|
|
6
|
+
{ title: 'Wallet', commands: ['login', 'logout', 'status', 'balance', 'send', 'activity', 'markets', 'yield', 'mandates', 'agents', 'accounts', 'api'] },
|
|
7
|
+
{ title: 'Agent', commands: ['agent'] },
|
|
8
|
+
{ title: 'Connect', commands: ['mcp'] },
|
|
9
|
+
{ title: 'System', commands: ['diagnose', 'config'] },
|
|
10
|
+
];
|
|
11
|
+
export function createProgram() {
|
|
12
|
+
const program = new Command();
|
|
13
|
+
program
|
|
14
|
+
.name('botanary')
|
|
15
|
+
.description('Botanary from your terminal.')
|
|
16
|
+
.option('--json', 'Force JSON output (auto-enabled when piped)')
|
|
17
|
+
.option('--no-interactive', 'Disable prompts and the REPL')
|
|
18
|
+
.option('--no-color', 'Disable color output')
|
|
19
|
+
.option('--reveal', 'Show redacted values in plain text')
|
|
20
|
+
.configureHelp({
|
|
21
|
+
formatHelp: (cmd, helper) => {
|
|
22
|
+
const lines = [];
|
|
23
|
+
lines.push(`${colors.bold('Usage:')} ${helper.commandUsage(cmd)}`);
|
|
24
|
+
lines.push('');
|
|
25
|
+
lines.push(cmd.description());
|
|
26
|
+
lines.push('');
|
|
27
|
+
for (const group of GROUPS) {
|
|
28
|
+
const subcommands = helper
|
|
29
|
+
.visibleCommands(cmd)
|
|
30
|
+
.filter((c) => group.commands.includes(c.name()));
|
|
31
|
+
if (!subcommands.length)
|
|
32
|
+
continue;
|
|
33
|
+
lines.push(colors.brand(colors.bold(`◆ ${group.title}`)));
|
|
34
|
+
for (const sub of subcommands) {
|
|
35
|
+
lines.push(` ${sub.name().padEnd(20)} ${sub.description()}`);
|
|
36
|
+
}
|
|
37
|
+
lines.push('');
|
|
38
|
+
}
|
|
39
|
+
const options = helper.visibleOptions(cmd);
|
|
40
|
+
if (options.length) {
|
|
41
|
+
lines.push(colors.brand(colors.bold('◆ Global options')));
|
|
42
|
+
for (const opt of options) {
|
|
43
|
+
lines.push(` ${helper.optionTerm(opt).padEnd(20)} ${helper.optionDescription(opt)}`);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
return lines.join('\n');
|
|
47
|
+
},
|
|
48
|
+
});
|
|
49
|
+
program.exitOverride();
|
|
50
|
+
return program;
|
|
51
|
+
}
|
|
52
|
+
/** Tokenizes one REPL input line into argv-style tokens, honoring double-quoted substrings so
|
|
53
|
+
* `send 25 usdc to "0xAb12...9F3"`-style input splits the same way a shell would. No escape-sequence
|
|
54
|
+
* handling beyond that - REPL input is a person typing a command name and simple arguments, not a shell
|
|
55
|
+
* script. */
|
|
56
|
+
export function parseLine(line) {
|
|
57
|
+
const tokens = [];
|
|
58
|
+
const re = /"([^"]*)"|(\S+)/g;
|
|
59
|
+
let match;
|
|
60
|
+
while ((match = re.exec(line)) !== null) {
|
|
61
|
+
tokens.push(match[1] !== undefined ? match[1] : match[2]);
|
|
62
|
+
}
|
|
63
|
+
return tokens;
|
|
64
|
+
}
|
|
65
|
+
//# sourceMappingURL=parser.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parser.js","sourceRoot":"","sources":["../../src/parser.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAE5C;wGACwG;AACxG,MAAM,MAAM,GAAiD;IAC3D,EAAE,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAE,CAAC,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,EAAE,UAAU,EAAE,SAAS,EAAE,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,UAAU,EAAE,KAAK,CAAC,EAAE;IACxJ,EAAE,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,CAAC,OAAO,CAAC,EAAE;IACvC,EAAE,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE,CAAC,KAAK,CAAC,EAAE;IACvC,EAAE,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAE,CAAC,UAAU,EAAE,QAAQ,CAAC,EAAE;CACtD,CAAC;AAEF,MAAM,UAAU,aAAa;IAC3B,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC;IAC9B,OAAO;SACJ,IAAI,CAAC,UAAU,CAAC;SAChB,WAAW,CAAC,8BAA8B,CAAC;SAC3C,MAAM,CAAC,QAAQ,EAAE,6CAA6C,CAAC;SAC/D,MAAM,CAAC,kBAAkB,EAAE,8BAA8B,CAAC;SAC1D,MAAM,CAAC,YAAY,EAAE,sBAAsB,CAAC;SAC5C,MAAM,CAAC,UAAU,EAAE,oCAAoC,CAAC;SACxD,aAAa,CAAC;QACb,UAAU,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,EAAE;YAC1B,MAAM,KAAK,GAAa,EAAE,CAAC;YAC3B,KAAK,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,MAAM,CAAC,YAAY,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;YACnE,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YACf,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,WAAW,EAAE,CAAC,CAAC;YAC9B,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YACf,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;gBAC3B,MAAM,WAAW,GAAG,MAAM;qBACvB,eAAe,CAAC,GAAG,CAAC;qBACpB,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;gBACpD,IAAI,CAAC,WAAW,CAAC,MAAM;oBAAE,SAAS;gBAClC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,KAAK,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,CAAC;gBAC1D,KAAK,MAAM,GAAG,IAAI,WAAW,EAAE,CAAC;oBAC9B,KAAK,CAAC,IAAI,CAAC,KAAK,GAAG,CAAC,IAAI,EAAE,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI,GAAG,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC;gBAChE,CAAC;gBACD,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YACjB,CAAC;YACD,MAAM,OAAO,GAAG,MAAM,CAAC,cAAc,CAAC,GAAG,CAAC,CAAC;YAC3C,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;gBACnB,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAC,CAAC,CAAC;gBAC1D,KAAK,MAAM,GAAG,IAAI,OAAO,EAAE,CAAC;oBAC1B,KAAK,CAAC,IAAI,CAAC,KAAK,MAAM,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI,MAAM,CAAC,iBAAiB,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;gBACxF,CAAC;YACH,CAAC;YACD,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC1B,CAAC;KACF,CAAC,CAAC;IACL,OAAO,CAAC,YAAY,EAAE,CAAC;IACvB,OAAO,OAAO,CAAC;AACjB,CAAC;AAED;;;cAGc;AACd,MAAM,UAAU,SAAS,CAAC,IAAY;IACpC,MAAM,MAAM,GAAa,EAAE,CAAC;IAC5B,MAAM,EAAE,GAAG,kBAAkB,CAAC;IAC9B,IAAI,KAA6B,CAAC;IAClC,OAAO,CAAC,KAAK,GAAG,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC;QACxC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;IAC5D,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import figlet from 'figlet';
|
|
2
|
+
import gradient from 'gradient-string';
|
|
3
|
+
import { COSMIC_BANNER_STOPS, isColorEnabled } from './colors.js';
|
|
4
|
+
/** The reserved cosmic-gradient wordmark - shown once, on bare invocation and on --help, never on every
|
|
5
|
+
* line of output (cosmic is a reserved register in the FE too: it earns impact by contrast). Falls back
|
|
6
|
+
* to plain text when color is disabled or the terminal is narrower than the wordmark. The default reads
|
|
7
|
+
* the real current color state from colors.ts rather than hardcoding true, so setColorEnabled(false)
|
|
8
|
+
* (--no-color/NO_COLOR) actually takes effect on a bare renderBanner(text) call. */
|
|
9
|
+
export function renderBanner(text, colorEnabled = isColorEnabled()) {
|
|
10
|
+
const ascii = figlet.textSync(text, { font: 'ANSI Shadow' });
|
|
11
|
+
const widest = Math.max(...ascii.split('\n').map((l) => l.length));
|
|
12
|
+
const columns = process.stdout.columns ?? 80;
|
|
13
|
+
if (!colorEnabled || widest > columns)
|
|
14
|
+
return ascii;
|
|
15
|
+
return gradient(Array.from(COSMIC_BANNER_STOPS)).multiline(ascii);
|
|
16
|
+
}
|
|
17
|
+
//# sourceMappingURL=banner.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"banner.js","sourceRoot":"","sources":["../../../src/render/banner.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,QAAQ,CAAC;AAC5B,OAAO,QAAQ,MAAM,iBAAiB,CAAC;AACvC,OAAO,EAAE,mBAAmB,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAElE;;;;qFAIqF;AACrF,MAAM,UAAU,YAAY,CAAC,IAAY,EAAE,YAAY,GAAG,cAAc,EAAE;IACxE,MAAM,KAAK,GAAG,MAAM,CAAC,QAAQ,CAAC,IAAI,EAAE,EAAE,IAAI,EAAE,aAAa,EAAE,CAAC,CAAC;IAC7D,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC;IACnE,MAAM,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC,OAAO,IAAI,EAAE,CAAC;IAC7C,IAAI,CAAC,YAAY,IAAI,MAAM,GAAG,OAAO;QAAE,OAAO,KAAK,CAAC;IACpD,OAAO,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,mBAAmB,CAAC,CAAC,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;AACpE,CAAC"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import pc from 'picocolors';
|
|
2
|
+
// Botanary's real design tokens, not invented here:
|
|
3
|
+
// botanary-fe/src/ui/styles/tokens/gradients.css -> --gradient-cosmic
|
|
4
|
+
// botanary-fe/src/ui/styles/tokens/dark.css -> [data-theme="dark"]
|
|
5
|
+
// Cosmic is reserved for the banner moment only (see banner.ts). Everyday status output uses the
|
|
6
|
+
// dark-theme's charcoal-tuned semantic colors. Brand rule: never purple.
|
|
7
|
+
export const COSMIC_BANNER_STOPS = ['#0f7a5a', '#1fbfa0', '#b1f0bb'];
|
|
8
|
+
const DARK_TOKENS = {
|
|
9
|
+
brand: '#7cbf95',
|
|
10
|
+
brandStrong: '#a6dcb8',
|
|
11
|
+
success: '#7cbf95',
|
|
12
|
+
warning: '#e6ac52',
|
|
13
|
+
danger: '#e8695f',
|
|
14
|
+
info: '#7fe0cf',
|
|
15
|
+
muted: '#6f7f74',
|
|
16
|
+
};
|
|
17
|
+
let colorEnabled = pc.isColorSupported;
|
|
18
|
+
/** Called once from cli.ts when --no-color is passed or NO_COLOR is set, overriding auto-detection. */
|
|
19
|
+
export function setColorEnabled(enabled) {
|
|
20
|
+
colorEnabled = enabled;
|
|
21
|
+
}
|
|
22
|
+
export function isColorEnabled() {
|
|
23
|
+
return colorEnabled;
|
|
24
|
+
}
|
|
25
|
+
function hex(hexColor, text) {
|
|
26
|
+
if (!colorEnabled)
|
|
27
|
+
return text;
|
|
28
|
+
const r = parseInt(hexColor.slice(1, 3), 16);
|
|
29
|
+
const g = parseInt(hexColor.slice(3, 5), 16);
|
|
30
|
+
const b = parseInt(hexColor.slice(5, 7), 16);
|
|
31
|
+
return `\x1b[38;2;${r};${g};${b}m${text}\x1b[39m`;
|
|
32
|
+
}
|
|
33
|
+
export const colors = {
|
|
34
|
+
brand: (s) => hex(DARK_TOKENS.brand, s),
|
|
35
|
+
brandStrong: (s) => hex(DARK_TOKENS.brandStrong, s),
|
|
36
|
+
success: (s) => hex(DARK_TOKENS.success, s),
|
|
37
|
+
warning: (s) => hex(DARK_TOKENS.warning, s),
|
|
38
|
+
danger: (s) => hex(DARK_TOKENS.danger, s),
|
|
39
|
+
info: (s) => hex(DARK_TOKENS.info, s),
|
|
40
|
+
muted: (s) => hex(DARK_TOKENS.muted, s),
|
|
41
|
+
bold: (s) => (colorEnabled ? pc.bold(s) : s),
|
|
42
|
+
dim: (s) => (colorEnabled ? pc.dim(s) : s),
|
|
43
|
+
};
|
|
44
|
+
export const glyphs = {
|
|
45
|
+
success: (s) => `${colors.success('✔')} ${s}`,
|
|
46
|
+
warning: (s) => `${colors.warning('⚠')} ${s}`,
|
|
47
|
+
danger: (s) => `${colors.danger('✖')} ${s}`,
|
|
48
|
+
info: (s) => `${colors.info('ℹ')} ${s}`,
|
|
49
|
+
};
|
|
50
|
+
//# sourceMappingURL=colors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"colors.js","sourceRoot":"","sources":["../../../src/render/colors.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/** --json forces it on. Otherwise: a non-TTY stdout (piped, redirected, or run from another program)
|
|
2
|
+
* auto-enables it, matching the Alchemy CLI reference exactly. --no-interactive alone does NOT force
|
|
3
|
+
* JSON - it only disables prompts; a human running --no-interactive in a real terminal still wants
|
|
4
|
+
* human-readable output unless they also asked for --json or piped it. */
|
|
5
|
+
export function isJsonMode(opts, stdout = process.stdout) {
|
|
6
|
+
if (opts.json)
|
|
7
|
+
return true;
|
|
8
|
+
return !stdout.isTTY;
|
|
9
|
+
}
|
|
10
|
+
//# sourceMappingURL=json-mode.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"json-mode.js","sourceRoot":"","sources":["../../../src/render/json-mode.ts"],"names":[],"mappings":"AAKA;;;2EAG2E;AAC3E,MAAM,UAAU,UAAU,CAAC,IAAkB,EAAE,SAA8B,OAAO,CAAC,MAAM;IACzF,IAAI,IAAI,CAAC,IAAI;QAAE,OAAO,IAAI,CAAC;IAC3B,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC;AACvB,CAAC"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { redactUnknown } from 'botanary-mcp';
|
|
2
|
+
/** Wraps botanary-mcp's own redactUnknown: masks `secret` wherever it appears inside `value` unless
|
|
3
|
+
* `reveal` is true. redactUnknown always returns a STRING (it's built for safe-to-log text), so for
|
|
4
|
+
* any non-string value this round-trips through JSON to redact the secret in place while preserving
|
|
5
|
+
* the value's shape - critical for --json mode, where the caller wants a redacted clone, not a
|
|
6
|
+
* flattened "[object Object]". Falls back to the flattened form only if the value can't round-trip
|
|
7
|
+
* through JSON (e.g. contains a function or a circular reference) - still safe (the secret is still
|
|
8
|
+
* masked), just loses shape in that edge case. */
|
|
9
|
+
export function redactForDisplay(value, secret, reveal) {
|
|
10
|
+
if (reveal || !secret)
|
|
11
|
+
return value;
|
|
12
|
+
if (typeof value === 'string')
|
|
13
|
+
return redactUnknown(value, secret);
|
|
14
|
+
try {
|
|
15
|
+
const serialized = JSON.stringify(value);
|
|
16
|
+
const masked = redactUnknown(serialized, secret);
|
|
17
|
+
return JSON.parse(masked);
|
|
18
|
+
}
|
|
19
|
+
catch {
|
|
20
|
+
return redactUnknown(value, secret);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
//# sourceMappingURL=redact.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"redact.js","sourceRoot":"","sources":["../../../src/render/redact.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAE7C;;;;;;mDAMmD;AACnD,MAAM,UAAU,gBAAgB,CAAC,KAAc,EAAE,MAAiC,EAAE,MAAe;IACjG,IAAI,MAAM,IAAI,CAAC,MAAM;QAAE,OAAO,KAAK,CAAC;IACpC,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,OAAO,aAAa,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;IACnE,IAAI,CAAC;QACH,MAAM,UAAU,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;QACzC,MAAM,MAAM,GAAG,aAAa,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC;QACjD,OAAO,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;IAC5B,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,aAAa,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;IACtC,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import Table from 'cli-table3';
|
|
2
|
+
/** Borderless aligned two-column table (the `config list` reference look) - not a bordered grid. */
|
|
3
|
+
export function renderTable(rows) {
|
|
4
|
+
const table = new Table({
|
|
5
|
+
chars: {
|
|
6
|
+
top: '', 'top-mid': '', 'top-left': '', 'top-right': '',
|
|
7
|
+
bottom: '', 'bottom-mid': '', 'bottom-left': '', 'bottom-right': '',
|
|
8
|
+
left: '', 'left-mid': '', mid: '', 'mid-mid': '',
|
|
9
|
+
right: '', 'right-mid': '', middle: ' ',
|
|
10
|
+
},
|
|
11
|
+
style: { 'padding-left': 0, 'padding-right': 4, border: [], head: [] },
|
|
12
|
+
});
|
|
13
|
+
table.push(...rows);
|
|
14
|
+
return table.toString();
|
|
15
|
+
}
|
|
16
|
+
//# sourceMappingURL=table.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"table.js","sourceRoot":"","sources":["../../../src/render/table.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,YAAY,CAAC;AAE/B,oGAAoG;AACpG,MAAM,UAAU,WAAW,CAAC,IAAwB;IAClD,MAAM,KAAK,GAAG,IAAI,KAAK,CAAC;QACtB,KAAK,EAAE;YACL,GAAG,EAAE,EAAE,EAAE,SAAS,EAAE,EAAE,EAAE,UAAU,EAAE,EAAE,EAAE,WAAW,EAAE,EAAE;YACvD,MAAM,EAAE,EAAE,EAAE,YAAY,EAAE,EAAE,EAAE,aAAa,EAAE,EAAE,EAAE,cAAc,EAAE,EAAE;YACnE,IAAI,EAAE,EAAE,EAAE,UAAU,EAAE,EAAE,EAAE,GAAG,EAAE,EAAE,EAAE,SAAS,EAAE,EAAE;YAChD,KAAK,EAAE,EAAE,EAAE,WAAW,EAAE,EAAE,EAAE,MAAM,EAAE,GAAG;SACxC;QACD,KAAK,EAAE,EAAE,cAAc,EAAE,CAAC,EAAE,eAAe,EAAE,CAAC,EAAE,MAAM,EAAE,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE;KACvE,CAAC,CAAC;IACH,KAAK,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,CAAC;IACpB,OAAO,KAAK,CAAC,QAAQ,EAAE,CAAC;AAC1B,CAAC"}
|
package/dist/src/repl.js
ADDED
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
import readline from 'node:readline';
|
|
2
|
+
import { CommanderError } from 'commander';
|
|
3
|
+
import { parseLine } from './parser.js';
|
|
4
|
+
import { renderBanner } from './render/banner.js';
|
|
5
|
+
import { colors } from './render/colors.js';
|
|
6
|
+
const COMMAND_NAMES = ['login', 'logout', 'status', 'balance', 'send', 'activity', 'markets', 'yield', 'mandates', 'agents', 'accounts', 'api', 'agent', 'mcp', 'diagnose', 'config', 'help', 'exit', 'quit'];
|
|
7
|
+
/** A dispatched command (e.g. `send`, `agent spend`) may itself build an interactive prompt via
|
|
8
|
+
* @clack/prompts, which creates its OWN readline interface on this same process.stdin. Verified live:
|
|
9
|
+
* two readline interfaces alive on one stdin at once is not just cosmetically risky - the REPL's own
|
|
10
|
+
* keypress listener stays attached and independently reinterprets the user's prompt answers as REPL
|
|
11
|
+
* command lines (e.g. typing "25" into a clack prompt also dispatches a stray "25" command), and
|
|
12
|
+
* closing the inner (clack) interface pauses the shared stdin stream as a side effect, which starves
|
|
13
|
+
* the REPL's still-open outer interface of further input with no way to recover (confirmed: it never
|
|
14
|
+
* sees a subsequent line again, including "exit"). The fix is to never let two interfaces be alive at
|
|
15
|
+
* once: close this interface before dispatching, then build a fresh one once the command settles. */
|
|
16
|
+
function createReplInterface() {
|
|
17
|
+
return readline.createInterface({
|
|
18
|
+
input: process.stdin,
|
|
19
|
+
output: process.stdout,
|
|
20
|
+
prompt: colors.brand('> '),
|
|
21
|
+
completer: (line) => {
|
|
22
|
+
const hits = COMMAND_NAMES.filter((c) => c.startsWith(line));
|
|
23
|
+
return [hits.length ? hits : COMMAND_NAMES, line];
|
|
24
|
+
},
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
export async function runRepl(program, state) {
|
|
28
|
+
console.log(renderBanner('BOTANARY'));
|
|
29
|
+
console.log(`${colors.brand('◆')} ${colors.bold('Welcome to Botanary')}`);
|
|
30
|
+
console.log(state.loggedIn ? `${colors.success('✔')} Logged in` : `${colors.muted('not logged in')} - try \`login\``);
|
|
31
|
+
console.log(colors.dim("Run commands directly (no 'botanary' prefix).\n"));
|
|
32
|
+
console.log(`${colors.brand('◆')} ${colors.bold('Quick commands')}`);
|
|
33
|
+
const quick = state.loggedIn ? ['balance', 'send', 'status'] : ['login', 'agent pair'];
|
|
34
|
+
for (const q of quick)
|
|
35
|
+
console.log(colors.dim(` - ${q}`));
|
|
36
|
+
console.log(colors.dim("\nPress TAB for autocomplete. Type 'exit' or 'quit' to leave.\n"));
|
|
37
|
+
await new Promise((resolve) => {
|
|
38
|
+
// The REPL's readline interface gets closed and rebuilt around every dispatched command (see
|
|
39
|
+
// createReplInterface's doc comment), so a *lot* more 'close' events fire than just "the user is
|
|
40
|
+
// leaving" - and a burst of already-buffered lines (a paste, or piped/non-interactive input) can
|
|
41
|
+
// land multiple 'line' events on ONE interface generation before its first line has even been
|
|
42
|
+
// dispatched, so a per-line closure can't just capture "the interface" once and trust it's still
|
|
43
|
+
// current by the time its turn in the queue comes up. `current` always points at whichever
|
|
44
|
+
// interface generation is live right now; every action below goes through it (never through a
|
|
45
|
+
// closure-captured reference) for exactly that reason.
|
|
46
|
+
let current;
|
|
47
|
+
let queue = Promise.resolve();
|
|
48
|
+
let finished = false;
|
|
49
|
+
// True only for the span between closing the current interface to dispatch a command and that
|
|
50
|
+
// command settling - distinguishes "we closed this ourselves, a fresh one is coming" from a real
|
|
51
|
+
// close (exit/quit, or the input stream ending on its own), which the close handler below uses to
|
|
52
|
+
// decide whether this close is news at all.
|
|
53
|
+
let closingForDispatch = false;
|
|
54
|
+
const finish = () => {
|
|
55
|
+
if (finished)
|
|
56
|
+
return;
|
|
57
|
+
finished = true;
|
|
58
|
+
console.log(colors.dim('\nbye.'));
|
|
59
|
+
resolve();
|
|
60
|
+
};
|
|
61
|
+
const attach = (iface) => {
|
|
62
|
+
current = iface;
|
|
63
|
+
iface.on('line', (line) => {
|
|
64
|
+
queue = queue.then(async () => {
|
|
65
|
+
if (finished)
|
|
66
|
+
return;
|
|
67
|
+
const trimmed = line.trim();
|
|
68
|
+
if (trimmed === 'exit' || trimmed === 'quit') {
|
|
69
|
+
current.close();
|
|
70
|
+
finish();
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
if (trimmed) {
|
|
74
|
+
// A dispatched command may itself open an interactive prompt (e.g. `send`/`agent spend`
|
|
75
|
+
// use @clack/prompts, which builds its OWN readline interface on this same process.stdin).
|
|
76
|
+
// Two live readline interfaces on one stdin fight over raw-mode/keypress state - closing
|
|
77
|
+
// this one first (and building a fresh one once the command settles) keeps exactly one
|
|
78
|
+
// interface alive at a time, never two.
|
|
79
|
+
closingForDispatch = true;
|
|
80
|
+
current.close();
|
|
81
|
+
try {
|
|
82
|
+
await program.parseAsync(parseLine(trimmed), { from: 'user' });
|
|
83
|
+
}
|
|
84
|
+
catch (e) {
|
|
85
|
+
if (e instanceof CommanderError) {
|
|
86
|
+
if (e.exitCode !== 0) {
|
|
87
|
+
console.log(colors.danger(e.message));
|
|
88
|
+
}
|
|
89
|
+
// exitCode === 0 means a successful help/version display (commander already printed it) -
|
|
90
|
+
// nothing more to report, just continue the loop.
|
|
91
|
+
}
|
|
92
|
+
else {
|
|
93
|
+
console.log(colors.danger(e instanceof Error ? e.message : String(e)));
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
finally {
|
|
97
|
+
closingForDispatch = false;
|
|
98
|
+
if (!finished) {
|
|
99
|
+
attach(createReplInterface());
|
|
100
|
+
current.prompt();
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
105
|
+
current.prompt();
|
|
106
|
+
});
|
|
107
|
+
});
|
|
108
|
+
iface.on('close', () => {
|
|
109
|
+
if (closingForDispatch)
|
|
110
|
+
return;
|
|
111
|
+
// Not our own transient close: either the exit/quit branch closed it (finish() already ran
|
|
112
|
+
// directly, so this is a no-op below) or the input stream ended on its own (piped/non-interactive
|
|
113
|
+
// stdin ran dry without the user ever typing exit/quit). Either way, defer the "are we actually
|
|
114
|
+
// done" check to the back of the queue rather than deciding right here - this can fire before an
|
|
115
|
+
// already-queued line (possibly the real exit/quit line) has had a chance to run, since a burst of
|
|
116
|
+
// buffered input can hit EOF in the same tick it delivers its last line.
|
|
117
|
+
queue = queue.then(() => {
|
|
118
|
+
if (!finished)
|
|
119
|
+
finish();
|
|
120
|
+
});
|
|
121
|
+
});
|
|
122
|
+
};
|
|
123
|
+
attach(createReplInterface());
|
|
124
|
+
// attach() assigns `current` synchronously before returning.
|
|
125
|
+
current.prompt();
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
//# sourceMappingURL=repl.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"repl.js","sourceRoot":"","sources":["../../src/repl.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "botanary",
|
|
3
|
+
"type": "module",
|
|
4
|
+
"version": "0.1.0",
|
|
5
|
+
"description": "Botanary from your terminal - a guided CLI over the same wallet and agent lanes botanary-mcp exposes to a coding agent.",
|
|
6
|
+
"license": "UNLICENSED",
|
|
7
|
+
"homepage": "https://docs.botanary.xyz",
|
|
8
|
+
"keywords": ["botanary", "cli", "wallet"],
|
|
9
|
+
"bin": {
|
|
10
|
+
"botanary": "dist/bin/botanary.js"
|
|
11
|
+
},
|
|
12
|
+
"files": ["dist", "README.md"],
|
|
13
|
+
"engines": {
|
|
14
|
+
"node": ">=22.0.0"
|
|
15
|
+
},
|
|
16
|
+
"scripts": {
|
|
17
|
+
"build": "tsc -p tsconfig.build.json",
|
|
18
|
+
"prepare": "tsc -p tsconfig.build.json",
|
|
19
|
+
"dev": "node --watch -r @swc-node/register bin/botanary.ts",
|
|
20
|
+
"start": "node dist/bin/botanary.js",
|
|
21
|
+
"typecheck": "tsc -p tsconfig.json --noEmit",
|
|
22
|
+
"test": "vitest run",
|
|
23
|
+
"test:watch": "vitest"
|
|
24
|
+
},
|
|
25
|
+
"dependencies": {
|
|
26
|
+
"botanary-mcp": "^0.5.0",
|
|
27
|
+
"commander": "^13.1.0",
|
|
28
|
+
"@clack/prompts": "^0.9.1",
|
|
29
|
+
"picocolors": "^1.1.1",
|
|
30
|
+
"gradient-string": "^3.0.0",
|
|
31
|
+
"figlet": "^1.7.0",
|
|
32
|
+
"cli-table3": "^0.6.5"
|
|
33
|
+
},
|
|
34
|
+
"devDependencies": {
|
|
35
|
+
"@swc-node/register": "^1.10.9",
|
|
36
|
+
"@types/figlet": "^1.7.0",
|
|
37
|
+
"@types/node": "^22.10.5",
|
|
38
|
+
"typescript": "^5.7.3",
|
|
39
|
+
"vitest": "^2.1.8"
|
|
40
|
+
}
|
|
41
|
+
}
|