shinjuku-shielded 0.3.154 → 0.3.155

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
@@ -6,19 +6,19 @@ 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.154. The npm packages `shinjuku-shield` and
9
+ This is version 0.3.155. 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
- npm install -g shinjuku@0.3.154
15
+ npm install -g shinjuku@0.3.155
16
16
  shinjuku setup
17
17
  ```
18
18
 
19
19
  Type the two lines as they are. `npx install shinjuku` does not work: npx
20
20
  reads `install` as the name of another npm package. To set up without
21
- installing, type `npx shinjuku@0.3.154 setup`.
21
+ installing, type `npx shinjuku@0.3.155 setup`.
22
22
 
23
23
  Setup makes the wallet on this machine, a private passphrase file, and the
24
24
  checked proof tools (about 191 MB), and writes `config.json`. It also writes
@@ -36,13 +36,13 @@ Every wallet command works after `shinjuku`, for example `shinjuku balance`,
36
36
  Claude Code:
37
37
 
38
38
  ```sh
39
- claude mcp add --scope user shinjuku -- npx -y --no-audit --no-fund shinjuku-shield@0.3.154 mcp
39
+ claude mcp add --scope user shinjuku -- npx -y --no-audit --no-fund shinjuku-shield@0.3.155 mcp
40
40
  ```
41
41
 
42
42
  Claude Desktop (`claude_desktop_config.json`) or Cursor (`~/.cursor/mcp.json`):
43
43
 
44
44
  ```json
45
- { "mcpServers": { "shinjuku": { "command": "npx", "args": ["-y", "--no-audit", "--no-fund", "shinjuku-shield@0.3.154", "mcp"] } } }
45
+ { "mcpServers": { "shinjuku": { "command": "npx", "args": ["-y", "--no-audit", "--no-fund", "shinjuku-shield@0.3.155", "mcp"] } } }
46
46
  ```
47
47
 
48
48
  On native Windows, if the host cannot find `npx`, use `"command": "cmd"` and
@@ -55,7 +55,7 @@ Codex (the Codex app and Codex CLI read the same file, `~/.codex/config.toml`):
55
55
  ```toml
56
56
  [mcp_servers.shinjuku]
57
57
  command = "npx"
58
- args = ["-y", "--no-audit", "--no-fund", "shinjuku-shield@0.3.154", "mcp"]
58
+ args = ["-y", "--no-audit", "--no-fund", "shinjuku-shield@0.3.155", "mcp"]
59
59
  startup_timeout_sec = 120
60
60
  tool_timeout_sec = 300
