@golba98/codexa 1.0.3 → 1.0.5
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 +17 -18
- package/bin/codexa.js +62 -144
- package/package.json +4 -3
- package/src/app.tsx +642 -303
- package/src/commands/handler.ts +7 -18
- package/src/config/buildInfo.ts +2 -2
- package/src/config/layeredConfig.ts +1 -1
- package/src/config/runtimeConfig.ts +1 -1
- package/src/config/settings.ts +1 -1
- package/src/config/trustStore.ts +1 -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/executableResolver.ts +5 -1
- package/src/core/models/codexModelCapabilities.ts +57 -4
- package/src/core/models/codexModelsCacheSeed.ts +153 -0
- package/src/core/models/providerModelCache.ts +106 -0
- package/src/core/perf/renderDebug.ts +10 -6
- package/src/core/process/CommandRunner.ts +12 -1
- package/src/core/providerLauncher/registry.ts +64 -18
- package/src/core/providerLauncher/types.ts +12 -9
- package/src/core/providerLauncher/workspaceConfig.ts +41 -26
- package/src/core/providerRuntime/anthropic.ts +10 -6
- package/src/core/providerRuntime/antigravity.ts +461 -0
- package/src/core/providerRuntime/claudeCodeDiscovery.ts +724 -446
- 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/mistralVibe.ts +663 -0
- package/src/core/providerRuntime/models.ts +40 -15
- package/src/core/providerRuntime/reasoning.ts +9 -6
- package/src/core/providerRuntime/registry.ts +76 -4
- package/src/core/providerRuntime/types.ts +20 -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/{channel.ts → version/channel.ts} +1 -1
- package/src/core/{updateCheck.ts → version/updateCheck.ts} +10 -5
- package/src/core/{launchContext.ts → workspace/launchContext.ts} +9 -16
- 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 +66 -98
- 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 +1 -1
- package/src/test/runtimeTestUtils.ts +90 -0
- package/src/ui/{ActivityBars.tsx → chrome/ActivityBars.tsx} +1 -1
- package/src/ui/{ActivityIndicator.tsx → chrome/ActivityIndicator.tsx} +3 -3
- package/src/ui/{AnimatedStatusText.tsx → chrome/AnimatedStatusText.tsx} +3 -3
- package/src/ui/chrome/AppShell.tsx +672 -0
- package/src/ui/{BottomComposer.tsx → chrome/BottomComposer.tsx} +159 -158
- package/src/ui/{DashCard.tsx → chrome/DashCard.tsx} +2 -2
- package/src/ui/{RunFooter.tsx → chrome/RunFooter.tsx} +3 -3
- package/src/ui/chrome/RuntimeStatusBar.tsx +108 -0
- package/src/ui/{Spinner.tsx → chrome/Spinner.tsx} +1 -1
- package/src/ui/{TopHeader.tsx → chrome/TopHeader.tsx} +54 -38
- package/src/ui/{UpdateAvailableCard.tsx → chrome/UpdateAvailableCard.tsx} +5 -5
- package/src/ui/{commandNormalize.ts → input/commandNormalize.ts} +1 -1
- package/src/ui/{focus.ts → input/focus.ts} +1 -1
- package/src/ui/{inputBuffer.ts → input/inputBuffer.ts} +3 -3
- package/src/ui/layout.ts +298 -24
- package/src/ui/{AttachmentImportPanel.tsx → panels/AttachmentImportPanel.tsx} +3 -3
- package/src/ui/{AuthPanel.tsx → panels/AuthPanel.tsx} +5 -5
- package/src/ui/{BackendPicker.tsx → panels/BackendPicker.tsx} +2 -2
- package/src/ui/{ModePicker.tsx → panels/ModePicker.tsx} +2 -2
- package/src/ui/{ModelPicker.tsx → panels/ModelPicker.tsx} +2 -2
- package/src/ui/{ModelPickerScreen.tsx → panels/ModelPickerScreen.tsx} +224 -42
- package/src/ui/{ModelReasoningPicker.tsx → panels/ModelReasoningPicker.tsx} +5 -5
- package/src/ui/{Panel.tsx → panels/Panel.tsx} +1 -1
- package/src/ui/{PermissionsPanel.tsx → panels/PermissionsPanel.tsx} +3 -3
- package/src/ui/{PlanActionPicker.tsx → panels/PlanActionPicker.tsx} +2 -2
- package/src/ui/{PlanReviewPanel.tsx → panels/PlanReviewPanel.tsx} +5 -5
- package/src/ui/panels/ProviderPicker.tsx +737 -0
- package/src/ui/{ReasoningPicker.tsx → panels/ReasoningPicker.tsx} +3 -3
- package/src/ui/{SelectionPanel.tsx → panels/SelectionPanel.tsx} +5 -1
- package/src/ui/{SettingsPanel.tsx → panels/SettingsPanel.tsx} +4 -4
- package/src/ui/{TextEntryPanel.tsx → panels/TextEntryPanel.tsx} +4 -4
- package/src/ui/{ThemePicker.tsx → panels/ThemePicker.tsx} +2 -2
- package/src/ui/{UpdatePromptPanel.tsx → panels/UpdatePromptPanel.tsx} +17 -23
- package/src/ui/{Markdown.tsx → render/Markdown.tsx} +2 -2
- package/src/ui/{diffRenderer.ts → render/diffRenderer.ts} +1 -1
- package/src/ui/{logoVariants.ts → render/logoVariants.ts} +4 -8
- package/src/ui/{modeDisplay.ts → render/modeDisplay.ts} +2 -2
- package/src/ui/{outputPipeline.ts → render/outputPipeline.ts} +2 -2
- package/src/ui/{runtimeDisplay.ts → render/runtimeDisplay.ts} +23 -10
- package/src/ui/{textLayout.ts → render/textLayout.ts} +15 -4
- package/src/ui/{ActionRequiredBlock.tsx → timeline/ActionRequiredBlock.tsx} +3 -3
- package/src/ui/{AgentBlock.tsx → timeline/AgentBlock.tsx} +10 -10
- package/src/ui/{StaticIntroItem.tsx → timeline/StaticIntroItem.tsx} +2 -2
- package/src/ui/{ThinkingBlock.tsx → timeline/ThinkingBlock.tsx} +4 -4
- package/src/ui/{Timeline.tsx → timeline/Timeline.tsx} +1620 -1471
- package/src/ui/timeline/TranscriptShell.tsx +322 -0
- package/src/ui/{TurnGroup.tsx → timeline/TurnGroup.tsx} +15 -15
- package/src/ui/timeline/layoutListWindow.ts +145 -0
- package/src/ui/{progressEntries.ts → timeline/progressEntries.ts} +3 -3
- package/src/ui/{runActivityView.ts → timeline/runActivityView.ts} +1 -1
- package/src/ui/{timelineMeasure.ts → timeline/timelineMeasure.ts} +206 -134
- package/src/core/codex.ts +0 -124
- package/src/ui/AppShell.tsx +0 -706
- package/src/ui/ProviderPicker.tsx +0 -321
- package/src/ui/StaticTranscriptItem.tsx +0 -56
- /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
- /package/src/ui/{busyStatusAnimation.ts → chrome/busyStatusAnimation.ts} +0 -0
- /package/src/ui/{slashCommands.ts → input/slashCommands.ts} +0 -0
- /package/src/ui/{terminalAnswerFormat.ts → render/terminalAnswerFormat.ts} +0 -0
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
2
|
+
import { homedir } from "node:os";
|
|
3
|
+
import { join } from "node:path";
|
|
4
|
+
import { formatReasoningLabel } from "../../config/settings.js";
|
|
5
|
+
import type { ProviderModel } from "../providerRuntime/types.js";
|
|
6
|
+
import type {
|
|
7
|
+
CodexModelCapabilities,
|
|
8
|
+
CodexModelCapability,
|
|
9
|
+
ReasoningEffortCapability,
|
|
10
|
+
} from "./codexModelCapabilities.js";
|
|
11
|
+
import { loadCachedProviderModels, type CachedProviderModels } from "./providerModelCache.js";
|
|
12
|
+
|
|
13
|
+
// The codex CLI maintains its own model catalog cache with slugs, labels and
|
|
14
|
+
// reasoning levels. Reading it seeds Codexa's OpenAI model list instantly —
|
|
15
|
+
// no subprocess — and stays current because the codex CLI refreshes the file
|
|
16
|
+
// on its own runs.
|
|
17
|
+
// Resolved per call from env (matching claudeCodeDiscovery) so HOME
|
|
18
|
+
// redirection in tests holds — Bun's homedir() ignores runtime HOME changes.
|
|
19
|
+
export function getCodexModelsCacheFile(): string {
|
|
20
|
+
const home = process.env.USERPROFILE ?? process.env.HOME ?? homedir();
|
|
21
|
+
return join(home, ".codex", "models_cache.json");
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
interface CodexSeed {
|
|
25
|
+
fetchedAt: number;
|
|
26
|
+
models: readonly ProviderModel[];
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
function isRecord(value: unknown): value is Record<string, unknown> {
|
|
30
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function asString(value: unknown): string | null {
|
|
34
|
+
return typeof value === "string" && value.trim().length > 0 ? value.trim() : null;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function parseReasoningLevels(raw: unknown): readonly ReasoningEffortCapability[] | null {
|
|
38
|
+
if (!Array.isArray(raw)) {
|
|
39
|
+
return null;
|
|
40
|
+
}
|
|
41
|
+
const levels = raw
|
|
42
|
+
.map((entry): ReasoningEffortCapability | null => {
|
|
43
|
+
if (!isRecord(entry)) {
|
|
44
|
+
return null;
|
|
45
|
+
}
|
|
46
|
+
const id = asString(entry.effort);
|
|
47
|
+
if (!id) {
|
|
48
|
+
return null;
|
|
49
|
+
}
|
|
50
|
+
return { id, label: formatReasoningLabel(id), description: asString(entry.description) };
|
|
51
|
+
})
|
|
52
|
+
.filter((entry): entry is ReasoningEffortCapability => entry !== null);
|
|
53
|
+
return levels.length > 0 ? levels : null;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
function parseSeedModel(raw: unknown): ProviderModel | null {
|
|
57
|
+
if (!isRecord(raw)) {
|
|
58
|
+
return null;
|
|
59
|
+
}
|
|
60
|
+
// Models with visibility "hide" are internal codex routes (e.g. auto-review).
|
|
61
|
+
if (asString(raw.visibility) === "hide") {
|
|
62
|
+
return null;
|
|
63
|
+
}
|
|
64
|
+
const modelId = asString(raw.slug);
|
|
65
|
+
if (!modelId) {
|
|
66
|
+
return null;
|
|
67
|
+
}
|
|
68
|
+
return {
|
|
69
|
+
id: modelId,
|
|
70
|
+
modelId,
|
|
71
|
+
label: asString(raw.display_name) ?? modelId,
|
|
72
|
+
description: asString(raw.description),
|
|
73
|
+
defaultReasoningLevel: asString(raw.default_reasoning_level),
|
|
74
|
+
supportedReasoningLevels: parseReasoningLevels(raw.supported_reasoning_levels),
|
|
75
|
+
source: "discovered",
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
export function loadCodexSeedModels(cacheFile = getCodexModelsCacheFile()): CodexSeed | null {
|
|
80
|
+
try {
|
|
81
|
+
if (!existsSync(cacheFile)) {
|
|
82
|
+
return null;
|
|
83
|
+
}
|
|
84
|
+
const parsed: unknown = JSON.parse(readFileSync(cacheFile, "utf8"));
|
|
85
|
+
if (!isRecord(parsed) || !Array.isArray(parsed.models)) {
|
|
86
|
+
return null;
|
|
87
|
+
}
|
|
88
|
+
const models = parsed.models
|
|
89
|
+
.map(parseSeedModel)
|
|
90
|
+
.filter((model): model is ProviderModel => model !== null);
|
|
91
|
+
if (models.length === 0) {
|
|
92
|
+
return null;
|
|
93
|
+
}
|
|
94
|
+
const fetchedAtRaw = asString(parsed.fetched_at);
|
|
95
|
+
const fetchedAt = fetchedAtRaw ? Date.parse(fetchedAtRaw) : Number.NaN;
|
|
96
|
+
return { fetchedAt: Number.isFinite(fetchedAt) ? fetchedAt : 0, models };
|
|
97
|
+
} catch {
|
|
98
|
+
return null;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// Freshest locally known OpenAI models without spawning a subprocess:
|
|
103
|
+
// codex's own cache file vs Codexa's persisted last-good discovery.
|
|
104
|
+
export function loadSeededOpenAiModels(options: {
|
|
105
|
+
codexCacheFile?: string;
|
|
106
|
+
providerCacheFile?: string;
|
|
107
|
+
} = {}): CachedProviderModels | null {
|
|
108
|
+
const seed = loadCodexSeedModels(options.codexCacheFile);
|
|
109
|
+
const persisted = options.providerCacheFile === undefined
|
|
110
|
+
? loadCachedProviderModels("openai")
|
|
111
|
+
: loadCachedProviderModels("openai", options.providerCacheFile);
|
|
112
|
+
if (seed && (!persisted || seed.fetchedAt >= persisted.discoveredAt)) {
|
|
113
|
+
return { discoveredAt: seed.fetchedAt, models: seed.models };
|
|
114
|
+
}
|
|
115
|
+
return persisted;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
function toCapability(model: ProviderModel, index: number): CodexModelCapability {
|
|
119
|
+
return {
|
|
120
|
+
id: model.id,
|
|
121
|
+
model: model.modelId,
|
|
122
|
+
label: model.label,
|
|
123
|
+
description: model.description,
|
|
124
|
+
available: true,
|
|
125
|
+
hidden: false,
|
|
126
|
+
isDefault: index === 0,
|
|
127
|
+
defaultReasoningLevel: model.defaultReasoningLevel,
|
|
128
|
+
supportedReasoningLevels: model.supportedReasoningLevels,
|
|
129
|
+
reasoningLevelCount: model.supportedReasoningLevels ? model.supportedReasoningLevels.length : null,
|
|
130
|
+
source: "runtime",
|
|
131
|
+
raw: model,
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
// Capabilities for the OpenAI picker sourced purely from local caches.
|
|
136
|
+
// Returns null when nothing is cached yet (first ever launch).
|
|
137
|
+
export function loadSeededCodexCapabilities(options: {
|
|
138
|
+
codexCacheFile?: string;
|
|
139
|
+
providerCacheFile?: string;
|
|
140
|
+
} = {}): CodexModelCapabilities | null {
|
|
141
|
+
const seeded = loadSeededOpenAiModels(options);
|
|
142
|
+
if (!seeded) {
|
|
143
|
+
return null;
|
|
144
|
+
}
|
|
145
|
+
return {
|
|
146
|
+
status: "ready",
|
|
147
|
+
source: "runtime",
|
|
148
|
+
models: seeded.models.map(toCapability),
|
|
149
|
+
discoveredAt: seeded.discoveredAt,
|
|
150
|
+
executable: null,
|
|
151
|
+
error: null,
|
|
152
|
+
};
|
|
153
|
+
}
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import { existsSync, readFileSync, writeFileSync } from "node:fs";
|
|
2
|
+
import { homedir } from "node:os";
|
|
3
|
+
import { join } from "node:path";
|
|
4
|
+
import type { ProviderId } from "../providerLauncher/types.js";
|
|
5
|
+
import type { ProviderModel } from "../providerRuntime/types.js";
|
|
6
|
+
|
|
7
|
+
// Persistent last-good model discovery results, one entry per provider.
|
|
8
|
+
// Lets pickers open instantly with the previous session's discovered models
|
|
9
|
+
// while a background refresh runs. Corrupt or missing cache degrades to null.
|
|
10
|
+
// Resolved per call from env (matching claudeCodeDiscovery) so HOME
|
|
11
|
+
// redirection in tests holds — Bun's homedir() ignores runtime HOME changes.
|
|
12
|
+
export function getProviderModelCacheFile(): string {
|
|
13
|
+
const home = process.env.USERPROFILE ?? process.env.HOME ?? homedir();
|
|
14
|
+
return join(home, ".codexa-model-cache.json");
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const CACHE_VERSION = 1;
|
|
18
|
+
|
|
19
|
+
export interface CachedProviderModels {
|
|
20
|
+
discoveredAt: number;
|
|
21
|
+
models: readonly ProviderModel[];
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
interface ProviderModelCacheFile {
|
|
25
|
+
version: number;
|
|
26
|
+
providers: Partial<Record<ProviderId, CachedProviderModels>>;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
function readCacheFile(cacheFile: string): ProviderModelCacheFile | null {
|
|
30
|
+
try {
|
|
31
|
+
if (!existsSync(cacheFile)) {
|
|
32
|
+
return null;
|
|
33
|
+
}
|
|
34
|
+
const parsed: unknown = JSON.parse(readFileSync(cacheFile, "utf8"));
|
|
35
|
+
if (
|
|
36
|
+
typeof parsed !== "object" || parsed === null || Array.isArray(parsed)
|
|
37
|
+
|| (parsed as ProviderModelCacheFile).version !== CACHE_VERSION
|
|
38
|
+
|| typeof (parsed as ProviderModelCacheFile).providers !== "object"
|
|
39
|
+
|| (parsed as ProviderModelCacheFile).providers === null
|
|
40
|
+
) {
|
|
41
|
+
return null;
|
|
42
|
+
}
|
|
43
|
+
return parsed as ProviderModelCacheFile;
|
|
44
|
+
} catch {
|
|
45
|
+
return null;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// A model id is passed straight to a provider CLI, so it must be a bare token.
|
|
50
|
+
// Discovery scrapes CLI output, and a buggy build can bake an ANSI escape into
|
|
51
|
+
// an id (e.g. "claude-fable-5\x1b[1m"). Reject rather than repair: a cached id
|
|
52
|
+
// we cannot vouch for is dropped so discovery re-probes for a clean one.
|
|
53
|
+
const VALID_MODEL_ID = /^[A-Za-z0-9._:\/-]+$/;
|
|
54
|
+
|
|
55
|
+
function isUsableModel(model: unknown): model is ProviderModel {
|
|
56
|
+
if (typeof model !== "object" || model === null) {
|
|
57
|
+
return false;
|
|
58
|
+
}
|
|
59
|
+
const candidate = model as ProviderModel;
|
|
60
|
+
return typeof candidate.id === "string"
|
|
61
|
+
&& typeof candidate.modelId === "string"
|
|
62
|
+
&& typeof candidate.label === "string"
|
|
63
|
+
&& VALID_MODEL_ID.test(candidate.id)
|
|
64
|
+
&& VALID_MODEL_ID.test(candidate.modelId);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
function isValidEntry(entry: unknown): entry is CachedProviderModels {
|
|
68
|
+
if (typeof entry !== "object" || entry === null) {
|
|
69
|
+
return false;
|
|
70
|
+
}
|
|
71
|
+
const candidate = entry as CachedProviderModels;
|
|
72
|
+
return typeof candidate.discoveredAt === "number" && Array.isArray(candidate.models);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
export function loadCachedProviderModels(
|
|
76
|
+
providerId: ProviderId,
|
|
77
|
+
cacheFile = getProviderModelCacheFile(),
|
|
78
|
+
): CachedProviderModels | null {
|
|
79
|
+
const cache = readCacheFile(cacheFile);
|
|
80
|
+
const entry = cache?.providers?.[providerId];
|
|
81
|
+
if (!entry || !isValidEntry(entry)) {
|
|
82
|
+
return null;
|
|
83
|
+
}
|
|
84
|
+
const models = entry.models.filter(isUsableModel);
|
|
85
|
+
if (models.length === 0) {
|
|
86
|
+
return null;
|
|
87
|
+
}
|
|
88
|
+
return { discoveredAt: entry.discoveredAt, models };
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
export function saveCachedProviderModels(
|
|
92
|
+
providerId: ProviderId,
|
|
93
|
+
entry: CachedProviderModels,
|
|
94
|
+
cacheFile = getProviderModelCacheFile(),
|
|
95
|
+
): void {
|
|
96
|
+
if (entry.models.length === 0) {
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
try {
|
|
100
|
+
const cache = readCacheFile(cacheFile) ?? { version: CACHE_VERSION, providers: {} };
|
|
101
|
+
cache.providers[providerId] = entry;
|
|
102
|
+
writeFileSync(cacheFile, `${JSON.stringify(cache, null, 2)}\n`, "utf8");
|
|
103
|
+
} catch {
|
|
104
|
+
// Persistence is best-effort; discovery still works without it.
|
|
105
|
+
}
|
|
106
|
+
}
|
|
@@ -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
|
}
|
|
@@ -9,6 +9,7 @@ export interface CommandSpec {
|
|
|
9
9
|
cwd: string;
|
|
10
10
|
env?: NodeJS.ProcessEnv;
|
|
11
11
|
timeoutMs?: number;
|
|
12
|
+
stdinData?: string;
|
|
12
13
|
}
|
|
13
14
|
|
|
14
15
|
export interface CommandResult {
|
|
@@ -177,10 +178,20 @@ function runProcess(
|
|
|
177
178
|
cwd: spec.cwd,
|
|
178
179
|
env: spec.env,
|
|
179
180
|
shell: false,
|
|
180
|
-
stdio: ["ignore", "pipe", "pipe"],
|
|
181
|
+
stdio: [spec.stdinData !== undefined ? "pipe" : "ignore", "pipe", "pipe"],
|
|
181
182
|
});
|
|
182
183
|
handlers.onProcessLifecycle?.("spawned");
|
|
183
184
|
|
|
185
|
+
if (spec.stdinData !== undefined) {
|
|
186
|
+
try {
|
|
187
|
+
child.stdin?.on("error", () => { /* EPIPE when the process exits before reading stdin */ });
|
|
188
|
+
child.stdin?.write(spec.stdinData);
|
|
189
|
+
child.stdin?.end();
|
|
190
|
+
} catch {
|
|
191
|
+
// stdin already closed; the close/error handlers report the outcome
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
|
|
184
195
|
const result = new Promise<CommandResult>((resolve) => {
|
|
185
196
|
const finish = (partial: Omit<CommandResult, "stdout" | "stderr" | "startedAt" | "endedAt" | "durationMs" | "userMessage"> & { endedAt?: number }) => {
|
|
186
197
|
if (timeoutHandle) clearTimeout(timeoutHandle);
|
|
@@ -14,12 +14,17 @@ 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 { discoverMistralVibeModels } from "../providerRuntime/mistralVibe.js";
|
|
20
|
+
import { setLocalProviderConfig } from "../providerRuntime/local.js";
|
|
19
21
|
import { formatContextLength, resolveModelContextLengthCached } from "../providerRuntime/contextMetadata.js";
|
|
20
22
|
import { resolveModelCapabilityProfileCached } from "../providerRuntime/capabilityProfile.js";
|
|
21
23
|
|
|
22
|
-
|
|
24
|
+
// Google/Gemini remains a recognized legacy config value so existing workspace
|
|
25
|
+
// files can be migrated, but it is no longer a selectable Codexa provider.
|
|
26
|
+
const PROVIDER_ORDER: readonly ProviderId[] = ["openai", "anthropic", "mistral", "local", "antigravity"];
|
|
27
|
+
const KNOWN_PROVIDER_IDS: readonly ProviderId[] = ["openai", "anthropic", "google", "mistral", "local", "antigravity"];
|
|
23
28
|
|
|
24
29
|
const DEFAULT_PROVIDER_ID: ProviderId = "openai";
|
|
25
30
|
|
|
@@ -63,8 +68,8 @@ const DEFAULT_PROVIDERS: Record<ProviderId, ProviderDefault> = {
|
|
|
63
68
|
isActiveRoute: false,
|
|
64
69
|
routeUnavailableReason: null,
|
|
65
70
|
},
|
|
66
|
-
local: {
|
|
67
|
-
id: "local",
|
|
71
|
+
local: {
|
|
72
|
+
id: "local",
|
|
68
73
|
displayName: "Local",
|
|
69
74
|
currentModel: () => "Local default",
|
|
70
75
|
backendType: "local-openai-compatible",
|
|
@@ -72,12 +77,34 @@ const DEFAULT_PROVIDERS: Record<ProviderId, ProviderDefault> = {
|
|
|
72
77
|
enabled: false,
|
|
73
78
|
launchCommand: null,
|
|
74
79
|
isActiveRoute: false,
|
|
75
|
-
routeUnavailableReason: "Local provider unavailable. Start LM Studio, load a model, and enable the local server.",
|
|
80
|
+
routeUnavailableReason: "Local provider unavailable. Start LM Studio, load a model, and enable the local server.",
|
|
81
|
+
},
|
|
82
|
+
mistral: {
|
|
83
|
+
id: "mistral",
|
|
84
|
+
displayName: "Mistral Vibe CLI",
|
|
85
|
+
currentModel: () => "Vibe default",
|
|
86
|
+
backendType: "mistral-vibe-cli-auth",
|
|
87
|
+
routeMode: "in-codexa",
|
|
88
|
+
enabled: true,
|
|
89
|
+
launchCommand: { executable: "vibe", args: [] },
|
|
90
|
+
isActiveRoute: false,
|
|
91
|
+
routeUnavailableReason: null,
|
|
76
92
|
},
|
|
77
|
-
|
|
93
|
+
antigravity: {
|
|
94
|
+
id: "antigravity",
|
|
95
|
+
displayName: "Antigravity",
|
|
96
|
+
currentModel: () => ANTIGRAVITY_DEFAULT_MODEL_ID,
|
|
97
|
+
backendType: "antigravity-cli-auth",
|
|
98
|
+
routeMode: "in-codexa",
|
|
99
|
+
enabled: true,
|
|
100
|
+
launchCommand: { executable: "agy", args: [] },
|
|
101
|
+
isActiveRoute: false,
|
|
102
|
+
routeUnavailableReason: null,
|
|
103
|
+
},
|
|
104
|
+
};
|
|
78
105
|
|
|
79
|
-
function isProviderId(value: unknown): value is ProviderId {
|
|
80
|
-
return typeof value === "string" &&
|
|
106
|
+
function isProviderId(value: unknown): value is ProviderId {
|
|
107
|
+
return typeof value === "string" && KNOWN_PROVIDER_IDS.includes(value as ProviderId);
|
|
81
108
|
}
|
|
82
109
|
|
|
83
110
|
function normalizeLaunchCommand(value: ProviderWorkspaceOverride["command"] | undefined): ProviderLaunchCommand | null | undefined {
|
|
@@ -122,25 +149,29 @@ function applyOverride(
|
|
|
122
149
|
: provider.currentModel,
|
|
123
150
|
enabled: nextEnabled,
|
|
124
151
|
launchCommand: nextCommand,
|
|
125
|
-
statusLabel: nextEnabled
|
|
126
|
-
?
|
|
127
|
-
: "
|
|
152
|
+
statusLabel: !nextEnabled
|
|
153
|
+
? "Disabled"
|
|
154
|
+
: provider.routeMode === "launch-only"
|
|
155
|
+
? provider.statusLabel
|
|
156
|
+
: (provider.routeUnavailableReason ? "Needs config" : "Enabled"),
|
|
128
157
|
};
|
|
129
158
|
}
|
|
130
159
|
|
|
131
|
-
export function getDefaultProviderId(config: ProviderWorkspaceConfig | null | undefined): ProviderId {
|
|
132
|
-
|
|
133
|
-
|
|
160
|
+
export function getDefaultProviderId(config: ProviderWorkspaceConfig | null | undefined): ProviderId {
|
|
161
|
+
const providerId = config?.workspaceDefaultProviderId;
|
|
162
|
+
return isProviderId(providerId) && providerId !== "google" ? providerId : DEFAULT_PROVIDER_ID;
|
|
163
|
+
}
|
|
134
164
|
|
|
135
165
|
export function getActiveRouteProviderId(config: ProviderWorkspaceConfig | null | undefined): ProviderId {
|
|
136
166
|
const providerId = config?.activeRoute?.providerId;
|
|
137
|
-
return isProviderId(providerId) && isProviderRoutableInCodexa(providerId)
|
|
167
|
+
return isProviderId(providerId) && providerId !== "google" && isProviderRoutableInCodexa(providerId)
|
|
138
168
|
? providerId
|
|
139
169
|
: DEFAULT_PROVIDER_ID;
|
|
140
170
|
}
|
|
141
171
|
|
|
142
172
|
export function buildProviderRegistry(options: {
|
|
143
173
|
activeModel: string;
|
|
174
|
+
workspaceRoot?: string;
|
|
144
175
|
workspaceConfig?: ProviderWorkspaceConfig | null;
|
|
145
176
|
diagnostics?: Record<string, Record<string, string | number | boolean | null>>;
|
|
146
177
|
routeErrors?: Record<string, string>;
|
|
@@ -154,7 +185,9 @@ export function buildProviderRegistry(options: {
|
|
|
154
185
|
}
|
|
155
186
|
const defaults = DEFAULT_PROVIDERS[id];
|
|
156
187
|
const runtime = getProviderRuntime(id);
|
|
157
|
-
const discovery =
|
|
188
|
+
const discovery = id === "mistral"
|
|
189
|
+
? discoverMistralVibeModels(options.workspaceRoot ?? process.cwd())
|
|
190
|
+
: runtime.discoverModels();
|
|
158
191
|
|
|
159
192
|
const activeRoute = options.workspaceConfig?.activeRoute;
|
|
160
193
|
const isThisActive = activeRoute?.providerId === id;
|
|
@@ -189,6 +222,10 @@ export function buildProviderRegistry(options: {
|
|
|
189
222
|
}
|
|
190
223
|
}
|
|
191
224
|
|
|
225
|
+
if (id === "mistral") {
|
|
226
|
+
currentModelLabel = discovery.models[0]?.modelId ?? "Vibe default";
|
|
227
|
+
}
|
|
228
|
+
|
|
192
229
|
const rawMetadataForModel = discovery.models.find((model) => model.modelId === currentModelLabel)?.raw;
|
|
193
230
|
const contextMetadata = resolveModelContextLengthCached({
|
|
194
231
|
providerId: id,
|
|
@@ -214,7 +251,16 @@ export function buildProviderRegistry(options: {
|
|
|
214
251
|
|
|
215
252
|
const enabled = id === "local" ? discovery.status === "ready" : defaults.enabled;
|
|
216
253
|
|
|
217
|
-
const
|
|
254
|
+
const availabilityStatus = options.diagnostics?.[id]?.availabilityStatus;
|
|
255
|
+
const statusLabel = id === "mistral"
|
|
256
|
+
? availabilityStatus === "checking"
|
|
257
|
+
? "Checking"
|
|
258
|
+
: availabilityStatus === "unavailable"
|
|
259
|
+
? "Missing"
|
|
260
|
+
: routeUnavailableReason
|
|
261
|
+
? "Needs config"
|
|
262
|
+
: "Enabled"
|
|
263
|
+
: id === "local"
|
|
218
264
|
? (discovery.status === "ready" ? "Enabled" : "Disabled")
|
|
219
265
|
: !defaults.enabled
|
|
220
266
|
? "Disabled"
|
|
@@ -1,10 +1,12 @@
|
|
|
1
|
-
export type ProviderId = "openai" | "anthropic" | "google" | "local";
|
|
1
|
+
export type ProviderId = "openai" | "anthropic" | "google" | "mistral" | "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
|
+
| "mistral-vibe-cli-auth"
|
|
8
|
+
| "antigravity-cli-auth"
|
|
9
|
+
| "openai-api-key"
|
|
8
10
|
| "gemini-api-key"
|
|
9
11
|
| "anthropic-api-key"
|
|
10
12
|
| "local-openai-compatible"
|
|
@@ -69,10 +71,11 @@ export interface ProviderWorkspaceOverride {
|
|
|
69
71
|
defaultModel?: string;
|
|
70
72
|
models?: Record<string, ProviderModelWorkspaceOverride>;
|
|
71
73
|
command?: string | ProviderLaunchCommand | null;
|
|
72
|
-
claudeCommandPath?: string;
|
|
73
|
-
geminiCommandPath?: string;
|
|
74
|
-
codexCommandPath?: string;
|
|
75
|
-
|
|
74
|
+
claudeCommandPath?: string;
|
|
75
|
+
geminiCommandPath?: string;
|
|
76
|
+
codexCommandPath?: string;
|
|
77
|
+
antigravityCommandPath?: string;
|
|
78
|
+
}
|
|
76
79
|
|
|
77
80
|
export interface ProviderModelWorkspaceOverride {
|
|
78
81
|
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
|
|