@bitkyc08/opencodex 2.42.0 → 2.43.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/AGENTS_INSTALL.md +2 -2
- package/README.md +31 -0
- package/bin/ocx.mjs +10 -1
- package/gui/dist/assets/index-DS1NE4Jn.css +1 -0
- package/gui/dist/assets/index-Djowl68T.js +112 -0
- package/gui/dist/index.html +2 -2
- package/package.json +1 -1
- package/src/adapters/anthropic-image-codec.ts +304 -0
- package/src/adapters/anthropic-image-normalize.ts +8 -298
- package/src/adapters/anthropic.ts +30 -7
- package/src/adapters/command-code.ts +7 -5
- package/src/adapters/cursor/desktop-executor-contract.ts +15 -0
- package/src/adapters/cursor/images.ts +36 -6
- package/src/adapters/cursor/live-transport.ts +7 -2
- package/src/adapters/cursor/native-exec-desktop.ts +2 -15
- package/src/adapters/cursor/protobuf-request.ts +13 -3
- package/src/adapters/cursor/tool-definitions.ts +5 -670
- package/src/adapters/cursor/tool-guidance.ts +236 -0
- package/src/adapters/cursor/tool-naming.ts +252 -0
- package/src/adapters/cursor/tool-schemas.ts +195 -0
- package/src/adapters/cursor/types.ts +6 -3
- package/src/adapters/exec-tool-result-normalize.ts +1 -1
- package/src/adapters/google-errors.ts +9 -1
- package/src/adapters/google.ts +1 -0
- package/src/adapters/kiro-calibration.ts +181 -0
- package/src/adapters/kiro.ts +135 -3
- package/src/adapters/openai-responses.ts +216 -26
- package/src/adapters/responses-code-mode.ts +59 -0
- package/src/adapters/tool-catalog-nudge.ts +1 -1
- package/src/adapters/xai-schema-analysis.ts +86 -0
- package/src/adapters/xai-tool-schema.ts +2 -87
- package/src/adapters/xai-web-search.ts +1 -1
- package/src/bridge.ts +22 -10
- package/src/chat/inbound.ts +11 -3
- package/src/claude/inbound-content-options.ts +60 -0
- package/src/claude/inbound-model-options.ts +142 -0
- package/src/claude/inbound-records.ts +7 -0
- package/src/claude/inbound.ts +10 -202
- package/src/claude/model-info.ts +45 -0
- package/src/cli/account-auth.ts +21 -6
- package/src/cli/capabilities.ts +13 -2
- package/src/cli/claude.ts +232 -39
- package/src/cli/config-command.ts +9 -1
- package/src/cli/dispatch.ts +5 -1
- package/src/cli/doctor.ts +10 -0
- package/src/cli/effort.ts +372 -0
- package/src/cli/export-command.ts +3 -9
- package/src/cli/help.ts +1 -0
- package/src/cli/index.ts +13 -0
- package/src/cli/init.ts +4 -0
- package/src/cli/model-selection-guidance.ts +30 -0
- package/src/cli/models-runtime.ts +3 -2
- package/src/cli/models.ts +8 -3
- package/src/cli/opencode.ts +4 -1
- package/src/cli/provider-runtime.ts +65 -0
- package/src/cli/provider.ts +8 -0
- package/src/cli/registry.ts +16 -2
- package/src/cli/runtime-api.ts +3 -1
- package/src/cli/star-prompt.ts +22 -6
- package/src/cli/status-probes.ts +168 -0
- package/src/cli/status.ts +5 -168
- package/src/clients/config-export/constants.ts +69 -0
- package/src/clients/config-export/contracts.ts +154 -0
- package/src/clients/config-export/dsh.ts +132 -0
- package/src/clients/config-export/fast-models.ts +29 -0
- package/src/clients/config-export/mcode.ts +83 -0
- package/src/clients/config-export/model-metadata.ts +108 -0
- package/src/clients/config-export/omp.ts +104 -0
- package/src/clients/config-export/zcode.ts +92 -0
- package/src/clients/config-export.ts +18 -710
- package/src/codex/account-lifecycle.ts +20 -3
- package/src/codex/account-usability.ts +2 -0
- package/src/codex/auth-api.ts +170 -23
- package/src/codex/auth-context.ts +328 -24
- package/src/codex/catalog/effort.ts +30 -4
- package/src/codex/catalog/metadata.ts +39 -9
- package/src/codex/catalog/native-models.ts +53 -12
- package/src/codex/catalog/parsing.ts +119 -5
- package/src/codex/catalog/provider-fetch.ts +150 -20
- package/src/codex/catalog/reserve.ts +52 -0
- package/src/codex/catalog/sync.ts +89 -16
- package/src/codex/convergence-types.ts +1 -0
- package/src/codex/convergence.ts +2 -0
- package/src/codex/data/upstream-models.json +1 -1
- package/src/codex/forward-transport-headers.ts +25 -0
- package/src/codex/inject.ts +3 -28
- package/src/codex/legacy-config-keys.ts +68 -0
- package/src/codex/log-guard/inspect-schema.ts +137 -0
- package/src/codex/log-guard/inspect.ts +2 -134
- package/src/codex/loopback-target.ts +54 -0
- package/src/codex/main-account-cache.ts +63 -1
- package/src/codex/main-account-hard-lock.ts +52 -0
- package/src/codex/main-account.ts +3 -1
- package/src/codex/management-convergence.ts +3 -0
- package/src/codex/model-entitlements.ts +54 -4
- package/src/codex/project-config-warnings.ts +92 -2
- package/src/codex/prompt-layers/encoding.ts +80 -0
- package/src/codex/prompt-layers/paths.ts +54 -0
- package/src/codex/prompt-layers/revision.ts +55 -0
- package/src/codex/prompt-layers/toml-edit.ts +163 -0
- package/src/codex/prompt-layers/toml-read.ts +181 -0
- package/src/codex/prompt-layers.ts +14 -520
- package/src/codex/quota-auto-refresh-state.ts +16 -0
- package/src/codex/quota-auto-refresh.ts +219 -0
- package/src/codex/quota-types.ts +51 -0
- package/src/codex/quota.ts +252 -93
- package/src/codex/reserve-availability.ts +177 -0
- package/src/codex/routing.ts +28 -9
- package/src/codex/shim.ts +53 -11
- package/src/codex/subagent-model-fallback.ts +23 -3
- package/src/combos/failover.ts +125 -7
- package/src/combos/identifiers.ts +89 -0
- package/src/combos/index.ts +4 -0
- package/src/combos/resolve.ts +80 -9
- package/src/combos/types.ts +20 -93
- package/src/config/subagent-models.ts +24 -0
- package/src/config.ts +156 -13
- package/src/generated/compatibility-version.json +454 -166
- package/src/generated/model-metadata.ts +1 -1
- package/src/integrations/journal.ts +65 -4
- package/src/integrations/store.ts +5 -0
- package/src/lab/events/limits.ts +4 -0
- package/src/lib/destination-policy.ts +31 -2
- package/src/lib/errors.ts +39 -0
- package/src/lib/provider-outbound.ts +69 -3
- package/src/lib/proxy-env.ts +22 -0
- package/src/lib/redact-folding.ts +176 -0
- package/src/lib/redact.ts +2 -175
- package/src/lib/state-store-sweeper.ts +20 -6
- package/src/lib/token-estimate.ts +94 -27
- package/src/lib/windows-user-principal.ts +53 -5
- package/src/oauth/anthropic-routing.ts +99 -3
- package/src/oauth/generic-account-failover.ts +36 -13
- package/src/oauth/index.ts +127 -26
- package/src/oauth/login-cli.ts +5 -0
- package/src/oauth/meta-muse.ts +117 -15
- package/src/oauth/pool-settings-capability.ts +15 -4
- package/src/providers/api-keys.ts +8 -10
- package/src/providers/default-aliases.ts +39 -0
- package/src/providers/derive.ts +10 -2
- package/src/providers/fastwire.ts +36 -7
- package/src/providers/initial-model-selection-runtime.ts +90 -0
- package/src/providers/initial-model-selection.ts +120 -0
- package/src/providers/key-failover.ts +134 -54
- package/src/providers/key-store.ts +11 -1
- package/src/providers/label.ts +1 -1
- package/src/providers/model-discovery.ts +76 -0
- package/src/providers/model-rename-startup.ts +72 -8
- package/src/providers/openai-sidecar.ts +17 -5
- package/src/providers/openai-tiers-destination.ts +102 -0
- package/src/providers/openai-tiers.ts +2 -99
- package/src/providers/opencode-go-transport.ts +41 -0
- package/src/providers/quota-key-accounts.ts +141 -0
- package/src/providers/quota-types.ts +9 -0
- package/src/providers/quota.ts +535 -104
- package/src/providers/registry.ts +60 -17
- package/src/providers/xai-responses-opt-in.ts +31 -5
- package/src/quota/reset-activation.ts +81 -0
- package/src/quota/reset-detector.ts +305 -0
- package/src/quota/reset-notify-config.ts +162 -0
- package/src/quota/reset-observer.ts +125 -0
- package/src/quota/reset-poller.ts +160 -0
- package/src/quota/reset-seen-store.ts +385 -0
- package/src/quota/reset-sinks.ts +199 -0
- package/src/quota/window-mapping.ts +106 -0
- package/src/responses/apply-patch-envelope.ts +46 -0
- package/src/responses/code-mode-helper-compat.ts +39 -1
- package/src/responses/custom-tool-compat.ts +10 -4
- package/src/responses/hosted-tool-policy.ts +12 -4
- package/src/responses/parser-content.ts +133 -0
- package/src/responses/parser-text-format.ts +24 -0
- package/src/responses/parser-tools.ts +188 -0
- package/src/responses/parser.ts +3 -326
- package/src/responses/state.ts +124 -28
- package/src/router.ts +48 -13
- package/src/routing/analytics.ts +1 -0
- package/src/routing/capability.ts +17 -4
- package/src/server/auth-cors.ts +7 -1
- package/src/server/background-lifecycle.ts +23 -1
- package/src/server/chat-completions.ts +25 -3
- package/src/server/claude-messages.ts +62 -5
- package/src/server/effort-row.ts +1 -1
- package/src/server/fast-row.ts +295 -0
- package/src/server/gui-static.ts +30 -4
- package/src/server/index.ts +107 -21
- package/src/server/management/agent-settings-routes.ts +2 -2
- package/src/server/management/combo-routes.ts +37 -9
- package/src/server/management/config-routes.ts +93 -2
- package/src/server/management/integration-routes.ts +108 -0
- package/src/server/management/model-routes.ts +13 -3
- package/src/server/management/model-rows.ts +20 -1
- package/src/server/management/native-integration-routes.ts +4 -1
- package/src/server/management/oauth-account-routes.ts +38 -10
- package/src/server/management/provider-routes.ts +34 -3
- package/src/server/management/quota-reset-routes.ts +57 -0
- package/src/server/management/route-registry.ts +7 -4
- package/src/server/management/shared.ts +19 -5
- package/src/server/management/system-routes.ts +3 -2
- package/src/server/management-api.ts +14 -2
- package/src/server/ports.ts +12 -2
- package/src/server/relay-eager.ts +38 -23
- package/src/server/relay.ts +4 -0
- package/src/server/request-log.ts +6 -0
- package/src/server/responses/codex-ws-correlation.ts +65 -0
- package/src/server/responses/codex-ws-exchange.ts +261 -0
- package/src/server/responses/codex-ws-metadata.ts +134 -0
- package/src/server/responses/codex-ws-pool.ts +162 -0
- package/src/server/responses/codex-ws-request.ts +87 -0
- package/src/server/responses/codex-ws-session.ts +93 -0
- package/src/server/responses/codex-ws-wire.ts +144 -0
- package/src/server/responses/collaboration.ts +41 -1
- package/src/server/responses/compact.ts +105 -12
- package/src/server/responses/core.ts +476 -57
- package/src/server/responses/fetch-helpers.ts +10 -3
- package/src/server/responses/input-admission.ts +16 -9
- package/src/server/responses/responses-field-backfill.ts +1 -1
- package/src/server/responses/ws-upstream.ts +34 -318
- package/src/server/responses-custom-tool-repair.ts +20 -4
- package/src/server/responses-undeclared-tool-guard.ts +100 -8
- package/src/server/safe-response-headers.ts +23 -0
- package/src/server/search.ts +9 -0
- package/src/server/subagent-models-startup.ts +27 -0
- package/src/server/system-env-shell.ts +238 -0
- package/src/server/system-env.ts +7 -234
- package/src/server/ws-bridge.ts +3 -25
- package/src/server/xai-responses-startup.ts +21 -0
- package/src/service-manager-probe.ts +1 -1
- package/src/service.ts +55 -16
- package/src/types/config.ts +108 -12
- package/src/types/provider.ts +36 -7
- package/src/types/tools.ts +26 -1
- package/src/types.ts +2 -0
- package/src/update/notify.ts +8 -2
- package/src/usage/cost.ts +38 -28
- package/src/usage/expected-prices.ts +34 -15
- package/src/usage/log.ts +2 -0
- package/src/usage/model-identity.ts +26 -0
- package/src/usage/summary.ts +15 -1
- package/src/vision/describe.ts +6 -0
- package/src/vision/image-rewrite.ts +108 -0
- package/src/vision/index.ts +19 -306
- package/src/vision/plan.ts +205 -0
- package/src/web-search/executor.ts +6 -0
- package/src/web-search/index.ts +8 -1
- package/gui/dist/assets/index-BU1tE0sr.js +0 -112
- package/gui/dist/assets/index-DL9-iS6J.css +0 -1
package/src/config.ts
CHANGED
|
@@ -4,6 +4,8 @@ import { dirname, join } from "node:path";
|
|
|
4
4
|
import { Database } from "bun:sqlite";
|
|
5
5
|
import * as z from "zod/v4";
|
|
6
6
|
import { isValidProviderName, hasOwnProvider } from "./config/provider-name";
|
|
7
|
+
import { DEFAULT_SUBAGENT_MODELS, SUBAGENT_MODELS_VERSION } from "./config/subagent-models";
|
|
8
|
+
export { DEFAULT_SUBAGENT_MODELS } from "./config/subagent-models";
|
|
7
9
|
import {
|
|
8
10
|
apiKeyTransportConfigError,
|
|
9
11
|
booleanRecordConfigError,
|
|
@@ -523,6 +525,12 @@ const providerConfigSchema = z.object({
|
|
|
523
525
|
modelAliases: z.record(z.string(), z.string()).optional(),
|
|
524
526
|
modelDisplayNames: modelDisplayNamesSchema.optional(),
|
|
525
527
|
defaultAliases: z.boolean().optional(),
|
|
528
|
+
initialModelSelection: z.object({
|
|
529
|
+
version: z.literal(1),
|
|
530
|
+
registrationId: z.uuid(),
|
|
531
|
+
status: z.enum(["pending", "ready", "all-off"]),
|
|
532
|
+
modelCount: z.number().int().nonnegative().optional(),
|
|
533
|
+
}).optional().catch(undefined),
|
|
526
534
|
requestPacing: requestPacingSchema.optional().catch(undefined),
|
|
527
535
|
mcpMaxTools: z.number().int().positive().optional(),
|
|
528
536
|
mcpMaxSchemaBytes: z.number().int().positive().optional(),
|
|
@@ -537,6 +545,7 @@ const providerConfigSchema = z.object({
|
|
|
537
545
|
modelSupportsServiceTier: z.record(z.string().min(1), z.boolean()).optional(),
|
|
538
546
|
preserveResponsesReasoningContent: z.boolean().optional(),
|
|
539
547
|
decodesNativeCompactionBlobs: z.boolean().optional(),
|
|
548
|
+
allowEncryptedV2AgentTasks: z.boolean().optional(),
|
|
540
549
|
allowPrivateNetwork: z.boolean().optional(),
|
|
541
550
|
// The management API accepts `null` as "clear this", so a config written before the POST
|
|
542
551
|
// canonicalization below can hold one on disk. Rejecting it here would send the operator
|
|
@@ -574,6 +583,7 @@ const providerConfigSchema = z.object({
|
|
|
574
583
|
}).strict().optional(),
|
|
575
584
|
responsesSnapshotRepair: z.boolean().optional(),
|
|
576
585
|
xaiResponsesXSearch: z.boolean().optional(),
|
|
586
|
+
xaiResponsesDefaultVersion: z.number().int().positive().optional().catch(undefined),
|
|
577
587
|
}).passthrough();
|
|
578
588
|
|
|
579
589
|
export { isValidProviderName, hasOwnProvider } from "./config/provider-name";
|
|
@@ -840,6 +850,34 @@ const codexAccountPrioritiesSchema = z.custom<Record<string, unknown>>(
|
|
|
840
850
|
}
|
|
841
851
|
}).pipe(z.record(z.string(), z.number().int()));
|
|
842
852
|
|
|
853
|
+
const codexQuotaAutoRefreshEntrySchema = z.object({
|
|
854
|
+
fiveHour: z.boolean().optional(),
|
|
855
|
+
weekly: z.boolean().optional(),
|
|
856
|
+
lastFiveHourResetAt: z.number().finite().nonnegative().optional(),
|
|
857
|
+
lastWeeklyResetAt: z.number().finite().nonnegative().optional(),
|
|
858
|
+
}).strict();
|
|
859
|
+
const CODEX_QUOTA_AUTO_REFRESH_KEY_ERROR =
|
|
860
|
+
"quota auto-refresh keys must be a Codex pool-account id or the main Codex account and cannot be reserved JavaScript object keys";
|
|
861
|
+
|
|
862
|
+
const codexQuotaAutoRefreshSchema = z.custom<Record<string, unknown>>(
|
|
863
|
+
(value): value is Record<string, unknown> => !!value
|
|
864
|
+
&& typeof value === "object"
|
|
865
|
+
&& !Array.isArray(value)
|
|
866
|
+
&& (Object.getPrototypeOf(value) === Object.prototype || Object.getPrototypeOf(value) === null),
|
|
867
|
+
{ error: "codexQuotaAutoRefresh must be a plain object" },
|
|
868
|
+
).superRefine((settings, ctx) => {
|
|
869
|
+
// Inspect own entries before z.record parses them; Zod omits __proto__ record keys.
|
|
870
|
+
for (const [accountId, setting] of Object.entries(settings)) {
|
|
871
|
+
if (!isCodexAccountPriorityKey(accountId)) {
|
|
872
|
+
ctx.addIssue({ code: "custom", path: [accountId], message: CODEX_QUOTA_AUTO_REFRESH_KEY_ERROR });
|
|
873
|
+
}
|
|
874
|
+
const parsed = codexQuotaAutoRefreshEntrySchema.safeParse(setting);
|
|
875
|
+
if (!parsed.success) {
|
|
876
|
+
ctx.addIssue({ code: "custom", path: [accountId], message: "invalid quota auto-refresh setting" });
|
|
877
|
+
}
|
|
878
|
+
}
|
|
879
|
+
}).pipe(z.record(z.string(), codexQuotaAutoRefreshEntrySchema));
|
|
880
|
+
|
|
843
881
|
/**
|
|
844
882
|
* Deliberately permissive. A user's config is not ours to invalidate: a strict
|
|
845
883
|
* entry fails the whole parse, and loadConfig's fallback then backs the file up
|
|
@@ -998,6 +1036,32 @@ const clientConnectionSchema = z.object({
|
|
|
998
1036
|
}).optional(),
|
|
999
1037
|
}).strict();
|
|
1000
1038
|
|
|
1039
|
+
/**
|
|
1040
|
+
* Quota-reset notification section.
|
|
1041
|
+
*
|
|
1042
|
+
* `.strict()` like its neighbour: a typo in an optional feature section should surface as a
|
|
1043
|
+
* rejected write rather than a silently ignored key that leaves the operator believing they
|
|
1044
|
+
* enabled something.
|
|
1045
|
+
*
|
|
1046
|
+
* `pollSeconds` admits 0 (passive-only, no timer) and the resolver clamps anything between 1
|
|
1047
|
+
* and the 60-second floor. Bounds live in the resolver rather than here so a hand-edited value
|
|
1048
|
+
* degrades to a sane one instead of discarding the whole section.
|
|
1049
|
+
*/
|
|
1050
|
+
const quotaResetNotifySchema = z.object({
|
|
1051
|
+
enabled: z.boolean().optional(),
|
|
1052
|
+
kinds: z.array(z.enum(["scheduled", "surprise"])).optional(),
|
|
1053
|
+
pollSeconds: z.number().int().min(0).optional(),
|
|
1054
|
+
// `z.string().url()` accepts any scheme. The payload carries account identity and the hook
|
|
1055
|
+
// URL is frequently a bearer-equivalent secret, so an http: sink puts both in cleartext.
|
|
1056
|
+
webhookUrl: z.string().url().refine(
|
|
1057
|
+
value => { try { return new URL(value).protocol === "https:"; } catch { return false; } },
|
|
1058
|
+
{ message: "webhookUrl must use https" },
|
|
1059
|
+
).optional(),
|
|
1060
|
+
allowPrivateNetwork: z.boolean().optional(),
|
|
1061
|
+
timeoutMs: z.number().int().positive().optional(),
|
|
1062
|
+
command: z.array(z.string()).optional(),
|
|
1063
|
+
}).strict();
|
|
1064
|
+
|
|
1001
1065
|
const configSchema = z.object({
|
|
1002
1066
|
port: z.number().int().min(0).max(65535).default(10100),
|
|
1003
1067
|
// A malformed hand edit must disable only remote-role behavior, not discard
|
|
@@ -1050,6 +1114,12 @@ const configSchema = z.object({
|
|
|
1050
1114
|
defaultModelAliases: z.boolean().optional(),
|
|
1051
1115
|
// Malformed hand edits disable this opt-in projection without rejecting providers.
|
|
1052
1116
|
cursorEffortRows: z.boolean().optional().catch(false),
|
|
1117
|
+
// Fast selectors default on; malformed hand edits disable them without rejecting providers.
|
|
1118
|
+
fastRows: z.boolean().default(true).catch(false),
|
|
1119
|
+
// Ultra Fast is opt-in for the same reason and degrades the same way: a malformed hand
|
|
1120
|
+
// edit turns the tier off rather than rejecting the config that carries it.
|
|
1121
|
+
ultraFastTier: z.boolean().optional().catch(false),
|
|
1122
|
+
codexMainAccountHardLock: z.boolean().optional().catch(false),
|
|
1053
1123
|
// Future versions remain opaque through passthrough-compatible whole-config saves.
|
|
1054
1124
|
// Only version 1 grants deletion authority in the rebase path.
|
|
1055
1125
|
configRebaseProvenance: z.unknown().optional(),
|
|
@@ -1061,12 +1131,16 @@ const configSchema = z.object({
|
|
|
1061
1131
|
openaiProviderTierVersion: z.union([z.literal(1), z.literal(2)]).optional(),
|
|
1062
1132
|
// Invalid hand edits must not discard an otherwise usable config.
|
|
1063
1133
|
googleAntigravityStaticCatalogVersion: z.union([z.literal(1), z.literal(2)]).optional().catch(undefined),
|
|
1134
|
+
subagentModelsVersion: z.number().int().positive().optional().catch(undefined),
|
|
1135
|
+
subagentModels: z.array(z.string().min(1)).optional().catch(undefined),
|
|
1064
1136
|
clientIntegrations: clientIntegrationsSchema.optional().catch(undefined),
|
|
1065
1137
|
providerContextCaps: z.record(z.string(), z.number().int().positive()).optional(),
|
|
1066
1138
|
contextCapValue: z.number().int().positive().optional(),
|
|
1067
1139
|
multiAgentGuidanceEnabled: z.boolean().optional(),
|
|
1068
1140
|
// Invalid optional recovery config must not discard unrelated provider/account state.
|
|
1069
1141
|
agentTaskRecovery: agentTaskRecoverySchema.optional().catch(undefined),
|
|
1142
|
+
// Same rationale: a bad notify section must not cost the operator their providers.
|
|
1143
|
+
quotaResetNotify: quotaResetNotifySchema.optional().catch(undefined),
|
|
1070
1144
|
// These selections pre-date schema validation and used to pass through as
|
|
1071
1145
|
// unknown fields. Invalid hand edits must disable only the optional
|
|
1072
1146
|
// delegation/native-default feature, not reject the whole config and hide
|
|
@@ -1083,6 +1157,7 @@ const configSchema = z.object({
|
|
|
1083
1157
|
codexShimAutoRestore: z.boolean().optional(),
|
|
1084
1158
|
codexDesktopAuthless: z.boolean().optional().catch(undefined),
|
|
1085
1159
|
pausedCodexAccountIds: z.array(z.string().regex(/^[a-zA-Z0-9._-]{1,64}$/)).optional(),
|
|
1160
|
+
codexQuotaAutoRefresh: codexQuotaAutoRefreshSchema.optional().catch(undefined),
|
|
1086
1161
|
codexAccountNamespaces: codexAccountNamespacesSchema.optional(),
|
|
1087
1162
|
// Selection order is a preference, not a safety control like pause: a malformed
|
|
1088
1163
|
// map degrades to "no ordering" rather than failing the parse, so a hand-edited
|
|
@@ -1514,17 +1589,6 @@ const configSchema = z.object({
|
|
|
1514
1589
|
}
|
|
1515
1590
|
});
|
|
1516
1591
|
|
|
1517
|
-
/**
|
|
1518
|
-
* Default featured subagent models (native GPT) seeded on a fresh install and when `subagentModels`
|
|
1519
|
-
* is unset. Codex's spawn_agent advertises the first 5 featured catalog entries, so this seed is a
|
|
1520
|
-
* deliberate 5-list: frontier gpt-5.5 first, the gpt-5.6 preview trio, and gpt-5.4-mini as the cheap
|
|
1521
|
-
* tier. gpt-5.4 / gpt-5.3-codex-spark stay selectable in the GUI's available list. The user can
|
|
1522
|
-
* remove any in the GUI — once they set the list (even to []), it is respected, so removals persist
|
|
1523
|
-
* (start-up only seeds the UNSET case). Kept to ids ChatGPT accepts; the start-up seed prefers the
|
|
1524
|
-
* live catalog's native slugs.
|
|
1525
|
-
*/
|
|
1526
|
-
export const DEFAULT_SUBAGENT_MODELS = ["gpt-5.5", "gpt-5.6-sol", "gpt-5.6-terra", "gpt-5.6-luna", "gpt-5.4-mini"];
|
|
1527
|
-
|
|
1528
1592
|
export function hardenExistingSecret(path: string): void {
|
|
1529
1593
|
if (existsSync(path)) {
|
|
1530
1594
|
try { chmodSync(path, 0o600); } catch { /* best-effort */ }
|
|
@@ -1723,6 +1787,17 @@ function warnDegradedCodexAccountPriorities(rawParsed: unknown, validated: OcxCo
|
|
|
1723
1787
|
}
|
|
1724
1788
|
}
|
|
1725
1789
|
|
|
1790
|
+
function degradedCodexQuotaAutoRefreshWarning(rawParsed: unknown, validated: OcxConfig): string | null {
|
|
1791
|
+
const raw = rawConfigRecord(rawParsed)?.codexQuotaAutoRefresh;
|
|
1792
|
+
if (raw === undefined || validated.codexQuotaAutoRefresh !== undefined) return null;
|
|
1793
|
+
return "codexQuotaAutoRefresh is invalid — automatic quota-window activation is disabled";
|
|
1794
|
+
}
|
|
1795
|
+
|
|
1796
|
+
function warnDegradedCodexQuotaAutoRefresh(rawParsed: unknown, validated: OcxConfig): void {
|
|
1797
|
+
const warning = degradedCodexQuotaAutoRefreshWarning(rawParsed, validated);
|
|
1798
|
+
if (warning) console.warn(`⚠️ config.json ${warning}`);
|
|
1799
|
+
}
|
|
1800
|
+
|
|
1726
1801
|
/**
|
|
1727
1802
|
* The apiKeys schema salvages entry by entry rather than failing the parse, so a
|
|
1728
1803
|
* dropped key is otherwise invisible — and it will not be re-saved by the next
|
|
@@ -1941,6 +2016,27 @@ function warnDegradedOptionalRemoteBlocks(rawParsed: unknown): void {
|
|
|
1941
2016
|
}
|
|
1942
2017
|
}
|
|
1943
2018
|
|
|
2019
|
+
function malformedQuotaResetNotifyWarning(rawParsed: unknown): string | null {
|
|
2020
|
+
const raw = rawConfigRecord(rawParsed);
|
|
2021
|
+
if (!raw || !Object.hasOwn(raw, "quotaResetNotify")) return null;
|
|
2022
|
+
const result = quotaResetNotifySchema.safeParse(raw.quotaResetNotify);
|
|
2023
|
+
if (result.success) return null;
|
|
2024
|
+
const field = result.error.issues[0]?.path.join(".");
|
|
2025
|
+
return `quotaResetNotify${field ? `.${field}` : ""} ignored: invalid quota-reset notification configuration`;
|
|
2026
|
+
}
|
|
2027
|
+
|
|
2028
|
+
/**
|
|
2029
|
+
* Warn once per load that the section was dropped.
|
|
2030
|
+
*
|
|
2031
|
+
* This matters more than a usual degradation notice: the failure is SILENT in the direction
|
|
2032
|
+
* that hurts. A dropped section means notifications are off, so the operator sees nothing —
|
|
2033
|
+
* which is exactly what they would see if the feature were working and no reset had happened.
|
|
2034
|
+
*/
|
|
2035
|
+
function warnDegradedQuotaResetNotify(rawParsed: unknown): void {
|
|
2036
|
+
const warning = malformedQuotaResetNotifyWarning(rawParsed);
|
|
2037
|
+
if (warning) console.warn(`⚠️ config.json ${warning}. Other settings were preserved.`);
|
|
2038
|
+
}
|
|
2039
|
+
|
|
1944
2040
|
type NativeSubagentPersistedField = "injectionModel" | "injectionEffort" | "syncCodexSubagentDefaults";
|
|
1945
2041
|
|
|
1946
2042
|
function rawConfigRecord(rawParsed: unknown): Record<string, unknown> | null {
|
|
@@ -2090,6 +2186,7 @@ export function loadConfig(): OcxConfig {
|
|
|
2090
2186
|
warnDegradedHostname(parsed, config);
|
|
2091
2187
|
warnDegradedApiKeys(parsed, config);
|
|
2092
2188
|
warnDegradedCodexAccountPriorities(parsed, config);
|
|
2189
|
+
warnDegradedCodexQuotaAutoRefresh(parsed, config);
|
|
2093
2190
|
warnDegradedClaudeSubagentEffort(parsed);
|
|
2094
2191
|
warnDegradedNativeSubagentConfig(parsed, config);
|
|
2095
2192
|
warnDegradedCodexAccountPicker(parsed);
|
|
@@ -2097,13 +2194,14 @@ export function loadConfig(): OcxConfig {
|
|
|
2097
2194
|
warnDegradedAgentTaskRecovery(parsed);
|
|
2098
2195
|
warnDegradedRuntimeRole(parsed);
|
|
2099
2196
|
warnDegradedOptionalRemoteBlocks(parsed);
|
|
2197
|
+
warnDegradedQuotaResetNotify(parsed);
|
|
2100
2198
|
return withRefreshedCostOverlays(normalizeClaudeSubagentEffort(normalizeNativeSubagentSync(config, parsed), parsed));
|
|
2101
2199
|
}
|
|
2102
2200
|
// Schema validation failed — merge defaults into the raw object instead of
|
|
2103
2201
|
// discarding it entirely, so pool accounts and providers survive a missing
|
|
2104
2202
|
// field like defaultProvider.
|
|
2105
2203
|
const defaults = getDefaultConfig();
|
|
2106
|
-
const merged = { ...defaults, ...parsed };
|
|
2204
|
+
const merged = { ...defaults, ...parsed, subagentModelsVersion: parsed.subagentModelsVersion };
|
|
2107
2205
|
// Ensure providers from both sides survive
|
|
2108
2206
|
if (parsed.providers && defaults.providers) {
|
|
2109
2207
|
merged.providers = { ...defaults.providers, ...parsed.providers };
|
|
@@ -2116,6 +2214,7 @@ export function loadConfig(): OcxConfig {
|
|
|
2116
2214
|
warnDegradedHostname(parsed, config);
|
|
2117
2215
|
warnDegradedApiKeys(parsed, config);
|
|
2118
2216
|
warnDegradedCodexAccountPriorities(parsed, config);
|
|
2217
|
+
warnDegradedCodexQuotaAutoRefresh(parsed, config);
|
|
2119
2218
|
warnDegradedClaudeSubagentEffort(parsed);
|
|
2120
2219
|
warnDegradedNativeSubagentConfig(parsed, config);
|
|
2121
2220
|
warnDegradedCodexAccountPicker(parsed);
|
|
@@ -2123,6 +2222,7 @@ export function loadConfig(): OcxConfig {
|
|
|
2123
2222
|
warnDegradedAgentTaskRecovery(parsed);
|
|
2124
2223
|
warnDegradedRuntimeRole(parsed);
|
|
2125
2224
|
warnDegradedOptionalRemoteBlocks(parsed);
|
|
2225
|
+
warnDegradedQuotaResetNotify(parsed);
|
|
2126
2226
|
return withRefreshedCostOverlays(normalizeClaudeSubagentEffort(normalizeNativeSubagentSync(config, parsed), parsed));
|
|
2127
2227
|
}
|
|
2128
2228
|
// Still failing, but if every complaint is about one or more named entries
|
|
@@ -2138,6 +2238,7 @@ export function loadConfig(): OcxConfig {
|
|
|
2138
2238
|
warnDegradedHostname(parsed, config);
|
|
2139
2239
|
warnDegradedApiKeys(parsed, config);
|
|
2140
2240
|
warnDegradedCodexAccountPriorities(parsed, config);
|
|
2241
|
+
warnDegradedCodexQuotaAutoRefresh(parsed, config);
|
|
2141
2242
|
warnDegradedClaudeSubagentEffort(parsed);
|
|
2142
2243
|
warnDegradedNativeSubagentConfig(parsed, config);
|
|
2143
2244
|
warnDegradedCodexAccountPicker(parsed);
|
|
@@ -2145,6 +2246,7 @@ export function loadConfig(): OcxConfig {
|
|
|
2145
2246
|
warnDegradedAgentTaskRecovery(parsed);
|
|
2146
2247
|
warnDegradedRuntimeRole(parsed);
|
|
2147
2248
|
warnDegradedOptionalRemoteBlocks(parsed);
|
|
2249
|
+
warnDegradedQuotaResetNotify(parsed);
|
|
2148
2250
|
return withRefreshedCostOverlays(normalizeClaudeSubagentEffort(normalizeNativeSubagentSync(config, parsed), parsed));
|
|
2149
2251
|
}
|
|
2150
2252
|
}
|
|
@@ -2267,6 +2369,8 @@ function validFileConfigDiagnostics(config: OcxConfig, rawParsed: unknown): Conf
|
|
|
2267
2369
|
const warnings = configPlaceholderWarnings(normalized);
|
|
2268
2370
|
warnings.push(...inheritedFastWireConflictProviderNames(normalized).map(inheritedFastWireConflictWarning));
|
|
2269
2371
|
warnings.push(...degradedCodexAccountPriorityWarnings(rawParsed, normalized));
|
|
2372
|
+
const quotaAutoRefreshWarning = degradedCodexQuotaAutoRefreshWarning(rawParsed, normalized);
|
|
2373
|
+
if (quotaAutoRefreshWarning) warnings.push(quotaAutoRefreshWarning);
|
|
2270
2374
|
if (rawEffort !== undefined && !isClaudeSubagentEffort(rawEffort)) {
|
|
2271
2375
|
warnings.push(`claudeCode.subagentEffort ignored: expected one of ${CLAUDE_SUBAGENT_EFFORTS.join(", ")}`);
|
|
2272
2376
|
}
|
|
@@ -2285,6 +2389,8 @@ function validFileConfigDiagnostics(config: OcxConfig, rawParsed: unknown): Conf
|
|
|
2285
2389
|
if (remoteGuiWarning) warnings.push(remoteGuiWarning);
|
|
2286
2390
|
const clientWarning = malformedClientConnectionWarning(rawParsed);
|
|
2287
2391
|
if (clientWarning) warnings.push(clientWarning);
|
|
2392
|
+
const notifyWarning = malformedQuotaResetNotifyWarning(rawParsed);
|
|
2393
|
+
if (notifyWarning) warnings.push(notifyWarning);
|
|
2288
2394
|
if (syncDisabledReason) {
|
|
2289
2395
|
warnings.push(`syncCodexSubagentDefaults ignored: ${syncDisabledReason}`);
|
|
2290
2396
|
}
|
|
@@ -2306,7 +2412,7 @@ function mergeConfigDefaults(parsed: unknown): unknown {
|
|
|
2306
2412
|
if (!parsed || typeof parsed !== "object") return parsed;
|
|
2307
2413
|
const defaults = getDefaultConfig();
|
|
2308
2414
|
const raw = parsed as Record<string, unknown>;
|
|
2309
|
-
const merged: Record<string, unknown> = { ...defaults, ...raw };
|
|
2415
|
+
const merged: Record<string, unknown> = { ...defaults, ...raw, subagentModelsVersion: raw.subagentModelsVersion };
|
|
2310
2416
|
if (raw.providers && typeof raw.providers === "object" && defaults.providers) {
|
|
2311
2417
|
merged.providers = { ...defaults.providers, ...(raw.providers as Record<string, unknown>) };
|
|
2312
2418
|
}
|
|
@@ -2423,6 +2529,16 @@ function clientRolePairError(value: unknown): string | null {
|
|
|
2423
2529
|
return null;
|
|
2424
2530
|
}
|
|
2425
2531
|
|
|
2532
|
+
function quotaResetNotifyError(value: unknown): string | null {
|
|
2533
|
+
const raw = rawConfigRecord(value);
|
|
2534
|
+
if (!raw || !Object.hasOwn(raw, "quotaResetNotify") || raw.quotaResetNotify === undefined) return null;
|
|
2535
|
+
const result = quotaResetNotifySchema.safeParse(raw.quotaResetNotify);
|
|
2536
|
+
if (result.success) return null;
|
|
2537
|
+
const issue = result.error.issues[0];
|
|
2538
|
+
const field = issue?.path.join(".");
|
|
2539
|
+
return `schema_invalid: quotaResetNotify${field ? `.${field}` : ""}: ${issue?.message ?? "invalid configuration"}`;
|
|
2540
|
+
}
|
|
2541
|
+
|
|
2426
2542
|
/**
|
|
2427
2543
|
* Same reasoning as {@link blankHostnameError}, and more urgent: the read path degrades a
|
|
2428
2544
|
* malformed selection-order map to undefined, which on a write would drop every entry the
|
|
@@ -2449,6 +2565,21 @@ function codexAccountPrioritiesError(value: unknown): string | null {
|
|
|
2449
2565
|
return null;
|
|
2450
2566
|
}
|
|
2451
2567
|
|
|
2568
|
+
function codexQuotaAutoRefreshError(value: unknown): string | null {
|
|
2569
|
+
const raw = rawConfigRecord(value);
|
|
2570
|
+
if (!raw || raw.codexQuotaAutoRefresh === undefined) return null;
|
|
2571
|
+
const parsed = codexQuotaAutoRefreshSchema.safeParse(raw.codexQuotaAutoRefresh);
|
|
2572
|
+
if (parsed.success) return null;
|
|
2573
|
+
const details = parsed.error.issues.map(issue => {
|
|
2574
|
+
const path = issue.path.join(".");
|
|
2575
|
+
const message = path === ""
|
|
2576
|
+
? issue.message.replace(/^codexQuotaAutoRefresh\s*/, "")
|
|
2577
|
+
: issue.message;
|
|
2578
|
+
return `codexQuotaAutoRefresh${path ? `.${path}` : ""}: ${message}`;
|
|
2579
|
+
});
|
|
2580
|
+
return `schema_invalid: ${details.join("; ")}`;
|
|
2581
|
+
}
|
|
2582
|
+
|
|
2452
2583
|
function googleAntigravityStaticCatalogVersionError(value: unknown): string | null {
|
|
2453
2584
|
const raw = rawConfigRecord(value);
|
|
2454
2585
|
if (!raw || !Object.hasOwn(raw, "googleAntigravityStaticCatalogVersion")) return null;
|
|
@@ -2581,8 +2712,10 @@ export function validateConfigCandidate(value: unknown): { ok: true; config: Ocx
|
|
|
2581
2712
|
?? appOwnedMemoryBudgetError(value)
|
|
2582
2713
|
?? upstreamHostCircuitThresholdError(value)
|
|
2583
2714
|
?? agentTaskRecoveryError(value)
|
|
2715
|
+
?? quotaResetNotifyError(value)
|
|
2584
2716
|
?? googleAntigravityStaticCatalogVersionError(value)
|
|
2585
2717
|
?? codexAccountPrioritiesError(value)
|
|
2718
|
+
?? codexQuotaAutoRefreshError(value)
|
|
2586
2719
|
?? codexAccountPickerEnabledError(value)
|
|
2587
2720
|
?? emptyCompletionRetryError(value)
|
|
2588
2721
|
?? oauthOpenBrowserError(value)
|
|
@@ -3112,6 +3245,14 @@ export function websocketsEnabled(config: Pick<OcxConfig, "websockets">): boolea
|
|
|
3112
3245
|
return config.websockets === true;
|
|
3113
3246
|
}
|
|
3114
3247
|
|
|
3248
|
+
/**
|
|
3249
|
+
* Opt-in Ultra Fast, read with the house `=== true` idiom so an absent key and a
|
|
3250
|
+
* malformed one both mean off.
|
|
3251
|
+
*/
|
|
3252
|
+
export function ultraFastTierEnabled(config: Pick<OcxConfig, "ultraFastTier">): boolean {
|
|
3253
|
+
return config.ultraFastTier === true;
|
|
3254
|
+
}
|
|
3255
|
+
|
|
3115
3256
|
// ---------------------------------------------------------------------------
|
|
3116
3257
|
// Hand-edit protection for the `claudeCode` subtree (devlog 260726_claude_auth_auto/040 H1).
|
|
3117
3258
|
//
|
|
@@ -3543,6 +3684,7 @@ export function getDefaultConfig(): OcxConfig {
|
|
|
3543
3684
|
return {
|
|
3544
3685
|
port: 10100,
|
|
3545
3686
|
emptyCompletionRetry: false,
|
|
3687
|
+
fastRows: true,
|
|
3546
3688
|
managementUsageMaxReadBytes: 64 * 1024 * 1024,
|
|
3547
3689
|
appOwnedMemoryBudgetMb: DEFAULT_APP_OWNED_MEMORY_BUDGET_BYTES / (1024 * 1024),
|
|
3548
3690
|
// Fresh/re-initialized configs are already written in the current three-tier
|
|
@@ -3559,6 +3701,7 @@ export function getDefaultConfig(): OcxConfig {
|
|
|
3559
3701
|
},
|
|
3560
3702
|
defaultProvider: "openai",
|
|
3561
3703
|
subagentModels: [...DEFAULT_SUBAGENT_MODELS],
|
|
3704
|
+
subagentModelsVersion: SUBAGENT_MODELS_VERSION,
|
|
3562
3705
|
multiAgentGuidanceEnabled: true,
|
|
3563
3706
|
websockets: false,
|
|
3564
3707
|
codexAutoStart: true,
|