61
61
  ```
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": "706b774ac8ab6d671a81f7aa269e2a1d1e222d60f545ddde48945fbfdc8b0bcd",
5
- "bytes": 9052676,
6
- "sourceCommit": "7b23397db24686bbab6bd45734cb9560c914981a",
4
+ "sha256": "65d2837cf983622ed22a9d2bfb488a3a6ff0f276cb0d561b1be6074415daab0f",
5
+ "bytes": 9055610,
6
+ "sourceCommit": "5645304267acd2efd47b75cf75ae25ffae3096c5",
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-03T05:31:30.536Z"
1041
+ "publishedAt": "2026-11-03T05:58:09.739Z"
1042
1042
  }
package/package.json CHANGED
@@ -1,10 +1,10 @@
1
1
  {
2
2
  "name": "shinjuku-shielded",
3
- "version": "0.3.154",
3
+ "version": "0.3.155",
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": "706b774a",
7
- "shinjukuSha256": "706b774ac8ab6d671a81f7aa269e2a1d1e222d60f545ddde48945fbfdc8b0bcd",
6
+ "shinjukuRelease": "65d2837c",
7
+ "shinjukuSha256": "65d2837cf983622ed22a9d2bfb488a3a6ff0f276cb0d561b1be6074415daab0f",
8
8
  "license": "SEE LICENSE IN LICENSE.txt",
9
9
  "author": "Shinjuku Shielded",
10
10
  "homepage": "https://github.com/ShinjukuStaition/shinjuku-shield#readme",
@@ -59679,7 +59679,7 @@ async function readCompactP03HistoryNow({
59679
59679
  poolPreRead,
59680
59680
  // walletHistory.mjs, with poolPreRead: page 0 asked beside the same refresh (requestCompactFirstPage).
59681
59681
  // Used as this read's page 0 when this read asks page 0 at all; readPages checks it as any page.
59682
- // Ignored with knownSnapshot.
59682
+ // Ignored with knownSnapshot, except in the read again after a refused tail hit (`tail` false).
59683
59683
  firstPreRead,
59684
59684
  // compactP03HistoryReport: run beside the spot checks once the initialization is verified
59685
59685
  // ({ snapshot, initialization, contexts }); its result comes back as `alongside`.
@@ -59693,7 +59693,7 @@ async function readCompactP03HistoryNow({
59693
59693
  // result and any throw are ignored.
59694
59694
  onList,
59695
59695
  // compactP03HistoryReport: the records of a compact cache that is not warm (cached.served). When the
59696
- // list is read (no knownSnapshot), these records (or `served`'s, when the pool outgrew them) that pass
59696
+ // list is read (no page 0 handed over by a behind wait), these records (or `served`'s, when the pool outgrew them) that pass
59697
59697
  // the start of the pool's last grid page take that page instead of every page (3b, combineCompactTail);
59698
59698
  // page 0 still goes out and is read to its end.
59699
59699
  prefix,
@@ -59702,8 +59702,8 @@ async function readCompactP03HistoryNow({
59702
59702
  // false: no tail path (compactP03HistoryReport's read again after a refused tail hit; it sent its set already).
59703
59703
  tail = true,
59704
59704
  // compactP03HistoryReport's read again (with tail false): the set the refused tail hit sent at this same count
59705
- // (sendRestOfSet's { pages, tail }), so the read again takes its pages instead of asking them a second time.
59706
- // Ignored with knownSnapshot.
59705
+ // (sendRestOfSet's { pages, tail }), so the read again takes its pages instead of asking them a second time,
59706
+ // with knownSnapshot too.
59707
59707
  restPreRead,
59708
59708
  // compactP03HistoryReport: called on a tail hit with { first (page 0's answer promise), snapshot (the pool
59709
59709
  // account read), check, rest (the set sent at the count) }, so a refused list can be read again from that same
@@ -59728,7 +59728,7 @@ async function readCompactP03HistoryNow({
59728
59728
  const hintIndex = knownSnapshot?.currentIndex ?? knownIndex;
59729
59729
  const cachedReachesKnown = hintIndex !== void 0 && served !== void 0 && Array.isArray(served.records) && Boolean(served.initialization) && BigInt(served.records.length) * SUBTREE_LEAVES3 >= hintIndex;
59730
59730
  const reusedFirst = knownSnapshot !== void 0 && knownFirst !== void 0 ? knownFirst : void 0;
59731
- const preFirst = knownSnapshot === void 0 ? firstPreRead : void 0;
59731
+ const preFirst = knownSnapshot === void 0 || !tail ? firstPreRead : void 0;
59732
59732
  const first = reusedFirst ?? (served === void 0 || hintIndex !== void 0 && !cachedReachesKnown ? preFirst ?? requestPage(source, poolString, 0, signal) : void 0);
59733
59733
  if (first !== void 0 && reusedFirst === void 0) markPhase(preFirst !== void 0 ? "compact-page0-handed-over" : "compact-page0-sent");
59734
59734
  let early = heldPicks.early;
@@ -59792,7 +59792,7 @@ async function readCompactP03HistoryNow({
59792
59792
  const count2 = Number(snapshot.currentIndex / SUBTREE_LEAVES3);
59793
59793
  if (!Number.isSafeInteger(count2)) throw refuse3("p03_compact_history_snapshot_invalid");
59794
59794
  const anchors = freezeFinalizedAnchors(snapshot);
59795
- const preRest = knownSnapshot === void 0 ? restPreRead : void 0;
59795
+ const preRest = knownSnapshot === void 0 || !tail ? restPreRead : void 0;
59796
59796
  let rest;
59797
59797
  const restOfSet = () => rest ??= preRest ?? sendRestOfSet(source, poolString, count2, tailGrid, signal);
59798
59798
  let aheadHere;
@@ -59837,7 +59837,7 @@ async function readCompactP03HistoryNow({
59837
59837
  };
59838
59838
  let prefixCheck;
59839
59839
  const readTailOrPages = async () => {
59840
- if (knownSnapshot !== void 0 || !tail) return readServedPages();
59840
+ if (reusedFirst !== void 0 || !tail) return readServedPages();
59841
59841
  const zero = first ?? preFirst ?? requestPage(source, poolString, 0, signal);
59842
59842
  if (first === void 0 && preFirst === void 0) markPhase("compact-page0-sent");
59843
59843
  const from = tailFrom(count2, tailGrid);
@@ -144691,13 +144691,30 @@ var init_homeScreen = __esm({
144691
144691
 
144692
144692
  // wallet/src/inference/brand.mjs
144693
144693
  function columnsOf(text3) {
144694
+ const parts = GRAPHEMES ? Array.from(GRAPHEMES.segment(text3), (part) => part.segment) : Array.from(text3);
144694
144695
  let count2 = 0;
144695
- for (const ch of text3) {
144696
- const code2 = ch.codePointAt(0);
144697
- count2 += code2 >= 11904 && code2 <= 42191 || code2 >= 65280 && code2 <= 65376 ? 2 : 1;
144696
+ for (const part of parts) {
144697
+ if (/^[\p{M}\p{Cf}]+$/u.test(part)) continue;
144698
+ count2 += new RegExp("\\p{Extended_Pictographic}|[\\u{1F1E6}-\\u{1F1FF}]|\u20E3", "u").test(part) || wideCode(part.codePointAt(0)) ? 2 : 1;
144698
144699
  }
144699
144700
  return count2;
144700
144701
  }
144702
+ function expandTabs(line, start = 0) {
144703
+ if (!line.includes(" ")) return line;
144704
+ let out = "";
144705
+ let column = start;
144706
+ for (const piece of line.match(/\x1b\[[0-9;]*m|\t|[^\t\x1b]+|\x1b/g) ?? []) {
144707
+ if (piece === " ") {
144708
+ const spaces = 8 - column % 8;
144709
+ out += " ".repeat(spaces);
144710
+ column += spaces;
144711
+ } else {
144712
+ out += piece;
144713
+ if (!piece.startsWith("\x1B[")) column += columnsOf(piece);
144714
+ }
144715
+ }
144716
+ return out;
144717
+ }
144701
144718
  function brandColor(stream = process.stderr, env = process.env) {
144702
144719
  if (!stream?.isTTY || (env.CI ?? "") !== "" || env.TERM === "dumb") return 0;
144703
144720
  return screenColor(stream, env);
@@ -144772,10 +144789,57 @@ function brandLine({ model: model2, tor = true, color = 0 }) {
144772
144789
  ...tor ? [[" \xB7 ", "ash"], ["Tor on", "brass"]] : []
144773
144790
  ], color);
144774
144791
  }
144792
+ function fitColumns(text3, columns, { prefix = "" } = {}) {
144793
+ const width = Math.floor(Number(columns));
144794
+ if (!(width >= 1)) return `${prefix}${text3}`;
144795
+ const visible = (part) => part.replace(/\x1b\[[0-9;]*m/g, "");
144796
+ return String(text3).split("\n").map((raw, index) => {
144797
+ const head = index === 0 ? prefix : "";
144798
+ const headColumns = columnsOf(visible(head));
144799
+ const line = expandTabs(raw, headColumns);
144800
+ if (headColumns + columnsOf(visible(line)) <= width) return `${head}${raw}`;
144801
+ const pad = " ".repeat(Math.min(visible(line).match(/^ */)[0].length, Math.max(0, width - 1)));
144802
+ const out = [];
144803
+ let current = head;
144804
+ let used = headColumns;
144805
+ let hasWord = false;
144806
+ let spaces = "";
144807
+ for (const piece of line.match(/ +|(?:\x1b\[[0-9;]*m|\x1b|[^ \x1b])+/g) ?? []) {
144808
+ if (piece[0] === " ") {
144809
+ if (hasWord) spaces += piece;
144810
+ else {
144811
+ const kept3 = Math.max(0, Math.min(piece.length, width - 1 - used));
144812
+ current += " ".repeat(kept3);
144813
+ used += kept3;
144814
+ }
144815
+ continue;
144816
+ }
144817
+ const seen = columnsOf(visible(piece));
144818
+ if (seen === 0) {
144819
+ current += piece;
144820
+ continue;
144821
+ }
144822
+ if (hasWord && used + spaces.length + seen > width) {
144823
+ out.push(current);
144824
+ current = pad;
144825
+ used = pad.length;
144826
+ } else {
144827
+ current += spaces;
144828
+ used += spaces.length;
144829
+ }
144830
+ spaces = "";
144831
+ current += piece;
144832
+ used += seen;
144833
+ hasWord = true;
144834
+ }
144835
+ out.push(current);
144836
+ return out.join("\n");
144837
+ }).join("\n");
144838
+ }
144775
144839
  function paidLine(atomic4, { color = 0, tail = "" } = {}) {
144776
144840
  return paint([["\u2713 ", "brass"], ["paid privately ", "dim"], [usdcWords(atomic4), "verm"], ...tail ? [[tail, "mute"]] : []], color);
144777
144841
  }
144778
- var HEADER_COLUMNS, STATEMENTS, KATAKANA2, PRIVATE_AI, TONES, joinParts2;
144842
+ var HEADER_COLUMNS, STATEMENTS, KATAKANA2, GRAPHEMES, wideCode, PRIVATE_AI, TONES, joinParts2;
144779
144843
  var init_brand = __esm({
144780
144844
  "wallet/src/inference/brand.mjs"() {
144781
144845
  "use strict";
@@ -144785,6 +144849,8 @@ var init_brand = __esm({
144785
144849
  HEADER_COLUMNS = 80;
144786
144850
  STATEMENTS = "Shield once. Take it everywhere. Pay unseen.";
144787
144851
  KATAKANA2 = Array.from({ length: 65438 - 65382 }, (_, index) => String.fromCharCode(65382 + index));
144852
+ GRAPHEMES = typeof Intl.Segmenter === "function" ? new Intl.Segmenter("en", { granularity: "grapheme" }) : void 0;
144853
+ wideCode = (code2) => code2 >= 4352 && code2 <= 4447 || code2 >= 11904 && code2 <= 42191 || code2 >= 44032 && code2 <= 55203 || code2 >= 63744 && code2 <= 64255 || code2 >= 65072 && code2 <= 65103 || code2 >= 65280 && code2 <= 65376 || code2 >= 65504 && code2 <= 65510 || code2 >= 131072 && code2 <= 262141;
144788
144854
  PRIVATE_AI = [["Private ", "bone"], ["AI", "crim"]];
144789
144855
  TONES = { b: "brass", c: "crim", o: "crimdim" };
144790
144856
  joinParts2 = (cells) => cells.reduce((parts, [ch, cls]) => {
@@ -145079,7 +145145,8 @@ async function runChat({ io, values, deps = {} }) {
145079
145145
  servedNow();
145080
145146
  const color = brandColor(process.stderr, env);
145081
145147
  const answerColor = brandColor(process.stdout, env);
145082
- const say3 = (line) => io.err(`${line}
145148
+ const fitErr = (text3) => fitColumns(text3, process.stderr.isTTY ? process.stderr.columns : 0);
145149
+ const say3 = (line) => io.err(`${fitErr(line)}
145083
145150
  `);
