vibe-coding-master 0.7.43 → 0.7.45

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 (54) hide show
  1. package/README.md +64 -39
  2. package/dist/backend/adapters/claude-adapter.js +2 -2
  3. package/dist/backend/adapters/codex-bridge-adapter.js +213 -0
  4. package/dist/backend/api/app-settings-routes.js +6 -6
  5. package/dist/backend/api/artifact-routes.js +3 -0
  6. package/dist/backend/api/harness-routes.js +16 -0
  7. package/dist/backend/api/task-routes.js +1 -0
  8. package/dist/backend/api/workflow-control-routes.js +12 -0
  9. package/dist/backend/cli/install-vcm-harness.js +21 -0
  10. package/dist/backend/server.js +11 -9
  11. package/dist/backend/services/app-settings-service.js +11 -11
  12. package/dist/backend/services/artifact-service.js +7 -30
  13. package/dist/backend/services/auto-memory-service.js +640 -12
  14. package/dist/backend/services/claude-hook-service.js +80 -2
  15. package/dist/backend/services/{ccr-integration-service.js → codex-bridge-integration-service.js} +71 -71
  16. package/dist/backend/services/gate-review-service.js +173 -74
  17. package/dist/backend/services/harness-feedback-service.js +76 -78
  18. package/dist/backend/services/harness-service.js +27 -3
  19. package/dist/backend/services/runtime-coordinator-service.js +2 -1
  20. package/dist/backend/services/session-service.js +16 -16
  21. package/dist/backend/services/status-service.js +1 -0
  22. package/dist/backend/services/translation-worker-service.js +19 -4
  23. package/dist/backend/services/usage-analytics-service.js +3 -3
  24. package/dist/backend/services/workflow-control-service.js +96 -12
  25. package/dist/backend/templates/handoff.js +44 -2
  26. package/dist/backend/templates/harness/architect-agent.js +13 -7
  27. package/dist/backend/templates/harness/architect-scaffold-worker-agent.js +1 -1
  28. package/dist/backend/templates/harness/check-scaffold-ledger.js +234 -10
  29. package/dist/backend/templates/harness/claude-root.js +3 -2
  30. package/dist/backend/templates/harness/coder-agent.js +8 -0
  31. package/dist/backend/templates/harness/gate-review.js +144 -49
  32. package/dist/backend/templates/harness/harness-engineer-agent.js +25 -10
  33. package/dist/backend/templates/harness/project-manager-agent.js +16 -10
  34. package/dist/backend/templates/harness/resolve-durable-doc-assignment.js +60 -0
  35. package/dist/backend/templates/harness/tester-agent.js +13 -0
  36. package/dist/backend/templates/harness/vcm-ask-user-skill.js +82 -0
  37. package/dist/backend/templates/harness/vcm-code-navigation-skill.js +7 -5
  38. package/dist/backend/templates/harness/vcm-task-state-skill.js +2 -2
  39. package/dist/backend/templates/harness/vcm-workflow-review-skill.js +1 -1
  40. package/dist/shared/types/session.js +28 -22
  41. package/dist/shared/types/workflow.js +1 -0
  42. package/dist/shared/validation/artifact-check.js +3 -3
  43. package/dist/shared/validation/artifact-contract.js +1 -1
  44. package/dist/shared/validation/artifact-registry.js +16 -0
  45. package/dist-frontend/assets/index-DDmygnV6.css +32 -0
  46. package/dist-frontend/assets/{index-VW9tYPP5.js → index-nAV6toi8.js} +47 -47
  47. package/dist-frontend/index.html +2 -2
  48. package/package.json +1 -1
  49. package/scripts/claude-plugins/vcm-lsp-bridge/.claude-plugin/plugin.json +21 -6
  50. package/scripts/{ccr-api-key-helper.mjs → codex-bridge-api-key-helper.mjs} +1 -1
  51. package/scripts/harness-tools/vcm-artifact +1 -2
  52. package/scripts/harness-tools/vcm-bash-guard +1 -1
  53. package/dist/backend/adapters/ccr-gateway-adapter.js +0 -172
  54. package/dist-frontend/assets/index-B0d4Z6ny.css +0 -32
