@golba98/codexa 1.0.3 → 1.0.4

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 (85) hide show
  1. package/README.md +17 -18
  2. package/bin/codexa.js +62 -144
  3. package/package.json +4 -3
  4. package/src/app.tsx +533 -275
  5. package/src/commands/handler.ts +2 -2
  6. package/src/config/buildInfo.ts +2 -2
  7. package/src/config/layeredConfig.ts +1 -1
  8. package/src/config/runtimeConfig.ts +1 -1
  9. package/src/config/settings.ts +1 -1
  10. package/src/config/trustStore.ts +1 -1
  11. package/src/core/README.md +52 -0
  12. package/src/core/agent/loop.ts +282 -0
  13. package/src/core/agent/protocol.ts +211 -0
  14. package/src/core/agent/tools.ts +414 -0
  15. package/src/core/{codexExecArgs.ts → codex/codexExecArgs.ts} +2 -2
  16. package/src/core/{codexLaunch.ts → codex/codexLaunch.ts} +3 -3
  17. package/src/core/{codexPrompt.ts → codex/codexPrompt.ts} +3 -3
  18. package/src/core/debug/modelStateDebug.ts +34 -0
  19. package/src/core/executables/antigravityExecutable.ts +48 -0
  20. package/src/core/executables/executableResolver.ts +5 -1
  21. package/src/core/perf/renderDebug.ts +10 -6
  22. package/src/core/providerLauncher/registry.ts +30 -14
  23. package/src/core/providerLauncher/types.ts +11 -9
  24. package/src/core/providerLauncher/workspaceConfig.ts +41 -26
  25. package/src/core/providerRuntime/anthropic.ts +7 -1
  26. package/src/core/providerRuntime/antigravity.ts +305 -0
  27. package/src/core/providerRuntime/claudeCodeDiscovery.ts +268 -22
  28. package/src/core/providerRuntime/claudeCodeDiscoveryDebug.ts +55 -0
  29. package/src/core/providerRuntime/contextMetadata.ts +12 -24
  30. package/src/core/providerRuntime/local.ts +129 -51
  31. package/src/core/providerRuntime/models.ts +22 -11
  32. package/src/core/providerRuntime/registry.ts +58 -31
  33. package/src/core/providerRuntime/types.ts +19 -14
  34. package/src/core/providers/codexSubprocess.ts +2 -2
  35. package/src/core/providers/types.ts +1 -1
  36. package/src/core/{attachments.ts → shared/attachments.ts} +27 -4
  37. package/src/core/{cleanupFastFail.ts → shared/cleanupFastFail.ts} +1 -1
  38. package/src/core/{hollowResponseFormat.ts → shared/hollowResponseFormat.ts} +1 -1
  39. package/src/core/terminal/clearFrameBoundary.ts +814 -0
  40. package/src/core/terminal/frameLock.ts +109 -0
  41. package/src/core/terminal/inkRenderReset.ts +123 -0
  42. package/src/core/terminal/terminalControl.ts +22 -0
  43. package/src/core/terminal/terminalTitle.ts +16 -102
  44. package/src/core/{channel.ts → version/channel.ts} +1 -1
  45. package/src/core/{updateCheck.ts → version/updateCheck.ts} +10 -5
  46. package/src/core/{launchContext.ts → workspace/launchContext.ts} +9 -16
  47. package/src/core/{planStorage.ts → workspace/planStorage.ts} +2 -2
  48. package/src/core/{workspaceGuard.ts → workspace/workspaceGuard.ts} +97 -13
  49. package/src/headless/execRunner.ts +2 -2
  50. package/src/index.tsx +43 -89
  51. package/src/session/appSession.ts +10 -7
  52. package/src/session/chatLifecycle.ts +1 -1
  53. package/src/session/liveRenderScheduler.ts +1 -1
  54. package/src/session/types.ts +1 -1
  55. package/src/ui/AppShell.tsx +672 -706
  56. package/src/ui/AttachmentImportPanel.tsx +2 -2
  57. package/src/ui/BottomComposer.tsx +145 -144
  58. package/src/ui/ModelPickerScreen.tsx +216 -36
  59. package/src/ui/ModelReasoningPicker.tsx +1 -1
  60. package/src/ui/PlanReviewPanel.tsx +1 -1
  61. package/src/ui/ProviderPicker.tsx +735 -321
  62. package/src/ui/RuntimeStatusBar.tsx +108 -0
  63. package/src/ui/SelectionPanel.tsx +4 -0
  64. package/src/ui/SettingsPanel.tsx +1 -1
  65. package/src/ui/TextEntryPanel.tsx +1 -1
  66. package/src/ui/Timeline.tsx +1619 -1470
  67. package/src/ui/TopHeader.tsx +46 -30
  68. package/src/ui/TranscriptShell.tsx +322 -0
  69. package/src/ui/TurnGroup.tsx +2 -2
  70. package/src/ui/UpdateAvailableCard.tsx +3 -3
  71. package/src/ui/UpdatePromptPanel.tsx +16 -22
  72. package/src/ui/layout.ts +298 -24
  73. package/src/ui/layoutListWindow.ts +145 -0
  74. package/src/ui/logoVariants.ts +4 -8
  75. package/src/ui/runtimeDisplay.ts +15 -3
  76. package/src/ui/textLayout.ts +15 -4
  77. package/src/ui/timelineMeasure.ts +194 -122
  78. package/src/core/codex.ts +0 -124
  79. package/src/ui/StaticTranscriptItem.tsx +0 -56
  80. /package/src/core/{inputDebug.ts → debug/inputDebug.ts} +0 -0
  81. /package/src/core/{clipboard.ts → shared/clipboard.ts} +0 -0
  82. /package/src/core/{githubDiagnostics.ts → shared/githubDiagnostics.ts} +0 -0
  83. /package/src/core/{projectInstructions.ts → workspace/projectInstructions.ts} +0 -0
  84. /package/src/core/{workspaceActivity.ts → workspace/workspaceActivity.ts} +0 -0
  85. /package/src/core/{workspaceRoot.ts → workspace/workspaceRoot.ts} +0 -0
