@golba98/codexa 1.0.1
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.
- package/README.md +320 -0
- package/bin/codexa.js +445 -0
- package/package.json +45 -0
- package/scripts/audit-codexa-capabilities.mjs +466 -0
- package/scripts/smoke-terminal-bench.mjs +35 -0
- package/src/app.tsx +4561 -0
- package/src/appRenderStability.test.ts +131 -0
- package/src/commands/handler.test.ts +643 -0
- package/src/commands/handler.ts +875 -0
- package/src/config/launchArgs.test.ts +158 -0
- package/src/config/launchArgs.ts +186 -0
- package/src/config/layeredConfig.test.ts +143 -0
- package/src/config/layeredConfig.ts +836 -0
- package/src/config/persistence.test.ts +110 -0
- package/src/config/persistence.ts +311 -0
- package/src/config/runtimeConfig.test.ts +218 -0
- package/src/config/runtimeConfig.ts +554 -0
- package/src/config/settings.test.ts +155 -0
- package/src/config/settings.ts +401 -0
- package/src/config/toml-serialize.ts +98 -0
- package/src/config/trustStore.test.ts +29 -0
- package/src/config/trustStore.ts +68 -0
- package/src/core/attachments.test.ts +155 -0
- package/src/core/attachments.ts +71 -0
- package/src/core/auth/codexAuth.test.ts +68 -0
- package/src/core/auth/codexAuth.ts +359 -0
- package/src/core/cleanupFastFail.test.ts +76 -0
- package/src/core/cleanupFastFail.ts +67 -0
- package/src/core/clipboard.ts +24 -0
- package/src/core/codex.ts +124 -0
- package/src/core/codexExecArgs.test.ts +195 -0
- package/src/core/codexExecArgs.ts +152 -0
- package/src/core/codexLaunch.test.ts +205 -0
- package/src/core/codexLaunch.ts +162 -0
- package/src/core/codexPrompt.test.ts +252 -0
- package/src/core/codexPrompt.ts +428 -0
- package/src/core/executables/claudeExecutable.ts +63 -0
- package/src/core/executables/codexExecutable.test.ts +212 -0
- package/src/core/executables/codexExecutable.ts +159 -0
- package/src/core/executables/executableResolver.test.ts +129 -0
- package/src/core/executables/executableResolver.ts +138 -0
- package/src/core/executables/geminiExecutable.test.ts +116 -0
- package/src/core/executables/geminiExecutable.ts +78 -0
- package/src/core/executables/pathSanityScan.test.ts +47 -0
- package/src/core/githubDiagnostics.test.ts +92 -0
- package/src/core/githubDiagnostics.ts +222 -0
- package/src/core/hollowResponseFormat.test.ts +58 -0
- package/src/core/hollowResponseFormat.ts +39 -0
- package/src/core/inputDebug.ts +51 -0
- package/src/core/launchContext.test.ts +157 -0
- package/src/core/launchContext.ts +266 -0
- package/src/core/models/codexCapabilities.test.ts +45 -0
- package/src/core/models/codexCapabilities.ts +95 -0
- package/src/core/models/codexModelCapabilities.test.ts +246 -0
- package/src/core/models/codexModelCapabilities.ts +571 -0
- package/src/core/models/modelSpecs.test.ts +283 -0
- package/src/core/models/modelSpecs.ts +300 -0
- package/src/core/perf/profiler.ts +125 -0
- package/src/core/perf/renderDebug.test.ts +230 -0
- package/src/core/perf/renderDebug.ts +373 -0
- package/src/core/planStorage.test.ts +143 -0
- package/src/core/planStorage.ts +141 -0
- package/src/core/process/CommandRunner.test.ts +105 -0
- package/src/core/process/CommandRunner.ts +269 -0
- package/src/core/process/processValidation.ts +101 -0
- package/src/core/projectInstructions.test.ts +50 -0
- package/src/core/projectInstructions.ts +54 -0
- package/src/core/providerLauncher/launcher.test.ts +238 -0
- package/src/core/providerLauncher/launcher.ts +203 -0
- package/src/core/providerLauncher/registry.test.ts +324 -0
- package/src/core/providerLauncher/registry.ts +253 -0
- package/src/core/providerLauncher/types.ts +84 -0
- package/src/core/providerLauncher/workspaceConfig.test.ts +638 -0
- package/src/core/providerLauncher/workspaceConfig.ts +407 -0
- package/src/core/providerRuntime/anthropic.test.ts +1120 -0
- package/src/core/providerRuntime/anthropic.ts +576 -0
- package/src/core/providerRuntime/capabilityProfile.test.ts +311 -0
- package/src/core/providerRuntime/capabilityProfile.ts +288 -0
- package/src/core/providerRuntime/claudeCodeDiscovery.ts +446 -0
- package/src/core/providerRuntime/contextMetadata.test.ts +468 -0
- package/src/core/providerRuntime/contextMetadata.ts +409 -0
- package/src/core/providerRuntime/gemini.test.ts +437 -0
- package/src/core/providerRuntime/gemini.ts +784 -0
- package/src/core/providerRuntime/lmstudio.test.ts +168 -0
- package/src/core/providerRuntime/lmstudio.ts +118 -0
- package/src/core/providerRuntime/local.test.ts +787 -0
- package/src/core/providerRuntime/local.ts +754 -0
- package/src/core/providerRuntime/models.ts +150 -0
- package/src/core/providerRuntime/reasoning.ts +17 -0
- package/src/core/providerRuntime/registry.test.ts +233 -0
- package/src/core/providerRuntime/registry.ts +203 -0
- package/src/core/providerRuntime/types.ts +103 -0
- package/src/core/providers/codexJsonStream.test.ts +148 -0
- package/src/core/providers/codexJsonStream.ts +305 -0
- package/src/core/providers/codexSubprocess.test.ts +68 -0
- package/src/core/providers/codexSubprocess.ts +372 -0
- package/src/core/providers/codexTranscript.test.ts +284 -0
- package/src/core/providers/codexTranscript.ts +695 -0
- package/src/core/providers/openaiNative.ts +13 -0
- package/src/core/providers/registry.ts +21 -0
- package/src/core/providers/types.ts +59 -0
- package/src/core/terminal/terminalCapabilities.test.ts +93 -0
- package/src/core/terminal/terminalCapabilities.ts +100 -0
- package/src/core/terminal/terminalControl.test.ts +75 -0
- package/src/core/terminal/terminalControl.ts +147 -0
- package/src/core/terminal/terminalSanitize.test.ts +22 -0
- package/src/core/terminal/terminalSanitize.ts +147 -0
- package/src/core/terminal/terminalSelection.test.ts +42 -0
- package/src/core/terminal/terminalSelection.ts +66 -0
- package/src/core/terminal/terminalTitle.test.ts +328 -0
- package/src/core/terminal/terminalTitle.ts +483 -0
- package/src/core/workspaceActivity.test.ts +163 -0
- package/src/core/workspaceActivity.ts +380 -0
- package/src/core/workspaceGuard.test.ts +151 -0
- package/src/core/workspaceGuard.ts +288 -0
- package/src/core/workspaceRoot.test.ts +23 -0
- package/src/core/workspaceRoot.ts +47 -0
- package/src/exec.test.ts +13 -0
- package/src/exec.ts +72 -0
- package/src/headless/execArgs.test.ts +147 -0
- package/src/headless/execArgs.ts +294 -0
- package/src/headless/execRunner.test.ts +434 -0
- package/src/headless/execRunner.ts +304 -0
- package/src/index.test.tsx +618 -0
- package/src/index.tsx +296 -0
- package/src/session/appSession.test.ts +897 -0
- package/src/session/appSession.ts +761 -0
- package/src/session/chatLifecycle.test.ts +64 -0
- package/src/session/chatLifecycle.ts +951 -0
- package/src/session/liveRenderScheduler.test.ts +201 -0
- package/src/session/liveRenderScheduler.ts +214 -0
- package/src/session/planFlow.test.ts +103 -0
- package/src/session/planFlow.ts +149 -0
- package/src/session/planTranscript.test.ts +65 -0
- package/src/session/planTranscript.ts +15 -0
- package/src/session/promptRunSchedule.test.ts +36 -0
- package/src/session/promptRunSchedule.ts +26 -0
- package/src/session/types.ts +228 -0
- package/src/test/runtimeTestUtils.ts +14 -0
- package/src/types/react-dom.d.ts +3 -0
- package/src/ui/ActionRequiredBlock.tsx +38 -0
- package/src/ui/ActivityBars.tsx +68 -0
- package/src/ui/ActivityIndicator.test.tsx +58 -0
- package/src/ui/ActivityIndicator.tsx +58 -0
- package/src/ui/AgentBlock.test.ts +6 -0
- package/src/ui/AgentBlock.tsx +130 -0
- package/src/ui/AnimatedStatusText.test.ts +16 -0
- package/src/ui/AnimatedStatusText.tsx +69 -0
- package/src/ui/AppShell.test.tsx +1739 -0
- package/src/ui/AppShell.tsx +698 -0
- package/src/ui/AttachmentImportPanel.test.tsx +204 -0
- package/src/ui/AttachmentImportPanel.tsx +98 -0
- package/src/ui/AuthPanel.tsx +113 -0
- package/src/ui/BackendPicker.tsx +28 -0
- package/src/ui/BottomComposer.test.ts +674 -0
- package/src/ui/BottomComposer.tsx +1028 -0
- package/src/ui/CodexLogo.tsx +55 -0
- package/src/ui/DashCard.tsx +82 -0
- package/src/ui/Markdown.test.ts +157 -0
- package/src/ui/Markdown.tsx +310 -0
- package/src/ui/ModePicker.tsx +27 -0
- package/src/ui/ModelPicker.tsx +31 -0
- package/src/ui/ModelPickerProviderScope.test.tsx +411 -0
- package/src/ui/ModelPickerScreen.test.tsx +99 -0
- package/src/ui/ModelPickerScreen.tsx +416 -0
- package/src/ui/ModelPickerState.test.tsx +151 -0
- package/src/ui/ModelReasoningPicker.test.tsx +447 -0
- package/src/ui/ModelReasoningPicker.tsx +458 -0
- package/src/ui/Panel.tsx +51 -0
- package/src/ui/PermissionsPanel.tsx +78 -0
- package/src/ui/PlanActionPicker.tsx +119 -0
- package/src/ui/PlanReviewPanel.test.tsx +267 -0
- package/src/ui/PlanReviewPanel.tsx +212 -0
- package/src/ui/PromptCardBorder.test.tsx +161 -0
- package/src/ui/ProviderPicker.test.tsx +289 -0
- package/src/ui/ProviderPicker.tsx +321 -0
- package/src/ui/ProviderShortcut.test.tsx +143 -0
- package/src/ui/ReasoningPicker.tsx +46 -0
- package/src/ui/RunFooter.tsx +65 -0
- package/src/ui/SelectionPanel.tsx +67 -0
- package/src/ui/SettingsPanel.test.tsx +233 -0
- package/src/ui/SettingsPanel.tsx +156 -0
- package/src/ui/Spinner.tsx +25 -0
- package/src/ui/StaticIntroItem.tsx +54 -0
- package/src/ui/StaticTranscriptItem.tsx +56 -0
- package/src/ui/TextEntryPanel.tsx +139 -0
- package/src/ui/ThemePicker.tsx +31 -0
- package/src/ui/ThinkingBlock.tsx +100 -0
- package/src/ui/Timeline.test.ts +2067 -0
- package/src/ui/Timeline.tsx +1472 -0
- package/src/ui/TimelineNavigation.test.tsx +201 -0
- package/src/ui/TopHeader.test.tsx +239 -0
- package/src/ui/TopHeader.tsx +257 -0
- package/src/ui/TurnGroup.test.tsx +365 -0
- package/src/ui/TurnGroup.tsx +657 -0
- package/src/ui/busyStatusAnimation.test.ts +30 -0
- package/src/ui/busyStatusAnimation.ts +11 -0
- package/src/ui/commandNormalize.test.ts +142 -0
- package/src/ui/commandNormalize.ts +66 -0
- package/src/ui/diffRenderer.test.ts +102 -0
- package/src/ui/diffRenderer.ts +116 -0
- package/src/ui/focus.ts +61 -0
- package/src/ui/focusFlow.test.tsx +1098 -0
- package/src/ui/inputBuffer.test.ts +151 -0
- package/src/ui/inputBuffer.ts +203 -0
- package/src/ui/layout.test.ts +145 -0
- package/src/ui/layout.ts +287 -0
- package/src/ui/modeDisplay.test.ts +42 -0
- package/src/ui/modeDisplay.ts +52 -0
- package/src/ui/outputPipeline.ts +64 -0
- package/src/ui/progressEntries.ts +156 -0
- package/src/ui/runActivityView.test.ts +89 -0
- package/src/ui/runActivityView.ts +37 -0
- package/src/ui/runLifecycleView.test.tsx +237 -0
- package/src/ui/slashCommands.ts +41 -0
- package/src/ui/statusRenderIsolation.test.tsx +654 -0
- package/src/ui/terminalAnswerFormat.test.ts +19 -0
- package/src/ui/terminalAnswerFormat.ts +128 -0
- package/src/ui/textLayout.test.ts +18 -0
- package/src/ui/textLayout.ts +338 -0
- package/src/ui/theme.tsx +395 -0
- package/src/ui/themeFlow.test.ts +53 -0
- package/src/ui/themeFlow.ts +41 -0
- package/src/ui/timelineMeasure.ts +3088 -0
- package/src/ui/timelineMeasureCache.test.ts +986 -0
- package/src/ui/useThrottledValue.ts +31 -0
|
@@ -0,0 +1,466 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* audit-codexa-capabilities.mjs
|
|
5
|
+
*
|
|
6
|
+
* Lightweight Codexa capability audit checker.
|
|
7
|
+
* Performs static analysis on source to report feature availability.
|
|
8
|
+
*
|
|
9
|
+
* Usage: node scripts/audit-codexa-capabilities.mjs
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import { existsSync, readFileSync } from "fs";
|
|
13
|
+
import { join, resolve } from "path";
|
|
14
|
+
import { fileURLToPath } from "url";
|
|
15
|
+
|
|
16
|
+
const __dirname = import.meta.dirname ??
|
|
17
|
+
resolve(new URL(import.meta.url).pathname, "..", "..");
|
|
18
|
+
|
|
19
|
+
const repoRoot = resolve(__dirname, "..");
|
|
20
|
+
|
|
21
|
+
const checks = {
|
|
22
|
+
entrypoint() {
|
|
23
|
+
const path = join(repoRoot, "bin", "codexa.js");
|
|
24
|
+
const exists = existsSync(path);
|
|
25
|
+
return {
|
|
26
|
+
pass: exists,
|
|
27
|
+
evidence: exists ? [path] : [],
|
|
28
|
+
reason: exists
|
|
29
|
+
? "Entry wrapper spawns Bun runtime to execute app"
|
|
30
|
+
: "Entry wrapper not found"
|
|
31
|
+
};
|
|
32
|
+
},
|
|
33
|
+
|
|
34
|
+
cliHelpVersion() {
|
|
35
|
+
const launchArgsPath = join(repoRoot, "src", "config", "launchArgs.ts");
|
|
36
|
+
const launcherPath = join(repoRoot, "bin", "codexa.js");
|
|
37
|
+
if (!existsSync(launchArgsPath) || !existsSync(launcherPath)) {
|
|
38
|
+
return { pass: false, evidence: [], reason: "launch arg parser or launcher not found" };
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const launchArgsContent = readFileSync(launchArgsPath, "utf-8");
|
|
42
|
+
const launcherContent = readFileSync(launcherPath, "utf-8");
|
|
43
|
+
const combined = `${launchArgsContent}\n${launcherContent}`;
|
|
44
|
+
const hasHelp = /--help/.test(combined) && /["']-h["']/.test(combined);
|
|
45
|
+
const hasVersion = /--version/.test(combined) && /["']-v["']/.test(combined);
|
|
46
|
+
const exitsBeforeInk = /process\.exit\(0\)/.test(launcherContent) && !/render\(/.test(launcherContent);
|
|
47
|
+
const readsPackageVersion = /package\.json/.test(launcherContent) && /version/.test(launcherContent);
|
|
48
|
+
|
|
49
|
+
return {
|
|
50
|
+
pass: hasHelp && hasVersion && exitsBeforeInk && readsPackageVersion,
|
|
51
|
+
evidence: [launchArgsPath, launcherPath],
|
|
52
|
+
reason: hasHelp && hasVersion && exitsBeforeInk && readsPackageVersion
|
|
53
|
+
? "--help/-h and --version/-v exit from launcher before Ink and version reads package.json"
|
|
54
|
+
: `Missing evidence: ${[
|
|
55
|
+
hasHelp ? null : "help flags",
|
|
56
|
+
hasVersion ? null : "version flags",
|
|
57
|
+
exitsBeforeInk ? null : "early exit before Ink",
|
|
58
|
+
readsPackageVersion ? null : "package.json version read",
|
|
59
|
+
].filter(Boolean).join(", ")}`
|
|
60
|
+
};
|
|
61
|
+
},
|
|
62
|
+
|
|
63
|
+
initialPromptArgument() {
|
|
64
|
+
const path = join(repoRoot, "src", "config", "launchArgs.ts");
|
|
65
|
+
const appPath = join(repoRoot, "src", "app.tsx");
|
|
66
|
+
|
|
67
|
+
if (!existsSync(path) || !existsSync(appPath)) {
|
|
68
|
+
return { pass: false, evidence: [], reason: "Required files not found" };
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
const launchContent = readFileSync(path, "utf-8");
|
|
72
|
+
const appContent = readFileSync(appPath, "utf-8");
|
|
73
|
+
|
|
74
|
+
const hasExtraction = /initialPrompt/.test(launchContent) && /promptArgs/.test(launchContent);
|
|
75
|
+
const hasUsage = /launchArgs\.initialPrompt/.test(appContent)
|
|
76
|
+
&& /initialPromptSubmittedRef/.test(appContent)
|
|
77
|
+
&& /startPromptRun\(initialPrompt,\s*initialPrompt\)/.test(appContent);
|
|
78
|
+
|
|
79
|
+
return {
|
|
80
|
+
pass: hasExtraction && hasUsage,
|
|
81
|
+
evidence: [path, appPath],
|
|
82
|
+
reason: hasExtraction && hasUsage
|
|
83
|
+
? "Initial prompt support present"
|
|
84
|
+
: "Passthrough args stored but not used for initial prompt"
|
|
85
|
+
};
|
|
86
|
+
},
|
|
87
|
+
|
|
88
|
+
interactiveMode() {
|
|
89
|
+
const indexPath = join(repoRoot, "src", "index.tsx");
|
|
90
|
+
if (!existsSync(indexPath)) {
|
|
91
|
+
return { pass: false, evidence: [], reason: "src/index.tsx not found" };
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
const content = readFileSync(indexPath, "utf-8");
|
|
95
|
+
const hasTTY = /isTTY|TTY|isatty/.test(content);
|
|
96
|
+
const hasInk = /render\(|<App/.test(content);
|
|
97
|
+
|
|
98
|
+
return {
|
|
99
|
+
pass: hasTTY && hasInk,
|
|
100
|
+
evidence: [indexPath],
|
|
101
|
+
reason: hasTTY && hasInk
|
|
102
|
+
? "Interactive mode with TTY detection and Ink UI present"
|
|
103
|
+
: "TTY or UI setup missing"
|
|
104
|
+
};
|
|
105
|
+
},
|
|
106
|
+
|
|
107
|
+
modelPicker() {
|
|
108
|
+
const paths = [
|
|
109
|
+
join(repoRoot, "src", "ui", "ModelPicker.tsx"),
|
|
110
|
+
join(repoRoot, "src", "config", "settings.ts")
|
|
111
|
+
];
|
|
112
|
+
|
|
113
|
+
const exist = paths.filter(p => existsSync(p));
|
|
114
|
+
const hasModels = exist.some(p =>
|
|
115
|
+
/AVAILABLE_MODELS/.test(readFileSync(p, "utf-8"))
|
|
116
|
+
);
|
|
117
|
+
|
|
118
|
+
return {
|
|
119
|
+
pass: exist.length === 2 && hasModels,
|
|
120
|
+
evidence: exist,
|
|
121
|
+
reason: exist.length === 2 && hasModels
|
|
122
|
+
? "Model picker UI and model enumeration present"
|
|
123
|
+
: `Missing components: ${exist.length}/2`
|
|
124
|
+
};
|
|
125
|
+
},
|
|
126
|
+
|
|
127
|
+
configLoading() {
|
|
128
|
+
const paths = [
|
|
129
|
+
join(repoRoot, "src", "config", "layeredConfig.ts"),
|
|
130
|
+
join(repoRoot, "src", "config", "persistence.ts"),
|
|
131
|
+
join(repoRoot, "src", "config", "runtimeConfig.ts")
|
|
132
|
+
];
|
|
133
|
+
|
|
134
|
+
const exist = paths.filter(p => existsSync(p));
|
|
135
|
+
return {
|
|
136
|
+
pass: exist.length === paths.length,
|
|
137
|
+
evidence: exist,
|
|
138
|
+
reason: exist.length === 3
|
|
139
|
+
? "Layered config resolution, persistence, and runtime config present"
|
|
140
|
+
: `Found ${exist.length}/3 config modules`
|
|
141
|
+
};
|
|
142
|
+
},
|
|
143
|
+
|
|
144
|
+
agentsmdSupport() {
|
|
145
|
+
const loaderPath = join(repoRoot, "src", "core", "projectInstructions.ts");
|
|
146
|
+
const appPath = join(repoRoot, "src", "app.tsx");
|
|
147
|
+
const promptPath = join(repoRoot, "src", "core", "codexPrompt.ts");
|
|
148
|
+
const providerPath = join(repoRoot, "src", "core", "providers", "codexSubprocess.ts");
|
|
149
|
+
|
|
150
|
+
const paths = [loaderPath, appPath, promptPath, providerPath];
|
|
151
|
+
const existing = paths.filter(p => existsSync(p));
|
|
152
|
+
if (existing.length !== paths.length) {
|
|
153
|
+
return {
|
|
154
|
+
pass: false,
|
|
155
|
+
evidence: existing,
|
|
156
|
+
reason: `Found ${existing.length}/4 AGENTS.md support files`
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
const loaderContent = readFileSync(loaderPath, "utf-8");
|
|
161
|
+
const appContent = readFileSync(appPath, "utf-8");
|
|
162
|
+
const promptContent = readFileSync(promptPath, "utf-8");
|
|
163
|
+
const providerContent = readFileSync(providerPath, "utf-8");
|
|
164
|
+
const discoversAgents = /AGENTS\.md/.test(loaderContent) && /\.codex/.test(loaderContent);
|
|
165
|
+
const appLoadsAgents = /loadProjectInstructions/.test(appContent) && /projectInstructions/.test(appContent);
|
|
166
|
+
const promptInjectsAgents = /Project instructions:/.test(promptContent) && /projectInstructions/.test(promptContent);
|
|
167
|
+
const providerPassesAgents = /projectInstructions/.test(providerContent) && /buildCodexPrompt/.test(providerContent);
|
|
168
|
+
|
|
169
|
+
return {
|
|
170
|
+
pass: discoversAgents && appLoadsAgents && promptInjectsAgents && providerPassesAgents,
|
|
171
|
+
evidence: paths,
|
|
172
|
+
reason: discoversAgents && appLoadsAgents && promptInjectsAgents && providerPassesAgents
|
|
173
|
+
? "AGENTS.md/.codex/AGENTS.md discovery, app loading, and prompt injection present"
|
|
174
|
+
: `Missing evidence: ${[
|
|
175
|
+
discoversAgents ? null : "discovery",
|
|
176
|
+
appLoadsAgents ? null : "app loading",
|
|
177
|
+
promptInjectsAgents ? null : "prompt injection",
|
|
178
|
+
providerPassesAgents ? null : "provider pass-through",
|
|
179
|
+
].filter(Boolean).join(", ")}`
|
|
180
|
+
};
|
|
181
|
+
},
|
|
182
|
+
|
|
183
|
+
commandExecution() {
|
|
184
|
+
const path = join(repoRoot, "src", "core", "process", "CommandRunner.ts");
|
|
185
|
+
if (!existsSync(path)) {
|
|
186
|
+
return { pass: false, evidence: [], reason: "CommandRunner.ts not found" };
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
const content = readFileSync(path, "utf-8");
|
|
190
|
+
const hasRun = /runCommand|spawn/.test(content);
|
|
191
|
+
const hasOutput = /stdout|stderr/.test(content);
|
|
192
|
+
|
|
193
|
+
return {
|
|
194
|
+
pass: hasRun && hasOutput,
|
|
195
|
+
evidence: [path],
|
|
196
|
+
reason: hasRun && hasOutput
|
|
197
|
+
? "Shell command execution with output capture present"
|
|
198
|
+
: "Command execution incomplete"
|
|
199
|
+
};
|
|
200
|
+
},
|
|
201
|
+
|
|
202
|
+
fileEditingLayer() {
|
|
203
|
+
const paths = [
|
|
204
|
+
join(repoRoot, "src", "core", "workspaceActivity.ts"),
|
|
205
|
+
join(repoRoot, "src", "core", "workspaceGuard.ts")
|
|
206
|
+
];
|
|
207
|
+
|
|
208
|
+
const exist = paths.filter(p => existsSync(p));
|
|
209
|
+
const content = exist.map(p => readFileSync(p, "utf-8")).join("");
|
|
210
|
+
const hasTracking = /createWorkspaceActivityTracker|modified|created|deleted/.test(content);
|
|
211
|
+
const hasGuard = /isPathInsideWorkspace|workspaceGuard/.test(content);
|
|
212
|
+
|
|
213
|
+
return {
|
|
214
|
+
pass: exist.length === 2 && hasTracking && hasGuard,
|
|
215
|
+
evidence: exist,
|
|
216
|
+
reason: hasTracking && hasGuard
|
|
217
|
+
? "File activity tracking and workspace guard present"
|
|
218
|
+
: exist.length < 2 ? "Activity or guard module missing" : "Tracking/guard logic incomplete"
|
|
219
|
+
};
|
|
220
|
+
},
|
|
221
|
+
|
|
222
|
+
diffRenderer() {
|
|
223
|
+
const rendererPath = join(repoRoot, "src", "ui", "diffRenderer.ts");
|
|
224
|
+
const testPath = join(repoRoot, "src", "ui", "diffRenderer.test.ts");
|
|
225
|
+
const markdownPath = join(repoRoot, "src", "ui", "Markdown.tsx");
|
|
226
|
+
const timelinePath = join(repoRoot, "src", "ui", "timelineMeasure.ts");
|
|
227
|
+
const paths = [rendererPath, testPath, markdownPath, timelinePath];
|
|
228
|
+
const existing = paths.filter(p => existsSync(p));
|
|
229
|
+
|
|
230
|
+
if (existing.length !== paths.length) {
|
|
231
|
+
return {
|
|
232
|
+
pass: false,
|
|
233
|
+
evidence: existing,
|
|
234
|
+
reason: `Found ${existing.length}/4 diff renderer files/integrations`
|
|
235
|
+
};
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
const rendererContent = readFileSync(rendererPath, "utf-8");
|
|
239
|
+
const testContent = readFileSync(testPath, "utf-8");
|
|
240
|
+
const markdownContent = readFileSync(markdownPath, "utf-8");
|
|
241
|
+
const timelineContent = readFileSync(timelinePath, "utf-8");
|
|
242
|
+
const exportsUtility = /export\s+function\s+isUnifiedDiff/.test(rendererContent)
|
|
243
|
+
&& /export\s+function\s+renderUnifiedDiff/.test(rendererContent)
|
|
244
|
+
&& /export\s+function\s+maybeRenderDiff/.test(rendererContent)
|
|
245
|
+
&& /DiffRenderLine/.test(rendererContent);
|
|
246
|
+
const detectsUnifiedDiff = /DIFF_GIT_HEADER_PATTERN/.test(rendererContent)
|
|
247
|
+
&& /HUNK_HEADER_PATTERN/.test(rendererContent)
|
|
248
|
+
&& /OLD_FILE_HEADER_PATTERN/.test(rendererContent)
|
|
249
|
+
&& /NEW_FILE_HEADER_PATTERN/.test(rendererContent);
|
|
250
|
+
const hasFocusedTests = /isUnifiedDiff/.test(testContent)
|
|
251
|
+
&& /renderUnifiedDiff/.test(testContent)
|
|
252
|
+
&& /ANSI|control/i.test(testContent)
|
|
253
|
+
&& /normal text|normal prose/i.test(testContent);
|
|
254
|
+
const markdownIntegrated = /diffRenderer/.test(markdownContent) && /maybeRenderDiff/.test(markdownContent);
|
|
255
|
+
const timelineIntegrated = /diffRenderer/.test(timelineContent) && /maybeRenderDiff/.test(timelineContent);
|
|
256
|
+
|
|
257
|
+
return {
|
|
258
|
+
pass: exportsUtility && detectsUnifiedDiff && hasFocusedTests && markdownIntegrated && timelineIntegrated,
|
|
259
|
+
evidence: paths,
|
|
260
|
+
reason: exportsUtility && detectsUnifiedDiff && hasFocusedTests && markdownIntegrated && timelineIntegrated
|
|
261
|
+
? "Unified diff renderer utility, tests, and UI integrations present"
|
|
262
|
+
: `Missing evidence: ${[
|
|
263
|
+
exportsUtility ? null : "utility exports",
|
|
264
|
+
detectsUnifiedDiff ? null : "unified diff detection",
|
|
265
|
+
hasFocusedTests ? null : "focused tests",
|
|
266
|
+
markdownIntegrated ? null : "Markdown integration",
|
|
267
|
+
timelineIntegrated ? null : "timeline integration",
|
|
268
|
+
].filter(Boolean).join(", ")}`
|
|
269
|
+
};
|
|
270
|
+
},
|
|
271
|
+
|
|
272
|
+
approvalSandboxLogic() {
|
|
273
|
+
const paths = [
|
|
274
|
+
join(repoRoot, "src", "core", "workspaceGuard.ts"),
|
|
275
|
+
join(repoRoot, "src", "config", "runtimeConfig.ts")
|
|
276
|
+
];
|
|
277
|
+
|
|
278
|
+
const exist = paths.filter(p => existsSync(p));
|
|
279
|
+
const content = exist.map(p => readFileSync(p, "utf-8")).join("");
|
|
280
|
+
const hasSandbox = /sandbox|approval|permission|writable.*root/.test(content);
|
|
281
|
+
|
|
282
|
+
return {
|
|
283
|
+
pass: exist.length === 2 && hasSandbox,
|
|
284
|
+
evidence: exist,
|
|
285
|
+
reason: hasSandbox
|
|
286
|
+
? "Sandbox configuration and approval logic present"
|
|
287
|
+
: "Approval or sandbox logic missing"
|
|
288
|
+
};
|
|
289
|
+
},
|
|
290
|
+
|
|
291
|
+
sessionHistoryPersistence() {
|
|
292
|
+
const paths = [
|
|
293
|
+
join(repoRoot, "src", "session", "types.ts"),
|
|
294
|
+
join(repoRoot, "src", "session", "appSession.ts"),
|
|
295
|
+
join(repoRoot, "src", "config", "persistence.ts")
|
|
296
|
+
];
|
|
297
|
+
|
|
298
|
+
const exist = paths.filter(p => existsSync(p));
|
|
299
|
+
return {
|
|
300
|
+
pass: exist.length === 3,
|
|
301
|
+
evidence: exist,
|
|
302
|
+
reason: exist.length === 3
|
|
303
|
+
? "Session event types, state management, and persistence present"
|
|
304
|
+
: `Found ${exist.length}/3 session modules`
|
|
305
|
+
};
|
|
306
|
+
},
|
|
307
|
+
|
|
308
|
+
debugLogging() {
|
|
309
|
+
const debugPath = join(repoRoot, "src", "core", "inputDebug.ts");
|
|
310
|
+
const envPath = join(repoRoot, "bin", "codexa.js");
|
|
311
|
+
|
|
312
|
+
const debugExists = existsSync(debugPath);
|
|
313
|
+
const envContent = existsSync(envPath) ? readFileSync(envPath, "utf-8") : "";
|
|
314
|
+
const hasEnvDebug = /CODEXA_DEBUG|debug/.test(envContent);
|
|
315
|
+
|
|
316
|
+
return {
|
|
317
|
+
pass: debugExists || hasEnvDebug,
|
|
318
|
+
evidence: [debugExists ? debugPath : envPath].filter(p => existsSync(p)),
|
|
319
|
+
reason: debugExists && hasEnvDebug
|
|
320
|
+
? "Debug logging module and environment variable support present"
|
|
321
|
+
: debugExists || hasEnvDebug
|
|
322
|
+
? "Partial debug support"
|
|
323
|
+
: "Debug logging not found"
|
|
324
|
+
};
|
|
325
|
+
},
|
|
326
|
+
|
|
327
|
+
windowsPowerShellHandling() {
|
|
328
|
+
const launcherPath = join(repoRoot, "bin", "codexa.js");
|
|
329
|
+
if (!existsSync(launcherPath)) {
|
|
330
|
+
return { pass: false, evidence: [], reason: "Launcher not found" };
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
const content = readFileSync(launcherPath, "utf-8");
|
|
334
|
+
const hasWinDetect = /win32|platform|windows/i.test(content);
|
|
335
|
+
const hasExeResolution = /bun\.exe|bun\.cmd|shell|spawn/.test(content);
|
|
336
|
+
|
|
337
|
+
return {
|
|
338
|
+
pass: hasWinDetect && hasExeResolution,
|
|
339
|
+
evidence: [launcherPath],
|
|
340
|
+
reason: hasWinDetect && hasExeResolution
|
|
341
|
+
? "Windows platform detection and executable resolution present"
|
|
342
|
+
: "Windows-specific handling incomplete"
|
|
343
|
+
};
|
|
344
|
+
},
|
|
345
|
+
|
|
346
|
+
resizeHandling() {
|
|
347
|
+
const indexPath = join(repoRoot, "src", "index.tsx");
|
|
348
|
+
if (!existsSync(indexPath)) {
|
|
349
|
+
return { pass: false, evidence: [], reason: "src/index.tsx not found" };
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
const content = readFileSync(indexPath, "utf-8");
|
|
353
|
+
const hasResize = /resize|onResize|RESIZE/.test(content);
|
|
354
|
+
const hasRepaint = /repaint|recalculate|calculateLayout/.test(content);
|
|
355
|
+
|
|
356
|
+
return {
|
|
357
|
+
pass: hasResize && hasRepaint,
|
|
358
|
+
evidence: [indexPath],
|
|
359
|
+
reason: hasResize && hasRepaint
|
|
360
|
+
? "Terminal resize event handling and UI recalculation present"
|
|
361
|
+
: "Resize handling incomplete"
|
|
362
|
+
};
|
|
363
|
+
},
|
|
364
|
+
|
|
365
|
+
streamingHandler() {
|
|
366
|
+
const paths = [
|
|
367
|
+
join(repoRoot, "src", "core", "providers", "codexSubprocess.ts"),
|
|
368
|
+
join(repoRoot, "src", "core", "codex.ts")
|
|
369
|
+
];
|
|
370
|
+
|
|
371
|
+
const exist = paths.filter(p => existsSync(p));
|
|
372
|
+
const content = exist.map(p => readFileSync(p, "utf-8")).join("");
|
|
373
|
+
const hasStreaming = /stream|emit|chunk|line|onLine/.test(content);
|
|
374
|
+
|
|
375
|
+
return {
|
|
376
|
+
pass: exist.length > 0 && hasStreaming,
|
|
377
|
+
evidence: exist,
|
|
378
|
+
reason: hasStreaming
|
|
379
|
+
? "Streaming response handler present"
|
|
380
|
+
: "Streaming implementation not found"
|
|
381
|
+
};
|
|
382
|
+
},
|
|
383
|
+
|
|
384
|
+
interruptCancelHandling() {
|
|
385
|
+
const indexPath = join(repoRoot, "src", "index.tsx");
|
|
386
|
+
const appPath = join(repoRoot, "src", "app.tsx");
|
|
387
|
+
|
|
388
|
+
const paths = [indexPath, appPath].filter(p => existsSync(p));
|
|
389
|
+
const content = paths.map(p => readFileSync(p, "utf-8")).join("");
|
|
390
|
+
const hasSignals = /SIGINT|SIGTERM|signal|cancel/.test(content);
|
|
391
|
+
const hasCancel = /cancel|abort|kill/.test(content);
|
|
392
|
+
|
|
393
|
+
return {
|
|
394
|
+
pass: hasSignals && hasCancel,
|
|
395
|
+
evidence: paths,
|
|
396
|
+
reason: hasSignals && hasCancel
|
|
397
|
+
? "Signal handling and cancellation logic present"
|
|
398
|
+
: "Interrupt/cancel handling incomplete"
|
|
399
|
+
};
|
|
400
|
+
}
|
|
401
|
+
};
|
|
402
|
+
|
|
403
|
+
function statusSymbol(pass) {
|
|
404
|
+
return pass ? "✓" : "✗";
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
function statusLabel(pass) {
|
|
408
|
+
return pass ? "PASS" : "MISSING";
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
function formatName(name) {
|
|
412
|
+
return name
|
|
413
|
+
.replace(/([A-Z])/g, " $1")
|
|
414
|
+
.replace(/^./, str => str.toUpperCase());
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
console.log("\n" + "=".repeat(80));
|
|
418
|
+
console.log("CODEXA CAPABILITY AUDIT REPORT");
|
|
419
|
+
console.log("=".repeat(80));
|
|
420
|
+
console.log(`Repository: ${repoRoot}\n`);
|
|
421
|
+
|
|
422
|
+
const results = [];
|
|
423
|
+
|
|
424
|
+
for (const [name, checkFn] of Object.entries(checks)) {
|
|
425
|
+
const result = checkFn();
|
|
426
|
+
results.push({ name, ...result });
|
|
427
|
+
|
|
428
|
+
const symbol = statusSymbol(result.pass);
|
|
429
|
+
const status = statusLabel(result.pass);
|
|
430
|
+
const formattedName = formatName(name);
|
|
431
|
+
|
|
432
|
+
console.log(`${symbol} ${status.padEnd(8)} | ${formattedName}`);
|
|
433
|
+
console.log(` ${result.reason}`);
|
|
434
|
+
if (result.evidence.length > 0) {
|
|
435
|
+
console.log(` Evidence: ${result.evidence.map(e => e.replace(repoRoot, ".")).join(", ")}`);
|
|
436
|
+
}
|
|
437
|
+
console.log();
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
const total = results.length;
|
|
441
|
+
const passed = results.filter(r => r.pass).length;
|
|
442
|
+
const missing = total - passed;
|
|
443
|
+
const pctComplete = Math.round((passed / total) * 100);
|
|
444
|
+
|
|
445
|
+
console.log("=".repeat(80));
|
|
446
|
+
console.log("CAPABILITY SUMMARY");
|
|
447
|
+
console.log("=".repeat(80));
|
|
448
|
+
console.log(`Total checks: ${total}`);
|
|
449
|
+
console.log(`Passed: ${passed} (${pctComplete}%)`);
|
|
450
|
+
console.log(`Missing/Partial: ${missing} (${100 - pctComplete}%)`);
|
|
451
|
+
console.log();
|
|
452
|
+
|
|
453
|
+
const missingFeatures = results.filter(r => !r.pass).map(r => formatName(r.name));
|
|
454
|
+
|
|
455
|
+
if (missingFeatures.length > 0) {
|
|
456
|
+
console.log("TOP MISSING FEATURES:");
|
|
457
|
+
missingFeatures.forEach((f, i) => {
|
|
458
|
+
console.log(` ${i + 1}. ${f}`);
|
|
459
|
+
});
|
|
460
|
+
console.log();
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
console.log("=".repeat(80));
|
|
464
|
+
console.log();
|
|
465
|
+
|
|
466
|
+
process.exit(passed === total ? 0 : 1);
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import { spawn } from "node:child_process";
|
|
4
|
+
import { dirname, join } from "node:path";
|
|
5
|
+
import { fileURLToPath } from "node:url";
|
|
6
|
+
|
|
7
|
+
const scriptDir = dirname(fileURLToPath(import.meta.url));
|
|
8
|
+
const repoRoot = dirname(scriptDir);
|
|
9
|
+
const binPath = join(repoRoot, "bin", "codexa.js");
|
|
10
|
+
const prompt = "Print the current directory, list files, and stop.";
|
|
11
|
+
|
|
12
|
+
const child = spawn(
|
|
13
|
+
process.execPath,
|
|
14
|
+
[binPath, "exec", prompt],
|
|
15
|
+
{
|
|
16
|
+
cwd: process.cwd(),
|
|
17
|
+
stdio: "inherit",
|
|
18
|
+
env: {
|
|
19
|
+
...process.env,
|
|
20
|
+
},
|
|
21
|
+
},
|
|
22
|
+
);
|
|
23
|
+
|
|
24
|
+
child.on("error", (error) => {
|
|
25
|
+
console.error(`[smoke-terminal-bench] failed to launch: ${error.message}`);
|
|
26
|
+
process.exit(1);
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
child.on("close", (code, signal) => {
|
|
30
|
+
if (signal) {
|
|
31
|
+
console.error(`[smoke-terminal-bench] terminated by ${signal}`);
|
|
32
|
+
process.exit(1);
|
|
33
|
+
}
|
|
34
|
+
process.exit(code ?? 0);
|
|
35
|
+
});
|