shinjuku-shielded 0.3.61 → 0.3.63

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 CHANGED
@@ -7,7 +7,7 @@ local MCP server (stdio) for your agent. Your keys never leave your machine.
7
7
  ## Set up
8
8
 
9
9
  ```sh
10
- npx -y shinjuku-shielded setup
10
+ npx -y --no-audit --no-fund shinjuku-shielded setup
11
11
  ```
12
12
 
13
13
  Setup makes the wallet on this machine, a private passphrase file, and the
@@ -21,13 +21,13 @@ server to that host's config.
21
21
  Claude Code:
22
22
 
23
23
  ```sh
24
- claude mcp add --scope user shinjuku-shielded -- npx -y shinjuku-shielded mcp
24
+ claude mcp add --scope user shinjuku-shielded -- npx -y --no-audit --no-fund shinjuku-shielded mcp
25
25
  ```
26
26
 
27
27
  Claude Desktop (`claude_desktop_config.json`) or Cursor (`~/.cursor/mcp.json`):
28
28
 
29
29
  ```json
30
- { "mcpServers": { "shinjuku-shielded": { "command": "npx", "args": ["-y", "shinjuku-shielded", "mcp"] } } }
30
+ { "mcpServers": { "shinjuku-shielded": { "command": "npx", "args": ["-y", "--no-audit", "--no-fund", "shinjuku-shielded", "mcp"] } } }
31
31
  ```
32
32
 
33
33
  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": "fd8f40cfc0110953e30d8479bfe751545e04952df8faf03b634073d7fd308c78",
5
- "bytes": 12166389,
6
- "sourceCommit": "c40abda927c59b08675a7e8c6067ace24cf24e78",
4
+ "sha256": "f3c652001435e22d3e54232fe742166dd8dd5ae183b92c1a24274c7a52ed137c",
5
+ "bytes": 12174893,
6
+ "sourceCommit": "46ac2745bf8ffeabba0e0cfaf8d052b20d6313e4",
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",
@@ -1282,5 +1282,5 @@
1282
1282
  "version": "1.8.0"
1283
1283
  }
1284
1284
  ],
1285
- "publishedAt": "2026-10-22T06:27:33.519Z"
1285
+ "publishedAt": "2026-10-22T08:20:53.830Z"
1286
1286
  }
