shinjuku-shield 0.3.92 → 0.3.94
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 +5 -5
- package/manifest.json +4 -4
- package/package.json +3 -3
- package/shinjuku-wallet.mjs +333 -85
package/README.md
CHANGED
|
@@ -6,13 +6,13 @@ answers privately, in a terminal chat or for your agent app. Its `mcp`
|
|
|
6
6
|
command runs a local MCP server (stdio) for your agent. Your keys never
|
|
7
7
|
leave your machine.
|
|
8
8
|
|
|
9
|
-
This is version 0.3.
|
|
9
|
+
This is version 0.3.94. The npm packages `shinjuku-shield` and
|
|
10
10
|
`shinjuku-shielded` hold the same files; `shinjuku` is the short command.
|
|
11
11
|
|
|
12
12
|
## Set up
|
|
13
13
|
|
|
14
14
|
```sh
|
|
15
|
-
npx -y --no-audit --no-fund shinjuku-shield@0.3.
|
|
15
|
+
npx -y --no-audit --no-fund shinjuku-shield@0.3.94 setup
|
|
16
16
|
```
|
|
17
17
|
|
|
18
18
|
Setup makes the wallet on this machine, a private passphrase file, and the
|
|
@@ -24,7 +24,7 @@ server to that host's config.
|
|
|
24
24
|
## The `shinjuku` command
|
|
25
25
|
|
|
26
26
|
```sh
|
|
27
|
-
npm install -g shinjuku@0.3.
|
|
27
|
+
npm install -g shinjuku@0.3.94
|
|
28
28
|
shinjuku help
|
|
29
29
|
```
|
|
30
30
|
|
|
@@ -36,13 +36,13 @@ Every wallet command works after `shinjuku`, for example `shinjuku balance`,
|
|
|
36
36
|
Claude Code:
|
|
37
37
|
|
|
38
38
|
```sh
|
|
39
|
-
claude mcp add --scope user shinjuku-shielded -- npx -y --no-audit --no-fund shinjuku-shield@0.3.
|
|
39
|
+
claude mcp add --scope user shinjuku-shielded -- npx -y --no-audit --no-fund shinjuku-shield@0.3.94 mcp
|
|
40
40
|
```
|
|
41
41
|
|
|
42
42
|
Claude Desktop (`claude_desktop_config.json`) or Cursor (`~/.cursor/mcp.json`):
|
|
43
43
|
|
|
44
44
|
```json
|
|
45
|
-
{ "mcpServers": { "shinjuku-shielded": { "command": "npx", "args": ["-y", "--no-audit", "--no-fund", "shinjuku-shield@0.3.
|
|
45
|
+
{ "mcpServers": { "shinjuku-shielded": { "command": "npx", "args": ["-y", "--no-audit", "--no-fund", "shinjuku-shield@0.3.94", "mcp"] } } }
|
|
46
46
|
```
|
|
47
47
|
|
|
48
48
|
On native Windows, if the host cannot find `npx`, use `"command": "cmd"` and
|
package/manifest.json
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schema": "carbon-shielded-wallet/bundle-manifest/v1",
|
|
3
3
|
"file": "shinjuku-wallet.mjs",
|
|
4
|
-
"sha256": "
|
|
5
|
-
"bytes":
|
|
6
|
-
"sourceCommit": "
|
|
4
|
+
"sha256": "af5b54d5bce11c64a002dca7d59c8593767ddefe4b7177b8ef44cdefb27f0030",
|
|
5
|
+
"bytes": 12706861,
|
|
6
|
+
"sourceCommit": "1de2cfe58fcb9a08b6665b2f37aad6bb916c943a",
|
|
7
7
|
"sourceDirty": false,
|
|
8
8
|
"installRecordMatchesLockfile": true,
|
|
9
9
|
"releaseRule": "valid only when two fresh npm ci --ignore-scripts builds on different OSes give the same sha256; installRecordMatchesLockfile true means every entry npm installed equals its package-lock.json entry and every entry not marked optional, devOptional included, is installed: an optional entry (a package for another platform) may be absent",
|
|
@@ -1297,5 +1297,5 @@
|
|
|
1297
1297
|
"version": "1.8.0"
|
|
1298
1298
|
}
|
|
1299
1299
|
],
|
|
1300
|
-
"publishedAt": "2026-10-
|
|
1300
|
+
"publishedAt": "2026-10-24T04:23:52.556Z"
|
|
1301
1301
|
}
|
package/package.json
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "shinjuku-shield",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.94",
|
|
4
4
|
"mcpName": "io.github.ShinjukuStaition/shinjuku-mcp",
|
|
5
5
|
"description": "Shinjuku Shielded, the private x402 facilitator on Solana: the self-custody wallet CLI and its MCP server. Shield, pay, and unshield USDC from any MCP agent, under caps you set.",
|
|
6
|
-
"shinjukuRelease": "
|
|
7
|
-
"shinjukuSha256": "
|
|
6
|
+
"shinjukuRelease": "af5b54d5",
|
|
7
|
+
"shinjukuSha256": "af5b54d5bce11c64a002dca7d59c8593767ddefe4b7177b8ef44cdefb27f0030",
|
|
8
8
|
"license": "SEE LICENSE IN LICENSE.txt",
|
|
9
9
|
"author": "Shinjuku Shielded",
|
|
10
10
|
"homepage": "https://github.com/ShinjukuStaition/shinjuku-mcp#readme",
|
package/shinjuku-wallet.mjs
CHANGED
|
@@ -47225,7 +47225,7 @@ async function rpcFetch(input, init) {
|
|
|
47225
47225
|
rpcNotBefore.set(post.key, Math.max(rpcNotBefore.get(post.key) ?? 0, Date.now() + retryAfterMs(response)));
|
|
47226
47226
|
}
|
|
47227
47227
|
}
|
|
47228
|
-
function
|
|
47228
|
+
function proxiedChild(args, mode, plainProxy, stdio) {
|
|
47229
47229
|
const proxy = withRunTag(mode, plainProxy);
|
|
47230
47230
|
const env = {
|
|
47231
47231
|
...process.env,
|
|
@@ -47237,8 +47237,11 @@ function reexec(args, mode, plainProxy) {
|
|
|
47237
47237
|
delete env[QUIET_RUN_MARK];
|
|
47238
47238
|
const quiet = quietRun(args);
|
|
47239
47239
|
if (quiet) env[QUIET_RUN_MARK] = quiet;
|
|
47240
|
+
return spawn(process.execPath, [...proxiedExecArgv(process.execArgv), process.argv[1], ...args], { env, stdio });
|
|
47241
|
+
}
|
|
47242
|
+
function reexec(args, mode, plainProxy) {
|
|
47240
47243
|
return new Promise((resolvePromise) => {
|
|
47241
|
-
const child =
|
|
47244
|
+
const child = proxiedChild(args, mode, plainProxy, "inherit");
|
|
47242
47245
|
const ignore = () => {
|
|
47243
47246
|
};
|
|
47244
47247
|
const forward = () => child.kill("SIGTERM");
|
|
@@ -47314,7 +47317,12 @@ async function proxyEntry(argv2, run5, { err = (text3) => process.stderr.write(t
|
|
|
47314
47317
|
}
|
|
47315
47318
|
return reexec(options.args, options.mode, options.proxy);
|
|
47316
47319
|
}
|
|
47317
|
-
|
|
47320
|
+
function torChild(argv2, stdio) {
|
|
47321
|
+
const options = proxyOptions(argv2);
|
|
47322
|
+
if (!options.mode) throw new ProxyUsageError("torChild needs --tor or --proxy");
|
|
47323
|
+
return proxiedChild(options.args, options.mode, options.proxy, stdio);
|
|
47324
|
+
}
|
|
47325
|
+
var TOR_HTTP_TUNNEL, TOR_CHECK, PROOF_TIMEOUT_MS, LOCAL_PROOF_TIMEOUT_MS, LOCAL_PROOF_MAX_BYTES, torProvenAt, proxyProvenAt, MARK, TOR_RUN_STARTED_ENV, ownProxyRefused, ONION_V3, RETRY_AFTER_CAP_MS, RETRY_AFTER_FLOOR_MS, RETRY_AFTER_DEFAULT_MS, RPC_NO_ANSWER_LIMIT_MS, RPC_PACING_CAP_MS, PACING_NOTICE_EVERY_MS, PACING_RATE_WINDOW_MS, TOR_MAX_ROTATIONS, runStartedAt, rpcNotBefore, pacingWaiters, pacingSince, pacedMs, rpcAnswered, lastAnswerAt, readSteps, pacingNoticeAt, pacingSamples, torMoves, torCircuitId, torMovesRefused, pendingMove, inTorRun, runNetworkMode, isOnionOrigin, ProxyUsageError, isOnionHost, TOR_EXPERT_BUNDLE, TOR_EXPERT_BUNDLE_SHA256, TUNNEL_LINE, TOR_INSTALL, torStart, OS_NAMES, osKey, torNotRunningMessage, NOTICE, QUIET_RUN_MARK, QUIET_NOTICE, QUIET_TERMINAL_COMMANDS, INFER_SUBCOMMANDS, quietRun, TOR_TROUBLE_LINE, TOR_WAIT_PLAIN, TOR_TROUBLE_PLAIN, TOR_TROUBLE_SAID, quietTorErr, withRunTag, proxyEnv, pacedSoFar, RESENDABLE_METHOD, torCircuit, GLOBAL_DISPATCHER2, laneDispatchers, paymentWarmStop, PROXY_WARNING_FLAG, proxiedExecArgv, proxiedNodeOptions, TOR_FROM_CONFIG_ENV, TOR_FROM_CONFIG_HINT;
|
|
47318
47326
|
var init_proxy = __esm({
|
|
47319
47327
|
"wallet/src/net/proxy.mjs"() {
|
|
47320
47328
|
"use strict";
|
|
@@ -47361,12 +47369,14 @@ var init_proxy = __esm({
|
|
|
47361
47369
|
};
|
|
47362
47370
|
isOnionHost = (host) => /\.onion$/i.test(String(host ?? "").replace(/\.+$/, ""));
|
|
47363
47371
|
TOR_EXPERT_BUNDLE = "15.0.25";
|
|
47372
|
+
TOR_EXPERT_BUNDLE_SHA256 = "c1988c701de2f24f7d098d1d6d7f507b58f27740d097f29c246e0524d639b252";
|
|
47364
47373
|
TUNNEL_LINE = "HTTPTunnelPort 127.0.0.1:9080 IsolateDestAddr";
|
|
47365
47374
|
TOR_INSTALL = Object.freeze({
|
|
47366
|
-
windows: `iwr https://archive.torproject.org/tor-package-archive/torbrowser/${TOR_EXPERT_BUNDLE}/tor-expert-bundle-windows-x86_64-${TOR_EXPERT_BUNDLE}.tar.gz -OutFile $env:TEMP\\tor.tar.gz; mkdir -Force $env:LOCALAPPDATA\\tor | Out-Null; tar -xzf $env:TEMP\\tor.tar.gz -C $env:LOCALAPPDATA\\tor; & $env:LOCALAPPDATA\\tor\\tor\\tor.exe --HTTPTunnelPort '127.0.0.1:9080 IsolateDestAddr' --SocksPort 0`,
|
|
47375
|
+
windows: `iwr https://archive.torproject.org/tor-package-archive/torbrowser/${TOR_EXPERT_BUNDLE}/tor-expert-bundle-windows-x86_64-${TOR_EXPERT_BUNDLE}.tar.gz -OutFile $env:TEMP\\tor.tar.gz; if ((Get-FileHash $env:TEMP\\tor.tar.gz -Algorithm SHA256).Hash -ne '${TOR_EXPERT_BUNDLE_SHA256}') { Remove-Item $env:TEMP\\tor.tar.gz; throw 'The Tor download does not match its pinned sha256, so it was deleted and not run' }; mkdir -Force $env:LOCALAPPDATA\\tor | Out-Null; & $env:SystemRoot\\System32\\tar.exe -xzf $env:TEMP\\tor.tar.gz -C $env:LOCALAPPDATA\\tor; & $env:LOCALAPPDATA\\tor\\tor\\tor.exe --HTTPTunnelPort '127.0.0.1:9080 IsolateDestAddr' --SocksPort 0`,
|
|
47367
47376
|
macos: `brew install tor && echo '${TUNNEL_LINE}' >> "$(brew --prefix)/etc/tor/torrc" && brew services restart tor`,
|
|
47368
47377
|
linux: `sudo apt install -y tor && echo '${TUNNEL_LINE}' | sudo tee -a /etc/tor/torrc && sudo systemctl restart tor`
|
|
47369
47378
|
});
|
|
47379
|
+
torStart = (platform = process.platform) => platform === "win32" ? { where: "PowerShell (keep its window open while the wallet runs)", command: TOR_INSTALL.windows } : platform === "darwin" ? { where: "Terminal", command: TOR_INSTALL.macos } : { where: "a terminal", command: TOR_INSTALL.linux };
|
|
47370
47380
|
OS_NAMES = { windows: "Windows (PowerShell; keep its window open while the wallet runs)", macos: "macOS (Homebrew)", linux: "Linux (Debian or Ubuntu)" };
|
|
47371
47381
|
osKey = (platform) => platform === "win32" ? "windows" : platform === "darwin" ? "macos" : "linux";
|
|
47372
47382
|
torNotRunningMessage = (address5, platform = process.platform) => `tor_not_running: Tor is not running on this machine (nothing answers at ${address5}), so nothing was sent. ${torInstallText(platform)}`;
|
|
@@ -67280,6 +67290,9 @@ var init_errorCodes = __esm({
|
|
|
67280
67290
|
"mcp_setup_switch_failed",
|
|
67281
67291
|
"mcp_tor_unavailable",
|
|
67282
67292
|
"setup_tor_unavailable",
|
|
67293
|
+
// The wallet server behind Tor that the setup server starts after a Tor setup (stdioServer.mjs startTorRelay).
|
|
67294
|
+
"setup_tor_wallet_ended",
|
|
67295
|
+
"setup_tor_wallet_slow",
|
|
67283
67296
|
"wallet_not_set_up",
|
|
67284
67297
|
"shinjuku_setup",
|
|
67285
67298
|
"wallet_status",
|
|
@@ -109970,7 +109983,7 @@ function refusalSay(a, tool, again, npmVersion) {
|
|
|
109970
109983
|
}
|
|
109971
109984
|
if (code2 === "mcp_balance_unknown") return "Nothing was moved yet: the wallet is still reading its private balance. Try again in a minute.";
|
|
109972
109985
|
if (code2 === "mcp_payment_still_open") return "Not paid: a payment for this request is still open. Ask with its request_id for the result.";
|
|
109973
|
-
if (code2 === "mcp_setup_restart_needed") return "The wallet is set up, but
|
|
109986
|
+
if (code2 === "mcp_setup_restart_needed") return "The wallet is set up, but it must reconnect once. Follow the steps below, then try again. Nothing was paid.";
|
|
109974
109987
|
if (code2 === "mcp_restart_needed") return "Nothing was paid. Restart this app, then try again.";
|
|
109975
109988
|
if (/accounts_split/.test(code2) || /accounts_split/.test(detail)) {
|
|
109976
109989
|
return `Nothing was ${tool === "wallet_unshield" ? "sent" : "paid"}. The wallet is getting your balance ready to send; try again in about 1 minute, then once more 2 minutes later.`;
|
|
@@ -110063,10 +110076,17 @@ function refusalSay(a, tool, again, npmVersion) {
|
|
|
110063
110076
|
return str(a.ownAddressCommand) && words(own) <= SAY_MAX_WORDS ? own : head;
|
|
110064
110077
|
}
|
|
110065
110078
|
if (code2 === "mcp_unshield_declined") return "Not sent. The send was not confirmed.";
|
|
110066
|
-
if (code2 === "mcp_setup_declined" && unshown) {
|
|
110067
|
-
return `Not set up. This app cannot show the setup question. Run ${oneTimeCommandLine("setup", npmVersion)} in a terminal, then
|
|
110079
|
+
if (code2 === "mcp_setup_declined" && unshown || code2 === "mcp_setup_needs_terminal") {
|
|
110080
|
+
return `Not set up. This app cannot show the setup question. Run ${oneTimeCommandLine("setup", npmVersion)} in a terminal, then reconnect the wallet.`;
|
|
110068
110081
|
}
|
|
110069
110082
|
if (code2 === "mcp_setup_declined") return "Not set up. The setup was not confirmed; nothing was created.";
|
|
110083
|
+
const setupTool = tool === "shinjuku_setup" || tool === "wallet_status";
|
|
110084
|
+
if (code2 === "tor_not_running" && setupTool && /Tor Browser is open/.test(detail)) {
|
|
110085
|
+
return "Not set up: Tor Browser is open, but the wallet needs its own Tor. Start it with the command below, or set up without Tor.";
|
|
110086
|
+
}
|
|
110087
|
+
if (code2 === "tor_not_running" && setupTool) return "Not set up: Tor is not running on this computer. Start it with the command below and ask again, or set up without Tor.";
|
|
110088
|
+
if (code2 === "wallet_not_set_up" && tool === "x402_discover") return "Not searched yet. Set up the wallet first: setup asks one question, whether to use Tor, which hides your IP address.";
|
|
110089
|
+
if (code2 === "wallet_not_set_up") return "The wallet is not set up yet, so nothing was paid. Ask to set up the wallet first.";
|
|
110070
110090
|
if (code2 === "mcp_tool_disabled") return "Nothing was paid or moved. This tool is off; only your owner can turn it on when starting the wallet.";
|
|
110071
110091
|
if (code2 === "mcp_unshield_to_invalid") {
|
|
110072
110092
|
return "Not sent. That address has no USDC account yet. Ask for a Solana address that already holds USDC, like a Phantom address.";
|
|
@@ -127172,7 +127192,7 @@ ${canonical5}`;
|
|
|
127172
127192
|
} catch {
|
|
127173
127193
|
onion = false;
|
|
127174
127194
|
}
|
|
127175
|
-
return { network: mode === "tor" ? { mode: "tor", detail: `every request of this wallet goes through Tor (checked at start)${onion ? "; the facilitator is reached over its onion service, so no Tor exit sees those requests" : ""}` } : mode === "proxy" ? { mode: "proxy", detail: "every request of this wallet goes through the proxy in its launch line (--proxy); it is not checked as Tor" } : { mode: "direct", detail:
|
|
127195
|
+
return { network: mode === "tor" ? { mode: "tor", detail: `every request of this wallet goes through Tor (checked at start)${onion ? "; the facilitator is reached over its onion service, so no Tor exit sees those requests" : ""}` } : mode === "proxy" ? { mode: "proxy", detail: "every request of this wallet goes through the proxy in its launch line (--proxy); it is not checked as Tor" } : { mode: "direct", detail: `no Tor: the facilitator, the RPC provider and each seller see this computer's IP address. To hide it, the user runs ${terminalCommand("setup --yes --prefer-tor")} once in a terminal (it records Tor and checks the wallet's files again; nothing else changes), then restarts this app` } };
|
|
127176
127196
|
}
|
|
127177
127197
|
function sayFirst(fields, tool, autoId) {
|
|
127178
127198
|
let say6 = sayFor(fields, { tool, npmVersion });
|
|
@@ -132573,9 +132593,9 @@ ${canonical5}`;
|
|
|
132573
132593
|
const moreTokens = (maxTokens) => Math.max(1024, 2 * maxTokens);
|
|
132574
132594
|
const torRefusal = () => refuse12(
|
|
132575
132595
|
"inference_tor_required",
|
|
132576
|
-
"inference sends the prompt to the AI provider and the company that runs the model, so this wallet sends it only
|
|
132577
|
-
//
|
|
132578
|
-
`Tell the user
|
|
132596
|
+
"inference sends the prompt to the AI provider and the company that runs the model, so this wallet sends it only over Tor (or a proxy the user trusts), where they see the exit and not this machine's IP. This wallet runs without Tor; nothing was sent or paid",
|
|
132597
|
+
// docs/mcp/TOR.md: no flag name, port number or torrc in an agent-app answer outside the one command (here the setup line).
|
|
132598
|
+
`Tell the user: private AI runs only over Tor, and this wallet runs without Tor. To turn Tor on, the user runs ${terminalCommand("setup --yes --prefer-tor")} once in a terminal (it records Tor and checks the wallet's files again; nothing else changes), then reconnects the wallet (${RESTART_STEPS}), and asks again`
|
|
132579
132599
|
);
|
|
132580
132600
|
const inferenceModels = {
|
|
132581
132601
|
name: "inference_models",
|
|
@@ -133433,7 +133453,7 @@ function createSetupTools({
|
|
|
133433
133453
|
log = () => {
|
|
133434
133454
|
},
|
|
133435
133455
|
activate,
|
|
133436
|
-
startWaitMs =
|
|
133456
|
+
startWaitMs = SETUP_ANSWER_WAIT_MS,
|
|
133437
133457
|
elicitTimeoutMs = ELICIT_TIMEOUT_MS,
|
|
133438
133458
|
discoverCacheDir = join32(setupHome(), "discover-cache"),
|
|
133439
133459
|
npmVersion
|
|
@@ -133460,6 +133480,17 @@ function createSetupTools({
|
|
|
133460
133480
|
recoveryFile ? { recoveryFile } : void 0
|
|
133461
133481
|
);
|
|
133462
133482
|
}
|
|
133483
|
+
if (job.state === "no_tor") {
|
|
133484
|
+
const torBrowser = job.torBrowser === true;
|
|
133485
|
+
job = void 0;
|
|
133486
|
+
const start = torStart();
|
|
133487
|
+
return refuse12(
|
|
133488
|
+
"tor_not_running",
|
|
133489
|
+
`the user chose Tor in the setup question, and Tor is not running on this computer (nothing answers at the wallet's local Tor connection${torBrowser ? "; Tor Browser is open, but it does not give the kind of connection the wallet needs" : ""}); nothing was created or paid`,
|
|
133490
|
+
`Tell the user: ${torBrowser ? "Tor Browser is open, but the wallet needs its own Tor connection. Run the command below." : "Tor hides your IP address, and it is not running on this computer."} Show torStartCommand in one code block, to copy into ${start.where}: this command downloads Tor and starts it for the wallet (more about Tor: https://www.torproject.org). If you can run commands here, offer to run it for the user. Then the user asks again to set up the wallet: it then sets up over Tor and always runs over Tor. Or, to set up without Tor, the user asks again and unticks "${SETUP_TOR_TITLE}" in the question`,
|
|
133491
|
+
{ torStartCommand: start.command }
|
|
133492
|
+
);
|
|
133493
|
+
}
|
|
133463
133494
|
if (job.state === "declined") {
|
|
133464
133495
|
const unshown = job.unshown === true;
|
|
133465
133496
|
job = void 0;
|
|
@@ -133487,19 +133518,11 @@ function createSetupTools({
|
|
|
133487
133518
|
wallet: summary.wallet.status,
|
|
133488
133519
|
...summary.wallet.recoveryFile ? { recoveryFile: summary.wallet.recoveryFile, solanaFeePayer: summary.wallet.solanaFeePayer } : {}
|
|
133489
133520
|
});
|
|
133490
|
-
if (job.state === "restart" && privateInference && job.failure.error === "setup_tor_needs_restart") {
|
|
133491
|
-
return json3({
|
|
133492
|
-
...doneFacts(job.summary),
|
|
133493
|
-
privateInference: true,
|
|
133494
|
-
restartNeeded: true,
|
|
133495
|
-
next: `The wallet is ready.${recoveryNext(job.summary)}${PRIVATE_INFERENCE_NEXT}`
|
|
133496
|
-
});
|
|
133497
|
-
}
|
|
133498
133521
|
if (job.state === "restart") {
|
|
133499
133522
|
return refuse12(
|
|
133500
133523
|
"mcp_setup_restart_needed",
|
|
133501
133524
|
`the wallet is set up, but this MCP server could not start the wallet tools in place (reason: ${job.failure.detail}); nothing was paid or moved`,
|
|
133502
|
-
|
|
133525
|
+
`Tell the user: ${RESTART_STEPS}; the wallet tools start then`,
|
|
133503
133526
|
{ stage: "done" }
|
|
133504
133527
|
);
|
|
133505
133528
|
}
|
|
@@ -133507,15 +133530,29 @@ function createSetupTools({
|
|
|
133507
133530
|
const summary = job.summary;
|
|
133508
133531
|
return json3({
|
|
133509
133532
|
...doneFacts(summary),
|
|
133533
|
+
...summary.tor === true ? { tor: true } : {},
|
|
133510
133534
|
...privateInference ? { privateInference: true } : {},
|
|
133511
|
-
next: `The wallet tools are live in this server: call wallet_balance.${recoveryNext(summary)} To add funds, call wallet_shield after the user sends USDC to solanaFeePayer (no SOL needed), or call wallet_add_funds: it gives a one-time address for any amount from 0.01 USDC. After the user sends USDC there, ask for the balance once: the wallet then sees the USDC and makes it private by itself after a random privacy wait of a few minutes
|
|
133535
|
+
next: `The wallet tools are live in this server: call wallet_balance.${recoveryNext(summary)}` + (summary.tor === true ? " Setup ran over Tor, and the wallet runs over Tor: the servers it talks to do not see this computer's IP address." : "") + (summary.wallet.solanaFeePayer ? " To add funds, call wallet_shield after the user sends USDC to solanaFeePayer (no SOL needed), or call" : " To add funds, call") + " wallet_add_funds: it gives a one-time address for any amount from 0.01 USDC. After the user sends USDC there, ask for the balance once: the wallet then sees the USDC and makes it private by itself after a random privacy wait of a few minutes." + (privateInference ? " Private inference is on: after funding, call inference_chat (with no prompt it lists the models and prices); if this server was started with --no-tor, restart it without --no-tor so it runs behind Tor (inference_chat refuses until then)." : "")
|
|
133512
133536
|
});
|
|
133513
133537
|
}
|
|
133538
|
+
if (job.state === "confirming") return json3({ say: SETUP_CONFIRMING_SAY, ok: true, stage: "confirming", next: SETUP_CONFIRMING_NEXT });
|
|
133514
133539
|
return json3({ ok: true, stage: job.stage, ...job.progress ? { progress: job.progress } : {}, next: SETUP_POLL_NEXT });
|
|
133515
133540
|
}
|
|
133541
|
+
async function waitForAnswer({ progress: progress3, signal } = {}) {
|
|
133542
|
+
if (job?.state !== "confirming") return;
|
|
133543
|
+
const cancelled = signal ? new Promise((resolve41) => {
|
|
133544
|
+
if (signal.aborted) resolve41();
|
|
133545
|
+
else signal.addEventListener("abort", resolve41, { once: true });
|
|
133546
|
+
}) : void 0;
|
|
133547
|
+
await waitOrProgress(
|
|
133548
|
+
[job.answered, ...cancelled ? [cancelled] : []],
|
|
133549
|
+
startWaitMs,
|
|
133550
|
+
{ progress: progress3, message: "waiting for the user's answer in the setup question" }
|
|
133551
|
+
);
|
|
133552
|
+
}
|
|
133516
133553
|
async function confirm2(plan) {
|
|
133517
133554
|
const limit = (atomic4) => String(atomic4) === NO_LIMIT_ATOMIC2 ? "no limit" : `${usdc9(atomic4)} USDC`;
|
|
133518
|
-
const message = `Create a Shinjuku Shield wallet on this machine (spending limits: ${limit(plan.maxPaymentAtomic)} per payment, ${limit(plan.maxSessionAtomic)} in any 24 hours)? The keys and a random passphrase stay in private files on this machine
|
|
133555
|
+
const message = `Create a Shinjuku Shield wallet on this machine (spending limits: ${limit(plan.maxPaymentAtomic)} per payment, ${limit(plan.maxSessionAtomic)} in any 24 hours)? The keys and a random passphrase stay in private files on this machine.`;
|
|
133519
133556
|
const askedAt = Date.now();
|
|
133520
133557
|
try {
|
|
133521
133558
|
const answer = await client.elicit({
|
|
@@ -133524,19 +133561,24 @@ function createSetupTools({
|
|
|
133524
133561
|
type: "object",
|
|
133525
133562
|
properties: {
|
|
133526
133563
|
confirm: { type: "boolean", title: "Create the wallet", description: message, default: true },
|
|
133527
|
-
|
|
133564
|
+
tor: { type: "boolean", title: SETUP_TOR_TITLE, description: `${SETUP_TOR_WHY} Setup downloads the wallet's files over Tor too.`, default: true },
|
|
133565
|
+
privateInference: { type: "boolean", title: "Use private inference for your AI now", description: `${PRIVATE_INFERENCE_WHY} It needs Tor, so it turns Tor on.`, default: false }
|
|
133528
133566
|
},
|
|
133529
133567
|
required: ["confirm"]
|
|
133530
133568
|
}
|
|
133531
133569
|
}, elicitTimeoutMs);
|
|
133532
133570
|
const ok = answer?.action === "accept" && answer?.content?.confirm !== false;
|
|
133533
|
-
|
|
133571
|
+
const privateInference = answer?.content?.privateInference === true;
|
|
133572
|
+
return { ok, privateInference, tor: answer?.content?.tor !== false || privateInference, unshown: !ok && elicitUnshown(askedAt, answer) };
|
|
133534
133573
|
} catch (error) {
|
|
133535
|
-
return { ok: false, privateInference: false, unshown: error?.timedOut !== true && elicitUnshown(askedAt) };
|
|
133574
|
+
return { ok: false, privateInference: false, tor: false, unshown: error?.timedOut !== true && elicitUnshown(askedAt) };
|
|
133536
133575
|
}
|
|
133537
133576
|
}
|
|
133538
|
-
async function begin() {
|
|
133539
|
-
if (job)
|
|
133577
|
+
async function begin(ctx) {
|
|
133578
|
+
if (job) {
|
|
133579
|
+
await waitForAnswer(ctx);
|
|
133580
|
+
return status();
|
|
133581
|
+
}
|
|
133540
133582
|
const plan = setup.plan();
|
|
133541
133583
|
if (!plan.ok) return refuse12(plan.code, plan.detail, `Nothing was created. ${setupTerminalNext()}, on a machine that can run the proof tools (Linux, or Windows with WSL)`);
|
|
133542
133584
|
if (!client?.canElicit?.()) {
|
|
@@ -133546,19 +133588,33 @@ function createSetupTools({
|
|
|
133546
133588
|
setupTerminalNext()
|
|
133547
133589
|
);
|
|
133548
133590
|
}
|
|
133549
|
-
|
|
133591
|
+
let answered2;
|
|
133592
|
+
job = { state: "confirming", stage: "confirming", answered: new Promise((resolve41) => {
|
|
133593
|
+
answered2 = resolve41;
|
|
133594
|
+
}) };
|
|
133550
133595
|
const started = (async () => {
|
|
133551
133596
|
const answer = await confirm2(plan);
|
|
133552
133597
|
if (!answer.ok) {
|
|
133553
133598
|
job.state = "declined";
|
|
133599
|
+
job.stage = "declined";
|
|
133554
133600
|
job.unshown = answer.unshown;
|
|
133555
133601
|
log(`MCP_SETUP_DECLINED${answer.unshown ? " unshown=true" : ""}`);
|
|
133602
|
+
answered2();
|
|
133603
|
+
return;
|
|
133604
|
+
}
|
|
133605
|
+
if (answer.tor && !inTorRun() && await localTorProof(TOR_HTTP_TUNNEL) === "refused") {
|
|
133606
|
+
job.torBrowser = await localTorProof(TOR_BROWSER_PORT) !== "refused";
|
|
133607
|
+
job.state = "no_tor";
|
|
133608
|
+
job.stage = "no_tor";
|
|
133609
|
+
log(`MCP_SETUP_NO_TOR${job.torBrowser ? " tor-browser=open" : ""}`);
|
|
133610
|
+
answered2();
|
|
133556
133611
|
return;
|
|
133557
133612
|
}
|
|
133558
133613
|
job.state = "running";
|
|
133559
133614
|
job.stage = "starting";
|
|
133615
|
+
answered2();
|
|
133560
133616
|
job.privateInference = answer.privateInference;
|
|
133561
|
-
log(
|
|
133617
|
+
log(`MCP_SETUP_STARTED tor=${answer.tor}`);
|
|
133562
133618
|
try {
|
|
133563
133619
|
job.summary = await setup.run((stage, progress3) => {
|
|
133564
133620
|
if (stage === "wallet-created" && progress3?.recoveryFile) {
|
|
@@ -133567,10 +133623,11 @@ function createSetupTools({
|
|
|
133567
133623
|
}
|
|
133568
133624
|
job.stage = stage;
|
|
133569
133625
|
job.progress = progress3;
|
|
133570
|
-
}, { privateInference: answer.privateInference });
|
|
133626
|
+
}, { privateInference: answer.privateInference, tor: answer.tor });
|
|
133571
133627
|
} catch (error) {
|
|
133572
133628
|
job.failure = failure2(error, "mcp_setup_failed");
|
|
133573
133629
|
job.state = "failed";
|
|
133630
|
+
job.stage = "failed";
|
|
133574
133631
|
log(`MCP_SETUP_FAILED ${job.failure.error}`);
|
|
133575
133632
|
return;
|
|
133576
133633
|
}
|
|
@@ -133581,22 +133638,21 @@ function createSetupTools({
|
|
|
133581
133638
|
} catch (error) {
|
|
133582
133639
|
job.failure = failure2(error, "mcp_setup_switch_failed");
|
|
133583
133640
|
job.state = "restart";
|
|
133641
|
+
job.stage = "done";
|
|
133584
133642
|
log(`MCP_SETUP_SWITCH_FAILED ${job.failure.error}`);
|
|
133585
133643
|
}
|
|
133586
133644
|
})();
|
|
133587
|
-
|
|
133588
|
-
|
|
133589
|
-
timer.unref?.();
|
|
133590
|
-
})]);
|
|
133645
|
+
started.then(answered2, answered2);
|
|
133646
|
+
await waitForAnswer(ctx);
|
|
133591
133647
|
return status();
|
|
133592
133648
|
}
|
|
133593
133649
|
const setupTool = {
|
|
133594
133650
|
name: "shinjuku_setup",
|
|
133595
133651
|
title: "Set up the Shinjuku Shield wallet",
|
|
133596
|
-
description: "The wallet is not set up on this machine yet. Call this when the user wants to pay an x402 URL, check a balance, or shield USDC. It asks the user to confirm in this client (with the spending caps), then creates a self-custody wallet on this machine (keys and a random passphrase in private local files; no tool takes or returns them), downloads and checks the proof tools (about 191 MB, minutes), and switches this server to the wallet tools. Takes no arguments. Call it again with no arguments as `next` says for the stage (confirming, platform, release, passphrase, wallet, proof-tools, config, done). A decline creates nothing (mcp_setup_declined). A client that cannot confirm is refused (mcp_setup_needs_terminal) with the terminal command; a client that declines at once without showing the dialog gets mcp_setup_declined with the same terminal command.",
|
|
133652
|
+
description: "The wallet is not set up on this machine yet. Call this when the user wants to pay an x402 URL, check a balance, or shield USDC. It asks the user to confirm in this client (with the spending caps), then creates a self-custody wallet on this machine (keys and a random passphrase in private local files; no tool takes or returns them), downloads and checks the proof tools (about 191 MB, minutes), and switches this server to the wallet tools. Takes no arguments. Call it again with no arguments as `next` says for the stage (confirming, tor, platform, release, passphrase, wallet, proof-tools, config, done; declined, no_tor or failed: the setup ended, and this call answers why). A decline creates nothing (mcp_setup_declined). A client that cannot confirm is refused (mcp_setup_needs_terminal) with the terminal command; a client that declines at once without showing the dialog gets mcp_setup_declined with the same terminal command.",
|
|
133597
133653
|
inputSchema: { type: "object", properties: {}, additionalProperties: false },
|
|
133598
133654
|
annotations: { readOnlyHint: false, destructiveHint: false, idempotentHint: true, openWorldHint: true },
|
|
133599
|
-
run: () => begin()
|
|
133655
|
+
run: (args, ctx) => begin(ctx)
|
|
133600
133656
|
};
|
|
133601
133657
|
const statusTool = {
|
|
133602
133658
|
name: "wallet_status",
|
|
@@ -133605,6 +133661,7 @@ function createSetupTools({
|
|
|
133605
133661
|
inputSchema: { type: "object", properties: {}, additionalProperties: false },
|
|
133606
133662
|
annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false },
|
|
133607
133663
|
run: async () => {
|
|
133664
|
+
if (job && ["failed", "no_tor", "declined", "restart"].includes(job.state)) return status();
|
|
133608
133665
|
let missing;
|
|
133609
133666
|
try {
|
|
133610
133667
|
missing = setup.missing();
|
|
@@ -133616,7 +133673,7 @@ function createSetupTools({
|
|
|
133616
133673
|
setUp: missing.length === 0 && (!job || job.state === "done"),
|
|
133617
133674
|
missing,
|
|
133618
133675
|
...job ? { stage: job.stage } : {},
|
|
133619
|
-
next: job ? SETUP_POLL_NEXT : "call shinjuku_setup when the user wants to use the wallet"
|
|
133676
|
+
next: job ? job.state === "confirming" ? SETUP_CONFIRMING_NEXT : SETUP_POLL_NEXT : "call shinjuku_setup when the user wants to use the wallet"
|
|
133620
133677
|
});
|
|
133621
133678
|
}
|
|
133622
133679
|
};
|
|
@@ -133628,11 +133685,11 @@ function createSetupTools({
|
|
|
133628
133685
|
annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false },
|
|
133629
133686
|
// Hidden after setup are hidden here too (callable by name, not listed).
|
|
133630
133687
|
...MCP_HIDDEN_TOOL_NAMES.includes(name) ? { hidden: true } : {},
|
|
133631
|
-
// After setup, a switch that could not happen
|
|
133688
|
+
// After setup, a switch that could not happen (the wallet did not open, or its server behind Tor did not start) keeps every money tool refused.
|
|
133632
133689
|
run: async () => job?.state === "restart" ? refuse12(
|
|
133633
133690
|
"mcp_setup_restart_needed",
|
|
133634
133691
|
`the wallet is set up, but this MCP server could not start the wallet tools in place (reason: ${job.failure.detail}); nothing was paid or moved`,
|
|
133635
|
-
|
|
133692
|
+
`Tell the user: ${RESTART_STEPS}; the wallet tools start then`,
|
|
133636
133693
|
{ stage: "done" }
|
|
133637
133694
|
) : refuse12(
|
|
133638
133695
|
"wallet_not_set_up",
|
|
@@ -133646,9 +133703,32 @@ function createSetupTools({
|
|
|
133646
133703
|
description: "The wallet is set up and its tools are live. Answers the setup summary; it never creates a second wallet.",
|
|
133647
133704
|
run: async () => job ? status() : json3({ ok: true, stage: "done", walletReady: true, next: "call wallet_balance" })
|
|
133648
133705
|
};
|
|
133649
|
-
|
|
133706
|
+
const discoverNow = inTorRun();
|
|
133707
|
+
const discoverAfterSetup = () => {
|
|
133708
|
+
const tool = notSetUp("x402_discover");
|
|
133709
|
+
return {
|
|
133710
|
+
...tool,
|
|
133711
|
+
description: "Finds x402 sellers after setup. Before setup it sends nothing: setup first asks the user whether to use Tor, which hides this computer's IP address from the servers that list sellers. Call shinjuku_setup first.",
|
|
133712
|
+
run: async (args) => job?.state === "restart" ? tool.run(args) : refuse12(
|
|
133713
|
+
"wallet_not_set_up",
|
|
133714
|
+
"x402_discover asks Shinjuku and other servers for their seller lists, and they would see this computer's IP address before the user chose whether to use Tor; nothing was sent",
|
|
133715
|
+
"Tell the user: set up the wallet first; setup asks one question, whether to use Tor (it hides your IP address). Then call shinjuku_setup; after setup, call x402_discover again",
|
|
133716
|
+
...job ? [{ stage: job.stage }] : []
|
|
133717
|
+
)
|
|
133718
|
+
};
|
|
133719
|
+
};
|
|
133720
|
+
const sayOnRefusal = (tool) => ({ ...tool, run: async (args, ctx) => {
|
|
133721
|
+
const output2 = await tool.run(args, ctx);
|
|
133722
|
+
const text3 = typeof output2?.text === "string" ? output2.text : output2?.content?.[0]?.text;
|
|
133723
|
+
return typeof text3 === "string" && /^\s*\{\s*"ok"\s*:\s*false\b/.test(text3) ? addSay(output2, tool.name, { npmVersion }) : output2;
|
|
133724
|
+
} });
|
|
133725
|
+
const discover = discoverNow ? withSay(discoverTool(discoverCacheDir), { npmVersion }) : sayOnRefusal(discoverAfterSetup());
|
|
133726
|
+
return {
|
|
133727
|
+
tools: [sayOnRefusal(setupTool), sayOnRefusal(statusTool), ...MCP_TOOL_NAMES.map((name) => name !== "x402_discover" ? sayOnRefusal(notSetUp(name)) : discover)],
|
|
133728
|
+
doneTool: sayOnRefusal(doneTool)
|
|
133729
|
+
};
|
|
133650
133730
|
}
|
|
133651
|
-
var import_web3133, shownCaps, RELEASE_RETRY_MS, STAGE_WORDS, stageWords, INTERNAL_BALANCE_DETAIL, shownBreakdown, sessionLeftShown, TOKEN_UNIT_TOOLS, RESOURCE_PAYMENT_WAL_PREFIX2, POOL_LAYOUT_CODE, POOL_LAYOUT_UPDATE, USEPOD_VIA_INFERENCE_CHAT, SEND_RUNS_ON, DEPOSIT_RUNS_ON, CLI_FUNDS_PLAN_PREFIX, CLI_FUNDS_SCHEMA, SELF_PAY_ORIGIN3, REQUEST_ID4, POSITIVE_ATOMIC6, PRIVATE_HOST3, FORBIDDEN_HEADERS3, MAX_BODY_BYTES2, PREVIEW_TIMEOUT_MS, PREVIEW_SELLER_READ_MS, CALL_BUDGET_MS, budgetLeft, MONEY_FIRST_ANSWER_MS, BALANCE_AFTER_LANDING_MS, JOIN_CALL_MAX_MS, JOIN_NUDGE_QUIET_MS, JOIN_STEP_MS, sleep2, PROGRESS_EVERY_MS2, READ_BUDGET_MS, UNPAID_TOR_TRY_MS, UNPAID_CLEAR_MS, READ_BUDGET_TOOLS, FLOAT_BUSY_CODES, RETRY_MARGIN_MS, ASK_PAY_CODES, runningNpmVersion, terminalCommand, capPlaceWords, capRaiseText, cheaperSellerText, limitNext, SAFE_TEXT, MCP_TOOL_ALIASES, POOL_SWITCH_WHY, POOL_SWITCH_NEXT, SWITCH_STATES, quietSwitch, switchKey, ATOMIC_TEXT, FLOAT_ID, ANSWERED_EXIT_RETRY_MS, ANSWERED_EXIT_UNCONFIRMED_MS, ANSWERED_EXIT_RETRY_WINDOW_MS, ANSWERED_EXIT_CLOSED, switchAmount, switchEta, switchRows, OWNER_CAP_CODES, JOIN_END_MCP, JOIN_END_TERMINAL_LIBRARY, JOIN_RETRY_BACKOFF_MS, WALLET_CAP_FIX, MCP_CAP_FIX, capFix, ownerOnlyNext, mcpNext, CONFIDENTIAL_RETIRED, json3, answerResult, discoverTool, refuse12, publicOffer, FLOAT_PAID_CODES, FLOAT_PRIVATE_LEG, floatStillSettling, MONEY_ID2, toRecordId, linkKindOf, moneyId, REFUSED_CODES, refusedCodeOf, PLAIN_REASONS, plainReason, KEPT_SEND_TRIES, shownId, isSplitSend, sendPartId, PROMISED_NEXT, PUBLIC_READ_TIMEOUT_MS, RECIPIENT_CHECK_TIMEOUT_MS, withTimeout, ownKey, readFailure, OWN_KEY_TOKENS_MAX, OWN_TOKENS_GRACE_MS, tokenAmountText, elsewhereId, AGENT_ID_SCHEMA, agentIdName, minutesText2, ageWords2, DEPOSIT_SENT_STATES, depositLanded, usdcText2, walkWalletHistory, REFRESH_LEASE_WALK_MS, HOME_MARKS_SETTLED_MS2, AUTO_BACKUPS_KEPT, AUTO_BACKUP_NAME, AUTO_BACKUP_VERIFIED, FRONTED_SETTLE_MARGIN_SLOTS, BALANCE_REFRESH_WAIT_MS, BALANCE_REFRESH_GRACE_MS, BALANCE_REFRESH_LONG_MS, INBOUND_REFRESH_AGE_MS, CAP_BALANCE_WAIT_MS, CAP_BALANCE_RETRY_MS, REFRESH_RETRY_MS, FINALITY_POLL_MS, FINALITY_WAIT_MS, FINALITY_REFRESH_LIMIT_MS, POOL_WATCH_MS, POOL_WATCH_POLL_MS, EARLY_BALANCE_DELAY_MS, FINALITY_SETTLE_WINDOW_SLOTS, PUBLIC_READ_ANSWER_MS, SWITCH_WAIT_MS, UNSHIELD_TO_NO_USDC_DETAIL, UNSHIELD_TO_INVALID_NEXT, INFERENCE_MIN_MAX_TOKENS, ELICIT_TIMEOUT_MS, ELICIT_UNSHOWN_MS, elicitUnshown, POLL_SECONDS3, TRANSFER_CHANGE_READ_MS, TEMP_CLEAN_DELAY_MS, KEPT_ON_DISK, MAX_SHIELDED_BALANCE_ATOMIC, receiveGenerator, MCP_TOOL_NAMES, MCP_HIDDEN_TOOL_NAMES, setupTerminalNext, SETUP_POLL_NEXT, PRIVATE_INFERENCE_WHY,
|
|
133731
|
+
var import_web3133, shownCaps, RELEASE_RETRY_MS, STAGE_WORDS, stageWords, INTERNAL_BALANCE_DETAIL, shownBreakdown, sessionLeftShown, TOKEN_UNIT_TOOLS, RESOURCE_PAYMENT_WAL_PREFIX2, POOL_LAYOUT_CODE, POOL_LAYOUT_UPDATE, USEPOD_VIA_INFERENCE_CHAT, SEND_RUNS_ON, DEPOSIT_RUNS_ON, CLI_FUNDS_PLAN_PREFIX, CLI_FUNDS_SCHEMA, SELF_PAY_ORIGIN3, REQUEST_ID4, POSITIVE_ATOMIC6, PRIVATE_HOST3, FORBIDDEN_HEADERS3, MAX_BODY_BYTES2, PREVIEW_TIMEOUT_MS, PREVIEW_SELLER_READ_MS, CALL_BUDGET_MS, budgetLeft, MONEY_FIRST_ANSWER_MS, BALANCE_AFTER_LANDING_MS, JOIN_CALL_MAX_MS, JOIN_NUDGE_QUIET_MS, JOIN_STEP_MS, sleep2, PROGRESS_EVERY_MS2, READ_BUDGET_MS, UNPAID_TOR_TRY_MS, UNPAID_CLEAR_MS, READ_BUDGET_TOOLS, FLOAT_BUSY_CODES, RETRY_MARGIN_MS, ASK_PAY_CODES, runningNpmVersion, terminalCommand, capPlaceWords, capRaiseText, cheaperSellerText, limitNext, SAFE_TEXT, MCP_TOOL_ALIASES, POOL_SWITCH_WHY, POOL_SWITCH_NEXT, SWITCH_STATES, quietSwitch, switchKey, ATOMIC_TEXT, FLOAT_ID, ANSWERED_EXIT_RETRY_MS, ANSWERED_EXIT_UNCONFIRMED_MS, ANSWERED_EXIT_RETRY_WINDOW_MS, ANSWERED_EXIT_CLOSED, switchAmount, switchEta, switchRows, OWNER_CAP_CODES, JOIN_END_MCP, JOIN_END_TERMINAL_LIBRARY, JOIN_RETRY_BACKOFF_MS, WALLET_CAP_FIX, MCP_CAP_FIX, capFix, ownerOnlyNext, mcpNext, CONFIDENTIAL_RETIRED, json3, answerResult, discoverTool, refuse12, publicOffer, FLOAT_PAID_CODES, FLOAT_PRIVATE_LEG, floatStillSettling, MONEY_ID2, toRecordId, linkKindOf, moneyId, REFUSED_CODES, refusedCodeOf, PLAIN_REASONS, plainReason, KEPT_SEND_TRIES, shownId, isSplitSend, sendPartId, PROMISED_NEXT, PUBLIC_READ_TIMEOUT_MS, RECIPIENT_CHECK_TIMEOUT_MS, withTimeout, ownKey, readFailure, OWN_KEY_TOKENS_MAX, OWN_TOKENS_GRACE_MS, tokenAmountText, elsewhereId, AGENT_ID_SCHEMA, agentIdName, minutesText2, ageWords2, DEPOSIT_SENT_STATES, depositLanded, usdcText2, walkWalletHistory, REFRESH_LEASE_WALK_MS, HOME_MARKS_SETTLED_MS2, AUTO_BACKUPS_KEPT, AUTO_BACKUP_NAME, AUTO_BACKUP_VERIFIED, FRONTED_SETTLE_MARGIN_SLOTS, BALANCE_REFRESH_WAIT_MS, BALANCE_REFRESH_GRACE_MS, BALANCE_REFRESH_LONG_MS, INBOUND_REFRESH_AGE_MS, CAP_BALANCE_WAIT_MS, CAP_BALANCE_RETRY_MS, REFRESH_RETRY_MS, FINALITY_POLL_MS, FINALITY_WAIT_MS, FINALITY_REFRESH_LIMIT_MS, POOL_WATCH_MS, POOL_WATCH_POLL_MS, EARLY_BALANCE_DELAY_MS, FINALITY_SETTLE_WINDOW_SLOTS, PUBLIC_READ_ANSWER_MS, SWITCH_WAIT_MS, UNSHIELD_TO_NO_USDC_DETAIL, UNSHIELD_TO_INVALID_NEXT, INFERENCE_MIN_MAX_TOKENS, ELICIT_TIMEOUT_MS, ELICIT_UNSHOWN_MS, elicitUnshown, POLL_SECONDS3, TRANSFER_CHANGE_READ_MS, TEMP_CLEAN_DELAY_MS, KEPT_ON_DISK, MAX_SHIELDED_BALANCE_ATOMIC, receiveGenerator, MCP_TOOL_NAMES, MCP_HIDDEN_TOOL_NAMES, setupTerminalNext, SETUP_POLL_NEXT, SETUP_ANSWER_WAIT_MS, SETUP_CONFIRMING_SAY, SETUP_CONFIRMING_NEXT, PRIVATE_INFERENCE_WHY, RESTART_STEPS, TOR_BROWSER_PORT, SETUP_TOR_TITLE, SETUP_TOR_WHY;
|
|
133652
133732
|
var init_tools = __esm({
|
|
133653
133733
|
"wallet/src/mcp/tools.mjs"() {
|
|
133654
133734
|
"use strict";
|
|
@@ -134043,7 +134123,7 @@ var init_tools = __esm({
|
|
|
134043
134123
|
UNSHIELD_TO_INVALID_NEXT = "Nothing was sent. Tell the user: a Shinjuku wallet can send only to an address that already holds USDC, and a Shinjuku wallet's one-time add-funds address cannot be paid from a Shinjuku wallet yet. Ask the person for a Solana address that already holds USDC (for example their Phantom address) and call wallet_unshield with it, or pay the link from a normal Solana wallet instead";
|
|
134044
134124
|
INFERENCE_MIN_MAX_TOKENS = 256;
|
|
134045
134125
|
ELICIT_TIMEOUT_MS = 5 * 6e4;
|
|
134046
|
-
ELICIT_UNSHOWN_MS =
|
|
134126
|
+
ELICIT_UNSHOWN_MS = 500;
|
|
134047
134127
|
elicitUnshown = (askedAt, answer) => Date.now() - askedAt < ELICIT_UNSHOWN_MS && answer?.action !== "accept";
|
|
134048
134128
|
POLL_SECONDS3 = 30;
|
|
134049
134129
|
TRANSFER_CHANGE_READ_MS = 2e3;
|
|
@@ -134081,10 +134161,16 @@ var init_tools = __esm({
|
|
|
134081
134161
|
"inference_models",
|
|
134082
134162
|
"wallet_receive_shielded"
|
|
134083
134163
|
]);
|
|
134084
|
-
setupTerminalNext = () => `Tell the user to run \`${terminalCommand("setup")}\` in a terminal on this machine, then
|
|
134164
|
+
setupTerminalNext = () => `Tell the user to run \`${terminalCommand("setup")}\` in a terminal on this machine, then reconnect the wallet (${RESTART_STEPS})`;
|
|
134085
134165
|
SETUP_POLL_NEXT = `call shinjuku_setup again in ${POLL_SECONDS3} s for the status (it never creates a second wallet)`;
|
|
134166
|
+
SETUP_ANSWER_WAIT_MS = CALL_BUDGET_MS;
|
|
134167
|
+
SETUP_CONFIRMING_SAY = "Answer the setup box on your screen. The wallet waits for your answer.";
|
|
134168
|
+
SETUP_CONFIRMING_NEXT = "The setup question is open in this app: tell the user to answer it. Call shinjuku_setup again at once (it waits for the answer and then gives the result); do not end the turn. It never creates a second wallet";
|
|
134086
134169
|
PRIVATE_INFERENCE_WHY = "Your agent then buys AI answers from an AI provider, paid from your private balance over Tor; the AI provider and the company that runs the model see the prompt, not who paid.";
|
|
134087
|
-
|
|
134170
|
+
RESTART_STEPS = "In Claude Code: type /mcp, pick shinjuku-shielded, and choose Reconnect. In Claude Desktop: quit it and open it again. In another app: restart it";
|
|
134171
|
+
TOR_BROWSER_PORT = "http://127.0.0.1:9150";
|
|
134172
|
+
SETUP_TOR_TITLE = "Use Tor?";
|
|
134173
|
+
SETUP_TOR_WHY = "It hides your IP address from the payment service and sellers.";
|
|
134088
134174
|
}
|
|
134089
134175
|
});
|
|
134090
134176
|
|
|
@@ -134203,7 +134289,7 @@ function createMcpDispatcher({ tools, instructions: instructions2 = INSTRUCTIONS
|
|
|
134203
134289
|
};
|
|
134204
134290
|
}
|
|
134205
134291
|
function serveStdio({ input, output: output2, dispatch, log = () => {
|
|
134206
|
-
}, client }) {
|
|
134292
|
+
}, client, forward = () => false }) {
|
|
134207
134293
|
const inFlight = /* @__PURE__ */ new Set();
|
|
134208
134294
|
const write = (message) => {
|
|
134209
134295
|
if (message === void 0) return;
|
|
@@ -134249,6 +134335,7 @@ function serveStdio({ input, output: output2, dispatch, log = () => {
|
|
|
134249
134335
|
write(parseError);
|
|
134250
134336
|
return;
|
|
134251
134337
|
}
|
|
134338
|
+
if (forward(text3, message)) return;
|
|
134252
134339
|
if (takeResponse(message)) return;
|
|
134253
134340
|
const task = (async () => {
|
|
134254
134341
|
if (Array.isArray(message)) {
|
|
@@ -135100,6 +135187,70 @@ function startProofToolsRefresh({
|
|
|
135100
135187
|
clearTimeout(retry);
|
|
135101
135188
|
};
|
|
135102
135189
|
}
|
|
135190
|
+
function startTorRelay({ spawn: spawn10, initParams, output: output2, log, rewrite = (line) => line, readyMs = TOR_RELAY_READY_MS }) {
|
|
135191
|
+
const child = spawn10();
|
|
135192
|
+
let ready = false;
|
|
135193
|
+
let settle;
|
|
135194
|
+
const answered2 = new Promise((resolvePromise, rejectPromise) => {
|
|
135195
|
+
settle = { resolve: resolvePromise, reject: rejectPromise };
|
|
135196
|
+
});
|
|
135197
|
+
const exited = new Promise((resolvePromise) => {
|
|
135198
|
+
child.on("error", (error) => {
|
|
135199
|
+
log(`MCP_TOR_RELAY_SPAWN_FAILED ${error?.code ?? error?.name ?? "Error"}`);
|
|
135200
|
+
resolvePromise(1);
|
|
135201
|
+
});
|
|
135202
|
+
child.on("exit", (code2, signal) => resolvePromise(code2 ?? (signal ? 1 : 0)));
|
|
135203
|
+
});
|
|
135204
|
+
exited.then((code2) => {
|
|
135205
|
+
if (!ready) settle.reject(new Error(`setup_tor_wallet_ended: the wallet server behind Tor ended (exit code ${code2}) before it answered; its own lines are in this server's log`));
|
|
135206
|
+
});
|
|
135207
|
+
const timer = setTimeout(() => settle.reject(new Error(`setup_tor_wallet_slow: the wallet server behind Tor gave no answer in ${readyMs / 1e3} s`)), readyMs);
|
|
135208
|
+
timer.unref?.();
|
|
135209
|
+
let buffer = "";
|
|
135210
|
+
child.stdout.setEncoding("utf8");
|
|
135211
|
+
child.stdout.on("data", (chunk) => {
|
|
135212
|
+
buffer += chunk;
|
|
135213
|
+
let newline;
|
|
135214
|
+
while ((newline = buffer.indexOf("\n")) !== -1) {
|
|
135215
|
+
const line = buffer.slice(0, newline);
|
|
135216
|
+
buffer = buffer.slice(newline + 1);
|
|
135217
|
+
if (!line.trim()) continue;
|
|
135218
|
+
if (!ready) {
|
|
135219
|
+
let message;
|
|
135220
|
+
try {
|
|
135221
|
+
message = JSON.parse(line);
|
|
135222
|
+
} catch {
|
|
135223
|
+
message = void 0;
|
|
135224
|
+
}
|
|
135225
|
+
if (message?.id === RELAY_INIT_ID) {
|
|
135226
|
+
ready = true;
|
|
135227
|
+
clearTimeout(timer);
|
|
135228
|
+
settle.resolve();
|
|
135229
|
+
continue;
|
|
135230
|
+
}
|
|
135231
|
+
}
|
|
135232
|
+
output2.write(`${rewrite(line)}
|
|
135233
|
+
`);
|
|
135234
|
+
}
|
|
135235
|
+
});
|
|
135236
|
+
child.stdin.on("error", () => {
|
|
135237
|
+
});
|
|
135238
|
+
const write = (line) => {
|
|
135239
|
+
if (child.stdin.writable) child.stdin.write(`${line}
|
|
135240
|
+
`);
|
|
135241
|
+
};
|
|
135242
|
+
write(JSON.stringify({
|
|
135243
|
+
jsonrpc: "2.0",
|
|
135244
|
+
id: RELAY_INIT_ID,
|
|
135245
|
+
method: "initialize",
|
|
135246
|
+
params: initParams ?? { protocolVersion: SUPPORTED_PROTOCOL_VERSIONS[0], capabilities: {}, clientInfo: { name: "shinjuku-setup-relay", version: "1" } }
|
|
135247
|
+
}));
|
|
135248
|
+
write(JSON.stringify({ jsonrpc: "2.0", method: "notifications/initialized" }));
|
|
135249
|
+
return answered2.then(() => ({ write, end: () => child.stdin.end(), exited }), (error) => {
|
|
135250
|
+
child.kill("SIGTERM");
|
|
135251
|
+
throw error;
|
|
135252
|
+
});
|
|
135253
|
+
}
|
|
135103
135254
|
async function runSetupModeServer({
|
|
135104
135255
|
setupTools,
|
|
135105
135256
|
startNormal,
|
|
@@ -135107,13 +135258,13 @@ async function runSetupModeServer({
|
|
|
135107
135258
|
output: output2 = process.stdout,
|
|
135108
135259
|
errorOutput = process.stderr,
|
|
135109
135260
|
updateCheck,
|
|
135110
|
-
discoverCacheDir,
|
|
135111
135261
|
launchNotice
|
|
135112
135262
|
}) {
|
|
135113
135263
|
const log = (line) => errorOutput.write(`${line}
|
|
135114
135264
|
`);
|
|
135115
135265
|
const client = createClientBridge();
|
|
135116
|
-
const
|
|
135266
|
+
const startNotice = (facilitator) => startUpdateNotice({ facilitator, log, ...updateCheck !== void 0 ? { check: updateCheck } : {} });
|
|
135267
|
+
let notice = startUpdateNotice({ log, check: false });
|
|
135117
135268
|
const saved = { log: console.log, info: console.info, debug: console.debug };
|
|
135118
135269
|
const toStderr = (...parts) => console.error(...parts);
|
|
135119
135270
|
console.log = toStderr;
|
|
@@ -135123,11 +135274,48 @@ async function runSetupModeServer({
|
|
|
135123
135274
|
let doneTool;
|
|
135124
135275
|
let current;
|
|
135125
135276
|
let ended;
|
|
135277
|
+
let initParams;
|
|
135278
|
+
let relay;
|
|
135279
|
+
let relayStopped;
|
|
135280
|
+
const relayEnded = new Promise((resolvePromise) => {
|
|
135281
|
+
relayStopped = resolvePromise;
|
|
135282
|
+
});
|
|
135283
|
+
const listIds = /* @__PURE__ */ new Set();
|
|
135284
|
+
const withDoneTool = (line) => {
|
|
135285
|
+
if (!doneTool || !listIds.size) return line;
|
|
135286
|
+
let message;
|
|
135287
|
+
try {
|
|
135288
|
+
message = JSON.parse(line);
|
|
135289
|
+
} catch {
|
|
135290
|
+
return line;
|
|
135291
|
+
}
|
|
135292
|
+
if (!listIds.delete(message?.id) || !Array.isArray(message?.result?.tools)) return line;
|
|
135293
|
+
const listed = {
|
|
135294
|
+
name: doneTool.name,
|
|
135295
|
+
title: doneTool.title,
|
|
135296
|
+
description: doneTool.description,
|
|
135297
|
+
inputSchema: doneTool.inputSchema,
|
|
135298
|
+
annotations: { title: doneTool.title, ...doneTool.annotations }
|
|
135299
|
+
};
|
|
135300
|
+
return JSON.stringify({ ...message, result: { ...message.result, tools: [...message.result.tools.filter((tool) => tool?.name !== doneTool.name), listed] } });
|
|
135301
|
+
};
|
|
135126
135302
|
const stopKeepWarm = startOnionKeepWarm();
|
|
135127
135303
|
const activate = async () => {
|
|
135128
|
-
if (wallet) return;
|
|
135304
|
+
if (wallet || relay) return;
|
|
135129
135305
|
const options = await startNormal();
|
|
135306
|
+
if (options.relay) {
|
|
135307
|
+
relay = await startTorRelay({ spawn: options.relay, initParams, output: output2, log, rewrite: withDoneTool });
|
|
135308
|
+
relay.exited.then((code2) => {
|
|
135309
|
+
log(`MCP_TOR_RELAY_ENDED code=${code2}`);
|
|
135310
|
+
relayStopped();
|
|
135311
|
+
});
|
|
135312
|
+
current = createMcpDispatcher({ tools: doneTool ? [doneTool] : [], instructions: INSTRUCTIONS, log, client, listChanged: true });
|
|
135313
|
+
log("MCP_SETUP_SWITCHED to the wallet server behind Tor");
|
|
135314
|
+
client.notify?.("notifications/tools/list_changed");
|
|
135315
|
+
return;
|
|
135316
|
+
}
|
|
135130
135317
|
wallet = await openWalletServer({ ...options, client, log });
|
|
135318
|
+
notice = startNotice(options.memoServiceUrl);
|
|
135131
135319
|
current = createMcpDispatcher({
|
|
135132
135320
|
tools: withLaunchNotice(notice.wrapTools([...wallet.tools, ...doneTool ? [doneTool] : []], UPDATE_NOTICE_TOOLS), launchNotice),
|
|
135133
135321
|
instructions: withLaunchLine(notice.instructions(INSTRUCTIONS), launchNotice),
|
|
@@ -135141,8 +135329,6 @@ async function runSetupModeServer({
|
|
|
135141
135329
|
};
|
|
135142
135330
|
try {
|
|
135143
135331
|
const setup = setupTools({ client, log, activate });
|
|
135144
|
-
if (discoverCacheDir) loadX402Listings({ cacheDir: discoverCacheDir }).catch(() => {
|
|
135145
|
-
});
|
|
135146
135332
|
doneTool = setup.doneTool;
|
|
135147
135333
|
if (launchNotice) log(`MCP_LAUNCH_OLD_FORM ${launchNotice}`);
|
|
135148
135334
|
current = createMcpDispatcher({
|
|
@@ -135154,15 +135340,30 @@ async function runSetupModeServer({
|
|
|
135154
135340
|
listChanged: true
|
|
135155
135341
|
});
|
|
135156
135342
|
log("MCP_READY setup-mode: the wallet is not set up; tools: shinjuku_setup, wallet_status");
|
|
135157
|
-
|
|
135343
|
+
const forward = (text3, message) => {
|
|
135344
|
+
if (!relay) return false;
|
|
135345
|
+
if (message?.method === "tools/call" && message.params?.name === "shinjuku_setup") return false;
|
|
135346
|
+
if (message?.method === "tools/list" && validId(message.id)) listIds.add(message.id);
|
|
135347
|
+
relay.write(text3);
|
|
135348
|
+
return true;
|
|
135349
|
+
};
|
|
135350
|
+
const served = serveStdio({ input, output: output2, log, client, forward, dispatch: (entry) => {
|
|
135351
|
+
if (entry?.method === "initialize") initParams = entry.params;
|
|
135352
|
+
return current(entry);
|
|
135353
|
+
} });
|
|
135354
|
+
await Promise.race([served, relayEnded]);
|
|
135158
135355
|
} finally {
|
|
135159
135356
|
stopKeepWarm();
|
|
135357
|
+
if (relay) {
|
|
135358
|
+
relay.end();
|
|
135359
|
+
await relay.exited;
|
|
135360
|
+
}
|
|
135160
135361
|
ended = wallet ? await closeWithin(wallet.close(), { moving: wallet.moving, movingWork: wallet.movingWork, historyBusy: closeHistoryBusy(wallet), log }) : true;
|
|
135161
135362
|
Object.assign(console, saved);
|
|
135162
135363
|
}
|
|
135163
135364
|
return { closed: ended };
|
|
135164
135365
|
}
|
|
135165
|
-
var import_web3134, SUPPORTED_PROTOCOL_VERSIONS, MAX_LINE_BYTES, POSITIVE_ATOMIC7, INSTRUCTIONS, MCP_LOG_LEVELS, POOL_SWITCH_LOG_LEVEL, validId, BUNDLED_SOURCE_DIR, SHA256_HEX, UPDATE_NOTICE_TOOLS, UPDATE_NOTICE_MAX_TEXT, NPM_VERSION2, GIT_COMMIT, ownWalletVersion, mcpServerVersion, UPDATE_NOTICE_TEXT, updateNoticeLine, LAUNCH_NOTICE_TOOLS, withLaunchLine, capRequired, setupInvalid, TOOL_ROOTS_WAIT_MS, ROOTS_FREE_TOOLS, MCP_CLOSE_BOUND_MS, MCP_CLOSE_HISTORY_BOUND_MS, MCP_CLOSE_UNREADABLE_BOUND_MS, MCP_CLOSE_POLL_MS, closeHistoryBusy, SETUP_INSTRUCTIONS;
|
|
135366
|
+
var import_web3134, SUPPORTED_PROTOCOL_VERSIONS, MAX_LINE_BYTES, POSITIVE_ATOMIC7, INSTRUCTIONS, MCP_LOG_LEVELS, POOL_SWITCH_LOG_LEVEL, validId, BUNDLED_SOURCE_DIR, SHA256_HEX, UPDATE_NOTICE_TOOLS, UPDATE_NOTICE_MAX_TEXT, NPM_VERSION2, GIT_COMMIT, ownWalletVersion, mcpServerVersion, UPDATE_NOTICE_TEXT, updateNoticeLine, LAUNCH_NOTICE_TOOLS, withLaunchLine, capRequired, setupInvalid, TOOL_ROOTS_WAIT_MS, ROOTS_FREE_TOOLS, MCP_CLOSE_BOUND_MS, MCP_CLOSE_HISTORY_BOUND_MS, MCP_CLOSE_UNREADABLE_BOUND_MS, MCP_CLOSE_POLL_MS, closeHistoryBusy, SETUP_INSTRUCTIONS, TOR_RELAY_READY_MS, RELAY_INIT_ID;
|
|
135166
135367
|
var init_stdioServer = __esm({
|
|
135167
135368
|
"wallet/src/mcp/stdioServer.mjs"() {
|
|
135168
135369
|
"use strict";
|
|
@@ -135222,6 +135423,8 @@ var init_stdioServer = __esm({
|
|
|
135222
135423
|
MCP_CLOSE_POLL_MS = 500;
|
|
135223
135424
|
closeHistoryBusy = (server) => () => compactHistoryReadsRunning() > 0 || memoReadsAheadRunning() > 0 || server.refreshOpen?.() === true;
|
|
135224
135425
|
SETUP_INSTRUCTIONS = `This Shinjuku Shield wallet server is NOT SET UP on this machine yet: every money tool answers wallet_not_set_up. When the user wants to pay, check a balance, or add money, call shinjuku_setup: it asks the user to confirm in this client, creates the wallet here, and downloads the proof tools (minutes: call it again as its next says). At stage done the wallet tools are live in this same server. After setup: ${INSTRUCTIONS}`;
|
|
135426
|
+
TOR_RELAY_READY_MS = 18e4;
|
|
135427
|
+
RELAY_INIT_ID = "shinjuku-wallet-relay-initialize";
|
|
135225
135428
|
}
|
|
135226
135429
|
});
|
|
135227
135430
|
|
|
@@ -135596,7 +135799,7 @@ async function serveTorMissingMcp({ message, recheck = async () => false, input
|
|
|
135596
135799
|
ready = false;
|
|
135597
135800
|
}
|
|
135598
135801
|
const body = ready ? {
|
|
135599
|
-
say:
|
|
135802
|
+
say: "Tor runs now. Reconnect the wallet once (the steps are below), then ask again. Nothing was paid.",
|
|
135600
135803
|
ok: false,
|
|
135601
135804
|
error: "mcp_restart_needed",
|
|
135602
135805
|
next: `Tell the user: ${RESTART}. Nothing was paid.`
|
|
@@ -135635,7 +135838,7 @@ var init_torMissingMcp = __esm({
|
|
|
135635
135838
|
"use strict";
|
|
135636
135839
|
init_stdioServer();
|
|
135637
135840
|
init_tools();
|
|
135638
|
-
RESTART =
|
|
135841
|
+
RESTART = `Reconnect the wallet once (${RESTART_STEPS}), then ask again`;
|
|
135639
135842
|
}
|
|
135640
135843
|
});
|
|
135641
135844
|
|
|
@@ -161961,6 +162164,7 @@ async function runInferStop(values, deps) {
|
|
|
161961
162164
|
var CHAT_RAW_ARGS = /* @__PURE__ */ Symbol("chat raw args");
|
|
161962
162165
|
var WALLET_FROM_SETUP = /* @__PURE__ */ Symbol("wallet from setup");
|
|
161963
162166
|
var RAN_BEHIND_TOR = /* @__PURE__ */ Symbol("ran behind tor");
|
|
162167
|
+
var SETUP_RERUN = /* @__PURE__ */ Symbol("setup rerun");
|
|
161964
162168
|
var INFER_CAP_FLAGS = Object.freeze(["--max-payment", "--max-session"]);
|
|
161965
162169
|
var RanBehindTorFailed = class extends Error {
|
|
161966
162170
|
constructor(code2) {
|
|
@@ -162219,15 +162423,7 @@ function withProofToolsRefresh(options, fromConfig) {
|
|
|
162219
162423
|
var inProxiedRun = (env) => childRunProxy(env).args.length > 0;
|
|
162220
162424
|
var terminalQuiet = (values, deps) => deps.stdoutIsTTY?.() === true && !values.has("--json") && !values.has("--verbose");
|
|
162221
162425
|
var TOR_RUN_STARTED_ENV2 = "SHINJUKU_WALLET_TOR_RUN_STARTED_FILE";
|
|
162222
|
-
var TOR_DOWN_DETAIL = "
|
|
162223
|
-
var recordedTunnelHost = (configPath2) => {
|
|
162224
|
-
try {
|
|
162225
|
-
const tunnel = readSetupConfig(dirname33(configPath2))?.torTunnel;
|
|
162226
|
-
return tunnel ? new URL(tunnel).host : "127.0.0.1:9080";
|
|
162227
|
-
} catch {
|
|
162228
|
-
return "127.0.0.1:9080";
|
|
162229
|
-
}
|
|
162230
|
-
};
|
|
162426
|
+
var TOR_DOWN_DETAIL = "The wallet runs only over Tor, and Tor is not running on this computer (after the computer restarts, Tor must be started again), so nothing was paid or sent.";
|
|
162231
162427
|
var recordedTunnelUrl = (configPath2) => {
|
|
162232
162428
|
try {
|
|
162233
162429
|
return readSetupConfig(dirname33(configPath2))?.torTunnel ?? TOR_HTTP_TUNNEL;
|
|
@@ -162235,11 +162431,18 @@ var recordedTunnelUrl = (configPath2) => {
|
|
|
162235
162431
|
return TOR_HTTP_TUNNEL;
|
|
162236
162432
|
}
|
|
162237
162433
|
};
|
|
162238
|
-
var torDownNext = (configPath2) => `Tell the user:
|
|
162434
|
+
var torDownNext = (configPath2) => `Tell the user why: Tor is not running, and the wallet never falls back to a direct connection. Show torStartCommand in one code block, to copy into ${torStart().where}: this command downloads Tor and starts it for the wallet. If you can run commands here, offer to run it for the user. When Tor runs: ${RESTART}. (Setup recorded Tor in ${configPath2}.)`;
|
|
162239
162435
|
async function runMcpTorDown({ exitCode, configPath: configPath2, input = process.stdin, output: output2 = process.stdout, errorOutput = process.stderr }) {
|
|
162240
162436
|
const log = (line) => errorOutput.write(`${line}
|
|
162241
162437
|
`);
|
|
162242
|
-
const unavailable = JSON.stringify({
|
|
162438
|
+
const unavailable = JSON.stringify({
|
|
162439
|
+
say: "Not paid: the wallet runs only over Tor, and Tor is not running on this computer. Start it with the command below.",
|
|
162440
|
+
ok: false,
|
|
162441
|
+
error: "mcp_tor_unavailable",
|
|
162442
|
+
detail: TOR_DOWN_DETAIL,
|
|
162443
|
+
next: torDownNext(configPath2),
|
|
162444
|
+
torStartCommand: torStart().command
|
|
162445
|
+
}, null, 2);
|
|
162243
162446
|
const tunnel = recordedTunnelUrl(configPath2);
|
|
162244
162447
|
const answer = async () => {
|
|
162245
162448
|
let ready = false;
|
|
@@ -162249,7 +162452,7 @@ async function runMcpTorDown({ exitCode, configPath: configPath2, input = proces
|
|
|
162249
162452
|
ready = false;
|
|
162250
162453
|
}
|
|
162251
162454
|
const restart = ready ? {
|
|
162252
|
-
say:
|
|
162455
|
+
say: "Tor runs now. Reconnect the wallet once (the steps are below), then ask again. Nothing was paid.",
|
|
162253
162456
|
ok: false,
|
|
162254
162457
|
error: "mcp_restart_needed",
|
|
162255
162458
|
next: `Tell the user: ${RESTART}. Nothing was paid.`
|
|
@@ -162381,11 +162584,12 @@ async function runMcpFirstRun(values, deps) {
|
|
|
162381
162584
|
discoverCacheDir: join40(home, "discover-cache"),
|
|
162382
162585
|
npmVersion: deps.walletVersion().npm
|
|
162383
162586
|
}),
|
|
162384
|
-
discoverCacheDir: join40(home, "discover-cache"),
|
|
162385
162587
|
startNormal: async () => {
|
|
162386
162588
|
const after = mcpValuesAfterSetup(values, home, deps);
|
|
162387
|
-
|
|
162388
|
-
|
|
162589
|
+
const config = after.values.get(MCP_FROM_CONFIG).config;
|
|
162590
|
+
if (config.tor === true && !after.values.has("--no-tor") && !inProxiedRun(deps.env)) {
|
|
162591
|
+
const args = ["--tor", "mcp", ...after.values.get(MCP_RAW_ARGS), ...config.torTunnel ? ["--proxy", config.torTunnel] : []];
|
|
162592
|
+
return { relay: () => deps.torChild(args, ["pipe", "pipe", "inherit"]) };
|
|
162389
162593
|
}
|
|
162390
162594
|
const options = withProofToolsRefresh(mcpServerOptions(after.values, after.deps), after.values.get(MCP_FROM_CONFIG));
|
|
162391
162595
|
warm = options.proofToolsPath ? deps.startKeepWarm(options, deps.env) : void 0;
|
|
@@ -162413,14 +162617,45 @@ function mcpSetupAdapter(values, home, deps) {
|
|
|
162413
162617
|
},
|
|
162414
162618
|
missing: () => missingPieces(home, readSetupConfig(home)),
|
|
162415
162619
|
// privateInference: the human ticked "Use private inference for your AI now" (a yes, as setup --private-inference);
|
|
162416
|
-
// no tick keeps what config.json records.
|
|
162417
|
-
|
|
162418
|
-
|
|
162419
|
-
|
|
162420
|
-
|
|
162421
|
-
|
|
162620
|
+
// no tick keeps what config.json records. tor: the answer to "Use Tor?" (private inference turns it on). A server
|
|
162621
|
+
// already behind Tor (or an old caller with no answer) sets up in place.
|
|
162622
|
+
run: async (onStage, { privateInference, tor } = {}) => {
|
|
162623
|
+
if (tor === true && !inProxiedRun(deps.env)) return mcpSetupBehindTor(values, home, deps, { privateInference: privateInference === true, onStage });
|
|
162624
|
+
return runSetupRecorded(
|
|
162625
|
+
{ ...setupOptionsOf(values, home), ...typeof tor === "boolean" ? { tor } : {}, onStage },
|
|
162626
|
+
setupDeps,
|
|
162627
|
+
inferenceRecordOf(readSetupConfig(home), privateInference === true ? true : void 0)
|
|
162628
|
+
);
|
|
162629
|
+
}
|
|
162422
162630
|
};
|
|
162423
162631
|
}
|
|
162632
|
+
async function mcpSetupBehindTor(values, home, deps, { privateInference, onStage }) {
|
|
162633
|
+
const caps = new Map(Object.entries(setupOptionsOf(values, home)).filter(([key]) => key !== "home").map(([key, value]) => [`--${key.replace(/[A-Z]/g, (c) => `-${c.toLowerCase()}`)}`, value]));
|
|
162634
|
+
onStage("tor", "setup runs over Tor: it makes the wallet and downloads its files (about 191 MB) over Tor, which takes a few minutes");
|
|
162635
|
+
const child = deps.torChild(
|
|
162636
|
+
["--tor", "setup", "--yes", "--prefer-tor", ...privateInference ? ["--private-inference"] : [], ...setupArgvOf(caps)],
|
|
162637
|
+
["ignore", 2, 2]
|
|
162638
|
+
);
|
|
162639
|
+
const code2 = await new Promise((resolvePromise) => {
|
|
162640
|
+
child.on("error", () => resolvePromise(1));
|
|
162641
|
+
child.on("exit", (exitCode, signal) => resolvePromise(exitCode ?? (signal ? 1 : 0)));
|
|
162642
|
+
});
|
|
162643
|
+
const config = code2 === 0 ? setupConfigOf(home) : void 0;
|
|
162644
|
+
if (!config) {
|
|
162645
|
+
const made = setupConfigOf(home)?.recoveryFile;
|
|
162646
|
+
if (made && existsSync(made)) onStage("wallet-created", { recoveryFile: made });
|
|
162647
|
+
throw new Error(`setup_tor_unavailable: setup ran behind Tor, and that run ended with exit code ${code2} (its lines are in this server's log); nothing was paid. It continues where it stopped when it runs again`);
|
|
162648
|
+
}
|
|
162649
|
+
onStage("tor", "the wallet is made; its server starts over Tor now (the first Tor connection can take a minute)");
|
|
162650
|
+
const recoveryFile = config.recoveryFile && existsSync(config.recoveryFile) ? config.recoveryFile : void 0;
|
|
162651
|
+
return Object.freeze({
|
|
162652
|
+
pool: config.pool,
|
|
162653
|
+
caps: config.caps,
|
|
162654
|
+
tor: true,
|
|
162655
|
+
wallet: { status: recoveryFile ? "created" : "existing", ...recoveryFile ? { recoveryFile } : {} },
|
|
162656
|
+
...privateInference ? { privateInference: true } : {}
|
|
162657
|
+
});
|
|
162658
|
+
}
|
|
162424
162659
|
function inferenceRecordOf(old, answer) {
|
|
162425
162660
|
const recorded = typeof old?.inference?.enabled === "boolean" ? old.inference.enabled : void 0;
|
|
162426
162661
|
if (answer === true) return true;
|
|
@@ -162717,13 +162952,14 @@ async function runSetupCommand(values, deps) {
|
|
|
162717
162952
|
let ownAddress = values.get("--own-address");
|
|
162718
162953
|
const old = setupConfigOf(home);
|
|
162719
162954
|
const behindTor = (wanted) => wanted && !values.has("--no-tor") && !inProxiedRun(deps.env);
|
|
162955
|
+
const missing = missingPieces(home, old);
|
|
162956
|
+
if (old && !missing.length) values.set(SETUP_RERUN, "settings");
|
|
162720
162957
|
if (!interactive && behindTor(values.has("--prefer-tor") || values.has("--private-inference") || old?.tor === true)) {
|
|
162721
162958
|
await setupBehindTor(setupArgvOf(values), deps);
|
|
162722
162959
|
if (ownAddress) io.out(`${recordOwnAddress(home, ownAddress, deps).join("\n")}
|
|
162723
162960
|
`);
|
|
162724
162961
|
return void 0;
|
|
162725
162962
|
}
|
|
162726
|
-
const missing = missingPieces(home, old);
|
|
162727
162963
|
const npmVersion = deps.walletVersion().npm;
|
|
162728
162964
|
const introduced = values.has("--yes") && inProxiedRun(deps.env);
|
|
162729
162965
|
const asksOwnFirst = interactive && Boolean(old) && terminal && !ownAddress;
|
|
@@ -162745,7 +162981,7 @@ async function runSetupCommand(values, deps) {
|
|
|
162745
162981
|
...values.has("--max-shield") ? { maxShield: values.get("--max-shield") } : {},
|
|
162746
162982
|
...values.has("--max-unshield") ? { maxUnshield: values.get("--max-unshield") } : {},
|
|
162747
162983
|
...values.has("--prefer-tor") || torRunRecords ? { tor: true } : {},
|
|
162748
|
-
// This --tor run's own local tunnel when it is not 127.0.0.1:9080 (setup --tor --proxy http://127.0.0.1:
|
|
162984
|
+
// This --tor run's own local tunnel when it is not 127.0.0.1:9080 (another local Tor HTTPTunnelPort, for example a second tor process: setup --tor --proxy http://127.0.0.1:9180): mcp uses it.
|
|
162749
162985
|
...torRunRecords && childRunProxy(deps.env).args[1] === "--proxy" ? { torTunnel: childRunProxy(deps.env).args[2] } : {},
|
|
162750
162986
|
...values.has("--passphrase-file") ? { passphraseFile: values.get("--passphrase-file") } : {},
|
|
162751
162987
|
...values.has("--facilitator") ? { facilitator: values.get("--facilitator") } : {},
|
|
@@ -162778,6 +163014,7 @@ async function runSetupCommand(values, deps) {
|
|
|
162778
163014
|
if (/^setup_own_address_[a-z_]+: /.test(String(error?.message))) throw new PublicFailure(error.message);
|
|
162779
163015
|
throw error;
|
|
162780
163016
|
}
|
|
163017
|
+
values.set(SETUP_RERUN, "own-address");
|
|
162781
163018
|
io.out([
|
|
162782
163019
|
`Saved: ${ownAddress} is your own address now, so your agent sends money back to you there without asking each time (no restart of your agent app needed).`,
|
|
162783
163020
|
...saved.dropped.length ? [`config.json keeps ${MAX_OWN_ADDRESSES} own addresses: the oldest (${saved.dropped.join(", ")}) now ask before each send.`] : [],
|
|
@@ -162859,25 +163096,33 @@ Copy it to two offline places now; it is the only way to restore this wallet.
|
|
|
162859
163096
|
lines.push("");
|
|
162860
163097
|
io.out(`${lines.join("\n")}
|
|
162861
163098
|
`);
|
|
163099
|
+
const rerun = values.get(SETUP_RERUN) === "settings";
|
|
162862
163100
|
const targets = values.get("--add-to") ?? [];
|
|
162863
163101
|
if (targets.length) addToHosts(targets, home, deps, { force: values.has("--force"), npmVersion });
|
|
162864
|
-
|
|
163102
|
+
if (rerun && !targets.length) {
|
|
163103
|
+
io.out("Your agent app keeps its MCP entry: restart this wallet's MCP server there (or restart the app) so it reads these settings. To add the wallet to another agent app, run setup again with --add-to claude-code, claude-desktop, or cursor.\n");
|
|
163104
|
+
} else {
|
|
163105
|
+
io.out(`${targets.length ? "Or add it by hand" : "Add it to your agent host"}:
|
|
162865
163106
|
${hostConfigText({ home, env: deps.env, platform: deps.platform ?? process.platform, npmVersion })}
|
|
162866
163107
|
`);
|
|
162867
|
-
|
|
163108
|
+
io.out(`
|
|
162868
163109
|
${terminalUseLines(npmVersion).join("\n")}
|
|
162869
163110
|
`);
|
|
163111
|
+
}
|
|
162870
163112
|
const config = setupConfigOf(home);
|
|
163113
|
+
const inferenceNow = summary.privateInference === true && (!rerun || old?.inference?.enabled !== true);
|
|
162871
163114
|
let apiKey;
|
|
162872
|
-
if (
|
|
163115
|
+
if (inferenceNow && config?.pool) {
|
|
162873
163116
|
try {
|
|
162874
163117
|
apiKey = localAiServerApiKey(home, { walletPath: homeWalletPath(home, config.pool) });
|
|
162875
163118
|
} catch {
|
|
162876
163119
|
apiKey = void 0;
|
|
162877
163120
|
}
|
|
162878
163121
|
}
|
|
162879
|
-
io.out(`
|
|
162880
|
-
${
|
|
163122
|
+
if (inferenceNow) io.out(`
|
|
163123
|
+
${privateInferencePath(config, { apiKey }).text}`);
|
|
163124
|
+
else if (!rerun) io.out(`
|
|
163125
|
+
${fundingStepText(config?.tor === true)}`);
|
|
162881
163126
|
if (interactive) await offerFundNow(deps, { tor: config?.tor === true });
|
|
162882
163127
|
}
|
|
162883
163128
|
function validateAddFunds(values) {
|
|
@@ -163738,8 +163983,9 @@ var COMMANDS = [
|
|
|
163738
163983
|
"A command that takes --pool (balance, recover, deposit, add-funds, and others) takes it, and the passphrase of this home's wallet, from config.json when you leave them out: shinjuku balance needs no flags. A pocket command (pocket list, scan, reshield, release, fill) takes this home's --wallet and passphrase file the same way, and --program, --proof-tools, --facilitator when it needs them. A flag or SHIELDED_WALLET_PASSPHRASE still wins; init and restore never use config.json, and move reads it itself."
|
|
163739
163984
|
],
|
|
163740
163985
|
next: `start it from your agent host with npx -y --no-audit --no-fund ${NPX_AT_VERSION} mcp (or ${CLI2} mcp), then ask your agent "what is my balance"`,
|
|
163741
|
-
// After a run: the same line as the host config setup printed (this npm version, when the wallet knows it).
|
|
163742
|
-
|
|
163986
|
+
// After a run: the same line as the host config setup printed (this npm version, when the wallet knows it). A rerun
|
|
163987
|
+
// of a complete setup (SETUP_RERUN): the agent app already has the entry.
|
|
163988
|
+
nextAfterRun: (values, deps) => values.get(SETUP_RERUN) === "settings" ? `restart this wallet's MCP server in your agent app (or restart the app) so it reads these settings, then ask your agent "what is my balance"` : values.get(SETUP_RERUN) === "own-address" ? "ask your agent to send money to your own address: it sends without asking you each time" : `start it from your agent host with npx -y --no-audit --no-fund ${npxPackageWord(deps.walletVersion().npm)} mcp (or ${CLI2} mcp), then ask your agent "what is my balance"`,
|
|
163743
163989
|
run: (args, values, deps, io) => deps.setupMain(values, { ...deps, io })
|
|
163744
163990
|
},
|
|
163745
163991
|
{
|
|
@@ -166250,6 +166496,8 @@ function defaultDependencies() {
|
|
|
166250
166496
|
else process.env[TOR_RUN_STARTED_ENV2] = before;
|
|
166251
166497
|
}
|
|
166252
166498
|
},
|
|
166499
|
+
/** One command line as a child behind Tor with the given stdio (the MCP setup server's Tor setup and Tor wallet server). */
|
|
166500
|
+
torChild: (argv2, stdio) => torChild(argv2, stdio),
|
|
166253
166501
|
// No command calls these (the v0b and laneb families are retired, RETIRED_FAMILIES). They stay only because
|
|
166254
166502
|
// wallet/scripts/bundle.mjs still requires the V0b zk-sdk WASM in the bundle; drop both together.
|
|
166255
166503
|
v0bMain: async (...args) => (await Promise.resolve().then(() => (init_cli4(), cli_exports))).v0bMain(...args),
|