145084
145151
  const modeName = () => state.mode === "each" ? "one question at a time" : "a conversation";
145085
145152
  const youPrompt = () => paint([
@@ -145614,7 +145681,7 @@ When it says ready, type your message here.`);
145614
145681
  lineAbove = (text3) => {
145615
145682
  lastLineAt = Date.now();
145616
145683
  clearStatus();
145617
- io.err(String(text3).endsWith("\n") ? String(text3) : `${text3}
145684
+ io.err(`${fitErr(String(text3).replace(/\n$/, ""))}
145618
145685
  `);
145619
145686
  if (inPlace) status();
145620
145687
  };
@@ -145683,7 +145750,11 @@ When it says ready, type your message here.`);
145683
145750
  }
145684
145751
  state.answers += 1;
145685
145752
  if (state.mode === "talk") state.history = [...turn.messages, { role: "assistant", content }];
145686
- io.out(`${answerColor ? paint([["AI ", "crim"], ["\u203A ", "ash"]], answerColor) : ""}${content}
145753
+ io.out(`${fitColumns(
145754
+ content,
145755
+ process.stdout.isTTY ? process.stdout.columns : 0,
145756
+ { prefix: answerColor ? paint([["AI ", "crim"], ["\u203A ", "ash"]], answerColor) : "" }
145757
+ )}
145687
145758
  `);
145688
145759
  const cut2 = result.finishReason === "length" ? `(the answer stopped at its ${turn.maxTokens}-token limit) ` : "";
145689
145760
  const plainPaid = paid !== void 0 && !replayed && !unpaid;