package/package.json CHANGED
@@ -1,10 +1,10 @@
1
1
  {
2
2
  "name": "shinjuku-shielded",
3
- "version": "0.3.61",
3
+ "version": "0.3.63",
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": "fd8f40cf",
7
- "shinjukuSha256": "fd8f40cfc0110953e30d8479bfe751545e04952df8faf03b634073d7fd308c78",
6
+ "shinjukuRelease": "f3c65200",
7
+ "shinjukuSha256": "f3c652001435e22d3e54232fe742166dd8dd5ae183b92c1a24274c7a52ed137c",
8
8
  "license": "SEE LICENSE IN LICENSE.txt",
9
9
  "author": "Shinjuku Shielded",
10
10
  "homepage": "https://github.com/ShinjukuStaition/shinjuku-mcp#readme",
@@ -42754,6 +42754,7 @@ async function routeFacilitatorsOverOnion(argv2, {
42754
42754
  live: onions.length,
42755
42755
  spares,
42756
42756
  waitMs: routeWaitMs,
42757
+ label: origin,
42757
42758
  onSpares: () => err(`tor: no onion of ${origin} has answered yet; its ${spares.length} spare onions ${spareHosts} join (Tor may still be fetching the onion addresses)
42758
42759
  `),
42759
42760
  onNone: () => err(`tor: no onion of ${origin} answered its start probe (${liveOnions(group).length} tried); its requests go to its onions in turn and wait for them (Tor may still be building circuits)
@@ -42774,7 +42775,7 @@ async function routeFacilitatorsOverOnion(argv2, {
42774
42775
  }
42775
42776
  }
42776
42777
  for (const [origin, onions] of Object.entries(PINNED_HISTORY_ONIONS)) {
42777
- const group = { onions, path: HISTORY_PROBE_PATH, onNone: () => err(`tor: no history-proxy onion answered its start probe (${onions.length} tried); the pool history reads go to the pinned onion ${new URL(onions[0]).host.slice(0, 8)}... and wait for it
42778
+ const group = { onions, path: HISTORY_PROBE_PATH, label: "the history proxy", onNone: () => err(`tor: no history-proxy onion answered its start probe (${onions.length} tried); the pool history reads go to the pinned onion ${new URL(onions[0]).host.slice(0, 8)}... and wait for it
42778
42779
  `) };
42779
42780
  groups.set(onions.join(" "), group);
42780
42781
  routes.set(origin, group);
@@ -42783,6 +42784,33 @@ async function routeFacilitatorsOverOnion(argv2, {
42783
42784
  } };
42784
42785
  for (const [origin, group] of routes) routedOrigins.set(origin, group.onions);
42785
42786
  const aborts = [];
42787
+ let stopped = false;
42788
+ const race = (group, onions, options) => {
42789
+ let unanswered2 = false;
42790
+ const onNone = options.onNone;
42791
+ const raced = raceOnions(onions, {
42792
+ fetchImpl,
42793
+ timeoutMs: raceTimeoutMs,
42794
+ ...group.path ? { path: group.path } : {},
42795
+ ...options,
42796
+ onNone: () => {
42797
+ unanswered2 = true;
42798
+ onNone?.();
42799
+ }
42800
+ });
42801
+ group.pending = raced.winner.then((onion) => {
42802
+ group.winner = onion;
42803
+ group.pending = void 0;
42804
+ if (!unanswered2 && !raced.stopped) err(`tor: the onion ${hostOf(onion)} of ${group.label} answered first; it serves this run's requests to it
42805
+ `);
42806
+ return onion;
42807
+ });
42808
+ aborts.push(() => {
42809
+ raced.stopped = true;
42810
+ raced.abort();
42811
+ });
42812
+ return raced;
42813
+ };
42786
42814
  for (const group of groups.values()) {
42787
42815
  routedGroups.push(group);
42788
42816
  if (group.onions.length === 1) {
@@ -42791,24 +42819,33 @@ async function routeFacilitatorsOverOnion(argv2, {
42791
42819
  continue;
42792
42820
  }
42793
42821
  const spares = group.spares ?? [];
42794
- const race = raceOnions(liveOnions(group), {
42795
- fetchImpl,
42796
- timeoutMs: raceTimeoutMs,
42797
- ...group.path ? { path: group.path } : {},
42822
+ group.startSpares = race(group, liveOnions(group), {
42798
42823
  ...group.onNone ? { onNone: group.onNone } : {},
42799
42824
  ...spares.length > 0 ? { spares, spareAfterMs, onSpares: () => {
42800
42825
  group.live = group.onions.length;
42801
42826
  group.onSpares?.();
42802
42827
  } } : {}
42803
- });
42804
- group.startSpares = race.startSpares;
42805
- group.pending = race.winner.then((onion) => {
42806
- group.winner = onion;
42807
- group.pending = void 0;
42808
- return onion;
42809
- });
42810
- aborts.push(race.abort);
42811
- }
42828
+ }).startSpares;
42829
+ }
42830
+ const moveOn = (group, onion, why) => {
42831
+ if (stopped || group.winner !== onion || group.pending) return;
42832
+ group.moves = (group.moves ?? 0) + 1;
42833
+ const max = group.onions.length;
42834
+ if (group.moves > max) {
42835
+ if (group.moves === max + 1) err(`tor: no onion of ${group.label} answered after ${max} moves; this run keeps ${hostOf(onion)} and retries there
42836
+ `);
42837
+ return;
42838
+ }
42839
+ (group.down ??= /* @__PURE__ */ new Set()).add(onion);
42840
+ const fresh = group.onions.filter((other) => !group.down.has(other));
42841
+ const others = fresh.length > 0 ? fresh : group.onions.filter((other) => other !== onion);
42842
+ group.live = group.onions.length;
42843
+ group.winner = void 0;
42844
+ err(`tor: the onion ${hostOf(onion)} of ${group.label} gave no answer (${why}); its requests move to the first of ${others.map(hostOf).join(", ")} to answer (move ${group.moves} of ${max})
42845
+ `);
42846
+ race(group, others, { onNone: () => err(`tor: no other onion of ${group.label} answered; its requests go to ${hostOf(others[0])} and wait for it
42847
+ `) });
42848
+ };
42812
42849
  const original = globalThis.fetch;
42813
42850
  const urlOf = (value) => {
42814
42851
  try {
@@ -42821,17 +42858,30 @@ async function routeFacilitatorsOverOnion(argv2, {
42821
42858
  const url = typeof input === "string" || input instanceof URL ? urlOf(String(input)) : input instanceof Request ? urlOf(input.url) : void 0;
42822
42859
  const group = url && routes.get(url.origin);
42823
42860
  if (!group) return original(input, init);
42861
+ const signal = init?.signal ?? (input instanceof Request ? input.signal : void 0);
42824
42862
  const send3 = (onion) => {
42825
42863
  if (onion === void 0) {
42826
42864
  group.startSpares?.();
42827
- const live = liveOnions(group);
42865
+ const up = liveOnions(group).filter((other) => !group.down?.has(other));
42866
+ const live = up.length > 0 ? up : liveOnions(group);
42828
42867
  onion = live[(group.sent = (group.sent ?? 0) + 1) % live.length];
42829
42868
  }
42830
42869
  const target = `${onion}${url.pathname}${url.search}`;
42831
- return original(input instanceof Request ? new Request(target, input) : target, onionInit(init));
42870
+ const sent = original(input instanceof Request ? new Request(target, input) : target, onionInit(init));
42871
+ if (group.onions.length < 2) return sent;
42872
+ return sent.then((response) => {
42873
+ if (onion === group.winner) {
42874
+ group.moves = 0;
42875
+ group.down?.clear();
42876
+ }
42877
+ return response;
42878
+ }, (error) => {
42879
+ const why = noAnswer(error, signal);
42880
+ if (why) moveOn(group, onion, why);
42881
+ throw error;
42882
+ });
42832
42883
  };
42833
42884
  if (group.winner) return send3(group.winner);
42834
- const signal = init?.signal ?? (input instanceof Request ? input.signal : void 0);
42835
42885
  if (!group.waitMs) return untilAborted(group.pending, signal).then(send3);
42836
42886
  let timer;
42837
42887
  const bound = new Promise((resolve38) => {
@@ -42843,12 +42893,13 @@ async function routeFacilitatorsOverOnion(argv2, {
42843
42893
  return {
42844
42894
  routes: new Map([...routes].map(([origin, group]) => [origin, group.onions])),
42845
42895
  stop: () => {
42896
+ stopped = true;
42846
42897
  for (const abort of aborts) abort();
42847
42898
  closeOnionDispatchers();
42848
42899
  }
42849
42900
  };
42850
42901
  }
42851
- var SITE_ONIONS, SITE_SPARE_ONIONS, PINNED_FACILITATOR_ONIONS, PINNED_SPARE_ONIONS, HISTORY_ONIONS, PINNED_HISTORY_ONIONS, HISTORY_PROBE_PATH, FACILITATOR_FLAGS, V3_ONION, DISCOVERY_TIMEOUT_MS, WARM_TIMEOUT_MS, RACE_TIMEOUT_MS, ROUTE_WAIT_MS, SPARE_AFTER_MS, routedGroups, liveOnions, routedOnions, routedOrigins, onionsOfOrigin, routesOverOnion, GLOBAL_DISPATCHER, onionDispatchers;
42902
+ var SITE_ONIONS, SITE_SPARE_ONIONS, PINNED_FACILITATOR_ONIONS, PINNED_SPARE_ONIONS, HISTORY_ONIONS, PINNED_HISTORY_ONIONS, HISTORY_PROBE_PATH, FACILITATOR_FLAGS, V3_ONION, DISCOVERY_TIMEOUT_MS, WARM_TIMEOUT_MS, RACE_TIMEOUT_MS, ROUTE_WAIT_MS, SPARE_AFTER_MS, routedGroups, liveOnions, hostOf, noAnswer, routedOnions, routedOrigins, onionsOfOrigin, routesOverOnion, GLOBAL_DISPATCHER, onionDispatchers;
42852
42903
  var init_facilitatorOnion = __esm({
42853
42904
  "wallet/src/net/facilitatorOnion.mjs"() {
42854
42905
  "use strict";
@@ -42888,6 +42939,12 @@ var init_facilitatorOnion = __esm({
42888
42939
  SPARE_AFTER_MS = ROUTE_WAIT_MS;
42889
42940
  routedGroups = [];
42890
42941
  liveOnions = (group) => group.onions.slice(0, group.live ?? group.onions.length);
42942
+ hostOf = (onion) => `${new URL(onion).host.slice(0, 8)}...`;
42943
+ noAnswer = (error, signal) => {
42944
+ if (signal?.aborted) return signal.reason?.name === "TimeoutError" ? "no answer before the request's timeout" : void 0;
42945
+ if (error?.name === "TimeoutError") return "no answer before the request's timeout";
42946
+ return error instanceof TypeError ? "the stream failed" : void 0;
42947
+ };
42891
42948
  routedOnions = () => [...new Set(routedGroups.flatMap((group) => group.winner ? [group.winner] : liveOnions(group)))];
42892
42949
  routedOrigins = /* @__PURE__ */ new Map();
42893
42950
  onionsOfOrigin = (origin) => routedOrigins.get(origin) ?? PINNED_FACILITATOR_ONIONS[origin] ?? [];
@@ -46874,11 +46931,11 @@ function childRunProxy(env = process.env) {
46874
46931
  return { args, env: clean5 };
46875
46932
  }
46876
46933
  function mayMoveTorCircuit(why = "rate") {
46877
- if (torRotations < TOR_MAX_ROTATIONS && canSwitchTorTag()) return true;
46878
- if (!torRotationsRefused) {
46879
- torRotationsRefused = true;
46934
+ if (torMoves[why] < TOR_MAX_ROTATIONS && canSwitchTorTag()) return true;
46935
+ if (!torMovesRefused[why]) {
46936
+ torMovesRefused[why] = true;
46880
46937
  const what = why === "stall" ? "a request stalled until its timeout" : "the RPC answered HTTP 429";
46881
- process.stderr.write(torRotations >= TOR_MAX_ROTATIONS ? why === "stall" ? `tor: a request stalled again after ${TOR_MAX_ROTATIONS} new circuits; this run keeps its circuit and retries there
46938
+ process.stderr.write(torMoves[why] >= TOR_MAX_ROTATIONS ? why === "stall" ? `tor: a request stalled again after ${TOR_MAX_ROTATIONS} new circuits in a row; this run keeps its circuit and retries there until one answers
46882
46939
  ` : `tor: the RPC still answers HTTP 429 after ${TOR_MAX_ROTATIONS} new circuits; this run keeps its circuit and waits as the RPC asks
46883
46940
  ` : `tor: ${what}, and Node ${process.versions.node} cannot move a run to a new Tor circuit (it has no http.setGlobalProxyFromEnv and no proxy dispatcher of its own); this run keeps its circuit
46884
46941
  `);
@@ -46950,12 +47007,19 @@ function noteAnswer(response) {
46950
47007
  rpcAnswered += 1;
46951
47008
  lastAnswerAt = Date.now();
46952
47009
  }
47010
+ function noteCircuitAnswer(response, circuit) {
47011
+ if (!response.ok || torMoves.stall === 0 || circuit !== torCircuitId) return;
47012
+ torMoves.stall = 0;
47013
+ torMovesRefused.stall = false;
47014
+ process.stderr.write(`tor: the new circuit answered, so this run may again move to a new circuit (up to ${TOR_MAX_ROTATIONS} in a row) when a request stalls
47015
+ `);
47016
+ }
46953
47017
  async function moveToNewTorCircuit(why = "rate") {
46954
47018
  if (!mayMoveTorCircuit(why)) return false;
46955
47019
  switchTorTag();
46956
- torRotations += 1;
46957
- process.stderr.write(why === "stall" ? `tor: a request on this circuit stalled until its timeout, so this run moved to a new Tor circuit (${torRotations} of ${TOR_MAX_ROTATIONS})
46958
- ` : `tor: this circuit kept answering HTTP 429 after the full wait the RPC asked for, so this run moved to a new Tor circuit (${torRotations} of ${TOR_MAX_ROTATIONS})
47020
+ torMoves[why] += 1;
47021
+ process.stderr.write(why === "stall" ? `tor: a request on this circuit stalled until its timeout, so this run moved to a new Tor circuit (${torMoves.stall} of ${TOR_MAX_ROTATIONS} in a row)
47022
+ ` : `tor: this circuit kept answering HTTP 429 after the full wait the RPC asked for, so this run moved to a new Tor circuit (${torMoves.rate} of ${TOR_MAX_ROTATIONS})
46959
47023
  `);
46960
47024
  return true;
46961
47025
  }
@@ -47021,8 +47085,10 @@ async function rpcFetch(input, init) {
47021
47085
  });
47022
47086
  const post = typeof init?.body === "string" ? describeRpcPost(input, init.body) : void 0;
47023
47087
  if (!post?.resendable) {
47088
+ const startedOn = torCircuitId;
47024
47089
  const response = await fetch2(input, init);
47025
47090
  noteAnswer(response);
47091
+ noteCircuitAnswer(response, startedOn);
47026
47092
  markRefusal(response, post);
47027
47093
  return response;
47028
47094
  }
@@ -47038,6 +47104,7 @@ async function rpcFetch(input, init) {
47038
47104
  const circuit = torCircuitId;
47039
47105
  const response = await fetch2(input, init);
47040
47106
  noteAnswer(response);
47107
+ noteCircuitAnswer(response, circuit);
47041
47108
  markRefusal(response, post);
47042
47109
  if (response.status !== 429) return response;
47043
47110
  await response.body?.cancel().catch(() => {
@@ -47141,7 +47208,7 @@ async function proxyEntry(argv2, run5, { err = (text3) => process.stderr.write(t
47141
47208
  }
47142
47209
  return reexec(options.args, options.mode, options.proxy);
47143
47210
  }
47144
- 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, torRotations, torCircuitId, torRotationsRefused, pendingMove, inTorRun, runNetworkMode, isOnionOrigin, ProxyUsageError, isOnionHost, TOR_EXPERT_BUNDLE, TUNNEL_LINE, TOR_INSTALL, OS_NAMES, osKey, torNotRunningMessage, NOTICE, withRunTag, proxyEnv, pacedSoFar, RESENDABLE_METHOD, torCircuit, GLOBAL_DISPATCHER2, laneDispatchers, paymentWarmStop;
47211
+ 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, TUNNEL_LINE, TOR_INSTALL, OS_NAMES, osKey, torNotRunningMessage, NOTICE, withRunTag, proxyEnv, pacedSoFar, RESENDABLE_METHOD, torCircuit, GLOBAL_DISPATCHER2, laneDispatchers, paymentWarmStop;
47145
47212
  var init_proxy = __esm({
47146
47213
  "wallet/src/net/proxy.mjs"() {
47147
47214
  "use strict";
@@ -47175,9 +47242,9 @@ var init_proxy = __esm({
47175
47242
  lastAnswerAt = runStartedAt;
47176
47243
  readSteps = /* @__PURE__ */ new Set();
47177
47244
  pacingSamples = [];
47178
- torRotations = 0;
47245
+ torMoves = { rate: 0, stall: 0 };
47179
47246
  torCircuitId = 0;
47180
- torRotationsRefused = false;
47247
+ torMovesRefused = { rate: false, stall: false };
47181
47248
  inTorRun = () => String(process.env[MARK] ?? "").startsWith("tor ");
47182
47249
  runNetworkMode = () => {
47183
47250
  const mode = String(process.env[MARK] ?? "").split(" ")[0];
@@ -50846,7 +50913,7 @@ function markHistoryChoice(own, choice) {
50846
50913
  function connectSplit(own, historyUrl, commitment = "finalized", { pause: pause3 = pauseFor, notice = noticeOnStderr } = {}) {
50847
50914
  if (historyUrl === void 0) return markHistoryChoice(own, "default");
50848
50915
  if (historyUrl === HISTORY_RPC_OWN) return markHistoryChoice(own, "own");
50849
- const history = connect2(historyUrl, commitment, { timeoutMs: HISTORY_RPC_REQUEST_TIMEOUT_MS });
50916
+ const history = connect2(historyUrl, commitment, { timeoutMs: HISTORY_RPC_REQUEST_TIMEOUT_MS, wrapFetch: trackHistoryAnswers });
50850
50917
  const ownRouted = COUNTED_RPC_METHODS.filter((name) => !HISTORY_RPC_METHODS.includes(name));
50851
50918
  const counts = Object.freeze({
50852
50919
  history: Object.fromEntries([...HISTORY_RPC_METHODS, "getTransactions"].map((name) => [name, 0])),
@@ -51561,7 +51628,7 @@ function depositIntentAddress2({ programId, pool: pool2, depositPublicInputBytes
51561
51628
  programId
51562
51629
  )[0];
51563
51630
  }
51564
- var import_web395, POOL_STATE_LEN2, POOL_STATE_LEN_RING2, POOL_STATE_LEN_RING_642, ANCHOR_MODE_RING2, ANCHOR_RING_HEADER2, ANCHOR_RING_FIRST_SLOT2, ANCHOR_RING_SLOT_LEN2, POOL_LAYOUTS, POOL_STATE_LEN_V22, BUFFER_HEADER_LEN2, MEMO_BUNDLE_BYTES2, PAYLOAD_LENGTH2, PAYLOAD_LENGTH_V22, TRANSITION_KIND2, INSTRUCTION2, COUNTED_RPC_METHODS, HISTORY_RPC_METHODS, PINNED_HISTORY_PROXIES, PINNED_HISTORY_HTTPS, HISTORY_RPC_OWN, historyRpcErrors, HISTORY_RPC_BEHIND_WAIT_MS, HISTORY_RPC_REQUEST_TIMEOUT_MS, HISTORY_RPC_BEHIND_FAST_MS, HISTORY_RPC_BEHIND_FAST_TRIES, HISTORY_RPC_BEHIND_RETRY_STEPS_MS, HISTORY_RPC_BEHIND_CODE, ED25519_SPKI_PREFIX, SIGNATURE_BYTES, VERSION_1_PREFIX, HISTORY_CROSS_CHECK_COUNT, runTransactions, warmedSources, bytes323, MEMO_BATCH_MAX, MEMO_LANES, MEMO_HEDGE_AFTER_MS, MEMO_ATTEMPTS, MEMO_MAX_WAIT_SECONDS, MEMO_RATE_LIMIT_BUDGET_SECONDS, memoGatesByFetch, MEMO_ANSWER_TIMEOUT_MS, MEMO_BODY_TIMEOUT_MS, pauseFor, noticeOnStderr, memoDigestHex, memoFailureText, prefetchedMemosByFetch, MEMO_PREFETCH_LIFE_MS;
51631
+ var import_web395, POOL_STATE_LEN2, POOL_STATE_LEN_RING2, POOL_STATE_LEN_RING_642, ANCHOR_MODE_RING2, ANCHOR_RING_HEADER2, ANCHOR_RING_FIRST_SLOT2, ANCHOR_RING_SLOT_LEN2, POOL_LAYOUTS, POOL_STATE_LEN_V22, BUFFER_HEADER_LEN2, MEMO_BUNDLE_BYTES2, PAYLOAD_LENGTH2, PAYLOAD_LENGTH_V22, TRANSITION_KIND2, INSTRUCTION2, COUNTED_RPC_METHODS, HISTORY_RPC_METHODS, PINNED_HISTORY_PROXIES, PINNED_HISTORY_HTTPS, HISTORY_RPC_OWN, historyRpcErrors, HISTORY_RPC_BEHIND_WAIT_MS, HISTORY_RPC_REQUEST_TIMEOUT_MS, HISTORY_SOURCE_SILENT_MS, historySilentSince, historyRequestsSent, historySourceState, trackHistoryAnswers, HISTORY_RPC_BEHIND_FAST_MS, HISTORY_RPC_BEHIND_FAST_TRIES, HISTORY_RPC_BEHIND_RETRY_STEPS_MS, HISTORY_RPC_BEHIND_CODE, ED25519_SPKI_PREFIX, SIGNATURE_BYTES, VERSION_1_PREFIX, HISTORY_CROSS_CHECK_COUNT, runTransactions, warmedSources, bytes323, MEMO_BATCH_MAX, MEMO_LANES, MEMO_HEDGE_AFTER_MS, MEMO_ATTEMPTS, MEMO_MAX_WAIT_SECONDS, MEMO_RATE_LIMIT_BUDGET_SECONDS, memoGatesByFetch, MEMO_ANSWER_TIMEOUT_MS, MEMO_BODY_TIMEOUT_MS, pauseFor, noticeOnStderr, memoDigestHex, memoFailureText, prefetchedMemosByFetch, MEMO_PREFETCH_LIFE_MS;
51565
51632
  var init_chain2 = __esm({
51566
51633
  "wallet/src/chain.mjs"() {
51567
51634
  "use strict";
@@ -51661,6 +51728,16 @@ var init_chain2 = __esm({
51661
51728
  historyRpcErrors = /* @__PURE__ */ new WeakSet();
51662
51729
  HISTORY_RPC_BEHIND_WAIT_MS = 6e4;
51663
51730
  HISTORY_RPC_REQUEST_TIMEOUT_MS = 2e4;
51731
+ HISTORY_SOURCE_SILENT_MS = 6e4;
51732
+ historyRequestsSent = 0;
51733
+ historySourceState = () => ({ silentSince: historySilentSince, sent: historyRequestsSent });
51734
+ trackHistoryAnswers = (fetch2) => async (input, init) => {
51735
+ historyRequestsSent += 1;
51736
+ historySilentSince ??= Date.now();
51737
+ const response = await fetch2(input, init);
51738
+ historySilentSince = void 0;
51739
+ return response;
51740
+ };
51664
51741
  HISTORY_RPC_BEHIND_FAST_MS = 150;
51665
51742
  HISTORY_RPC_BEHIND_FAST_TRIES = 12;
51666
51743
  HISTORY_RPC_BEHIND_RETRY_STEPS_MS = Object.freeze([500, 1e3, 2e3, 5e3]);
@@ -58781,9 +58858,32 @@ function walletHistoryHomeMarks(store) {
58781
58858
  function latestPrewarmedWalletHistory() {
58782
58859
  return latestPrewarm;
58783
58860
  }
58861
+ function untilHistorySourceSilent(walking, startedAt) {
58862
+ const sentBefore = historySourceState().sent;
58863
+ let timer;
58864
+ const silent = new Promise((_resolve, reject) => {
58865
+ const check = () => {
58866
+ const { silentSince, sent } = historySourceState();
58867
+ if (sent > sentBefore && silentSince !== void 0 && Date.now() - Math.max(silentSince, startedAt) >= HISTORY_SOURCE_SILENT_MS) {
58868
+ markPhase("history-source-silent");
58869
+ reject(new Error("history_rpc_failed", { cause: new Error(
58870
+ `history_source_silent: the history source answered no request for ${HISTORY_SOURCE_SILENT_MS / 1e3} s`
58871
+ ) }));
58872
+ return;
58873
+ }
58874
+ timer = setTimeout(check, 1e3);
58875
+ timer.unref?.();
58876
+ };
58877
+ timer = setTimeout(check, 1e3);
58878
+ timer.unref?.();
58879
+ });
58880
+ walking.catch(() => {
58881
+ });
58882
+ return Promise.race([walking, silent]).finally(() => clearTimeout(timer));
58883
+ }
58784
58884
  async function loadWalletP03HistoryNow(args) {
58785
58885
  const startedAt = Date.now();
58786
- const report = await walkWalletP03HistoryNow(args);
58886
+ const report = await untilHistorySourceSilent(walkWalletP03HistoryNow(args), startedAt);
58787
58887
  if (report !== null && typeof report === "object" && !REPORT_STARTED_AT.has(report)) REPORT_STARTED_AT.set(report, startedAt);
58788
58888
  return report;
58789
58889
  }
@@ -63977,6 +64077,7 @@ var init_errorCodes = __esm({
63977
64077
  "history_rpc_failed",
63978
64078
  "history_rpc_invalid",
63979
64079
  "history_shared_walk_slow",
64080
+ "history_source_silent",
63980
64081
  "house_budget_exhausted",
63981
64082
  "house_deposit_above_pool_cap",
63982
64083
  "house_deposit_below_minimum",
@@ -75474,12 +75575,23 @@ async function readFinalizedClock(connection) {
75474
75575
  return Number(timestamp);
75475
75576
  }
75476
75577
  function startFinalizedChainTime(connection, { reuseRecent = false } = {}) {
75578
+ const keyed = typeof connection === "object" && connection !== null;
75477
75579
  const recentClock = () => {
75478
- const last = typeof connection === "object" && connection !== null ? lastClockAnswers.get(connection) : void 0;
75580
+ const last = keyed ? lastClockAnswers.get(connection) : void 0;
75479
75581
  const age = last === void 0 ? Infinity : performance.now() - last.arrivedAt;
75480
75582
  return age <= PROOF_CHAIN_TIME_REUSE_MS ? { time: last.time, age } : void 0;
75481
75583
  };
75482
75584
  const recent = reuseRecent ? recentClock() : void 0;
75585
+ const inFlight = reuseRecent && recent === void 0 && keyed ? clockReadsInFlight.get(connection) : void 0;
75586
+ if (inFlight !== void 0 && performance.now() - inFlight.startedAt <= PROOF_CHAIN_TIME_REUSE_MS) {
75587
+ return async () => {
75588
+ const answer = await inFlight.answer.catch(() => void 0);
75589
+ const age = answer?.time === void 0 ? Infinity : performance.now() - answer.arrivedAt;
75590
+ if (age > EARLY_CHAIN_TIME_MAX_AGE_MS) return readFinalizedClock(connection);
75591
+ markPhase("chain-time-joined");
75592
+ return answer.time + Math.floor(age / 1e3);
75593
+ };
75594
+ }
75483
75595
  if (recent !== void 0) {
75484
75596
  let fallback;
75485
75597
  const timer = setTimeout(() => {
@@ -75504,6 +75616,16 @@ function startFinalizedChainTime(connection, { reuseRecent = false } = {}) {
75504
75616
  });
75505
75617
  early.catch(() => {
75506
75618
  });
75619
+ if (keyed) {
75620
+ const entry = { startedAt, answer: early.then((time) => ({ time, arrivedAt })) };
75621
+ entry.answer.catch(() => {
75622
+ });
75623
+ clockReadsInFlight.set(connection, entry);
75624
+ early.finally(() => {
75625
+ if (clockReadsInFlight.get(connection) === entry) clockReadsInFlight.delete(connection);
75626
+ }).catch(() => {
75627
+ });
75628
+ }
75507
75629
  return async () => {
75508
75630
  const now = performance.now();
75509
75631
  if (arrivedAt === void 0 && now - startedAt > EARLY_CHAIN_TIME_MAX_AGE_MS) return readFinalizedClock(connection);
@@ -75946,7 +76068,7 @@ function assertProvedPaymentBinding(proved, { poolDomain, inputAccountCommitment
75946
76068
  fail15("proved_request_binding_invalid");
75947
76069
  }
75948
76070
  }
75949
- var import_web3106, MODEL_DIR3, seedBytes5, EARLY_CHAIN_TIME_MAX_AGE_MS, settledNoteExits, PROOF_CHAIN_TIME_REUSE_MS, lastClockAnswers, lastProofRecoveries, lastProofRecovery;
76071
+ var import_web3106, MODEL_DIR3, seedBytes5, EARLY_CHAIN_TIME_MAX_AGE_MS, settledNoteExits, PROOF_CHAIN_TIME_REUSE_MS, lastClockAnswers, clockReadsInFlight, lastProofRecoveries, lastProofRecovery;
75950
76072
  var init_prepareRecoveredPayment = __esm({
75951
76073
  "wallet/src/pay/prepareRecoveredPayment.mjs"() {
75952
76074
  "use strict";
@@ -75970,6 +76092,7 @@ var init_prepareRecoveredPayment = __esm({
75970
76092
  settledNoteExits = /* @__PURE__ */ new Map();
75971
76093
  PROOF_CHAIN_TIME_REUSE_MS = 5e3;
75972
76094
  lastClockAnswers = /* @__PURE__ */ new WeakMap();
76095
+ clockReadsInFlight = /* @__PURE__ */ new WeakMap();
75973
76096
  lastProofRecoveries = /* @__PURE__ */ new Map();
75974
76097
  lastProofRecovery = (store) => lastProofRecoveries.get(store.path);
75975
76098
  }
@@ -103224,7 +103347,7 @@ import { dirname as dirname18, isAbsolute as isAbsolute6, join as join18, resolv
103224
103347
  function retiredPoolText(pool2) {
103225
103348
  const next = RETIRED_POOLS[pool2];
103226
103349
  if (!next) return void 0;
103227
- return `pool ${pool2} is retired: the production facilitator now runs pool ${next}, and nothing serves the old pool. It held no user balance when it was retired. Your old wallet file stays where it is; run npx -y shinjuku-shielded@latest setup to make a wallet for the new pool`;
103350
+ return `pool ${pool2} is retired: the production facilitator now runs pool ${next}, and nothing serves the old pool. It held no user balance when it was retired. Your old wallet file stays where it is; run npx -y --no-audit --no-fund shinjuku-shielded@latest setup to make a wallet for the new pool`;
103228
103351
  }
103229
103352
  function setupHome(env = process.env) {
103230
103353
  return resolve18(env.SHIELDED_WALLET_HOME || join18(homedir2(), ".carbon-shielded-wallet"));
@@ -103327,7 +103450,7 @@ function mcpFlagsFromConfig(home, config) {
103327
103450
  }
103328
103451
  function mcpServerEntry({ home, env = process.env } = {}) {
103329
103452
  const custom2 = env.SHIELDED_WALLET_HOME ? { env: { SHIELDED_WALLET_HOME: home } } : {};
103330
- return { command: "npx", args: ["-y", NPX_PACKAGE, "mcp"], ...custom2 };
103453
+ return { command: "npx", args: ["-y", ...NPX_INSTALL_FLAGS, NPX_PACKAGE, "mcp"], ...custom2 };
103331
103454
  }
103332
103455
  function claudeCodeArgs({ home, env = process.env, platform = process.platform } = {}) {
103333
103456
  return [
@@ -103341,6 +103464,7 @@ function claudeCodeArgs({ home, env = process.env, platform = process.platform }
103341
103464
  ...platform === "win32" ? ["cmd", "/c"] : [],
103342
103465
  "npx",
103343
103466
  "-y",
103467
+ ...NPX_INSTALL_FLAGS,
103344
103468
  NPX_PACKAGE,
103345
103469
  "mcp"
103346
103470
  ];
@@ -103390,6 +103514,11 @@ function hostConfigText({ home, env = process.env, platform = process.platform }
103390
103514
  ...json3.split("\n").map((line) => ` ${line}`)
103391
103515
  ].join("\n");
103392
103516
  }
103517
+ function isOlderSetupEntry(existing, entry) {
103518
+ if (!isPlainObject3(existing) || entry.command !== "npx" || !Array.isArray(entry.args)) return false;
103519
+ const older = { ...entry, args: entry.args.filter((arg) => !NPX_INSTALL_FLAGS.includes(arg)) };
103520
+ return older.args.length !== entry.args.length && sameJson(existing, older);
103521
+ }
103393
103522
  function restrictToOwnerWindows(file, { run: run5 = execFileSync2 } = {}) {
103394
103523
  const system32 = join18(process.env.SystemRoot || "C:/Windows", "System32");
103395
103524
  try {
@@ -103422,7 +103551,7 @@ function addToJsonHost(file, entry, { now = /* @__PURE__ */ new Date(), force =
103422
103551
  const existing = current.mcpServers?.[MCP_SERVER_NAME];
103423
103552
  if (existing !== void 0) {
103424
103553
  if (sameJson(existing, entry)) return { file, changed: false };
103425
- if (!force) {
103554
+ if (!force && !isOlderSetupEntry(existing, entry)) {
103426
103555
  throw new Error(`setup_host_config_conflict: the host's config file already has a different "${MCP_SERVER_NAME}" server, so setup left it alone; rerun setup with --force to replace it (the old file is backed up first), or edit it by hand`);
103427
103556
  }
103428
103557
  }
@@ -103469,7 +103598,7 @@ function addToJsonHost(file, entry, { now = /* @__PURE__ */ new Date(), force =
103469
103598
  }
103470
103599
  return { file, changed: true, ...backup ? { backup } : {} };
103471
103600
  }
103472
- var import_web3118, CONFIG_SCHEMA, CONFIG_FILE, NPX_PACKAGE, MCP_SERVER_NAME, P03_BINDING2, PRODUCTION, RETIRED_POOLS, NO_LIMIT_ATOMIC2, DEFAULT_CAPS, OLD_DEFAULT_SETUP_CAPS, OLD_DEFAULT_WALLET_BUDGETS, capText, POSITIVE_ATOMIC2, configPath, homeWalletPath, invalid3, isPubkey, HOST_TARGETS, WINDOWS_SHELL_CODE, isPlainObject3, sameJson;
103601
+ var import_web3118, CONFIG_SCHEMA, CONFIG_FILE, NPX_PACKAGE, NPX_INSTALL_FLAGS, MCP_SERVER_NAME, P03_BINDING2, PRODUCTION, RETIRED_POOLS, NO_LIMIT_ATOMIC2, DEFAULT_CAPS, OLD_DEFAULT_SETUP_CAPS, OLD_DEFAULT_WALLET_BUDGETS, capText, POSITIVE_ATOMIC2, configPath, homeWalletPath, invalid3, isPubkey, HOST_TARGETS, WINDOWS_SHELL_CODE, isPlainObject3, sameJson;
103473
103602
  var init_config2 = __esm({
103474
103603
  "wallet/src/setup/config.mjs"() {
103475
103604
  "use strict";
@@ -103479,6 +103608,7 @@ var init_config2 = __esm({
103479
103608
  CONFIG_SCHEMA = "shinjuku-shielded/config/v1";
103480
103609
  CONFIG_FILE = "config.json";
103481
103610
  NPX_PACKAGE = "shinjuku-shielded";
103611
+ NPX_INSTALL_FLAGS = Object.freeze(["--no-audit", "--no-fund"]);
103482
103612
  MCP_SERVER_NAME = "shinjuku-shielded";
103483
103613
  P03_BINDING2 = "carbon-shielded-exact/svm-v3";
103484
103614
  PRODUCTION = Object.freeze({
@@ -104634,7 +104764,7 @@ function canonicalJson(value) {
104634
104764
  }
104635
104765
  function channelPublicKey(publicKeyHex = CHANNEL_PUBLIC_KEY_HEX) {
104636
104766
  if (typeof publicKeyHex !== "string" || !HEX642.test(publicKeyHex)) {
104637
- throw fail25("wallet_channel_key_unset", "this wallet build carries no release-channel key, so it trusts only the proof-tool set it pins. Update the wallet: npx -y shinjuku-shielded@latest setup");
104767
+ throw fail25("wallet_channel_key_unset", "this wallet build carries no release-channel key, so it trusts only the proof-tool set it pins. Update the wallet: npx -y --no-audit --no-fund shinjuku-shielded@latest setup");
104638
104768
  }
104639
104769
  return createPublicKey5({ key: Buffer.concat([ED25519_SPKI_PREFIX3, Buffer.from(publicKeyHex, "hex")]), format: "der", type: "spki" });
104640
104770
  }
@@ -105387,7 +105517,7 @@ var init_proofTools = __esm({
105387
105517
  sumsSha256: "a9af32df6b7ff7e3243bd607b7ff582da5732fa422f28afd9b8bc3e9f0d6c741"
105388
105518
  })
105389
105519
  });
105390
- UPDATE_NEXT = "update the wallet: npx -y shinjuku-shielded@latest setup";
105520
+ UPDATE_NEXT = "update the wallet: npx -y --no-audit --no-fund shinjuku-shielded@latest setup";
105391
105521
  HEX643 = /^[0-9a-f]{64}$/;
105392
105522
  DIR2 = /^[0-9a-f]{8}$/;
105393
105523
  SUMS_LINE = /^([0-9a-f]{64}) [ *]([A-Za-z0-9._/-]{1,200})$/;
@@ -106667,7 +106797,7 @@ async function poolProofTools({ home, config, entry, release, facilitator, trust
106667
106797
  });
106668
106798
  } catch (error) {
106669
106799
  if (!UNTRUSTED.test(String(error?.message))) throw error;
106670
- throw fail32("wallet_move_proof_tools_untrusted", `the facilitator names proof-tool set ${set.dir} (SHA256SUMS ${set.sumsSha256}) for pool ${entry.pool}, and neither this wallet build's pin nor the signed release channel vouches for it; nothing was downloaded or moved. Update the wallet (npx -y shinjuku-shielded@latest), or (advanced) after you checked that set out of band run shinjuku-wallet move --trust-proof-tools ${set.sumsSha256} (repeat the flag once per set)`);
106800
+ throw fail32("wallet_move_proof_tools_untrusted", `the facilitator names proof-tool set ${set.dir} (SHA256SUMS ${set.sumsSha256}) for pool ${entry.pool}, and neither this wallet build's pin nor the signed release channel vouches for it; nothing was downloaded or moved. Update the wallet (npx -y --no-audit --no-fund shinjuku-shielded@latest), or (advanced) after you checked that set out of band run shinjuku-wallet move --trust-proof-tools ${set.sumsSha256} (repeat the flag once per set)`);
106671
106801
  }
106672
106802
  }
106673
106803
  const tools = await (deps.installProofTools ?? installProofTools)({ facilitator, toolsRoot: join23(home, "proof-tools"), expected: trusted, fetchImpl });
@@ -106803,7 +106933,7 @@ var init_migration = __esm({
106803
106933
  fail32 = (code2, detail) => new Error(`${code2}: ${detail}`);
106804
106934
  releaseInvalid = (why) => fail32(
106805
106935
  "wallet_move_release_invalid",
106806
- `the facilitator's release document names its pools in a shape this wallet does not accept (${why}); nothing was moved. Update the wallet (npx -y shinjuku-shielded@latest), then run shinjuku-wallet move again`
106936
+ `the facilitator's release document names its pools in a shape this wallet does not accept (${why}); nothing was moved. Update the wallet (npx -y --no-audit --no-fund shinjuku-shielded@latest), then run shinjuku-wallet move again`
106807
106937
  );
106808
106938
  isPubkey2 = (value) => {
106809
106939
  try {
@@ -108027,7 +108157,7 @@ function refusalSay(a, tool, again) {
108027
108157
  return unshown ? "Not sent. This app answered the send question before you could see it. Use an app that shows the question." : "Not sent. The send was not confirmed.";
108028
108158
  }
108029
108159
  if (code2 === "mcp_setup_declined" && unshown) {
108030
- return "Not set up. This app cannot show the setup question. Run npx -y shinjuku-shielded setup in a terminal, then restart this app.";
108160
+ return "Not set up. This app cannot show the setup question. Run npx -y --no-audit --no-fund shinjuku-shielded setup in a terminal, then restart this app.";
108031
108161
  }
108032
108162
  if (code2 === "mcp_setup_declined") return "Not set up. The setup was not confirmed; nothing was created.";
108033
108163
  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.";
@@ -108135,8 +108265,8 @@ function addFundsHeldSay(entries, have = "") {
108135
108265
  if (!nowAny && waiting === 0n) return "";
108136
108266
  const lead = (text3) => have ? `${have}; ${text3}` : `${text3[0].toUpperCase()}${text3.slice(1)}`;
108137
108267
  const now = !nowUnknown ? `${usdcText(nowHeld)} USDC is becoming private now` : nowHeld > 0n ? `${usdcText(nowHeld)} USDC and an amount still being read are becoming private now` : "an amount still being read is becoming private now";
108138
- const later = startMinutes !== null ? `within about 1 minute of your next wallet request${startMinutes > 0 ? ` after about ${minutesText(startMinutes)}` : ""}` : minutesKnown && minutes !== null ? `in about ${minutesText(minutes)}` : "in a few minutes";
108139
- const askLater = startMinutes !== null && startMinutes > 0 ? `a random privacy wait ends in about ${minutesText(startMinutes)}: ask then; it is private 1 minute later` : null;
108268
+ const later = startMinutes !== null ? "in about 1 minute (or at your next ask)" : minutesKnown && minutes !== null ? `in about ${minutesText(minutes)}` : "in a few minutes";
108269
+ const askLater = startMinutes !== null && startMinutes > 0 ? `a random privacy wait ends in about ${minutesText(startMinutes)}: ask then, and again 1 minute later` : null;
108140
108270
  if (nowAny && waiting > 0n) return askLater ? `${lead(`${now}; ${usdcText(waiting)} USDC more is in a random privacy wait: ask in about ${minutesText(startMinutes)}`)}.` : `${lead(`${now}, and ${usdcText(waiting)} USDC more ${later}`)}.`;
108141
108271
  if (nowAny) return `${lead(now)}. Nothing to do.`;
108142
108272
  const arrived = askLater ? `${usdcText(waiting)} USDC arrived; ${askLater}` : `${usdcText(waiting)} USDC arrived and becomes private ${later === "in a few minutes" ? "within a few minutes of your next wallet request" : later}`;
@@ -109679,7 +109809,7 @@ var init_job = __esm({
109679
109809
  ],
109680
109810
  wallet_move_proof_tools_untrusted: [
109681
109811
  "the facilitator names a proof-tool set for a pool of this move that neither this wallet build's pin nor the signed release channel vouches for (see proofToolSet); nothing was downloaded or moved",
109682
- "update the wallet (npx -y shinjuku-shielded@latest), or (advanced) after you checked that set out of band run shinjuku-wallet move --trust-proof-tools <its SHA256SUMS hash>, once per set"
109812
+ "update the wallet (npx -y --no-audit --no-fund shinjuku-shielded@latest), or (advanced) after you checked that set out of band run shinjuku-wallet move --trust-proof-tools <its SHA256SUMS hash>, once per set"
109683
109813
  ],
109684
109814
  wallet_move_proof_tools_unavailable: [
109685
109815
  "the proof tools of a pool of this move could not be downloaded or checked (see toolsCode); nothing was moved, and the tools recorded before stay",
@@ -109736,7 +109866,7 @@ var init_job = __esm({
109736
109866
  wallet_succession_leg_in_flight: ["a move to the new pool is on its way; your money is safe and counts once in your balance", "nothing to do; it lands in about a minute"],
109737
109867
  wallet_succession_target_untrusted: [
109738
109868
  "the switch record names a new pool this wallet does not trust, so nothing moves; your money is safe in the old pool",
109739
- "tell the operator; update the wallet (npx -y shinjuku-shielded@latest)"
109869
+ "tell the operator; update the wallet (npx -y --no-audit --no-fund shinjuku-shielded@latest)"
109740
109870
  ],
109741
109871
  wallet_succession_leg_conflict: ["another copy of this wallet used the same money in the new pool, so this move stopped; nothing was paid", "tell the operator"]
109742
109872
  });
@@ -116433,7 +116563,7 @@ function floatRefusal(error) {
116433
116563
  return [
116434
116564
  code2,
116435
116565
  `Shinjuku refused to forward this seller's payment terms${why}; nothing was paid`,
116436
- "Nothing was paid. Do not retry this URL unchanged. If Shinjuku's words name this wallet's pool, tell your owner to run npx -y shinjuku-shielded@latest setup"
116566
+ "Nothing was paid. Do not retry this URL unchanged. If Shinjuku's words name this wallet's pool, tell your owner to run npx -y --no-audit --no-fund shinjuku-shielded@latest setup"
116437
116567
  ];
116438
116568
  }
116439
116569
  default:
@@ -118640,7 +118770,7 @@ ${canonical5}`;
118640
118770
  return refuse11(
118641
118771
  code2,
118642
118772
  rest || "your private connection (the Tor proxy) is not answering; nothing was paid",
118643
- `Nothing was paid and nothing was sent. Start Tor (or run npx -y shinjuku-shielded@latest setup again), then call ${tool} again with request_id "${requestId}" and ${same2} (it never pays twice)`,
118773
+ `Nothing was paid and nothing was sent. Start Tor (or run npx -y --no-audit --no-fund shinjuku-shielded@latest setup again), then call ${tool} again with request_id "${requestId}" and ${same2} (it never pays twice)`,
118644
118774
  { requestId, paid: false }
118645
118775
  );
118646
118776
  } else if (code2.startsWith("wallet_quote_refused_") || code2.startsWith("fetch_")) {
@@ -118648,7 +118778,8 @@ ${canonical5}`;
118648
118778
  } else {
118649
118779
  next = inference ? `the outcome is not known to be final: ${resume}. Or close an unsent payment with wallet_cancel request_id "${requestId}"; wallet_receipts lists it if it was paid` : `the outcome is not known to be final: call x402_pay again with request_id "${requestId}" (it never pays twice), or close an unsent payment with wallet_cancel request_id "${requestId}"; wallet_receipts lists it if it was paid`;
118650
118780
  }
118651
- return refuse11(code2, rest || "the payment did not finish", next, { requestId });
118781
+ const plainRest = /^[a-z0-9]+(_[a-z0-9]+)+$/.test(rest ?? "") ? PLAIN_REASONS.find(([match]) => match.test(rest))?.[1] : void 0;
118782
+ return refuse11(code2, plainRest ? `the payment did not finish: ${plainRest}` : rest || "the payment did not finish", next, { requestId });
118652
118783
  }
118653
118784
  const linkHeldSeen = /* @__PURE__ */ new Map();
118654
118785
  const LINK_HELD_FRESH_MS = 6e4;
@@ -119044,7 +119175,7 @@ ${canonical5}`;
119044
119175
  const arrivingAll = addFundsOpen.filter((link2) => link2.landed !== true && (link2.state === "shielding" || /^[1-9][0-9]*$/.test(String(link2.heldAtomic ?? ""))));
119045
119176
  const arrivingLine = (arriving) => {
119046
119177
  const amount = /^[1-9][0-9]*$/.test(String(arriving.shieldingAtomic ?? "")) ? `${usdcText2(arriving.shieldingAtomic)} USDC` : /^[1-9][0-9]*$/.test(String(arriving.heldAtomic ?? "")) ? `${usdcText2(arriving.heldAtomic)} USDC` : "USDC (an amount still being read)";
119047
- const when = arriving.state === "shielding" && !arriving.startsAtNextRequest ? "is becoming private now (its deposit transaction was sent; about 1 minute)" : arriving.startsInMinutes > 0 ? `waits about ${minutesText2(arriving.startsInMinutes)} (a random wait hides the link to the deposit); call wallet_balance again after that, and it becomes private within about 1 minute of that request; no step for the user` : "becomes private: its deposit started with this request and takes about 1 minute; if this wallet process ends first, the next wallet request continues it";
119178
+ const when = arriving.state === "shielding" && !arriving.startsAtNextRequest ? "is becoming private now (its deposit transaction was sent; about 1 minute)" : arriving.startsInMinutes > 0 ? `waits about ${minutesText2(arriving.startsInMinutes)} (a random wait hides the link to the deposit); call wallet_balance again after that (that request starts the deposit), and once more about 1 minute later if it is not private yet (a host that ends this process after each answer needs that one); no step for the user` : "becomes private: its deposit started with this request and takes about 1 minute; if this wallet process ends first, the next wallet request continues it";
119048
119179
  return `${amount} arrived at add-funds address "${arriving.requestId}" and ${when}`;
119049
119180
  };
119050
119181
  if (arrivingAll.length === 1) {
@@ -119120,7 +119251,7 @@ ${canonical5}`;
119120
119251
  } catch {
119121
119252
  }
119122
119253
  const sessionLeft = sessionLeftShown(policy, countStore);
119123
- const sessionSummary = `Spending limits: ${capWords(policy.limits.maxPaymentAtomic)} per payment and ${capWords(policy.limits.maxSessionAtomic)} in any 24 hours, for this wallet (every MCP process counts; a pool upgrade starts a new 24-hour count)${sessionLeft === null ? "" : ` (${usdcText2(sessionLeft)} USDC left now)`}; ${usdcText2(policy.sessionSpentAtomic) ?? "0"} USDC paid in the last 24 hours. They come from this MCP server's launch line in the host (--max-payment and --max-session, in USDC like 0.05), else from the limits setup recorded. To change them, edit those flags in the host's MCP entry, or run npx -y shinjuku-shielded setup --yes --max-payment <usdc> --max-session <usdc> in a terminal; then restart the host. The wallet file also holds its own limits (--max-payment, and --max-cumulative for all payments together): npx -y shinjuku-shielded limits shows and changes them`;
119254
+ const sessionSummary = `Spending limits: ${capWords(policy.limits.maxPaymentAtomic)} per payment and ${capWords(policy.limits.maxSessionAtomic)} in any 24 hours, for this wallet (every MCP process counts; a pool upgrade starts a new 24-hour count)${sessionLeft === null ? "" : ` (${usdcText2(sessionLeft)} USDC left now)`}; ${usdcText2(policy.sessionSpentAtomic) ?? "0"} USDC paid in the last 24 hours. They come from this MCP server's launch line in the host (--max-payment and --max-session, in USDC like 0.05), else from the limits setup recorded. To change them, edit those flags in the host's MCP entry, or run npx -y --no-audit --no-fund shinjuku-shielded setup --yes --max-payment <usdc> --max-session <usdc> in a terminal; then restart the host. The wallet file also holds its own limits (--max-payment, and --max-cumulative for all payments together): npx -y --no-audit --no-fund shinjuku-shielded limits shows and changes them`;
119124
119255
  return json2({
119125
119256
  ok: true,
119126
119257
  ...reportPublic,
@@ -119915,7 +120046,10 @@ ${canonical5}`;
119915
120046
  function jobFailure(kind, job, error, linkHeld = /* @__PURE__ */ new Map()) {
119916
120047
  const line = describeError(error, { fallback: KINDS[kind].failCode, safeText: SAFE_TEXT });
119917
120048
  let code2 = line.split(/[\s:;(]/, 1)[0];
119918
- let detail = line.slice(code2.length).replace(/^[:;]\s*/, "").trim() || `the ${KINDS[kind].noun} did not finish`;
120049
+ const plain = PLAIN_REASONS.find(([match]) => match.test(code2))?.[1];
120050
+ let detail = line.slice(code2.length).replace(/^[:;]\s*/, "").trim() || (plain ? `the ${KINDS[kind].noun} did not finish: ${plain}` : `the ${KINDS[kind].noun} did not finish`);
120051
+ const plainDetail = /^[a-z0-9]+(_[a-z0-9]+)+$/.test(detail) ? PLAIN_REASONS.find(([match]) => match.test(detail))?.[1] : void 0;
120052
+ if (plainDetail) detail = `the ${KINDS[kind].noun} did not finish: ${plainDetail}`;
119919
120053
  let next;
119920
120054
  let joinStage = false;
119921
120055
  const joinAt = () => job.joinAtMs ??= joinStartOf(job);
@@ -122782,7 +122916,7 @@ ${canonical5}`;
122782
122916
  const torRefusal = () => refuse11(
122783
122917
  "inference_tor_required",
122784
122918
  "inference sends the prompt to usePod and the model's provider, so this wallet sends it only from a --tor or --proxy run, where they see the proxy's exit and not this machine's IP. This MCP server was started without --tor or --proxy; nothing was sent or paid",
122785
- "Tell the user to add --tor to this MCP server's launch line in the host (for example `npx -y shinjuku-shielded mcp --tor`, with Tor's HTTPTunnelPort 127.0.0.1:9080 on), or --proxy http://host:port for an HTTP proxy they trust, then restart the server and call inference_chat again"
122919
+ "Tell the user to add --tor to this MCP server's launch line in the host (for example `npx -y --no-audit --no-fund shinjuku-shielded mcp --tor`, with Tor's HTTPTunnelPort 127.0.0.1:9080 on), or --proxy http://host:port for an HTTP proxy they trust, then restart the server and call inference_chat again"
122786
122920
  );
122787
122921
  const inferenceModels = {
122788
122922
  name: "inference_models",
@@ -124067,6 +124201,9 @@ var init_tools = __esm({
124067
124201
  [/^mcp_balance_unknown$|no_spendable_account/, "the balance could not be read yet"],
124068
124202
  [/insufficient/, "an open payment held part of the balance"],
124069
124203
  [POOL_LAYOUT_CODE, "this wallet version cannot read the pool (a newer version can)"],
124204
+ // ab-18 2026-10-22: a 445 s unshield answered only "the unshield did not finish".
124205
+ [/^history_source_silent$/, "the pool's public history source answered nothing for 60 s (with --tor, a slow or dead Tor circuit)"],
124206
+ [/^history_rpc_failed$|compact_history_source_unavailable/, "the pool's public history did not answer in time (with --tor, a slow or dead Tor circuit)"],
124070
124207
  [/memo_service|relay|facilitator|unavailable|rate_limited|fetch|timeout|timed_out|network|socket|econn|rpc|blockhash/i, "the facilitator or the network did not answer"],
124071
124208
  [/prove|proof|prover/, "the private proof did not finish"]
124072
124209
  ];
@@ -124178,7 +124315,7 @@ var init_tools = __esm({
124178
124315
  "inference_models",
124179
124316
  "wallet_receive_shielded"
124180
124317
  ]);
124181
- SETUP_TERMINAL_NEXT = "Tell the user to run `npx -y shinjuku-shielded setup` in a terminal on this machine, then restart this MCP server in the host";
124318
+ SETUP_TERMINAL_NEXT = "Tell the user to run `npx -y --no-audit --no-fund shinjuku-shielded setup` in a terminal on this machine, then restart this MCP server in the host";
124182
124319
  SETUP_POLL_NEXT = `call shinjuku_setup again in ${POLL_SECONDS3} s for the status (it never creates a second wallet)`;
124183
124320
  PRIVATE_INFERENCE_WHY = "Your agent then buys AI answers from usePod, paid from your shielded balance over Tor; usePod and the model see the prompt, not who paid.";
124184
124321
  PRIVATE_INFERENCE_NEXT = " Private inference is on: config.json records Tor, so restart this MCP server in the host now; it then runs behind Tor (Tor must run with HTTPTunnelPort 127.0.0.1:9080), and until then every wallet tool and inference_chat stay refused. After the restart: fund the wallet with wallet_add_funds (it gives a one-time address; USDC sent there from any wallet becomes private a few minutes after it arrives, at the next wallet call; no other step), then call inference_chat (with no prompt it lists the models; a short qwen3-8-flash answer costs about 0.001 USDC, 0.011 USDC when usePod offers only its standard payment).";
@@ -124510,11 +124647,11 @@ function startUpdateNotice({ facilitator, log = () => {
124510
124647
  const ready = check === false ? Promise.resolve() : Promise.resolve().then(() => check({ facilitator })).then((found) => {
124511
124648
  if (!found) return;
124512
124649
  update3 = found;
124513
- log(`MCP_UPDATE_AVAILABLE release=${found.current} running=${found.running}: restart this MCP server to load it (a fixed-version host: npx -y ${NPX_PACKAGE}@latest mcp); nothing was downloaded`);
124650
+ log(`MCP_UPDATE_AVAILABLE release=${found.current} running=${found.running}: restart this MCP server to load it (a fixed-version host: npx -y --no-audit --no-fund ${NPX_PACKAGE}@latest mcp); nothing was downloaded`);
124514
124651
  }, () => {
124515
124652
  });
124516
124653
  let shown = false;
124517
- const field4 = () => ({ available: true, release: update3.current, running: update3.running, command: `npx -y ${NPX_PACKAGE}@latest mcp`, detail: updateNoticeLine(update3) });
124654
+ const field4 = () => ({ available: true, release: update3.current, running: update3.running, command: `npx -y --no-audit --no-fund ${NPX_PACKAGE}@latest mcp`, detail: updateNoticeLine(update3) });
124518
124655
  return {
124519
124656
  ready,
124520
124657
  current: () => update3,
@@ -124792,6 +124929,17 @@ async function openWalletServer({
124792
124929
  if (typeof tools.warmHistory === "function") tools.warmHistory({ afterBoot: warmDiscover });
124793
124930
  else warmDiscover?.();
124794
124931
  let rootsLanded = Promise.resolve();
124932
+ let toolRootsLanded;
124933
+ const rootsForTools = (install, started) => {
124934
+ let timer;
124935
+ const bound = new Promise((done) => {
124936
+ timer = setTimeout(done, TOOL_ROOTS_WAIT_MS);
124937
+ timer.unref?.();
124938
+ });
124939
+ return Promise.race([Promise.resolve(install).then(() => {
124940
+ }, () => {
124941
+ }), bound]).finally(() => clearTimeout(timer)).then(() => started);
124942
+ };
124795
124943
  if (proofToolsRefresh?.home) {
124796
124944
  let timer;
124797
124945
  const late2 = new Promise((done) => {
@@ -124817,15 +124965,19 @@ async function openWalletServer({
124817
124965
  setFamilyRootResolver(() => void 0);
124818
124966
  return { state: "unproven" };
124819
124967
  };
124820
- const land = Promise.race([install(), late2]).finally(() => clearTimeout(timer)).then((installed) => {
124968
+ const installing = install();
124969
+ const land = Promise.race([installing, late2]).finally(() => clearTimeout(timer)).then((installed) => {
124821
124970
  if (installed.state === "timeout") setFamilyRootResolver(() => void 0);
124822
124971
  if (installed.state !== "none") log(`FAMILY_ROOTS ${installed.state}${installed.seq === void 0 ? "" : ` seq=${installed.seq}`}${installed.count === void 0 ? "" : ` count=${installed.count}`}${installed.code ? ` code=${installed.code}` : ""}`);
124823
124972
  });
124824
124973
  if (!rootsInBackground) await land;
124825
- else rootsLanded = land.catch((error) => {
124826
- setFamilyRootResolver(() => void 0);
124827
- log(`FAMILY_ROOTS failed code=${String(error?.message ?? error).split(/[\s:;(]/, 1)[0]}`);
124828
- });
124974
+ else {
124975
+ rootsLanded = land.catch((error) => {
124976
+ setFamilyRootResolver(() => void 0);
124977
+ log(`FAMILY_ROOTS failed code=${String(error?.message ?? error).split(/[\s:;(]/, 1)[0]}`);
124978
+ });
124979
+ toolRootsLanded = rootsForTools(installing, rootsLanded);
124980
+ }
124829
124981
  } else if (rootsInBackground && cliRootsLate !== void 0) {
124830
124982
  let timer;
124831
124983
  const late2 = new Promise((done) => {
@@ -124838,6 +124990,7 @@ async function openWalletServer({
124838
124990
  setFamilyRootResolver(() => void 0);
124839
124991
  log("FAMILY_ROOTS timeout");
124840
124992
  });
124993
+ toolRootsLanded = rootsForTools(cliRootsLate, rootsLanded);
124841
124994
  }
124842
124995
  if (rootsInBackground) {
124843
124996
  for (let index = 0; index < tools.length; index += 1) {
@@ -124845,7 +124998,7 @@ async function openWalletServer({
124845
124998
  if (ROOTS_FREE_TOOLS.has(tool.name)) continue;
124846
124999
  tools[index] = { ...tool, run: async (...args) => {
124847
125000
  const startedAt = Date.now();
124848
- await rootsLanded;
125001
+ await (toolRootsLanded ?? rootsLanded);
124849
125002
  if (Date.now() - startedAt >= 20) log(`MCP_ROOTS_WAIT tool=${tool.name} ms=${Date.now() - startedAt}`);
124850
125003
  return tool.run(...args);
124851
125004
  } };
@@ -125123,7 +125276,7 @@ async function runSetupModeServer({
125123
125276
  }
125124
125277
  return { closed: ended };
125125
125278
  }
125126
- var import_web3134, SUPPORTED_PROTOCOL_VERSIONS, SERVER_VERSION, 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, UPDATE_NOTICE_TEXT, updateNoticeLine, LAUNCH_NOTICE_TOOLS, withLaunchLine, capRequired, setupInvalid, ROOTS_FREE_TOOLS, MCP_CLOSE_BOUND_MS, MCP_CLOSE_HISTORY_BOUND_MS, MCP_CLOSE_UNREADABLE_BOUND_MS, MCP_CLOSE_POLL_MS, closeHistoryBusy, SETUP_INSTRUCTIONS;
125279
+ var import_web3134, SUPPORTED_PROTOCOL_VERSIONS, SERVER_VERSION, 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, 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;
125127
125280
  var init_stdioServer = __esm({
125128
125281
  "wallet/src/mcp/stdioServer.mjs"() {
125129
125282
  "use strict";
@@ -125162,7 +125315,7 @@ var init_stdioServer = __esm({
125162
125315
  UPDATE_NOTICE_TOOLS = Object.freeze(["wallet_balance", "x402_pay", "inference_chat"]);
125163
125316
  UPDATE_NOTICE_MAX_TEXT = 262144;
125164
125317
  UPDATE_NOTICE_TEXT = "A new wallet version is ready. Restart this MCP server in your app (or restart the app): each start loads the latest version. Nothing was downloaded or changed yet, and this version keeps working until then.";
125165
- updateNoticeLine = (update3) => `Tell the user: ${UPDATE_NOTICE_TEXT} (release ${update3.current}; this wallet runs ${update3.running}; a host that starts a fixed version runs npx -y ${NPX_PACKAGE}@latest mcp instead.)`;
125318
+ updateNoticeLine = (update3) => `Tell the user: ${UPDATE_NOTICE_TEXT} (release ${update3.current}; this wallet runs ${update3.running}; a host that starts a fixed version runs npx -y --no-audit --no-fund ${NPX_PACKAGE}@latest mcp instead.)`;
125166
125319
  LAUNCH_NOTICE_TOOLS = Object.freeze(["wallet_balance", "wallet_status"]);
125167
125320
  withLaunchLine = (instructions2, line) => !line ? instructions2 : () => `${typeof instructions2 === "function" ? instructions2() : instructions2} Tell the user: ${line}`;
125168
125321
  capRequired = (detail) => {
@@ -125171,6 +125324,7 @@ var init_stdioServer = __esm({
125171
125324
  setupInvalid = (detail) => {
125172
125325
  throw new Error(`mcp_setup_invalid: ${detail}; the MCP server did not start and nothing was moved`);
125173
125326
  };
125327
+ TOOL_ROOTS_WAIT_MS = 6e4;
125174
125328
  ROOTS_FREE_TOOLS = /* @__PURE__ */ new Set(["x402_pay", "inference_chat", "inference_models", "x402_preview", "x402_discover"]);
125175
125329
  MCP_CLOSE_BOUND_MS = 5e3;
125176
125330
  MCP_CLOSE_HISTORY_BOUND_MS = 45e3;
@@ -145998,7 +146152,7 @@ function identityOf(facilitator, release, successors = []) {
145998
146152
  const pool2 = successors.includes(served.pool) ? served.pool : PRODUCTION.pool;
145999
146153
  for (const [name, value] of Object.entries(served)) {
146000
146154
  if (value !== null && value !== void 0 && value !== (name === "pool" ? pool2 : PRODUCTION[name])) {
146001
- throw fail40("setup_identity_mismatch", `the production facilitator's release names another ${name} than this wallet build, and no signed succession links it; nothing was created. Run npx -y shinjuku-shielded@latest setup; if the latest build says the same, the facilitator is not serving the production pool`);
146155
+ throw fail40("setup_identity_mismatch", `the production facilitator's release names another ${name} than this wallet build, and no signed succession links it; nothing was created. Run npx -y --no-audit --no-fund shinjuku-shielded@latest setup; if the latest build says the same, the facilitator is not serving the production pool`);
146002
146156
  }
146003
146157
  }
146004
146158
  return { pool: pool2, program: PRODUCTION.program, network: PRODUCTION.network, asset: PRODUCTION.asset };
@@ -151311,7 +151465,7 @@ async function runMcpFirstRun(values, deps) {
151311
151465
  ` : "Shinjuku Shielded is not set up on this machine yet (no config.json, wallet, passphrase file, or proof tools).\n");
151312
151466
  const answer = String(await deps.ask("Set up Shinjuku Shielded now? (y/n) ")).trim();
151313
151467
  if (!/^y(es)?$/i.test(answer)) {
151314
- throw new PublicFailure("mcp_not_set_up: the wallet is not set up, so the MCP server did not start and nothing was created; run shinjuku-wallet setup (npx -y shinjuku-shielded setup) when you are ready");
151468
+ throw new PublicFailure("mcp_not_set_up: the wallet is not set up, so the MCP server did not start and nothing was created; run shinjuku-wallet setup (npx -y --no-audit --no-fund shinjuku-shielded setup) when you are ready");
151315
151469
  }
151316
151470
  const setupValues = new Map(Object.entries(setupOptionsOf(values, home)).filter(([key]) => key !== "home").map(([key, value]) => [`--${key.replace(/[A-Z]/g, (c) => `-${c.toLowerCase()}`)}`, value]));
151317
151471
  await runSetupCommand(setupValues, deps);
@@ -151559,6 +151713,7 @@ function addToHosts(targets, home, deps, { force = false } = {}) {
151559
151713
  const status = deps.runClaudeCli(claudeCodeArgs(options));
151560
151714
  io.out(status === 0 ? "Added to Claude Code (user scope).\n" : `Claude Code did not take the server (claude CLI exit ${status}); run it yourself:
151561
151715
  ${claudeCodeCommand(options)}
151716
+ (if it says the server already exists, run claude mcp remove --scope user ${MCP_SERVER_NAME} first, then the line above)
151562
151717
  `);
151563
151718
  continue;
151564
151719
  }
@@ -151607,7 +151762,7 @@ async function runSetupCommand(values, deps) {
151607
151762
  if (interactive && !deps.stdinIsTTY()) {
151608
151763
  const line = ["setup", "--yes", ...setupArgvOf(values), ...childRunProxy(deps.env).args].map(shellWord).join(" ");
151609
151764
  throw new UsageError(
151610
- `setup asks its questions in a terminal; in a script or a pipe pass --yes: npx -y shinjuku-shielded ${line} (add any of --max-payment, --max-session, --max-cumulative, --prefer-tor, --private-inference)`,
151765
+ `setup asks its questions in a terminal; in a script or a pipe pass --yes: npx -y --no-audit --no-fund shinjuku-shielded ${line} (add any of --max-payment, --max-session, --max-cumulative, --prefer-tor, --private-inference)`,
151611
151766
  COMMAND_BY_NAME.get("setup")
151612
151767
  );
151613
151768
  }
@@ -151622,7 +151777,7 @@ async function runSetupCommand(values, deps) {
151622
151777
  ...introduced ? [] : [
151623
151778
  "Shinjuku Shielded: a self-custody wallet that pays x402 URLs privately from a shielded USDC balance.",
151624
151779
  "Setup makes the wallet on this machine (your keys never leave it), downloads and checks the proof tools, and writes config.json.",
151625
- "An agent host then starts it with one command: npx -y shinjuku-shielded mcp",
151780
+ "An agent host then starts it with one command: npx -y --no-audit --no-fund shinjuku-shielded mcp",
151626
151781
  ""
151627
151782
  ],
151628
151783
  old ? `Status: ${missing.includes("pool-retired") ? `set up before for a retired pool: ${retiredPoolText(old.pool).split("; run ")[0]}. This run moves config.json to the new pool and makes its wallet` : missing.length ? `set up before; missing now: ${missing.join(", ")}` : "set up; every piece is checked again"} (home ${home}).` : `Home: ${home}`,
@@ -152407,7 +152562,7 @@ var COMMANDS = [
152407
152562
  `${CLI2} mcp --max-payment 0.05 --max-session 0.2 --max-shield 2 --unshield-to <your public address> --max-unshield 1 --exit-proof-tools exit-proof-tools.json --profile public-profile.json ${PAYER_SESSION_BASE}`
152408
152563
  ],
152409
152564
  notes: [
152410
- `Zero config: after ${CLI2} setup (npx -y shinjuku-shielded setup), mcp with no --pool and no --wallet reads config.json from SHIELDED_WALLET_HOME (default ~/.carbon-shielded-wallet): the wallet, the passphrase file, the proof tools, the caps, and Tor. A flag on the command line still wins. Agent host config: npx -y shinjuku-shielded mcp (Claude Code: claude mcp add --scope user shinjuku-shielded -- npx -y shinjuku-shielded mcp). Before setup, mcp in a terminal asks to run setup; started by an agent host (stdin is not a terminal), it serves SETUP MODE: shinjuku_setup and wallet_status, and every money tool answers wallet_not_set_up. shinjuku_setup asks the user to confirm in the host (MCP elicitation; never a secret), runs setup in the background (the same call answers its stage), then switches the same server to the wallet tools (notifications/tools/list_changed). A host without elicitation is told to run setup in a terminal.`,
152565
+ `Zero config: after ${CLI2} setup (npx -y --no-audit --no-fund shinjuku-shielded setup), mcp with no --pool and no --wallet reads config.json from SHIELDED_WALLET_HOME (default ~/.carbon-shielded-wallet): the wallet, the passphrase file, the proof tools, the caps, and Tor. A flag on the command line still wins. Agent host config: npx -y --no-audit --no-fund shinjuku-shielded mcp (Claude Code: claude mcp add --scope user shinjuku-shielded -- npx -y --no-audit --no-fund shinjuku-shielded mcp). Before setup, mcp in a terminal asks to run setup; started by an agent host (stdin is not a terminal), it serves SETUP MODE: shinjuku_setup and wallet_status, and every money tool answers wallet_not_set_up. shinjuku_setup asks the user to confirm in the host (MCP elicitation; never a secret), runs setup in the background (the same call answers its stage), then switches the same server to the wallet tools (notifications/tools/list_changed). A host without elicitation is told to run setup in a terminal.`,
152411
152566
  `Add it to an agent host with one line, for example Claude Code: claude mcp add shinjuku-pay -- node shinjuku-wallet.mjs mcp --max-payment 0.05 --max-session 0.2 --tor ${PAYER_SESSION_BASE} (the passphrase comes from ${PASSPHRASE_ENV2} or --passphrase-file; never a tool argument).`,
152412
152567
  `Claude Desktop, or any MCP host that takes a JSON config (claude_desktop_config.json: "mcpServers"), with absolute paths (yours differ; on Windows write C:/Users/you/...): {"mcpServers":{"shinjuku-pay":{"command":"node","args":["/home/you/shinjuku/shinjuku-wallet.mjs","mcp","--max-payment","0.05","--max-session","0.2","--pool","${GUIDE.pool}","--passphrase-file","/home/you/shinjuku/passphrase.txt","--proof-tools","/home/you/shinjuku/proof-tools.json","--program","${GUIDE.program}","--memo-service","${GUIDE.facilitator}","--tor"],"env":{"SHIELDED_WALLET_HOME":"/home/you/.shielded-wallet"}}}}. A host starts the server from its own folder, so a relative path does not work there. Without --rpc-file the RPC reads go to the facilitator relay.`,
152413
152568
  "Payments, in this order: shielded-exact (needs --proof-tools), then standard exact through Shinjuku (you pay Shinjuku privately, price + a small fee; Shinjuku pays the seller). A seller that offers only scheme confidential (hidden amounts) is refused, and nothing is paid: hidden-amount payments are retired (the program behind them closed on 2026-10-11).",
@@ -152445,9 +152600,9 @@ var COMMANDS = [
152445
152600
  bool2("--private-inference", 'answer yes to "Set your LLM to private inference now?": your agent buys AI answers from usePod, paid from your shielded balance over Tor. Records inference.enabled and Tor (as --prefer-tor) in config.json, and prints the path to the first private call. Without it, --yes keeps what config.json records'),
152446
152601
  flag2("--passphrase-file", "<file>", "your own passphrase file (8 or more characters); default: setup writes a new random passphrase to <home>/passphrase.txt, readable by you alone. Needed for a wallet that exists already"),
152447
152602
  flag2("--facilitator", "<https origin>", `the facilitator whose release, pool, and proof tools setup uses; default ${GUIDE.facilitator}`, { check: "origin" }),
152448
- flag2("--add-to", "<claude-code|claude-desktop|cursor>", "also add the server (npx -y shinjuku-shielded mcp) to this agent host's config; repeat it for more. Without it, setup prints the configs", { repeat: true }),
152603
+ flag2("--add-to", "<claude-code|claude-desktop|cursor>", "also add the server (npx -y --no-audit --no-fund shinjuku-shielded mcp) to this agent host's config; repeat it for more. Without it, setup prints the configs", { repeat: true }),
152449
152604
  bool2("--force", "with --add-to: replace a different shinjuku-shielded entry already in a JSON host config (the old file is backed up first, mode 0600)"),
152450
- flag2("--trust-proof-tools", "<sha256>", "ADVANCED: install the proof-tool set whose SHA256SUMS has this SHA-256 instead of the set this wallet build pins (needed for a facilitator the build does not pin). Check the set out of band first; the normal fix for a new set is npx -y shinjuku-shielded@latest setup")
152605
+ flag2("--trust-proof-tools", "<sha256>", "ADVANCED: install the proof-tool set whose SHA256SUMS has this SHA-256 instead of the set this wallet build pins (needed for a facilitator the build does not pin). Check the set out of band first; the normal fix for a new set is npx -y --no-audit --no-fund shinjuku-shielded@latest setup")
152451
152606
  ],
152452
152607
  examples: [
152453
152608
  `${CLI2} setup --yes`,
@@ -152455,20 +152610,20 @@ var COMMANDS = [
152455
152610
  `${CLI2} setup --yes --private-inference`
152456
152611
  ],
152457
152612
  notes: [
152458
- "npx -y shinjuku-shielded setup runs the same command. Without --yes it asks in the terminal: the caps (Enter keeps the default), Tor, and private inference.",
152613
+ "npx -y --no-audit --no-fund shinjuku-shielded setup runs the same command. Without --yes it asks in the terminal: the caps (Enter keeps the default), Tor, and private inference.",
152459
152614
  `When Tor is recorded or asked for (a yes, --tor, --prefer-tor, or --private-inference), setup itself runs behind Tor: the release, the proof-tool downloads, and the RPC requests go over Tor, so the facilitator never sees this machine's IP address make the wallet. config.json then records Tor for mcp ("tor": true), so the MCP runs behind Tor too. Tor must run first (torrc: HTTPTunnelPort 127.0.0.1:9080); --no-tor runs it without Tor.`,
152460
152615
  `Private inference (a yes, or --private-inference): ${PRIVATE_INFERENCE_WHY} Setup records Tor, then prints five steps with real commands: add-funds (it shields the USDC), the first call (${CLI2} infer - --model qwen3-8-flash ... --tor, about 0.0011 USDC = 1100 atomic; its --max-payment must cover the 10000 = 0.01 USDC ceiling plus the fee), infer serve for an OpenAI client, and an MCP restart for inference_chat. In a terminal it then offers to run add-funds; it never pays an inference call.`,
152461
152616
  "The wallet home is SHIELDED_WALLET_HOME, default ~/.carbon-shielded-wallet (every command of this CLI uses it). setup writes there: config.json, passphrase.txt (mode 0600; on Windows an access list of your account alone), the wallet (<pool>/wallet.json, made by init with the production pool, program, network, and USDC), a recovery file recovery-<time>.txt, and proof-tools/<dir>/.",
152462
152617
  "The passphrase is never printed and no MCP tool takes or returns it. The recovery file holds the seed and the key: copy it to two offline places, then delete it from this machine.",
152463
- "The proof tools are the set this wallet build PINS (its SHA256SUMS hash is in the wallet; --trust-proof-tools replaces it). A facilitator whose /api/wallet/release names another set is refused (setup_proof_tools_pin_mismatch: update the wallet, npx -y shinjuku-shielded@latest setup). SHA256SUMS must have the pinned SHA-256, and every file must have the SHA-256 its line names, as /skill.md section 7b; bin/ and house/bin/ get the execute bit. A file that does not match is not kept. Each download has a hard size limit.",
152618
+ "The proof tools are the set this wallet build PINS (its SHA256SUMS hash is in the wallet; --trust-proof-tools replaces it). A facilitator whose /api/wallet/release names another set is refused (setup_proof_tools_pin_mismatch: update the wallet, npx -y --no-audit --no-fund shinjuku-shielded@latest setup). SHA256SUMS must have the pinned SHA-256, and every file must have the SHA-256 its line names, as /skill.md section 7b; bin/ and house/bin/ get the execute bit. A file that does not match is not kept. Each download has a hard size limit.",
152464
152619
  "Your own --passphrase-file must be private: on Linux and macOS setup refuses a file that group or other may read or write, or that another user owns (setup_passphrase_file_insecure: chmod 600 <file>). On Windows setup cannot read the access list; it accepts the file with a warning.",
152465
152620
  "--add-to for Claude Desktop or Cursor: a host config whose mcpServers is not a JSON object, or that has a different shinjuku-shielded entry (without --force), is left alone. Otherwise the old file is copied to <file>.bak-<time> (mode 0600 on Linux and macOS; on Windows the folder's access list) and the new file replaces it in one rename.",
152466
152621
  "The provers are Linux programs. Linux: ready. Windows: the wallet runs them through WSL; setup checks that wsl.exe runs (wsl --install -d Ubuntu otherwise). macOS: not supported; setup says so and creates nothing.",
152467
152622
  "Run it again at any time: it never changes an existing wallet, keeps the recorded caps unless you pass new ones, checks every proof-tool file again, downloads what is missing or newer, and rewrites config.json.",
152468
- "Then mcp needs no flags: npx -y shinjuku-shielded mcp reads config.json (a flag on the command line still wins). Before setup, mcp in a terminal offers to run setup; started by an agent host, it serves shinjuku_setup, which runs this same setup after you confirm in the host.",
152623
+ "Then mcp needs no flags: npx -y --no-audit --no-fund shinjuku-shielded mcp reads config.json (a flag on the command line still wins). Before setup, mcp in a terminal offers to run setup; started by an agent host, it serves shinjuku_setup, which runs this same setup after you confirm in the host.",
152469
152624
  "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-wallet 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."
152470
152625
  ],
152471
- next: `start it from your agent host with npx -y shinjuku-shielded mcp (or ${CLI2} mcp), then ask your agent "what is my balance"`,
152626
+ next: `start it from your agent host with npx -y --no-audit --no-fund shinjuku-shielded mcp (or ${CLI2} mcp), then ask your agent "what is my balance"`,
152472
152627
  run: (args, values, deps, io) => deps.setupMain(values, { ...deps, io })
152473
152628
  },
152474
152629
  {
@@ -152834,7 +152989,7 @@ var COMMANDS = [
152834
152989
  flags: [
152835
152990
  bool2("--dry-run", "show what would move from local files only: no network call, nothing changes"),
152836
152991
  flag2("--rpc-file", "<file>", RPC_FILE_ABOUT),
152837
- flag2("--trust-proof-tools", "<sha256>", "ADVANCED: trust the proof-tool set whose SHA256SUMS has this SHA-256 for a pool of this move, when neither this wallet build's pin nor the signed release channel vouches for it (wallet_move_proof_tools_untrusted names the set). Repeat it once per set. Check each set out of band first; the normal fix is npx -y shinjuku-shielded@latest", { repeat: true })
152992
+ flag2("--trust-proof-tools", "<sha256>", "ADVANCED: trust the proof-tool set whose SHA256SUMS has this SHA-256 for a pool of this move, when neither this wallet build's pin nor the signed release channel vouches for it (wallet_move_proof_tools_untrusted names the set). Repeat it once per set. Check each set out of band first; the normal fix is npx -y --no-audit --no-fund shinjuku-shielded@latest", { repeat: true })
152838
152993
  ],
152839
152994
  examples: [`${CLI2} move --dry-run`, `${CLI2} move`],
152840
152995
  notes: [
@@ -153058,9 +153213,9 @@ function overviewText() {
153058
153213
  `Usage: ${CLI2} <command> [flags]`,
153059
153214
  ` ${CLI2} help <command> one command, with an example that works`,
153060
153215
  "",
153061
- "Start here (one command): npx -y shinjuku-shielded setup",
153216
+ "Start here (one command): npx -y --no-audit --no-fund shinjuku-shielded setup",
153062
153217
  " It makes the wallet, a private passphrase file, the checked proof tools, and config.json, and prints the lines for your agent host",
153063
- " (the host then runs npx -y shinjuku-shielded mcp). Then ask your agent to add funds (wallet_add_funds, from 0.01 USDC).",
153218
+ " (the host then runs npx -y --no-audit --no-fund shinjuku-shielded mcp). Then ask your agent to add funds (wallet_add_funds, from 0.01 USDC).",
153064
153219
  "",
153065
153220
  "Manual set up (advanced, without setup):",
153066
153221
  " export SHIELDED_WALLET_HOME=<a private directory>",
@@ -153087,7 +153242,7 @@ function overviewText() {
153087
153242
  ` facilitator ${GUIDE.facilitator}`,
153088
153243
  "",
153089
153244
  "Exit codes: 0 done; 1 the command ran and failed (one-line reason); 2 the command line is wrong (shows a working example).",
153090
- `Start here: npx -y shinjuku-shielded setup (or ${CLI2} setup), then the agent host runs npx -y shinjuku-shielded mcp, and your agent adds funds with wallet_add_funds (from 0.01 USDC).`,
153245
+ `Start here: npx -y --no-audit --no-fund shinjuku-shielded setup (or ${CLI2} setup), then the agent host runs npx -y --no-audit --no-fund shinjuku-shielded mcp, and your agent adds funds with wallet_add_funds (from 0.01 USDC).`,
153091
153246
  `Manual path, without setup: ${CLI2} help init, then ${CLI2} help add-funds (whole USDC only).`,
153092
153247
  `Lost the wallet file? ${CLI2} help restore (from the init recovery file)`,
153093
153248
  ""
@@ -154417,7 +154572,7 @@ function floatFailureHint(reason, floatError) {
154417
154572
  if (/p03_float_origin_missing/.test(reason)) return "nothing was paid: pass --memo-service, the facilitator that pays standard exact sellers for you";
154418
154573
  if (/p03_float_body_too_large/.test(reason)) return "nothing was paid: this seller's payment terms are larger than 12 KiB, too large to forward. Do not pay this seller";
154419
154574
  if (/p03_float_request_refused/.test(reason)) {
154420
- return "nothing was paid: Shinjuku refused to forward this seller's payment terms (its code follows p03_float_request_refused). Do not retry unchanged; float_body_invalid about refundTo means this wallet is on another pool than the facilitator: run npx -y shinjuku-shielded@latest setup";
154575
+ return "nothing was paid: Shinjuku refused to forward this seller's payment terms (its code follows p03_float_request_refused). Do not retry unchanged; float_body_invalid about refundTo means this wallet is on another pool than the facilitator: run npx -y --no-audit --no-fund shinjuku-shielded@latest setup";
154421
154576
  }
154422
154577
  if (/p03_float_already_paid/.test(reason)) {
154423
154578
  return "Shinjuku records this payment as paid, but this wallet holds no record of that payment: do not pay again. Keep the wallet folder as it is and rerun the same command with the same --request-id";