@namzu/cli 14.3.0 → 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 (134) hide show
  1. package/README.md +107 -17
  2. package/dist/cli.d.ts.map +1 -1
  3. package/dist/cli.js +26 -26
  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/run.d.ts.map +1 -1
  15. package/dist/commands/run.js +22 -9
  16. package/dist/commands/run.js.map +1 -1
  17. package/dist/commands/{stubs.d.ts → serve.d.ts} +1 -10
  18. package/dist/commands/serve.d.ts.map +1 -0
  19. package/dist/commands/{stubs.js → serve.js} +1 -24
  20. package/dist/commands/serve.js.map +1 -0
  21. package/dist/commands/skills.d.ts +19 -0
  22. package/dist/commands/skills.d.ts.map +1 -0
  23. package/dist/commands/skills.js +107 -0
  24. package/dist/commands/skills.js.map +1 -0
  25. package/dist/integrations/mcp/servers.d.ts +7 -0
  26. package/dist/integrations/mcp/servers.d.ts.map +1 -1
  27. package/dist/integrations/mcp/servers.js +33 -8
  28. package/dist/integrations/mcp/servers.js.map +1 -1
  29. package/dist/integrations/sessions/store.d.ts +8 -0
  30. package/dist/integrations/sessions/store.d.ts.map +1 -1
  31. package/dist/integrations/sessions/store.js +15 -0
  32. package/dist/integrations/sessions/store.js.map +1 -1
  33. package/dist/integrations/subagents/runtime.d.ts +2 -0
  34. package/dist/integrations/subagents/runtime.d.ts.map +1 -1
  35. package/dist/integrations/subagents/runtime.js +86 -13
  36. package/dist/integrations/subagents/runtime.js.map +1 -1
  37. package/dist/integrations/updates.d.ts.map +1 -1
  38. package/dist/integrations/updates.js +29 -4
  39. package/dist/integrations/updates.js.map +1 -1
  40. package/dist/tui/App.d.ts +10 -1
  41. package/dist/tui/App.d.ts.map +1 -1
  42. package/dist/tui/App.js +1003 -186
  43. package/dist/tui/App.js.map +1 -1
  44. package/dist/tui/ChoicePicker.d.ts +2 -1
  45. package/dist/tui/ChoicePicker.d.ts.map +1 -1
  46. package/dist/tui/ChoicePicker.js +10 -6
  47. package/dist/tui/ChoicePicker.js.map +1 -1
  48. package/dist/tui/Composer.d.ts +19 -2
  49. package/dist/tui/Composer.d.ts.map +1 -1
  50. package/dist/tui/Composer.js +526 -70
  51. package/dist/tui/Composer.js.map +1 -1
  52. package/dist/tui/CopyPicker.d.ts.map +1 -1
  53. package/dist/tui/CopyPicker.js +3 -4
  54. package/dist/tui/CopyPicker.js.map +1 -1
  55. package/dist/tui/EditPromptPicker.d.ts.map +1 -1
  56. package/dist/tui/EditPromptPicker.js +3 -4
  57. package/dist/tui/EditPromptPicker.js.map +1 -1
  58. package/dist/tui/Markdown.d.ts +3 -1
  59. package/dist/tui/Markdown.d.ts.map +1 -1
  60. package/dist/tui/Markdown.js +11 -9
  61. package/dist/tui/Markdown.js.map +1 -1
  62. package/dist/tui/PermissionOverlay.d.ts +11 -6
  63. package/dist/tui/PermissionOverlay.d.ts.map +1 -1
  64. package/dist/tui/PermissionOverlay.js +13 -20
  65. package/dist/tui/PermissionOverlay.js.map +1 -1
  66. package/dist/tui/Picker.d.ts.map +1 -1
  67. package/dist/tui/Picker.js +47 -11
  68. package/dist/tui/Picker.js.map +1 -1
  69. package/dist/tui/ResumePicker.d.ts.map +1 -1
  70. package/dist/tui/ResumePicker.js +6 -1
  71. package/dist/tui/ResumePicker.js.map +1 -1
  72. package/dist/tui/TextPrompt.d.ts +21 -0
  73. package/dist/tui/TextPrompt.d.ts.map +1 -0
  74. package/dist/tui/TextPrompt.js +139 -0
  75. package/dist/tui/TextPrompt.js.map +1 -0
  76. package/dist/tui/Transcript.d.ts +3 -3
  77. package/dist/tui/Transcript.d.ts.map +1 -1
  78. package/dist/tui/Transcript.js +4 -4
  79. package/dist/tui/Transcript.js.map +1 -1
  80. package/dist/tui/agent.d.ts +24 -20
  81. package/dist/tui/agent.d.ts.map +1 -1
  82. package/dist/tui/agent.js +98 -74
  83. package/dist/tui/agent.js.map +1 -1
  84. package/dist/tui/exit-summary.d.ts.map +1 -1
  85. package/dist/tui/exit-summary.js +2 -1
  86. package/dist/tui/exit-summary.js.map +1 -1
  87. package/dist/tui/external-editor.d.ts +25 -0
  88. package/dist/tui/external-editor.d.ts.map +1 -0
  89. package/dist/tui/external-editor.js +169 -0
  90. package/dist/tui/external-editor.js.map +1 -0
  91. package/dist/tui/index.d.ts.map +1 -1
  92. package/dist/tui/index.js +4 -0
  93. package/dist/tui/index.js.map +1 -1
  94. package/dist/tui/login-prompt.d.ts +2 -0
  95. package/dist/tui/login-prompt.d.ts.map +1 -1
  96. package/dist/tui/login-prompt.js +8 -1
  97. package/dist/tui/login-prompt.js.map +1 -1
  98. package/dist/tui/mentions.d.ts +19 -0
  99. package/dist/tui/mentions.d.ts.map +1 -1
  100. package/dist/tui/mentions.js +96 -5
  101. package/dist/tui/mentions.js.map +1 -1
  102. package/dist/tui/permission-review.d.ts +59 -0
  103. package/dist/tui/permission-review.d.ts.map +1 -0
  104. package/dist/tui/permission-review.js +219 -0
  105. package/dist/tui/permission-review.js.map +1 -0
  106. package/dist/tui/selection-window.d.ts +18 -0
  107. package/dist/tui/selection-window.d.ts.map +1 -0
  108. package/dist/tui/selection-window.js +37 -0
  109. package/dist/tui/selection-window.js.map +1 -0
  110. package/dist/tui/slashCommands.d.ts +48 -8
  111. package/dist/tui/slashCommands.d.ts.map +1 -1
  112. package/dist/tui/slashCommands.js +129 -47
  113. package/dist/tui/slashCommands.js.map +1 -1
  114. package/dist/tui/terminal-hyperlinks.d.ts +20 -0
  115. package/dist/tui/terminal-hyperlinks.d.ts.map +1 -0
  116. package/dist/tui/terminal-hyperlinks.js +70 -0
  117. package/dist/tui/terminal-hyperlinks.js.map +1 -0
  118. package/dist/tui/types.d.ts +2 -0
  119. package/dist/tui/types.d.ts.map +1 -1
  120. package/dist/tui/use-selection-index.d.ts +8 -0
  121. package/dist/tui/use-selection-index.d.ts.map +1 -0
  122. package/dist/tui/use-selection-index.js +13 -0
  123. package/dist/tui/use-selection-index.js.map +1 -0
  124. package/dist/tui/workspace-review.d.ts +15 -0
  125. package/dist/tui/workspace-review.d.ts.map +1 -0
  126. package/dist/tui/workspace-review.js +67 -0
  127. package/dist/tui/workspace-review.js.map +1 -0
  128. package/dist/version.d.ts +10 -0
  129. package/dist/version.d.ts.map +1 -0
  130. package/dist/version.js +23 -0
  131. package/dist/version.js.map +1 -0
  132. package/package.json +6 -5
  133. package/dist/commands/stubs.d.ts.map +0 -1
  134. package/dist/commands/stubs.js.map +0 -1