@@ -158,7 +158,7 @@ export function createClaudeHookService(deps) {
158
158
  ? await deps.harnessFeedbackService?.handleTaskRetrospectiveHook(context.project.repoRoot, {
159
159
  taskSlug: activeTask.taskSlug,
160
160
  eventName,
161
- memoryReviewSucceeded: memoryState?.status !== "failed"
161
+ memoryReviewStatus: memoryState?.status ?? "idle"
162
162
  })
163
163
  : false;
164
164
  if (memoryHandled || retrospectiveHandled) {
@@ -212,6 +212,16 @@ export function createClaudeHookService(deps) {
212
212
  if (memoryResult) {
213
213
  return memoryResult;
214
214
  }
215
+ const prompt = stringOrUndefined(input.event.prompt);
216
+ if (input.role === "project-manager"
217
+ && prompt
218
+ && isDirectUserPrompt(prompt)
219
+ && deps.workflowControlService) {
220
+ const workflowState = await deps.workflowControlService.getState(createWorkflowControlContext(context));
221
+ if (workflowState.awaitingUser) {
222
+ await deps.workflowControlService.resolveUserInput(createWorkflowControlContext(context));
223
+ }
224
+ }
215
225
  const session = await deps.sessionService.recordClaudeHookEvent(context.project.repoRoot, {
216
226
  taskSlug: context.taskSlug,
217
227
  role: input.role,
@@ -266,7 +276,7 @@ export function createClaudeHookService(deps) {
266
276
  handoffDir: context.task.handoffDir,
267
277
  taskSlug: context.taskSlug,
268
278
  role: input.role,
269
- prompt: stringOrUndefined(input.event.prompt)
279
+ prompt
270
280
  });
271
281
  if (submitted) {
272
282
  await deps.architectRestartService?.recordRouteAccepted(context.project.repoRoot, context.taskSlug, submitted);
@@ -298,6 +308,7 @@ export function createClaudeHookService(deps) {
298
308
  return completedHookResult(input, eventName);
299
309
  }
300
310
  await clearStopFailureRecoveryState(context, input.role);
311
+ let pmAwaitingUser = false;
301
312
  if (options.allowBlock && deps.jobGuard) {
302
313
  const verdict = await deps.jobGuard.evaluateStop({
303
314
  repoRoot: context.project.repoRoot,
@@ -319,12 +330,42 @@ export function createClaudeHookService(deps) {
319
330
  };
320
331
  }
321
332
  }
333
+ if (input.role === "project-manager" && deps.workflowControlService) {
334
+ const workflowState = await deps.workflowControlService.getState(createWorkflowControlContext(context));
335
+ if (workflowState.awaitingUser) {
336
+ pmAwaitingUser = true;
337
+ }
338
+ else {
339
+ const lastAssistantMessage = stringOrUndefined(input.event.last_assistant_message);
340
+ if (options.allowBlock && lastAssistantMessage && asksUserQuestion(lastAssistantMessage)) {
341
+ return {
342
+ ok: true,
343
+ eventName,
344
+ taskSlug: context.taskSlug,
345
+ role: input.role,
346
+ sessionUpdated: false,
347
+ dispatchedCount: 0,
348
+ stopDecision: {
349
+ behavior: "block",
350
+ reason: "You asked the user a question without registering the wait. Use vcm-ask-user with the exact question, then ask that question and stop. Do not advance or route the workflow."
351
+ }
352
+ };
353
+ }
354
+ }
355
+ }
322
356
  await deps.roleStallDetector?.recordHook({
323
357
  ...createStallContext(context),
324
358
  role: input.role,
325
359
  eventName,
326
360
  event: input.event
327
361
  });
362
+ if (pmAwaitingUser) {
363
+ return recordTurnEnd(input, context, eventName, {
364
+ dispatchRouteFiles: false,
365
+ notifyGateway: true,
366
+ settleGuard: false
367
+ });
368
+ }
328
369
  return recordTurnEnd(input, context, eventName, {
329
370
  dispatchRouteFiles: !isReviewerRoleName(input.role),
330
371
  notifyGateway: true,
@@ -554,6 +595,17 @@ export function createClaudeHookService(deps) {
554
595
  if (!deps.autoMemoryService || !(await deps.autoMemoryService.isRoleMemoryTurn(context.taskRepoRoot, input.role))) {
555
596
  return undefined;
556
597
  }
598
+ const prompt = stringOrUndefined(input.event.prompt);
599
+ if (eventName === "UserPromptSubmit"
600
+ && input.role === "project-manager"
601
+ && prompt
602
+ && isDirectUserPrompt(prompt)
603
+ && deps.workflowControlService) {
604
+ const workflowState = await deps.workflowControlService.getState(createWorkflowControlContext(context));
605
+ if (workflowState.awaitingUser) {
606
+ await deps.workflowControlService.resolveUserInput(createWorkflowControlContext(context));
607
+ }
608
+ }
557
609
  const session = await deps.sessionService.recordClaudeHookEvent(context.project.repoRoot, {
558
610
  taskSlug: context.taskSlug,
559
611
  role: input.role,
@@ -593,6 +645,10 @@ export function createClaudeHookService(deps) {
593
645
  role: input.role,
594
646
  eventName
595
647
  });
648
+ if (eventName === "Stop") {
649
+ const memoryState = await deps.autoMemoryService.getState(context.project.repoRoot, context.taskRepoRoot);
650
+ await deps.harnessFeedbackService?.completeWaitingTaskRetrospective(context.project.repoRoot, context.taskSlug, memoryState.status);
651
+ }
596
652
  return {
597
653
  ok: true,
598
654
  eventName,
@@ -613,6 +669,14 @@ export function createClaudeHookService(deps) {
613
669
  ...(stoppedRole ? { stoppedRole } : {})
614
670
  };
615
671
  }
672
+ function createWorkflowControlContext(context) {
673
+ return {
674
+ taskRepoRoot: context.taskRepoRoot,
675
+ stateRoot: context.config.stateRoot,
676
+ handoffDir: context.task.handoffDir,
677
+ taskSlug: context.taskSlug
678
+ };
679
+ }
616
680
  async function isCurrentRoleHook(context, input, eventName) {
617
681
  const current = await deps.sessionService.getRoleSession(context.project.repoRoot, context.taskSlug, input.role);
618
682
  return Boolean(current && matchesRoleHookSession(current, {
@@ -1017,3 +1081,17 @@ function normalizeDiagnosticString(value, maxLength) {
1017
1081
  function stringOrUndefined(value) {
1018
1082
  return typeof value === "string" ? value : undefined;
1019
1083
  }
1084
+ function isDirectUserPrompt(prompt) {
1085
+ const normalized = prompt.trim();
1086
+ return normalized.length > 0 && !/^\[VCM(?:\s|\])/i.test(normalized);
1087
+ }
1088
+ function asksUserQuestion(message) {
1089
+ const withoutCodeBlocks = message.replace(/```[\s\S]*?```/g, "");
1090
+ const lines = withoutCodeBlocks
1091
+ .split(/\r?\n/)
1092
+ .map((line) => line.trim())
1093
+ .filter(Boolean);
1094
+ return lines.some((line) => /[??]["')\]}】”’]*$/.test(line)
1095
+ || /^(?:please\s+(?:answer|choose|confirm|decide|provide|select|tell)|(?:can|could|do|does|is|are|should|will|would)\s+you\b)/i.test(line)
1096
+ || /^(?:请(?:回答|选择|确认|决定|提供|告知)|你(?:是否|能否|要不要|可否)|是否需要你|需要你(?:选择|确认|决定|提供|告知))/.test(line));
1097
+ }
@@ -1,19 +1,19 @@
1
- import { CCR_GATEWAY_BASE_URL, CCR_GPT_AUTO_COMPACT_PERCENT, CCR_GPT_AUTO_COMPACT_WINDOW_TOKENS, CCR_GPT_EFFECTIVE_CONTEXT_TOKENS, CCR_GPT_MODEL_ID, createSessionModelOptions, isCcrSessionModel } from "../../shared/types/session.js";
2
1
  import path from "node:path";
3
2
  import { fileURLToPath } from "node:url";
3
+ import { CODEX_BRIDGE_AUTO_COMPACT_PERCENT, CODEX_BRIDGE_AUTO_COMPACT_WINDOW_TOKENS, CODEX_BRIDGE_BASE_URL, CODEX_BRIDGE_EFFECTIVE_CONTEXT_TOKENS, createSessionModelOptions, getCodexBridgeModelId, isCodexBridgeSessionModel } from "../../shared/types/session.js";
4
4
  import { VcmError } from "../errors.js";
5
5
  import { resolveVcmDataDir } from "../vcm-data-dir.js";
6
6
  const DEFAULT_CACHE_TTL_MS = 10_000;
7
- const DEFAULT_API_KEY_HELPER_PATH = fileURLToPath(new URL("../../../scripts/ccr-api-key-helper.mjs", import.meta.url));
8
- export function createCcrIntegrationService(deps) {
7
+ const DEFAULT_API_KEY_HELPER_PATH = fileURLToPath(new URL("../../../scripts/codex-bridge-api-key-helper.mjs", import.meta.url));
8
+ export function createCodexBridgeIntegrationService(deps) {
9
9
  const now = deps.now ?? (() => new Date());
10
10
  const cacheTtlMs = deps.cacheTtlMs ?? DEFAULT_CACHE_TTL_MS;
11
11
  const baseEnv = deps.baseEnv ?? process.env;
12
- const configDir = deps.configDir ?? path.join(resolveVcmDataDir(baseEnv), "claude", "ccr");
12
+ const configDir = deps.configDir ?? path.join(resolveVcmDataDir(baseEnv), "claude", "codex-bridge");
13
13
  let cachedProbe;
14
14
  let inFlight;
15
15
  async function probe(force = false) {
16
- const settings = await deps.settings.getCcrIntegrationSettings();
16
+ const settings = await deps.settings.getCodexBridgeIntegrationSettings();
17
17
  if (!settings.apiKey) {
18
18
  throw missingApiKeyError();
19
19
  }
@@ -24,7 +24,7 @@ export function createCcrIntegrationService(deps) {
24
24
  if (inFlight) {
25
25
  return inFlight;
26
26
  }
27
- inFlight = deps.gateway.probe(settings.apiKey).then((result) => {
27
+ inFlight = deps.bridge.probe(settings.apiKey).then((result) => {
28
28
  const checkedAtDate = now();
29
29
  cachedProbe = {
30
30
  result,
@@ -38,14 +38,15 @@ export function createCcrIntegrationService(deps) {
38
38
  return inFlight;
39
39
  }
40
40
  async function buildStatus(options = {}) {
41
- const settings = await deps.settings.getCcrIntegrationSettings();
41
+ const settings = await deps.settings.getCodexBridgeIntegrationSettings();
42
42
  if (!settings.enabled) {
43
43
  return createStatus({
44
44
  enabled: false,
45
45
  apiKeyConfigured: Boolean(settings.apiKey),
46
46
  connectionState: "disabled",
47
47
  modelAvailable: false,
48
- error: settings.apiKey ? undefined : "Save a CCR API key before enabling CCR GPT models."
48
+ models: [],
49
+ error: settings.apiKey ? undefined : "Save a Codex Bridge API key before enabling Codex models."
49
50
  });
50
51
  }
51
52
  if (!cachedProbe && options.refreshIfMissing) {
@@ -56,7 +57,8 @@ export function createCcrIntegrationService(deps) {
56
57
  enabled: true,
57
58
  apiKeyConfigured: true,
58
59
  connectionState: "checking",
59
- modelAvailable: false
60
+ modelAvailable: false,
61
+ models: []
60
62
  });
61
63
  }
62
64
  return createStatus({
@@ -64,13 +66,14 @@ export function createCcrIntegrationService(deps) {
64
66
  apiKeyConfigured: true,
65
67
  connectionState: cachedProbe.result.connectionState,
66
68
  modelAvailable: cachedProbe.result.modelAvailable,
69
+ models: cachedProbe.result.models,
67
70
  checkedAt: cachedProbe.checkedAt,
68
71
  error: cachedProbe.result.error
69
72
  });
70
73
  }
71
74
  return {
72
75
  async initialize() {
73
- const settings = await deps.settings.getCcrIntegrationSettings();
76
+ const settings = await deps.settings.getCodexBridgeIntegrationSettings();
74
77
  if (settings.enabled) {
75
78
  await probe(true);
76
79
  }
@@ -80,15 +83,15 @@ export function createCcrIntegrationService(deps) {
80
83
  },
81
84
  async updateSettings(input) {
82
85
  if (input.apiKey !== undefined && typeof input.apiKey !== "string") {
83
- throw invalidSettingsError("CCR API key must be a string.");
86
+ throw invalidSettingsError("Codex Bridge API key must be a string.");
84
87
  }
85
88
  if (input.enabled !== undefined && typeof input.enabled !== "boolean") {
86
- throw invalidSettingsError("CCR enabled state must be a boolean.");
89
+ throw invalidSettingsError("Codex Bridge enabled state must be a boolean.");
87
90
  }
88
91
  if (input.clearApiKey !== undefined && typeof input.clearApiKey !== "boolean") {
89
- throw invalidSettingsError("CCR clear-key state must be a boolean.");
92
+ throw invalidSettingsError("Codex Bridge clear-key state must be a boolean.");
90
93
  }
91
- const current = await deps.settings.getCcrIntegrationSettings();
94
+ const current = await deps.settings.getCodexBridgeIntegrationSettings();
92
95
  const clearApiKey = input.clearApiKey === true;
93
96
  const nextApiKey = clearApiKey
94
97
  ? ""
@@ -99,7 +102,7 @@ export function createCcrIntegrationService(deps) {
99
102
  if (nextEnabled && !nextApiKey) {
100
103
  throw missingApiKeyError();
101
104
  }
102
- await deps.settings.updateCcrIntegrationSettings({
105
+ await deps.settings.updateCodexBridgeIntegrationSettings({
103
106
  enabled: nextEnabled,
104
107
  apiKey: nextApiKey
105
108
  });
@@ -114,64 +117,65 @@ export function createCcrIntegrationService(deps) {
114
117
  return buildStatus();
115
118
  },
116
119
  async checkConnection() {
117
- const settings = await deps.settings.getCcrIntegrationSettings();
120
+ const settings = await deps.settings.getCodexBridgeIntegrationSettings();
118
121
  if (!settings.enabled) {
119
122
  throw new VcmError({
120
- code: "CCR_DISABLED",
121
- message: "CCR GPT models are disabled.",
123
+ code: "CODEX_BRIDGE_DISABLED",
124
+ message: "Codex Bridge models are disabled.",
122
125
  statusCode: 409,
123
- hint: "Save the CCR API key and enable CCR GPT models before checking the connection."
126
+ hint: "Save the Codex Bridge API key and enable Codex models before checking the connection."
124
127
  });
125
128
  }
126
129
  await probe(true);
127
130
  return buildStatus();
128
131
  },
129
132
  async getLaunchEnvironment(model) {
130
- if (!isCcrSessionModel(model)) {
133
+ if (!isCodexBridgeSessionModel(model)) {
131
134
  return buildNativeLaunchEnvironment(baseEnv);
132
135
  }
133
- const settings = await deps.settings.getCcrIntegrationSettings();
136
+ const settings = await deps.settings.getCodexBridgeIntegrationSettings();
134
137
  if (!settings.enabled) {
135
138
  throw new VcmError({
136
- code: "CCR_DISABLED",
137
- message: "CCR GPT models are disabled.",
139
+ code: "CODEX_BRIDGE_DISABLED",
140
+ message: "Codex Bridge models are disabled.",
138
141
  statusCode: 409,
139
- hint: "Enable CCR GPT models in VCM Settings before starting this session."
142
+ hint: "Enable Codex Bridge in VCM Settings before starting this session."
140
143
  });
141
144
  }
142
145
  const checked = await probe();
143
- if (checked.result.connectionState !== "available" || !checked.result.modelAvailable) {
146
+ const modelId = getCodexBridgeModelId(model);
147
+ const modelAvailable = checked.result.models.some((available) => available.id === modelId);
148
+ if (checked.result.connectionState !== "available" || !modelAvailable) {
144
149
  throw new VcmError({
145
- code: "CCR_MODEL_UNAVAILABLE",
146
- message: checked.result.error ?? `CCR model ${CCR_GPT_MODEL_ID} is unavailable.`,
150
+ code: "CODEX_BRIDGE_MODEL_UNAVAILABLE",
151
+ message: checked.result.error ?? `Codex Bridge model ${modelId} is unavailable.`,
147
152
  statusCode: 409,
148
- hint: "Check that host CCR is running on port 3456 and exposes GPT-5.6 Sol."
153
+ hint: "Check Codex Bridge on port 3456, refresh its Codex login, and verify the selected model."
149
154
  });
150
155
  }
151
- const gatewayBaseUrl = checked.result.baseUrl ?? CCR_GATEWAY_BASE_URL;
152
- const gatewayHost = new URL(gatewayBaseUrl).hostname;
153
- const noProxy = mergeNoProxy(deps.baseEnv?.NO_PROXY ?? deps.baseEnv?.no_proxy ?? process.env.NO_PROXY ?? process.env.no_proxy, gatewayHost);
156
+ const bridgeBaseUrl = checked.result.baseUrl ?? CODEX_BRIDGE_BASE_URL;
157
+ const bridgeHost = new URL(bridgeBaseUrl).hostname;
158
+ const noProxy = mergeNoProxy(deps.baseEnv?.NO_PROXY ?? deps.baseEnv?.no_proxy ?? process.env.NO_PROXY ?? process.env.no_proxy, bridgeHost);
154
159
  return {
155
- ANTHROPIC_BASE_URL: gatewayBaseUrl,
156
- ANTHROPIC_API_BASE_URL: gatewayBaseUrl,
157
- CLAUDE_AGENT_API_BASE_URL: gatewayBaseUrl,
160
+ ANTHROPIC_BASE_URL: bridgeBaseUrl,
161
+ ANTHROPIC_API_BASE_URL: bridgeBaseUrl,
162
+ CLAUDE_AGENT_API_BASE_URL: bridgeBaseUrl,
158
163
  ANTHROPIC_AUTH_TOKEN: undefined,
159
164
  ANTHROPIC_API_KEY: undefined,
160
- ANTHROPIC_MODEL: CCR_GPT_MODEL_ID,
161
- CCR_CLAUDE_CODE_MODEL: CCR_GPT_MODEL_ID,
162
- CODEXL_CLAUDE_CODE_MODEL: CCR_GPT_MODEL_ID,
163
- ANTHROPIC_SMALL_FAST_MODEL: CCR_GPT_MODEL_ID,
165
+ ANTHROPIC_MODEL: modelId,
166
+ CODEX_BRIDGE_CLAUDE_MODEL: modelId,
167
+ ANTHROPIC_SMALL_FAST_MODEL: modelId,
164
168
  CLAUDE_CODE_ENABLE_GATEWAY_MODEL_DISCOVERY: "1",
165
- CLAUDE_CODE_MAX_CONTEXT_TOKENS: String(CCR_GPT_EFFECTIVE_CONTEXT_TOKENS),
166
- CLAUDE_CODE_AUTO_COMPACT_WINDOW: String(CCR_GPT_AUTO_COMPACT_WINDOW_TOKENS),
167
- CLAUDE_AUTOCOMPACT_PCT_OVERRIDE: String(CCR_GPT_AUTO_COMPACT_PERCENT),
169
+ CLAUDE_CODE_MAX_CONTEXT_TOKENS: String(CODEX_BRIDGE_EFFECTIVE_CONTEXT_TOKENS),
170
+ CLAUDE_CODE_AUTO_COMPACT_WINDOW: String(CODEX_BRIDGE_AUTO_COMPACT_WINDOW_TOKENS),
171
+ CLAUDE_AUTOCOMPACT_PCT_OVERRIDE: String(CODEX_BRIDGE_AUTO_COMPACT_PERCENT),
168
172
  CLAUDE_CONFIG_DIR: configDir,
169
173
  NO_PROXY: noProxy,
170
174
  no_proxy: noProxy
171
175
  };
172
176
  },
173
177
  async getLaunchSettingsOverride(model) {
174
- if (!isCcrSessionModel(model)) {
178
+ if (!isCodexBridgeSessionModel(model)) {
175
179
  return undefined;
176
180
  }
177
181
  return {
@@ -180,51 +184,50 @@ export function createCcrIntegrationService(deps) {
180
184
  }
181
185
  };
182
186
  }
183
- const CCR_BASE_URL_KEYS = [
187
+ const BRIDGE_BASE_URL_KEYS = [
184
188
  "ANTHROPIC_BASE_URL",
185
189
  "ANTHROPIC_API_BASE_URL",
186
190
  "CLAUDE_AGENT_API_BASE_URL"
187
191
  ];
188
- const CCR_MODEL_KEYS = [
192
+ const BRIDGE_MODEL_KEYS = [
189
193
  "ANTHROPIC_MODEL",
190
194
  "ANTHROPIC_SMALL_FAST_MODEL"
191
195
  ];
192
- const CCR_ONLY_ENV_KEYS = [
193
- "CCR_CLAUDE_CODE_MODEL",
194
- "CODEXL_CLAUDE_CODE_MODEL",
196
+ const BRIDGE_ONLY_ENV_KEYS = [
197
+ "CODEX_BRIDGE_CLAUDE_MODEL",
195
198
  "CLAUDE_CODE_ENABLE_GATEWAY_MODEL_DISCOVERY"
196
199
  ];
197
200
  export function buildNativeLaunchEnvironment(baseEnv) {
198
201
  const environment = {};
199
- let inheritedCcrTakeover = false;
202
+ let inheritedBridgeTakeover = false;
200
203
  if (baseEnv.CLAUDE_CONFIG_DIR?.trim()) {
201
204
  environment.CLAUDE_CONFIG_DIR = baseEnv.CLAUDE_CONFIG_DIR.trim();
202
205
  }
203
- for (const key of CCR_BASE_URL_KEYS) {
204
- if (isCcrGatewayUrl(baseEnv[key])) {
206
+ for (const key of BRIDGE_BASE_URL_KEYS) {
207
+ if (isCodexBridgeUrl(baseEnv[key])) {
205
208
  environment[key] = undefined;
206
- inheritedCcrTakeover = true;
209
+ inheritedBridgeTakeover = true;
207
210
  }
208
211
  }
209
- for (const key of CCR_MODEL_KEYS) {
210
- if (isCcrModelName(baseEnv[key])) {
212
+ for (const key of BRIDGE_MODEL_KEYS) {
213
+ if (isCodexBridgeModelName(baseEnv[key], baseEnv.CODEX_BRIDGE_CLAUDE_MODEL)) {
211
214
  environment[key] = undefined;
212
- inheritedCcrTakeover = true;
215
+ inheritedBridgeTakeover = true;
213
216
  }
214
217
  }
215
- for (const key of CCR_ONLY_ENV_KEYS) {
218
+ for (const key of BRIDGE_ONLY_ENV_KEYS) {
216
219
  if (baseEnv[key] !== undefined) {
217
220
  environment[key] = undefined;
218
- inheritedCcrTakeover = true;
221
+ inheritedBridgeTakeover = true;
219
222
  }
220
223
  }
221
- if (inheritedCcrTakeover) {
224
+ if (inheritedBridgeTakeover) {
222
225
  environment.ANTHROPIC_AUTH_TOKEN = undefined;
223
226
  environment.ANTHROPIC_API_KEY = undefined;
224
227
  }
225
228
  return environment;
226
229
  }
227
- function isCcrGatewayUrl(value) {
230
+ function isCodexBridgeUrl(value) {
228
231
  if (!value) {
229
232
  return false;
230
233
  }
@@ -237,32 +240,29 @@ function isCcrGatewayUrl(value) {
237
240
  return false;
238
241
  }
239
242
  }
240
- function isCcrModelName(value) {
241
- if (!value) {
242
- return false;
243
- }
244
- return value === CCR_GPT_MODEL_ID
245
- || value.startsWith("anthropic/claude-ccr-h");
243
+ function isCodexBridgeModelName(value, bridgeModel) {
244
+ return Boolean(value && bridgeModel && value === bridgeModel);
246
245
  }
247
246
  function createStatus(input) {
247
+ const { models, ...status } = input;
248
248
  const reason = input.error
249
- ?? (input.enabled ? "CCR GPT-5.6 Sol is unavailable." : "Enable CCR GPT models in Settings.");
249
+ ?? (input.enabled ? "Codex Bridge models are unavailable." : "Enable Codex Bridge in Settings.");
250
250
  return {
251
- ...input,
252
- modelOptions: createSessionModelOptions(input.enabled && input.modelAvailable, reason)
251
+ ...status,
252
+ modelOptions: createSessionModelOptions(models, input.enabled && input.modelAvailable ? undefined : reason)
253
253
  };
254
254
  }
255
255
  function missingApiKeyError() {
256
256
  return new VcmError({
257
- code: "CCR_API_KEY_MISSING",
258
- message: "CCR API key is not configured.",
257
+ code: "CODEX_BRIDGE_API_KEY_MISSING",
258
+ message: "Codex Bridge API key is not configured.",
259
259
  statusCode: 400,
260
- hint: "Save the CCR API key before enabling CCR GPT models."
260
+ hint: "Save the Codex Bridge API key before enabling Codex models."
261
261
  });
262
262
  }
263
263
  function invalidSettingsError(message) {
264
264
  return new VcmError({
265
- code: "CCR_SETTINGS_INVALID",
265
+ code: "CODEX_BRIDGE_SETTINGS_INVALID",
266
266
  message,
267
267
  statusCode: 400
268
268
  });