@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.
Files changed (125) hide show
  1. package/README.md +17 -18
  2. package/bin/codexa.js +62 -144
  3. package/package.json +4 -3
  4. package/src/app.tsx +642 -303
  5. package/src/commands/handler.ts +7 -18
  6. package/src/config/buildInfo.ts +2 -2
  7. package/src/config/layeredConfig.ts +1 -1
  8. package/src/config/runtimeConfig.ts +1 -1
  9. package/src/config/settings.ts +1 -1
  10. package/src/config/trustStore.ts +1 -1
  11. package/src/core/README.md +52 -0
  12. package/src/core/agent/loop.ts +282 -0
  13. package/src/core/agent/protocol.ts +211 -0
  14. package/src/core/agent/tools.ts +414 -0
  15. package/src/core/{codexExecArgs.ts → codex/codexExecArgs.ts} +2 -2
  16. package/src/core/{codexLaunch.ts → codex/codexLaunch.ts} +3 -3
  17. package/src/core/{codexPrompt.ts → codex/codexPrompt.ts} +3 -3
  18. package/src/core/debug/modelStateDebug.ts +34 -0
  19. package/src/core/executables/antigravityExecutable.ts +48 -0
  20. package/src/core/executables/executableResolver.ts +5 -1
  21. package/src/core/models/codexModelCapabilities.ts +57 -4
  22. package/src/core/models/codexModelsCacheSeed.ts +153 -0
  23. package/src/core/models/providerModelCache.ts +106 -0
  24. package/src/core/perf/renderDebug.ts +10 -6
  25. package/src/core/process/CommandRunner.ts +12 -1
  26. package/src/core/providerLauncher/registry.ts +64 -18
  27. package/src/core/providerLauncher/types.ts +12 -9
  28. package/src/core/providerLauncher/workspaceConfig.ts +41 -26
  29. package/src/core/providerRuntime/anthropic.ts +10 -6
  30. package/src/core/providerRuntime/antigravity.ts +461 -0
  31. package/src/core/providerRuntime/claudeCodeDiscovery.ts +724 -446
  32. package/src/core/providerRuntime/claudeCodeDiscoveryDebug.ts +55 -0
  33. package/src/core/providerRuntime/contextMetadata.ts +12 -24
  34. package/src/core/providerRuntime/local.ts +129 -51
  35. package/src/core/providerRuntime/mistralVibe.ts +663 -0
  36. package/src/core/providerRuntime/models.ts +40 -15
  37. package/src/core/providerRuntime/reasoning.ts +9 -6
  38. package/src/core/providerRuntime/registry.ts +76 -4
  39. package/src/core/providerRuntime/types.ts +20 -14
  40. package/src/core/providers/codexSubprocess.ts +2 -2
  41. package/src/core/providers/types.ts +1 -1
  42. package/src/core/{attachments.ts → shared/attachments.ts} +27 -4
  43. package/src/core/{cleanupFastFail.ts → shared/cleanupFastFail.ts} +1 -1
  44. package/src/core/{hollowResponseFormat.ts → shared/hollowResponseFormat.ts} +1 -1
  45. package/src/core/terminal/clearFrameBoundary.ts +814 -0
  46. package/src/core/terminal/frameLock.ts +109 -0
  47. package/src/core/terminal/inkRenderReset.ts +123 -0
  48. package/src/core/terminal/terminalControl.ts +22 -0
  49. package/src/core/terminal/terminalTitle.ts +16 -102
  50. package/src/core/{channel.ts → version/channel.ts} +1 -1
  51. package/src/core/{updateCheck.ts → version/updateCheck.ts} +10 -5
  52. package/src/core/{launchContext.ts → workspace/launchContext.ts} +9 -16
  53. package/src/core/{planStorage.ts → workspace/planStorage.ts} +2 -2
  54. package/src/core/{workspaceGuard.ts → workspace/workspaceGuard.ts} +97 -13
  55. package/src/headless/execRunner.ts +2 -2
  56. package/src/index.tsx +66 -98
  57. package/src/session/appSession.ts +10 -7
  58. package/src/session/chatLifecycle.ts +1 -1
  59. package/src/session/liveRenderScheduler.ts +1 -1
  60. package/src/session/types.ts +1 -1
  61. package/src/test/runtimeTestUtils.ts +90 -0
  62. package/src/ui/{ActivityBars.tsx → chrome/ActivityBars.tsx} +1 -1
  63. package/src/ui/{ActivityIndicator.tsx → chrome/ActivityIndicator.tsx} +3 -3
  64. package/src/ui/{AnimatedStatusText.tsx → chrome/AnimatedStatusText.tsx} +3 -3
  65. package/src/ui/chrome/AppShell.tsx +672 -0
  66. package/src/ui/{BottomComposer.tsx → chrome/BottomComposer.tsx} +159 -158
  67. package/src/ui/{DashCard.tsx → chrome/DashCard.tsx} +2 -2
  68. package/src/ui/{RunFooter.tsx → chrome/RunFooter.tsx} +3 -3
  69. package/src/ui/chrome/RuntimeStatusBar.tsx +108 -0
  70. package/src/ui/{Spinner.tsx → chrome/Spinner.tsx} +1 -1
  71. package/src/ui/{TopHeader.tsx → chrome/TopHeader.tsx} +54 -38
  72. package/src/ui/{UpdateAvailableCard.tsx → chrome/UpdateAvailableCard.tsx} +5 -5
  73. package/src/ui/{commandNormalize.ts → input/commandNormalize.ts} +1 -1
  74. package/src/ui/{focus.ts → input/focus.ts} +1 -1
  75. package/src/ui/{inputBuffer.ts → input/inputBuffer.ts} +3 -3
  76. package/src/ui/layout.ts +298 -24
  77. package/src/ui/{AttachmentImportPanel.tsx → panels/AttachmentImportPanel.tsx} +3 -3
  78. package/src/ui/{AuthPanel.tsx → panels/AuthPanel.tsx} +5 -5
  79. package/src/ui/{BackendPicker.tsx → panels/BackendPicker.tsx} +2 -2
  80. package/src/ui/{ModePicker.tsx → panels/ModePicker.tsx} +2 -2
  81. package/src/ui/{ModelPicker.tsx → panels/ModelPicker.tsx} +2 -2
  82. package/src/ui/{ModelPickerScreen.tsx → panels/ModelPickerScreen.tsx} +224 -42
  83. package/src/ui/{ModelReasoningPicker.tsx → panels/ModelReasoningPicker.tsx} +5 -5
  84. package/src/ui/{Panel.tsx → panels/Panel.tsx} +1 -1
  85. package/src/ui/{PermissionsPanel.tsx → panels/PermissionsPanel.tsx} +3 -3
  86. package/src/ui/{PlanActionPicker.tsx → panels/PlanActionPicker.tsx} +2 -2
  87. package/src/ui/{PlanReviewPanel.tsx → panels/PlanReviewPanel.tsx} +5 -5
  88. package/src/ui/panels/ProviderPicker.tsx +737 -0
  89. package/src/ui/{ReasoningPicker.tsx → panels/ReasoningPicker.tsx} +3 -3
  90. package/src/ui/{SelectionPanel.tsx → panels/SelectionPanel.tsx} +5 -1
  91. package/src/ui/{SettingsPanel.tsx → panels/SettingsPanel.tsx} +4 -4
  92. package/src/ui/{TextEntryPanel.tsx → panels/TextEntryPanel.tsx} +4 -4
  93. package/src/ui/{ThemePicker.tsx → panels/ThemePicker.tsx} +2 -2
  94. package/src/ui/{UpdatePromptPanel.tsx → panels/UpdatePromptPanel.tsx} +17 -23
  95. package/src/ui/{Markdown.tsx → render/Markdown.tsx} +2 -2
  96. package/src/ui/{diffRenderer.ts → render/diffRenderer.ts} +1 -1
  97. package/src/ui/{logoVariants.ts → render/logoVariants.ts} +4 -8
  98. package/src/ui/{modeDisplay.ts → render/modeDisplay.ts} +2 -2
  99. package/src/ui/{outputPipeline.ts → render/outputPipeline.ts} +2 -2
  100. package/src/ui/{runtimeDisplay.ts → render/runtimeDisplay.ts} +23 -10
  101. package/src/ui/{textLayout.ts → render/textLayout.ts} +15 -4
  102. package/src/ui/{ActionRequiredBlock.tsx → timeline/ActionRequiredBlock.tsx} +3 -3
  103. package/src/ui/{AgentBlock.tsx → timeline/AgentBlock.tsx} +10 -10
  104. package/src/ui/{StaticIntroItem.tsx → timeline/StaticIntroItem.tsx} +2 -2
  105. package/src/ui/{ThinkingBlock.tsx → timeline/ThinkingBlock.tsx} +4 -4
  106. package/src/ui/{Timeline.tsx → timeline/Timeline.tsx} +1620 -1471
  107. package/src/ui/timeline/TranscriptShell.tsx +322 -0
  108. package/src/ui/{TurnGroup.tsx → timeline/TurnGroup.tsx} +15 -15
  109. package/src/ui/timeline/layoutListWindow.ts +145 -0
  110. package/src/ui/{progressEntries.ts → timeline/progressEntries.ts} +3 -3
  111. package/src/ui/{runActivityView.ts → timeline/runActivityView.ts} +1 -1
  112. package/src/ui/{timelineMeasure.ts → timeline/timelineMeasure.ts} +206 -134
  113. package/src/core/codex.ts +0 -124
  114. package/src/ui/AppShell.tsx +0 -706
  115. package/src/ui/ProviderPicker.tsx +0 -321
  116. package/src/ui/StaticTranscriptItem.tsx +0 -56
  117. /package/src/core/{inputDebug.ts → debug/inputDebug.ts} +0 -0
  118. /package/src/core/{clipboard.ts → shared/clipboard.ts} +0 -0
  119. /package/src/core/{githubDiagnostics.ts → shared/githubDiagnostics.ts} +0 -0
  120. /package/src/core/{projectInstructions.ts → workspace/projectInstructions.ts} +0 -0
  121. /package/src/core/{workspaceActivity.ts → workspace/workspaceActivity.ts} +0 -0
  122. /package/src/core/{workspaceRoot.ts → workspace/workspaceRoot.ts} +0 -0
  123. /package/src/ui/{busyStatusAnimation.ts → chrome/busyStatusAnimation.ts} +0 -0
  124. /package/src/ui/{slashCommands.ts → input/slashCommands.ts} +0 -0
  125. /package/src/ui/{terminalAnswerFormat.ts → render/terminalAnswerFormat.ts} +0 -0
