codebase-cli 2.0.0-pre.4 → 2.0.0-pre.41

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 (111) hide show
  1. package/dist/agent/agent.js +43 -15
  2. package/dist/agent/agent.js.map +1 -1
  3. package/dist/agent/config.js +61 -20
  4. package/dist/agent/config.js.map +1 -1
  5. package/dist/agent/events.bench.js +84 -0
  6. package/dist/agent/events.bench.js.map +1 -0
  7. package/dist/agent/prompt-suggestion.js +141 -0
  8. package/dist/agent/prompt-suggestion.js.map +1 -0
  9. package/dist/agent/system-prompt.js +15 -0
  10. package/dist/agent/system-prompt.js.map +1 -1
  11. package/dist/app-server/protocol.js +7 -0
  12. package/dist/app-server/protocol.js.map +1 -0
  13. package/dist/app-server/server.js +241 -0
  14. package/dist/app-server/server.js.map +1 -0
  15. package/dist/auth/cli.js +1 -1
  16. package/dist/auth/cli.js.map +1 -1
  17. package/dist/auth/credentials.js +33 -2
  18. package/dist/auth/credentials.js.map +1 -1
  19. package/dist/auth/flow.js +145 -24
  20. package/dist/auth/flow.js.map +1 -1
  21. package/dist/auth/token-manager.js +122 -0
  22. package/dist/auth/token-manager.js.map +1 -0
  23. package/dist/cli.js +56 -1
  24. package/dist/cli.js.map +1 -1
  25. package/dist/commands/builtins.js +160 -14
  26. package/dist/commands/builtins.js.map +1 -1
  27. package/dist/commands/registry.js +46 -1
  28. package/dist/commands/registry.js.map +1 -1
  29. package/dist/compaction/monitor.js +38 -0
  30. package/dist/compaction/monitor.js.map +1 -0
  31. package/dist/config/types.js.map +1 -1
  32. package/dist/glue/client.js +12 -2
  33. package/dist/glue/client.js.map +1 -1
  34. package/dist/hooks/manager.js +8 -2
  35. package/dist/hooks/manager.js.map +1 -1
  36. package/dist/memory/store.js +2 -3
  37. package/dist/memory/store.js.map +1 -1
  38. package/dist/plan/run-flow.js +89 -0
  39. package/dist/plan/run-flow.js.map +1 -0
  40. package/dist/projects/cli.js +92 -0
  41. package/dist/projects/cli.js.map +1 -0
  42. package/dist/projects/client.js +120 -0
  43. package/dist/projects/client.js.map +1 -0
  44. package/dist/projects/types.js +2 -0
  45. package/dist/projects/types.js.map +1 -0
  46. package/dist/skills/platform-loader.js +133 -38
  47. package/dist/skills/platform-loader.js.map +1 -1
  48. package/dist/tools/__test__/mock-tool-context.js +31 -0
  49. package/dist/tools/__test__/mock-tool-context.js.map +1 -0
  50. package/dist/tools/file-state-cache.js.map +1 -1
  51. package/dist/tools/read-file.js +7 -2
  52. package/dist/tools/read-file.js.map +1 -1
  53. package/dist/ui/App.js +109 -110
  54. package/dist/ui/App.js.map +1 -1
  55. package/dist/ui/CompactionBanner.js +23 -0
  56. package/dist/ui/CompactionBanner.js.map +1 -0
  57. package/dist/ui/FirstRunSetup.js +66 -14
  58. package/dist/ui/FirstRunSetup.js.map +1 -1
  59. package/dist/ui/Input.js +370 -20
  60. package/dist/ui/Input.js.map +1 -1
  61. package/dist/ui/Markdown.js +286 -0
  62. package/dist/ui/Markdown.js.map +1 -0
  63. package/dist/ui/Message.js +110 -48
  64. package/dist/ui/Message.js.map +1 -1
  65. package/dist/ui/MessageList.js +100 -3
  66. package/dist/ui/MessageList.js.map +1 -1
  67. package/dist/ui/Permission.js +43 -20
  68. package/dist/ui/Permission.js.map +1 -1
  69. package/dist/ui/PixelC.js +25 -0
  70. package/dist/ui/PixelC.js.map +1 -0
  71. package/dist/ui/Status.js +267 -7
  72. package/dist/ui/Status.js.map +1 -1
  73. package/dist/ui/Throbber.js +11 -7
  74. package/dist/ui/Throbber.js.map +1 -1
  75. package/dist/ui/Welcome.js +59 -0
  76. package/dist/ui/Welcome.js.map +1 -0
  77. package/dist/ui/attachments.js +68 -0
  78. package/dist/ui/attachments.js.map +1 -0
  79. package/dist/ui/debug-input.js +44 -0
  80. package/dist/ui/debug-input.js.map +1 -0
  81. package/dist/ui/diff-summary.js +171 -0
  82. package/dist/ui/diff-summary.js.map +1 -0
  83. package/dist/ui/highlight.js +324 -0
  84. package/dist/ui/highlight.js.map +1 -0
  85. package/dist/ui/history-store.js +60 -0
  86. package/dist/ui/history-store.js.map +1 -0
  87. package/dist/ui/input-state.js +125 -1
  88. package/dist/ui/input-state.js.map +1 -1
  89. package/dist/ui/path-complete.js +102 -0
  90. package/dist/ui/path-complete.js.map +1 -0
  91. package/dist/ui/paths.js +41 -0
  92. package/dist/ui/paths.js.map +1 -0
  93. package/dist/ui/shell-escape.js +42 -0
  94. package/dist/ui/shell-escape.js.map +1 -0
  95. package/dist/ui/terminal-restore.js +83 -0
  96. package/dist/ui/terminal-restore.js.map +1 -0
  97. package/dist/ui/terminal-title.js +21 -0
  98. package/dist/ui/terminal-title.js.map +1 -0
  99. package/dist/ui/tool-call-line.js +83 -0
  100. package/dist/ui/tool-call-line.js.map +1 -0
  101. package/dist/ui/tool-labels.js +194 -0
  102. package/dist/ui/tool-labels.js.map +1 -0
  103. package/dist/ui/truncated-output.js +42 -0
  104. package/dist/ui/truncated-output.js.map +1 -0
  105. package/dist/ui/use-coalesced-agent-events.js +70 -0
  106. package/dist/ui/use-coalesced-agent-events.js.map +1 -0
  107. package/dist/ui/use-prompt-suggestion.js +52 -0
  108. package/dist/ui/use-prompt-suggestion.js.map +1 -0
  109. package/dist/ui/wrapped-lines.js +18 -0
  110. package/dist/ui/wrapped-lines.js.map +1 -0
  111. package/package.json +6 -1
