@tabai/sdk 0.2.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/LICENSE +23 -0
- package/README.md +401 -0
- package/bin/tab.mjs +23 -0
- package/dist/_shared/abi.d.ts +150 -0
- package/dist/_shared/abi.d.ts.map +1 -0
- package/dist/_shared/abi.js +197 -0
- package/dist/_shared/abi.js.map +1 -0
- package/dist/_shared/chains.d.ts +118 -0
- package/dist/_shared/chains.d.ts.map +1 -0
- package/dist/_shared/chains.js +89 -0
- package/dist/_shared/chains.js.map +1 -0
- package/dist/_shared/hex.d.ts +35 -0
- package/dist/_shared/hex.d.ts.map +1 -0
- package/dist/_shared/hex.js +40 -0
- package/dist/_shared/hex.js.map +1 -0
- package/dist/_shared/index.d.ts +14 -0
- package/dist/_shared/index.d.ts.map +1 -0
- package/dist/_shared/index.js +14 -0
- package/dist/_shared/index.js.map +1 -0
- package/dist/_shared/keccak256.d.ts +29 -0
- package/dist/_shared/keccak256.d.ts.map +1 -0
- package/dist/_shared/keccak256.js +145 -0
- package/dist/_shared/keccak256.js.map +1 -0
- package/dist/_shared/result.d.ts +78 -0
- package/dist/_shared/result.d.ts.map +1 -0
- package/dist/_shared/result.js +61 -0
- package/dist/_shared/result.js.map +1 -0
- package/dist/cli/client-config.d.ts +155 -0
- package/dist/cli/client-config.d.ts.map +1 -0
- package/dist/cli/client-config.js +382 -0
- package/dist/cli/client-config.js.map +1 -0
- package/dist/cli/connect.d.ts +76 -0
- package/dist/cli/connect.d.ts.map +1 -0
- package/dist/cli/connect.js +158 -0
- package/dist/cli/connect.js.map +1 -0
- package/dist/cli/doctor.d.ts +57 -0
- package/dist/cli/doctor.d.ts.map +1 -0
- package/dist/cli/doctor.js +253 -0
- package/dist/cli/doctor.js.map +1 -0
- package/dist/cli/index.d.ts +13 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +13 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/main.d.ts +45 -0
- package/dist/cli/main.d.ts.map +1 -0
- package/dist/cli/main.js +371 -0
- package/dist/cli/main.js.map +1 -0
- package/dist/errors.d.ts +29 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +37 -0
- package/dist/errors.js.map +1 -0
- package/dist/http/client-402.d.ts +243 -0
- package/dist/http/client-402.d.ts.map +1 -0
- package/dist/http/client-402.js +515 -0
- package/dist/http/client-402.js.map +1 -0
- package/dist/http/headers.d.ts +173 -0
- package/dist/http/headers.d.ts.map +1 -0
- package/dist/http/headers.js +284 -0
- package/dist/http/headers.js.map +1 -0
- package/dist/http/index.d.ts +15 -0
- package/dist/http/index.d.ts.map +1 -0
- package/dist/http/index.js +15 -0
- package/dist/http/index.js.map +1 -0
- package/dist/http/metering-claim.d.ts +82 -0
- package/dist/http/metering-claim.d.ts.map +1 -0
- package/dist/http/metering-claim.js +99 -0
- package/dist/http/metering-claim.js.map +1 -0
- package/dist/index.d.ts +48 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +51 -0
- package/dist/index.js.map +1 -0
- package/dist/logger.d.ts +40 -0
- package/dist/logger.d.ts.map +1 -0
- package/dist/logger.js +50 -0
- package/dist/logger.js.map +1 -0
- package/dist/mcp/assets.d.ts +31 -0
- package/dist/mcp/assets.d.ts.map +1 -0
- package/dist/mcp/assets.js +78 -0
- package/dist/mcp/assets.js.map +1 -0
- package/dist/mcp/index.d.ts +19 -0
- package/dist/mcp/index.d.ts.map +1 -0
- package/dist/mcp/index.js +19 -0
- package/dist/mcp/index.js.map +1 -0
- package/dist/mcp/json-schema.d.ts +86 -0
- package/dist/mcp/json-schema.d.ts.map +1 -0
- package/dist/mcp/json-schema.js +215 -0
- package/dist/mcp/json-schema.js.map +1 -0
- package/dist/mcp/json.d.ts +43 -0
- package/dist/mcp/json.d.ts.map +1 -0
- package/dist/mcp/json.js +69 -0
- package/dist/mcp/json.js.map +1 -0
- package/dist/mcp/registry-client.d.ts +88 -0
- package/dist/mcp/registry-client.d.ts.map +1 -0
- package/dist/mcp/registry-client.js +158 -0
- package/dist/mcp/registry-client.js.map +1 -0
- package/dist/mcp/schemas.d.ts +82 -0
- package/dist/mcp/schemas.d.ts.map +1 -0
- package/dist/mcp/schemas.js +493 -0
- package/dist/mcp/schemas.js.map +1 -0
- package/dist/mcp/server.d.ts +97 -0
- package/dist/mcp/server.d.ts.map +1 -0
- package/dist/mcp/server.js +285 -0
- package/dist/mcp/server.js.map +1 -0
- package/dist/mcp/settings.d.ts +90 -0
- package/dist/mcp/settings.d.ts.map +1 -0
- package/dist/mcp/settings.js +160 -0
- package/dist/mcp/settings.js.map +1 -0
- package/dist/mcp/toolset.d.ts +231 -0
- package/dist/mcp/toolset.d.ts.map +1 -0
- package/dist/mcp/toolset.js +760 -0
- package/dist/mcp/toolset.js.map +1 -0
- package/dist/payments/abi.d.ts +9 -0
- package/dist/payments/abi.d.ts.map +1 -0
- package/dist/payments/abi.js +17 -0
- package/dist/payments/abi.js.map +1 -0
- package/dist/payments/config.d.ts +199 -0
- package/dist/payments/config.d.ts.map +1 -0
- package/dist/payments/config.js +259 -0
- package/dist/payments/config.js.map +1 -0
- package/dist/payments/index.d.ts +13 -0
- package/dist/payments/index.d.ts.map +1 -0
- package/dist/payments/index.js +13 -0
- package/dist/payments/index.js.map +1 -0
- package/dist/payments/kuru.d.ts +191 -0
- package/dist/payments/kuru.d.ts.map +1 -0
- package/dist/payments/kuru.js +377 -0
- package/dist/payments/kuru.js.map +1 -0
- package/dist/payments/monad.d.ts +69 -0
- package/dist/payments/monad.d.ts.map +1 -0
- package/dist/payments/monad.js +306 -0
- package/dist/payments/monad.js.map +1 -0
- package/dist/payments/permit2.d.ts +118 -0
- package/dist/payments/permit2.d.ts.map +1 -0
- package/dist/payments/permit2.js +366 -0
- package/dist/payments/permit2.js.map +1 -0
- package/dist/payments/registry.d.ts +119 -0
- package/dist/payments/registry.d.ts.map +1 -0
- package/dist/payments/registry.js +199 -0
- package/dist/payments/registry.js.map +1 -0
- package/dist/payments/strategy.d.ts +80 -0
- package/dist/payments/strategy.d.ts.map +1 -0
- package/dist/payments/strategy.js +103 -0
- package/dist/payments/strategy.js.map +1 -0
- package/dist/proxy/hooks.d.ts +90 -0
- package/dist/proxy/hooks.d.ts.map +1 -0
- package/dist/proxy/hooks.js +35 -0
- package/dist/proxy/hooks.js.map +1 -0
- package/dist/proxy/index.d.ts +9 -0
- package/dist/proxy/index.d.ts.map +1 -0
- package/dist/proxy/index.js +9 -0
- package/dist/proxy/index.js.map +1 -0
- package/dist/proxy/proxy.d.ts +156 -0
- package/dist/proxy/proxy.d.ts.map +1 -0
- package/dist/proxy/proxy.js +366 -0
- package/dist/proxy/proxy.js.map +1 -0
- package/dist/server/adapters/express.d.ts +89 -0
- package/dist/server/adapters/express.d.ts.map +1 -0
- package/dist/server/adapters/express.js +215 -0
- package/dist/server/adapters/express.js.map +1 -0
- package/dist/server/adapters/hono.d.ts +52 -0
- package/dist/server/adapters/hono.d.ts.map +1 -0
- package/dist/server/adapters/hono.js +61 -0
- package/dist/server/adapters/hono.js.map +1 -0
- package/dist/server/adapters/next.d.ts +52 -0
- package/dist/server/adapters/next.d.ts.map +1 -0
- package/dist/server/adapters/next.js +56 -0
- package/dist/server/adapters/next.js.map +1 -0
- package/dist/server/index.d.ts +30 -0
- package/dist/server/index.d.ts.map +1 -0
- package/dist/server/index.js +30 -0
- package/dist/server/index.js.map +1 -0
- package/dist/server/metering.d.ts +209 -0
- package/dist/server/metering.d.ts.map +1 -0
- package/dist/server/metering.js +365 -0
- package/dist/server/metering.js.map +1 -0
- package/dist/server/post-paid.d.ts +355 -0
- package/dist/server/post-paid.d.ts.map +1 -0
- package/dist/server/post-paid.js +512 -0
- package/dist/server/post-paid.js.map +1 -0
- package/dist/x402/client.d.ts +203 -0
- package/dist/x402/client.d.ts.map +1 -0
- package/dist/x402/client.js +337 -0
- package/dist/x402/client.js.map +1 -0
- package/dist/x402/hub.d.ts +79 -0
- package/dist/x402/hub.d.ts.map +1 -0
- package/dist/x402/hub.js +164 -0
- package/dist/x402/hub.js.map +1 -0
- package/dist/x402/index.d.ts +27 -0
- package/dist/x402/index.d.ts.map +1 -0
- package/dist/x402/index.js +27 -0
- package/dist/x402/index.js.map +1 -0
- package/dist/x402/proxy.d.ts +162 -0
- package/dist/x402/proxy.d.ts.map +1 -0
- package/dist/x402/proxy.js +198 -0
- package/dist/x402/proxy.js.map +1 -0
- package/dist/x402/server.d.ts +162 -0
- package/dist/x402/server.d.ts.map +1 -0
- package/dist/x402/server.js +306 -0
- package/dist/x402/server.js.map +1 -0
- package/dist/x402/wire.d.ts +104 -0
- package/dist/x402/wire.d.ts.map +1 -0
- package/dist/x402/wire.js +265 -0
- package/dist/x402/wire.js.map +1 -0
- package/package.json +61 -0
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `tab`: the executable entry point of this package.
|
|
3
|
+
*
|
|
4
|
+
* Five commands. `mcp` serves the four tools, and is what the `mcpServers`
|
|
5
|
+
* stanza launches. `connect` writes that stanza. `doctor` checks the whole
|
|
6
|
+
* installation without a key. `status` and `settle` are the two tools a person
|
|
7
|
+
* reaches for outside a model, one to see what is owed and one to pay it.
|
|
8
|
+
*
|
|
9
|
+
* ## stdout belongs to the protocol
|
|
10
|
+
*
|
|
11
|
+
* Under `mcp` the process speaks MCP over stdout, so this file writes every
|
|
12
|
+
* human-readable line to stderr and every machine-readable payload to stdout,
|
|
13
|
+
* and the two never mix. `--json` on `status`, `settle` and `doctor` puts a
|
|
14
|
+
* single JSON document on stdout and nothing else, which is what makes the
|
|
15
|
+
* commands scriptable.
|
|
16
|
+
*
|
|
17
|
+
* ## `settle` does not broadcast unless it is told to
|
|
18
|
+
*
|
|
19
|
+
* A Settlement spends real funds, and a command that spends by default is a
|
|
20
|
+
* command somebody runs to see what it does. So `tab settle` is a dry run unless
|
|
21
|
+
* `--broadcast` is passed: it resolves the strategy, the Collection Address and
|
|
22
|
+
* the surface, reports exactly what would be sent, and sends nothing. The MCP
|
|
23
|
+
* tool has the same `dryRun` field for the same reason, defaulted the other way
|
|
24
|
+
* because a model calling `tab_settle` has already decided.
|
|
25
|
+
*
|
|
26
|
+
* Requirements: 25.5, 25.6
|
|
27
|
+
*/
|
|
28
|
+
/** The name the help text uses. `npx @tabai/sdk` resolves to this. */
|
|
29
|
+
export declare const CLI_NAME = "tab";
|
|
30
|
+
export interface CliIo {
|
|
31
|
+
/** Machine-readable output. Under `mcp` this is the protocol stream and nothing else writes to it. */
|
|
32
|
+
out(line: string): void;
|
|
33
|
+
/** Everything a person reads. */
|
|
34
|
+
err(line: string): void;
|
|
35
|
+
}
|
|
36
|
+
export interface CliOptions {
|
|
37
|
+
readonly io?: CliIo;
|
|
38
|
+
readonly env?: NodeJS.ProcessEnv;
|
|
39
|
+
readonly cwd?: string;
|
|
40
|
+
/** Blocks the two commands that would spend, so a test can never broadcast. */
|
|
41
|
+
readonly allowBroadcast?: boolean;
|
|
42
|
+
}
|
|
43
|
+
/** Runs one invocation and answers a process exit code. Never throws. */
|
|
44
|
+
export declare function runCli(argv: readonly string[], options?: CliOptions): Promise<number>;
|
|
45
|
+
//# sourceMappingURL=main.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"main.d.ts","sourceRoot":"","sources":["../../src/cli/main.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAYH,sEAAsE;AACtE,eAAO,MAAM,QAAQ,QAAQ,CAAC;AAE9B,MAAM,WAAW,KAAK;IACpB,sGAAsG;IACtG,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,iCAAiC;IACjC,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;CACzB;AAOD,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,EAAE,CAAC,EAAE,KAAK,CAAC;IACpB,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;IACjC,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC;IACtB,+EAA+E;IAC/E,QAAQ,CAAC,cAAc,CAAC,EAAE,OAAO,CAAC;CACnC;AA0UD,yEAAyE;AACzE,wBAAsB,MAAM,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,EAAE,OAAO,GAAE,UAAe,GAAG,OAAO,CAAC,MAAM,CAAC,CAyC/F"}
|
package/dist/cli/main.js
ADDED
|
@@ -0,0 +1,371 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `tab`: the executable entry point of this package.
|
|
3
|
+
*
|
|
4
|
+
* Five commands. `mcp` serves the four tools, and is what the `mcpServers`
|
|
5
|
+
* stanza launches. `connect` writes that stanza. `doctor` checks the whole
|
|
6
|
+
* installation without a key. `status` and `settle` are the two tools a person
|
|
7
|
+
* reaches for outside a model, one to see what is owed and one to pay it.
|
|
8
|
+
*
|
|
9
|
+
* ## stdout belongs to the protocol
|
|
10
|
+
*
|
|
11
|
+
* Under `mcp` the process speaks MCP over stdout, so this file writes every
|
|
12
|
+
* human-readable line to stderr and every machine-readable payload to stdout,
|
|
13
|
+
* and the two never mix. `--json` on `status`, `settle` and `doctor` puts a
|
|
14
|
+
* single JSON document on stdout and nothing else, which is what makes the
|
|
15
|
+
* commands scriptable.
|
|
16
|
+
*
|
|
17
|
+
* ## `settle` does not broadcast unless it is told to
|
|
18
|
+
*
|
|
19
|
+
* A Settlement spends real funds, and a command that spends by default is a
|
|
20
|
+
* command somebody runs to see what it does. So `tab settle` is a dry run unless
|
|
21
|
+
* `--broadcast` is passed: it resolves the strategy, the Collection Address and
|
|
22
|
+
* the surface, reports exactly what would be sent, and sends nothing. The MCP
|
|
23
|
+
* tool has the same `dryRun` field for the same reason, defaulted the other way
|
|
24
|
+
* because a model calling `tab_settle` has already decided.
|
|
25
|
+
*
|
|
26
|
+
* Requirements: 25.5, 25.6
|
|
27
|
+
*/
|
|
28
|
+
import { ok } from "../_shared/index.js";
|
|
29
|
+
import { validationError } from "../errors.js";
|
|
30
|
+
import { createTabMcpServer, stderrLogger } from "../mcp/server.js";
|
|
31
|
+
import { resolveTabMcpSettings } from "../mcp/settings.js";
|
|
32
|
+
import { detectMcpClients } from "./client-config.js";
|
|
33
|
+
import { runConnect } from "./connect.js";
|
|
34
|
+
import { runDoctor } from "./doctor.js";
|
|
35
|
+
/** The name the help text uses. `npx @tabai/sdk` resolves to this. */
|
|
36
|
+
export const CLI_NAME = "tab";
|
|
37
|
+
const processIo = {
|
|
38
|
+
out: (line) => process.stdout.write(`${line}\n`),
|
|
39
|
+
err: (line) => process.stderr.write(`${line}\n`),
|
|
40
|
+
};
|
|
41
|
+
const BOOLEAN_FLAGS = new Set(["help", "version", "json", "dry-run", "broadcast", "http"]);
|
|
42
|
+
function parseFlags(argv) {
|
|
43
|
+
const positional = [];
|
|
44
|
+
const values = {};
|
|
45
|
+
const booleans = new Set();
|
|
46
|
+
for (let index = 0; index < argv.length; index += 1) {
|
|
47
|
+
const token = argv[index];
|
|
48
|
+
if (!token.startsWith("--")) {
|
|
49
|
+
positional.push(token);
|
|
50
|
+
continue;
|
|
51
|
+
}
|
|
52
|
+
const body = token.slice(2);
|
|
53
|
+
const equals = body.indexOf("=");
|
|
54
|
+
if (equals >= 0) {
|
|
55
|
+
values[body.slice(0, equals)] = body.slice(equals + 1);
|
|
56
|
+
continue;
|
|
57
|
+
}
|
|
58
|
+
const next = argv[index + 1];
|
|
59
|
+
if (BOOLEAN_FLAGS.has(body) && (next === undefined || next.startsWith("--"))) {
|
|
60
|
+
booleans.add(body);
|
|
61
|
+
continue;
|
|
62
|
+
}
|
|
63
|
+
if (next === undefined || next.startsWith("--")) {
|
|
64
|
+
if (BOOLEAN_FLAGS.has(body)) {
|
|
65
|
+
booleans.add(body);
|
|
66
|
+
continue;
|
|
67
|
+
}
|
|
68
|
+
return validationError("FLAG_VALUE_MISSING", `\`--${body}\` needs a value`, { details: { flag: body } });
|
|
69
|
+
}
|
|
70
|
+
values[body] = next;
|
|
71
|
+
index += 1;
|
|
72
|
+
}
|
|
73
|
+
return ok({ positional, values, booleans });
|
|
74
|
+
}
|
|
75
|
+
// ---------------------------------------------------------------- rendering
|
|
76
|
+
/** Fixed-width so the check names line up in a terminal. */
|
|
77
|
+
const markOf = (status) => status === "pass" ? " ok " : status === "warn" ? " warn " : status === "fail" ? " FAIL " : " skip ";
|
|
78
|
+
function renderDoctor(report, io) {
|
|
79
|
+
io.err("");
|
|
80
|
+
for (const check of report.checks) {
|
|
81
|
+
io.err(`[${markOf(check.status)}] ${check.name}: ${check.detail}`);
|
|
82
|
+
if (check.hint !== undefined)
|
|
83
|
+
io.err(` ${check.hint}`);
|
|
84
|
+
}
|
|
85
|
+
io.err("");
|
|
86
|
+
io.err(`${report.counts.pass} passed, ${report.counts.warn} warned, ${report.counts.fail} failed, ${report.counts.skip} skipped`);
|
|
87
|
+
io.err(report.ok ? "This installation can read the deployment." : "This installation is not usable as configured.");
|
|
88
|
+
}
|
|
89
|
+
const HELP = `${CLI_NAME} - post-paid billing for autonomous agents on Monad
|
|
90
|
+
|
|
91
|
+
Usage
|
|
92
|
+
npx -y @tabai/sdk <command> [options]
|
|
93
|
+
|
|
94
|
+
Commands
|
|
95
|
+
mcp Serve the four Tab tools over MCP. This is what an MCP client launches.
|
|
96
|
+
connect Write the tab server into an MCP client's config. Never writes a key.
|
|
97
|
+
doctor Check the installation. Every check is a keyless read.
|
|
98
|
+
status What the Agent owes, may still spend, and has settled.
|
|
99
|
+
settle Pay down an Open Tab. A dry run unless --broadcast is given.
|
|
100
|
+
|
|
101
|
+
Options
|
|
102
|
+
mcp --http [--port <n>] [--host <h>] [--endpoint <p>] serve streamable HTTP instead of stdio
|
|
103
|
+
connect --client <id> | --config <path> | --dry-run
|
|
104
|
+
clients: ${detectMcpClients()
|
|
105
|
+
.filter((target) => target.configPath !== undefined)
|
|
106
|
+
.map((target) => target.id)
|
|
107
|
+
.join(", ")}
|
|
108
|
+
doctor --client <id> | --config <path> | --json
|
|
109
|
+
status --agent <0x..> --asset <chainId:0x..> --history-limit <n> --json
|
|
110
|
+
settle --service <0x..> --asset <chainId:0x..> --amount <baseUnits>
|
|
111
|
+
--strategy <id> --broadcast --json
|
|
112
|
+
|
|
113
|
+
Environment
|
|
114
|
+
MONAD_RPC_URL the Monad JSON-RPC endpoint
|
|
115
|
+
MONAD_CHAIN_ID 143 for Mainnet, 10143 for Testnet
|
|
116
|
+
NEXT_PUBLIC_REGISTRY_API_URL the Tab registry read API, which serves discovery and status
|
|
117
|
+
AGENT_PRIVATE_KEY read only when a Settlement is signed, and never written anywhere
|
|
118
|
+
|
|
119
|
+
Configuration
|
|
120
|
+
tab.config.ts beside your project declares the Agent address, the registry URL,
|
|
121
|
+
the Service endpoints, and the payment strategies. The chain records no Service
|
|
122
|
+
endpoint, so tab_call needs one from there.
|
|
123
|
+
`;
|
|
124
|
+
// ---------------------------------------------------------------- commands
|
|
125
|
+
async function settingsFor(flags, options) {
|
|
126
|
+
return resolveTabMcpSettings({
|
|
127
|
+
...(flags.values["agent"] === undefined ? {} : { agent: flags.values["agent"] }),
|
|
128
|
+
...(flags.values["registry-url"] === undefined ? {} : { registryUrl: flags.values["registry-url"] }),
|
|
129
|
+
...(flags.values["rpc-url"] === undefined ? {} : { rpcUrl: flags.values["rpc-url"] }),
|
|
130
|
+
...(options.cwd === undefined ? {} : { cwd: options.cwd }),
|
|
131
|
+
...(options.env === undefined ? {} : { env: options.env }),
|
|
132
|
+
logger: stderrLogger,
|
|
133
|
+
});
|
|
134
|
+
}
|
|
135
|
+
async function commandMcp(flags, options) {
|
|
136
|
+
const io = options.io ?? processIo;
|
|
137
|
+
const server = await createTabMcpServer({
|
|
138
|
+
...(options.cwd === undefined ? {} : { cwd: options.cwd }),
|
|
139
|
+
...(options.env === undefined ? {} : { env: options.env }),
|
|
140
|
+
logger: stderrLogger,
|
|
141
|
+
});
|
|
142
|
+
if (flags.booleans.has("http") || flags.values["port"] !== undefined) {
|
|
143
|
+
const port = Number.parseInt(flags.values["port"] ?? "8790", 10);
|
|
144
|
+
if (!Number.isInteger(port) || port < 1 || port > 65_535) {
|
|
145
|
+
io.err(`tab: --port must be a TCP port, received \`${flags.values["port"] ?? ""}\``);
|
|
146
|
+
return 1;
|
|
147
|
+
}
|
|
148
|
+
const served = await server.serveHttp({
|
|
149
|
+
port,
|
|
150
|
+
...(flags.values["host"] === undefined ? {} : { host: flags.values["host"] }),
|
|
151
|
+
...(flags.values["endpoint"] === undefined ? {} : { endpoint: flags.values["endpoint"] }),
|
|
152
|
+
});
|
|
153
|
+
if (!served.ok) {
|
|
154
|
+
io.err(`tab: ${served.error.message}`);
|
|
155
|
+
return 1;
|
|
156
|
+
}
|
|
157
|
+
io.err(`tab: MCP over streamable HTTP at http://${served.value.host}:${served.value.port}${served.value.endpoint}`);
|
|
158
|
+
// Held open by the listening socket. The process exits when it is closed.
|
|
159
|
+
return 0;
|
|
160
|
+
}
|
|
161
|
+
const served = await server.serveStdio();
|
|
162
|
+
if (!served.ok) {
|
|
163
|
+
io.err(`tab: ${served.error.message}`);
|
|
164
|
+
return 1;
|
|
165
|
+
}
|
|
166
|
+
return 0;
|
|
167
|
+
}
|
|
168
|
+
async function commandConnect(flags, options) {
|
|
169
|
+
const io = options.io ?? processIo;
|
|
170
|
+
const settings = await settingsFor(flags, options);
|
|
171
|
+
const report = await runConnect({
|
|
172
|
+
settings,
|
|
173
|
+
...(flags.values["client"] === undefined ? {} : { client: flags.values["client"] }),
|
|
174
|
+
...(flags.values["config"] === undefined ? {} : { configPath: flags.values["config"] }),
|
|
175
|
+
...(options.env === undefined ? {} : { env: options.env }),
|
|
176
|
+
...(options.cwd === undefined ? {} : { cwd: options.cwd }),
|
|
177
|
+
dryRun: flags.booleans.has("dry-run"),
|
|
178
|
+
logger: stderrLogger,
|
|
179
|
+
});
|
|
180
|
+
if (!report.ok) {
|
|
181
|
+
io.err(`tab connect: ${report.error.message}`);
|
|
182
|
+
return 1;
|
|
183
|
+
}
|
|
184
|
+
const value = report.value;
|
|
185
|
+
io.err("");
|
|
186
|
+
io.err(`Client ${value.client}`);
|
|
187
|
+
io.err(`Config ${value.configPath}`);
|
|
188
|
+
io.err(`Registry ${value.preflight.registryUrl ?? "not configured"}`);
|
|
189
|
+
io.err(` ${value.preflight.note}`);
|
|
190
|
+
io.err("");
|
|
191
|
+
if (!value.changed) {
|
|
192
|
+
io.err(`Already connected. \`${value.configPath}\` already runs the tab server, so nothing was written.`);
|
|
193
|
+
}
|
|
194
|
+
else if (value.dryRun) {
|
|
195
|
+
io.err("Dry run. Nothing was written. This is the change that would be made:");
|
|
196
|
+
io.err("");
|
|
197
|
+
io.err(value.diff);
|
|
198
|
+
}
|
|
199
|
+
else {
|
|
200
|
+
io.err(value.hadStanza ? "Updated the tab server stanza." : "Added the tab server stanza.");
|
|
201
|
+
if (value.backupPath !== undefined)
|
|
202
|
+
io.err(`Backed up the previous config to ${value.backupPath}`);
|
|
203
|
+
io.err("");
|
|
204
|
+
io.err(value.diff);
|
|
205
|
+
}
|
|
206
|
+
io.err("");
|
|
207
|
+
io.err("No private key was written. Settlement signing keys are read from the environment at run time.");
|
|
208
|
+
io.err("");
|
|
209
|
+
io.err("Next");
|
|
210
|
+
io.err(value.client === "custom"
|
|
211
|
+
? " 1. Restart the client that reads that file, so it picks up the new server."
|
|
212
|
+
: ` 1. Restart ${value.client} so it picks up the new server.`);
|
|
213
|
+
io.err(" 2. Ask it to run tab_discover, which lists the Services registered on Monad.");
|
|
214
|
+
io.err(` 3. Check the whole installation with: npx -y @tabai/sdk doctor --config ${value.configPath}`);
|
|
215
|
+
return 0;
|
|
216
|
+
}
|
|
217
|
+
async function commandDoctor(flags, options) {
|
|
218
|
+
const io = options.io ?? processIo;
|
|
219
|
+
const settings = await settingsFor(flags, options);
|
|
220
|
+
let clientConfigPath = flags.values["config"];
|
|
221
|
+
if (clientConfigPath === undefined) {
|
|
222
|
+
const detected = detectMcpClients({
|
|
223
|
+
...(options.env === undefined ? {} : { env: options.env }),
|
|
224
|
+
...(options.cwd === undefined ? {} : { cwd: options.cwd }),
|
|
225
|
+
});
|
|
226
|
+
const named = flags.values["client"];
|
|
227
|
+
const chosen = named === undefined ? detected.find((t) => t.present) : detected.find((t) => t.id === named);
|
|
228
|
+
clientConfigPath = chosen?.configPath;
|
|
229
|
+
}
|
|
230
|
+
const report = await runDoctor({
|
|
231
|
+
settings,
|
|
232
|
+
...(options.env === undefined ? {} : { env: options.env }),
|
|
233
|
+
...(clientConfigPath === undefined ? {} : { clientConfigPath }),
|
|
234
|
+
logger: stderrLogger,
|
|
235
|
+
});
|
|
236
|
+
if (flags.booleans.has("json")) {
|
|
237
|
+
io.out(JSON.stringify(report, null, 2));
|
|
238
|
+
}
|
|
239
|
+
else {
|
|
240
|
+
renderDoctor(report, io);
|
|
241
|
+
}
|
|
242
|
+
return report.ok ? 0 : 1;
|
|
243
|
+
}
|
|
244
|
+
async function commandStatus(flags, options) {
|
|
245
|
+
const io = options.io ?? processIo;
|
|
246
|
+
const settings = await settingsFor(flags, options);
|
|
247
|
+
const server = await createTabMcpServer({ settings, logger: stderrLogger });
|
|
248
|
+
const output = await server.toolset.status({
|
|
249
|
+
...(flags.values["agent"] === undefined ? {} : { agent: flags.values["agent"] }),
|
|
250
|
+
...(flags.values["asset"] === undefined ? {} : { asset: flags.values["asset"] }),
|
|
251
|
+
...(flags.values["history-limit"] === undefined
|
|
252
|
+
? {}
|
|
253
|
+
: { historyLimit: Number.parseInt(flags.values["history-limit"], 10) }),
|
|
254
|
+
});
|
|
255
|
+
if (flags.booleans.has("json")) {
|
|
256
|
+
io.out(JSON.stringify(output, null, 2));
|
|
257
|
+
return output.error === undefined ? 0 : 1;
|
|
258
|
+
}
|
|
259
|
+
io.err("");
|
|
260
|
+
io.err(`Agent ${output.agent}`);
|
|
261
|
+
if (output.error !== undefined) {
|
|
262
|
+
io.err(` ${output.error.code}: ${output.error.message}`);
|
|
263
|
+
return 1;
|
|
264
|
+
}
|
|
265
|
+
if (output.perAsset.length === 0)
|
|
266
|
+
io.err(" no Asset activity is indexed for this Agent");
|
|
267
|
+
for (const entry of output.perAsset) {
|
|
268
|
+
io.err(` ${entry.asset}`);
|
|
269
|
+
io.err(` credit limit ${entry.creditLimitBaseUnits ?? "withheld"}`);
|
|
270
|
+
io.err(` open tab ${entry.openTabBaseUnits}`);
|
|
271
|
+
io.err(` headroom ${entry.headroomBaseUnits ?? "withheld"}`);
|
|
272
|
+
io.err(` delinquent ${String(entry.delinquent)}`);
|
|
273
|
+
}
|
|
274
|
+
io.err(` settlements ${output.settlements?.length ?? 0}`);
|
|
275
|
+
for (const settlement of output.settlements ?? []) {
|
|
276
|
+
io.err(` ${settlement.txHash} ${settlement.amountBaseUnits} ${settlement.asset}`);
|
|
277
|
+
}
|
|
278
|
+
return 0;
|
|
279
|
+
}
|
|
280
|
+
async function commandSettle(flags, options) {
|
|
281
|
+
const io = options.io ?? processIo;
|
|
282
|
+
const broadcast = flags.booleans.has("broadcast");
|
|
283
|
+
if (broadcast && options.allowBroadcast === false) {
|
|
284
|
+
io.err("tab settle: broadcasting is disabled in this process");
|
|
285
|
+
return 1;
|
|
286
|
+
}
|
|
287
|
+
// The strategy comes from `tab.config`, loaded by the toolset the first time a
|
|
288
|
+
// Settlement needs one. Nothing is loaded here, so a dry run that fails for
|
|
289
|
+
// another reason never touches a signer.
|
|
290
|
+
const settings = await settingsFor(flags, options);
|
|
291
|
+
const server = await createTabMcpServer({
|
|
292
|
+
settings,
|
|
293
|
+
...(options.cwd === undefined ? {} : { cwd: options.cwd }),
|
|
294
|
+
logger: stderrLogger,
|
|
295
|
+
});
|
|
296
|
+
const output = await server.toolset.settle({
|
|
297
|
+
...(flags.values["service"] === undefined ? {} : { serviceId: flags.values["service"] }),
|
|
298
|
+
...(flags.values["asset"] === undefined ? {} : { asset: flags.values["asset"] }),
|
|
299
|
+
...(flags.values["amount"] === undefined ? {} : { amountBaseUnits: flags.values["amount"] }),
|
|
300
|
+
...(flags.values["strategy"] === undefined ? {} : { strategyId: flags.values["strategy"] }),
|
|
301
|
+
dryRun: !broadcast,
|
|
302
|
+
});
|
|
303
|
+
if (flags.booleans.has("json")) {
|
|
304
|
+
io.out(JSON.stringify(output, null, 2));
|
|
305
|
+
return output.ok ? 0 : 1;
|
|
306
|
+
}
|
|
307
|
+
io.err("");
|
|
308
|
+
if (!output.ok) {
|
|
309
|
+
io.err(`tab settle: ${output.error?.code ?? "FAILED"}: ${output.error?.message ?? "the Settlement was not built"}`);
|
|
310
|
+
return 1;
|
|
311
|
+
}
|
|
312
|
+
if (output.dryRun) {
|
|
313
|
+
io.err("Dry run. Nothing was broadcast.");
|
|
314
|
+
io.err(` chain id ${String(output.chainId)}`);
|
|
315
|
+
io.err(` amount ${output.amountBaseUnits}`);
|
|
316
|
+
io.err("");
|
|
317
|
+
io.err("Add --broadcast to send it. This spends real funds.");
|
|
318
|
+
return 0;
|
|
319
|
+
}
|
|
320
|
+
io.err("Broadcast.");
|
|
321
|
+
io.err(` tx ${output.txHash ?? "unknown"}`);
|
|
322
|
+
io.err(` amount ${output.amountBaseUnits}`);
|
|
323
|
+
io.err(` applied ${output.appliedBaseUnits ?? "pending"}`);
|
|
324
|
+
io.err(` prepaid ${output.prepaidBaseUnits ?? "pending"}`);
|
|
325
|
+
io.err(` explorer ${output.explorerUrl ?? "unknown"}`);
|
|
326
|
+
return 0;
|
|
327
|
+
}
|
|
328
|
+
// ---------------------------------------------------------------- entry
|
|
329
|
+
/** Runs one invocation and answers a process exit code. Never throws. */
|
|
330
|
+
export async function runCli(argv, options = {}) {
|
|
331
|
+
const io = options.io ?? processIo;
|
|
332
|
+
const parsed = parseFlags(argv);
|
|
333
|
+
if (!parsed.ok) {
|
|
334
|
+
io.err(`tab: ${parsed.error.message}`);
|
|
335
|
+
return 1;
|
|
336
|
+
}
|
|
337
|
+
const flags = parsed.value;
|
|
338
|
+
const command = flags.positional[0];
|
|
339
|
+
if (flags.booleans.has("version")) {
|
|
340
|
+
io.out("0.0.0");
|
|
341
|
+
return 0;
|
|
342
|
+
}
|
|
343
|
+
if (command === undefined || flags.booleans.has("help") || command === "help") {
|
|
344
|
+
io.err(HELP);
|
|
345
|
+
return command === undefined || command === "help" || flags.booleans.has("help") ? 0 : 1;
|
|
346
|
+
}
|
|
347
|
+
try {
|
|
348
|
+
switch (command) {
|
|
349
|
+
case "mcp":
|
|
350
|
+
return await commandMcp(flags, options);
|
|
351
|
+
case "connect":
|
|
352
|
+
return await commandConnect(flags, options);
|
|
353
|
+
case "doctor":
|
|
354
|
+
return await commandDoctor(flags, options);
|
|
355
|
+
case "status":
|
|
356
|
+
return await commandStatus(flags, options);
|
|
357
|
+
case "settle":
|
|
358
|
+
return await commandSettle(flags, options);
|
|
359
|
+
default:
|
|
360
|
+
io.err(`tab: \`${command}\` is not a command. Run \`${CLI_NAME} help\` for the list.`);
|
|
361
|
+
return 1;
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
catch (error) {
|
|
365
|
+
// The commands are written not to reach here. A bug that does should still
|
|
366
|
+
// leave a message and an exit code rather than an unhandled rejection.
|
|
367
|
+
io.err(`tab: ${command} failed unexpectedly: ${error instanceof Error ? error.message : String(error)}`);
|
|
368
|
+
return 1;
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
//# sourceMappingURL=main.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"main.js","sourceRoot":"","sources":["../../src/cli/main.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * `tab`: the executable entry point of this package.\n *\n * Five commands. `mcp` serves the four tools, and is what the `mcpServers`\n * stanza launches. `connect` writes that stanza. `doctor` checks the whole\n * installation without a key. `status` and `settle` are the two tools a person\n * reaches for outside a model, one to see what is owed and one to pay it.\n *\n * ## stdout belongs to the protocol\n *\n * Under `mcp` the process speaks MCP over stdout, so this file writes every\n * human-readable line to stderr and every machine-readable payload to stdout,\n * and the two never mix. `--json` on `status`, `settle` and `doctor` puts a\n * single JSON document on stdout and nothing else, which is what makes the\n * commands scriptable.\n *\n * ## `settle` does not broadcast unless it is told to\n *\n * A Settlement spends real funds, and a command that spends by default is a\n * command somebody runs to see what it does. So `tab settle` is a dry run unless\n * `--broadcast` is passed: it resolves the strategy, the Collection Address and\n * the surface, reports exactly what would be sent, and sends nothing. The MCP\n * tool has the same `dryRun` field for the same reason, defaulted the other way\n * because a model calling `tab_settle` has already decided.\n *\n * Requirements: 25.5, 25.6\n */\n\nimport type { Result } from \"../_shared/index.js\";\nimport { ok } from \"../_shared/index.js\";\n\nimport { validationError } from \"../errors.js\";\nimport { createTabMcpServer, stderrLogger } from \"../mcp/server.js\";\nimport { resolveTabMcpSettings, type TabMcpSettings } from \"../mcp/settings.js\";\nimport { detectMcpClients } from \"./client-config.js\";\nimport { runConnect } from \"./connect.js\";\nimport { runDoctor, type CheckStatus, type DoctorReport } from \"./doctor.js\";\n\n/** The name the help text uses. `npx @tabai/sdk` resolves to this. */\nexport const CLI_NAME = \"tab\";\n\nexport interface CliIo {\n /** Machine-readable output. Under `mcp` this is the protocol stream and nothing else writes to it. */\n out(line: string): void;\n /** Everything a person reads. */\n err(line: string): void;\n}\n\nconst processIo: CliIo = {\n out: (line) => process.stdout.write(`${line}\\n`),\n err: (line) => process.stderr.write(`${line}\\n`),\n};\n\nexport interface CliOptions {\n readonly io?: CliIo;\n readonly env?: NodeJS.ProcessEnv;\n readonly cwd?: string;\n /** Blocks the two commands that would spend, so a test can never broadcast. */\n readonly allowBroadcast?: boolean;\n}\n\n// ---------------------------------------------------------------- flags\n\n/** A flag parse. Everything is `--name value` or `--name` for a boolean. */\ninterface Flags {\n readonly positional: readonly string[];\n readonly values: Readonly<Record<string, string>>;\n readonly booleans: ReadonlySet<string>;\n}\n\nconst BOOLEAN_FLAGS = new Set([\"help\", \"version\", \"json\", \"dry-run\", \"broadcast\", \"http\"]);\n\nfunction parseFlags(argv: readonly string[]): Result<Flags> {\n const positional: string[] = [];\n const values: Record<string, string> = {};\n const booleans = new Set<string>();\n\n for (let index = 0; index < argv.length; index += 1) {\n const token = argv[index]!;\n if (!token.startsWith(\"--\")) {\n positional.push(token);\n continue;\n }\n const body = token.slice(2);\n const equals = body.indexOf(\"=\");\n if (equals >= 0) {\n values[body.slice(0, equals)] = body.slice(equals + 1);\n continue;\n }\n const next = argv[index + 1];\n if (BOOLEAN_FLAGS.has(body) && (next === undefined || next.startsWith(\"--\"))) {\n booleans.add(body);\n continue;\n }\n if (next === undefined || next.startsWith(\"--\")) {\n if (BOOLEAN_FLAGS.has(body)) {\n booleans.add(body);\n continue;\n }\n return validationError(\"FLAG_VALUE_MISSING\", `\\`--${body}\\` needs a value`, { details: { flag: body } });\n }\n values[body] = next;\n index += 1;\n }\n return ok({ positional, values, booleans });\n}\n\n// ---------------------------------------------------------------- rendering\n\n/** Fixed-width so the check names line up in a terminal. */\nconst markOf = (status: CheckStatus): string =>\n status === \"pass\" ? \" ok \" : status === \"warn\" ? \" warn \" : status === \"fail\" ? \" FAIL \" : \" skip \";\n\nfunction renderDoctor(report: DoctorReport, io: CliIo): void {\n io.err(\"\");\n for (const check of report.checks) {\n io.err(`[${markOf(check.status)}] ${check.name}: ${check.detail}`);\n if (check.hint !== undefined) io.err(` ${check.hint}`);\n }\n io.err(\"\");\n io.err(\n `${report.counts.pass} passed, ${report.counts.warn} warned, ${report.counts.fail} failed, ${report.counts.skip} skipped`,\n );\n io.err(report.ok ? \"This installation can read the deployment.\" : \"This installation is not usable as configured.\");\n}\n\nconst HELP = `${CLI_NAME} - post-paid billing for autonomous agents on Monad\n\nUsage\n npx -y @tabai/sdk <command> [options]\n\nCommands\n mcp Serve the four Tab tools over MCP. This is what an MCP client launches.\n connect Write the tab server into an MCP client's config. Never writes a key.\n doctor Check the installation. Every check is a keyless read.\n status What the Agent owes, may still spend, and has settled.\n settle Pay down an Open Tab. A dry run unless --broadcast is given.\n\nOptions\n mcp --http [--port <n>] [--host <h>] [--endpoint <p>] serve streamable HTTP instead of stdio\n connect --client <id> | --config <path> | --dry-run\n clients: ${detectMcpClients()\n .filter((target) => target.configPath !== undefined)\n .map((target) => target.id)\n .join(\", \")}\n doctor --client <id> | --config <path> | --json\n status --agent <0x..> --asset <chainId:0x..> --history-limit <n> --json\n settle --service <0x..> --asset <chainId:0x..> --amount <baseUnits>\n --strategy <id> --broadcast --json\n\nEnvironment\n MONAD_RPC_URL the Monad JSON-RPC endpoint\n MONAD_CHAIN_ID 143 for Mainnet, 10143 for Testnet\n NEXT_PUBLIC_REGISTRY_API_URL the Tab registry read API, which serves discovery and status\n AGENT_PRIVATE_KEY read only when a Settlement is signed, and never written anywhere\n\nConfiguration\n tab.config.ts beside your project declares the Agent address, the registry URL,\n the Service endpoints, and the payment strategies. The chain records no Service\n endpoint, so tab_call needs one from there.\n`;\n\n// ---------------------------------------------------------------- commands\n\nasync function settingsFor(flags: Flags, options: CliOptions): Promise<TabMcpSettings> {\n return resolveTabMcpSettings({\n ...(flags.values[\"agent\"] === undefined ? {} : { agent: flags.values[\"agent\"] }),\n ...(flags.values[\"registry-url\"] === undefined ? {} : { registryUrl: flags.values[\"registry-url\"] }),\n ...(flags.values[\"rpc-url\"] === undefined ? {} : { rpcUrl: flags.values[\"rpc-url\"] }),\n ...(options.cwd === undefined ? {} : { cwd: options.cwd }),\n ...(options.env === undefined ? {} : { env: options.env }),\n logger: stderrLogger,\n });\n}\n\nasync function commandMcp(flags: Flags, options: CliOptions): Promise<number> {\n const io = options.io ?? processIo;\n const server = await createTabMcpServer({\n ...(options.cwd === undefined ? {} : { cwd: options.cwd }),\n ...(options.env === undefined ? {} : { env: options.env }),\n logger: stderrLogger,\n });\n\n if (flags.booleans.has(\"http\") || flags.values[\"port\"] !== undefined) {\n const port = Number.parseInt(flags.values[\"port\"] ?? \"8790\", 10);\n if (!Number.isInteger(port) || port < 1 || port > 65_535) {\n io.err(`tab: --port must be a TCP port, received \\`${flags.values[\"port\"] ?? \"\"}\\``);\n return 1;\n }\n const served = await server.serveHttp({\n port,\n ...(flags.values[\"host\"] === undefined ? {} : { host: flags.values[\"host\"] }),\n ...(flags.values[\"endpoint\"] === undefined ? {} : { endpoint: flags.values[\"endpoint\"] }),\n });\n if (!served.ok) {\n io.err(`tab: ${served.error.message}`);\n return 1;\n }\n io.err(`tab: MCP over streamable HTTP at http://${served.value.host}:${served.value.port}${served.value.endpoint}`);\n // Held open by the listening socket. The process exits when it is closed.\n return 0;\n }\n\n const served = await server.serveStdio();\n if (!served.ok) {\n io.err(`tab: ${served.error.message}`);\n return 1;\n }\n return 0;\n}\n\nasync function commandConnect(flags: Flags, options: CliOptions): Promise<number> {\n const io = options.io ?? processIo;\n const settings = await settingsFor(flags, options);\n const report = await runConnect({\n settings,\n ...(flags.values[\"client\"] === undefined ? {} : { client: flags.values[\"client\"] }),\n ...(flags.values[\"config\"] === undefined ? {} : { configPath: flags.values[\"config\"] }),\n ...(options.env === undefined ? {} : { env: options.env }),\n ...(options.cwd === undefined ? {} : { cwd: options.cwd }),\n dryRun: flags.booleans.has(\"dry-run\"),\n logger: stderrLogger,\n });\n\n if (!report.ok) {\n io.err(`tab connect: ${report.error.message}`);\n return 1;\n }\n\n const value = report.value;\n io.err(\"\");\n io.err(`Client ${value.client}`);\n io.err(`Config ${value.configPath}`);\n io.err(`Registry ${value.preflight.registryUrl ?? \"not configured\"}`);\n io.err(` ${value.preflight.note}`);\n io.err(\"\");\n\n if (!value.changed) {\n io.err(`Already connected. \\`${value.configPath}\\` already runs the tab server, so nothing was written.`);\n } else if (value.dryRun) {\n io.err(\"Dry run. Nothing was written. This is the change that would be made:\");\n io.err(\"\");\n io.err(value.diff);\n } else {\n io.err(value.hadStanza ? \"Updated the tab server stanza.\" : \"Added the tab server stanza.\");\n if (value.backupPath !== undefined) io.err(`Backed up the previous config to ${value.backupPath}`);\n io.err(\"\");\n io.err(value.diff);\n }\n\n io.err(\"\");\n io.err(\"No private key was written. Settlement signing keys are read from the environment at run time.\");\n io.err(\"\");\n io.err(\"Next\");\n io.err(\n value.client === \"custom\"\n ? \" 1. Restart the client that reads that file, so it picks up the new server.\"\n : ` 1. Restart ${value.client} so it picks up the new server.`,\n );\n io.err(\" 2. Ask it to run tab_discover, which lists the Services registered on Monad.\");\n io.err(` 3. Check the whole installation with: npx -y @tabai/sdk doctor --config ${value.configPath}`);\n return 0;\n}\n\nasync function commandDoctor(flags: Flags, options: CliOptions): Promise<number> {\n const io = options.io ?? processIo;\n const settings = await settingsFor(flags, options);\n\n let clientConfigPath = flags.values[\"config\"];\n if (clientConfigPath === undefined) {\n const detected = detectMcpClients({\n ...(options.env === undefined ? {} : { env: options.env }),\n ...(options.cwd === undefined ? {} : { cwd: options.cwd }),\n });\n const named = flags.values[\"client\"];\n const chosen = named === undefined ? detected.find((t) => t.present) : detected.find((t) => t.id === named);\n clientConfigPath = chosen?.configPath;\n }\n\n const report = await runDoctor({\n settings,\n ...(options.env === undefined ? {} : { env: options.env }),\n ...(clientConfigPath === undefined ? {} : { clientConfigPath }),\n logger: stderrLogger,\n });\n\n if (flags.booleans.has(\"json\")) {\n io.out(JSON.stringify(report, null, 2));\n } else {\n renderDoctor(report, io);\n }\n return report.ok ? 0 : 1;\n}\n\nasync function commandStatus(flags: Flags, options: CliOptions): Promise<number> {\n const io = options.io ?? processIo;\n const settings = await settingsFor(flags, options);\n const server = await createTabMcpServer({ settings, logger: stderrLogger });\n\n const output = await server.toolset.status({\n ...(flags.values[\"agent\"] === undefined ? {} : { agent: flags.values[\"agent\"] }),\n ...(flags.values[\"asset\"] === undefined ? {} : { asset: flags.values[\"asset\"] }),\n ...(flags.values[\"history-limit\"] === undefined\n ? {}\n : { historyLimit: Number.parseInt(flags.values[\"history-limit\"], 10) }),\n });\n\n if (flags.booleans.has(\"json\")) {\n io.out(JSON.stringify(output, null, 2));\n return output.error === undefined ? 0 : 1;\n }\n\n io.err(\"\");\n io.err(`Agent ${output.agent}`);\n if (output.error !== undefined) {\n io.err(` ${output.error.code}: ${output.error.message}`);\n return 1;\n }\n if (output.perAsset.length === 0) io.err(\" no Asset activity is indexed for this Agent\");\n for (const entry of output.perAsset) {\n io.err(` ${entry.asset}`);\n io.err(` credit limit ${entry.creditLimitBaseUnits ?? \"withheld\"}`);\n io.err(` open tab ${entry.openTabBaseUnits}`);\n io.err(` headroom ${entry.headroomBaseUnits ?? \"withheld\"}`);\n io.err(` delinquent ${String(entry.delinquent)}`);\n }\n io.err(` settlements ${output.settlements?.length ?? 0}`);\n for (const settlement of output.settlements ?? []) {\n io.err(` ${settlement.txHash} ${settlement.amountBaseUnits} ${settlement.asset}`);\n }\n return 0;\n}\n\nasync function commandSettle(flags: Flags, options: CliOptions): Promise<number> {\n const io = options.io ?? processIo;\n const broadcast = flags.booleans.has(\"broadcast\");\n\n if (broadcast && options.allowBroadcast === false) {\n io.err(\"tab settle: broadcasting is disabled in this process\");\n return 1;\n }\n\n // The strategy comes from `tab.config`, loaded by the toolset the first time a\n // Settlement needs one. Nothing is loaded here, so a dry run that fails for\n // another reason never touches a signer.\n const settings = await settingsFor(flags, options);\n const server = await createTabMcpServer({\n settings,\n ...(options.cwd === undefined ? {} : { cwd: options.cwd }),\n logger: stderrLogger,\n });\n\n const output = await server.toolset.settle({\n ...(flags.values[\"service\"] === undefined ? {} : { serviceId: flags.values[\"service\"] }),\n ...(flags.values[\"asset\"] === undefined ? {} : { asset: flags.values[\"asset\"] }),\n ...(flags.values[\"amount\"] === undefined ? {} : { amountBaseUnits: flags.values[\"amount\"] }),\n ...(flags.values[\"strategy\"] === undefined ? {} : { strategyId: flags.values[\"strategy\"] }),\n dryRun: !broadcast,\n });\n\n if (flags.booleans.has(\"json\")) {\n io.out(JSON.stringify(output, null, 2));\n return output.ok ? 0 : 1;\n }\n\n io.err(\"\");\n if (!output.ok) {\n io.err(`tab settle: ${output.error?.code ?? \"FAILED\"}: ${output.error?.message ?? \"the Settlement was not built\"}`);\n return 1;\n }\n if (output.dryRun) {\n io.err(\"Dry run. Nothing was broadcast.\");\n io.err(` chain id ${String(output.chainId)}`);\n io.err(` amount ${output.amountBaseUnits}`);\n io.err(\"\");\n io.err(\"Add --broadcast to send it. This spends real funds.\");\n return 0;\n }\n io.err(\"Broadcast.\");\n io.err(` tx ${output.txHash ?? \"unknown\"}`);\n io.err(` amount ${output.amountBaseUnits}`);\n io.err(` applied ${output.appliedBaseUnits ?? \"pending\"}`);\n io.err(` prepaid ${output.prepaidBaseUnits ?? \"pending\"}`);\n io.err(` explorer ${output.explorerUrl ?? \"unknown\"}`);\n return 0;\n}\n\n// ---------------------------------------------------------------- entry\n\n/** Runs one invocation and answers a process exit code. Never throws. */\nexport async function runCli(argv: readonly string[], options: CliOptions = {}): Promise<number> {\n const io = options.io ?? processIo;\n const parsed = parseFlags(argv);\n if (!parsed.ok) {\n io.err(`tab: ${parsed.error.message}`);\n return 1;\n }\n const flags = parsed.value;\n const command = flags.positional[0];\n\n if (flags.booleans.has(\"version\")) {\n io.out(\"0.0.0\");\n return 0;\n }\n if (command === undefined || flags.booleans.has(\"help\") || command === \"help\") {\n io.err(HELP);\n return command === undefined || command === \"help\" || flags.booleans.has(\"help\") ? 0 : 1;\n }\n\n try {\n switch (command) {\n case \"mcp\":\n return await commandMcp(flags, options);\n case \"connect\":\n return await commandConnect(flags, options);\n case \"doctor\":\n return await commandDoctor(flags, options);\n case \"status\":\n return await commandStatus(flags, options);\n case \"settle\":\n return await commandSettle(flags, options);\n default:\n io.err(`tab: \\`${command}\\` is not a command. Run \\`${CLI_NAME} help\\` for the list.`);\n return 1;\n }\n } catch (error) {\n // The commands are written not to reach here. A bug that does should still\n // leave a message and an exit code rather than an unhandled rejection.\n io.err(`tab: ${command} failed unexpectedly: ${error instanceof Error ? error.message : String(error)}`);\n return 1;\n }\n}\n"]}
|
package/dist/errors.d.ts
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Error constructors for the SDK.
|
|
3
|
+
*
|
|
4
|
+
* Nothing exported from this package throws (R21.5, design section 13.1), so
|
|
5
|
+
* every fallible call ends in one of these. The categories, codes, and the
|
|
6
|
+
* status each category maps to all come from `./_shared/index.js`; this module only
|
|
7
|
+
* saves every call site from writing the same object literal.
|
|
8
|
+
*
|
|
9
|
+
* Requirements: 21.5
|
|
10
|
+
*/
|
|
11
|
+
import { type ErrorCategory, type Result, type TabError } from "./_shared/index.js";
|
|
12
|
+
/** The optional half of a `TabError`, so a call site names only what it knows. */
|
|
13
|
+
export type ErrorExtras = Partial<Pick<TabError, "retryable" | "retryAfterMs" | "details" | "cause">>;
|
|
14
|
+
/**
|
|
15
|
+
* Builds a `TabError`. `retryable` defaults to false: a caller that retries an
|
|
16
|
+
* error nobody marked retryable is the failure mode worth defaulting against.
|
|
17
|
+
*/
|
|
18
|
+
export declare function tabError(category: ErrorCategory, code: string, message: string, extras?: ErrorExtras): TabError;
|
|
19
|
+
/** `tabError` already wrapped as a failed `Result`. */
|
|
20
|
+
export declare const fail: (category: ErrorCategory, code: string, message: string, extras?: ErrorExtras) => Result<never>;
|
|
21
|
+
/** Caller-supplied input is malformed. HTTP 400. */
|
|
22
|
+
export declare const validationError: (code: string, message: string, extras?: ErrorExtras) => Result<never>;
|
|
23
|
+
/** Unknown strategy, asset, service, or config file. HTTP 404. */
|
|
24
|
+
export declare const notFoundError: (code: string, message: string, extras?: ErrorExtras) => Result<never>;
|
|
25
|
+
/** An RPC endpoint, a module loader, or a consumer-supplied callback failed. HTTP 502. */
|
|
26
|
+
export declare const upstreamError: (code: string, message: string, extras?: ErrorExtras) => Result<never>;
|
|
27
|
+
/** A Monad transaction failed to submit. HTTP 500. */
|
|
28
|
+
export declare const chainError: (code: string, message: string, extras?: ErrorExtras) => Result<never>;
|
|
29
|
+
//# sourceMappingURL=errors.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAO,KAAK,aAAa,EAAE,KAAK,MAAM,EAAE,KAAK,QAAQ,EAAE,MAAM,eAAe,CAAC;AAEpF,kFAAkF;AAClF,MAAM,MAAM,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,QAAQ,EAAE,WAAW,GAAG,cAAc,GAAG,SAAS,GAAG,OAAO,CAAC,CAAC,CAAC;AAEtG;;;GAGG;AACH,wBAAgB,QAAQ,CACtB,QAAQ,EAAE,aAAa,EACvB,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,EACf,MAAM,GAAE,WAAgB,GACvB,QAAQ,CAUV;AAED,uDAAuD;AACvD,eAAO,MAAM,IAAI,GACf,UAAU,aAAa,EACvB,MAAM,MAAM,EACZ,SAAS,MAAM,EACf,SAAQ,WAAgB,KACvB,MAAM,CAAC,KAAK,CAAmD,CAAC;AAEnE,oDAAoD;AACpD,eAAO,MAAM,eAAe,GAAI,MAAM,MAAM,EAAE,SAAS,MAAM,EAAE,SAAS,WAAW,KAAG,MAAM,CAAC,KAAK,CACvD,CAAC;AAE5C,kEAAkE;AAClE,eAAO,MAAM,aAAa,GAAI,MAAM,MAAM,EAAE,SAAS,MAAM,EAAE,SAAS,WAAW,KAAG,MAAM,CAAC,KAAK,CACtD,CAAC;AAE3C,0FAA0F;AAC1F,eAAO,MAAM,aAAa,GAAI,MAAM,MAAM,EAAE,SAAS,MAAM,EAAE,SAAS,WAAW,KAAG,MAAM,CAAC,KAAK,CACvD,CAAC;AAE1C,sDAAsD;AACtD,eAAO,MAAM,UAAU,GAAI,MAAM,MAAM,EAAE,SAAS,MAAM,EAAE,SAAS,WAAW,KAAG,MAAM,CAAC,KAAK,CACvD,CAAC"}
|
package/dist/errors.js
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Error constructors for the SDK.
|
|
3
|
+
*
|
|
4
|
+
* Nothing exported from this package throws (R21.5, design section 13.1), so
|
|
5
|
+
* every fallible call ends in one of these. The categories, codes, and the
|
|
6
|
+
* status each category maps to all come from `./_shared/index.js`; this module only
|
|
7
|
+
* saves every call site from writing the same object literal.
|
|
8
|
+
*
|
|
9
|
+
* Requirements: 21.5
|
|
10
|
+
*/
|
|
11
|
+
import { err } from "./_shared/index.js";
|
|
12
|
+
/**
|
|
13
|
+
* Builds a `TabError`. `retryable` defaults to false: a caller that retries an
|
|
14
|
+
* error nobody marked retryable is the failure mode worth defaulting against.
|
|
15
|
+
*/
|
|
16
|
+
export function tabError(category, code, message, extras = {}) {
|
|
17
|
+
return {
|
|
18
|
+
category,
|
|
19
|
+
code,
|
|
20
|
+
message,
|
|
21
|
+
retryable: extras.retryable ?? false,
|
|
22
|
+
...(extras.retryAfterMs === undefined ? {} : { retryAfterMs: extras.retryAfterMs }),
|
|
23
|
+
...(extras.details === undefined ? {} : { details: extras.details }),
|
|
24
|
+
...(extras.cause === undefined ? {} : { cause: extras.cause }),
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
/** `tabError` already wrapped as a failed `Result`. */
|
|
28
|
+
export const fail = (category, code, message, extras = {}) => err(tabError(category, code, message, extras));
|
|
29
|
+
/** Caller-supplied input is malformed. HTTP 400. */
|
|
30
|
+
export const validationError = (code, message, extras) => fail("VALIDATION", code, message, extras);
|
|
31
|
+
/** Unknown strategy, asset, service, or config file. HTTP 404. */
|
|
32
|
+
export const notFoundError = (code, message, extras) => fail("NOT_FOUND", code, message, extras);
|
|
33
|
+
/** An RPC endpoint, a module loader, or a consumer-supplied callback failed. HTTP 502. */
|
|
34
|
+
export const upstreamError = (code, message, extras) => fail("UPSTREAM", code, message, extras);
|
|
35
|
+
/** A Monad transaction failed to submit. HTTP 500. */
|
|
36
|
+
export const chainError = (code, message, extras) => fail("CHAIN", code, message, extras);
|
|
37
|
+
//# sourceMappingURL=errors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,GAAG,EAAkD,MAAM,eAAe,CAAC;AAKpF;;;GAGG;AACH,MAAM,UAAU,QAAQ,CACtB,QAAuB,EACvB,IAAY,EACZ,OAAe,EACf,SAAsB,EAAE;IAExB,OAAO;QACL,QAAQ;QACR,IAAI;QACJ,OAAO;QACP,SAAS,EAAE,MAAM,CAAC,SAAS,IAAI,KAAK;QACpC,GAAG,CAAC,MAAM,CAAC,YAAY,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,YAAY,EAAE,MAAM,CAAC,YAAY,EAAE,CAAC;QACnF,GAAG,CAAC,MAAM,CAAC,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,MAAM,CAAC,OAAO,EAAE,CAAC;QACpE,GAAG,CAAC,MAAM,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,EAAE,CAAC;KAC/D,CAAC;AACJ,CAAC;AAED,uDAAuD;AACvD,MAAM,CAAC,MAAM,IAAI,GAAG,CAClB,QAAuB,EACvB,IAAY,EACZ,OAAe,EACf,SAAsB,EAAE,EACT,EAAE,CAAC,GAAG,CAAC,QAAQ,CAAC,QAAQ,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC,CAAC;AAEnE,oDAAoD;AACpD,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,IAAY,EAAE,OAAe,EAAE,MAAoB,EAAiB,EAAE,CACpG,IAAI,CAAC,YAAY,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC;AAE5C,kEAAkE;AAClE,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,IAAY,EAAE,OAAe,EAAE,MAAoB,EAAiB,EAAE,CAClG,IAAI,CAAC,WAAW,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC;AAE3C,0FAA0F;AAC1F,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,IAAY,EAAE,OAAe,EAAE,MAAoB,EAAiB,EAAE,CAClG,IAAI,CAAC,UAAU,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC;AAE1C,sDAAsD;AACtD,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,IAAY,EAAE,OAAe,EAAE,MAAoB,EAAiB,EAAE,CAC/F,IAAI,CAAC,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC","sourcesContent":["/**\n * Error constructors for the SDK.\n *\n * Nothing exported from this package throws (R21.5, design section 13.1), so\n * every fallible call ends in one of these. The categories, codes, and the\n * status each category maps to all come from `./_shared/index.js`; this module only\n * saves every call site from writing the same object literal.\n *\n * Requirements: 21.5\n */\n\nimport { err, type ErrorCategory, type Result, type TabError } from \"./_shared/index.js\";\n\n/** The optional half of a `TabError`, so a call site names only what it knows. */\nexport type ErrorExtras = Partial<Pick<TabError, \"retryable\" | \"retryAfterMs\" | \"details\" | \"cause\">>;\n\n/**\n * Builds a `TabError`. `retryable` defaults to false: a caller that retries an\n * error nobody marked retryable is the failure mode worth defaulting against.\n */\nexport function tabError(\n category: ErrorCategory,\n code: string,\n message: string,\n extras: ErrorExtras = {},\n): TabError {\n return {\n category,\n code,\n message,\n retryable: extras.retryable ?? false,\n ...(extras.retryAfterMs === undefined ? {} : { retryAfterMs: extras.retryAfterMs }),\n ...(extras.details === undefined ? {} : { details: extras.details }),\n ...(extras.cause === undefined ? {} : { cause: extras.cause }),\n };\n}\n\n/** `tabError` already wrapped as a failed `Result`. */\nexport const fail = (\n category: ErrorCategory,\n code: string,\n message: string,\n extras: ErrorExtras = {},\n): Result<never> => err(tabError(category, code, message, extras));\n\n/** Caller-supplied input is malformed. HTTP 400. */\nexport const validationError = (code: string, message: string, extras?: ErrorExtras): Result<never> =>\n fail(\"VALIDATION\", code, message, extras);\n\n/** Unknown strategy, asset, service, or config file. HTTP 404. */\nexport const notFoundError = (code: string, message: string, extras?: ErrorExtras): Result<never> =>\n fail(\"NOT_FOUND\", code, message, extras);\n\n/** An RPC endpoint, a module loader, or a consumer-supplied callback failed. HTTP 502. */\nexport const upstreamError = (code: string, message: string, extras?: ErrorExtras): Result<never> =>\n fail(\"UPSTREAM\", code, message, extras);\n\n/** A Monad transaction failed to submit. HTTP 500. */\nexport const chainError = (code: string, message: string, extras?: ErrorExtras): Result<never> =>\n fail(\"CHAIN\", code, message, extras);\n"]}
|