@@ -73,29 +73,47 @@ export const GEMINI_FALLBACK_MODELS: readonly ProviderModel[] = [
73
73
  },
74
74
  ] as const;
75
75
 
76
+ function fallbackModelDescription(family: string): string {
77
+ return `Claude ${family} alias — version unknown because model discovery is unavailable`;
78
+ }
79
+
76
80
  export const ANTHROPIC_FALLBACK_MODELS: readonly ProviderModel[] = [
81
+ {
82
+ id: "fable",
83
+ modelId: "fable",
84
+ label: "Claude Fable (version unknown)",
85
+ description: fallbackModelDescription("Fable"),
86
+ defaultReasoningLevel: "xhigh",
87
+ supportedReasoningLevels: getClaudeCodeEffortLevels(["low", "medium", "high", "xhigh", "max"]),
88
+ source: "fallback",
89
+ canonicalId: "fable",
90
+ family: "fable",
91
+ effortSource: "fallback",
92
+ effortVerified: false,
93
+ },
77
94
  {
78
95
  id: "opus",
79
96
  modelId: "opus",
80
- label: "Opus 4.7",
81
- description: "Claude Opus 4.7 - Fallback defaults",
97
+ label: "Claude Opus (version unknown)",
98
+ description: fallbackModelDescription("Opus"),
82
99
  defaultReasoningLevel: "xhigh",
83
100
  supportedReasoningLevels: getClaudeCodeEffortLevels(["low", "medium", "high", "xhigh", "max"]),
84
101
  source: "fallback",
85
- canonicalId: "claude-opus-4-7",
102
+ canonicalId: "opus",
86
103
  family: "opus",
87
104
  effortSource: "fallback",
88
105
  effortVerified: false,
89
106
  },
90
- {
91
- id: "sonnet",
107
+
108
+ {
109
+ id: "sonnet",
92
110
  modelId: "sonnet",
93
- label: "Sonnet 4.6",
94
- description: "Claude Sonnet 4.6 - Fallback defaults",
111
+ label: "Claude Sonnet (version unknown)",
112
+ description: fallbackModelDescription("Sonnet"),
95
113
  defaultReasoningLevel: "high",
96
- supportedReasoningLevels: getClaudeCodeEffortLevels(["low", "medium", "high", "max"]),
114
+ supportedReasoningLevels: getClaudeCodeEffortLevels(["low", "medium", "high", "xhigh", "max"]),
97
115
  source: "fallback",
98
- canonicalId: "claude-sonnet-4-6",
116
+ canonicalId: "sonnet",
99
117
  family: "sonnet",
100
118
  effortSource: "fallback",
101
119
  effortVerified: false,
@@ -103,20 +121,27 @@ export const ANTHROPIC_FALLBACK_MODELS: readonly ProviderModel[] = [
103
121
  {
104
122
  id: "haiku",
105
123
  modelId: "haiku",
106
- label: "Haiku 4.5",
107
- description: "Claude Haiku 4.5 - Fallback defaults; effort metadata unverified",
124
+ label: "Claude Haiku (version unknown)",
125
+ description: fallbackModelDescription("Haiku"),
108
126
  defaultReasoningLevel: "medium",
109
- supportedReasoningLevels: getClaudeCodeEffortLevels(["low", "medium", "high"]),
127
+ supportedReasoningLevels: getClaudeCodeEffortLevels(["low", "medium", "high", "xhigh", "max"]),
110
128
  source: "fallback",
111
- canonicalId: "claude-haiku-4-5",
129
+ canonicalId: "haiku",
112
130
  family: "haiku",
113
131
  effortSource: "fallback",
114
132
  effortVerified: false,
115
133
  },
116
- ] as const;
134
+ ];
117
135
 
118
136
  function isRuntimeSource(source: ProviderModel["source"]): boolean {
119
- return source === "discovered" || source === "claude-code" || source === "settings" || source === "config";
137
+ return source === "discovered"
138
+ || source === "claude-code"
139
+ || source === "claude-code-command"
140
+ || source === "claude-code-package"
141
+ || source === "claude-code-cache"
142
+ || source === "claude-code-config"
143
+ || source === "settings"
144
+ || source === "config";
120
145
  }
121
146
 
122
147
  export function providerModelsToCodexCapabilities(
@@ -1,4 +1,5 @@
1
- import type { ReasoningEffortCapability } from "../models/codexModelCapabilities.js";
1
+ import type { ReasoningEffortCapability } from "../models/codexModelCapabilities.js";
2
+ import { formatReasoningLabel } from "../../config/settings.js";
2
3
 
3
4
  export const CLAUDE_CODE_EFFORT_LEVELS: readonly ReasoningEffortCapability[] = [
4
5
  { id: "low", label: "Low", description: "Claude Code low effort." },
@@ -10,8 +11,10 @@ export const CLAUDE_CODE_EFFORT_LEVELS: readonly ReasoningEffortCapability[] = [
10
11
 
11
12
  export const CLAUDE_CODE_EFFORT_IDS = new Set(CLAUDE_CODE_EFFORT_LEVELS.map((level) => level.id));
12
13
 
13
- export function getClaudeCodeEffortLevels(ids: readonly string[]): readonly ReasoningEffortCapability[] {
14
- return ids
15
- .map((id) => CLAUDE_CODE_EFFORT_LEVELS.find((level) => level.id === id))
16
- .filter((level): level is ReasoningEffortCapability => Boolean(level));
17
- }
14
+ export function getClaudeCodeEffortLevels(ids: readonly string[]): readonly ReasoningEffortCapability[] {
15
+ return ids.map((id) => CLAUDE_CODE_EFFORT_LEVELS.find((level) => level.id === id) ?? {
16
+ id,
17
+ label: formatReasoningLabel(id),
18
+ description: null,
19
+ });
20
+ }
@@ -1,9 +1,13 @@
1
1
  import { codexSubprocessProvider } from "../providers/codexSubprocess.js";
2
+ import { loadSeededOpenAiModels } from "../models/codexModelsCacheSeed.js";
3
+ import { loadCachedProviderModels, saveCachedProviderModels } from "../models/providerModelCache.js";
2
4
  import type { BackendRunHandlers } from "../providers/types.js";
3
5
  import type { ProviderId, ProviderActiveRoute, ProviderWorkspaceOverride } from "../providerLauncher/types.js";
4
6
  import { anthropicRuntime } from "./anthropic.js";
5
7
  import { geminiRuntime } from "./gemini.js";
6
8
  import { localRuntime } from "./local.js";
9
+ import { antigravityRuntime, ANTIGRAVITY_DEFAULT_MODEL_ID, migrateAntigravityLegacyModelId } from "./antigravity.js";
10
+ import { mistralVibeRuntime } from "./mistralVibe.js";
7
11
  import {
8
12
  ANTHROPIC_FALLBACK_MODELS,
9
13
  GEMINI_DEFAULT_MODEL_ID,
@@ -27,11 +31,14 @@ const openAiRuntime: ProviderRuntime = {
27
31
  routeAvailable: true,
28
32
  routeStatus: "Uses the configured Codex/OpenAI backend inside Codexa.",
29
33
  launchAvailable: true,
34
+ // Seeded from local caches (codex's own models_cache.json or Codexa's
35
+ // last-good discovery); live app-server discovery refreshes them via
36
+ // getCodexModelCapabilities in the app run loop.
30
37
  discoverModels: () => ({
31
38
  status: "ready",
32
39
  providerId: "openai",
33
40
  backendKind: "codex-cli-auth",
34
- models: [],
41
+ models: loadSeededOpenAiModels()?.models ?? [],
35
42
  }),
36
43
  run: (request: ProviderChatRequest, handlers: BackendRunHandlers) => {
37
44
  handlers.onProgress?.({
@@ -73,7 +80,9 @@ const PROVIDER_RUNTIMES: Record<ProviderId, ProviderRuntime> = {
73
80
  openai: openAiRuntime,
74
81
  anthropic: anthropicRuntime,
75
82
  google: geminiRuntime,
83
+ mistral: mistralVibeRuntime,
76
84
  local: localRuntime,
85
+ antigravity: antigravityRuntime,
77
86
  };
78
87
 
79
88
  export function getProviderRuntime(providerId: ProviderId): ProviderRuntime {
@@ -95,7 +104,29 @@ export function getProviderRouteSetupMessage(providerId: ProviderId): string {
95
104
  }
96
105
 
97
106
  export function discoverProviderModels(providerId: ProviderId): ProviderModelDiscoveryResult {
98
- return getProviderRuntime(providerId).discoverModels();
107
+ const result = getProviderRuntime(providerId).discoverModels();
108
+ // When the live/synchronous probe only produced fallback entries (or none),
109
+ // prefer the last-good discovery persisted from a previous session.
110
+ const hasRuntimeModels = result.models.some((model) => model.source && model.source !== "fallback");
111
+ if (result.status === "ready" && !hasRuntimeModels) {
112
+ const cached = loadCachedProviderModels(providerId);
113
+ if (cached) {
114
+ return { ...result, models: cached.models };
115
+ }
116
+ }
117
+ return result;
118
+ }
119
+
120
+ // Persist a ready discovery so the next session starts from last-good models.
121
+ export function persistProviderDiscovery(discovery: ProviderModelDiscoveryResult): void {
122
+ const runtimeModels = discovery.models.filter((model) => model.source && model.source !== "fallback");
123
+ if (discovery.status !== "ready" || runtimeModels.length === 0) {
124
+ return;
125
+ }
126
+ saveCachedProviderModels(discovery.providerId, {
127
+ discoveredAt: Date.now(),
128
+ models: runtimeModels,
129
+ });
99
130
  }
100
131
 
101
132
  export async function validateProviderRouteActivation(options: {
@@ -103,6 +134,7 @@ export async function validateProviderRouteActivation(options: {
103
134
  workspaceRoot: string;
104
135
  geminiCommandPath?: string | null;
105
136
  claudeCommandPath?: string | null;
137
+ antigravityCommandPath?: string | null;
106
138
  localConfig?: ProviderWorkspaceOverride | null;
107
139
  }): Promise<ProviderRouteValidationResult> {
108
140
  const runtime = getProviderRuntime(options.route.providerId);
@@ -154,7 +186,7 @@ export function resolveActiveProviderRoute(options: {
154
186
  currentReasoning: string;
155
187
  }): ActiveProviderRoute {
156
188
  const configuredRoute = options.workspaceConfigActiveRoute;
157
- if (configuredRoute && isProviderRoutableInCodexa(configuredRoute.providerId)) {
189
+ if (configuredRoute && configuredRoute.providerId !== "google" && isProviderRoutableInCodexa(configuredRoute.providerId)) {
158
190
  const route: ActiveProviderRoute = {
159
191
  providerId: configuredRoute.providerId,
160
192
  modelId: configuredRoute.modelId,
@@ -167,6 +199,17 @@ export function resolveActiveProviderRoute(options: {
167
199
  route.modelId = resolveGeminiModelId(route.modelSelection);
168
200
  } else if (route.providerId === "google") {
169
201
  route.modelId = normalizeGeminiModelId(route.modelId);
202
+ } else if (route.providerId === "anthropic") {
203
+ const discovery = discoverProviderModels("anthropic");
204
+ const stillAvailable = discovery.models.some((model) =>
205
+ model.modelId === route.modelId ||
206
+ model.id === route.modelId ||
207
+ model.canonicalId === route.modelId
208
+ );
209
+ const hasNonFallbackModels = discovery.models.some((model) => model.source !== "fallback");
210
+ if (discovery.status === "ready" && hasNonFallbackModels && discovery.models.length > 0 && !stillAvailable) {
211
+ route.modelId = discovery.models[0]!.modelId;
212
+ }
170
213
  } else if (route.providerId === "local") {
171
214
  const discovery = discoverProviderModels("local");
172
215
  const selectedModel = typeof discovery.diagnostics?.selectedModel === "string"
@@ -175,6 +218,24 @@ export function resolveActiveProviderRoute(options: {
175
218
  if (discovery.status === "ready" && selectedModel) {
176
219
  route.modelId = selectedModel;
177
220
  }
221
+ } else if (route.providerId === "antigravity") {
222
+ const migrated = migrateAntigravityLegacyModelId(route.modelId);
223
+ route.modelId = migrated.modelId;
224
+ if (!route.reasoning && migrated.reasoning) {
225
+ route.reasoning = migrated.reasoning;
226
+ }
227
+ const discovery = discoverProviderModels("antigravity");
228
+ if (discovery.status === "ready" && discovery.models.length > 0) {
229
+ let model = discovery.models.find((item) => item.modelId === route.modelId || item.id === route.modelId);
230
+ if (!model) {
231
+ model = discovery.models[0];
232
+ route.modelId = model.modelId;
233
+ }
234
+ const levels = model.supportedReasoningLevels;
235
+ if (levels?.length && (!route.reasoning || !levels.some((level) => level.id === route.reasoning))) {
236
+ route.reasoning = model.defaultReasoningLevel ?? levels[0]?.id;
237
+ }
238
+ }
178
239
  }
179
240
 
180
241
  return route;
@@ -190,7 +251,11 @@ export function resolveActiveProviderRoute(options: {
190
251
 
191
252
  export function getDefaultRouteModel(providerId: ProviderId, currentOpenAiModel: string): string {
192
253
  if (providerId === "anthropic") {
193
- return ANTHROPIC_FALLBACK_MODELS[0]?.modelId ?? "claude-sonnet-4-20250514";
254
+ const discovered = discoverProviderModels("anthropic");
255
+ if (discovered.status === "ready" && discovered.models.length > 0) {
256
+ return discovered.models[0].modelId;
257
+ }
258
+ return ANTHROPIC_FALLBACK_MODELS[0]?.modelId ?? "sonnet";
194
259
  }
195
260
  if (providerId === "google") {
196
261
  return GEMINI_FALLBACK_MODELS[0]?.modelId ?? GEMINI_DEFAULT_MODEL_ID;
@@ -199,5 +264,12 @@ export function getDefaultRouteModel(providerId: ProviderId, currentOpenAiModel:
199
264
  const discovery = discoverProviderModels("local");
200
265
  return discovery.models[0]?.modelId ?? "Local default";
201
266
  }
267
+ if (providerId === "mistral") {
268
+ const discovery = discoverProviderModels("mistral");
269
+ return discovery.models[0]?.modelId ?? "Vibe default";
270
+ }
271
+ if (providerId === "antigravity") {
272
+ return discoverProviderModels("antigravity").models[0]?.modelId ?? ANTIGRAVITY_DEFAULT_MODEL_ID;
273
+ }
202
274
  return currentOpenAiModel;
203
275
  }
@@ -1,5 +1,5 @@
1
1
  import type { ReasoningEffortCapability } from "../models/codexModelCapabilities.js";
2
- import type { ProjectInstructions } from "../projectInstructions.js";
2
+ import type { ProjectInstructions } from "../workspace/projectInstructions.js";
3
3
  import type { BackendRunHandlers } from "../providers/types.js";
4
4
  import type { ResolvedRuntimeConfig } from "../../config/runtimeConfig.js";
5
5
  export type { ResolvedRuntimeConfig };
@@ -7,10 +7,12 @@ import type { ProviderId } from "../providerLauncher/types.js";
7
7
  import type { ProviderWorkspaceOverride } from "../providerLauncher/types.js";
8
8
 
9
9
  export type ProviderBackendKind =
10
- | "codex-cli-auth"
11
- | "gemini-cli-auth"
12
- | "claude-code-auth"
13
- | "openai-api-key"
10
+ | "codex-cli-auth"
11
+ | "gemini-cli-auth"
12
+ | "claude-code-auth"
13
+ | "mistral-vibe-cli-auth"
14
+ | "antigravity-cli-auth"
15
+ | "openai-api-key"
14
16
  | "gemini-api-key"
15
17
  | "anthropic-api-key"
16
18
  | "local-openai-compatible"
@@ -23,10 +25,13 @@ export interface ProviderModel {
23
25
  description: string | null;
24
26
  defaultReasoningLevel: string | null;
25
27
  supportedReasoningLevels: readonly ReasoningEffortCapability[] | null;
26
- source?: "discovered" | "claude-code" | "settings" | "config" | "fallback";
27
- canonicalId?: string;
28
- family?: string;
29
- effortSource?: "claude-code" | "settings" | "config" | "fallback";
28
+ source?: "discovered" | "claude-code" | "claude-code-command" | "claude-code-package" | "claude-code-cache" | "claude-code-config" | "settings" | "config" | "fallback";
29
+ canonicalId?: string;
30
+ family?: string;
31
+ version?: string;
32
+ isFallback?: boolean;
33
+ discoveryKind?: "models" | "aliases";
34
+ effortSource?: "claude-code" | "claude-code-command" | "claude-code-package" | "claude-code-cache" | "claude-code-config" | "settings" | "config" | "fallback";
30
35
  effortVerified?: boolean;
31
36
  raw?: unknown;
32
37
  }
@@ -58,11 +63,12 @@ export type ActiveProviderRoute = ProviderRoute;
58
63
 
59
64
  export interface ProviderRouteValidationRequest {
60
65
  route: ProviderRoute;
61
- workspaceRoot: string;
62
- geminiCommandPath?: string | null;
63
- claudeCommandPath?: string | null;
64
- localConfig?: ProviderWorkspaceOverride | null;
65
- }
66
+ workspaceRoot: string;
67
+ geminiCommandPath?: string | null;
68
+ claudeCommandPath?: string | null;
69
+ antigravityCommandPath?: string | null;
70
+ localConfig?: ProviderWorkspaceOverride | null;
71
+ }
66
72
 
67
73
  export interface ProviderRouteValidationResult {
68
74
  status: "ready" | "not-configured";
@@ -1,8 +1,8 @@
1
1
  import { spawn } from "child_process";
2
2
  import { formatCodexLaunchError, spawnCodexProcess } from "../executables/codexExecutable.js";
3
- import { prepareCodexExecLaunch } from "../codexLaunch.js";
3
+ import { prepareCodexExecLaunch } from "../codex/codexLaunch.js";
4
4
  import * as perf from "../perf/profiler.js";
5
- import { buildCodexPrompt } from "../codexPrompt.js";
5
+ import { buildCodexPrompt } from "../codex/codexPrompt.js";
6
6
  import { createTerminalTitleSequenceStripper } from "../terminal/terminalTitle.js";
7
7
  import { createCodexJsonStreamParser } from "./codexJsonStream.js";
8
8
  import {
@@ -1,6 +1,6 @@
1
1
  import type { AvailableBackend } from "../../config/settings.js";
2
2
  import type { ResolvedRuntimeConfig } from "../../config/runtimeConfig.js";
3
- import type { ProjectInstructions } from "../projectInstructions.js";
3
+ import type { ProjectInstructions } from "../workspace/projectInstructions.js";
4
4
  import type { RunProgressSource, RunToolActivity } from "../../session/types.js";
5
5
 
6
6
  export interface BackendProgressUpdate {
@@ -1,5 +1,10 @@
1
- import { access, copyFile, mkdir } from "node:fs/promises";
1
+ import { access, copyFile, mkdir, stat } from "node:fs/promises";
2
+ import { existsSync } from "node:fs";
2
3
  import path from "node:path";
4
+ import {
5
+ isSkippedExternalDependencyPath,
6
+ normalizeDiagnosticPath,
7
+ } from "../workspace/workspaceGuard.js";
3
8
 
4
9
  export const IMAGE_EXTENSIONS = new Set([
5
10
  ".png",
@@ -44,10 +49,28 @@ export async function resolveAttachmentDestPath(
44
49
  export async function importExternalFile(
45
50
  srcPath: string,
46
51
  attachmentsDir: string,
47
- ): Promise<string> {
52
+ ): Promise<string | null> {
53
+ const normalized = normalizeDiagnosticPath(srcPath);
54
+
55
+ if (isSkippedExternalDependencyPath(normalized)) {
56
+ return null;
57
+ }
58
+
59
+ try {
60
+ if (!existsSync(normalized)) {
61
+ return null;
62
+ }
63
+ const s = await stat(normalized);
64
+ if (!s.isFile()) {
65
+ return null;
66
+ }
67
+ } catch {
68
+ return null;
69
+ }
70
+
48
71
  await mkdir(attachmentsDir, { recursive: true });
49
- const destPath = await resolveAttachmentDestPath(srcPath, attachmentsDir);
50
- await copyFile(srcPath, destPath);
72
+ const destPath = await resolveAttachmentDestPath(normalized, attachmentsDir);
73
+ await copyFile(normalized, destPath);
51
74
  return destPath;
52
75
  }
53
76
 
@@ -1,4 +1,4 @@
1
- import type { RunToolActivity } from "../session/types.js";
1
+ import type { RunToolActivity } from "../../session/types.js";
2
2
 
3
3
  const DELETE_COMMAND_PATTERN =
4
4
  /(?:^|[\s;&|])(?:remove-item|rm|rmdir|del|erase|unlink)\b/i;
@@ -1,4 +1,4 @@
1
- import type { HollowResponseResult } from "./codexPrompt.js";
1
+ import type { HollowResponseResult } from "../codex/codexPrompt.js";
2
2
 
3
3
  const MESSAGES: Record<string, [string, string]> = {
4
4
  greeting: [