@namzu/cli 14.2.1 → 15.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (164) hide show
  1. package/README.md +123 -11
  2. package/dist/cli.d.ts.map +1 -1
  3. package/dist/cli.js +33 -27
  4. package/dist/cli.js.map +1 -1
  5. package/dist/commands/acp.js +1 -1
  6. package/dist/commands/acp.js.map +1 -1
  7. package/dist/commands/doctor.d.ts.map +1 -1
  8. package/dist/commands/doctor.js +2 -0
  9. package/dist/commands/doctor.js.map +1 -1
  10. package/dist/commands/login.d.ts +2 -0
  11. package/dist/commands/login.d.ts.map +1 -1
  12. package/dist/commands/login.js +45 -7
  13. package/dist/commands/login.js.map +1 -1
  14. package/dist/commands/prior-messages.d.ts.map +1 -1
  15. package/dist/commands/prior-messages.js +13 -4
  16. package/dist/commands/prior-messages.js.map +1 -1
  17. package/dist/commands/run.d.ts.map +1 -1
  18. package/dist/commands/run.js +22 -9
  19. package/dist/commands/run.js.map +1 -1
  20. package/dist/commands/{stubs.d.ts → serve.d.ts} +1 -10
  21. package/dist/commands/serve.d.ts.map +1 -0
  22. package/dist/commands/{stubs.js → serve.js} +1 -24
  23. package/dist/commands/serve.js.map +1 -0
  24. package/dist/commands/skills.d.ts +19 -0
  25. package/dist/commands/skills.d.ts.map +1 -0
  26. package/dist/commands/skills.js +107 -0
  27. package/dist/commands/skills.js.map +1 -0
  28. package/dist/commands/upgrade.d.ts +25 -0
  29. package/dist/commands/upgrade.d.ts.map +1 -0
  30. package/dist/commands/upgrade.js +182 -0
  31. package/dist/commands/upgrade.js.map +1 -0
  32. package/dist/context/runtime-message.d.ts +4 -0
  33. package/dist/context/runtime-message.d.ts.map +1 -0
  34. package/dist/context/runtime-message.js +20 -0
  35. package/dist/context/runtime-message.js.map +1 -0
  36. package/dist/integrations/mcp/servers.d.ts +7 -0
  37. package/dist/integrations/mcp/servers.d.ts.map +1 -1
  38. package/dist/integrations/mcp/servers.js +33 -8
  39. package/dist/integrations/mcp/servers.js.map +1 -1
  40. package/dist/integrations/sessions/store.d.ts +8 -0
  41. package/dist/integrations/sessions/store.d.ts.map +1 -1
  42. package/dist/integrations/sessions/store.js +15 -0
  43. package/dist/integrations/sessions/store.js.map +1 -1
  44. package/dist/integrations/sessions/transcript-export.d.ts.map +1 -1
  45. package/dist/integrations/sessions/transcript-export.js +10 -1
  46. package/dist/integrations/sessions/transcript-export.js.map +1 -1
  47. package/dist/integrations/sessions/turn-evidence.d.ts.map +1 -1
  48. package/dist/integrations/sessions/turn-evidence.js +9 -1
  49. package/dist/integrations/sessions/turn-evidence.js.map +1 -1
  50. package/dist/integrations/subagents/runtime.d.ts +2 -0
  51. package/dist/integrations/subagents/runtime.d.ts.map +1 -1
  52. package/dist/integrations/subagents/runtime.js +86 -13
  53. package/dist/integrations/subagents/runtime.js.map +1 -1
  54. package/dist/integrations/updates.d.ts +7 -1
  55. package/dist/integrations/updates.d.ts.map +1 -1
  56. package/dist/integrations/updates.js +86 -23
  57. package/dist/integrations/updates.js.map +1 -1
  58. package/dist/tui/App.d.ts +12 -1
  59. package/dist/tui/App.d.ts.map +1 -1
  60. package/dist/tui/App.js +1211 -208
  61. package/dist/tui/App.js.map +1 -1
  62. package/dist/tui/ChoicePicker.d.ts +2 -1
  63. package/dist/tui/ChoicePicker.d.ts.map +1 -1
  64. package/dist/tui/ChoicePicker.js +10 -6
  65. package/dist/tui/ChoicePicker.js.map +1 -1
  66. package/dist/tui/Composer.d.ts +33 -6
  67. package/dist/tui/Composer.d.ts.map +1 -1
  68. package/dist/tui/Composer.js +569 -48
  69. package/dist/tui/Composer.js.map +1 -1
  70. package/dist/tui/CopyPicker.d.ts.map +1 -1
  71. package/dist/tui/CopyPicker.js +3 -4
  72. package/dist/tui/CopyPicker.js.map +1 -1
  73. package/dist/tui/EditPromptPicker.d.ts.map +1 -1
  74. package/dist/tui/EditPromptPicker.js +3 -4
  75. package/dist/tui/EditPromptPicker.js.map +1 -1
  76. package/dist/tui/LiveActivity.d.ts +3 -0
  77. package/dist/tui/LiveActivity.d.ts.map +1 -1
  78. package/dist/tui/LiveActivity.js +4 -1
  79. package/dist/tui/LiveActivity.js.map +1 -1
  80. package/dist/tui/Markdown.d.ts +3 -1
  81. package/dist/tui/Markdown.d.ts.map +1 -1
  82. package/dist/tui/Markdown.js +11 -9
  83. package/dist/tui/Markdown.js.map +1 -1
  84. package/dist/tui/PermissionOverlay.d.ts +11 -6
  85. package/dist/tui/PermissionOverlay.d.ts.map +1 -1
  86. package/dist/tui/PermissionOverlay.js +13 -20
  87. package/dist/tui/PermissionOverlay.js.map +1 -1
  88. package/dist/tui/Picker.d.ts.map +1 -1
  89. package/dist/tui/Picker.js +87 -20
  90. package/dist/tui/Picker.js.map +1 -1
  91. package/dist/tui/ResumePicker.d.ts.map +1 -1
  92. package/dist/tui/ResumePicker.js +6 -1
  93. package/dist/tui/ResumePicker.js.map +1 -1
  94. package/dist/tui/TextPrompt.d.ts +21 -0
  95. package/dist/tui/TextPrompt.d.ts.map +1 -0
  96. package/dist/tui/TextPrompt.js +139 -0
  97. package/dist/tui/TextPrompt.js.map +1 -0
  98. package/dist/tui/Transcript.d.ts +3 -1
  99. package/dist/tui/Transcript.d.ts.map +1 -1
  100. package/dist/tui/Transcript.js +4 -4
  101. package/dist/tui/Transcript.js.map +1 -1
  102. package/dist/tui/agent.d.ts +39 -20
  103. package/dist/tui/agent.d.ts.map +1 -1
  104. package/dist/tui/agent.js +115 -74
  105. package/dist/tui/agent.js.map +1 -1
  106. package/dist/tui/exit-summary.d.ts +6 -0
  107. package/dist/tui/exit-summary.d.ts.map +1 -0
  108. package/dist/tui/exit-summary.js +9 -0
  109. package/dist/tui/exit-summary.js.map +1 -0
  110. package/dist/tui/external-editor.d.ts +25 -0
  111. package/dist/tui/external-editor.d.ts.map +1 -0
  112. package/dist/tui/external-editor.js +169 -0
  113. package/dist/tui/external-editor.js.map +1 -0
  114. package/dist/tui/index.d.ts.map +1 -1
  115. package/dist/tui/index.js +19 -6
  116. package/dist/tui/index.js.map +1 -1
  117. package/dist/tui/log-pane.d.ts +13 -8
  118. package/dist/tui/log-pane.d.ts.map +1 -1
  119. package/dist/tui/log-pane.js +23 -29
  120. package/dist/tui/log-pane.js.map +1 -1
  121. package/dist/tui/login-prompt.d.ts +2 -0
  122. package/dist/tui/login-prompt.d.ts.map +1 -1
  123. package/dist/tui/login-prompt.js +8 -1
  124. package/dist/tui/login-prompt.js.map +1 -1
  125. package/dist/tui/mentions.d.ts +19 -0
  126. package/dist/tui/mentions.d.ts.map +1 -1
  127. package/dist/tui/mentions.js +96 -5
  128. package/dist/tui/mentions.js.map +1 -1
  129. package/dist/tui/open-browser.d.ts.map +1 -1
  130. package/dist/tui/open-browser.js +27 -9
  131. package/dist/tui/open-browser.js.map +1 -1
  132. package/dist/tui/permission-review.d.ts +59 -0
  133. package/dist/tui/permission-review.d.ts.map +1 -0
  134. package/dist/tui/permission-review.js +219 -0
  135. package/dist/tui/permission-review.js.map +1 -0
  136. package/dist/tui/selection-window.d.ts +18 -0
  137. package/dist/tui/selection-window.d.ts.map +1 -0
  138. package/dist/tui/selection-window.js +37 -0
  139. package/dist/tui/selection-window.js.map +1 -0
  140. package/dist/tui/slashCommands.d.ts +48 -8
  141. package/dist/tui/slashCommands.d.ts.map +1 -1
  142. package/dist/tui/slashCommands.js +129 -47
  143. package/dist/tui/slashCommands.js.map +1 -1
  144. package/dist/tui/terminal-hyperlinks.d.ts +20 -0
  145. package/dist/tui/terminal-hyperlinks.d.ts.map +1 -0
  146. package/dist/tui/terminal-hyperlinks.js +70 -0
  147. package/dist/tui/terminal-hyperlinks.js.map +1 -0
  148. package/dist/tui/types.d.ts +2 -0
  149. package/dist/tui/types.d.ts.map +1 -1
  150. package/dist/tui/use-selection-index.d.ts +8 -0
  151. package/dist/tui/use-selection-index.d.ts.map +1 -0
  152. package/dist/tui/use-selection-index.js +13 -0
  153. package/dist/tui/use-selection-index.js.map +1 -0
  154. package/dist/tui/workspace-review.d.ts +15 -0
  155. package/dist/tui/workspace-review.d.ts.map +1 -0
  156. package/dist/tui/workspace-review.js +67 -0
  157. package/dist/tui/workspace-review.js.map +1 -0
  158. package/dist/version.d.ts +10 -0
  159. package/dist/version.d.ts.map +1 -0
  160. package/dist/version.js +23 -0
  161. package/dist/version.js.map +1 -0
  162. package/package.json +7 -6
  163. package/dist/commands/stubs.d.ts.map +0 -1
  164. package/dist/commands/stubs.js.map +0 -1
