@iislee/opencodex 2.31.0 → 2.35.0
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 +3 -3
- package/bin/ocx.mjs +99 -70
- package/gui/dist/assets/index-Be1sDpWw.css +1 -0
- package/gui/dist/assets/index-D4OKgUV4.js +114 -0
- package/gui/dist/index.html +2 -2
- package/package.json +3 -1
- package/src/adapters/anthropic.ts +104 -15
- package/src/adapters/base.ts +29 -1
- package/src/adapters/command-code.ts +42 -6
- package/src/adapters/cursor/call-id.ts +44 -0
- package/src/adapters/cursor/catalog.ts +541 -0
- package/src/adapters/cursor/checkpoint-store.ts +15 -10
- package/src/adapters/cursor/cursor-errors.ts +15 -0
- package/src/adapters/cursor/discovery.ts +69 -18
- package/src/adapters/cursor/effort-map.ts +79 -1
- package/src/adapters/cursor/envelope-echo.ts +290 -0
- package/src/adapters/cursor/live-models.ts +7 -2
- package/src/adapters/cursor/live-transport.ts +14 -0
- package/src/adapters/cursor/message-mapper.ts +4 -1
- package/src/adapters/cursor/native-exec-desktop.ts +23 -0
- package/src/adapters/cursor/native-exec-fs.ts +2 -2
- package/src/adapters/cursor/native-exec-network.ts +1 -1
- package/src/adapters/cursor/native-exec-shell.ts +5 -2
- package/src/adapters/cursor/native-exec.ts +20 -0
- package/src/adapters/cursor/protobuf-request.ts +68 -14
- package/src/adapters/cursor/request-builder.ts +40 -10
- package/src/adapters/cursor/tool-definitions.ts +14 -4
- package/src/adapters/cursor/tool-result-normalize.ts +28 -5
- package/src/adapters/cursor/types.ts +20 -0
- package/src/adapters/cursor.ts +209 -38
- package/src/adapters/exec-tool-result-normalize.ts +99 -0
- package/src/adapters/google-antigravity-replay.ts +173 -25
- package/src/adapters/google-antigravity-wire.ts +5 -0
- package/src/adapters/google-errors.ts +44 -12
- package/src/adapters/google.ts +136 -24
- package/src/adapters/image.ts +1 -1
- package/src/adapters/kiro-constants.ts +27 -0
- package/src/adapters/kiro-tools.ts +55 -16
- package/src/adapters/kiro.ts +182 -23
- package/src/adapters/openai-chat.ts +300 -242
- package/src/adapters/openai-responses.ts +353 -27
- package/src/adapters/run-turn-queue.ts +36 -1
- package/src/adapters/tool-catalog-nudge.ts +4 -3
- package/src/adapters/xai-tool-schema.ts +436 -0
- package/src/adapters/xai-web-search.ts +17 -16
- package/src/bridge.ts +90 -37
- package/src/chat/inbound.ts +14 -1
- package/src/chat/outbound.ts +15 -7
- package/src/claude/agents-inject.ts +8 -1
- package/src/claude/context-windows.ts +16 -9
- package/src/claude/outbound.ts +24 -11
- package/src/cli/access.ts +46 -3
- package/src/cli/account-api.ts +116 -19
- package/src/cli/account-extended.ts +262 -29
- package/src/cli/account-main.ts +12 -12
- package/src/cli/account.ts +69 -15
- package/src/cli/agent.ts +8 -1
- package/src/cli/alias.ts +66 -0
- package/src/cli/capabilities-command.ts +94 -0
- package/src/cli/capabilities.ts +496 -0
- package/src/cli/claude-desktop.ts +31 -11
- package/src/cli/claude.ts +26 -1
- package/src/cli/dispatch.ts +256 -28
- package/src/cli/doctor.ts +126 -14
- package/src/cli/help.ts +17 -6
- package/src/cli/index.ts +39 -9
- package/src/cli/init.ts +1 -0
- package/src/cli/inspect.ts +230 -0
- package/src/cli/models-runtime.ts +95 -0
- package/src/cli/models.ts +26 -10
- package/src/cli/observe.ts +31 -8
- package/src/cli/provider-runtime.ts +16 -2
- package/src/cli/provider.ts +2 -1
- package/src/cli/registry.ts +49 -10
- package/src/cli/runtime-api.ts +51 -7
- package/src/cli/status.ts +41 -1
- package/src/cli/storage.ts +234 -0
- package/src/cli/system-command.ts +16 -0
- package/src/cli/system-restart-client.ts +1 -1
- package/src/cli/usage-report.ts +184 -0
- package/src/cli/v2.ts +34 -10
- package/src/cli/version-skew.ts +46 -0
- package/src/clients/config-export.ts +85 -3
- package/src/clients/effective-status.ts +30 -2
- package/src/clients/probes/cline.ts +81 -0
- package/src/codex/account-label.ts +21 -0
- package/src/codex/account-pause.ts +2 -1
- package/src/codex/account-priority.ts +3 -2
- package/src/codex/app-server-processes.ts +83 -7
- package/src/codex/auth-api.ts +50 -10
- package/src/codex/auth-context.ts +21 -18
- package/src/codex/autostart-health.ts +16 -0
- package/src/codex/catalog/aggregation.ts +18 -0
- package/src/codex/catalog/effort.ts +18 -3
- package/src/codex/catalog/metadata.ts +27 -1
- package/src/codex/catalog/native-models.ts +5 -2
- package/src/codex/catalog/parsing.ts +72 -27
- package/src/codex/catalog/provider-fetch.ts +187 -31
- package/src/codex/catalog/sync.ts +131 -5
- package/src/codex/catalog.ts +1 -1
- package/src/codex/codex-write-lock.ts +3 -1
- package/src/codex/convergence-types.ts +1 -1
- package/src/codex/convergence.ts +27 -2
- package/src/codex/desired-state.ts +2 -2
- package/src/codex/desktop-app-restart.ts +355 -0
- package/src/codex/history-job.ts +32 -3
- package/src/codex/history-manifest.ts +112 -0
- package/src/codex/history-migration-guardian.ts +5 -5
- package/src/codex/history-provider.ts +825 -247
- package/src/codex/history-worker.ts +8 -5
- package/src/codex/inject-coordination.ts +83 -0
- package/src/codex/inject.ts +63 -22
- package/src/codex/injected-marker.ts +1 -1
- package/src/codex/internal/history-writer.ts +4 -3
- package/src/codex/log-guard/inspect.ts +22 -4
- package/src/codex/model-entitlements.ts +9 -2
- package/src/codex/native-profile-startup.ts +157 -27
- package/src/codex/native-residue.ts +26 -33
- package/src/codex/prompt-layers.ts +371 -25
- package/src/codex/prompt-text-probe.ts +238 -0
- package/src/codex/quota.ts +91 -10
- package/src/codex/routing.ts +9 -0
- package/src/codex/shim.ts +56 -3
- package/src/codex/subagent-model-fallback.ts +104 -25
- package/src/codex/transition-state.ts +116 -8
- package/src/combos/failover.ts +27 -0
- package/src/combos/types.ts +10 -0
- package/src/compatibility/index.ts +26 -0
- package/src/compatibility/manifest.ts +253 -0
- package/src/compatibility/openai-responses.ts +121 -0
- package/src/config/atomic-write.ts +219 -0
- package/src/config/paths.ts +40 -0
- package/src/config/process-state.ts +309 -0
- package/src/config/provider-validation.ts +177 -0
- package/src/config/rebase-provenance.ts +68 -0
- package/src/config.ts +206 -824
- package/src/generated/compatibility-version.json +373 -213
- package/src/images/loop.ts +5 -4
- package/src/images/plan.ts +5 -4
- package/src/integrations/ownership-policy.ts +160 -0
- package/src/integrations/ownership.ts +46 -2
- package/src/integrations/registry.ts +7 -0
- package/src/integrations/state.ts +79 -7
- package/src/integrations/writer.ts +26 -2
- package/src/lab/conformance/fixtures/protocol-v1-cases.json +1 -1
- package/src/lab/fabric/producer-child.ts +1 -1
- package/src/lib/admin-secrets.ts +24 -0
- package/src/lib/bounded-body.ts +14 -2
- package/src/lib/config-ownership.ts +20 -0
- package/src/lib/errors.ts +36 -3
- package/src/lib/package-tree-integrity.ts +101 -0
- package/src/lib/process-control.ts +2 -1
- package/src/lib/service-secrets.ts +15 -0
- package/src/lib/tool-argument-integers.ts +56 -5
- package/src/oauth/callback-server.ts +22 -2
- package/src/oauth/cline.ts +203 -0
- package/src/oauth/generic-account-failover.ts +231 -0
- package/src/oauth/health.ts +1 -1
- package/src/oauth/index.ts +65 -6
- package/src/oauth/key-providers.ts +10 -1
- package/src/oauth/kimi.ts +9 -1
- package/src/oauth/kiro.ts +45 -0
- package/src/oauth/local-token-detect.ts +2 -0
- package/src/oauth/open-browser-choice.ts +26 -0
- package/src/oauth/store.ts +14 -5
- package/src/oauth/types.ts +15 -0
- package/src/providers/auto-compact-budget.ts +65 -0
- package/src/providers/command-code-efforts.ts +38 -6
- package/src/providers/context-cap.ts +4 -3
- package/src/providers/default-aliases.ts +65 -0
- package/src/providers/derive.ts +28 -0
- package/src/providers/fastwire.ts +7 -1
- package/src/providers/label.ts +34 -1
- package/src/providers/model-presets.ts +119 -0
- package/src/providers/new-model-policy.ts +146 -0
- package/src/providers/provider-id-rewrite.ts +2 -1
- package/src/providers/quota.ts +65 -7
- package/src/providers/registry.ts +184 -69
- package/src/providers/slug-codec.ts +52 -0
- package/src/providers/xai-transport.ts +21 -0
- package/src/reasoning-effort.ts +19 -2
- package/src/responses/apply-patch-envelope.ts +63 -0
- package/src/responses/code-mode-helper-compat.ts +50 -0
- package/src/responses/custom-tool-compat.ts +157 -39
- package/src/responses/namespace-tool-compat.ts +84 -4
- package/src/responses/parser.ts +7 -2
- package/src/responses/reasoning-replay-cache.ts +81 -3
- package/src/responses/schema.ts +5 -1
- package/src/responses/state.ts +94 -4
- package/src/responses/thought-signature-replay.ts +17 -0
- package/src/responses/turn-termination.ts +107 -0
- package/src/router.ts +40 -2
- package/src/routing/analytics.ts +1 -0
- package/src/routing/quota.ts +10 -0
- package/src/server/auth-cors.ts +27 -7
- package/src/server/chat-completions.ts +24 -16
- package/src/server/chat-native-sse.ts +3 -3
- package/src/server/chat-native.ts +30 -11
- package/src/server/claude-messages.ts +1 -1
- package/src/server/index.ts +179 -32
- package/src/server/lifecycle.ts +52 -1
- package/src/server/local-management-read-client.ts +1 -1
- package/src/server/local-provider-reload-client.ts +1 -1
- package/src/server/management/agent-settings-routes.ts +45 -23
- package/src/server/management/codex-prompt-routes.ts +570 -0
- package/src/server/management/combo-routes.ts +2 -1
- package/src/server/management/config-routes.ts +59 -12
- package/src/server/management/context.ts +10 -1
- package/src/server/management/logs-usage-routes.ts +30 -24
- package/src/server/management/model-routes.ts +274 -4
- package/src/server/management/model-rows.ts +4 -0
- package/src/server/management/native-integration-routes.ts +2 -1
- package/src/server/management/oauth-account-routes.ts +10 -4
- package/src/server/management/provider-capability-config.ts +1 -1
- package/src/server/management/provider-routes.ts +81 -11
- package/src/server/management/route-registry.ts +332 -0
- package/src/server/management/routing-profile-routes.ts +2 -2
- package/src/server/management/system-restart.ts +1 -1
- package/src/server/management-api.ts +18 -16
- package/src/server/port-reclaim.ts +1 -1
- package/src/server/proxy-liveness.ts +29 -5
- package/src/server/relay-eager.ts +147 -20
- package/src/server/relay.ts +251 -19
- package/src/server/request-log-conversation.ts +51 -0
- package/src/server/request-log.ts +70 -16
- package/src/server/responses/codex-auth-error.ts +55 -0
- package/src/server/responses/collaboration.ts +37 -3
- package/src/server/responses/combo-stream-preflight.ts +178 -0
- package/src/server/responses/compact.ts +6 -21
- package/src/server/responses/core.ts +810 -208
- package/src/server/responses/empty-completion-guard.ts +63 -6
- package/src/server/responses/fetch-helpers.ts +17 -102
- package/src/server/responses/input-admission.ts +3 -1
- package/src/server/responses/passthrough-error.ts +33 -9
- package/src/server/responses/responses-field-backfill.ts +105 -13
- package/src/server/responses/ws-upstream.ts +75 -2
- package/src/server/responses-custom-tool-repair.ts +87 -6
- package/src/server/responses-terminal-repair.ts +25 -4
- package/src/server/responses-undeclared-tool-guard.ts +241 -18
- package/src/server/sse-frame-buffer.ts +31 -4
- package/src/server/ws-bridge.ts +14 -2
- package/src/service.ts +42 -4
- package/src/storage/policy-job.ts +14 -4
- package/src/storage/policy.ts +88 -23
- package/src/types/config.ts +66 -0
- package/src/types/provider.ts +69 -0
- package/src/types/request.ts +17 -4
- package/src/types/tools.ts +116 -11
- package/src/types.ts +3 -1
- package/src/update/index.ts +5 -4
- package/src/update/job.ts +3 -1
- package/src/update/transactional-install.mjs +8 -1
- package/src/usage/expected-prices.ts +43 -24
- package/src/usage/log.ts +63 -12
- package/src/usage/summary.ts +211 -8
- package/src/vision/describe.ts +18 -13
- package/src/web-search/exa-executor.ts +40 -9
- package/src/web-search/executor.ts +10 -3
- package/src/web-search/loop.ts +5 -4
- package/gui/dist/assets/index-BF38heuV.js +0 -104
- package/gui/dist/assets/index-DMiI18Kv.css +0 -1
package/src/server/lifecycle.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
1
2
|
import { flushAntigravityReplay } from "../adapters/google-antigravity-replay";
|
|
2
3
|
import { flushResponseState } from "../responses/state";
|
|
3
4
|
import { setStorageCleanupPolicyLiveSink } from "../storage/policy";
|
|
@@ -30,6 +31,8 @@ import { releaseNativeMainStartupLifecycle } from "../codex/native-profile-start
|
|
|
30
31
|
// ---------------------------------------------------------------------------
|
|
31
32
|
|
|
32
33
|
export const MAX_ACTIVE_TURNS = 256;
|
|
34
|
+
export const MAX_ACTIVE_SESSION_LANES = 64;
|
|
35
|
+
export const SESSION_LANE_ID_BYTES = 32;
|
|
33
36
|
const turnGate = createAdmissionGate("active_turns", MAX_ACTIVE_TURNS);
|
|
34
37
|
export interface ActiveTurnLease extends AdmissionLease {
|
|
35
38
|
bindAbortController(ac: AbortController): void;
|
|
@@ -38,6 +41,10 @@ export interface ActiveTurnLease extends AdmissionLease {
|
|
|
38
41
|
}
|
|
39
42
|
const activeTurns = new Map<AbortController, ActiveTurnLease>();
|
|
40
43
|
const admittedTurns = new Set<ActiveTurnLease>();
|
|
44
|
+
const activeSessionLaneRefCounts = new Map<string, number>();
|
|
45
|
+
let sessionLanePeak = 0;
|
|
46
|
+
let sessionLaneAdmitted = 0;
|
|
47
|
+
let sessionLaneRejected = 0;
|
|
41
48
|
const knownTurnControllers = new WeakSet<AbortController>();
|
|
42
49
|
let turnReleaseMisses = 0;
|
|
43
50
|
let shutdownDraining = false;
|
|
@@ -149,6 +156,10 @@ export function resetLifecycleDrainStateForTests(): void {
|
|
|
149
156
|
temporaryDrainOwners.clear();
|
|
150
157
|
nativeMainDrainOwners.clear();
|
|
151
158
|
nativeMainTurns.clear();
|
|
159
|
+
activeSessionLaneRefCounts.clear();
|
|
160
|
+
sessionLanePeak = 0;
|
|
161
|
+
sessionLaneAdmitted = 0;
|
|
162
|
+
sessionLaneRejected = 0;
|
|
152
163
|
nativeMainSelections = 0;
|
|
153
164
|
for (const resolve of temporaryDrainWaiters) resolve();
|
|
154
165
|
temporaryDrainWaiters.clear();
|
|
@@ -157,10 +168,27 @@ export function resetLifecycleDrainStateForTests(): void {
|
|
|
157
168
|
serverStartupReleaseFlights = new WeakMap<ReturnType<typeof Bun.serve>, Promise<void>>();
|
|
158
169
|
releaseServerStartupLifecycleImpl = releaseNativeMainStartupLifecycle;
|
|
159
170
|
}
|
|
160
|
-
export function tryAdmitTurn(): ActiveTurnLease | null {
|
|
171
|
+
export function tryAdmitTurn(sessionLaneId?: string): ActiveTurnLease | null {
|
|
161
172
|
if (isDraining()) return null;
|
|
173
|
+
const opaqueSessionLaneId = sessionLaneId
|
|
174
|
+
? createHash("sha256").update(sessionLaneId).digest("hex").slice(0, SESSION_LANE_ID_BYTES)
|
|
175
|
+
: undefined;
|
|
176
|
+
const sessionLaneRefCount = opaqueSessionLaneId
|
|
177
|
+
? activeSessionLaneRefCounts.get(opaqueSessionLaneId) ?? 0
|
|
178
|
+
: 0;
|
|
179
|
+
if (opaqueSessionLaneId && sessionLaneRefCount === 0 && activeSessionLaneRefCounts.size >= MAX_ACTIVE_SESSION_LANES) {
|
|
180
|
+
sessionLaneRejected += 1;
|
|
181
|
+
return null;
|
|
182
|
+
}
|
|
162
183
|
const gateLease = turnGate.tryAcquire();
|
|
163
184
|
if (!gateLease) return null;
|
|
185
|
+
if (opaqueSessionLaneId) {
|
|
186
|
+
activeSessionLaneRefCounts.set(opaqueSessionLaneId, sessionLaneRefCount + 1);
|
|
187
|
+
if (sessionLaneRefCount === 0) {
|
|
188
|
+
sessionLaneAdmitted += 1;
|
|
189
|
+
sessionLanePeak = Math.max(sessionLanePeak, activeSessionLaneRefCounts.size);
|
|
190
|
+
}
|
|
191
|
+
}
|
|
164
192
|
const controllers = new Set<AbortController>();
|
|
165
193
|
let active = true;
|
|
166
194
|
let transferred = false;
|
|
@@ -211,6 +239,13 @@ export function tryAdmitTurn(): ActiveTurnLease | null {
|
|
|
211
239
|
}
|
|
212
240
|
controllers.clear();
|
|
213
241
|
nativeMainTurns.delete(lease);
|
|
242
|
+
if (opaqueSessionLaneId) {
|
|
243
|
+
const currentRefCount = activeSessionLaneRefCounts.get(opaqueSessionLaneId);
|
|
244
|
+
if (currentRefCount === 1) activeSessionLaneRefCounts.delete(opaqueSessionLaneId);
|
|
245
|
+
else if (currentRefCount && currentRefCount > 1) {
|
|
246
|
+
activeSessionLaneRefCounts.set(opaqueSessionLaneId, currentRefCount - 1);
|
|
247
|
+
}
|
|
248
|
+
}
|
|
214
249
|
gateLease.release();
|
|
215
250
|
},
|
|
216
251
|
};
|
|
@@ -261,6 +296,22 @@ export function unregisterTurn(ac: AbortController): void {
|
|
|
261
296
|
}
|
|
262
297
|
export function isDraining(): boolean { return shutdownDraining || temporaryDrainOwners.size > 0; }
|
|
263
298
|
export function getActiveTurnCount(): number { return turnGate.metrics().active; }
|
|
299
|
+
export interface SessionLaneMetrics {
|
|
300
|
+
active: number;
|
|
301
|
+
peak: number;
|
|
302
|
+
admitted: number;
|
|
303
|
+
rejected: number;
|
|
304
|
+
retainedBytes: number;
|
|
305
|
+
}
|
|
306
|
+
export function sessionLaneMetrics(): SessionLaneMetrics {
|
|
307
|
+
return {
|
|
308
|
+
active: activeSessionLaneRefCounts.size,
|
|
309
|
+
peak: sessionLanePeak,
|
|
310
|
+
admitted: sessionLaneAdmitted,
|
|
311
|
+
rejected: sessionLaneRejected,
|
|
312
|
+
retainedBytes: activeSessionLaneRefCounts.size * SESSION_LANE_ID_BYTES,
|
|
313
|
+
};
|
|
314
|
+
}
|
|
264
315
|
export function getNativeMainProfileRequestCount(): number {
|
|
265
316
|
return nativeMainSelections + nativeMainTurns.size;
|
|
266
317
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { readRuntimePort, type RuntimePortState } from "../config";
|
|
1
|
+
import { readRuntimePort, type RuntimePortState } from "../config/process-state";
|
|
2
2
|
import { createLocalAttestationChallenge } from "../lib/local-management-attestation";
|
|
3
3
|
import {
|
|
4
4
|
LOCAL_MANAGEMENT_CAPABILITY_HEADER,
|
|
@@ -5,6 +5,7 @@ import { catalogModelSlug, invalidateCodexModelsCache, nativeContextLimits, nati
|
|
|
5
5
|
import {
|
|
6
6
|
DEFAULT_SUBAGENT_MODELS,
|
|
7
7
|
codexAutoStartEnabled,
|
|
8
|
+
deleteConfigTopLevelKey,
|
|
8
9
|
hasOwnProvider,
|
|
9
10
|
isValidProviderName,
|
|
10
11
|
loadConfig,
|
|
@@ -60,6 +61,7 @@ import {
|
|
|
60
61
|
webSearchCandidateRows,
|
|
61
62
|
webSearchModelIsRejected,
|
|
62
63
|
webSearchModelRejection,
|
|
64
|
+
type WebSearchBackend,
|
|
63
65
|
} from "./web-search-sidecar-options";
|
|
64
66
|
import { drainAndShutdown } from "../lifecycle";
|
|
65
67
|
import { filterRequestLogs, getRequestLogEntries, type RequestLogEntry } from "../request-log";
|
|
@@ -94,7 +96,7 @@ function mirrorDesiredEnabledOntoSnapshot(config: OcxConfig, client: "claude-des
|
|
|
94
96
|
const integrations = { ...(config.clientIntegrations ?? {}) };
|
|
95
97
|
if (enabled) delete integrations[client];
|
|
96
98
|
else integrations[client] = false;
|
|
97
|
-
if (Object.keys(integrations).length === 0)
|
|
99
|
+
if (Object.keys(integrations).length === 0) deleteConfigTopLevelKey(config, "clientIntegrations");
|
|
98
100
|
else config.clientIntegrations = integrations;
|
|
99
101
|
}
|
|
100
102
|
|
|
@@ -148,7 +150,7 @@ function runGrokApplyFlight(): Promise<unknown> {
|
|
|
148
150
|
flight.promise = (grokApplyTestHooks?.run ?? (async () => {
|
|
149
151
|
const [{ syncGrokConfig }, { readRuntimePort }] = await Promise.all([
|
|
150
152
|
import("../../grok/sync"),
|
|
151
|
-
import("../../config"),
|
|
153
|
+
import("../../config/process-state"),
|
|
152
154
|
]);
|
|
153
155
|
const currentConfig = loadConfig();
|
|
154
156
|
const runtime = readRuntimePort(process.pid);
|
|
@@ -305,9 +307,18 @@ export async function handleAgentSettingsRoutes(ctx: ManagementContext): Promise
|
|
|
305
307
|
return jsonResponse({ error: "body.multiAgentModeHintText must be a non-empty string or null" }, 400);
|
|
306
308
|
}
|
|
307
309
|
const mode = wantsMode ? body.multiAgentMode as "v1" | "default" | "v2" : undefined;
|
|
308
|
-
const
|
|
310
|
+
const effectiveMode = mode ?? config.multiAgentMode ?? "default";
|
|
311
|
+
const effectiveKeepNative = wantsKeepNative
|
|
312
|
+
? body.keepNativeChatGptOnV1 === true
|
|
313
|
+
: config.keepNativeChatGptOnV1 === true;
|
|
314
|
+
const hybridPinActive = effectiveMode === "v2" && effectiveKeepNative;
|
|
315
|
+
const modeFlag = mode === "v2" ? !hybridPinActive : mode === "v1" ? false : undefined;
|
|
309
316
|
if (wantsFlag && modeFlag !== undefined && body.enabled !== modeFlag) {
|
|
310
|
-
return jsonResponse({
|
|
317
|
+
return jsonResponse({
|
|
318
|
+
error: hybridPinActive
|
|
319
|
+
? "body.enabled=true conflicts with keepNativeChatGptOnV1: Codex's global multi_agent_v2 override outranks catalog pins"
|
|
320
|
+
: `body.enabled conflicts with multiAgentMode '${mode}'`,
|
|
321
|
+
}, 400);
|
|
311
322
|
}
|
|
312
323
|
const {
|
|
313
324
|
isMultiAgentV2Enabled, hasAgentsMaxThreads, getLogicalMaxThreads, transitionMultiAgentV2,
|
|
@@ -325,7 +336,14 @@ export async function handleAgentSettingsRoutes(ctx: ManagementContext): Promise
|
|
|
325
336
|
}, 502);
|
|
326
337
|
}
|
|
327
338
|
const warnings: string[] = [];
|
|
328
|
-
|
|
339
|
+
if (wantsFlag && body.enabled === true && hybridPinActive) {
|
|
340
|
+
return jsonResponse({
|
|
341
|
+
error: "body.enabled=true conflicts with keepNativeChatGptOnV1: Codex's global multi_agent_v2 override outranks catalog pins",
|
|
342
|
+
}, 400);
|
|
343
|
+
}
|
|
344
|
+
const requestedFlag = wantsFlag
|
|
345
|
+
? body.enabled as boolean
|
|
346
|
+
: modeFlag ?? (wantsKeepNative && hybridPinActive ? false : undefined);
|
|
329
347
|
if (requestedFlag !== undefined || wantsThreads) {
|
|
330
348
|
const targetFlag = requestedFlag ?? isMultiAgentV2Enabled();
|
|
331
349
|
let toggle = deps.toggleCodexMultiAgentV2;
|
|
@@ -340,16 +358,15 @@ export async function handleAgentSettingsRoutes(ctx: ManagementContext): Promise
|
|
|
340
358
|
if (result.changed && result.threadLimit !== null) warnings.push(`Thread limit ${result.threadLimit} preserved for ${targetFlag ? "v2" : "v1"}.`);
|
|
341
359
|
}
|
|
342
360
|
if (wantsMode) {
|
|
343
|
-
if (mode === "default")
|
|
361
|
+
if (mode === "default") deleteConfigTopLevelKey(config, "multiAgentMode");
|
|
344
362
|
else config.multiAgentMode = mode;
|
|
345
363
|
saveConfigPreservingClaudeCode(config);
|
|
346
364
|
warnings.push(`Multi-agent mode set to '${mode}'. Applies to new sessions.`);
|
|
347
365
|
}
|
|
348
366
|
if (wantsKeepNative) {
|
|
349
367
|
if (body.keepNativeChatGptOnV1 === true) config.keepNativeChatGptOnV1 = true;
|
|
350
|
-
else
|
|
368
|
+
else deleteConfigTopLevelKey(config, "keepNativeChatGptOnV1");
|
|
351
369
|
saveConfigPreservingClaudeCode(config);
|
|
352
|
-
const effectiveMode = mode ?? config.multiAgentMode ?? "default";
|
|
353
370
|
warnings.push(body.keepNativeChatGptOnV1 === true
|
|
354
371
|
? (effectiveMode === "v2"
|
|
355
372
|
? "ChatGPT-native models stay on v1 while other models use v2. Applies to new sessions."
|
|
@@ -558,13 +575,13 @@ export async function handleAgentSettingsRoutes(ctx: ManagementContext): Promise
|
|
|
558
575
|
|
|
559
576
|
config.multiAgentGuidanceEnabled = nextEnabled;
|
|
560
577
|
if (nextSyncCodexSubagentDefaults) config.syncCodexSubagentDefaults = true;
|
|
561
|
-
else
|
|
578
|
+
else deleteConfigTopLevelKey(config, "syncCodexSubagentDefaults");
|
|
562
579
|
if (nextModel) config.injectionModel = nextModel;
|
|
563
|
-
else
|
|
580
|
+
else deleteConfigTopLevelKey(config, "injectionModel");
|
|
564
581
|
if (nextEffort) config.injectionEffort = nextEffort;
|
|
565
|
-
else
|
|
582
|
+
else deleteConfigTopLevelKey(config, "injectionEffort");
|
|
566
583
|
if (nextPrompt) config.injectionPrompt = nextPrompt;
|
|
567
|
-
else
|
|
584
|
+
else deleteConfigTopLevelKey(config, "injectionPrompt");
|
|
568
585
|
|
|
569
586
|
saveConfigPreservingClaudeCode(config);
|
|
570
587
|
return jsonResponse({
|
|
@@ -595,7 +612,7 @@ export async function handleAgentSettingsRoutes(ctx: ManagementContext): Promise
|
|
|
595
612
|
for (const key of ["effortCap", "subagentEffortCap"] as const) {
|
|
596
613
|
if (!(key in body)) continue;
|
|
597
614
|
const value = body[key];
|
|
598
|
-
if (value === null || value === "") {
|
|
615
|
+
if (value === null || value === "") { deleteConfigTopLevelKey(config, key); continue; }
|
|
599
616
|
if (typeof value !== "string" || !isCodexReasoningEffort(value)) {
|
|
600
617
|
return jsonResponse({ error: `unknown reasoning effort "${String(value)}"` }, 400);
|
|
601
618
|
}
|
|
@@ -714,9 +731,9 @@ export async function handleAgentSettingsRoutes(ctx: ManagementContext): Promise
|
|
|
714
731
|
}
|
|
715
732
|
}
|
|
716
733
|
if (nextModels !== undefined) config.subagentModelFallback = nextModels;
|
|
717
|
-
else
|
|
734
|
+
else deleteConfigTopLevelKey(config, "subagentModelFallback");
|
|
718
735
|
if (nextPollMs !== undefined) config.subagentModelFallbackPollMs = nextPollMs;
|
|
719
|
-
else
|
|
736
|
+
else deleteConfigTopLevelKey(config, "subagentModelFallbackPollMs");
|
|
720
737
|
saveConfigPreservingClaudeCode(config);
|
|
721
738
|
return jsonResponse({
|
|
722
739
|
ok: true,
|
|
@@ -757,7 +774,7 @@ export async function handleAgentSettingsRoutes(ctx: ManagementContext): Promise
|
|
|
757
774
|
// cannot grow config.json without bound.
|
|
758
775
|
const excluded = [...new Set(raw as string[])].sort();
|
|
759
776
|
if (excluded.length > 2000) return jsonResponse({ error: "excluded list is too large" }, 400);
|
|
760
|
-
if (excluded.length === 0)
|
|
777
|
+
if (excluded.length === 0) deleteConfigTopLevelKey(config, "grokExcludedModels");
|
|
761
778
|
else config.grokExcludedModels = excluded;
|
|
762
779
|
saveConfigPreservingClaudeCode(config);
|
|
763
780
|
return jsonResponse({ ok: true, excluded });
|
|
@@ -1248,13 +1265,18 @@ export async function handleAgentSettingsRoutes(ctx: ManagementContext): Promise
|
|
|
1248
1265
|
if (field === "webSearchSidecar"
|
|
1249
1266
|
&& (section.model !== undefined || section.backend !== undefined)) {
|
|
1250
1267
|
const stored = config.claudeCode?.webSearchSidecar;
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
|
|
1268
|
+
// Validate against the SUBMITTED backend across the whole union, not
|
|
1269
|
+
// just openai/anthropic (#2457). allowedBackends above already refused
|
|
1270
|
+
// unknown literals; Array.includes does not narrow, hence the cast.
|
|
1271
|
+
// null keeps its own meaning here — drop the override and inherit the
|
|
1272
|
+
// global backend — which is deliberately NOT the sidecar-settings rule.
|
|
1273
|
+
const submittedBackend = section.backend;
|
|
1274
|
+
const effectiveBackend = typeof submittedBackend === "string"
|
|
1275
|
+
&& allowedBackends.includes(submittedBackend)
|
|
1276
|
+
? submittedBackend as WebSearchBackend
|
|
1277
|
+
: submittedBackend === null
|
|
1278
|
+
? config.webSearchSidecar?.backend ?? "openai"
|
|
1279
|
+
: stored?.backend ?? config.webSearchSidecar?.backend ?? "openai";
|
|
1258
1280
|
const effectiveModel = section.model === ""
|
|
1259
1281
|
? config.webSearchSidecar?.model
|
|
1260
1282
|
: typeof section.model === "string"
|