@golba98/codexa 1.0.2 → 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.
- package/README.md +396 -100
- package/bin/codexa.js +62 -144
- package/package.json +14 -8
- package/src/app.tsx +596 -306
- package/src/commands/handler.ts +6 -6
- package/src/config/buildInfo.ts +2 -2
- package/src/config/layeredConfig.ts +1 -1
- package/src/config/persistence.ts +10 -0
- package/src/config/runtimeConfig.ts +1 -1
- package/src/config/settings.ts +8 -16
- package/src/config/trustStore.ts +1 -1
- package/src/config/updateCheckCache.ts +19 -1
- package/src/core/README.md +52 -0
- package/src/core/agent/loop.ts +282 -0
- package/src/core/agent/protocol.ts +211 -0
- package/src/core/agent/tools.ts +414 -0
- package/src/core/{codexExecArgs.ts → codex/codexExecArgs.ts} +2 -2
- package/src/core/{codexLaunch.ts → codex/codexLaunch.ts} +3 -3
- package/src/core/{codexPrompt.ts → codex/codexPrompt.ts} +3 -3
- package/src/core/debug/modelStateDebug.ts +34 -0
- package/src/core/executables/antigravityExecutable.ts +48 -0
- package/src/core/executables/codexExecutable.ts +1 -0
- package/src/core/executables/executableResolver.ts +65 -43
- package/src/core/perf/renderDebug.ts +10 -6
- package/src/core/process/processValidation.ts +9 -5
- package/src/core/providerLauncher/launcher.ts +59 -42
- package/src/core/providerLauncher/registry.ts +30 -14
- package/src/core/providerLauncher/types.ts +11 -9
- package/src/core/providerLauncher/workspaceConfig.ts +41 -26
- package/src/core/providerRuntime/anthropic.ts +7 -1
- package/src/core/providerRuntime/antigravity.ts +305 -0
- package/src/core/providerRuntime/claudeCodeDiscovery.ts +268 -22
- package/src/core/providerRuntime/claudeCodeDiscoveryDebug.ts +55 -0
- package/src/core/providerRuntime/contextMetadata.ts +12 -24
- package/src/core/providerRuntime/local.ts +129 -51
- package/src/core/providerRuntime/models.ts +22 -11
- package/src/core/providerRuntime/registry.ts +58 -31
- package/src/core/providerRuntime/types.ts +19 -14
- package/src/core/providers/codexSubprocess.ts +2 -2
- package/src/core/providers/types.ts +1 -1
- package/src/core/{attachments.ts → shared/attachments.ts} +27 -4
- package/src/core/{cleanupFastFail.ts → shared/cleanupFastFail.ts} +1 -1
- package/src/core/{hollowResponseFormat.ts → shared/hollowResponseFormat.ts} +1 -1
- package/src/core/terminal/clearFrameBoundary.ts +814 -0
- package/src/core/terminal/frameLock.ts +109 -0
- package/src/core/terminal/inkRenderReset.ts +123 -0
- package/src/core/terminal/terminalControl.ts +22 -0
- package/src/core/terminal/terminalTitle.ts +16 -102
- package/src/core/version/channel.ts +23 -0
- package/src/core/version/updateCheck.ts +193 -0
- package/src/core/{launchContext.ts → workspace/launchContext.ts} +32 -39
- package/src/core/{planStorage.ts → workspace/planStorage.ts} +2 -2
- package/src/core/{workspaceGuard.ts → workspace/workspaceGuard.ts} +97 -13
- package/src/headless/execRunner.ts +2 -2
- package/src/index.tsx +43 -89
- package/src/session/appSession.ts +10 -7
- package/src/session/chatLifecycle.ts +1 -1
- package/src/session/liveRenderScheduler.ts +1 -1
- package/src/session/types.ts +3 -2
- package/src/ui/ActionRequiredBlock.tsx +5 -5
- package/src/ui/ActivityBars.tsx +3 -3
- package/src/ui/ActivityIndicator.tsx +6 -6
- package/src/ui/AgentBlock.tsx +6 -6
- package/src/ui/AnimatedStatusText.tsx +1 -1
- package/src/ui/AppShell.tsx +670 -719
- package/src/ui/AttachmentImportPanel.tsx +8 -8
- package/src/ui/AuthPanel.tsx +20 -20
- package/src/ui/BottomComposer.tsx +158 -118
- package/src/ui/DashCard.tsx +3 -3
- package/src/ui/Markdown.tsx +17 -17
- package/src/ui/ModelPickerScreen.tsx +222 -42
- package/src/ui/ModelReasoningPicker.tsx +15 -15
- package/src/ui/Panel.tsx +3 -3
- package/src/ui/PlanActionPicker.tsx +6 -6
- package/src/ui/PlanReviewPanel.tsx +9 -9
- package/src/ui/ProviderPicker.tsx +735 -321
- package/src/ui/RunFooter.tsx +3 -3
- package/src/ui/RuntimeStatusBar.tsx +108 -0
- package/src/ui/SelectionPanel.tsx +8 -4
- package/src/ui/SettingsPanel.tsx +9 -9
- package/src/ui/Spinner.tsx +1 -1
- package/src/ui/TextEntryPanel.tsx +11 -11
- package/src/ui/ThinkingBlock.tsx +8 -8
- package/src/ui/Timeline.tsx +1625 -1472
- package/src/ui/TopHeader.tsx +437 -293
- package/src/ui/TranscriptShell.tsx +322 -0
- package/src/ui/TurnGroup.tsx +33 -33
- package/src/ui/UpdateAvailableCard.tsx +41 -0
- package/src/ui/UpdatePromptPanel.tsx +197 -0
- package/src/ui/focus.ts +3 -0
- package/src/ui/layout.ts +299 -25
- package/src/ui/layoutListWindow.ts +145 -0
- package/src/ui/logoVariants.ts +103 -0
- package/src/ui/modeDisplay.ts +12 -12
- package/src/ui/runtimeDisplay.ts +112 -0
- package/src/ui/textLayout.ts +15 -4
- package/src/ui/theme.tsx +274 -395
- package/src/ui/timelineMeasure.ts +218 -136
- package/scripts/audit-codexa-capabilities.mjs +0 -466
- package/scripts/gen-build-info.mjs +0 -33
- package/scripts/smoke-terminal-bench.mjs +0 -35
- package/src/appRenderStability.test.ts +0 -131
- package/src/commands/handler.test.ts +0 -655
- package/src/config/launchArgs.test.ts +0 -189
- package/src/config/layeredConfig.test.ts +0 -143
- package/src/config/persistence.test.ts +0 -114
- package/src/config/runtimeConfig.test.ts +0 -218
- package/src/config/settings.test.ts +0 -155
- package/src/config/trustStore.test.ts +0 -29
- package/src/core/attachments.test.ts +0 -155
- package/src/core/auth/codexAuth.test.ts +0 -68
- package/src/core/cleanupFastFail.test.ts +0 -76
- package/src/core/codex.ts +0 -124
- package/src/core/codexExecArgs.test.ts +0 -195
- package/src/core/codexLaunch.test.ts +0 -205
- package/src/core/codexPrompt.test.ts +0 -252
- package/src/core/executables/codexExecutable.test.ts +0 -212
- package/src/core/executables/executableResolver.test.ts +0 -129
- package/src/core/executables/geminiExecutable.test.ts +0 -116
- package/src/core/executables/pathSanityScan.test.ts +0 -47
- package/src/core/githubDiagnostics.test.ts +0 -92
- package/src/core/hollowResponseFormat.test.ts +0 -58
- package/src/core/launchContext.test.ts +0 -157
- package/src/core/models/codexCapabilities.test.ts +0 -45
- package/src/core/models/codexModelCapabilities.test.ts +0 -246
- package/src/core/models/modelSpecs.test.ts +0 -283
- package/src/core/perf/renderDebug.test.ts +0 -230
- package/src/core/planStorage.test.ts +0 -143
- package/src/core/process/CommandRunner.test.ts +0 -105
- package/src/core/projectInstructions.test.ts +0 -50
- package/src/core/providerLauncher/launcher.test.ts +0 -238
- package/src/core/providerLauncher/registry.test.ts +0 -324
- package/src/core/providerLauncher/workspaceConfig.test.ts +0 -638
- package/src/core/providerRuntime/anthropic.test.ts +0 -1120
- package/src/core/providerRuntime/capabilityProfile.test.ts +0 -311
- package/src/core/providerRuntime/contextMetadata.test.ts +0 -468
- package/src/core/providerRuntime/gemini.test.ts +0 -437
- package/src/core/providerRuntime/lmstudio.test.ts +0 -168
- package/src/core/providerRuntime/local.test.ts +0 -787
- package/src/core/providerRuntime/registry.test.ts +0 -233
- package/src/core/providers/codexJsonStream.test.ts +0 -148
- package/src/core/providers/codexSubprocess.test.ts +0 -68
- package/src/core/providers/codexTranscript.test.ts +0 -284
- package/src/core/terminal/startupClear.test.ts +0 -55
- package/src/core/terminal/terminalCapabilities.test.ts +0 -93
- package/src/core/terminal/terminalControl.test.ts +0 -75
- package/src/core/terminal/terminalSanitize.test.ts +0 -22
- package/src/core/terminal/terminalSelection.test.ts +0 -42
- package/src/core/terminal/terminalTitle.test.ts +0 -328
- package/src/core/updateCheck.test.ts +0 -194
- package/src/core/updateCheck.ts +0 -172
- package/src/core/workspaceActivity.test.ts +0 -163
- package/src/core/workspaceGuard.test.ts +0 -151
- package/src/core/workspaceRoot.test.ts +0 -23
- package/src/exec.test.ts +0 -13
- package/src/headless/execArgs.test.ts +0 -147
- package/src/headless/execRunner.test.ts +0 -436
- package/src/index.test.tsx +0 -620
- package/src/session/appSession.test.ts +0 -897
- package/src/session/chatLifecycle.test.ts +0 -64
- package/src/session/liveRenderScheduler.test.ts +0 -201
- package/src/session/planFlow.test.ts +0 -103
- package/src/session/planTranscript.test.ts +0 -65
- package/src/session/promptRunSchedule.test.ts +0 -36
- package/src/ui/ActivityIndicator.test.tsx +0 -58
- package/src/ui/AgentBlock.test.ts +0 -6
- package/src/ui/AnimatedStatusText.test.ts +0 -16
- package/src/ui/AppShell.test.tsx +0 -1776
- package/src/ui/AttachmentImportPanel.test.tsx +0 -204
- package/src/ui/BottomComposer.test.ts +0 -674
- package/src/ui/CodexLogo.tsx +0 -55
- package/src/ui/Markdown.test.ts +0 -157
- package/src/ui/ModelPickerProviderScope.test.tsx +0 -411
- package/src/ui/ModelPickerScreen.test.tsx +0 -99
- package/src/ui/ModelPickerState.test.tsx +0 -151
- package/src/ui/ModelReasoningPicker.test.tsx +0 -447
- package/src/ui/PlanReviewPanel.test.tsx +0 -267
- package/src/ui/PromptCardBorder.test.tsx +0 -161
- package/src/ui/ProviderPicker.test.tsx +0 -289
- package/src/ui/ProviderShortcut.test.tsx +0 -143
- package/src/ui/SettingsPanel.test.tsx +0 -233
- package/src/ui/StaticTranscriptItem.tsx +0 -56
- package/src/ui/Timeline.test.ts +0 -2067
- package/src/ui/TimelineNavigation.test.tsx +0 -201
- package/src/ui/TopHeader.test.tsx +0 -254
- package/src/ui/TurnGroup.test.tsx +0 -365
- package/src/ui/busyStatusAnimation.test.ts +0 -30
- package/src/ui/commandNormalize.test.ts +0 -142
- package/src/ui/diffRenderer.test.ts +0 -102
- package/src/ui/focusFlow.test.tsx +0 -1098
- package/src/ui/inputBuffer.test.ts +0 -151
- package/src/ui/layout.test.ts +0 -146
- package/src/ui/modeDisplay.test.ts +0 -42
- package/src/ui/runActivityView.test.ts +0 -89
- package/src/ui/runLifecycleView.test.tsx +0 -237
- package/src/ui/statusRenderIsolation.test.tsx +0 -654
- package/src/ui/terminalAnswerFormat.test.ts +0 -19
- package/src/ui/textLayout.test.ts +0 -18
- package/src/ui/themeFlow.test.ts +0 -53
- package/src/ui/timelineMeasureCache.test.ts +0 -986
- /package/src/core/{inputDebug.ts → debug/inputDebug.ts} +0 -0
- /package/src/core/{clipboard.ts → shared/clipboard.ts} +0 -0
- /package/src/core/{githubDiagnostics.ts → shared/githubDiagnostics.ts} +0 -0
- /package/src/core/{projectInstructions.ts → workspace/projectInstructions.ts} +0 -0
- /package/src/core/{workspaceActivity.ts → workspace/workspaceActivity.ts} +0 -0
- /package/src/core/{workspaceRoot.ts → workspace/workspaceRoot.ts} +0 -0
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { runCommand } from "../process/CommandRunner.js";
|
|
2
|
+
import { resolveExecutable } from "./executableResolver.js";
|
|
3
|
+
|
|
4
|
+
type CommandRunner = typeof runCommand;
|
|
5
|
+
|
|
6
|
+
let cachedExecutable: string | null = null;
|
|
7
|
+
|
|
8
|
+
export function resetAgyExecutableCacheForTests(): void {
|
|
9
|
+
cachedExecutable = null;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Returns the resolved Antigravity CLI executable (full path or bare name).
|
|
14
|
+
*
|
|
15
|
+
* Priority:
|
|
16
|
+
* 1. Configured path override (antigravityCommandPath)
|
|
17
|
+
* 2. AGY_EXECUTABLE env var
|
|
18
|
+
* 3. Windows PATH lookup for real files: agy.exe, agy.cmd, agy.bat, agy
|
|
19
|
+
* 4. Bare name fallback "agy" (Unix PATH resolution)
|
|
20
|
+
*/
|
|
21
|
+
export async function resolveAgyExecutable(options?: {
|
|
22
|
+
runCommandImpl?: CommandRunner;
|
|
23
|
+
cwd?: string;
|
|
24
|
+
configuredPath?: string | null;
|
|
25
|
+
}): Promise<string> {
|
|
26
|
+
if (!options?.configuredPath && !options?.runCommandImpl && cachedExecutable !== null) {
|
|
27
|
+
return cachedExecutable;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const result = await resolveExecutable({
|
|
31
|
+
runCommandImpl: options?.runCommandImpl,
|
|
32
|
+
cwd: options?.cwd,
|
|
33
|
+
configuredPath: options?.configuredPath,
|
|
34
|
+
envOverrides: ["AGY_EXECUTABLE"],
|
|
35
|
+
commandNames: process.platform === "win32"
|
|
36
|
+
? ["agy.exe", "agy.cmd", "agy.bat", "agy"]
|
|
37
|
+
: ["agy"],
|
|
38
|
+
knownPathDirectories: [],
|
|
39
|
+
knownFilePaths: [],
|
|
40
|
+
label: "antigravity",
|
|
41
|
+
allowBareFallback: true,
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
if (!options?.configuredPath && !options?.runCommandImpl) {
|
|
45
|
+
cachedExecutable = result;
|
|
46
|
+
}
|
|
47
|
+
return result;
|
|
48
|
+
}
|
|
@@ -101,6 +101,7 @@ export function spawnCodexProcess(
|
|
|
101
101
|
options: SpawnOptions,
|
|
102
102
|
): ReturnType<typeof spawn> {
|
|
103
103
|
const spec = buildSpawnSpec(executable, args);
|
|
104
|
+
if (!spec.executable) throw new Error("Codex executable path is empty.");
|
|
104
105
|
return spawn(spec.executable, spec.args, { ...options, shell: false });
|
|
105
106
|
}
|
|
106
107
|
|
|
@@ -21,18 +21,27 @@ export interface ExecutableResolverOptions {
|
|
|
21
21
|
requireResolvedFile?: boolean;
|
|
22
22
|
}
|
|
23
23
|
|
|
24
|
-
function validateConfiguredExecutable(value: string, label: string, cwd: string): string {
|
|
25
|
-
return normalizeExecutableValue(value, {
|
|
24
|
+
function validateConfiguredExecutable(value: string, label: string, cwd: string): string {
|
|
25
|
+
return normalizeExecutableValue(value, {
|
|
26
26
|
label,
|
|
27
27
|
cwd,
|
|
28
28
|
requireExistingPath: /[\\/]/.test(value) || /^[\s"']*[A-Za-z]:/.test(value),
|
|
29
29
|
allowBareExecutable: true,
|
|
30
|
-
});
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function validateResolvedExecutable(value: string, label: string, cwd: string): string {
|
|
34
|
+
return normalizeExecutableValue(value, {
|
|
35
|
+
label,
|
|
36
|
+
cwd,
|
|
37
|
+
requireExistingPath: false,
|
|
38
|
+
allowBareExecutable: true,
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
async function resolveWithWhere(
|
|
43
|
+
runCommandImpl: CommandRunner,
|
|
44
|
+
cwd: string,
|
|
36
45
|
query: string,
|
|
37
46
|
requireResolvedFile: boolean,
|
|
38
47
|
): Promise<string | null> {
|
|
@@ -47,13 +56,19 @@ async function resolveWithWhere(
|
|
|
47
56
|
const lines = whereResult.stdout
|
|
48
57
|
.trim()
|
|
49
58
|
.split(/[\r\n]+/)
|
|
50
|
-
.map((l) => l.trim())
|
|
51
|
-
.filter(Boolean);
|
|
52
|
-
for (const line of lines) {
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
}
|
|
59
|
+
.map((l) => l.trim())
|
|
60
|
+
.filter(Boolean);
|
|
61
|
+
for (const line of lines) {
|
|
62
|
+
let candidate: string;
|
|
63
|
+
try {
|
|
64
|
+
candidate = validateResolvedExecutable(line, "where.exe result", cwd);
|
|
65
|
+
} catch {
|
|
66
|
+
continue;
|
|
67
|
+
}
|
|
68
|
+
if (!requireResolvedFile || existsSync(candidate)) return candidate;
|
|
69
|
+
}
|
|
70
|
+
return null;
|
|
71
|
+
}
|
|
57
72
|
|
|
58
73
|
/**
|
|
59
74
|
* Resolves an executable's location.
|
|
@@ -98,41 +113,48 @@ export async function resolveExecutable(options: ExecutableResolverOptions): Pro
|
|
|
98
113
|
for (const candidate of options.commandNames) {
|
|
99
114
|
knownCandidates.push(join(dir, candidate));
|
|
100
115
|
}
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
for (const candidate of knownCandidates) {
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
for (const candidate of knownCandidates) {
|
|
119
|
+
const validated = validateResolvedExecutable(candidate, `${options.label} known executable`, cwd);
|
|
120
|
+
if (existsSync(validated)) return validated;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
// 5. Explicit known file fallbacks
|
|
125
|
+
for (const candidate of options.knownFilePaths ?? []) {
|
|
126
|
+
const validated = validateResolvedExecutable(candidate, `${options.label} known executable`, cwd);
|
|
127
|
+
if (existsSync(validated)) return validated;
|
|
128
|
+
}
|
|
112
129
|
|
|
113
130
|
if (options.allowBareFallback === false) {
|
|
114
131
|
throw new Error(`${options.label} executable was not found.`);
|
|
115
132
|
}
|
|
116
133
|
|
|
117
|
-
// 6. Bare name fallback — prefer the name without an extension (works on Unix).
|
|
118
|
-
const bareName = options.commandNames.find((c) => !c.includes(".")) ?? options.commandNames[0];
|
|
119
|
-
return bareName
|
|
120
|
-
}
|
|
134
|
+
// 6. Bare name fallback — prefer the name without an extension (works on Unix).
|
|
135
|
+
const bareName = options.commandNames.find((c) => !c.includes(".")) ?? options.commandNames[0];
|
|
136
|
+
return validateResolvedExecutable(bareName!, `${options.label} executable`, cwd);
|
|
137
|
+
}
|
|
121
138
|
|
|
122
139
|
/**
|
|
123
140
|
* Builds the spawn spec for a resolved executable.
|
|
124
141
|
* .cmd and .bat files must be invoked via `cmd.exe /d /s /c` on Windows.
|
|
142
|
+
*
|
|
143
|
+
* `platform` defaults to the host platform; it is injectable so the Windows
|
|
144
|
+
* wrapping branch can be unit-tested from any OS.
|
|
125
145
|
*/
|
|
126
|
-
export function buildSpawnSpec(
|
|
127
|
-
executable: string,
|
|
128
|
-
args: string[],
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
}
|
|
146
|
+
export function buildSpawnSpec(
|
|
147
|
+
executable: string,
|
|
148
|
+
args: string[],
|
|
149
|
+
platform: NodeJS.Platform = process.platform,
|
|
150
|
+
): { executable: string; args: string[] } {
|
|
151
|
+
const validatedExecutable = validateResolvedExecutable(executable, "Executable", process.cwd());
|
|
152
|
+
if (platform === "win32") {
|
|
153
|
+
const lower = validatedExecutable.toLowerCase();
|
|
154
|
+
if (lower.endsWith(".cmd") || lower.endsWith(".bat")) {
|
|
155
|
+
validateWindowsBatchExecutableForCmd(validatedExecutable, "Windows batch executable");
|
|
156
|
+
return { executable: "cmd.exe", args: ["/d", "/s", "/c", "call", validatedExecutable, ...args] };
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
return { executable: validatedExecutable, args };
|
|
160
|
+
}
|
|
@@ -4,14 +4,14 @@ import { useEffect, useRef } from "react";
|
|
|
4
4
|
|
|
5
5
|
type DebugEnv = Record<string, string | undefined>;
|
|
6
6
|
|
|
7
|
-
// Global debug state — populated lazily on first check, or eagerly via configureRenderDebug().
|
|
7
|
+
// Global debug state — populated lazily on first check, or eagerly via configureRenderDebug().
|
|
8
8
|
let configured = false;
|
|
9
9
|
let enabled = false;
|
|
10
10
|
let renderTraceEnabled = false;
|
|
11
11
|
let lifecycleEnabled = false;
|
|
12
12
|
let flickerEnabled = false;
|
|
13
13
|
let plainActionsEnabled = false;
|
|
14
|
-
let logPath = join(process.cwd(), ".codexa
|
|
14
|
+
let logPath = join(process.cwd(), ".codexa", "debug", "render-status.log");
|
|
15
15
|
let sessionId = `${Date.now()}-${process.pid}`;
|
|
16
16
|
const counters = new Map<string, number>();
|
|
17
17
|
|
|
@@ -19,13 +19,17 @@ function configureFromEnv(env: DebugEnv = process.env): void {
|
|
|
19
19
|
renderTraceEnabled = env["CODEXA_DEBUG_RENDER_TRACE"] === "1";
|
|
20
20
|
// Both CODEXA_RENDER_DEBUG and CODEXA_DEBUG_RENDER activate render debugging —
|
|
21
21
|
// two names exist for historical reasons; either one is sufficient.
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
22
|
+
// CODEXA_TERMINAL_TRACE is a focused alias for diagnosing terminal/clear/resize
|
|
23
|
+
// render-state issues; it lights up the same `terminal` trace channel.
|
|
24
|
+
enabled = env["CODEXA_RENDER_DEBUG"] === "1"
|
|
25
|
+
|| env["CODEXA_DEBUG_MODEL_STATE"] === "1"
|
|
26
|
+
|| env["CODEXA_DEBUG_RENDER"] === "1"
|
|
27
|
+
|| env["CODEXA_TERMINAL_TRACE"] === "1"
|
|
28
|
+
|| renderTraceEnabled;
|
|
25
29
|
lifecycleEnabled = env["CODEXA_DEBUG_LIFECYCLE"] === "1";
|
|
26
30
|
flickerEnabled = env["CODEXA_DEBUG_FLICKER"] === "1";
|
|
27
31
|
plainActionsEnabled = env["CODEXA_DEBUG_PLAIN_ACTIONS"] === "1";
|
|
28
|
-
logPath = env["CODEXA_RENDER_DEBUG_FILE"]?.trim() || join(process.cwd(), ".codexa
|
|
32
|
+
logPath = env["CODEXA_RENDER_DEBUG_FILE"]?.trim() || join(process.cwd(), ".codexa", "debug", "render-status.log");
|
|
29
33
|
sessionId = `${Date.now()}-${process.pid}`;
|
|
30
34
|
configured = true;
|
|
31
35
|
}
|
|
@@ -23,10 +23,14 @@ function stripBalancedWrappingQuotes(value: string): string {
|
|
|
23
23
|
return value;
|
|
24
24
|
}
|
|
25
25
|
|
|
26
|
-
function looksLikePath(value: string): boolean {
|
|
27
|
-
return /[\\/]/.test(value) || /^[A-Za-z]:/.test(value);
|
|
28
|
-
}
|
|
29
|
-
|
|
26
|
+
function looksLikePath(value: string): boolean {
|
|
27
|
+
return /[\\/]/.test(value) || /^[A-Za-z]:/.test(value);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function isWindowsAbsolutePath(value: string): boolean {
|
|
31
|
+
return /^[A-Za-z]:[\\/]/.test(value);
|
|
32
|
+
}
|
|
33
|
+
|
|
30
34
|
function hasWindowsBatchExtension(value: string): boolean {
|
|
31
35
|
return /\.(?:cmd|bat)$/i.test(value);
|
|
32
36
|
}
|
|
@@ -67,7 +71,7 @@ export function normalizeExecutableValue(
|
|
|
67
71
|
return trimmed;
|
|
68
72
|
}
|
|
69
73
|
|
|
70
|
-
const normalized = isAbsolute(trimmed)
|
|
74
|
+
const normalized = isAbsolute(trimmed) || isWindowsAbsolutePath(trimmed) ? trimmed : resolve(cwd, trimmed);
|
|
71
75
|
validateCommonExecutableSyntax(normalized, options.label);
|
|
72
76
|
|
|
73
77
|
if (requireExistingPath && !existsSync(normalized)) {
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import { spawn, type ChildProcess } from "child_process";
|
|
2
|
-
import { existsSync } from "fs";
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import
|
|
1
|
+
import { spawn, type ChildProcess } from "child_process";
|
|
2
|
+
import { accessSync, constants, existsSync } from "fs";
|
|
3
|
+
import { delimiter, join } from "path";
|
|
4
|
+
import { buildSpawnSpec } from "../executables/executableResolver.js";
|
|
5
|
+
import { normalizeExecutableValue } from "../process/processValidation.js";
|
|
6
|
+
import type { ProviderConfig, ProviderLaunchCommand } from "./types.js";
|
|
6
7
|
|
|
7
8
|
export interface ProviderLaunchSpec {
|
|
8
9
|
executable: string;
|
|
@@ -75,43 +76,55 @@ function setRawMode(stdin: RawModeStream | null | undefined, enabled: boolean):
|
|
|
75
76
|
}
|
|
76
77
|
}
|
|
77
78
|
|
|
78
|
-
function executableLooksLikePath(executable: string): boolean {
|
|
79
|
-
return /[\\/]/.test(executable) || /^[A-Za-z]:/.test(executable);
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
79
|
+
function executableLooksLikePath(executable: string): boolean {
|
|
80
|
+
return /[\\/]/.test(executable) || /^[A-Za-z]:/.test(executable);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
function canAccessExecutable(path: string): boolean {
|
|
84
|
+
try {
|
|
85
|
+
if (process.platform === "win32") {
|
|
86
|
+
return existsSync(path);
|
|
87
|
+
}
|
|
88
|
+
accessSync(path, constants.X_OK);
|
|
89
|
+
return true;
|
|
90
|
+
} catch {
|
|
91
|
+
return false;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
function getPathExecutableCandidates(executable: string): string[] {
|
|
96
|
+
if (process.platform !== "win32" || /\.[A-Za-z0-9_-]+$/.test(executable)) {
|
|
97
|
+
return [executable];
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
const pathExt = process.env.PATHEXT?.split(";").filter(Boolean) ?? [".COM", ".EXE", ".BAT", ".CMD"];
|
|
101
|
+
return [executable, ...pathExt.map((ext) => `${executable}${ext.toLowerCase()}`)];
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
export async function commandExistsOnPath(executable: string): Promise<boolean> {
|
|
105
|
+
let candidate: string;
|
|
106
|
+
try {
|
|
107
|
+
candidate = normalizeExecutableValue(executable, {
|
|
108
|
+
label: "Provider launch command",
|
|
109
|
+
allowBareExecutable: true,
|
|
110
|
+
});
|
|
111
|
+
} catch {
|
|
112
|
+
return false;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
const trimmed = candidate.trim();
|
|
116
|
+
if (executableLooksLikePath(trimmed)) {
|
|
117
|
+
return canAccessExecutable(trimmed);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
const pathEntries = process.env.PATH?.split(delimiter).filter(Boolean) ?? [];
|
|
121
|
+
for (const dir of pathEntries) {
|
|
122
|
+
for (const name of getPathExecutableCandidates(trimmed)) {
|
|
123
|
+
if (canAccessExecutable(join(dir, name))) return true;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
return false;
|
|
127
|
+
}
|
|
115
128
|
|
|
116
129
|
function formatSpawnError(provider: ProviderConfig, executable: string, error: NodeJS.ErrnoException): ProviderLaunchResult {
|
|
117
130
|
if (error.code === "ENOENT") {
|
|
@@ -162,6 +175,10 @@ export async function launchProviderCli(
|
|
|
162
175
|
let child: ChildProcess;
|
|
163
176
|
try {
|
|
164
177
|
const spawnSpec = buildSpawnSpec(spec.executable, spec.args);
|
|
178
|
+
if (!spawnSpec.executable) {
|
|
179
|
+
resolve({ status: "spawn-error", message: "Executable path is empty after resolution." });
|
|
180
|
+
return;
|
|
181
|
+
}
|
|
165
182
|
child = spawnImpl(spawnSpec.executable, spawnSpec.args, {
|
|
166
183
|
cwd: spec.cwd,
|
|
167
184
|
shell: false,
|
|
@@ -14,12 +14,16 @@ import {
|
|
|
14
14
|
isProviderRoutableInCodexa,
|
|
15
15
|
isProviderRouteConfigured,
|
|
16
16
|
} from "../providerRuntime/registry.js";
|
|
17
|
-
import { normalizeGeminiModelId } from "../providerRuntime/models.js";
|
|
18
|
-
import {
|
|
17
|
+
import { normalizeGeminiModelId } from "../providerRuntime/models.js";
|
|
18
|
+
import { ANTIGRAVITY_DEFAULT_MODEL_ID } from "../providerRuntime/antigravity.js";
|
|
19
|
+
import { setLocalProviderConfig } from "../providerRuntime/local.js";
|
|
19
20
|
import { formatContextLength, resolveModelContextLengthCached } from "../providerRuntime/contextMetadata.js";
|
|
20
21
|
import { resolveModelCapabilityProfileCached } from "../providerRuntime/capabilityProfile.js";
|
|
21
22
|
|
|
22
|
-
|
|
23
|
+
// Google/Gemini remains a recognized legacy config value so existing workspace
|
|
24
|
+
// files can be migrated, but it is no longer a selectable Codexa provider.
|
|
25
|
+
const PROVIDER_ORDER: readonly ProviderId[] = ["openai", "anthropic", "local", "antigravity"];
|
|
26
|
+
const KNOWN_PROVIDER_IDS: readonly ProviderId[] = ["openai", "anthropic", "google", "local", "antigravity"];
|
|
23
27
|
|
|
24
28
|
const DEFAULT_PROVIDER_ID: ProviderId = "openai";
|
|
25
29
|
|
|
@@ -63,8 +67,8 @@ const DEFAULT_PROVIDERS: Record<ProviderId, ProviderDefault> = {
|
|
|
63
67
|
isActiveRoute: false,
|
|
64
68
|
routeUnavailableReason: null,
|
|
65
69
|
},
|
|
66
|
-
local: {
|
|
67
|
-
id: "local",
|
|
70
|
+
local: {
|
|
71
|
+
id: "local",
|
|
68
72
|
displayName: "Local",
|
|
69
73
|
currentModel: () => "Local default",
|
|
70
74
|
backendType: "local-openai-compatible",
|
|
@@ -72,12 +76,23 @@ const DEFAULT_PROVIDERS: Record<ProviderId, ProviderDefault> = {
|
|
|
72
76
|
enabled: false,
|
|
73
77
|
launchCommand: null,
|
|
74
78
|
isActiveRoute: false,
|
|
75
|
-
routeUnavailableReason: "Local provider unavailable. Start LM Studio, load a model, and enable the local server.",
|
|
76
|
-
},
|
|
77
|
-
|
|
79
|
+
routeUnavailableReason: "Local provider unavailable. Start LM Studio, load a model, and enable the local server.",
|
|
80
|
+
},
|
|
81
|
+
antigravity: {
|
|
82
|
+
id: "antigravity",
|
|
83
|
+
displayName: "Antigravity",
|
|
84
|
+
currentModel: () => ANTIGRAVITY_DEFAULT_MODEL_ID,
|
|
85
|
+
backendType: "antigravity-cli-auth",
|
|
86
|
+
routeMode: "in-codexa",
|
|
87
|
+
enabled: true,
|
|
88
|
+
launchCommand: { executable: "agy", args: [] },
|
|
89
|
+
isActiveRoute: false,
|
|
90
|
+
routeUnavailableReason: null,
|
|
91
|
+
},
|
|
92
|
+
};
|
|
78
93
|
|
|
79
|
-
function isProviderId(value: unknown): value is ProviderId {
|
|
80
|
-
return typeof value === "string" &&
|
|
94
|
+
function isProviderId(value: unknown): value is ProviderId {
|
|
95
|
+
return typeof value === "string" && KNOWN_PROVIDER_IDS.includes(value as ProviderId);
|
|
81
96
|
}
|
|
82
97
|
|
|
83
98
|
function normalizeLaunchCommand(value: ProviderWorkspaceOverride["command"] | undefined): ProviderLaunchCommand | null | undefined {
|
|
@@ -128,13 +143,14 @@ function applyOverride(
|
|
|
128
143
|
};
|
|
129
144
|
}
|
|
130
145
|
|
|
131
|
-
export function getDefaultProviderId(config: ProviderWorkspaceConfig | null | undefined): ProviderId {
|
|
132
|
-
|
|
133
|
-
|
|
146
|
+
export function getDefaultProviderId(config: ProviderWorkspaceConfig | null | undefined): ProviderId {
|
|
147
|
+
const providerId = config?.workspaceDefaultProviderId;
|
|
148
|
+
return isProviderId(providerId) && providerId !== "google" ? providerId : DEFAULT_PROVIDER_ID;
|
|
149
|
+
}
|
|
134
150
|
|
|
135
151
|
export function getActiveRouteProviderId(config: ProviderWorkspaceConfig | null | undefined): ProviderId {
|
|
136
152
|
const providerId = config?.activeRoute?.providerId;
|
|
137
|
-
return isProviderId(providerId) && isProviderRoutableInCodexa(providerId)
|
|
153
|
+
return isProviderId(providerId) && providerId !== "google" && isProviderRoutableInCodexa(providerId)
|
|
138
154
|
? providerId
|
|
139
155
|
: DEFAULT_PROVIDER_ID;
|
|
140
156
|
}
|
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
export type ProviderId = "openai" | "anthropic" | "google" | "local";
|
|
1
|
+
export type ProviderId = "openai" | "anthropic" | "google" | "local" | "antigravity";
|
|
2
2
|
|
|
3
3
|
export type ProviderBackendType =
|
|
4
|
-
| "codex-cli-auth"
|
|
5
|
-
| "gemini-cli-auth"
|
|
6
|
-
| "claude-code-auth"
|
|
7
|
-
| "
|
|
4
|
+
| "codex-cli-auth"
|
|
5
|
+
| "gemini-cli-auth"
|
|
6
|
+
| "claude-code-auth"
|
|
7
|
+
| "antigravity-cli-auth"
|
|
8
|
+
| "openai-api-key"
|
|
8
9
|
| "gemini-api-key"
|
|
9
10
|
| "anthropic-api-key"
|
|
10
11
|
| "local-openai-compatible"
|
|
@@ -69,10 +70,11 @@ export interface ProviderWorkspaceOverride {
|
|
|
69
70
|
defaultModel?: string;
|
|
70
71
|
models?: Record<string, ProviderModelWorkspaceOverride>;
|
|
71
72
|
command?: string | ProviderLaunchCommand | null;
|
|
72
|
-
claudeCommandPath?: string;
|
|
73
|
-
geminiCommandPath?: string;
|
|
74
|
-
codexCommandPath?: string;
|
|
75
|
-
|
|
73
|
+
claudeCommandPath?: string;
|
|
74
|
+
geminiCommandPath?: string;
|
|
75
|
+
codexCommandPath?: string;
|
|
76
|
+
antigravityCommandPath?: string;
|
|
77
|
+
}
|
|
76
78
|
|
|
77
79
|
export interface ProviderModelWorkspaceOverride {
|
|
78
80
|
contextLength?: number;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { existsSync, mkdirSync, readFileSync, renameSync, writeFileSync } from "fs";
|
|
2
2
|
import { dirname, join } from "path";
|
|
3
3
|
import { DEFAULT_MODEL } from "../../config/settings.js";
|
|
4
|
-
import { normalizeWorkspaceRoot } from "../workspaceRoot.js";
|
|
4
|
+
import { normalizeWorkspaceRoot } from "../workspace/workspaceRoot.js";
|
|
5
5
|
import { isKnownProviderId } from "./registry.js";
|
|
6
6
|
import { getDefaultRouteModel, getProviderRuntime, isProviderRouteConfigured, isProviderRoutableInCodexa } from "../providerRuntime/registry.js";
|
|
7
7
|
import { normalizeGeminiModelId } from "../providerRuntime/models.js";
|
|
@@ -13,8 +13,9 @@ import type {
|
|
|
13
13
|
ProviderWorkspaceOverride,
|
|
14
14
|
} from "./types.js";
|
|
15
15
|
|
|
16
|
-
const DEPRECATED_ANTIGRAVITY_PROVIDER_ID = "antigravity";
|
|
17
|
-
const DEPRECATED_ANTIGRAVITY_BACKENDS = new Set(["antigravity-cli-auth", "agy"]);
|
|
16
|
+
const DEPRECATED_ANTIGRAVITY_PROVIDER_ID = "antigravity";
|
|
17
|
+
const DEPRECATED_ANTIGRAVITY_BACKENDS = new Set(["antigravity-cli-auth", "agy"]);
|
|
18
|
+
const DEPRECATED_GOOGLE_PROVIDER_ID = "google";
|
|
18
19
|
|
|
19
20
|
export function getProviderWorkspaceConfigFile(workspaceRoot: string): string {
|
|
20
21
|
return join(normalizeWorkspaceRoot(workspaceRoot), ".codexa", "providers.json");
|
|
@@ -28,16 +29,20 @@ function isDeprecatedAntigravityProviderId(value: unknown): boolean {
|
|
|
28
29
|
return value === DEPRECATED_ANTIGRAVITY_PROVIDER_ID;
|
|
29
30
|
}
|
|
30
31
|
|
|
31
|
-
function isDeprecatedAntigravityRoute(value: unknown): boolean {
|
|
32
|
+
function isDeprecatedAntigravityRoute(value: unknown): boolean {
|
|
32
33
|
if (!isRecord(value)) return false;
|
|
33
34
|
return isDeprecatedAntigravityProviderId(value.providerId ?? value.provider_id)
|
|
34
35
|
|| DEPRECATED_ANTIGRAVITY_BACKENDS.has(String(value.backendKind ?? value.backend_kind));
|
|
35
|
-
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function isDeprecatedGoogleRoute(value: unknown): boolean {
|
|
39
|
+
return isRecord(value) && (value.providerId ?? value.provider_id) === DEPRECATED_GOOGLE_PROVIDER_ID;
|
|
40
|
+
}
|
|
36
41
|
|
|
37
42
|
function resolveDeprecatedProviderFallback(
|
|
38
43
|
providers: Partial<Record<ProviderId, ProviderWorkspaceOverride>>,
|
|
39
44
|
): ProviderId {
|
|
40
|
-
const candidates: readonly ProviderId[] = ["openai", "
|
|
45
|
+
const candidates: readonly ProviderId[] = ["openai", "anthropic", "local"];
|
|
41
46
|
return candidates.find((providerId) =>
|
|
42
47
|
isProviderRoutableInCodexa(providerId)
|
|
43
48
|
&& (providerId === "openai" || providers[providerId] !== undefined || isProviderRouteConfigured(providerId))
|
|
@@ -214,22 +219,24 @@ function parseActiveRoute(value: unknown): ProviderActiveRoute | undefined {
|
|
|
214
219
|
export function parseProviderWorkspaceConfig(data: unknown): ProviderWorkspaceConfig {
|
|
215
220
|
if (!isRecord(data)) return {};
|
|
216
221
|
|
|
217
|
-
const config: ProviderWorkspaceConfig = {};
|
|
218
|
-
const providers: Partial<Record<ProviderId, ProviderWorkspaceOverride>> = {};
|
|
219
|
-
let foundDeprecatedAntigravity = false;
|
|
222
|
+
const config: ProviderWorkspaceConfig = {};
|
|
223
|
+
const providers: Partial<Record<ProviderId, ProviderWorkspaceOverride>> = {};
|
|
224
|
+
let foundDeprecatedAntigravity = false;
|
|
225
|
+
let foundDeprecatedGoogle = false;
|
|
220
226
|
|
|
221
227
|
if (isRecord(data.providers)) {
|
|
222
228
|
for (const [id, value] of Object.entries(data.providers)) {
|
|
223
|
-
if (isDeprecatedAntigravityProviderId(id)) {
|
|
224
|
-
foundDeprecatedAntigravity = true;
|
|
225
|
-
continue;
|
|
226
|
-
}
|
|
227
|
-
if (
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
229
|
+
if (isDeprecatedAntigravityProviderId(id)) {
|
|
230
|
+
foundDeprecatedAntigravity = true;
|
|
231
|
+
continue;
|
|
232
|
+
}
|
|
233
|
+
if (id === DEPRECATED_GOOGLE_PROVIDER_ID) {
|
|
234
|
+
foundDeprecatedGoogle = true;
|
|
235
|
+
continue;
|
|
236
|
+
}
|
|
237
|
+
if (!isKnownProviderId(id)) continue;
|
|
238
|
+
const override = parseProviderOverride(value);
|
|
239
|
+
if (override) providers[id] = override;
|
|
233
240
|
}
|
|
234
241
|
config.providers = providers;
|
|
235
242
|
}
|
|
@@ -238,7 +245,10 @@ export function parseProviderWorkspaceConfig(data: unknown): ProviderWorkspaceCo
|
|
|
238
245
|
?? data.workspace_default_provider_id
|
|
239
246
|
?? data.defaultProviderId
|
|
240
247
|
?? data.default_provider_id;
|
|
241
|
-
if (
|
|
248
|
+
if (defaultProvider === DEPRECATED_GOOGLE_PROVIDER_ID) {
|
|
249
|
+
foundDeprecatedGoogle = true;
|
|
250
|
+
config.workspaceDefaultProviderId = resolveDeprecatedProviderFallback(providers);
|
|
251
|
+
} else if (isDeprecatedAntigravityProviderId(defaultProvider)) {
|
|
242
252
|
foundDeprecatedAntigravity = true;
|
|
243
253
|
config.workspaceDefaultProviderId = resolveDeprecatedProviderFallback(providers);
|
|
244
254
|
} else if (typeof defaultProvider === "string" && isKnownProviderId(defaultProvider)) {
|
|
@@ -246,7 +256,12 @@ export function parseProviderWorkspaceConfig(data: unknown): ProviderWorkspaceCo
|
|
|
246
256
|
}
|
|
247
257
|
|
|
248
258
|
const rawActiveRoute = data.activeRoute ?? data.active_route;
|
|
249
|
-
if (
|
|
259
|
+
if (isDeprecatedGoogleRoute(rawActiveRoute)) {
|
|
260
|
+
foundDeprecatedGoogle = true;
|
|
261
|
+
const fallbackProviderId = resolveDeprecatedProviderFallback(providers);
|
|
262
|
+
config.activeRoute = createFallbackActiveRoute(fallbackProviderId, providers);
|
|
263
|
+
config.workspaceDefaultProviderId ??= fallbackProviderId;
|
|
264
|
+
} else if (isDeprecatedAntigravityRoute(rawActiveRoute)) {
|
|
250
265
|
foundDeprecatedAntigravity = true;
|
|
251
266
|
const fallbackProviderId = resolveDeprecatedProviderFallback(providers);
|
|
252
267
|
config.activeRoute = createFallbackActiveRoute(fallbackProviderId, providers);
|
|
@@ -258,12 +273,12 @@ export function parseProviderWorkspaceConfig(data: unknown): ProviderWorkspaceCo
|
|
|
258
273
|
}
|
|
259
274
|
}
|
|
260
275
|
|
|
261
|
-
if (foundDeprecatedAntigravity) {
|
|
276
|
+
if (foundDeprecatedGoogle || foundDeprecatedAntigravity) {
|
|
262
277
|
const revertedProviderId = config.activeRoute?.providerId
|
|
263
278
|
?? config.workspaceDefaultProviderId
|
|
264
279
|
?? resolveDeprecatedProviderFallback(providers);
|
|
265
280
|
config.migrationNotice = {
|
|
266
|
-
deprecatedProviderId: DEPRECATED_ANTIGRAVITY_PROVIDER_ID,
|
|
281
|
+
deprecatedProviderId: foundDeprecatedGoogle ? DEPRECATED_GOOGLE_PROVIDER_ID : DEPRECATED_ANTIGRAVITY_PROVIDER_ID,
|
|
267
282
|
revertedProviderId,
|
|
268
283
|
};
|
|
269
284
|
}
|
|
@@ -348,13 +363,13 @@ export function saveProviderWorkspaceConfig(workspaceRoot: string, config: Provi
|
|
|
348
363
|
renameSync(tmpFile, filePath);
|
|
349
364
|
}
|
|
350
365
|
|
|
351
|
-
export function setProviderWorkspaceDefault(
|
|
366
|
+
export function setProviderWorkspaceDefault(
|
|
352
367
|
config: ProviderWorkspaceConfig,
|
|
353
368
|
providerId: ProviderId,
|
|
354
369
|
): ProviderWorkspaceConfig {
|
|
355
370
|
return {
|
|
356
371
|
...config,
|
|
357
|
-
workspaceDefaultProviderId: providerId,
|
|
372
|
+
workspaceDefaultProviderId: providerId === DEPRECATED_GOOGLE_PROVIDER_ID ? "openai" : providerId,
|
|
358
373
|
};
|
|
359
374
|
}
|
|
360
375
|
|
|
@@ -396,7 +411,7 @@ export function setProviderActiveRoute(
|
|
|
396
411
|
config: ProviderWorkspaceConfig,
|
|
397
412
|
activeRoute: ProviderActiveRoute,
|
|
398
413
|
): ProviderWorkspaceConfig {
|
|
399
|
-
if (!isProviderRoutableInCodexa(activeRoute.providerId) || !isProviderRouteConfigured(activeRoute.providerId)) {
|
|
414
|
+
if (activeRoute.providerId === DEPRECATED_GOOGLE_PROVIDER_ID || !isProviderRoutableInCodexa(activeRoute.providerId) || !isProviderRouteConfigured(activeRoute.providerId)) {
|
|
400
415
|
return config;
|
|
401
416
|
}
|
|
402
417
|
|