codebase-cli 2.0.0-pre.3 → 2.0.0-pre.31

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 (79) hide show
  1. package/dist/agent/agent.js +31 -12
  2. package/dist/agent/agent.js.map +1 -1
  3. package/dist/agent/config.js +101 -20
  4. package/dist/agent/config.js.map +1 -1
  5. package/dist/agent/prompt-suggestion.js +145 -0
  6. package/dist/agent/prompt-suggestion.js.map +1 -0
  7. package/dist/agent/system-prompt.js +15 -0
  8. package/dist/agent/system-prompt.js.map +1 -1
  9. package/dist/app-server/protocol.js +7 -0
  10. package/dist/app-server/protocol.js.map +1 -0
  11. package/dist/app-server/server.js +241 -0
  12. package/dist/app-server/server.js.map +1 -0
  13. package/dist/auth/credentials.js +10 -0
  14. package/dist/auth/credentials.js.map +1 -1
  15. package/dist/auth/flow.js +145 -24
  16. package/dist/auth/flow.js.map +1 -1
  17. package/dist/cli.js +58 -6
  18. package/dist/cli.js.map +1 -1
  19. package/dist/commands/builtins.js +155 -5
  20. package/dist/commands/builtins.js.map +1 -1
  21. package/dist/commands/registry.js +46 -1
  22. package/dist/commands/registry.js.map +1 -1
  23. package/dist/compaction/monitor.js +38 -0
  24. package/dist/compaction/monitor.js.map +1 -0
  25. package/dist/glue/client.js +10 -1
  26. package/dist/glue/client.js.map +1 -1
  27. package/dist/headless/run.js +1 -1
  28. package/dist/headless/run.js.map +1 -1
  29. package/dist/hooks/manager.js +8 -2
  30. package/dist/hooks/manager.js.map +1 -1
  31. package/dist/permissions/store.js +4 -0
  32. package/dist/permissions/store.js.map +1 -1
  33. package/dist/projects/cli.js +92 -0
  34. package/dist/projects/cli.js.map +1 -0
  35. package/dist/projects/client.js +120 -0
  36. package/dist/projects/client.js.map +1 -0
  37. package/dist/projects/types.js +2 -0
  38. package/dist/projects/types.js.map +1 -0
  39. package/dist/skills/platform-loader.js +133 -38
  40. package/dist/skills/platform-loader.js.map +1 -1
  41. package/dist/tools/__test__/mock-tool-context.js +31 -0
  42. package/dist/tools/__test__/mock-tool-context.js.map +1 -0
  43. package/dist/tools/read-file.js +8 -2
  44. package/dist/tools/read-file.js.map +1 -1
  45. package/dist/ui/App.js +267 -17
  46. package/dist/ui/App.js.map +1 -1
  47. package/dist/ui/FirstRunSetup.js +66 -14
  48. package/dist/ui/FirstRunSetup.js.map +1 -1
  49. package/dist/ui/Input.js +270 -14
  50. package/dist/ui/Input.js.map +1 -1
  51. package/dist/ui/Markdown.js +286 -0
  52. package/dist/ui/Markdown.js.map +1 -0
  53. package/dist/ui/Message.js +604 -25
  54. package/dist/ui/Message.js.map +1 -1
  55. package/dist/ui/MessageList.js +100 -3
  56. package/dist/ui/MessageList.js.map +1 -1
  57. package/dist/ui/Permission.js +43 -20
  58. package/dist/ui/Permission.js.map +1 -1
  59. package/dist/ui/PixelC.js +25 -0
  60. package/dist/ui/PixelC.js.map +1 -0
  61. package/dist/ui/Status.js +213 -7
  62. package/dist/ui/Status.js.map +1 -1
  63. package/dist/ui/Throbber.js +11 -7
  64. package/dist/ui/Throbber.js.map +1 -1
  65. package/dist/ui/Welcome.js +59 -0
  66. package/dist/ui/Welcome.js.map +1 -0
  67. package/dist/ui/attachments.js +68 -0
  68. package/dist/ui/attachments.js.map +1 -0
  69. package/dist/ui/debug-input.js +44 -0
  70. package/dist/ui/debug-input.js.map +1 -0
  71. package/dist/ui/highlight.js +324 -0
  72. package/dist/ui/highlight.js.map +1 -0
  73. package/dist/ui/history-store.js +60 -0
  74. package/dist/ui/history-store.js.map +1 -0
  75. package/dist/ui/path-complete.js +102 -0
  76. package/dist/ui/path-complete.js.map +1 -0
  77. package/dist/ui/terminal-restore.js +83 -0
  78. package/dist/ui/terminal-restore.js.map +1 -0
  79. package/package.json +5 -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,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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "codebase-cli",
3
- "version": "2.0.0-pre.3",
3
+ "version": "2.0.0-pre.31",
4
4
  "description": "Codebase CLI — a TypeScript coding agent on the pi-mono runtime. OAuth-aware, any LLM provider, single install.",
5
5
  "keywords": [
6
6
  "ai",
@@ -52,12 +52,16 @@
52
52
  "test": "vitest --run",
53
53
  "test:watch": "vitest",
54
54
  "check": "npm run typecheck && npm run lint && npm test",
55
+ "bench": "node bench/run.mjs",
56
+ "bench:report": "node bench/aggregate.mjs",
55
57
  "prepublishOnly": "npm run clean && npm run check && npm run build",
56
58
  "prepack": "npm run build"
57
59
  },
58
60
  "dependencies": {
59
61
  "@earendil-works/pi-agent-core": "0.74.0",
60
62
  "@earendil-works/pi-ai": "0.74.0",
63
+ "@types/diff": "^7.0.2",
64
+ "diff": "^9.0.0",
61
65
  "glob": "^13.0.1",
62
66
  "ignore": "^7.0.0",
63
67
  "ink": "^5.2.1",