@@ -7,9 +7,9 @@
7
7
  * fix for that forced the SDK logger's level to `silent` via
8
8
  * `configureLogger`, which threw every diagnostic away rather than
9
9
  * choosing where it belonged. The correct choice is a sink that does not
10
- * write: a bounded ring buffer, drained to stderr only once Ink has
11
- * released the terminal — on a clean exit, or on a crash Ink itself did
12
- * not catch.
10
+ * write: a bounded ring buffer retained for a crash and discarded on a clean
11
+ * exit. Replaying routine boot/tool diagnostics after Ctrl+C is not a useful
12
+ * exit summary; it is a hidden log pane suddenly becoming terminal output.
13
13
  *
14
14
  * The ring buffer is implemented HERE rather than imported from
15
15
  * `@namzu/sdk`: LOG-04's confirmed export list (LogRecord, LogSink,
@@ -31,10 +31,9 @@
31
31
  import type { ResolvedLogging } from '../logging.js';
32
32
  /**
33
33
  * Installs the ring buffer as the process sink for the life of the TUI and
34
- * registers the two flush paths Ink cannot own itself: a clean exit,
35
- * driven by the function this returns (`launchTui`'s `finally`), and a
36
- * crash — an uncaught exception or an unhandled rejection reaching the top
37
- * of the process, neither of which `waitUntilExit()` ever resolves for.
34
+ * registers the fatal flush path Ink cannot own itself: an uncaught exception
35
+ * or unhandled rejection reaching the top of the process. The returned clean
36
+ * close path detaches those listeners and discards routine diagnostics.
38
37
  * Both listeners are `.once`, removed the moment either fires: a sink that
39
38
  * itself throws while flushing must not re-enter the same handler, and a
40
39
  * process that launches the TUI more than once in its lifetime (this
@@ -44,5 +43,11 @@ import type { ResolvedLogging } from '../logging.js';
44
43
  * through `contextLogging` to the same resolution an invocation with no
45
44
  * flags and no env override would have gotten.
46
45
  */
47
- export declare function installTuiLogSink(logging?: ResolvedLogging): () => void;
46
+ export interface TuiLogSinkLifecycle {
47
+ /** Normal TUI settlement: remove crash hooks and discard routine diagnostics. */
48
+ close(): void;
49
+ /** Fatal settlement: print the bounded diagnostics after Ink releases the terminal. */
50
+ flush(): void;
51
+ }
52
+ export declare function installTuiLogSink(logging?: ResolvedLogging): TuiLogSinkLifecycle;
48
53
  //# sourceMappingURL=log-pane.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"log-pane.d.ts","sourceRoot":"","sources":["../../src/tui/log-pane.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AAOH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,eAAe,CAAA;AAsBpD;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,CAAC,EAAE,eAAe,GAAG,MAAM,IAAI,CAuCvE"}