@@ -0,0 +1,25 @@
1
+ export declare class ExternalEditorError extends Error {
2
+ constructor(message: string);
3
+ }
4
+ /**
5
+ * Split the operator-owned VISUAL/EDITOR value without invoking a shell.
6
+ *
7
+ * Quotes admit executable paths and arguments with spaces. A backslash only
8
+ * escapes syntax that needs escaping, so an ordinary Windows path does not
9
+ * lose every separator when the same configuration is used across shells.
10
+ */
11
+ export declare function parseExternalEditorCommand(raw: string): readonly string[];
12
+ export declare function resolveExternalEditorCommand(env?: Readonly<NodeJS.ProcessEnv>): readonly string[];
13
+ export interface ExternalEditorOptions {
14
+ readonly cwd: string;
15
+ readonly env?: Readonly<NodeJS.ProcessEnv>;
16
+ readonly signal?: AbortSignal;
17
+ readonly temporaryRoot?: string;
18
+ }
19
+ /**
20
+ * Run the operator's configured editor against a private temporary Markdown
21
+ * file and return the edited text. This is a direct host action explicitly
22
+ * requested by the operator; it is never exposed to the model as a tool.
23
+ */
24
+ export declare function editDraftInExternalEditor(seed: string, options: ExternalEditorOptions): Promise<string>;
25
+ //# sourceMappingURL=external-editor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"external-editor.d.ts","sourceRoot":"","sources":["../../src/tui/external-editor.ts"],"names":[],"mappings":"AAOA,qBAAa,mBAAoB,SAAQ,KAAK;gBACjC,OAAO,EAAE,MAAM;CAI3B;AAED;;;;;;GAMG;AACH,wBAAgB,0BAA0B,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,MAAM,EAAE,CAmEzE;AAED,wBAAgB,4BAA4B,CAC3C,GAAG,GAAE,QAAQ,CAAC,MAAM,CAAC,UAAU,CAAe,GAC5C,SAAS,MAAM,EAAE,CAMnB;AAED,MAAM,WAAW,qBAAqB;IACrC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;IACpB,QAAQ,CAAC,GAAG,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,UAAU,CAAC,CAAA;IAC1C,QAAQ,CAAC,MAAM,CAAC,EAAE,WAAW,CAAA;IAC7B,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAA;CAC/B;AAED;;;;GAIG;AACH,wBAAsB,yBAAyB,CAC9C,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,qBAAqB,GAC5B,OAAO,CAAC,MAAM,CAAC,CAoCjB"}
@@ -0,0 +1,169 @@
1
+ import { spawn } from 'node:child_process';
2
+ import { lstat, mkdtemp, readFile, rm, writeFile } from 'node:fs/promises';
3
+ import { tmpdir } from 'node:os';
4
+ import { join } from 'node:path';
5
+ const MAX_EDITED_DRAFT_BYTES = 4 * 1024 * 1024;
6
+ export class ExternalEditorError extends Error {
7
+ constructor(message) {
8
+ super(message);
9
+ this.name = 'ExternalEditorError';
10
+ }
11
+ }
12
+ /**
13
+ * Split the operator-owned VISUAL/EDITOR value without invoking a shell.
14
+ *
15
+ * Quotes admit executable paths and arguments with spaces. A backslash only
16
+ * escapes syntax that needs escaping, so an ordinary Windows path does not
17
+ * lose every separator when the same configuration is used across shells.
18
+ */
19
+ export function parseExternalEditorCommand(raw) {
20
+ const result = [];
21
+ let token = '';
22
+ let tokenStarted = false;
23
+ let quote = null;
24
+ for (let index = 0; index < raw.length; index += 1) {
25
+ const char = raw[index] ?? '';
26
+ if (quote === 'single') {
27
+ if (char === "'")
28
+ quote = null;
29
+ else
30
+ token += char;
31
+ continue;
32
+ }
33
+ if (quote === 'double') {
34
+ if (char === '"') {
35
+ quote = null;
36
+ continue;
37
+ }
38
+ if (char === '\\') {
39
+ const next = raw[index + 1];
40
+ if (next === '"' || next === '\\') {
41
+ token += next;
42
+ index += 1;
43
+ continue;
44
+ }
45
+ }
46
+ token += char;
47
+ continue;
48
+ }
49
+ if (/\s/u.test(char)) {
50
+ if (tokenStarted) {
51
+ result.push(token);
52
+ token = '';
53
+ tokenStarted = false;
54
+ }
55
+ continue;
56
+ }
57
+ if (char === "'") {
58
+ quote = 'single';
59
+ tokenStarted = true;
60
+ continue;
61
+ }
62
+ if (char === '"') {
63
+ quote = 'double';
64
+ tokenStarted = true;
65
+ continue;
66
+ }
67
+ if (char === '\\') {
68
+ const next = raw[index + 1];
69
+ if (next !== undefined &&
70
+ (/\s/u.test(next) || next === '"' || next === "'" || next === '\\')) {
71
+ token += next;
72
+ tokenStarted = true;
73
+ index += 1;
74
+ continue;
75
+ }
76
+ }
77
+ token += char;
78
+ tokenStarted = true;
79
+ }
80
+ if (quote)
81
+ throw new ExternalEditorError('the editor command contains an unclosed quote');
82
+ if (tokenStarted)
83
+ result.push(token);
84
+ if (!result[0])
85
+ throw new ExternalEditorError('neither VISUAL nor EDITOR names an executable');
86
+ return result;
87
+ }
88
+ export function resolveExternalEditorCommand(env = process.env) {
89
+ const visual = env.VISUAL?.trim();
90
+ const editor = env.EDITOR?.trim();
91
+ const raw = visual || editor;
92
+ if (!raw)
93
+ throw new ExternalEditorError('set VISUAL or EDITOR before pressing Ctrl+G');
94
+ return parseExternalEditorCommand(raw);
95
+ }
96
+ /**
97
+ * Run the operator's configured editor against a private temporary Markdown
98
+ * file and return the edited text. This is a direct host action explicitly
99
+ * requested by the operator; it is never exposed to the model as a tool.
100
+ */
101
+ export async function editDraftInExternalEditor(seed, options) {
102
+ options.signal?.throwIfAborted();
103
+ const command = resolveExternalEditorCommand(options.env);
104
+ const directory = await mkdtemp(join(options.temporaryRoot ?? tmpdir(), 'namzu-editor-'));
105
+ const draftPath = join(directory, 'draft.md');
106
+ let edited;
107
+ let failure;
108
+ try {
109
+ await writeFile(draftPath, seed, { encoding: 'utf8', flag: 'wx', mode: 0o600 });
110
+ await runEditorProcess(command, draftPath, options);
111
+ const metadata = await lstat(draftPath);
112
+ if (!metadata.isFile()) {
113
+ throw new ExternalEditorError('the editor replaced the draft with a non-file');
114
+ }
115
+ const size = metadata.size;
116
+ if (size > MAX_EDITED_DRAFT_BYTES) {
117
+ throw new ExternalEditorError(`the edited draft is ${size.toLocaleString()} bytes; the limit is ${MAX_EDITED_DRAFT_BYTES.toLocaleString()}`);
118
+ }
119
+ edited = await readFile(draftPath, 'utf8');
120
+ }
121
+ catch (error) {
122
+ failure = error;
123
+ }
124
+ try {
125
+ await rm(directory, {
126
+ force: true,
127
+ recursive: true,
128
+ maxRetries: 5,
129
+ retryDelay: 50,
130
+ });
131
+ }
132
+ catch {
133
+ throw new ExternalEditorError('could not remove the private temporary editor buffer');
134
+ }
135
+ if (failure !== undefined)
136
+ throw failure;
137
+ return edited ?? '';
138
+ }
139
+ async function runEditorProcess(command, draftPath, options) {
140
+ const executable = command[0];
141
+ if (!executable)
142
+ throw new ExternalEditorError('the editor command is empty');
143
+ await new Promise((resolve, reject) => {
144
+ let settled = false;
145
+ const settle = (action) => {
146
+ if (settled)
147
+ return;
148
+ settled = true;
149
+ action();
150
+ };
151
+ const child = spawn(executable, [...command.slice(1), draftPath], {
152
+ cwd: options.cwd,
153
+ env: options.env ? { ...options.env } : process.env,
154
+ signal: options.signal,
155
+ stdio: 'inherit',
156
+ windowsHide: false,
157
+ });
158
+ child.once('error', (error) => settle(() => reject(new ExternalEditorError(`could not start the editor: ${error.message}`))));
159
+ child.once('exit', (code, signal) => settle(() => {
160
+ if (code === 0)
161
+ resolve();
162
+ else if (signal)
163
+ reject(new ExternalEditorError(`the editor stopped on signal ${signal}`));
164
+ else
165
+ reject(new ExternalEditorError(`the editor exited with status ${code ?? 'unknown'}`));
166
+ }));
167
+ });
168
+ }
169
+ //# sourceMappingURL=external-editor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"external-editor.js","sourceRoot":"","sources":["../../src/tui/external-editor.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/tui/index.tsx"],"names":[],"mappings":"AAAA;;;GAGG;AAQH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAA;AAE5C,wBAAsB,SAAS,CAAC,GAAG,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CAuC9D"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/tui/index.tsx"],"names":[],"mappings":"AAAA;;;GAGG;AAQH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAA;AAE5C,wBAAsB,SAAS,CAAC,GAAG,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CA2C9D"}
package/dist/tui/index.js CHANGED
@@ -35,6 +35,10 @@ export async function launchTui(ctx) {
35
35
  stderr: process.stderr,
36
36
  stdin: process.stdin,
37
37
  exitOnCtrlC: false,
38
+ kittyKeyboard: {
39
+ mode: 'auto',
40
+ flags: ['disambiguateEscapeCodes'],
41
+ },
38
42
  });
