codebase-cli 2.0.0-pre.2 → 2.0.0-pre.20

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 (63) hide show
  1. package/dist/agent/agent.js +2 -0
  2. package/dist/agent/agent.js.map +1 -1
  3. package/dist/agent/config.js +76 -9
  4. package/dist/agent/config.js.map +1 -1
  5. package/dist/app-server/protocol.js +7 -0
  6. package/dist/app-server/protocol.js.map +1 -0
  7. package/dist/app-server/server.js +241 -0
  8. package/dist/app-server/server.js.map +1 -0
  9. package/dist/auth/flow.js +174 -41
  10. package/dist/auth/flow.js.map +1 -1
  11. package/dist/cli.js +47 -6
  12. package/dist/cli.js.map +1 -1
  13. package/dist/commands/builtins.js +88 -5
  14. package/dist/commands/builtins.js.map +1 -1
  15. package/dist/commands/registry.js +46 -1
  16. package/dist/commands/registry.js.map +1 -1
  17. package/dist/headless/run.js +1 -1
  18. package/dist/headless/run.js.map +1 -1
  19. package/dist/permissions/store.js +4 -0
  20. package/dist/permissions/store.js.map +1 -1
  21. package/dist/projects/cli.js +92 -0
  22. package/dist/projects/cli.js.map +1 -0
  23. package/dist/projects/client.js +120 -0
  24. package/dist/projects/client.js.map +1 -0
  25. package/dist/projects/types.js +2 -0
  26. package/dist/projects/types.js.map +1 -0
  27. package/dist/skills/platform-loader.js +133 -38
  28. package/dist/skills/platform-loader.js.map +1 -1
  29. package/dist/ui/App.js +122 -12
  30. package/dist/ui/App.js.map +1 -1
  31. package/dist/ui/FirstRunSetup.js +90 -15
  32. package/dist/ui/FirstRunSetup.js.map +1 -1
  33. package/dist/ui/Input.js +245 -13
  34. package/dist/ui/Input.js.map +1 -1
  35. package/dist/ui/Markdown.js +286 -0
  36. package/dist/ui/Markdown.js.map +1 -0
  37. package/dist/ui/Message.js +449 -25
  38. package/dist/ui/Message.js.map +1 -1
  39. package/dist/ui/MessageList.js +7 -2
  40. package/dist/ui/MessageList.js.map +1 -1
  41. package/dist/ui/Permission.js +43 -20
  42. package/dist/ui/Permission.js.map +1 -1
  43. package/dist/ui/PixelC.js +25 -0
  44. package/dist/ui/PixelC.js.map +1 -0
  45. package/dist/ui/Status.js +213 -7
  46. package/dist/ui/Status.js.map +1 -1
  47. package/dist/ui/Throbber.js +11 -7
  48. package/dist/ui/Throbber.js.map +1 -1
  49. package/dist/ui/Welcome.js +59 -0
  50. package/dist/ui/Welcome.js.map +1 -0
  51. package/dist/ui/attachments.js +68 -0
  52. package/dist/ui/attachments.js.map +1 -0
  53. package/dist/ui/debug-input.js +44 -0
  54. package/dist/ui/debug-input.js.map +1 -0
  55. package/dist/ui/highlight.js +324 -0
  56. package/dist/ui/highlight.js.map +1 -0
  57. package/dist/ui/history-store.js +60 -0
  58. package/dist/ui/history-store.js.map +1 -0
  59. package/dist/ui/path-complete.js +102 -0
  60. package/dist/ui/path-complete.js.map +1 -0
  61. package/dist/ui/terminal-restore.js +83 -0
  62. package/dist/ui/terminal-restore.js.map +1 -0
  63. package/package.json +3 -1