@@ -0,0 +1,102 @@
1
+ import { readdirSync, statSync } from "node:fs";
2
+ import { isAbsolute, join, posix } from "node:path";
3
+ const MAX_RESULTS = 12;
4
+ const IGNORED_DIRS = new Set([
5
+ ".git",
6
+ "node_modules",
7
+ ".next",
8
+ "dist",
9
+ "build",
10
+ ".turbo",
11
+ ".cache",
12
+ ".venv",
13
+ "venv",
14
+ "__pycache__",
15
+ "target",
16
+ ]);
17
+ /**
18
+ * Complete a path prefix against the filesystem, returning up to
19
+ * MAX_RESULTS candidates ordered alphabetically. Directories sort
20
+ * first and end in `/` so users can tell them apart at a glance.
21
+ *
22
+ * `prefix` is the text after `@` — a relative or absolute path, or
23
+ * empty. Examples:
24
+ * "" → contents of cwd
25
+ * "src" → siblings of cwd starting with "src"
26
+ * "src/ui" → contents of src/ filtered to those starting with "ui"
27
+ * "src/ui/" → contents of src/ui
28
+ *
29
+ * Returns the matched relative paths (still beginning with the
30
+ * directory parts the user already typed). Caller is responsible
31
+ * for stitching them back into the buffer.
32
+ */
33
+ export function completePath(prefix, cwd) {
34
+ const { dir, partial } = splitPrefix(prefix);
35
+ const root = isAbsolute(dir) ? dir : dir ? join(cwd, dir) : cwd;
36
+ let entries;
37
+ try {
38
+ entries = readdirSync(root);
39
+ }
40
+ catch {
41
+ return [];
42
+ }
43
+ const out = [];
44
+ for (const name of entries) {
45
+ if (name.startsWith(".") && !partial.startsWith("."))
46
+ continue;
47
+ if (IGNORED_DIRS.has(name))
48
+ continue;
49
+ if (!name.toLowerCase().startsWith(partial.toLowerCase()))
50
+ continue;
51
+ let isDir = false;
52
+ try {
53
+ isDir = statSync(join(root, name)).isDirectory();
54
+ }
55
+ catch {
56
+ continue;
57
+ }
58
+ out.push({ name, isDir });
59
+ }
60
+ out.sort((a, b) => {
61
+ if (a.isDir !== b.isDir)
62
+ return a.isDir ? -1 : 1;
63
+ return a.name.localeCompare(b.name);
64
+ });
65
+ return out.slice(0, MAX_RESULTS).map(({ name, isDir }) => {
66
+ const joined = dir ? posix.join(dir, name) : name;
67
+ return isDir ? `${joined}/` : joined;
68
+ });
69
+ }
70
+ /** Split "src/ui/In" into { dir: "src/ui", partial: "In" }. */
71
+ function splitPrefix(prefix) {
72
+ const idx = prefix.lastIndexOf("/");
73
+ if (idx < 0)
74
+ return { dir: "", partial: prefix };
75
+ return { dir: prefix.slice(0, idx), partial: prefix.slice(idx + 1) };
76
+ }
77
+ /**
78
+ * Locate the `@<path>` token at or immediately before the cursor.
79
+ * Returns the start index and the typed prefix (no leading `@`), or
80
+ * null if the cursor isn't inside an @-token.
81
+ */
82
+ export function findAtTokenAt(buffer, cursor) {
83
+ if (cursor === 0)
84
+ return null;
85
+ // Walk back from cursor — accept the path-charset, stop at whitespace.
86
+ let i = cursor;
87
+ while (i > 0) {
88
+ const ch = buffer[i - 1];
89
+ if (ch === "@") {
90
+ // Make sure it's a standalone @ (start of buffer or preceded by whitespace).
91
+ if (i - 1 === 0 || /\s/.test(buffer[i - 2])) {
92
+ return { start: i - 1, prefix: buffer.slice(i, cursor) };
93
+ }
94
+ return null;
95
+ }
96
+ if (!/[A-Za-z0-9_./-]/.test(ch))
97
+ return null;
98
+ i--;
99
+ }
100
+ return null;
101
+ }
102
+ //# sourceMappingURL=path-complete.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"path-complete.js","sourceRoot":"","sources":["../../src/ui/path-complete.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,41 @@
1
+ import { isAbsolute, sep as pathSep, relative as relativePath, resolve as resolveAbsolute } from "node:path";
2
+ /**
3
+ * Show a path relative to the working directory when it's inside (so
4
+ * "src/ui/Message.tsx" instead of "/home/half/.../src/ui/Message.tsx"),
5
+ * but keep it absolute when it points outside the project — that's
6
+ * useful information the user should see at full fidelity. Empty
7
+ * strings pass through unchanged. The returned string is wrapped in an
8
+ * OSC 8 hyperlink so supporting terminals make it clickable.
9
+ */
10
+ export function displayPath(p) {
11
+ if (!p)
12
+ return p;
13
+ const visible = makeRelative(p);
14
+ return hyperlinkPath(visible, p);
15
+ }
16
+ export function makeRelative(p) {
17
+ if (!p.startsWith(pathSep))
18
+ return p; // already relative
19
+ const cwd = process.cwd();
20
+ const rel = relativePath(cwd, p);
21
+ if (!rel || rel.startsWith(".."))
22
+ return p; // outside cwd — keep absolute
23
+ return rel;
24
+ }
25
+ /**
26
+ * Wrap a visible path in an OSC 8 hyperlink so terminals that support
27
+ * it (Ghostty, iTerm2, Kitty, recent gnome-terminal) make file paths
28
+ * clickable — click opens the file in $EDITOR / the OS default. The
29
+ * escape is zero-width and well-handled by wrap-ansi for width calc.
30
+ * Terminals that don't recognise OSC 8 silently strip it, so the
31
+ * fallback is just "non-clickable plain text" — no visible breakage.
32
+ * Opt-out: NO_HYPERLINK=1.
33
+ */
34
+ export function hyperlinkPath(visible, rawPath) {
35
+ if (process.env.NO_HYPERLINK === "1")
36
+ return visible;
37
+ const absolute = isAbsolute(rawPath) ? rawPath : resolveAbsolute(process.cwd(), rawPath);
38
+ const url = `file://${absolute.split(pathSep).map(encodeURIComponent).join("/")}`;
39
+ return `\x1b]8;;${url}\x1b\\${visible}\x1b]8;;\x1b\\`;
40
+ }
41
+ //# sourceMappingURL=paths.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"paths.js","sourceRoot":"","sources":["../../src/ui/paths.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,GAAG,IAAI,OAAO,EAAE,QAAQ,IAAI,YAAY,EAAE,OAAO,IAAI,eAAe,EAAE,MAAM,WAAW,CAAC;AAE7G;;;;;;;GAOG;AACH,MAAM,UAAU,WAAW,CAAC,CAAS;IACpC,IAAI,CAAC,CAAC;QAAE,OAAO,CAAC,CAAC;IACjB,MAAM,OAAO,GAAG,YAAY,CAAC,CAAC,CAAC,CAAC;IAChC,OAAO,aAAa,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;AAClC,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,CAAS;IACrC,IAAI,CAAC,CAAC,CAAC,UAAU,CAAC,OAAO,CAAC;QAAE,OAAO,CAAC,CAAC,CAAC,mBAAmB;IACzD,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC;IAC1B,MAAM,GAAG,GAAG,YAAY,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;IACjC,IAAI,CAAC,GAAG,IAAI,GAAG,CAAC,UAAU,CAAC,IAAI,CAAC;QAAE,OAAO,CAAC,CAAC,CAAC,8BAA8B;IAC1E,OAAO,GAAG,CAAC;AACZ,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,aAAa,CAAC,OAAe,EAAE,OAAe;IAC7D,IAAI,OAAO,CAAC,GAAG,CAAC,YAAY,KAAK,GAAG;QAAE,OAAO,OAAO,CAAC;IACrD,MAAM,QAAQ,GAAG,UAAU,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,eAAe,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,OAAO,CAAC,CAAC;IACzF,MAAM,GAAG,GAAG,UAAU,QAAQ,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,kBAAkB,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;IAClF,OAAO,WAAW,GAAG,SAAS,OAAO,gBAAgB,CAAC;AACvD,CAAC"}
@@ -0,0 +1,42 @@
1
+ import { spawn } from "node:child_process";
2
+ /**
3
+ * Run a one-shot `!command` and append its output to the status lines.
4
+ * This is intentionally divorced from the agent's shell tool — the
5
+ * agent's tool is for tool-use turns, this is a CLI escape so the user
6
+ * can `!git status` without spending a turn. Output is capped at 32 KB
7
+ * to keep the transcript from drowning.
8
+ */
9
+ export async function runShellEscape(command, cwd, emit) {
10
+ emit(`! ${command}`);
11
+ return new Promise((resolve) => {
12
+ const child = spawn(command, { shell: true, cwd, env: process.env });
13
+ let buffer = "";
14
+ const MAX = 32 * 1024;
15
+ const onChunk = (chunk) => {
16
+ if (buffer.length >= MAX)
17
+ return;
18
+ buffer += chunk.toString("utf8").slice(0, MAX - buffer.length);
19
+ };
20
+ child.stdout?.on("data", onChunk);
21
+ child.stderr?.on("data", onChunk);
22
+ child.on("close", (code) => {
23
+ const trimmed = buffer.trim();
24
+ if (trimmed.length === 0) {
25
+ emit(code === 0 ? "(no output)" : `(exit ${code})`);
26
+ }
27
+ else {
28
+ const lines = trimmed.split("\n").slice(0, 60);
29
+ for (const line of lines)
30
+ emit(line);
31
+ if (code !== 0)
32
+ emit(`(exit ${code})`);
33
+ }
34
+ resolve();
35
+ });
36
+ child.on("error", (err) => {
37
+ emit(`! ${err.message}`);
38
+ resolve();
39
+ });
40
+ });
41
+ }
42
+ //# sourceMappingURL=shell-escape.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shell-escape.js","sourceRoot":"","sources":["../../src/ui/shell-escape.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAE3C;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,OAAe,EAAE,GAAW,EAAE,IAA4B;IAC9F,IAAI,CAAC,KAAK,OAAO,EAAE,CAAC,CAAC;IACrB,OAAO,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,EAAE;QACpC,MAAM,KAAK,GAAG,KAAK,CAAC,OAAO,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,GAAG,EAAE,GAAG,EAAE,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC;QACrE,IAAI,MAAM,GAAG,EAAE,CAAC;QAChB,MAAM,GAAG,GAAG,EAAE,GAAG,IAAI,CAAC;QACtB,MAAM,OAAO,GAAG,CAAC,KAAa,EAAE,EAAE;YACjC,IAAI,MAAM,CAAC,MAAM,IAAI,GAAG;gBAAE,OAAO;YACjC,MAAM,IAAI,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC;QAChE,CAAC,CAAC;QACF,KAAK,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QAClC,KAAK,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QAClC,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,IAAI,EAAE,EAAE;YAC1B,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,EAAE,CAAC;YAC9B,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBAC1B,IAAI,CAAC,IAAI,KAAK,CAAC,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,SAAS,IAAI,GAAG,CAAC,CAAC;YACrD,CAAC;iBAAM,CAAC;gBACP,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;gBAC/C,KAAK,MAAM,IAAI,IAAI,KAAK;oBAAE,IAAI,CAAC,IAAI,CAAC,CAAC;gBACrC,IAAI,IAAI,KAAK,CAAC;oBAAE,IAAI,CAAC,SAAS,IAAI,GAAG,CAAC,CAAC;YACxC,CAAC;YACD,OAAO,EAAE,CAAC;QACX,CAAC,CAAC,CAAC;QACH,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,GAAG,EAAE,EAAE;YACzB,IAAI,CAAC,KAAK,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC;YACzB,OAAO,EAAE,CAAC;QACX,CAAC,CAAC,CAAC;IACJ,CAAC,CAAC,CAAC;AACJ,CAAC"}
@@ -0,0 +1,83 @@
1
+ /**
2
+ * Restore the terminal to a sane state on exit, including the unhappy
3
+ * paths Ink doesn't catch — uncaught exceptions, SIGINT, SIGTERM, and
4
+ * any unmount that happens with raw mode still engaged.
5
+ *
6
+ * Without this, a thrown error inside the React tree (or a kill -9 to
7
+ * a parent shell) leaves the terminal in raw mode with the cursor
8
+ * hidden and ANSI attributes still set, and the user has to type
9
+ * `stty sane` blind to recover. Production-grade TUIs always install
10
+ * these handlers; this is table-stakes hygiene.
11
+ */
12
+ const RESET_SEQUENCE =
13
+ // Show cursor.
14
+ "\x1b[?25h" +
15
+ // Reset all SGR attributes (color, bold, italic, etc.).
16
+ "\x1b[0m" +
17
+ // Disable bracketed paste mode if we ever enabled it.
18
+ "\x1b[?2004l";
19
+ let installed = false;
20
+ export function installTerminalRestoreHandlers(instance) {
21
+ if (installed)
22
+ return;
23
+ installed = true;
24
+ let restored = false;
25
+ const restore = () => {
26
+ if (restored)
27
+ return;
28
+ restored = true;
29
+ try {
30
+ instance?.unmount();
31
+ }
32
+ catch {
33
+ // unmount can throw if Ink is already torn down; ignore.
34
+ }
35
+ try {
36
+ // Belt and suspenders: write the reset directly to the TTY in
37
+ // case Ink's unmount didn't (e.g. because we got here via
38
+ // uncaughtException before Ink even mounted).
39
+ if (process.stdout.isTTY)
40
+ process.stdout.write(RESET_SEQUENCE);
41
+ }
42
+ catch {
43
+ // Best-effort; the process is going down regardless.
44
+ }
45
+ try {
46
+ // If raw mode is somehow still on (Ink should disable it on
47
+ // unmount, but uncaught exceptions can skip that path), turn
48
+ // it off so the user gets a usable shell back.
49
+ if (process.stdin.isTTY && process.stdin.setRawMode) {
50
+ process.stdin.setRawMode(false);
51
+ }
52
+ }
53
+ catch {
54
+ // Ignore — stdin may already be detached.
55
+ }
56
+ };
57
+ process.once("exit", restore);
58
+ process.once("SIGINT", () => {
59
+ restore();
60
+ // Mirror the default SIGINT exit code so parent shells see it.
61
+ process.exit(130);
62
+ });
63
+ process.once("SIGTERM", () => {
64
+ restore();
65
+ process.exit(143);
66
+ });
67
+ process.once("SIGHUP", () => {
68
+ restore();
69
+ process.exit(129);
70
+ });
71
+ process.on("uncaughtException", (err) => {
72
+ restore();
73
+ process.stderr.write(`\nuncaught exception: ${err instanceof Error ? (err.stack ?? err.message) : String(err)}\n`);
74
+ process.exit(1);
75
+ });
76
+ process.on("unhandledRejection", (reason) => {
77
+ restore();
78
+ const msg = reason instanceof Error ? (reason.stack ?? reason.message) : String(reason);
79
+ process.stderr.write(`\nunhandled rejection: ${msg}\n`);
80
+ process.exit(1);
81
+ });
82
+ }
83
+ //# sourceMappingURL=terminal-restore.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"terminal-restore.js","sourceRoot":"","sources":["../../src/ui/terminal-restore.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;GAUG;AAEH,MAAM,cAAc;AACnB,eAAe;AACf,WAAW;IACX,wDAAwD;IACxD,SAAS;IACT,sDAAsD;IACtD,aAAa,CAAC;AAEf,IAAI,SAAS,GAAG,KAAK,CAAC;AAEtB,MAAM,UAAU,8BAA8B,CAAC,QAAmB;IACjE,IAAI,SAAS;QAAE,OAAO;IACtB,SAAS,GAAG,IAAI,CAAC;IAEjB,IAAI,QAAQ,GAAG,KAAK,CAAC;IACrB,MAAM,OAAO,GAAG,GAAS,EAAE;QAC1B,IAAI,QAAQ;YAAE,OAAO;QACrB,QAAQ,GAAG,IAAI,CAAC;QAChB,IAAI,CAAC;YACJ,QAAQ,EAAE,OAAO,EAAE,CAAC;QACrB,CAAC;QAAC,MAAM,CAAC;YACR,yDAAyD;QAC1D,CAAC;QACD,IAAI,CAAC;YACJ,8DAA8D;YAC9D,0DAA0D;YAC1D,8CAA8C;YAC9C,IAAI,OAAO,CAAC,MAAM,CAAC,KAAK;gBAAE,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC;QAChE,CAAC;QAAC,MAAM,CAAC;YACR,qDAAqD;QACtD,CAAC;QACD,IAAI,CAAC;YACJ,4DAA4D;YAC5D,6DAA6D;YAC7D,+CAA+C;YAC/C,IAAI,OAAO,CAAC,KAAK,CAAC,KAAK,IAAI,OAAO,CAAC,KAAK,CAAC,UAAU,EAAE,CAAC;gBACrD,OAAO,CAAC,KAAK,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC;YACjC,CAAC;QACF,CAAC;QAAC,MAAM,CAAC;YACR,0CAA0C;QAC3C,CAAC;IACF,CAAC,CAAC;IAEF,OAAO,CAAC,IAAI,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC9B,OAAO,CAAC,IAAI,CAAC,QAAQ,EAAE,GAAG,EAAE;QAC3B,OAAO,EAAE,CAAC;QACV,+DAA+D;QAC/D,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACnB,CAAC,CAAC,CAAC;IACH,OAAO,CAAC,IAAI,CAAC,SAAS,EAAE,GAAG,EAAE;QAC5B,OAAO,EAAE,CAAC;QACV,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACnB,CAAC,CAAC,CAAC;IACH,OAAO,CAAC,IAAI,CAAC,QAAQ,EAAE,GAAG,EAAE;QAC3B,OAAO,EAAE,CAAC;QACV,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACnB,CAAC,CAAC,CAAC;IACH,OAAO,CAAC,EAAE,CAAC,mBAAmB,EAAE,CAAC,GAAG,EAAE,EAAE;QACvC,OAAO,EAAE,CAAC;QACV,OAAO,CAAC,MAAM,CAAC,KAAK,CACnB,yBAAyB,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,IAAI,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CAC5F,CAAC;QACF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACjB,CAAC,CAAC,CAAC;IACH,OAAO,CAAC,EAAE,CAAC,oBAAoB,EAAE,CAAC,MAAM,EAAE,EAAE;QAC3C,OAAO,EAAE,CAAC;QACV,MAAM,GAAG,GAAG,MAAM,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,IAAI,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;QACxF,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,0BAA0B,GAAG,IAAI,CAAC,CAAC;QACxD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACjB,CAAC,CAAC,CAAC;AACJ,CAAC"}
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Set the terminal window/tab title via OSC 0. Honored by all modern
3
+ * terminals (xterm, iTerm2, Ghostty, kitty) plus the integrated
4
+ * terminals in VS Code, Cursor, JetBrains IDEs — so "node" tabs become
5
+ * "codebase". TMUX/screen forward this through to the host emulator.
6
+ *
7
+ * No-op on non-TTY stdouts (piped output, CI logs) so we don't pollute
8
+ * captured output with stray escape bytes.
9
+ *
10
+ * We intentionally don't try to "restore" the prior title on exit:
11
+ * there's no portable way to read the current title, and on shell exit
12
+ * the parent shell's PROMPT_COMMAND / precmd hook will set it back
13
+ * within milliseconds. Setting it to empty would be worse than leaving
14
+ * our title in place during the brief gap.
15
+ */
16
+ export function setTerminalTitle(title) {
17
+ if (!process.stdout.isTTY)
18
+ return;
19
+ process.stdout.write(`\x1b]0;${title}\x07`);
20
+ }
21
+ //# sourceMappingURL=terminal-title.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"terminal-title.js","sourceRoot":"","sources":["../../src/ui/terminal-title.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AACH,MAAM,UAAU,gBAAgB,CAAC,KAAa;IAC7C,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK;QAAE,OAAO;IAClC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,UAAU,KAAK,MAAM,CAAC,CAAC;AAC7C,CAAC"}
@@ -0,0 +1,83 @@
1
+ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { Box, Text } from "ink";
3
+ import { useEffect, useState } from "react";
4
+ import { DiffSummary, diffSummary } from "./diff-summary.js";
5
+ import { displayPath } from "./paths.js";
6
+ import { nounForReadTool, pastVerbForReadTool, presentVerbForReadTool, toolActionLabel, toolActionPast, truncate, } from "./tool-labels.js";
7
+ import { WrappedLines } from "./wrapped-lines.js";
8
+ const SPINNER_FRAMES = ["⣾", "⣽", "⣻", "⢿", "⡿", "⣟", "⣯", "⣷"];
9
+ export function useSpinner(active, intervalMs = 90) {
10
+ const [frame, setFrame] = useState(0);
11
+ useEffect(() => {
12
+ if (!active)
13
+ return;
14
+ const id = setInterval(() => setFrame((f) => (f + 1) % SPINNER_FRAMES.length), intervalMs);
15
+ return () => clearInterval(id);
16
+ }, [active, intervalMs]);
17
+ return SPINNER_FRAMES[frame];
18
+ }
19
+ /**
20
+ * Tool calls that are pure reads — runs of these collapse into a single
21
+ * "Read N files" / "Searched 3 patterns" line. Keep the set tight:
22
+ * anything that mutates state, runs shell, or has a meaningful argument
23
+ * shape (grep query, fetch URL) reads weird when collapsed and stays
24
+ * per-row.
25
+ */
26
+ export const COLLAPSIBLE_READ_TOOLS = new Set(["read_file"]);
27
+ /**
28
+ * One tool-call row that morphs through three states:
29
+ * running → spinner + present tense ("⣾ Reading src/index.ts")
30
+ * done → ✓ + past tense ("✓ Read src/index.ts")
31
+ * error → ✗ + past tense + red ("✗ Read src/index.ts")
32
+ *
33
+ * State source: the per-session `tools` Map on ChatState. If no entry
34
+ * exists for this id (e.g. an old session being replayed without
35
+ * inflight tracking), we render the past-tense "done" form — safe
36
+ * fallback that never strands the UI on a fake spinner.
37
+ */
38
+ export function ToolCallLine({ id, name, args, width, keyPrefix, tools, }) {
39
+ const exec = tools?.get(id);
40
+ const status = exec?.status ?? "done";
41
+ const isRunning = status === "running";
42
+ const spinner = useSpinner(isRunning);
43
+ if (isRunning) {
44
+ return (_jsx(WrappedLines, { text: `${spinner} ${toolActionLabel(name, args)}…`, width: width, keyPrefix: keyPrefix, color: "magenta" }));
45
+ }
46
+ const isError = status === "error";
47
+ const glyph = isError ? "✗" : "✓";
48
+ const past = toolActionPast(name, args);
49
+ const diff = !isError ? diffSummary(name, args) : null;
50
+ return (_jsxs(_Fragment, { children: [_jsx(WrappedLines, { text: `${glyph} ${past}`, width: width, keyPrefix: keyPrefix, color: isError ? "red" : "magenta" }), diff ? _jsx(DiffSummary, { diff: diff, width: width, keyPrefix: `${keyPrefix}-diff` }) : null] }));
51
+ }
52
+ /**
53
+ * Collapsed row for a run of pure-read tool calls. Renders as
54
+ * "✓ Read N files" with the per-file paths in a dim indented list
55
+ * beneath. If any call errored, the glyph flips to ✗ and the line
56
+ * goes red — we still show the paths so the user can see what
57
+ * failed.
58
+ */
59
+ export function CollapsedReadGroup({ calls, width, keyPrefix, tools, }) {
60
+ const statuses = calls.map((c) => tools?.get(c.id)?.status);
61
+ const anyRunning = statuses.some((s) => s === "running");
62
+ const anyError = statuses.some((s) => s === "error");
63
+ const doneCount = statuses.filter((s) => s !== "running").length;
64
+ const spinner = useSpinner(anyRunning);
65
+ const glyph = anyRunning ? spinner : anyError ? "✗" : "✓";
66
+ const color = anyError ? "red" : "magenta";
67
+ const verb = anyRunning ? presentVerbForReadTool(calls[0].name) : pastVerbForReadTool(calls[0].name);
68
+ const noun = nounForReadTool(calls[0].name, calls.length);
69
+ const header = anyRunning
70
+ ? `${glyph} ${verb} ${doneCount} of ${calls.length} ${noun}…`
71
+ : `${glyph} ${verb} ${calls.length} ${noun}`;
72
+ return (_jsxs(_Fragment, { children: [_jsx(WrappedLines, { text: header, width: width, keyPrefix: keyPrefix, color: color }), _jsx(Box, { flexDirection: "column", marginLeft: 2, children: calls.map((c) => {
73
+ const a = (c.arguments ?? {});
74
+ const rawPath = typeof a.path === "string" ? a.path : typeof a.file_path === "string" ? a.file_path : "";
75
+ const path = displayPath(rawPath);
76
+ const status = tools?.get(c.id)?.status;
77
+ const failed = status === "error";
78
+ const running = status === "running";
79
+ const marker = failed ? " ✗ " : running ? " → " : " · ";
80
+ return (_jsxs(Text, { color: failed ? "red" : running ? "magenta" : undefined, dimColor: !failed && !running, children: [marker, truncate(path, Math.max(20, width - 6))] }, `${keyPrefix}-f-${c.id}`));
81
+ }) })] }));
82
+ }
83
+ //# sourceMappingURL=tool-call-line.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tool-call-line.js","sourceRoot":"","sources":["../../src/ui/tool-call-line.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,194 @@
1
+ import { displayPath } from "./paths.js";
2
+ /**
3
+ * Render a tool call as a human-friendly action label: present-tense
4
+ * verb + the salient argument (file path, command, URL, search query,
5
+ * etc.) instead of the raw `toolName(k1=v1, k2=v2)` shape. Falls back
6
+ * to the verbose form for tools we don't have a special case for.
7
+ */
8
+ export function toolActionLabel(name, args) {
9
+ const a = (args ?? {});
10
+ const str = (k) => (typeof a[k] === "string" ? a[k] : "");
11
+ const path = displayPath(str("path") || str("file_path"));
12
+ switch (name) {
13
+ case "read_file":
14
+ return `Reading ${path}`;
15
+ case "write_file":
16
+ return `Writing ${path}`;
17
+ case "edit_file":
18
+ return `Editing ${path}`;
19
+ case "multi_edit":
20
+ return `Editing ${path}`;
21
+ case "notebook_edit":
22
+ return `Editing notebook ${path}`;
23
+ case "list_files":
24
+ return `Listing ${path || "."}`;
25
+ case "glob":
26
+ return `Searching ${str("pattern")}`;
27
+ case "grep":
28
+ return `Searching for "${str("pattern")}"`;
29
+ case "shell":
30
+ return `Running: ${truncate(str("command") || str("cmd"), 60)}`;
31
+ case "web_fetch":
32
+ return `Fetching ${str("url")}`;
33
+ case "web_search":
34
+ return `Searching: ${truncate(str("query"), 60)}`;
35
+ case "git_status":
36
+ return "git status";
37
+ case "git_diff":
38
+ return `git diff${str("target") ? ` ${str("target")}` : ""}`;
39
+ case "git_log":
40
+ return "git log";
41
+ case "git_commit":
42
+ return `git commit: ${truncate(str("message"), 50)}`;
43
+ case "git_branch":
44
+ return str("name") ? `git branch ${str("name")}` : "git branches";
45
+ case "enter_worktree":
46
+ return `Entering worktree ${str("branch") || str("name")}`;
47
+ case "exit_worktree":
48
+ return "Leaving worktree";
49
+ case "enter_plan_mode":
50
+ return "Entering plan mode";
51
+ case "exit_plan_mode":
52
+ return "Exiting plan mode";
53
+ case "dispatch_agent":
54
+ return `Dispatching subagent: ${truncate(str("task"), 60)}`;
55
+ case "ask_user":
56
+ return `Asking: ${truncate(str("question"), 60)}`;
57
+ case "create_task":
58
+ return `Task: ${truncate(str("subject"), 60)}`;
59
+ case "update_task":
60
+ return `Updating task ${str("taskId")}`;
61
+ case "list_tasks":
62
+ return "Listing tasks";
63
+ case "get_task":
64
+ return `Reading task ${str("taskId")}`;
65
+ case "save_memory":
66
+ return `Saving memory: ${str("name") || str("type")}`;
67
+ case "read_memory":
68
+ return str("filename") ? `Reading memory ${str("filename")}` : "Reading MEMORY.md";
69
+ case "config":
70
+ return str("path") ? `config(${str("path")})` : "Reading config";
71
+ default:
72
+ return `${name}(${summarizeArgs(args)})`;
73
+ }
74
+ }
75
+ /**
76
+ * Past-tense action label, used when a tool has finished. Same shape
77
+ * as `toolActionLabel` but with the verbs swapped to past tense.
78
+ */
79
+ export function toolActionPast(name, args) {
80
+ const a = (args ?? {});
81
+ const str = (k) => (typeof a[k] === "string" ? a[k] : "");
82
+ const path = displayPath(str("path") || str("file_path"));
83
+ switch (name) {
84
+ case "read_file":
85
+ return `Read ${path}`;
86
+ case "write_file":
87
+ return `Wrote ${path}`;
88
+ case "edit_file":
89
+ return `Edited ${path}`;
90
+ case "multi_edit":
91
+ return `Edited ${path}`;
92
+ case "notebook_edit":
93
+ return `Edited notebook ${path}`;
94
+ case "list_files":
95
+ return `Listed ${path || "."}`;
96
+ case "glob":
97
+ return `Searched ${str("pattern")}`;
98
+ case "grep":
99
+ return `Searched for "${str("pattern")}"`;
100
+ case "shell":
101
+ return `Ran: ${truncate(str("command") || str("cmd"), 60)}`;
102
+ case "web_fetch":
103
+ return `Fetched ${str("url")}`;
104
+ case "web_search":
105
+ return `Searched: ${truncate(str("query"), 60)}`;
106
+ case "git_status":
107
+ return "git status";
108
+ case "git_diff":
109
+ return `git diff${str("target") ? ` ${str("target")}` : ""}`;
110
+ case "git_log":
111
+ return "git log";
112
+ case "git_commit":
113
+ return `git commit: ${truncate(str("message"), 50)}`;
114
+ case "git_branch":
115
+ return str("name") ? `git branch ${str("name")}` : "git branches";
116
+ case "enter_worktree":
117
+ return `Entered worktree ${str("branch") || str("name")}`;
118
+ case "exit_worktree":
119
+ return "Left worktree";
120
+ case "enter_plan_mode":
121
+ return "Entered plan mode";
122
+ case "exit_plan_mode":
123
+ return "Exited plan mode";
124
+ case "dispatch_agent":
125
+ return `Subagent: ${truncate(str("task"), 60)}`;
126
+ case "ask_user":
127
+ return `Asked: ${truncate(str("question"), 60)}`;
128
+ case "create_task":
129
+ return `Created task: ${truncate(str("subject"), 60)}`;
130
+ case "update_task":
131
+ return `Updated task ${str("taskId")}`;
132
+ case "list_tasks":
133
+ return "Listed tasks";
134
+ case "get_task":
135
+ return `Read task ${str("taskId")}`;
136
+ case "save_memory":
137
+ return `Saved memory: ${str("name") || str("type")}`;
138
+ case "read_memory":
139
+ return str("filename") ? `Read memory ${str("filename")}` : "Read MEMORY.md";
140
+ case "config":
141
+ return str("path") ? `config(${str("path")})` : "Read config";
142
+ default:
143
+ return `${name}(${summarizeArgs(args)})`;
144
+ }
145
+ }
146
+ /** Verb used when describing a *running* read-style tool in collapse rows. */
147
+ export function presentVerbForReadTool(name) {
148
+ if (name === "read_file")
149
+ return "Reading";
150
+ if (name === "list_files")
151
+ return "Listing";
152
+ if (name === "glob")
153
+ return "Searching";
154
+ if (name === "grep")
155
+ return "Grepping";
156
+ return "Running";
157
+ }
158
+ /** Verb used when describing a *finished* read-style tool in collapse rows. */
159
+ export function pastVerbForReadTool(name) {
160
+ if (name === "read_file")
161
+ return "Read";
162
+ if (name === "list_files")
163
+ return "Listed";
164
+ if (name === "glob")
165
+ return "Searched";
166
+ if (name === "grep")
167
+ return "Grepped";
168
+ return "Ran";
169
+ }
170
+ /** Plural noun used to describe N items of a given read tool. */
171
+ export function nounForReadTool(name, count) {
172
+ if (name === "read_file")
173
+ return count === 1 ? "file" : "files";
174
+ if (name === "list_files")
175
+ return count === 1 ? "directory" : "directories";
176
+ return count === 1 ? "call" : "calls";
177
+ }
178
+ export function truncate(s, n) {
179
+ if (s.length <= n)
180
+ return s;
181
+ return `${s.slice(0, n - 1)}…`;
182
+ }
183
+ function summarizeArgs(args) {
184
+ if (!args || typeof args !== "object")
185
+ return "";
186
+ const entries = Object.entries(args).slice(0, 3);
187
+ return entries
188
+ .map(([k, v]) => {
189
+ const s = typeof v === "string" ? `"${v.slice(0, 30)}"` : String(v);
190
+ return `${k}=${s}`;
191
+ })
192
+ .join(", ");
193
+ }
194
+ //# sourceMappingURL=tool-labels.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tool-labels.js","sourceRoot":"","sources":["../../src/ui/tool-labels.ts"],"names":[],"mappings":"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"}