package/README.md CHANGED
@@ -507,7 +507,11 @@ npm view @golba98/codexa versions --json
507
507
  npm view @golba98/codexa dist-tags --json
508
508
  ```
509
509
 
510
- If `dist-tags.latest` points to an older version, v1.0.3 may not have been published yet, or the `latest` tag may need to be updated. Until v1.0.3 is published to npm, `@latest` will resolve to the highest published version.
510
+ If `dist-tags.latest` points to an older version, the registry may be slow to propagate. Wait a few minutes and retry, or install a specific version explicitly:
511
+
512
+ ```bash
513
+ npm install -g @golba98/codexa@1.0.3
514
+ ```
511
515
 
512
516
  ### `codexa --version` still shows an old version after updating
513
517
 
@@ -575,6 +579,12 @@ npm install -g @golba98/codexa@latest
575
579
 
576
580
  Codexa checks for updates on startup and caches the result for 6 hours (stored in `~/.codexa-update-check.json`). The update notice only appears when the npm registry `latest` version is newer than the running version.
577
581
 
582
+ Published npm versions are immutable. Versions before the fixed update checker may not show update notices even when a newer package exists. If in doubt, update directly:
583
+
584
+ ```bash
585
+ npm install -g @golba98/codexa@latest
586
+ ```
587
+
578
588
  If you expect a notice but don't see one:
579
589
 
580
590
  1. Check the current registry state: `npm view @golba98/codexa dist-tags --json`
@@ -596,22 +606,11 @@ If you expect a notice but don't see one:
596
606
 
597
607
  See [CHANGELOG.md](CHANGELOG.md) for the full release history.
598
608
 
599
- **Current release: v1.0.3**
600
-
601
- v1.0.3 is a package correctness and release-process fix:
602
- - The installed `npm` package now shows the full Codexa UI (logo, header, workspace, provider)
603
- - `APP_VERSION` in the package is guaranteed to match `package.json` at publish time
604
- - Test files are excluded from the published tarball
605
- - Semantic color-token system (`logoPrimary`, `text`, `textMuted`, etc.)
606
- - Responsive ASCII logo with three fallback sizes
607
-
608
- > Once v1.0.3 is published to npm, users on v1.0.2 will see the in-app update notice within 6 hours (cache TTL). To trigger it immediately: delete `~/.codexa-update-check.json` and restart Codexa.
609
-
610
- ## Repo Hygiene
609
+ **Current release: v1.0.4**
611
610
 
612
- Local-only files kept out of version control:
611
+ v1.0.4 is an update-notice reliability fix:
612
+ - Older installed versions can detect when npm `latest` is newer
613
+ - `/update check` bypasses stale cache and reports a useful status
614
+ - Failed registry lookups do not get cached as “up to date”
613
615
 
614
- - `node_modules/`
615
- - `.claude/`
616
- - `.env` and other local secret files
617
- - Editor, OS, and cache files
616
+ > Versions before the fixed update checker may not show update notices. Update directly with `npm install -g @golba98/codexa@latest`.
package/bin/codexa.js CHANGED
@@ -10,13 +10,10 @@ process.title = "CODEXA";
10
10
  const currentFile = fileURLToPath(import.meta.url);
11
11
  const packageRoot = dirname(dirname(currentFile));
12
12
  const forwardArgs = process.argv.slice(2);
13
- const workspaceRoot = process.cwd();
14
- const launcherStartTimeMs = Number(process.env.CODEXA_EXEC_TIMING_EPOCH_MS) || Date.now();
15
- let launcherPreviousElapsedMs = 0;
16
- const titleSequencePattern = /\x1b\](?:0|2);[^\x07]*(?:\x07|\x1b\\)/g;
17
- const titleSequenceDetectPattern = /\x1b\]([02]);([\s\S]*?)(?:\x07|\x1b\\)/g;
18
- const incompleteTitleSequencePattern = /\x1b\](?:0|2);[^\x07]*$/;
19
- let intendedTerminalTitle = "Codexa";
13
+ const workspaceRoot = process.cwd();
14
+ const launcherStartTimeMs = Number(process.env.CODEXA_EXEC_TIMING_EPOCH_MS) || Date.now();
15
+ let launcherPreviousElapsedMs = 0;
16
+ let intendedTerminalTitle = "Codexa";
20
17
 
21
18
  function writeRenderDebugRecord(kind, fields) {
22
19
  if (process.env.CODEXA_RENDER_DEBUG !== "1" && process.env.CODEXA_DEBUG_RENDER !== "1") {
@@ -24,10 +21,10 @@ function writeRenderDebugRecord(kind, fields) {
24
21
  }
25
22
 
26
23
  try {
27
- const debugDir = join(workspaceRoot, ".codexa-debug");
28
- mkdirSync(debugDir, { recursive: true });
29
- appendFileSync(
30
- join(debugDir, "render-debug.log"),
24
+ const debugDir = join(workspaceRoot, ".codexa", "debug");
25
+ mkdirSync(debugDir, { recursive: true });
26
+ appendFileSync(
27
+ process.env.CODEXA_RENDER_DEBUG_FILE?.trim() || join(debugDir, "render-status.log"),
31
28
  JSON.stringify({
32
29
  ts: Date.now(),
33
30
  pid: process.pid,
@@ -58,11 +55,13 @@ function writeTerminalTitleDebugRecord(fields) {
58
55
  return;
59
56
  }
60
57
 
61
- try {
62
- const debugDir = join(workspaceRoot, ".codexa-debug");
63
- mkdirSync(debugDir, { recursive: true });
64
- appendFileSync(
65
- process.env.CODEXA_TERMINAL_TITLE_DEBUG_FILE?.trim() || join(debugDir, "terminal-title-debug.log"),
58
+ try {
59
+ const debugDir = join(workspaceRoot, ".codexa", "debug");
60
+ mkdirSync(debugDir, { recursive: true });
61
+ appendFileSync(
62
+ process.env.CODEXA_TERMINAL_TITLE_DEBUG_FILE?.trim()
63
+ || process.env.CODEXA_RENDER_DEBUG_FILE?.trim()
64
+ || join(debugDir, "render-status.log"),
66
65
  JSON.stringify({
67
66
  ts: Date.now(),
68
67
  pid: process.pid,
@@ -76,26 +75,7 @@ function writeTerminalTitleDebugRecord(fields) {
76
75
  }
77
76
  }
78
77
 
79
- function traceTitleSequences(text, fields) {
80
- if (!text) return false;
81
- let found = false;
82
- titleSequenceDetectPattern.lastIndex = 0;
83
- for (let match = titleSequenceDetectPattern.exec(text); match; match = titleSequenceDetectPattern.exec(text)) {
84
- found = true;
85
- const title = match[2] || "";
86
- writeTerminalTitleDebugRecord({
87
- event: "terminalTitleSequence",
88
- osc: match[1] === "2" ? "OSC 2" : "OSC 0",
89
- title,
90
- containsWindowsSystem: title.toLowerCase().includes("c:\\windows\\system"),
91
- bytes: Buffer.byteLength(match[0] || ""),
92
- ...fields,
93
- });
94
- }
95
- return found;
96
- }
97
-
98
- function sanitizeTerminalTitle(title) {
78
+ function sanitizeTerminalTitle(title) {
99
79
  return String(title ?? "")
100
80
  .replace(/[\u0000-\u001f\u007f]/g, " ")
101
81
  .replace(/\x1b/g, "")
@@ -110,63 +90,22 @@ function normalizeTerminalTitle(title) {
110
90
  return cleanTitle;
111
91
  }
112
92
 
113
- function buildTitleSequence(title) {
114
- const safeTitle = normalizeTerminalTitle(title);
115
- return `\x1b]0;${safeTitle}\x07\x1b]2;${safeTitle}\x07`;
116
- }
117
-
118
- function writeIntendedTitle(reason, force = true) {
119
- const sequence = buildTitleSequence(intendedTerminalTitle);
120
- writeRenderDebugRecord("stdout", {
121
- event: "directWrite",
122
- source: `bin/codexa.js:${reason}`,
123
- bytes: Buffer.byteLength(sequence),
124
- containsViewportClear: false,
125
- containsScrollbackClear: false,
126
- containsCursorHome: false,
127
- containsTerminalReset: false,
128
- containsTitleSequence: true,
129
- });
130
- process.stdout.write(sequence);
131
- writeTerminalTitleDebugRecord({
132
- event: "codexaTitleWrite",
133
- source: `bin/codexa.js:${reason}`,
134
- title: intendedTerminalTitle,
135
- reason,
136
- force,
137
- bytes: Buffer.byteLength(sequence),
138
- });
139
- }
140
-
141
- function startLauncherTitleGuard() {
142
- const startedAt = Date.now();
143
- const interval = setInterval(() => {
144
- if (Date.now() - startedAt >= 2500) {
145
- clearInterval(interval);
146
- writeIntendedTitle("launcher-title-guard-end");
147
- return;
148
- }
149
- writeIntendedTitle("launcher-title-guard");
150
- }, 150);
151
- interval.unref?.();
152
- return () => clearInterval(interval);
153
- }
154
-
155
- function createTitleStripper(fields) {
156
- let carryover = "";
157
- return (chunk) => {
158
- const input = carryover + Buffer.from(chunk).toString("utf8");
159
- carryover = "";
160
- const incomplete = incompleteTitleSequencePattern.exec(input);
161
- const processable = incomplete?.index != null ? input.slice(0, incomplete.index) : input;
162
- if (incomplete?.index != null) {
163
- carryover = input.slice(incomplete.index);
164
- }
165
- return traceTitleSequences(processable, fields)
166
- ? processable.replace(titleSequencePattern, "")
167
- : processable;
168
- };
169
- }
93
+ function recordIntendedTitle(reason, force = true) {
94
+ writeTerminalTitleDebugRecord({
95
+ event: "codexaTitleSkipped",
96
+ source: `bin/codexa.js:${reason}`,
97
+ title: intendedTerminalTitle,
98
+ reason,
99
+ force,
100
+ });
101
+ writeRenderDebugRecord("title", {
102
+ event: "launcherTitleSkipped",
103
+ source: `bin/codexa.js:${reason}`,
104
+ title: intendedTerminalTitle,
105
+ reason,
106
+ force,
107
+ });
108
+ }
170
109
 
171
110
  function hasFlag(args, longFlag, shortFlag) {
172
111
  for (const arg of args) {
@@ -251,12 +190,10 @@ function markExecTiming(phase, fields = {}) {
251
190
 
252
191
  markExecTiming("launcher_start", { pid: process.pid });
253
192
 
254
- let stopLauncherTitleGuard = null;
255
- if (!isHeadlessMode && parentHasTTY) {
256
- intendedTerminalTitle = normalizeTerminalTitle(process.env.CODEXA_INITIAL_TERMINAL_TITLE || "Codexa");
257
- writeIntendedTitle("launcher-startup-title");
258
- stopLauncherTitleGuard = startLauncherTitleGuard();
259
- }
193
+ if (!isHeadlessMode && parentHasTTY) {
194
+ intendedTerminalTitle = normalizeTerminalTitle(process.env.CODEXA_INITIAL_TERMINAL_TITLE || "Codexa");
195
+ recordIntendedTitle("launcher-startup-title-disabled");
196
+ }
260
197
 
261
198
  if (!isHeadlessMode && hasFlag(forwardArgs, "--help", "-h")) {
262
199
  printHelp();
@@ -334,10 +271,10 @@ debugLaunch("resolved launch mode", {
334
271
  childStdio,
335
272
  });
336
273
 
337
- markExecTiming("bun_spawn_start", { executable: bunExecutable });
338
- if (!isHeadlessMode && parentHasTTY) {
339
- writeIntendedTitle("before-bun-spawn");
340
- }
274
+ markExecTiming("bun_spawn_start", { executable: bunExecutable });
275
+ if (!isHeadlessMode && parentHasTTY) {
276
+ recordIntendedTitle("before-bun-spawn-disabled");
277
+ }
341
278
 
342
279
  const child = spawn(
343
280
  bunExecutable,
@@ -361,13 +298,11 @@ const child = spawn(
361
298
  },
362
299
  );
363
300
 
364
- child.once("spawn", () => {
365
- if (!isHeadlessMode && parentHasTTY) {
366
- writeIntendedTitle("after-bun-spawn");
367
- stopLauncherTitleGuard?.();
368
- stopLauncherTitleGuard = null;
369
- }
370
- });
301
+ child.once("spawn", () => {
302
+ if (!isHeadlessMode && parentHasTTY) {
303
+ recordIntendedTitle("after-bun-spawn-disabled");
304
+ }
305
+ });
371
306
 
372
307
  if (!isHeadlessMode && !parentHasTTY) {
373
308
  const mouseFilter = createMouseFilter();
@@ -395,46 +330,29 @@ if (!isHeadlessMode && !parentHasTTY) {
395
330
  });
396
331
  }
397
332
 
398
- if (!isHeadlessMode) {
399
- const stripStdoutTitle = createTitleStripper({
400
- source: "bin/codexa.js:bun.stdout",
401
- stream: "stdout",
402
- origin: "child",
403
- action: "stripped",
404
- });
405
- const stripStderrTitle = createTitleStripper({
406
- source: "bin/codexa.js:bun.stderr",
407
- stream: "stderr",
408
- origin: "child",
409
- action: "stripped",
410
- });
411
-
412
- child.stdout?.on("data", (chunk) => {
413
- const safeChunk = stripStdoutTitle(chunk);
414
- if (safeChunk) process.stdout.write(safeChunk);
415
- });
416
- child.stderr?.on("data", (chunk) => {
417
- const safeChunk = stripStderrTitle(chunk);
418
- if (safeChunk) process.stderr.write(safeChunk);
419
- });
420
- }
421
-
422
- child.on("error", (error) => {
423
- if (!isHeadlessMode && parentHasTTY) {
424
- writeIntendedTitle("bun-spawn-error");
425
- }
333
+ if (!isHeadlessMode) {
334
+ child.stdout?.on("data", (chunk) => {
335
+ process.stdout.write(chunk);
336
+ });
337
+ child.stderr?.on("data", (chunk) => {
338
+ process.stderr.write(chunk);
339
+ });
340
+ }
341
+
342
+ child.on("error", (error) => {
343
+ if (!isHeadlessMode && parentHasTTY) {
344
+ recordIntendedTitle("bun-spawn-error-disabled");
345
+ }
426
346
  markExecTiming("bun_spawn_error", { message: error.message });
427
347
  console.error(`Failed to launch Bun: ${error.message}`);
428
348
  console.error("Bun is required to launch codexa. Install Bun, then run this command again.");
429
349
  process.exit(1);
430
350
  });
431
351
 
432
- child.on("close", (code, signal) => {
433
- if (!isHeadlessMode && parentHasTTY) {
434
- writeIntendedTitle("bun-close");
435
- stopLauncherTitleGuard?.();
436
- stopLauncherTitleGuard = null;
437
- }
352
+ child.on("close", (code, signal) => {
353
+ if (!isHeadlessMode && parentHasTTY) {
354
+ recordIntendedTitle("bun-close-disabled");
355
+ }
438
356
  markExecTiming("launcher_exit", { exit_code: code ?? 0, signal: signal ?? null });
439
357
  if (signal) {
440
358
  process.kill(process.pid, signal);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@golba98/codexa",
3
- "version": "1.0.3",
3
+ "version": "1.0.4",
4
4
  "description": "Terminal UI for Codexa — TypeScript + Bun + Ink",
5
5
  "type": "module",
6
6
  "bin": {
@@ -10,8 +10,9 @@
10
10
  "start": "bun run --silent src/index.tsx",
11
11
  "dev": "bun --watch --silent src/index.tsx",
12
12
  "dev:run": "node scripts/run-local-dev.mjs",
13
- "install:dev-bin": "node scripts/install-local-dev-bin.mjs",
14
- "typecheck": "tsc --noEmit",
13
+ "install:dev-bin": "node scripts/install-local-dev-bin.mjs",
14
+ "debug:claude-models": "bun run --silent src/core/providerRuntime/claudeCodeDiscoveryDebug.ts",
15
+ "typecheck": "tsc --noEmit",
15
16
  "test": "bun test",
16
17
  "audit:codexa-gap": "node scripts/audit-codexa-capabilities.mjs",
17
18
  "smoke:terminal-bench": "node scripts/smoke-terminal-bench.mjs",