1
+ {"version":3,"file":"log-pane.d.ts","sourceRoot":"","sources":["../../src/tui/log-pane.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AAOH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,eAAe,CAAA;AAsBpD;;;;;;;;;;;;;GAaG;AACH,MAAM,WAAW,mBAAmB;IACnC,iFAAiF;IACjF,KAAK,IAAI,IAAI,CAAA;IACb,uFAAuF;IACvF,KAAK,IAAI,IAAI,CAAA;CACb;AAED,wBAAgB,iBAAiB,CAAC,OAAO,CAAC,EAAE,eAAe,GAAG,mBAAmB,CA+ChF"}
@@ -7,9 +7,9 @@
7
7
  * fix for that forced the SDK logger's level to `silent` via
8
8
  * `configureLogger`, which threw every diagnostic away rather than
9
9
  * choosing where it belonged. The correct choice is a sink that does not
10
- * write: a bounded ring buffer, drained to stderr only once Ink has
11
- * released the terminal — on a clean exit, or on a crash Ink itself did
12
- * not catch.
10
+ * write: a bounded ring buffer retained for a crash and discarded on a clean
11
+ * exit. Replaying routine boot/tool diagnostics after Ctrl+C is not a useful
12
+ * exit summary; it is a hidden log pane suddenly becoming terminal output.
13
13
  *
14
14
  * The ring buffer is implemented HERE rather than imported from
15
15
  * `@namzu/sdk`: LOG-04's confirmed export list (LogRecord, LogSink,
@@ -50,40 +50,35 @@ function createRingBufferSink(capacity) {
50
50
  },
51
51
  };
52
52
  }