@@ -0,0 +1,324 @@
1
+ /**
2
+ * Tiny regex-based syntax highlighter for code blocks inside markdown.
3
+ * Each language is a flat list of `(regex, kind)` rules tried in order;
4
+ * the first match wins, the matched span is emitted as a typed token,
5
+ * and the scan resumes after it. Anything not matched falls through as
6
+ * plain text.
7
+ *
8
+ * We deliberately do *not* take a 6 MB dep (highlight.js, prismjs) just
9
+ * to colorize terminal code blocks — these rules handle 95% of what an
10
+ * LLM emits and stay easy to read. If a language isn't in `LANGS`, the
11
+ * caller renders the code block as plain text.
12
+ */
13
+ const TS_KEYWORDS = [
14
+ "abstract",
15
+ "as",
16
+ "async",
17
+ "await",
18
+ "break",
19
+ "case",
20
+ "catch",
21
+ "class",
22
+ "const",
23
+ "continue",
24
+ "debugger",
25
+ "declare",
26
+ "default",
27
+ "delete",
28
+ "do",
29
+ "else",
30
+ "enum",
31
+ "export",
32
+ "extends",
33
+ "finally",
34
+ "for",
35
+ "from",
36
+ "function",
37
+ "get",
38
+ "if",
39
+ "implements",
40
+ "import",
41
+ "in",
42
+ "infer",
43
+ "instanceof",
44
+ "interface",
45
+ "is",
46
+ "keyof",
47
+ "let",
48
+ "namespace",
49
+ "new",
50
+ "null",
51
+ "of",
52
+ "package",
53
+ "private",
54
+ "protected",
55
+ "public",
56
+ "readonly",
57
+ "return",
58
+ "set",
59
+ "static",
60
+ "super",
61
+ "switch",
62
+ "this",
63
+ "throw",
64
+ "true",
65
+ "false",
66
+ "try",
67
+ "type",
68
+ "typeof",
69
+ "undefined",
70
+ "var",
71
+ "void",
72
+ "while",
73
+ "with",
74
+ "yield",
75
+ ];
76
+ const PY_KEYWORDS = [
77
+ "and",
78
+ "as",
79
+ "assert",
80
+ "async",
81
+ "await",
82
+ "break",
83
+ "class",
84
+ "continue",
85
+ "def",
86
+ "del",
87
+ "elif",
88
+ "else",
89
+ "except",
90
+ "False",
91
+ "finally",
92
+ "for",
93
+ "from",
94
+ "global",
95
+ "if",
96
+ "import",
97
+ "in",
98
+ "is",
99
+ "lambda",
100
+ "None",
101
+ "nonlocal",
102
+ "not",
103
+ "or",
104
+ "pass",
105
+ "raise",
106
+ "return",
107
+ "True",
108
+ "try",
109
+ "while",
110
+ "with",
111
+ "yield",
112
+ ];
113
+ const GO_KEYWORDS = [
114
+ "break",
115
+ "case",
116
+ "chan",
117
+ "const",
118
+ "continue",
119
+ "default",
120
+ "defer",
121
+ "else",
122
+ "fallthrough",
123
+ "for",
124
+ "func",
125
+ "go",
126
+ "goto",
127
+ "if",
128
+ "import",
129
+ "interface",
130
+ "map",
131
+ "package",
132
+ "range",
133
+ "return",
134
+ "select",
135
+ "struct",
136
+ "switch",
137
+ "type",
138
+ "var",
139
+ "nil",
140
+ "true",
141
+ "false",
142
+ ];
143
+ const SH_KEYWORDS = [
144
+ "if",
145
+ "then",
146
+ "else",
147
+ "elif",
148
+ "fi",
149
+ "for",
150
+ "in",
151
+ "do",
152
+ "done",
153
+ "while",
154
+ "until",
155
+ "case",
156
+ "esac",
157
+ "function",
158
+ "return",
159
+ "exit",
160
+ "break",
161
+ "continue",
162
+ "local",
163
+ "export",
164
+ "readonly",
165
+ "declare",
166
+ "set",
167
+ "unset",
168
+ "shift",
169
+ ];
170
+ const TS_RULES = [
171
+ { pattern: /^\/\/[^\n]*/, kind: "comment" },
172
+ { pattern: /^\/\*[\s\S]*?\*\//, kind: "comment" },
173
+ { pattern: /^`(?:[^`\\]|\\.)*`/, kind: "string" },
174
+ { pattern: /^"(?:[^"\\\n]|\\.)*"/, kind: "string" },
175
+ { pattern: /^'(?:[^'\\\n]|\\.)*'/, kind: "string" },
176
+ { pattern: /^\b(?:0x[0-9a-fA-F]+|0b[01]+|\d+\.?\d*(?:[eE][+-]?\d+)?)\b/, kind: "number" },
177
+ { pattern: new RegExp(`^\\b(?:${TS_KEYWORDS.join("|")})\\b`), kind: "keyword" },
178
+ { pattern: /^\b[A-Z][A-Za-z0-9_]*\b/, kind: "type" },
179
+ { pattern: /^[A-Za-z_$][\w$]*(?=\s*\()/, kind: "function" },
180
+ { pattern: /^[A-Za-z_$][\w$]*(?=\s*:)/, kind: "property" },
181
+ { pattern: /^[+\-*/%=<>!&|^~?:]+/, kind: "operator" },
182
+ { pattern: /^[{}[\]().,;]/, kind: "punctuation" },
183
+ ];
184
+ const PY_RULES = [
185
+ { pattern: /^#[^\n]*/, kind: "comment" },
186
+ { pattern: /^"""[\s\S]*?"""/, kind: "string" },
187
+ { pattern: /^'''[\s\S]*?'''/, kind: "string" },
188
+ { pattern: /^"(?:[^"\\\n]|\\.)*"/, kind: "string" },
189
+ { pattern: /^'(?:[^'\\\n]|\\.)*'/, kind: "string" },
190
+ { pattern: /^\b\d+\.?\d*(?:[eE][+-]?\d+)?\b/, kind: "number" },
191
+ { pattern: new RegExp(`^\\b(?:${PY_KEYWORDS.join("|")})\\b`), kind: "keyword" },
192
+ { pattern: /^\b[A-Z][A-Za-z0-9_]*\b/, kind: "type" },
193
+ { pattern: /^[A-Za-z_][\w]*(?=\s*\()/, kind: "function" },
194
+ { pattern: /^[+\-*/%=<>!&|^~]+/, kind: "operator" },
195
+ { pattern: /^[{}[\]().,:;]/, kind: "punctuation" },
196
+ ];
197
+ const GO_RULES = [
198
+ { pattern: /^\/\/[^\n]*/, kind: "comment" },
199
+ { pattern: /^\/\*[\s\S]*?\*\//, kind: "comment" },
200
+ { pattern: /^`[\s\S]*?`/, kind: "string" },
201
+ { pattern: /^"(?:[^"\\\n]|\\.)*"/, kind: "string" },
202
+ { pattern: /^'(?:[^'\\]|\\.)*'/, kind: "string" },
203
+ { pattern: /^\b\d+\.?\d*\b/, kind: "number" },
204
+ { pattern: new RegExp(`^\\b(?:${GO_KEYWORDS.join("|")})\\b`), kind: "keyword" },
205
+ { pattern: /^\b[A-Z][A-Za-z0-9_]*\b/, kind: "type" },
206
+ { pattern: /^[A-Za-z_][\w]*(?=\s*\()/, kind: "function" },
207
+ { pattern: /^[+\-*/%=<>!&|^~]+/, kind: "operator" },
208
+ { pattern: /^[{}[\]().,;:]/, kind: "punctuation" },
209
+ ];
210
+ const SH_RULES = [
211
+ { pattern: /^#[^\n]*/, kind: "comment" },
212
+ { pattern: /^"(?:[^"\\\n]|\\.)*"/, kind: "string" },
213
+ { pattern: /^'[^'\n]*'/, kind: "string" },
214
+ { pattern: /^\$[A-Za-z_][\w]*/, kind: "property" },
215
+ { pattern: /^\$\{[^}]*\}/, kind: "property" },
216
+ { pattern: /^\b\d+\b/, kind: "number" },
217
+ { pattern: new RegExp(`^\\b(?:${SH_KEYWORDS.join("|")})\\b`), kind: "keyword" },
218
+ { pattern: /^-{1,2}[A-Za-z][\w-]*/, kind: "operator" },
219
+ { pattern: /^[|&;<>(){}]+/, kind: "punctuation" },
220
+ ];
221
+ const JSON_RULES = [
222
+ { pattern: /^"(?:[^"\\\n]|\\.)*"(?=\s*:)/, kind: "property" },
223
+ { pattern: /^"(?:[^"\\\n]|\\.)*"/, kind: "string" },
224
+ { pattern: /^\b(?:true|false|null)\b/, kind: "keyword" },
225
+ { pattern: /^-?\b\d+\.?\d*(?:[eE][+-]?\d+)?\b/, kind: "number" },
226
+ { pattern: /^[{}[\],]/, kind: "punctuation" },
227
+ { pattern: /^:/, kind: "operator" },
228
+ ];
229
+ const LANGS = {
230
+ ts: TS_RULES,
231
+ tsx: TS_RULES,
232
+ js: TS_RULES,
233
+ jsx: TS_RULES,
234
+ javascript: TS_RULES,
235
+ typescript: TS_RULES,
236
+ py: PY_RULES,
237
+ python: PY_RULES,
238
+ go: GO_RULES,
239
+ golang: GO_RULES,
240
+ sh: SH_RULES,
241
+ bash: SH_RULES,
242
+ zsh: SH_RULES,
243
+ shell: SH_RULES,
244
+ json: JSON_RULES,
245
+ };
246
+ /** Get the rule set for a language slug, or null if unsupported. */
247
+ export function rulesFor(lang) {
248
+ if (!lang)
249
+ return null;
250
+ return LANGS[lang.toLowerCase()] ?? null;
251
+ }
252
+ /**
253
+ * Tokenize `code` according to `lang`. Returns one big flat token list
254
+ * with whitespace and unmatched content emitted as `text`. The caller
255
+ * is responsible for rendering each token in its kind's color.
256
+ */
257
+ export function highlight(code, lang) {
258
+ const rules = rulesFor(lang);
259
+ if (!rules)
260
+ return [{ kind: "text", text: code }];
261
+ const out = [];
262
+ let buffer = "";
263
+ let i = 0;
264
+ while (i < code.length) {
265
+ // Eat whitespace into the rolling text buffer — saves work and keeps
266
+ // indentation intact in the output.
267
+ const ch = code[i];
268
+ if (ch === " " || ch === "\t" || ch === "\n" || ch === "\r") {
269
+ buffer += ch;
270
+ i++;
271
+ continue;
272
+ }
273
+ const slice = code.slice(i);
274
+ let matched = null;
275
+ for (const rule of rules) {
276
+ const m = slice.match(rule.pattern);
277
+ if (m && m.index === 0) {
278
+ matched = { kind: rule.kind, len: m[0].length };
279
+ break;
280
+ }
281
+ }
282
+ if (matched) {
283
+ if (buffer) {
284
+ out.push({ kind: "text", text: buffer });
285
+ buffer = "";
286
+ }
287
+ out.push({ kind: matched.kind, text: slice.slice(0, matched.len) });
288
+ i += matched.len;
289
+ continue;
290
+ }
291
+ // No match — accumulate one char into the plain-text buffer.
292
+ buffer += ch;
293
+ i++;
294
+ }
295
+ if (buffer)
296
+ out.push({ kind: "text", text: buffer });
297
+ return out;
298
+ }
299
+ /** Map a token kind to an Ink color. Returns undefined for plain text. */
300
+ export function colorForKind(kind) {
301
+ switch (kind) {
302
+ case "keyword":
303
+ return "magenta";
304
+ case "string":
305
+ return "green";
306
+ case "number":
307
+ return "yellow";
308
+ case "comment":
309
+ return "gray";
310
+ case "type":
311
+ return "cyan";
312
+ case "function":
313
+ return "blue";
314
+ case "property":
315
+ return "cyan";
316
+ case "regex":
317
+ return "yellow";
318
+ case "operator":
319
+ case "punctuation":
320
+ case "text":
321
+ return undefined;
322
+ }
323
+ }
324
+ //# sourceMappingURL=highlight.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"highlight.js","sourceRoot":"","sources":["../../src/ui/highlight.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,60 @@
1
+ import { createHash } from "node:crypto";
2
+ import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
3
+ import { homedir } from "node:os";
4
+ import { join } from "node:path";
5
+ const MAX_HISTORY = 200;
6
+ /**
7
+ * Per-cwd prompt history persisted to ~/.codebase/projects/<hash>/history.json.
8
+ * Keeps the most recent MAX_HISTORY entries, oldest first; identical to
9
+ * SessionStore's hashing so we share the project directory layout.
10
+ *
11
+ * Stored as a JSON array of strings. No metadata, no timestamps — the
12
+ * Input component just needs the chronological list for ↑/↓ recall.
13
+ */
14
+ export class HistoryStore {
15
+ path;
16
+ max;
17
+ constructor(options) {
18
+ const dataRoot = options.dataRoot ?? join(homedir(), ".codebase");
19
+ const hash = createHash("sha256").update(options.cwd).digest("hex").slice(0, 8);
20
+ this.path = join(dataRoot, "projects", hash, "history.json");
21
+ this.max = options.max ?? MAX_HISTORY;
22
+ }
23
+ get filePath() {
24
+ return this.path;
25
+ }
26
+ load() {
27
+ if (!existsSync(this.path))
28
+ return [];
29
+ try {
30
+ const raw = readFileSync(this.path, "utf8");
31
+ const parsed = JSON.parse(raw);
32
+ if (!Array.isArray(parsed))
33
+ return [];
34
+ return parsed.filter((s) => typeof s === "string");
35
+ }
36
+ catch {
37
+ return [];
38
+ }
39
+ }
40
+ /** Append `entry`. Collapses adjacent dupes so ↑↑↑ doesn't dwell. */
41
+ append(entry) {
42
+ const trimmed = entry.trim();
43
+ if (!trimmed)
44
+ return;
45
+ const current = this.load();
46
+ if (current[current.length - 1] === trimmed)
47
+ return;
48
+ const next = [...current, trimmed];
49
+ const sliced = next.length > this.max ? next.slice(next.length - this.max) : next;
50
+ const dir = join(this.path, "..");
51
+ try {
52
+ mkdirSync(dir, { recursive: true });
53
+ writeFileSync(this.path, JSON.stringify(sliced), { mode: 0o600 });
54
+ }
55
+ catch {
56
+ // best-effort — losing one history write isn't worth surfacing an error.
57
+ }
58
+ }
59
+ }
60
+ //# sourceMappingURL=history-store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"history-store.js","sourceRoot":"","sources":["../../src/ui/history-store.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAC7E,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,MAAM,WAAW,GAAG,GAAG,CAAC;AAQxB;;;;;;;GAOG;AACH,MAAM,OAAO,YAAY;IACP,IAAI,CAAS;IACb,GAAG,CAAS;IAE7B,YAAY,OAA4B;QACvC,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,IAAI,IAAI,CAAC,OAAO,EAAE,EAAE,WAAW,CAAC,CAAC;QAClE,MAAM,IAAI,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;QAChF,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,QAAQ,EAAE,UAAU,EAAE,IAAI,EAAE,cAAc,CAAC,CAAC;QAC7D,IAAI,CAAC,GAAG,GAAG,OAAO,CAAC,GAAG,IAAI,WAAW,CAAC;IACvC,CAAC;IAED,IAAI,QAAQ;QACX,OAAO,IAAI,CAAC,IAAI,CAAC;IAClB,CAAC;IAED,IAAI;QACH,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC;YAAE,OAAO,EAAE,CAAC;QACtC,IAAI,CAAC;YACJ,MAAM,GAAG,GAAG,YAAY,CAAC,IAAI,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;YAC5C,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;YAC/B,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC;gBAAE,OAAO,EAAE,CAAC;YACtC,OAAO,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAe,EAAE,CAAC,OAAO,CAAC,KAAK,QAAQ,CAAC,CAAC;QACjE,CAAC;QAAC,MAAM,CAAC;YACR,OAAO,EAAE,CAAC;QACX,CAAC;IACF,CAAC;IAED,qEAAqE;IACrE,MAAM,CAAC,KAAa;QACnB,MAAM,OAAO,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC;QAC7B,IAAI,CAAC,OAAO;YAAE,OAAO;QACrB,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;QAC5B,IAAI,OAAO,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,KAAK,OAAO;YAAE,OAAO;QACpD,MAAM,IAAI,GAAG,CAAC,GAAG,OAAO,EAAE,OAAO,CAAC,CAAC;QACnC,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;QAClF,MAAM,GAAG,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;QAClC,IAAI,CAAC;YACJ,SAAS,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;YACpC,aAAa,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;QACnE,CAAC;QAAC,MAAM,CAAC;YACR,yEAAyE;QAC1E,CAAC;IACF,CAAC;CACD"}
@@ -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.2",
3
+ "version": "2.0.0-pre.20",
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,6 +52,8 @@
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
  },