39
43
  try {
40
44
  await instance.waitUntilExit();
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/tui/index.tsx"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,KAAK,CAAA;AAC5B,OAAO,KAAK,MAAM,OAAO,CAAA;AAEzB,OAAO,EAAE,GAAG,EAAE,MAAM,UAAU,CAAA;AAC9B,OAAO,EAAuB,oBAAoB,EAAE,MAAM,mBAAmB,CAAA;AAC7E,OAAO,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAA;AAGjD,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,GAAe;IAC9C,uEAAuE;IACvE,6DAA6D;IAC7D,+DAA+D;IAC/D,uEAAuE;IACvE,uEAAuE;IACvE,uEAAuE;IACvE,2EAA2E;IAC3E,2EAA2E;IAC3E,MAAM,IAAI,GAAG,iBAAiB,CAAC,GAAG,CAAC,OAAO,CAAC,CAAA;IAC3C,IAAI,WAAW,GAA0B,IAAI,CAAA;IAC7C,qEAAqE;IACrE,0CAA0C;IAC1C,yEAAyE;IACzE,yDAAyD;IACzD,IAAI,OAAO,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC;QAC1B,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,sBAAsB,CAAC,CAAA;IAC7C,CAAC;IACD,MAAM,QAAQ,GAAG,MAAM,CACtB,KAAK,CAAC,aAAa,CAAC,GAAG,EAAE;QACxB,GAAG;QACH,aAAa,EAAE,CAAC,OAAuB,EAAE,EAAE;YAC1C,WAAW,GAAG,OAAO,CAAA;QACtB,CAAC;KACD,CAAC,EACF;QACC,MAAM,EAAE,OAAO,CAAC,MAAM;QACtB,MAAM,EAAE,OAAO,CAAC,MAAM;QACtB,KAAK,EAAE,OAAO,CAAC,KAAK;QACpB,WAAW,EAAE,KAAK;KAClB,CACD,CAAA;IACD,IAAI,CAAC;QACJ,MAAM,QAAQ,CAAC,aAAa,EAAE,CAAA;IAC/B,CAAC;YAAS,CAAC;QACV,IAAI,CAAC,KAAK,EAAE,CAAA;QACZ,MAAM,OAAO,GAAG,oBAAoB,CAAC,WAAW,CAAC,CAAA;QACjD,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC;YAAE,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,CAAA;IACtD,CAAC;AACF,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/tui/index.tsx"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,KAAK,CAAA;AAC5B,OAAO,KAAK,MAAM,OAAO,CAAA;AAEzB,OAAO,EAAE,GAAG,EAAE,MAAM,UAAU,CAAA;AAC9B,OAAO,EAAuB,oBAAoB,EAAE,MAAM,mBAAmB,CAAA;AAC7E,OAAO,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAA;AAGjD,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,GAAe;IAC9C,uEAAuE;IACvE,6DAA6D;IAC7D,+DAA+D;IAC/D,uEAAuE;IACvE,uEAAuE;IACvE,uEAAuE;IACvE,2EAA2E;IAC3E,2EAA2E;IAC3E,MAAM,IAAI,GAAG,iBAAiB,CAAC,GAAG,CAAC,OAAO,CAAC,CAAA;IAC3C,IAAI,WAAW,GAA0B,IAAI,CAAA;IAC7C,qEAAqE;IACrE,0CAA0C;IAC1C,yEAAyE;IACzE,yDAAyD;IACzD,IAAI,OAAO,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC;QAC1B,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,sBAAsB,CAAC,CAAA;IAC7C,CAAC;IACD,MAAM,QAAQ,GAAG,MAAM,CACtB,KAAK,CAAC,aAAa,CAAC,GAAG,EAAE;QACxB,GAAG;QACH,aAAa,EAAE,CAAC,OAAuB,EAAE,EAAE;YAC1C,WAAW,GAAG,OAAO,CAAA;QACtB,CAAC;KACD,CAAC,EACF;QACC,MAAM,EAAE,OAAO,CAAC,MAAM;QACtB,MAAM,EAAE,OAAO,CAAC,MAAM;QACtB,KAAK,EAAE,OAAO,CAAC,KAAK;QACpB,WAAW,EAAE,KAAK;QAClB,aAAa,EAAE;YACd,IAAI,EAAE,MAAM;YACZ,KAAK,EAAE,CAAC,yBAAyB,CAAC;SAClC;KACD,CACD,CAAA;IACD,IAAI,CAAC;QACJ,MAAM,QAAQ,CAAC,aAAa,EAAE,CAAA;IAC/B,CAAC;YAAS,CAAC;QACV,IAAI,CAAC,KAAK,EAAE,CAAA;QACZ,MAAM,OAAO,GAAG,oBAAoB,CAAC,WAAW,CAAC,CAAA;QACjD,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC;YAAE,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,CAAA;IACtD,CAAC;AACF,CAAC"}
@@ -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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"}
@@ -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"}