53
- /**
54
- * Installs the ring buffer as the process sink for the life of the TUI and
55
- * registers the two flush paths Ink cannot own itself: a clean exit,
56
- * driven by the function this returns (`launchTui`'s `finally`), and a
57
- * crash — an uncaught exception or an unhandled rejection reaching the top
58
- * of the process, neither of which `waitUntilExit()` ever resolves for.
59
- * Both listeners are `.once`, removed the moment either fires: a sink that
60
- * itself throws while flushing must not re-enter the same handler, and a
61
- * process that launches the TUI more than once in its lifetime (this
62
- * package's own tests) must not accumulate one pair per launch.
63
- *
64
- * `logging` is optional — see `TuiContext.logging` — and falls back
65
- * through `contextLogging` to the same resolution an invocation with no
66
- * flags and no env override would have gotten.
67
- */
68
53
  export function installTuiLogSink(logging) {
69
54
  const resolved = contextLogging({ logging });
70
55
  const ring = createRingBufferSink(RING_CAPACITY);
71
56
  installCliLogging(ring, resolved.level);
72
- let flushed = false;
73
- const flush = () => {
74
- // Idempotent: a crash's default handling ends the process, which also
75
- // emits 'exit' — both fire for the same crash, and a second pass must
76
- // not print an empty batch's worth of nothing a second time.
77
- if (flushed)
78
- return;
79
- flushed = true;
57
+ let settled = false;
58
+ const detach = () => {
80
59
  process.removeListener('uncaughtException', onFatal);
81
60
  process.removeListener('unhandledRejection', onFatal);
82
- process.removeListener('exit', flush);
61
+ };
62
+ const flush = () => {
63
+ // Idempotent: a sink error or repeated fatal signal must not re-enter the
64
+ // same handler or print an empty batch a second time.
65
+ if (settled)
66
+ return;
67
+ settled = true;
68
+ detach();
83
69
  const out = resolved.format === 'json' ? jsonLinesSink(process.stderr) : prettySink(process.stderr);
84
70
  for (const record of ring.drain())
85
71
  out.emit(record);
86
72
  };
73
+ const close = () => {
74
+ if (settled)
75
+ return;
76
+ settled = true;
77
+ detach();
78
+ // Explicitly release retained records. Clean exit has a separate, concise
79
+ // conversation handoff; boot diagnostics remain diagnostics.
80
+ ring.drain();
81
+ };
87
82
  // Registering a listener for either event turns OFF Node's own default
88
83
  // handling (print the error, exit 1) — both replicated explicitly below,
89
84
  // after the buffer is flushed, so a crash mid-session does not also drop
@@ -100,7 +95,6 @@ export function installTuiLogSink(logging) {
100
95
  };
101
96
  process.once('uncaughtException', onFatal);
102
97
  process.once('unhandledRejection', onFatal);
103
- process.once('exit', flush);
104
- return flush;
98
+ return { close, flush };
105
99
  }
106
100
  //# sourceMappingURL=log-pane.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"log-pane.js","sourceRoot":"","sources":["../../src/tui/log-pane.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AAEH,OAAO,EAAe,aAAa,EAAE,UAAU,EAAE,MAAM,YAAY,CAAA;AAGnE,OAAO,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAA;AACtD,OAAO,EAAE,cAAc,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAA;AAGjE;;kEAEkE;AAClE,MAAM,aAAa,GAAG,GAAG,CAAA;AAEzB,SAAS,oBAAoB,CAAC,QAAgB;IAC7C,MAAM,MAAM,GAAgB,EAAE,CAAA;IAC9B,OAAO;QACN,IAAI,CAAC,MAAiB;YACrB,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;YACnB,gEAAgE;YAChE,gEAAgE;YAChE,IAAI,MAAM,CAAC,MAAM,GAAG,QAAQ;gBAAE,MAAM,CAAC,KAAK,EAAE,CAAA;QAC7C,CAAC;QACD,KAAK;YACJ,OAAO,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,MAAM,CAAC,MAAM,CAAC,CAAA;QACvC,CAAC;KACD,CAAA;AACF,CAAC;AAED;;;;;;;;;;;;;;GAcG;AACH,MAAM,UAAU,iBAAiB,CAAC,OAAyB;IAC1D,MAAM,QAAQ,GAAG,cAAc,CAAC,EAAE,OAAO,EAAE,CAAC,CAAA;IAC5C,MAAM,IAAI,GAAG,oBAAoB,CAAC,aAAa,CAAC,CAAA;IAChD,iBAAiB,CAAC,IAAI,EAAE,QAAQ,CAAC,KAAK,CAAC,CAAA;IAEvC,IAAI,OAAO,GAAG,KAAK,CAAA;IACnB,MAAM,KAAK,GAAG,GAAS,EAAE;QACxB,sEAAsE;QACtE,sEAAsE;QACtE,6DAA6D;QAC7D,IAAI,OAAO;YAAE,OAAM;QACnB,OAAO,GAAG,IAAI,CAAA;QACd,OAAO,CAAC,cAAc,CAAC,mBAAmB,EAAE,OAAO,CAAC,CAAA;QACpD,OAAO,CAAC,cAAc,CAAC,oBAAoB,EAAE,OAAO,CAAC,CAAA;QACrD,OAAO,CAAC,cAAc,CAAC,MAAM,EAAE,KAAK,CAAC,CAAA;QACrC,MAAM,GAAG,GACR,QAAQ,CAAC,MAAM,KAAK,MAAM,CAAC,CAAC,CAAC,aAAa,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,OAAO,CAAC,MAAM,CAAC,CAAA;QACxF,KAAK,MAAM,MAAM,IAAI,IAAI,CAAC,KAAK,EAAE;YAAE,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;IACpD,CAAC,CAAA;IAED,uEAAuE;IACvE,yEAAyE;IACzE,yEAAyE;IACzE,kEAAkE;IAClE,qEAAqE;IACrE,uEAAuE;IACvE,sEAAsE;IACtE,iEAAiE;IACjE,kCAAkC;IAClC,MAAM,OAAO,GAAG,CAAC,GAAY,EAAQ,EAAE;QACtC,KAAK,EAAE,CAAA;QACP,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,IAAI,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,CAAA;QAC5F,OAAO,CAAC,IAAI,CAAC,mBAAmB,CAAC,CAAA;IAClC,CAAC,CAAA;IACD,OAAO,CAAC,IAAI,CAAC,mBAAmB,EAAE,OAAO,CAAC,CAAA;IAC1C,OAAO,CAAC,IAAI,CAAC,oBAAoB,EAAE,OAAO,CAAC,CAAA;IAC3C,OAAO,CAAC,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC,CAAA;IAE3B,OAAO,KAAK,CAAA;AACb,CAAC"}
1
+ {"version":3,"file":"log-pane.js","sourceRoot":"","sources":["../../src/tui/log-pane.tsx"],"names":[],"mappings":"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"}
@@ -58,6 +58,8 @@ export declare function describeLoginOutcome(outcome: LoginOutcome, hints?: {
58
58
  }): string;
59
59
  /** What the operator reads after asking namzu to forget the credential. */
60
60
  export declare function describeLogout(path: string, removed: boolean): string;
61
+ /** A provider-specific logout result for a store that may hold two siblings. */
62
+ export declare function describeProviderLogout(path: string, provider: 'anthropic' | 'codex', removed: boolean): string;
61
63
  /**
62
64
  * Whether a `/login` argument is an attempt to finish, rather than to start.
63
65
  *
@@ -1 +1 @@
1
- {"version":3,"file":"login-prompt.d.ts","sourceRoot":"","sources":["../../src/tui/login-prompt.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oCAAoC,CAAA;AAEtE;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE;IACzC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;IACpB,QAAQ,CAAC,aAAa,EAAE,OAAO,CAAA;IAC/B;;;;;;;;;;OAUG;IACH,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,CAAA;CAChC,GAAG,MAAM,CAcT;AAED,wBAAgB,6BAA6B,CAAC,KAAK,EAAE;IACpD,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;IACpB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;IACzB,QAAQ,CAAC,aAAa,EAAE,OAAO,CAAA;CAC/B,GAAG,MAAM,CAaT;AAED;;;;;;;;;GASG;AACH,wBAAgB,oBAAoB,CACnC,OAAO,EAAE,YAAY,EACrB,KAAK,GAAE;IAAE,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAO,GAC/D,MAAM,CAUR;AAED,2EAA2E;AAC3E,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,GAAG,MAAM,CAIrE;AAED;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,GAAG,OAAO,CAErE"}
1
+ {"version":3,"file":"login-prompt.d.ts","sourceRoot":"","sources":["../../src/tui/login-prompt.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oCAAoC,CAAA;AAEtE;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE;IACzC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;IACpB,QAAQ,CAAC,aAAa,EAAE,OAAO,CAAA;IAC/B;;;;;;;;;;OAUG;IACH,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,CAAA;CAChC,GAAG,MAAM,CAcT;AAED,wBAAgB,6BAA6B,CAAC,KAAK,EAAE;IACpD,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;IACpB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;IACzB,QAAQ,CAAC,aAAa,EAAE,OAAO,CAAA;CAC/B,GAAG,MAAM,CAaT;AAED;;;;;;;;;GASG;AACH,wBAAgB,oBAAoB,CACnC,OAAO,EAAE,YAAY,EACrB,KAAK,GAAE;IAAE,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAO,GAC/D,MAAM,CAUR;AAED,2EAA2E;AAC3E,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,GAAG,MAAM,CAIrE;AAED,gFAAgF;AAChF,wBAAgB,sBAAsB,CACrC,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,WAAW,GAAG,OAAO,EAC/B,OAAO,EAAE,OAAO,GACd,MAAM,CAKR;AAED;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,GAAG,OAAO,CAErE"}
@@ -71,9 +71,16 @@ export function describeLoginOutcome(outcome, hints = {}) {
71
71
  /** What the operator reads after asking namzu to forget the credential. */
72
72
  export function describeLogout(path, removed) {
73
73
  return removed
74
- ? `Removed the stored credential at ${path}. This session keeps working until it ends; the next one will ask you to sign in again.\n\nSigning out here does not revoke anything at the provider — do that in your account settings if you need to.`
74
+ ? `Removed the stored credential at ${path}. An active turn is not interrupted; a later turn may ask you to sign in again.\n\nSigning out here does not revoke anything at the provider — do that in your account settings if you need to.`
75
75
  : "There was no stored credential to remove. If namzu is using one, it came from your environment or from another tool on this machine, and neither is namzu's to delete.";
76
76
  }
77
+ /** A provider-specific logout result for a store that may hold two siblings. */
78
+ export function describeProviderLogout(path, provider, removed) {
79
+ const label = provider === 'anthropic' ? 'Claude' : 'Codex';
80
+ return removed
81
+ ? `Removed Namzu's stored ${label} subscription credential at ${path}. Other stored subscriptions were kept. An active turn is not interrupted; a later turn using ${label} may ask you to sign in again.\n\nSigning out here does not revoke anything at the provider, and credentials owned by other tools on this machine were not changed.`
82
+ : `There was no Namzu-owned ${label} subscription credential to remove. Credentials from the environment or another tool on this machine were not changed.`;
83
+ }
77
84
  /**
78
85
  * Whether a `/login` argument is an attempt to finish, rather than to start.
79
86
  *
@@ -1 +1 @@
1
- {"version":3,"file":"login-prompt.js","sourceRoot":"","sources":["../../src/tui/login-prompt.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAIH;;;;;;;GAOG;AACH,MAAM,UAAU,kBAAkB,CAAC,KAelC;IACA,MAAM,KAAK,GAAG;QACb,KAAK,CAAC,aAAa;YAClB,CAAC,CAAC,6GAA6G;YAC/G,CAAC,CAAC,0FAA0F;QAC7F,EAAE;QACF,KAAK,CAAC,GAAG;QACT,EAAE;KACF,CAAA;IACD,KAAK,CAAC,IAAI,CACT,mHAAmH,CACnH,CAAA;IACD,KAAK,CAAC,IAAI,CAAC,EAAE,EAAE,KAAK,KAAK,CAAC,cAAc,IAAI,wCAAwC,EAAE,CAAC,CAAA;IACvF,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;AACxB,CAAC;AAED,MAAM,UAAU,6BAA6B,CAAC,KAI7C;IACA,OAAO;QACN,KAAK,CAAC,aAAa;YAClB,CAAC,CAAC,oFAAoF;YACtF,CAAC,CAAC,4CAA4C;QAC/C,EAAE;QACF,KAAK,CAAC,GAAG;QACT,EAAE;QACF,kCAAkC;QAClC,KAAK,KAAK,CAAC,QAAQ,EAAE;QACrB,EAAE;QACF,wFAAwF;KACxF,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;AACb,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,oBAAoB,CACnC,OAAqB,EACrB,QAA+D,EAAE;IAEjE,IAAI,CAAC,OAAO,CAAC,EAAE,EAAE,CAAC;QACjB,OAAO,GAAG,OAAO,CAAC,MAAM,WAAW,KAAK,CAAC,KAAK,IAAI,QAAQ,gBAAgB,CAAA;IAC3E,CAAC;IACD,OAAO;QACN,qFAAqF;QACrF,KAAK,OAAO,CAAC,QAAQ,EAAE;QACvB,EAAE;QACF,wFAAwF,KAAK,CAAC,MAAM,IAAI,SAAS,gBAAgB;KACjI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;AACb,CAAC;AAED,2EAA2E;AAC3E,MAAM,UAAU,cAAc,CAAC,IAAY,EAAE,OAAgB;IAC5D,OAAO,OAAO;QACb,CAAC,CAAC,oCAAoC,IAAI,yMAAyM;QACnP,CAAC,CAAC,wKAAwK,CAAA;AAC5K,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,oBAAoB,CAAC,IAAuB;IAC3D,OAAO,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,CAAA;AACxC,CAAC"}
1
+ {"version":3,"file":"login-prompt.js","sourceRoot":"","sources":["../../src/tui/login-prompt.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAIH;;;;;;;GAOG;AACH,MAAM,UAAU,kBAAkB,CAAC,KAelC;IACA,MAAM,KAAK,GAAG;QACb,KAAK,CAAC,aAAa;YAClB,CAAC,CAAC,6GAA6G;YAC/G,CAAC,CAAC,0FAA0F;QAC7F,EAAE;QACF,KAAK,CAAC,GAAG;QACT,EAAE;KACF,CAAA;IACD,KAAK,CAAC,IAAI,CACT,mHAAmH,CACnH,CAAA;IACD,KAAK,CAAC,IAAI,CAAC,EAAE,EAAE,KAAK,KAAK,CAAC,cAAc,IAAI,wCAAwC,EAAE,CAAC,CAAA;IACvF,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;AACxB,CAAC;AAED,MAAM,UAAU,6BAA6B,CAAC,KAI7C;IACA,OAAO;QACN,KAAK,CAAC,aAAa;YAClB,CAAC,CAAC,oFAAoF;YACtF,CAAC,CAAC,4CAA4C;QAC/C,EAAE;QACF,KAAK,CAAC,GAAG;QACT,EAAE;QACF,kCAAkC;QAClC,KAAK,KAAK,CAAC,QAAQ,EAAE;QACrB,EAAE;QACF,wFAAwF;KACxF,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;AACb,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,oBAAoB,CACnC,OAAqB,EACrB,QAA+D,EAAE;IAEjE,IAAI,CAAC,OAAO,CAAC,EAAE,EAAE,CAAC;QACjB,OAAO,GAAG,OAAO,CAAC,MAAM,WAAW,KAAK,CAAC,KAAK,IAAI,QAAQ,gBAAgB,CAAA;IAC3E,CAAC;IACD,OAAO;QACN,qFAAqF;QACrF,KAAK,OAAO,CAAC,QAAQ,EAAE;QACvB,EAAE;QACF,wFAAwF,KAAK,CAAC,MAAM,IAAI,SAAS,gBAAgB;KACjI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;AACb,CAAC;AAED,2EAA2E;AAC3E,MAAM,UAAU,cAAc,CAAC,IAAY,EAAE,OAAgB;IAC5D,OAAO,OAAO;QACb,CAAC,CAAC,oCAAoC,IAAI,iMAAiM;QAC3O,CAAC,CAAC,wKAAwK,CAAA;AAC5K,CAAC;AAED,gFAAgF;AAChF,MAAM,UAAU,sBAAsB,CACrC,IAAY,EACZ,QAA+B,EAC/B,OAAgB;IAEhB,MAAM,KAAK,GAAG,QAAQ,KAAK,WAAW,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAA;IAC3D,OAAO,OAAO;QACb,CAAC,CAAC,0BAA0B,KAAK,+BAA+B,IAAI,iGAAiG,KAAK,qKAAqK;QAC/U,CAAC,CAAC,4BAA4B,KAAK,wHAAwH,CAAA;AAC7J,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,oBAAoB,CAAC,IAAuB;IAC3D,OAAO,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,CAAA;AACxC,CAAC"}
@@ -8,6 +8,25 @@
8
8
  * file is capped so a huge file can't blow up the turn. Non-existent or
9
9
  * unreadable tokens are left as literal text.
10
10
  */
11
+ export interface ActiveFileMention {
12
+ /** Inclusive `@` position in the complete composer value. */
13
+ readonly start: number;
14
+ /** Exclusive end of the token, equal to the current cursor. */
15
+ readonly end: number;
16
+ readonly query: string;
17
+ }
18
+ /** The file token currently ending at the cursor, excluding email-like text. */
19
+ export declare function activeFileMention(text: string, cursor: number): ActiveFileMention | null;
20
+ /**
21
+ * List tracked and unignored project files once per hydrated TUI session.
22
+ *
23
+ * The command is argument-vector based (no shell), bounded by time, output and
24
+ * result count, and returns no candidates outside a repository. Exact `@path`
25
+ * input keeps working outside Git; only the convenience picker is absent.
26
+ */
27
+ export declare function listMentionableFiles(cwd: string, signal?: AbortSignal): Promise<readonly string[]>;
28
+ /** Deterministic fuzzy file matches for the active token, bounded for rendering. */
29
+ export declare function matchMentionableFiles(query: string, files: readonly string[], limit?: number): readonly string[];
11
30
  export interface ExpandedMessage {
12
31
  /** Text to send to the model (original + inlined `<file>` blocks). */
13
32
  readonly sendText: string;
@@ -1 +1 @@
1
- {"version":3,"file":"mentions.d.ts","sourceRoot":"","sources":["../../src/tui/mentions.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAUH,MAAM,WAAW,eAAe;IAC/B,sEAAsE;IACtE,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;IACzB,8DAA8D;IAC9D,QAAQ,CAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,CAAA;CACpC;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CACjC,IAAI,EAAE,MAAM,EACZ,GAAG,EAAE,MAAM,EACX,QAAQ,GAAE,CAAC,OAAO,EAAE,MAAM,KAAK,MAAM,GAAG,IAAuC,GAC7E,eAAe,CAmBjB"}
1
+ {"version":3,"file":"mentions.d.ts","sourceRoot":"","sources":["../../src/tui/mentions.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAgBH,MAAM,WAAW,iBAAiB;IACjC,6DAA6D;IAC7D,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;IACtB,+DAA+D;IAC/D,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;IACpB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;CACtB;AAED,gFAAgF;AAChF,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,iBAAiB,GAAG,IAAI,CASxF;AAOD;;;;;;GAMG;AACH,wBAAsB,oBAAoB,CACzC,GAAG,EAAE,MAAM,EACX,MAAM,CAAC,EAAE,WAAW,GAClB,OAAO,CAAC,SAAS,MAAM,EAAE,CAAC,CAsB5B;AAuBD,oFAAoF;AACpF,wBAAgB,qBAAqB,CACpC,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,SAAS,MAAM,EAAE,EACxB,KAAK,SAAM,GACT,SAAS,MAAM,EAAE,CAcnB;AAED,MAAM,WAAW,eAAe;IAC/B,sEAAsE;IACtE,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;IACzB,8DAA8D;IAC9D,QAAQ,CAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,CAAA;CACpC;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CACjC,IAAI,EAAE,MAAM,EACZ,GAAG,EAAE,MAAM,EACX,QAAQ,GAAE,CAAC,OAAO,EAAE,MAAM,KAAK,MAAM,GAAG,IAAuC,GAC7E,eAAe,CAmBjB"}
@@ -8,11 +8,102 @@
8
8
  * file is capped so a huge file can't blow up the turn. Non-existent or
9
9
  * unreadable tokens are left as literal text.
10
10
  */
11
- import { readFileSync, statSync } from 'node:fs';
11
+ import { execFile } from 'node:child_process';
12
+ import { readFileSync, realpathSync, statSync } from 'node:fs';
12
13
  import { resolve, sep } from 'node:path';
14
+ import { promisify } from 'node:util';
13
15
  /** Path-ish characters only, so `@a.ts,` or `@a.ts)` don't swallow punctuation. */
14
16
  const MENTION = /@([\w./~-]+)/g;
17
+ const MENTION_PATH = /^[\w./~-]+$/u;
15
18
  const MAX_FILE_CHARS = 60_000;
19
+ const MAX_MENTION_FILES = 20_000;
20
+ const FILE_LIST_TIMEOUT_MS = 5_000;
21
+ const run = promisify(execFile);
22
+ /** The file token currently ending at the cursor, excluding email-like text. */
23
+ export function activeFileMention(text, cursor) {
24
+ const prefix = text.slice(0, Math.max(0, Math.min(cursor, text.length)));
25
+ const start = prefix.lastIndexOf('@');
26
+ if (start < 0)
27
+ return null;
28
+ const query = prefix.slice(start + 1);
29
+ if (query.length > 0 && !MENTION_PATH.test(query))
30
+ return null;
31
+ const before = start > 0 ? prefix[start - 1] : undefined;
32
+ if (before !== undefined && /[\w./~-]/u.test(before))
33
+ return null;
34
+ return { start, end: prefix.length, query };
35
+ }
36
+ function isMentionablePath(path) {
37
+ if (path.length === 0 || path.startsWith('/') || !MENTION_PATH.test(path))
38
+ return false;
39
+ return !path.split('/').some((part) => part === '' || part === '.' || part === '..');
40
+ }
41
+ /**
42
+ * List tracked and unignored project files once per hydrated TUI session.
43
+ *
44
+ * The command is argument-vector based (no shell), bounded by time, output and
45
+ * result count, and returns no candidates outside a repository. Exact `@path`
46
+ * input keeps working outside Git; only the convenience picker is absent.
47
+ */
48
+ export async function listMentionableFiles(cwd, signal) {
49
+ try {
50
+ const { stdout } = await run('git', ['ls-files', '--cached', '--others', '--exclude-standard', '-z', '--'], {
51
+ cwd,
52
+ signal,
53
+ timeout: FILE_LIST_TIMEOUT_MS,
54
+ maxBuffer: 2 * 1024 * 1024,
55
+ });
56
+ const files = [];
57
+ for (const path of stdout.split('\0')) {
58
+ if (!isMentionablePath(path))
59
+ continue;
60
+ files.push(path);
61
+ if (files.length === MAX_MENTION_FILES)
62
+ break;
63
+ }
64
+ return files;
65
+ }
66
+ catch {
67
+ return [];
68
+ }
69
+ }
70
+ function subsequenceMatch(candidate, query) {
71
+ let index = 0;
72
+ for (const character of candidate) {
73
+ if (character === query[index])
74
+ index += 1;
75
+ if (index === query.length)
76
+ return true;
77
+ }
78
+ return query.length === 0;
79
+ }
80
+ function mentionRank(path, query) {
81
+ if (query.length === 0)
82
+ return [0, path.length, path];
83
+ const normalized = path.toLowerCase();
84
+ const basename = normalized.slice(normalized.lastIndexOf('/') + 1);
85
+ if (basename.startsWith(query))
86
+ return [0, path.length, path];
87
+ if (normalized.startsWith(query))
88
+ return [1, path.length, path];
89
+ if (basename.includes(query))
90
+ return [2, path.length, path];
91
+ if (normalized.includes(query))
92
+ return [3, path.length, path];
93
+ if (subsequenceMatch(normalized, query))
94
+ return [4, path.length, path];
95
+ return null;
96
+ }
97
+ /** Deterministic fuzzy file matches for the active token, bounded for rendering. */
98
+ export function matchMentionableFiles(query, files, limit = 100) {
99
+ const normalizedQuery = query.toLowerCase();
100
+ return files
101
+ .map((path) => ({ path, rank: mentionRank(path, normalizedQuery) }))
102
+ .filter((candidate) => candidate.rank !== null)
103
+ .sort((a, b) => a.rank[0] - b.rank[0] || a.rank[1] - b.rank[1] || a.rank[2].localeCompare(b.rank[2]))
104
+ .slice(0, Math.max(0, limit))
105
+ .map(({ path }) => path);
106
+ }
16
107
  /**
17
108
  * Expand `@path` tokens in `text`. `readFile` is injectable for tests; the
18
109
  * default reads from disk, scoped to `cwd` and size-capped.
@@ -42,11 +133,11 @@ export function expandFileMentions(text, cwd, readFile = (rel) => safeReadInCwd(
42
133
  return { sendText: `${text}\n\n${blocks.join('\n\n')}`, attached };
43
134
  }
44
135
  function safeReadInCwd(cwd, rel) {
45
- const root = resolve(cwd);
46
- const abs = resolve(root, rel);
47
- if (abs !== root && !abs.startsWith(root + sep))
48
- return null;
49
136
  try {
137
+ const root = realpathSync(resolve(cwd));
138
+ const abs = realpathSync(resolve(root, rel));
139
+ if (abs !== root && !abs.startsWith(root + sep))
140
+ return null;
50
141
  if (!statSync(abs).isFile())
51
142
  return null;
52
143
  const raw = readFileSync(abs, 'utf8');
@@ -1 +1 @@
1
- {"version":3,"file":"mentions.js","sourceRoot":"","sources":["../../src/tui/mentions.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAA;AAChD,OAAO,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,WAAW,CAAA;AAExC,mFAAmF;AACnF,MAAM,OAAO,GAAG,eAAe,CAAA;AAE/B,MAAM,cAAc,GAAG,MAAM,CAAA;AAS7B;;;GAGG;AACH,MAAM,UAAU,kBAAkB,CACjC,IAAY,EACZ,GAAW,EACX,WAA+C,CAAC,GAAG,EAAE,EAAE,CAAC,aAAa,CAAC,GAAG,EAAE,GAAG,CAAC;IAE/E,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAA;IAClC,IAAI,CAAC,MAAM;QAAE,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAA;IACpD,MAAM,QAAQ,GAAa,EAAE,CAAA;IAC7B,MAAM,MAAM,GAAa,EAAE,CAAA;IAC3B,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAA;IAC9B,KAAK,MAAM,GAAG,IAAI,MAAM,EAAE,CAAC;QAC1B,wEAAwE;QACxE,wCAAwC;QACxC,MAAM,GAAG,GAAG,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,YAAY,EAAE,EAAE,CAAC,CAAA;QAClD,IAAI,GAAG,CAAC,MAAM,KAAK,CAAC,IAAI,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC;YAAE,SAAQ;QAC/C,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;QACb,MAAM,OAAO,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAA;QAC7B,IAAI,OAAO,KAAK,IAAI;YAAE,SAAQ;QAC9B,MAAM,CAAC,IAAI,CAAC,eAAe,GAAG,OAAO,OAAO,WAAW,CAAC,CAAA;QACxD,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;IACnB,CAAC;IACD,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAA;IAChE,OAAO,EAAE,QAAQ,EAAE,GAAG,IAAI,OAAO,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,EAAE,QAAQ,EAAE,CAAA;AACnE,CAAC;AAED,SAAS,aAAa,CAAC,GAAW,EAAE,GAAW;IAC9C,MAAM,IAAI,GAAG,OAAO,CAAC,GAAG,CAAC,CAAA;IACzB,MAAM,GAAG,GAAG,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,CAAA;IAC9B,IAAI,GAAG,KAAK,IAAI,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,IAAI,GAAG,GAAG,CAAC;QAAE,OAAO,IAAI,CAAA;IAC5D,IAAI,CAAC;QACJ,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE;YAAE,OAAO,IAAI,CAAA;QACxC,MAAM,GAAG,GAAG,YAAY,CAAC,GAAG,EAAE,MAAM,CAAC,CAAA;QACrC,OAAO,GAAG,CAAC,MAAM,GAAG,cAAc,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,cAAc,CAAC,iBAAiB,CAAC,CAAC,CAAC,GAAG,CAAA;IAC5F,CAAC;IAAC,MAAM,CAAC;QACR,OAAO,IAAI,CAAA;IACZ,CAAC;AACF,CAAC"}
1
+ {"version":3,"file":"mentions.js","sourceRoot":"","sources":["../../src/tui/mentions.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"open-browser.d.ts","sourceRoot":"","sources":["../../src/tui/open-browser.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAMH,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CA+BlD"}
1
+ {"version":3,"file":"open-browser.d.ts","sourceRoot":"","sources":["../../src/tui/open-browser.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAwBH,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CA6BlD"}
@@ -21,22 +21,40 @@
21
21
  * start and this says so, which is the case the paste path exists for.
22
22
  */
23
23
  import { spawn } from 'node:child_process';
24
+ import { constants, accessSync } from 'node:fs';
24
25
  import { platform } from 'node:os';
25
- import { join } from 'node:path';
26
+ import { delimiter, isAbsolute, join } from 'node:path';
27
+ /** Resolve a launcher before claiming that one started. */
28
+ function executableOnPath(name) {
29
+ for (const directory of (process.env.PATH ?? '').split(delimiter)) {
30
+ // An empty or relative PATH member delegates executable authority to the
31
+ // project cwd. Opening an OAuth URL must never run a project-owned helper.
32
+ if (!directory || !isAbsolute(directory))
33
+ continue;
34
+ const candidate = join(directory, name);
35
+ try {
36
+ accessSync(candidate, constants.X_OK);
37
+ return candidate;
38
+ }
39
+ catch {
40
+ // Keep looking. PATH order remains the operator's host policy.
41
+ }
42
+ }
43
+ return null;
44
+ }
26
45
  export function openInBrowser(url) {
27
46
  // Refuse anything that is not a web address. This is handed to the
28
47
  // machine's protocol handler, and `file:` or a custom scheme reaching it
29
48
  // would be this function opening something nobody named.
30
49
  if (!/^https?:\/\//i.test(url))
31
50
  return false;
32
- const [command, args] = platform() === 'darwin'
33
- ? ['open', [url]]
34
- : platform() === 'win32'
35
- ? [
36
- join(process.env.SystemRoot ?? 'C:\\Windows', 'System32', 'rundll32.exe'),
37
- ['url.dll,FileProtocolHandler', url],
38
- ]
39
- : ['xdg-open', [url]];
51
+ const currentPlatform = platform();
52
+ const command = currentPlatform === 'win32'
53
+ ? join(process.env.SystemRoot ?? 'C:\\Windows', 'System32', 'rundll32.exe')
54
+ : executableOnPath(currentPlatform === 'darwin' ? 'open' : 'xdg-open');
55
+ if (!command)
56
+ return false;
57
+ const args = currentPlatform === 'win32' ? ['url.dll,FileProtocolHandler', url] : [url];
40
58
  try {
41
59
  const child = spawn(command, args, {
42
60
  stdio: 'ignore',
@@ -1 +1 @@
1
- {"version":3,"file":"open-browser.js","sourceRoot":"","sources":["../../src/tui/open-browser.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAA;AAC1C,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAA;AAClC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;AAEhC,MAAM,UAAU,aAAa,CAAC,GAAW;IACxC,mEAAmE;IACnE,yEAAyE;IACzE,yDAAyD;IACzD,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,GAAG,CAAC;QAAE,OAAO,KAAK,CAAA;IAE5C,MAAM,CAAC,OAAO,EAAE,IAAI,CAAC,GACpB,QAAQ,EAAE,KAAK,QAAQ;QACtB,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC;QACjB,CAAC,CAAC,QAAQ,EAAE,KAAK,OAAO;YACvB,CAAC,CAAC;gBACA,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,UAAU,IAAI,aAAa,EAAE,UAAU,EAAE,cAAc,CAAC;gBACzE,CAAC,6BAA6B,EAAE,GAAG,CAAC;aACpC;YACF,CAAC,CAAC,CAAC,UAAU,EAAE,CAAC,GAAG,CAAC,CAAC,CAAA;IAExB,IAAI,CAAC;QACJ,MAAM,KAAK,GAAG,KAAK,CAAC,OAAiB,EAAE,IAAgB,EAAE;YACxD,KAAK,EAAE,QAAQ;YACf,QAAQ,EAAE,IAAI;SACd,CAAC,CAAA;QACF,oEAAoE;QACpE,sEAAsE;QACtE,uEAAuE;QACvE,+DAA+D;QAC/D,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE,GAAE,CAAC,CAAC,CAAA;QAC3B,KAAK,CAAC,KAAK,EAAE,CAAA;QACb,OAAO,IAAI,CAAA;IACZ,CAAC;IAAC,MAAM,CAAC;QACR,OAAO,KAAK,CAAA;IACb,CAAC;AACF,CAAC"}
1
+ {"version":3,"file":"open-browser.js","sourceRoot":"","sources":["../../src/tui/open-browser.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAA;AAC1C,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,SAAS,CAAA;AAC/C,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAA;AAClC,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;AAEvD,2DAA2D;AAC3D,SAAS,gBAAgB,CAAC,IAAY;IACrC,KAAK,MAAM,SAAS,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,SAAS,CAAC,EAAE,CAAC;QACnE,yEAAyE;QACzE,2EAA2E;QAC3E,IAAI,CAAC,SAAS,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC;YAAE,SAAQ;QAClD,MAAM,SAAS,GAAG,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,CAAA;QACvC,IAAI,CAAC;YACJ,UAAU,CAAC,SAAS,EAAE,SAAS,CAAC,IAAI,CAAC,CAAA;YACrC,OAAO,SAAS,CAAA;QACjB,CAAC;QAAC,MAAM,CAAC;YACR,+DAA+D;QAChE,CAAC;IACF,CAAC;IACD,OAAO,IAAI,CAAA;AACZ,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,GAAW;IACxC,mEAAmE;IACnE,yEAAyE;IACzE,yDAAyD;IACzD,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,GAAG,CAAC;QAAE,OAAO,KAAK,CAAA;IAE5C,MAAM,eAAe,GAAG,QAAQ,EAAE,CAAA;IAClC,MAAM,OAAO,GACZ,eAAe,KAAK,OAAO;QAC1B,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,UAAU,IAAI,aAAa,EAAE,UAAU,EAAE,cAAc,CAAC;QAC3E,CAAC,CAAC,gBAAgB,CAAC,eAAe,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,UAAU,CAAC,CAAA;IACxE,IAAI,CAAC,OAAO;QAAE,OAAO,KAAK,CAAA;IAC1B,MAAM,IAAI,GAAG,eAAe,KAAK,OAAO,CAAC,CAAC,CAAC,CAAC,6BAA6B,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAA;IAEvF,IAAI,CAAC;QACJ,MAAM,KAAK,GAAG,KAAK,CAAC,OAAO,EAAE,IAAI,EAAE;YAClC,KAAK,EAAE,QAAQ;YACf,QAAQ,EAAE,IAAI;SACd,CAAC,CAAA;QACF,oEAAoE;QACpE,sEAAsE;QACtE,uEAAuE;QACvE,+DAA+D;QAC/D,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE,GAAE,CAAC,CAAC,CAAA;QAC3B,KAAK,CAAC,KAAK,EAAE,CAAA;QACb,OAAO,IAAI,CAAA;IACZ,CAAC;IAAC,MAAM,CAAC;QACR,OAAO,KAAK,CAAA;IACb,CAAC;AACF,CAAC"}
@@ -0,0 +1,59 @@
1
+ /**
2
+ * Maximum exact permission envelope handed to an interactive reviewer.
3
+ *
4
+ * This is a refusal boundary, not a display truncation boundary. A call above
5
+ * it is not offered for approval and is not executed. Keeping the limit on the
6
+ * complete batch also prevents many individually-small calls from turning one
7
+ * consent prompt into an unbounded allocation.
8
+ */
9
+ export declare const MAX_PERMISSION_REVIEW_BYTES = 8000;
10
+ /** Physical rows kept visible in the exact-input pager. */
11
+ export declare const PERMISSION_REVIEW_PAGE_ROWS = 8;
12
+ export interface PermissionReviewCall {
13
+ readonly id: string;
14
+ readonly name: string;
15
+ readonly input: unknown;
16
+ readonly isDestructive: boolean;
17
+ }
18
+ export type PermissionReviewResult = {
19
+ readonly ok: true;
20
+ readonly text: string;
21
+ readonly bytes: number;
22
+ } | {
23
+ readonly ok: false;
24
+ readonly reason: 'too_large' | 'unrepresentable';
25
+ };
26
+ /** Actionable fail-closed feedback for a TUI review that cannot be exact. */
27
+ export declare function permissionReviewRefusal(reason: 'too_large' | 'unrepresentable'): string;
28
+ /** One terminal row of the source-preserving permission projection. */
29
+ export interface PermissionReviewRow {
30
+ /** Stable absolute position in the projected review. */
31
+ readonly index: number;
32
+ readonly text: string;
33
+ /** True when this row continues the logical line above it. */
34
+ readonly continuation: boolean;
35
+ }
36
+ /**
37
+ * Serialize the exact executable batch without invoking getters or `toJSON`.
38
+ *
39
+ * `ToolRegistry.prepareExecution()` already publishes detached JSON values,
40
+ * but this is a host boundary and structural SDK implementations can still
41
+ * supply `unknown`. Ordinary `JSON.stringify` would execute an accessor and
42
+ * could silently turn a Date/Map/custom object into something other than the
43
+ * value being approved. The bounded writer accepts only the JSON graph the
44
+ * permission protocol can preserve and stops building as soon as the complete
45
+ * envelope crosses the limit.
46
+ */
47
+ export declare function buildPermissionReview(calls: readonly PermissionReviewCall[], maxBytes?: number): PermissionReviewResult;
48
+ /**
49
+ * Project and wrap exact review text into PHYSICAL terminal rows.
50
+ *
51
+ * JSON strings can contain thousands of characters on one logical line. Ink
52
+ * would wrap that line after pagination, leaving the suffix below the viewport
53
+ * while the pager still believed there was only one row. Wrapping first makes
54
+ * the pager's unit the same row the operator sees. Non-ASCII code points count
55
+ * conservatively as two cells; overestimating produces shorter rows, never a
56
+ * hidden tail.
57
+ */
58
+ export declare function permissionReviewRows(review: string, terminalColumns: number | undefined): readonly PermissionReviewRow[];
59
+ //# sourceMappingURL=permission-review.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"permission-review.d.ts","sourceRoot":"","sources":["../../src/tui/permission-review.ts"],"names":[],"mappings":"AAEA;;;;;;;GAOG;AACH,eAAO,MAAM,2BAA2B,OAAQ,CAAA;AAEhD,2DAA2D;AAC3D,eAAO,MAAM,2BAA2B,IAAI,CAAA;AAE5C,MAAM,WAAW,oBAAoB;IACpC,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAA;IACnB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAA;IACvB,QAAQ,CAAC,aAAa,EAAE,OAAO,CAAA;CAC/B;AAED,MAAM,MAAM,sBAAsB,GAC/B;IAAE,QAAQ,CAAC,EAAE,EAAE,IAAI,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GACpE;IAAE,QAAQ,CAAC,EAAE,EAAE,KAAK,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,WAAW,GAAG,iBAAiB,CAAA;CAAE,CAAA;AAE3E,6EAA6E;AAC7E,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,WAAW,GAAG,iBAAiB,GAAG,MAAM,CAIvF;AAED,uEAAuE;AACvE,MAAM,WAAW,mBAAmB;IACnC,wDAAwD;IACxD,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;IACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,8DAA8D;IAC9D,QAAQ,CAAC,YAAY,EAAE,OAAO,CAAA;CAC9B;AAKD;;;;;;;;;;GAUG;AACH,wBAAgB,qBAAqB,CACpC,KAAK,EAAE,SAAS,oBAAoB,EAAE,EACtC,QAAQ,SAA8B,GACpC,sBAAsB,CAqJxB;AAED;;;;;;;;;GASG;AACH,wBAAgB,oBAAoB,CACnC,MAAM,EAAE,MAAM,EACd,eAAe,EAAE,MAAM,GAAG,SAAS,GACjC,SAAS,mBAAmB,EAAE,CA6BhC"}