shinjuku-shielded 0.3.174 → 0.3.176
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 +177 -43
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.176. The npm packages `shinjuku-shield` and
|
|
10
10
|
`shinjuku-shielded` hold the same files. The command is `shinjuku`.
|
|
11
11
|
|
|
12
12
|
## Set up
|
|
13
13
|
|
|
14
14
|
```sh
|
|
15
|
-
npx -y shinjuku@0.3.
|
|
15
|
+
npx -y shinjuku@0.3.176 setup
|
|
16
16
|
```
|
|
17
17
|
|
|
18
18
|
Setup offers to install the `shinjuku` command and, on Windows, adds npm's
|
|
@@ -35,13 +35,13 @@ Every wallet command works after `shinjuku`, for example `shinjuku balance`,
|
|
|
35
35
|
Claude Code:
|
|
36
36
|
|
|
37
37
|
```sh
|
|
38
|
-
claude mcp add --scope user shinjuku -- npx -y --no-audit --no-fund shinjuku-shield@0.3.
|
|
38
|
+
claude mcp add --scope user shinjuku -- npx -y --no-audit --no-fund shinjuku-shield@0.3.176 mcp
|
|
39
39
|
```
|
|
40
40
|
|
|
41
41
|
Claude Desktop (`claude_desktop_config.json`) or Cursor (`~/.cursor/mcp.json`):
|
|
42
42
|
|
|
43
43
|
```json
|
|
44
|
-
{ "mcpServers": { "shinjuku": { "command": "npx", "args": ["-y", "--no-audit", "--no-fund", "shinjuku-shield@0.3.
|
|
44
|
+
{ "mcpServers": { "shinjuku": { "command": "npx", "args": ["-y", "--no-audit", "--no-fund", "shinjuku-shield@0.3.176", "mcp"] } } }
|
|
45
45
|
```
|
|
46
46
|
|
|
47
47
|
On native Windows, if the host cannot find `npx`, use `"command": "cmd"` and
|
|
@@ -54,7 +54,7 @@ Codex (the Codex app and Codex CLI read the same file, `~/.codex/config.toml`):
|
|
|
54
54
|
```toml
|
|
55
55
|
[mcp_servers.shinjuku]
|
|
56
56
|
command = "npx"
|
|
57
|
-
args = ["-y", "--no-audit", "--no-fund", "shinjuku-shield@0.3.
|
|
57
|
+
args = ["-y", "--no-audit", "--no-fund", "shinjuku-shield@0.3.176", "mcp"]
|
|
58
58
|
startup_timeout_sec = 120
|
|
59
59
|
tool_timeout_sec = 300
|
|
60
60
|
```
|
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": "eb8212021af756602a223fcb5e329e0eaf488b7b276850014abef3c6a917eb81",
|
|
5
|
+
"bytes": 9401666,
|
|
6
|
+
"sourceCommit": "d6237649219078cad2c31a571967809dc888a3fc",
|
|
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",
|
|
@@ -1038,5 +1038,5 @@
|
|
|
1038
1038
|
"version": "1.8.0"
|
|
1039
1039
|
}
|
|
1040
1040
|
],
|
|
1041
|
-
"publishedAt": "2026-11-
|
|
1041
|
+
"publishedAt": "2026-11-06T00:15:32.603Z"
|
|
1042
1042
|
}
|
package/package.json
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "shinjuku-shielded",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.176",
|
|
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": "eb821202",
|
|
7
|
+
"shinjukuSha256": "eb8212021af756602a223fcb5e329e0eaf488b7b276850014abef3c6a917eb81",
|
|
8
8
|
"license": "SEE LICENSE IN LICENSE.txt",
|
|
9
9
|
"author": "Shinjuku Shielded",
|
|
10
10
|
"homepage": "https://github.com/ShinjukuStaition/shinjuku-shield#readme",
|
package/shinjuku-wallet.mjs
CHANGED
|
@@ -54474,7 +54474,7 @@ function hostStartFolder(target, entry) {
|
|
|
54474
54474
|
}
|
|
54475
54475
|
function noStartFolderWords(target, entry) {
|
|
54476
54476
|
if (hasPrefix(entry) || hostStartFolder(target, entry) !== void 0) return "";
|
|
54477
|
-
return ` Your wallet folder path has a character that Windows reads as code (% & | < > ^ ! or
|
|
54477
|
+
return ` Your wallet folder path has a character that Windows reads as code (% & | < > ^ ! " $ or \`), so ${HOST_NAMES[target]} starts the wallet in a folder of its own: a settings file there (.npmrc) can stop the wallet. If the wallet does not start there, set up the wallet again in a folder without these characters.`;
|
|
54478
54478
|
}
|
|
54479
54479
|
function cwdFolder(cwd) {
|
|
54480
54480
|
if (typeof cwd !== "string" || !cwd) return void 0;
|
|
@@ -54492,12 +54492,12 @@ function installPackageWord(npmVersion) {
|
|
|
54492
54492
|
const version3 = knownNpmVersion(npmVersion);
|
|
54493
54493
|
return version3 ? `${COMMAND_PACKAGE}@${version3}` : COMMAND_PACKAGE;
|
|
54494
54494
|
}
|
|
54495
|
-
function oneTimeCommandLine(words2, npmVersion) {
|
|
54496
|
-
return [npxCommandPrefix(npmVersion, { recovery: RECOVERY_WORDS.test(String(words2 ?? "")) }), words2].join(" ");
|
|
54495
|
+
function oneTimeCommandLine(words2, npmVersion, { npmArgs = [] } = {}) {
|
|
54496
|
+
return [npxCommandPrefix(npmVersion, { recovery: RECOVERY_WORDS.test(String(words2 ?? "")), npmArgs }), words2].join(" ");
|
|
54497
54497
|
}
|
|
54498
|
-
function npxCommandPrefix(npmVersion, { recovery = false } = {}) {
|
|
54498
|
+
function npxCommandPrefix(npmVersion, { recovery = false, npmArgs = [] } = {}) {
|
|
54499
54499
|
const cache = knownNpmVersion(npmVersion) && !recovery ? npxCacheFlag() : void 0;
|
|
54500
|
-
return ["npx", ...cache ? [cache] : [], "-y", ...NPX_INSTALL_FLAGS, npxPackageWord(npmVersion)].join(" ");
|
|
54500
|
+
return ["npx", ...cache ? [cache] : [], "-y", ...NPX_INSTALL_FLAGS, ...npmArgs, npxPackageWord(npmVersion)].join(" ");
|
|
54501
54501
|
}
|
|
54502
54502
|
function npxLineFlags(text3, ownVersion) {
|
|
54503
54503
|
const own = knownNpmVersion(ownVersion);
|
|
@@ -54539,7 +54539,7 @@ function mcpServerEntry({ home, platform = process.platform, npmVersion, path, t
|
|
|
54539
54539
|
}
|
|
54540
54540
|
function npmPrefixArgs(home, platform = process.platform) {
|
|
54541
54541
|
const folder = resolve6(home);
|
|
54542
|
-
return platform === "win32" &&
|
|
54542
|
+
return platform === "win32" && WIN_ARG_CODE.test(folder) ? [] : [`--prefix=${folder}`];
|
|
54543
54543
|
}
|
|
54544
54544
|
function homeTorOn(home) {
|
|
54545
54545
|
try {
|
|
@@ -55812,7 +55812,7 @@ function changeFileOnce(file, change, { now, platform, restrict, codec = JSON_CO
|
|
|
55812
55812
|
}
|
|
55813
55813
|
return { changed: true, ...backup ? { backup } : {} };
|
|
55814
55814
|
}
|
|
55815
|
-
var import_web396, CONFIG_SCHEMA, CONFIG_FILE, NPM_PACKAGE_NAMES, COMMAND_PACKAGE, NPX_PACKAGE, NPX_INSTALL_FLAGS, MCP_SERVER_NAME, OLD_MCP_SERVER_NAMES, P03_BINDING, PRODUCTION, RETIRED_POOLS, NO_LIMIT_ATOMIC, DEFAULT_CAPS, OLD_DEFAULT_SETUP_CAPS, OLD_DEFAULT_WALLET_BUDGETS, capText, POSITIVE_ATOMIC, HOME_FOLDER, OLDER_HOME_FOLDER, defaultHomeWords, configPath, homeWalletPath, invalid, isPubkey, MAX_OWN_ADDRESSES, isOwnAddressText, salvagePath, clearConfigSalvage, HOST_TARGETS, HOST_NAMES, hostServersKey, CWD_HOSTS, hasPrefix, CODEX_STARTUP_TIMEOUT_SEC, CODEX_TOOL_TIMEOUT_SEC, PINNED_PACKAGE, LAUNCHER_PACKAGE, NPM_VERSION, knownNpmVersion, RECOVERY_WORDS, NPX_WALLET_LINE, RELEASES_URL, npmStartEnvironment,
|
|
55815
|
+
var import_web396, CONFIG_SCHEMA, CONFIG_FILE, NPM_PACKAGE_NAMES, COMMAND_PACKAGE, NPX_PACKAGE, NPX_INSTALL_FLAGS, MCP_SERVER_NAME, OLD_MCP_SERVER_NAMES, P03_BINDING, PRODUCTION, RETIRED_POOLS, NO_LIMIT_ATOMIC, DEFAULT_CAPS, OLD_DEFAULT_SETUP_CAPS, OLD_DEFAULT_WALLET_BUDGETS, capText, POSITIVE_ATOMIC, HOME_FOLDER, OLDER_HOME_FOLDER, defaultHomeWords, configPath, homeWalletPath, invalid, isPubkey, MAX_OWN_ADDRESSES, isOwnAddressText, salvagePath, clearConfigSalvage, HOST_TARGETS, HOST_NAMES, hostServersKey, CWD_HOSTS, hasPrefix, CODEX_STARTUP_TIMEOUT_SEC, CODEX_TOOL_TIMEOUT_SEC, PINNED_PACKAGE, LAUNCHER_PACKAGE, NPM_VERSION, knownNpmVersion, RECOVERY_WORDS, NPX_WALLET_LINE, RELEASES_URL, npmStartEnvironment, WIN_ARG_CODE, NPM_START_KEYS, defaultWalletHome, CMD_UNSAFE, programOf, claudeLineDiffers, WINDOWS_SHELL_CODE, CLAUDE_DESKTOP_FILE, claudeDataDirsCache, CONTINUE_HEADER, tomlString, tomlKey, codexEntryOf, HERMES_TRUST, HERMES_TOOL_TIMEOUT_SEC, hermesCwd, HERMES_OWN_KEYS, HERMES_RESERVED_PROFILES, yamlString, hermesEntryOf, isPlainObject, sameJson, claudeCodeEntry, READ_ONLY_TOOL_NAMES, claudeCodeAllowRules, claudeCodeSettingsFile, UNREADABLE_JSON, JSON_CODEC, indentAt, TEXT_CODEC, RACED;
|
|
55816
55816
|
var init_config = __esm({
|
|
55817
55817
|
"wallet/src/setup/config.mjs"() {
|
|
55818
55818
|
"use strict";
|
|
@@ -55901,7 +55901,7 @@ var init_config = __esm({
|
|
|
55901
55901
|
NPX_WALLET_LINE = /npx (?:--(?:prefer-)?offline )?-y ((?:--no-audit --no-fund )?(?:shinjuku-shield|shinjuku)@(\d+\.\d+\.\d+))((?: (?:setup|restore))(?=\s|$|[^\w-]))?/g;
|
|
55902
55902
|
RELEASES_URL = "https://github.com/ShinjukuStaition/shinjuku-shield#releases";
|
|
55903
55903
|
npmStartEnvironment = (tor) => tor ? { npm_config_offline: "true" } : { npm_config_prefer_offline: "true" };
|
|
55904
|
-
|
|
55904
|
+
WIN_ARG_CODE = /[%&|<>^!"$`\r\n]/;
|
|
55905
55905
|
NPM_START_KEYS = ["npm_config_offline", "npm_config_prefer_offline"];
|
|
55906
55906
|
defaultWalletHome = (home = homedir()) => setupHome({}, home);
|
|
55907
55907
|
CMD_UNSAFE = /[%"\r\n]/;
|
|
@@ -135122,7 +135122,8 @@ ${canonical5}`;
|
|
|
135122
135122
|
return said;
|
|
135123
135123
|
}
|
|
135124
135124
|
if (typeof parsed2.next !== "string") return said;
|
|
135125
|
-
|
|
135125
|
+
const note = typeof nextNote === "function" ? nextNote(parsed2) : nextNote;
|
|
135126
|
+
parsed2.next = `${parsed2.next.replace(/[.\s]+$/, "")}. ${note}`;
|
|
135126
135127
|
const out = JSON.stringify(parsed2, null, /^\s*\{\s*\n/.test(text3) ? 2 : void 0);
|
|
135127
135128
|
return { ...said, text: out, ...blocks ? { content: [{ ...blocks[0], text: out }, ...blocks.slice(1)] } : {} };
|
|
135128
135129
|
}
|
|
@@ -137280,8 +137281,29 @@ ${canonical5}`;
|
|
|
137280
137281
|
return "not_known";
|
|
137281
137282
|
}
|
|
137282
137283
|
}
|
|
137283
|
-
function
|
|
137284
|
-
const
|
|
137284
|
+
function sendTransactionOf(requestId, job = jobs.get(`unshield:${toRecordId(requestId)}`)) {
|
|
137285
|
+
const fromJob = typeof job?.result?.exitTransaction === "string" ? job.result.exitTransaction : void 0;
|
|
137286
|
+
let fromRecord;
|
|
137287
|
+
try {
|
|
137288
|
+
const record = session.openStore().readWal(`self-pay-${moneyId(requestId)}`);
|
|
137289
|
+
fromRecord = typeof record?.exitTransaction === "string" ? record.exitTransaction : void 0;
|
|
137290
|
+
} catch {
|
|
137291
|
+
fromRecord = void 0;
|
|
137292
|
+
}
|
|
137293
|
+
if (fromJob && fromRecord && fromJob !== fromRecord) return { conflict: true };
|
|
137294
|
+
const tx = fromJob ?? fromRecord;
|
|
137295
|
+
return tx ? { tx } : {};
|
|
137296
|
+
}
|
|
137297
|
+
const CANCEL_SEND_WAIT_MS = 15e3;
|
|
137298
|
+
async function newestSendCancel({ signal } = {}) {
|
|
137299
|
+
let found = newestSendJob();
|
|
137300
|
+
if (found?.state === "sending" && !signal?.aborted) {
|
|
137301
|
+
const until = Date.now() + CANCEL_SEND_WAIT_MS;
|
|
137302
|
+
while (found.state === "sending" && !signal?.aborted && Date.now() < until) {
|
|
137303
|
+
await stageOrTimeout(found.job, until - Date.now(), signal);
|
|
137304
|
+
found = { job: found.job, state: sendJobState(found.job) };
|
|
137305
|
+
}
|
|
137306
|
+
}
|
|
137285
137307
|
const receipts2 = "wallet_receipts (kind moves) shows each send of this wallet and its state";
|
|
137286
137308
|
if (!found) {
|
|
137287
137309
|
return refuse12(
|
|
@@ -137302,8 +137324,15 @@ ${canonical5}`;
|
|
|
137302
137324
|
{ ...ids, sendState: "confirming" }
|
|
137303
137325
|
);
|
|
137304
137326
|
}
|
|
137327
|
+
const sent = state2 === "sent" || state2 === "sending" ? sendTransactionOf(job.requestId, job) : {};
|
|
137328
|
+
const txFields = sent.tx ? { exitTransaction: sent.tx } : {};
|
|
137305
137329
|
if (state2 === "sent") {
|
|
137306
|
-
return refuse12(
|
|
137330
|
+
return refuse12(
|
|
137331
|
+
"mcp_unshield_cancel_done",
|
|
137332
|
+
`${what} was already sent${sent.tx ? ` (transaction ${sent.tx})` : ""}; nothing was changed`,
|
|
137333
|
+
sent.tx ? `Nothing to stop. Tell the user it was sent, with transaction ${sent.tx}` : `Nothing to stop. Tell the user it was sent; call wallet_receipts (kind moves) for its transaction and give the user that transaction${sent.conflict ? " (the wallet's two records of it disagree, so check wallet_receipts)" : ""}`,
|
|
137334
|
+
{ ...ids, sendState: "sent", ...txFields }
|
|
137335
|
+
);
|
|
137307
137336
|
}
|
|
137308
137337
|
if (state2 === "ended") {
|
|
137309
137338
|
return refuse12(
|
|
@@ -137323,11 +137352,31 @@ ${canonical5}`;
|
|
|
137323
137352
|
}
|
|
137324
137353
|
return refuse12(
|
|
137325
137354
|
"mcp_unshield_cancel_sending",
|
|
137326
|
-
`the user confirmed ${what} and it is being sent now; a confirmed send cannot be stopped; nothing was changed`,
|
|
137327
|
-
`Nothing was stopped. Tell the user the send goes on and cannot be cancelled
|
|
137328
|
-
{ ...ids, sendState: "sending" }
|
|
137355
|
+
`the user confirmed ${what} and it is being sent now${sent.tx ? ` (transaction ${sent.tx}; the wallet confirms it)` : ""}; a confirmed send cannot be stopped; nothing was changed`,
|
|
137356
|
+
`Nothing was stopped. Tell the user the send goes on and cannot be cancelled${sent.tx ? `, with transaction ${sent.tx}` : ""}. ` + sendRetryNext(job.requestId, sent, { amountAtomic: job.amountAtomic, to: job.to }),
|
|
137357
|
+
{ ...ids, sendState: "sending", ...txFields }
|
|
137329
137358
|
);
|
|
137330
137359
|
}
|
|
137360
|
+
const sendRetryNext = (requestId, sent = {}, { amountAtomic, to } = {}) => `Then call wallet_unshield with request_id "${requestId}"${amountAtomic ? `, amount_atomic "${amountAtomic}"` : ""}${to ? `, and to "${to}"` : ""} (the same arguments: it reads this same send, finishes it after a restart, never asks again and never sends twice) until it answers done, and give the user its transaction${sent.conflict ? " (the wallet's two records of it disagree now: check wallet_receipts)" : ""}; do not offer the history in place of it. Do not call wallet_cancel with this request_id: for a send in parts that stops its unsent payments`;
|
|
137361
|
+
function stageOrTimeout(job, ms, signal) {
|
|
137362
|
+
return new Promise((resolve43) => {
|
|
137363
|
+
let timer;
|
|
137364
|
+
const done = () => {
|
|
137365
|
+
clearTimeout(timer);
|
|
137366
|
+
job.stageWaiters?.delete(done);
|
|
137367
|
+
signal?.removeEventListener?.("abort", done);
|
|
137368
|
+
resolve43();
|
|
137369
|
+
};
|
|
137370
|
+
if (signal?.aborted) {
|
|
137371
|
+
resolve43();
|
|
137372
|
+
return;
|
|
137373
|
+
}
|
|
137374
|
+
(job.stageWaiters ??= /* @__PURE__ */ new Set()).add(done);
|
|
137375
|
+
signal?.addEventListener?.("abort", done, { once: true });
|
|
137376
|
+
timer = setTimeout(done, Math.max(0, ms));
|
|
137377
|
+
timer.unref?.();
|
|
137378
|
+
});
|
|
137379
|
+
}
|
|
137331
137380
|
function cancelMatches(store, requestId) {
|
|
137332
137381
|
const found = [];
|
|
137333
137382
|
let float;
|
|
@@ -137609,7 +137658,7 @@ ${canonical5}`;
|
|
|
137609
137658
|
const cancel = {
|
|
137610
137659
|
name: "wallet_cancel",
|
|
137611
137660
|
title: "Close or stop one unfinished request",
|
|
137612
|
-
description: `Use this when the user says "stop that send", also after this app stopped a call before its answer (then never say nothing was sent: leave request_id out and this reads the newest send of this session, or says to check wallet_receipts), or wants to stop something unfinished, by its request_id: a payment (pay_for_service or inference_chat) that can no longer settle, so its reserved balance comes back; a private send in smaller payments (an older wallet version started it): its smaller payments not sent yet stop and stay in the balance; a wallet_add_funds address nothing reached: it closes. A single send (one exit, a send of the whole balance too) cannot be stopped: the answer says its state. A private send's stop is written under the wallet lock: when another step of this wallet holds it (one of the smaller payments being sent, a payment), this call waits for that step, up to about ${CALL_BUDGET_MS / 1e3} s. Only an answer with cancelled: true means the stop is saved; an answer with stage cancelling means nothing is stopped yet: call wallet_cancel again. It finds the request by itself; when one request_id names two of these, pass kind. A payment whose bytes never left the wallet closes at once. A sent payment closes only once the chain proves it can never land (usually about two minutes after its quote expired); until then it is refused, because closing earlier could let a retry pay twice. Pays nothing and moves nothing.`,
|
|
137661
|
+
description: `Use this when the user says "stop that send", also after this app stopped a call before its answer (then never say nothing was sent: leave request_id out and this reads the newest send of this session, or says to check wallet_receipts), or wants to stop something unfinished, by its request_id: a payment (pay_for_service or inference_chat) that can no longer settle, so its reserved balance comes back; a private send in smaller payments (an older wallet version started it): its smaller payments not sent yet stop and stay in the balance; a wallet_add_funds address nothing reached: it closes. A single send (one exit, a send of the whole balance too) cannot be stopped: the answer says its state and, once it is out, its transaction (exitTransaction; without request_id it waits up to 15 s for it): give the user that transaction. A private send's stop is written under the wallet lock: when another step of this wallet holds it (one of the smaller payments being sent, a payment), this call waits for that step, up to about ${CALL_BUDGET_MS / 1e3} s. Only an answer with cancelled: true means the stop is saved; an answer with stage cancelling means nothing is stopped yet: call wallet_cancel again. It finds the request by itself; when one request_id names two of these, pass kind. A payment whose bytes never left the wallet closes at once. A sent payment closes only once the chain proves it can never land (usually about two minutes after its quote expired); until then it is refused, because closing earlier could let a retry pay twice. Pays nothing and moves nothing.`,
|
|
137613
137662
|
inputSchema: {
|
|
137614
137663
|
type: "object",
|
|
137615
137664
|
properties: {
|
|
@@ -137619,10 +137668,10 @@ ${canonical5}`;
|
|
|
137619
137668
|
additionalProperties: false
|
|
137620
137669
|
},
|
|
137621
137670
|
annotations: { readOnlyHint: false, destructiveHint: false, idempotentHint: true, openWorldHint: true },
|
|
137622
|
-
async run(args, { progress: progress2 } = {}) {
|
|
137671
|
+
async run(args, { progress: progress2, signal } = {}) {
|
|
137623
137672
|
const startedAt = Date.now();
|
|
137624
137673
|
const requestId = args?.request_id;
|
|
137625
|
-
if (requestId === void 0 && (args?.kind === void 0 || args.kind === "send")) return cancelWords(newestSendCancel());
|
|
137674
|
+
if (requestId === void 0 && (args?.kind === void 0 || args.kind === "send")) return cancelWords(await newestSendCancel({ signal }));
|
|
137626
137675
|
if (typeof requestId !== "string" || !REQUEST_ID4.test(requestId)) {
|
|
137627
137676
|
return refuse12("mcp_argument_invalid", "request_id must be 1-128 characters of A-Z a-z 0-9 . _ : -", "pass the request_id of the payment, send, or address to close");
|
|
137628
137677
|
}
|
|
@@ -138013,7 +138062,7 @@ ${canonical5}`;
|
|
|
138013
138062
|
const sendStoppedFailure = (job) => ({
|
|
138014
138063
|
code: SEND_STOPPED,
|
|
138015
138064
|
detail: `the app stopped the call before the send of ${usdcText3(job.amountAtomic)} USDC was signed, so the wallet stopped it; nothing was sent`,
|
|
138016
|
-
next: "Nothing was sent. Tell the user the send was stopped and nothing left the private balance. Send it only if the user asks again: then call wallet_unshield with a NEW request_id (it asks the user again)",
|
|
138065
|
+
next: "Nothing was sent. Tell the user the send was stopped and nothing left the private balance. Send it only if the user asks again: then call wallet_unshield with a NEW request_id (it asks the user again, except for an address the user saved, which sends at once)",
|
|
138017
138066
|
say: `Nothing was sent: the send of ${usdcText3(job.amountAtomic)} USDC was stopped before it was signed.`
|
|
138018
138067
|
});
|
|
138019
138068
|
function jobFailure(kind, job, error, linkHeld = /* @__PURE__ */ new Map()) {
|
|
@@ -138797,16 +138846,30 @@ ${canonical5}`;
|
|
|
138797
138846
|
return { ok: false, why: error?.timedOut === true ? `no answer in ${Math.round(elicitTimeoutMs / 1e3)} s` : "this app did not answer the confirmation" };
|
|
138798
138847
|
}
|
|
138799
138848
|
}
|
|
138800
|
-
function intentDoneAtMs(kind) {
|
|
138849
|
+
function intentDoneAtMs(kind, stopped = {}) {
|
|
138850
|
+
const released = () => {
|
|
138851
|
+
stopped.seen = true;
|
|
138852
|
+
return stopped.release === true ? 0 : void 0;
|
|
138853
|
+
};
|
|
138801
138854
|
return (requestId, store) => {
|
|
138802
138855
|
const job = jobs.get(`${kind}:${toRecordId(requestId)}`);
|
|
138803
138856
|
if (job?.state === "done") return job.doneAtMs;
|
|
138857
|
+
if (kind === "unshield" && job?.state === "failed" && job.error?.code === SEND_STOPPED) return released();
|
|
138804
138858
|
if (job?.state === "failed") return /NEW request_id|Do not retry this request/.test(String(job.error?.next ?? "")) ? 0 : void 0;
|
|
138805
138859
|
if (job) return void 0;
|
|
138806
138860
|
const names = kind === "unshield" ? [`self-pay-${moneyId(requestId)}`, privateSendPlanName(moneyId(requestId))] : [KINDS[kind].walName(requestId)];
|
|
138807
138861
|
for (const name of names) {
|
|
138808
138862
|
const record = store.readWal(name);
|
|
138809
138863
|
if (!record) continue;
|
|
138864
|
+
if (kind === "unshield" && name === names[0] && record.schema === SELF_PAY_WAL_SCHEMA && record.state === "started" && record.refusedCode === SEND_STOPPED) {
|
|
138865
|
+
let signed = true;
|
|
138866
|
+
try {
|
|
138867
|
+
signed = selfPayMayHaveSigned(store, moneyId(requestId));
|
|
138868
|
+
} catch {
|
|
138869
|
+
signed = true;
|
|
138870
|
+
}
|
|
138871
|
+
return signed ? void 0 : released();
|
|
138872
|
+
}
|
|
138810
138873
|
const finished = kind !== "unshield" ? ["published", "foreign_funded", "reclaimed"].includes(record.state) : record.schema === PRIVATE_SEND_WAL_SCHEMA ? record.state === "done" || record.state === "cancelled" && privateSendStatus(store, record).done : ["exited", "released", "abandoned"].includes(record.state);
|
|
138811
138874
|
if (!finished) return void 0;
|
|
138812
138875
|
const at = Date.parse(String(record.doneAt ?? "")) || sentAtMs(record);
|
|
@@ -138851,13 +138914,30 @@ ${canonical5}`;
|
|
|
138851
138914
|
}
|
|
138852
138915
|
return void 0;
|
|
138853
138916
|
}
|
|
138917
|
+
const CLAIM_LEASE_WAIT_MS = 8e3;
|
|
138918
|
+
async function claimUnderLease(task) {
|
|
138919
|
+
const until = Date.now() + CLAIM_LEASE_WAIT_MS;
|
|
138920
|
+
for (; ; ) {
|
|
138921
|
+
try {
|
|
138922
|
+
return await underLease(task);
|
|
138923
|
+
} catch (error) {
|
|
138924
|
+
if (!/wallet_process_locked|wallet_locked/.test(String(error?.message ?? error)) || Date.now() >= until) throw error;
|
|
138925
|
+
await new Promise((resolve43) => {
|
|
138926
|
+
const timer = setTimeout(resolve43, 250);
|
|
138927
|
+
timer.unref?.();
|
|
138928
|
+
});
|
|
138929
|
+
}
|
|
138930
|
+
}
|
|
138931
|
+
}
|
|
138854
138932
|
async function beginWithoutId(kind, args, options) {
|
|
138855
138933
|
const spec = KINDS[kind];
|
|
138856
138934
|
const probe = argumentsOf(kind, { ...args, request_id: "intent-probe" }, { probe: true });
|
|
138857
138935
|
if (probe.refusal) return refuse12(...probe.refusal);
|
|
138858
138936
|
let claimed;
|
|
138937
|
+
const stopped = {};
|
|
138859
138938
|
try {
|
|
138860
|
-
|
|
138939
|
+
const found = intents.find(kind, probe, INTENT_WINDOW_MS, intentDoneAtMs(kind, stopped));
|
|
138940
|
+
if (found && !stopped.seen) claimed = { ...found, created: false };
|
|
138861
138941
|
} catch (error) {
|
|
138862
138942
|
return refuse12(
|
|
138863
138943
|
"mcp_wallet_unreadable",
|
|
@@ -138865,13 +138945,21 @@ ${canonical5}`;
|
|
|
138865
138945
|
`call ${spec.tool} again, or pass your own request_id`
|
|
138866
138946
|
);
|
|
138867
138947
|
}
|
|
138948
|
+
if (!claimed) {
|
|
138949
|
+
try {
|
|
138950
|
+
claimed = await claimUnderLease(() => intents.claim(kind, probe, INTENT_WINDOW_MS, intentDoneAtMs(kind, { release: true })));
|
|
138951
|
+
} catch (error) {
|
|
138952
|
+
return /^(?:wallet_locked|wallet_process_locked)$/.test(errorCode2(error, "wallet_locked")) ? refuse12(
|
|
138953
|
+
"wallet_locked",
|
|
138954
|
+
"another program is using this wallet right now, so this call did not start anything; another app may be running the same request",
|
|
138955
|
+
`This call did not start a ${spec.noun}. Do not tell the user whether money moved: first call ${spec.tool === "wallet_unshield" ? "wallet_cancel with no request_id, or wallet_receipts" : "wallet_receipts"}, or call ${spec.tool} again with the same arguments in about a minute (it reads the same request and never moves money twice). If it repeats, tell the user another program (for example a Shinjuku terminal window) is using the wallet`,
|
|
138956
|
+
{ done: false, say: "The wallet is busy with another program right now, so this request did not start here. I will check and try again.", ...lockedFields() }
|
|
138957
|
+
) : refuse12("mcp_wallet_unreadable", describeError(error, { fallback: "wallet_store_unreadable" }), `call ${spec.tool} again, or pass your own request_id`);
|
|
138958
|
+
}
|
|
138959
|
+
}
|
|
138868
138960
|
if (claimed.created) log(`MCP_INTENT_NEW kind=${kind} requestId=${claimed.requestId}`);
|
|
138869
138961
|
const answer = await begin(kind, { ...args, request_id: claimed.requestId }, options);
|
|
138870
|
-
return withAutoId(
|
|
138871
|
-
answer,
|
|
138872
|
-
spec.tool,
|
|
138873
|
-
"The same call without request_id within 10 minutes after it ends reads this same request; if the user wants to do it again later, ask after 10 minutes or give a new request_id."
|
|
138874
|
-
);
|
|
138962
|
+
return withAutoId(answer, spec.tool, (parsed2) => kind === "unshield" && parsed2.error === SEND_STOPPED ? "The same call without request_id reads this stopped send again; to send it, the user must ask again and you pass a NEW request_id." : "The same call without request_id within 10 minutes after it ends reads this same request; if the user wants to do it again later, ask after 10 minutes or give a new request_id.");
|
|
138875
138963
|
}
|
|
138876
138964
|
function stageChanged(job) {
|
|
138877
138965
|
if (!job.changed) {
|
|
@@ -138887,6 +138975,7 @@ ${canonical5}`;
|
|
|
138887
138975
|
const changed = job.changed;
|
|
138888
138976
|
job.changed = void 0;
|
|
138889
138977
|
changed?.resolve();
|
|
138978
|
+
if (job.stageWaiters?.size) for (const wake of [...job.stageWaiters]) wake();
|
|
138890
138979
|
}
|
|
138891
138980
|
async function begin(kind, args, { waitMs, ask = true, startedAt = Date.now(), progress: progress2, canProgress = false, signal, rpcId } = {}) {
|
|
138892
138981
|
const spec = KINDS[kind];
|
|
@@ -139952,20 +140041,22 @@ ${canonical5}`;
|
|
|
139952
140041
|
const what = `the send of ${usdcText3(record.amountAtomic)} USDC to ${record.mcpTo.slice(0, 4)}...${record.mcpTo.slice(-4)}`;
|
|
139953
140042
|
const call = `call wallet_unshield with request_id "${requestId}", amount_atomic "${record.amountAtomic}", and to "${record.mcpTo}"`;
|
|
139954
140043
|
const ask = `${call} to see its progress (it never sends twice)`;
|
|
140044
|
+
const sent = state2 === "sent" || state2 === "sending" ? sendTransactionOf(requestId) : {};
|
|
140045
|
+
const txFields = sent.tx ? { exitTransaction: sent.tx } : {};
|
|
139955
140046
|
if (state2 === "sent") {
|
|
139956
140047
|
return refuse12(
|
|
139957
140048
|
"mcp_unshield_cancel_done",
|
|
139958
|
-
`${what} was already sent; nothing was changed`,
|
|
139959
|
-
`Nothing to stop. Tell the user it was sent
|
|
139960
|
-
{ requestId, sendState: "sent" }
|
|
140049
|
+
`${what} was already sent${sent.tx ? ` (transaction ${sent.tx})` : ""}; nothing was changed`,
|
|
140050
|
+
sent.tx ? `Nothing to stop. Tell the user it was sent, with transaction ${sent.tx}` : `Nothing to stop. Tell the user it was sent; call wallet_receipts (kind moves) for its transaction and give the user that transaction${sent.conflict ? " (the wallet's two records of it disagree, so check wallet_receipts)" : ""}`,
|
|
140051
|
+
{ requestId, sendState: "sent", ...txFields }
|
|
139961
140052
|
);
|
|
139962
140053
|
}
|
|
139963
140054
|
const how = sendNowWords(state2, intent);
|
|
139964
140055
|
return refuse12(
|
|
139965
140056
|
state2 === "sending" ? "mcp_unshield_cancel_sending" : "mcp_unshield_cancel_single",
|
|
139966
|
-
`${what} ${how}; a send of one exit cannot be stopped; nothing was changed`,
|
|
139967
|
-
`Nothing was stopped. Tell the user ${what} ${how} and cannot be cancelled; ${ask}`,
|
|
139968
|
-
{ requestId, sendState: state2 ?? record.state }
|
|
140057
|
+
`${what} ${how}${sent.tx ? ` (transaction ${sent.tx}; the wallet confirms it)` : ""}; a send of one exit cannot be stopped; nothing was changed`,
|
|
140058
|
+
state2 === "sending" ? `Nothing was stopped. Tell the user ${what} ${how} and cannot be cancelled${sent.tx ? `, with transaction ${sent.tx}` : ""}. ${sendRetryNext(requestId, sent, { amountAtomic: record.amountAtomic, to: record.mcpTo })}` : `Nothing was stopped. Tell the user ${what} ${how} and cannot be cancelled; ${ask}`,
|
|
140059
|
+
{ requestId, sendState: state2 ?? record.state, ...txFields }
|
|
139969
140060
|
);
|
|
139970
140061
|
}
|
|
139971
140062
|
async function cancelUnshield(args, { startedAt = Date.now(), progress: progress2 } = {}) {
|
|
@@ -140556,7 +140647,7 @@ ${canonical5}`;
|
|
|
140556
140647
|
name: "wallet_unshield",
|
|
140557
140648
|
// UX130-13: a host that defers tools may show only the title: it says where a send goes by default.
|
|
140558
140649
|
title: "Send USDC privately",
|
|
140559
|
-
description: `Use this when the user says "send 2 USDC to <address>" or "withdraw to my wallet" (for "my wallet" leave \`to\` out: it uses the address saved at setup, or says how to set one; never ask the user first): it sends amount (USDC, like "2"; or amount_atomic) from the PRIVATE balance as plain USDC to \`to\`, a public Solana address. BEFORE you call it to send all of the balance when wallet_balance showed balanceParts above 1, write to the user that the wallet first gets the balance ready to send (do not tell the user how the wallet stores the balance; some apps show nothing until this call ends). Privately: the chain shows the pool paying the address, not which wallet paid. The wallet's own key (ownAddress in wallet_balance) is this wallet's public address: it holds the public USDC, wallet_shield deposits from it, and wallet_transfer_token sells from it. So it is refused as \`to\`: an exit there would show on chain that the private balance belongs to this wallet. This holds whether or not that key ever deposited: wallet_add_funds deposits come from one-time addresses, not from this key, so never tell the user the deposits came from it. Shinjuku pays every network fee; no SOL is needed. The user's saved own addresses (setup or this app's wallet entry) send at once. Any other address is sent only after the user confirms it in
|
|
140650
|
+
description: `Use this when the user says "send 2 USDC to <address>" or "withdraw to my wallet" (for "my wallet" leave \`to\` out: it uses the address saved at setup, or says how to set one; never ask the user first): it sends amount (USDC, like "2"; or amount_atomic) from the PRIVATE balance as plain USDC to \`to\`, a public Solana address. BEFORE you call it to send all of the balance when wallet_balance showed balanceParts above 1, write to the user that the wallet first gets the balance ready to send (do not tell the user how the wallet stores the balance; some apps show nothing until this call ends). Privately: the chain shows the pool paying the address, not which wallet paid. The wallet's own key (ownAddress in wallet_balance) is this wallet's public address: it holds the public USDC, wallet_shield deposits from it, and wallet_transfer_token sells from it. So it is refused as \`to\`: an exit there would show on chain that the private balance belongs to this wallet. This holds whether or not that key ever deposited: wallet_add_funds deposits come from one-time addresses, not from this key, so never tell the user the deposits came from it. Shinjuku pays every network fee; no SOL is needed. The user's saved own addresses (setup or this app's wallet entry) send at once. Any other address is sent only after the user confirms it in a dialog of this app; a client that cannot ask is refused (mcp_unshield_to_not_allowed) and a decline sends nothing (mcp_unshield_declined). \`to\` must already be able to receive USDC: an address that cannot is refused before any dialog (mcp_unshield_to_invalid). It runs in steps and may wait for the pool's next anchor: the call answers within about 20 s with stage (confirming, queued, refreshing, self-pay = preparing, exit = sending, done; joining = the wallet first gets the balance ready to send, then sends; each call goes on with it (joinSteps: its steps, one after another; doneInMinutesLow to doneInMinutesHigh: the time to say), ok: true); call wallet_unshield again with the SAME request_id, amount, and to for the status (each call answers within about 20 s, at once when the send ends; a dialog may take longer). When the wallet must first get the balance ready to send, the FIRST call answers at once with stage joining and joinTellFirst: true; write its say to the user, then call again with the same request_id at once. One exception: for a send whose balance must first be made ready, when this app sends a progress token with the call, that next call gets the balance ready and then sends, with a progress line every ${JOIN_STEP_MS / 1e3} s ("getting your balance ready to send"; some apps show none of them, so the line is said before the call, as above). It answers when the send is done, or after about ${joinAnswerSeconds(JOIN_CALL_MAX_MS)} s with how far it got (joinsDone; sendState sending: the USDC is leaving, never say nothing moved); then call again with the same request_id. Without a progress token it answers within about 20 s with stage joining: call again until it sends. The same request_id never sends twice, also after a restart. request_id is optional: without it the answer names the id it made, and the same call again within 10 minutes after it ends reads that same send. An optional limit the user sets (the unshield limit) may bound each call and what this wallet sends in any 24 hours, from every app that runs it (mcp_unshield_cap_exceeded: tell the user). Other refusals: mcp_argument_invalid, mcp_request_id_reused, wallet_locked, mcp_tool_disabled, mcp_unshield_failed, and the unshield's own p03_* codes. A call the app stopped or calls rejected or interrupted, or one that failed, may still send: call wallet_cancel (no request_id) before you tell the user anything about that send; never say nothing was sent without it. A send is one payment to \`to\`. ${HOST_BLOCKED_LINE}`,
|
|
140560
140651
|
inputSchema: {
|
|
140561
140652
|
type: "object",
|
|
140562
140653
|
properties: {
|
|
@@ -145702,7 +145793,7 @@ var init_stdioServer = __esm({
|
|
|
145702
145793
|
SUPPORTED_PROTOCOL_VERSIONS = Object.freeze(["2025-06-18", "2025-03-26", "2024-11-05"]);
|
|
145703
145794
|
MAX_LINE_BYTES = 4 * 1024 * 1024;
|
|
145704
145795
|
POSITIVE_ATOMIC7 = /^[1-9][0-9]{0,30}$/;
|
|
145705
|
-
INSTRUCTIONS_BASE = `A self-custody Shinjuku Shield wallet on this machine; no tool takes or returns its keys or passphrase. Each answer's say is one plain sentence for the user; other fields hold numbers. Never tell the user a tool, field, code or protocol name (x402, MCP) unless told to. Map a plain request to one tool: "what is my balance" -> wallet_balance (safe at any time); "add money" / "deposit" / "move USDC in from Phantom or an exchange" -> wallet_add_funds (a one-time address; the next wallet_balance after the USDC arrives makes it private, up to 5 USDC); "shield the USDC on this wallet's own address" -> wallet_shield; "stop" / "cancel" -> wallet_cancel (the request_id of what to stop); "pay this URL" -> pay_for_service (no preview needed); "what does this URL cost" -> check_price (only when asked); "find a paid API for X" -> find_paid_services, then pay its url; "send 2 USDC to <address>" -> wallet_unshield; "show my payments" -> wallet_receipts; "send another token" -> wallet_transfer_token; "which AI models" -> inference_models; "ask an AI model" -> inference_chat; "give my other AI app a private AI" -> inference_server
|
|
145796
|
+
INSTRUCTIONS_BASE = `A self-custody Shinjuku Shield wallet on this machine; no tool takes or returns its keys or passphrase. Each answer's say is one plain sentence for the user; other fields hold numbers. Never tell the user a tool, field, code or protocol name (x402, MCP) unless told to. Map a plain request to one tool: "what is my balance" -> wallet_balance (safe at any time); "add money" / "deposit" / "move USDC in from Phantom or an exchange" -> wallet_add_funds (a one-time address; the next wallet_balance after the USDC arrives makes it private, up to 5 USDC); "shield the USDC on this wallet's own address" -> wallet_shield; "stop" / "cancel" -> wallet_cancel (the request_id of what to stop); "pay this URL" -> pay_for_service (no preview needed); "what does this URL cost" -> check_price (only when asked); "find a paid API for X" -> find_paid_services, then pay its url; "send 2 USDC to <address>" -> wallet_unshield; "show my payments" -> wallet_receipts; "send another token" -> wallet_transfer_token; "which AI models" -> inference_models; "ask an AI model" -> inference_chat; "give my other AI app a private AI" -> inference_server. wallet_balance answers ONE balance (balanceAtomic); pay_for_service pays any paid URL from it. Fields ending in Atomic are atomic units (1000000 = 1 USDC); tell the user USDC. The wallet does its own upkeep. A shield, add-funds or unshield call can run for minutes: call again with the SAME request_id as next says. Pass your own request_id to pay_for_service: the same one never pays or moves money twice (a code ending in _retry_same_request: call again with it). pay_for_service never pays above the spending limits (one payment; 24 hours); with none, the balance is the only bound. Never claim a payment happened unless the answer has a transaction. After a pay or send call that stopped or failed (also one this app calls rejected or interrupted), call wallet_receipts (a payment) or wallet_cancel (a send; no request_id) before you say whether it happened; never say nothing moved without that. Privacy: the chain does not show which wallet paid, but this app and its model provider see every URL, body, price and answer you handle; reach a seller or its domain only through these tools, never yourself (no curl, browser, DNS or DNS-over-HTTPS lookup), also when the user asks for no Tor: that shows their IP address to the site or a DNS company. When an answer's poolSwitch.items[] item has tellUser true, tell the user its message once, in plain words; the wallet moves the balance by itself.`;
|
|
145706
145797
|
SELL_LINE = "To sell or swap a token the wallet holds: wallet_transfer_token.";
|
|
145707
145798
|
OWN_ADDRESS_LINE = '"Send to my (main) wallet": wallet_unshield with no to uses the address saved at setup; never ask for it.';
|
|
145708
145799
|
INSTRUCTIONS = `${INSTRUCTIONS_BASE} ${SELL_LINE} ${OWN_ADDRESS_LINE} ${HOST_BLOCKED_LINE}`;
|
|
@@ -157932,7 +158023,41 @@ var PROGRESS = /^(downloading the setup files|tor: |history: )/;
|
|
|
157932
158023
|
var LABEL = /^ {2}([a-z][a-z -]{1,12}?)( {2,}|(?<=^ {2}.{12}) )(\S.*)$/;
|
|
157933
158024
|
var COMMAND = /^ {2}(npx |shinjuku |claude |codex |cursor |\$ )/;
|
|
157934
158025
|
var NEXT = /^(Next|Status|Home|Then): ?(.*)$/;
|
|
157935
|
-
|
|
158026
|
+
var NOT_PROSE = /^\s|[\\/`$]|\s--|\bnpx\b|\biwr\b|\bshinjuku [a-z]/;
|
|
158027
|
+
var wrapWidth = (columns) => Number.isSafeInteger(columns) && columns >= 40 ? columns - 1 : void 0;
|
|
158028
|
+
function wrapWords(text3, width) {
|
|
158029
|
+
const lines = [];
|
|
158030
|
+
let line = "";
|
|
158031
|
+
for (const word2 of text3.split(" ")) {
|
|
158032
|
+
if (line && `${line} ${word2}`.length > width) {
|
|
158033
|
+
lines.push(line);
|
|
158034
|
+
line = word2;
|
|
158035
|
+
} else line = line ? `${line} ${word2}` : word2;
|
|
158036
|
+
}
|
|
158037
|
+
if (line) lines.push(line);
|
|
158038
|
+
return lines;
|
|
158039
|
+
}
|
|
158040
|
+
function proseKind(line) {
|
|
158041
|
+
if (NOT_PROSE.test(line)) return void 0;
|
|
158042
|
+
if (DONE.test(line)) return { mark: ["\u25C6 ", "crim"], cls: "verm" };
|
|
158043
|
+
if (FAIL.test(line)) return { mark: ["\u25CB ", "crim"], cls: "crim" };
|
|
158044
|
+
if (WARN.test(line)) return { mark: ["! ", "verm"], cls: "verm" };
|
|
158045
|
+
if (STEP.test(line)) return { mark: ["\u25C6 ", "crim"], cls: "bone" };
|
|
158046
|
+
if (PROGRESS.test(line) || COMMAND.test(line) || LABEL.test(line)) return void 0;
|
|
158047
|
+
if (NEXT.test(line)) return { cls: "bone", next: true };
|
|
158048
|
+
return { cls: "dim" };
|
|
158049
|
+
}
|
|
158050
|
+
function paintSetupLine(line, paint2, columns) {
|
|
158051
|
+
const width = wrapWidth(columns);
|
|
158052
|
+
const kind = width && line.length > width && !line.includes("\x1B[") ? proseKind(line) : void 0;
|
|
158053
|
+
if (kind) {
|
|
158054
|
+
const indent = kind.mark ? " " : "";
|
|
158055
|
+
const pieces = wrapWords(line, width - indent.length);
|
|
158056
|
+
if (pieces.length > 1) {
|
|
158057
|
+
const first = kind.mark ? paint2([kind.mark, [pieces[0], kind.cls]]) : kind.next ? paintSetupLine(pieces[0], paint2) : paint2([[pieces[0], kind.cls]]);
|
|
158058
|
+
return [first, ...pieces.slice(1).map((piece) => paint2([[indent, ""], [piece, kind.cls]]))].join("\n");
|
|
158059
|
+
}
|
|
158060
|
+
}
|
|
157936
158061
|
if (line === "" || line.includes("\x1B[")) return line;
|
|
157937
158062
|
if (DONE.test(line)) return paint2([["\u25C6 ", "crim"], [line, "verm"]]);
|
|
157938
158063
|
if (FAIL.test(line)) return paint2([["\u25CB ", "crim"], [line, "crim"]]);
|
|
@@ -157950,20 +158075,20 @@ var THEME_CHILD_ENV = "SHINJUKU_WALLET_THEMED";
|
|
|
157950
158075
|
function terminalThemeOn({ stdout = process.stdout, env = process.env } = {}) {
|
|
157951
158076
|
return Boolean(stdout?.isTTY) && (env.CI ?? "") === "" && env.TERM !== "dumb";
|
|
157952
158077
|
}
|
|
157953
|
-
function paintChunk(chunk, paint2) {
|
|
158078
|
+
function paintChunk(chunk, paint2, columns) {
|
|
157954
158079
|
if (typeof chunk !== "string") return chunk;
|
|
157955
158080
|
const text3 = chunk;
|
|
157956
158081
|
if (text3.includes("\x1B") || text3.length <= 2 || !/[A-Za-z]/.test(text3)) return chunk;
|
|
157957
158082
|
return text3.split("\n").map((line) => {
|
|
157958
158083
|
const [, back, rest] = /^(\r*)([^]*)$/.exec(line);
|
|
157959
|
-
return rest.trim() === "" ? line : `${back}${paintSetupLine(rest, paint2)}`;
|
|
158084
|
+
return rest.trim() === "" ? line : `${back}${paintSetupLine(rest, paint2, back ? void 0 : columns)}`;
|
|
157960
158085
|
}).join("\n");
|
|
157961
158086
|
}
|
|
157962
158087
|
function themeStreams(paint2, streams = [process.stdout, process.stderr]) {
|
|
157963
158088
|
const undo = streams.map((stream) => {
|
|
157964
158089
|
const original = stream.write;
|
|
157965
158090
|
stream.write = function themedWrite(chunk, ...rest) {
|
|
157966
|
-
return original.call(stream, paintChunk(chunk, paint2), ...rest);
|
|
158091
|
+
return original.call(stream, paintChunk(chunk, paint2, stream.isTTY ? stream.columns : void 0), ...rest);
|
|
157967
158092
|
};
|
|
157968
158093
|
return () => {
|
|
157969
158094
|
stream.write = original;
|
|
@@ -157990,10 +158115,16 @@ function commandFooter(columns = 80, { stream = process.stdout, env = process.en
|
|
|
157990
158115
|
` : "";
|
|
157991
158116
|
}
|
|
157992
158117
|
function themedIo(io, paint2) {
|
|
157993
|
-
const draw = (text3) => String(text3).split("\n").map((line) => paintSetupLine(line, paint2)).join("\n");
|
|
157994
|
-
return { ...io, out: (text3) => io.out(draw(text3)), err: (text3) => io.err(draw(text3)) };
|
|
157995
|
-
}
|
|
157996
|
-
var themedAsk = (ask, paint2
|
|
158118
|
+
const draw = (text3, stream) => String(text3).split("\n").map((line) => paintSetupLine(line, paint2, stream?.isTTY ? stream.columns : void 0)).join("\n");
|
|
158119
|
+
return { ...io, out: (text3) => io.out(draw(text3, process.stdout)), err: (text3) => io.err(draw(text3, process.stderr)) };
|
|
158120
|
+
}
|
|
158121
|
+
var themedAsk = (ask, paint2, stream = process.stdout) => (prompt, ...rest) => {
|
|
158122
|
+
const text3 = String(prompt);
|
|
158123
|
+
if (text3.startsWith("? ") || text3.includes("\x1B[")) return ask(prompt, ...rest);
|
|
158124
|
+
const width = stream?.isTTY ? wrapWidth(stream.columns) : void 0;
|
|
158125
|
+
const pieces = width && text3.length + 2 > width && !NOT_PROSE.test(text3) ? wrapWords(text3, width - 2) : [text3];
|
|
158126
|
+
return ask([paint2([["? ", "crim"], [pieces[0], "bone"]]), ...pieces.slice(1).map((piece) => paint2([[" ", ""], [piece, "bone"]]))].join("\n"), ...rest);
|
|
158127
|
+
};
|
|
157997
158128
|
function setupHeader(paint2, columns = 80, title = "set up the wallet") {
|
|
157998
158129
|
return `\x1B[0m\x1B[2J\x1B[H${commandHeader(columns, title)}
|
|
157999
158130
|
`;
|
|
@@ -162197,7 +162328,10 @@ async function runSetupCommand(values, deps) {
|
|
|
162197
162328
|
readsBack ? "Setup keeps the restored wallet on this machine (your keys never leave it), downloads and checks the setup files, and writes config.json." : "Setup makes the wallet on this machine (your keys never leave it), downloads and checks the setup files, and writes config.json.",
|
|
162198
162329
|
// 0.3.97 T4, live proof 2026-10-24: the command on its own line.
|
|
162199
162330
|
"An agent app then starts it with this command:",
|
|
162200
|
-
|
|
162331
|
+
// Row 25 rerun on 0.3.174 (check C): the line a user may copy into an app setup cannot add has the app entry's
|
|
162332
|
+
// --prefix (npm reads no .npmrc of the folder the app starts in); a Windows home with a cmd sign, $ or ` gets none, as
|
|
162333
|
+
// the entry. Quoted for the user's shell (hostShellWord: single quotes on POSIX; Codex round 1 on 1b3aaa99 item 2).
|
|
162334
|
+
` ${oneTimeCommandLine("mcp", npmVersion, { npmArgs: npmPrefixArgs(home, deps.platform ?? process.platform).map((word2) => hostShellWord(word2, deps.platform ?? process.platform)) })}`,
|
|
162201
162335
|
""
|
|
162202
162336
|
],
|
|
162203
162337
|
// The status line too, when a terminal setup started this run and printed it (AB234's live run 2026-11-04 showed
|