@bitkyc08/opencodex 2.59.0 → 2.61.0-preview.20260922
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 +64 -0
- package/README.md +28 -1
- package/bin/ocx.mjs +382 -209
- package/gui/dist/assets/App-E64Rzjap.js +50 -0
- package/gui/dist/assets/Tray-_nfzD8k4.js +1 -0
- package/gui/dist/assets/index-DpdfZWMK.js +86 -0
- package/gui/dist/assets/index-_bpvxJu0.css +1 -0
- package/gui/dist/assets/usage-companion-chart-DtoK7T6h.js +1 -0
- package/gui/dist/favicon.png +0 -0
- package/gui/dist/index.html +2 -2
- package/gui/dist/provider-icons/stepfun-color.svg +1 -0
- package/package.json +8 -1
- package/src/adapters/anthropic-image-codec.ts +16 -2
- package/src/adapters/anthropic-image-normalize.ts +49 -2
- package/src/adapters/anthropic.ts +20 -1
- package/src/adapters/base.ts +23 -0
- package/src/adapters/coding-agent/protocol.ts +36 -6
- package/src/adapters/coding-agent/turn.ts +32 -4
- package/src/adapters/command-code.ts +52 -4
- package/src/adapters/cursor/catalog.ts +51 -7
- package/src/adapters/cursor/checkpoint-store.ts +3 -0
- package/src/adapters/cursor/discovery.ts +11 -8
- package/src/adapters/cursor/live-transport.ts +26 -9
- package/src/adapters/cursor/protobuf-request.ts +6 -3
- package/src/adapters/cursor/request-builder.ts +20 -4
- package/src/adapters/cursor/transport.ts +19 -0
- package/src/adapters/cursor.ts +14 -3
- package/src/adapters/declaration-carrier.ts +45 -0
- package/src/adapters/devin/cloud-direct/chat.ts +3 -1
- package/src/adapters/devin/cloud-direct/stated-reset-retry.ts +42 -5
- package/src/adapters/devin.ts +125 -36
- package/src/adapters/google-antigravity-replay.ts +1 -1
- package/src/adapters/google-antigravity-wire.ts +34 -7
- package/src/adapters/google-errors.ts +7 -1
- package/src/adapters/google-http.ts +49 -10
- package/src/adapters/google-tool-schema.ts +595 -31
- package/src/adapters/google-wire-compiler.ts +93 -10
- package/src/adapters/google-wire-shape.ts +461 -0
- package/src/adapters/google.ts +66 -11
- package/src/adapters/image.ts +4 -1
- package/src/adapters/input-media-guard.ts +21 -9
- package/src/adapters/kiro/usage.ts +3 -2
- package/src/adapters/kiro-tool-fallback.ts +1 -1
- package/src/adapters/ollama-native.ts +6 -0
- package/src/adapters/openai-chat/developer-role.ts +61 -0
- package/src/adapters/openai-chat/messages.ts +46 -27
- package/src/adapters/openai-chat/parallel-tool-calls.ts +32 -0
- package/src/adapters/openai-chat/passthrough.ts +33 -9
- package/src/adapters/openai-chat/reasoning-wire.ts +89 -0
- package/src/adapters/openai-chat-images.ts +3 -1
- package/src/adapters/openai-chat.ts +23 -58
- package/src/adapters/openai-responses/image-gen.ts +8 -6
- package/src/adapters/openai-responses/passthrough.ts +17 -3
- package/src/adapters/openai-responses/reasoning.ts +7 -0
- package/src/adapters/opencode-go-additional-tools.ts +12 -2
- package/src/adapters/registry.ts +3 -2
- package/src/adapters/run-turn-queue.ts +178 -29
- package/src/adapters/xai-web-search.ts +16 -1
- package/src/bridge/errors.ts +8 -2
- package/src/bridge/response-json.ts +9 -1
- package/src/bridge/sse.ts +13 -151
- package/src/chat/inbound.ts +141 -5
- package/src/claude/desktop-3p.ts +7 -1
- package/src/claude/desktop-first-party.ts +183 -0
- package/src/claude/desktop-gateway-state.ts +41 -0
- package/src/claude/inbound-content-options.ts +6 -0
- package/src/claude/inbound.ts +32 -6
- package/src/claude/intercept/connect-proxy.ts +179 -0
- package/src/claude/intercept/listener.ts +122 -0
- package/src/claude/intercept/local-ca.ts +298 -0
- package/src/claude/intercept/runtime.ts +98 -0
- package/src/claude/intercept/settings.ts +189 -0
- package/src/cli/access.ts +87 -0
- package/src/cli/account-auth.ts +19 -0
- package/src/cli/account-extended.ts +4 -4
- package/src/cli/capabilities.ts +31 -0
- package/src/cli/claude-desktop.ts +206 -16
- package/src/cli/codex-shim-autorestore.ts +3 -0
- package/src/cli/companion.ts +56 -0
- package/src/cli/dispatch.ts +46 -7
- package/src/cli/doctor.ts +28 -9
- package/src/cli/ensure-desired-integrations.ts +43 -5
- package/src/cli/help.ts +7 -9
- package/src/cli/hub.ts +3 -2
- package/src/cli/index.ts +203 -59
- package/src/cli/init.ts +8 -0
- package/src/cli/integrations.ts +7 -1
- package/src/cli/opencode.ts +2 -2
- package/src/cli/provider.ts +13 -1
- package/src/cli/registry.ts +41 -2
- package/src/cli/resolve.ts +230 -0
- package/src/cli/root.ts +24 -1
- package/src/cli/start-ownership-publication.ts +56 -0
- package/src/cli/status-probes.ts +2 -18
- package/src/cli/status.ts +62 -0
- package/src/cli/stop-report.ts +143 -0
- package/src/cli/uninstall-plan.ts +9 -0
- package/src/client/machine-api.ts +2 -2
- package/src/client/machine-listener.ts +4 -7
- package/src/client/runtime.ts +26 -2
- package/src/clients/aside-profiles.ts +4 -0
- package/src/clients/config-export/zcode-store.ts +157 -0
- package/src/clients/config-export.ts +36 -0
- package/src/codex/account-store.ts +65 -0
- package/src/codex/app-server-processes.ts +72 -40
- package/src/codex/auth-api/account-list.ts +19 -11
- package/src/codex/auth-api/login-flow.ts +6 -1
- package/src/codex/auth-api/pool-quota-probe.ts +30 -7
- package/src/codex/autostart-health.ts +28 -0
- package/src/codex/catalog/build-entries.ts +2 -2
- package/src/codex/catalog/effort.ts +3 -3
- package/src/codex/catalog/gather-capture.ts +21 -2
- package/src/codex/catalog/model-hints.ts +29 -28
- package/src/codex/catalog/parsing.ts +7 -0
- package/src/codex/catalog/provider-models.ts +43 -17
- package/src/codex/catalog/retained-sync.ts +24 -28
- package/src/codex/catalog/routed-gather.ts +19 -0
- package/src/codex/context-compat.ts +5 -2
- package/src/codex/convergence.ts +2 -2
- package/src/codex/desired-state.ts +4 -1
- package/src/codex/history-job.ts +6 -6
- package/src/codex/history-provider.ts +31 -166
- package/src/codex/history-rollout-read.ts +174 -0
- package/src/codex/inject/config-toml.ts +41 -6
- package/src/codex/inject/paginated-openai-compat.ts +90 -0
- package/src/codex/inject.ts +18 -15
- package/src/codex/injected-marker.ts +18 -0
- package/src/codex/internal/catalog-writer.ts +33 -1
- package/src/codex/main-account.ts +6 -0
- package/src/codex/model-cache.ts +99 -6
- package/src/codex/model-entitlement-admission.ts +59 -0
- package/src/codex/model-entitlements.ts +116 -54
- package/src/codex/native-main-admission.ts +83 -0
- package/src/codex/observed-model-denials.ts +101 -8
- package/src/codex/prompt-text-probe.ts +9 -6
- package/src/codex/routing/health-store.ts +39 -0
- package/src/codex/routing/selection.ts +37 -1
- package/src/codex/routing.ts +12 -42
- package/src/codex/shim-templates.ts +29 -3
- package/src/codex/shim.ts +1 -1
- package/src/codex/subagent-model-fallback.ts +22 -4
- package/src/combos/failover.ts +3 -0
- package/src/companion/settings.ts +132 -0
- package/src/config/admitted-identity.ts +222 -0
- package/src/config/atomic-write.ts +117 -5
- package/src/config/diagnostics.ts +22 -1
- package/src/config/feature-flags.ts +5 -0
- package/src/config/load-degrade.ts +52 -7
- package/src/config/process-state.ts +1 -1
- package/src/config/proxy-env.ts +8 -2
- package/src/config/schema/compaction-triggers.ts +11 -0
- package/src/config/schema/config-schema.ts +31 -1
- package/src/config/schema/leaf-validators.ts +59 -0
- package/src/config.ts +3 -3
- package/src/generated/compatibility-version.json +604 -280
- package/src/grok/reset-coupons.ts +38 -19
- package/src/images/loop.ts +6 -1
- package/src/integrations/aside-profile-context.ts +37 -3
- package/src/integrations/aside-profile-journal.ts +68 -3
- package/src/integrations/aside-profiles.ts +128 -3
- package/src/integrations/config-io.ts +44 -10
- package/src/integrations/merge.ts +120 -13
- package/src/integrations/mutation-plan.ts +921 -0
- package/src/integrations/registry.ts +38 -0
- package/src/integrations/state.ts +78 -45
- package/src/integrations/target.ts +208 -0
- package/src/integrations/writer.ts +134 -110
- package/src/lab/conformance/fixture-provider.ts +5 -0
- package/src/lab/live/transport.ts +4 -0
- package/src/lab/live/types.ts +5 -0
- package/src/lab/subject/behavior-fingerprint.ts +1 -1
- package/src/lib/admin-secrets.ts +9 -1
- package/src/lib/browser-launch-notice.ts +59 -0
- package/src/lib/bun-runtime.ts +6 -2
- package/src/lib/debug-log-buffer.ts +6 -1
- package/src/lib/debug.ts +63 -0
- package/src/lib/errors.ts +79 -0
- package/src/lib/http-response-semantics.ts +57 -0
- package/src/lib/lab-live-pinned-sender.ts +26 -12
- package/src/lib/open-url.ts +51 -7
- package/src/lib/package-tree-integrity.ts +2 -1
- package/src/lib/package-version.ts +8 -0
- package/src/lib/pinned-http.ts +142 -2
- package/src/lib/plain-data.ts +103 -0
- package/src/lib/process-control.ts +13 -5
- package/src/lib/provider-egress.ts +310 -0
- package/src/lib/provider-outbound.ts +109 -16
- package/src/lib/proxy-env.ts +82 -7
- package/src/lib/request-execution-budget.ts +72 -0
- package/src/lib/request-failure-attribution.ts +183 -0
- package/src/lib/request-failure-model.ts +236 -0
- package/src/lib/request-resend-gate.ts +138 -0
- package/src/lib/socks5-fetch.ts +136 -26
- package/src/lib/spend-ledger-owner.ts +364 -0
- package/src/lib/spend-reservation-ledger.ts +218 -27
- package/src/lib/standalone.ts +16 -0
- package/src/lib/upstream-retry.ts +167 -16
- package/src/lib/windows-system-proxy.ts +16 -11
- package/src/lib/winsw.ts +2 -2
- package/src/oauth/callback-server.ts +4 -3
- package/src/oauth/generic-account-failover.ts +1 -0
- package/src/oauth/health.ts +12 -1
- package/src/oauth/index.ts +27 -108
- package/src/oauth/login-cli.ts +80 -29
- package/src/oauth/login-flow-state.ts +127 -0
- package/src/providers/api-key-resolve.ts +133 -0
- package/src/providers/api-key-selection.ts +5 -1
- package/src/providers/derive.ts +34 -17
- package/src/providers/devin-cli-authmode-migration.ts +14 -10
- package/src/providers/key-failover.ts +97 -19
- package/src/providers/key-store.ts +34 -110
- package/src/providers/model-rename-fields.ts +147 -0
- package/src/providers/model-rename-migration.ts +179 -38
- package/src/providers/model-rename-startup.ts +7 -5
- package/src/providers/openai-virtual-models.ts +42 -2
- package/src/providers/quota/antigravity.ts +22 -2
- package/src/providers/quota/vendor-probes-key.ts +38 -23
- package/src/providers/reasoning-metadata.ts +43 -18
- package/src/providers/registry/entries-core.ts +47 -20
- package/src/providers/registry/entries-extended.ts +63 -4
- package/src/providers/registry/model-ids.ts +168 -0
- package/src/providers/registry/model-seeds.ts +56 -10
- package/src/providers/registry/types.ts +2 -0
- package/src/providers/resolved-model-policy-merge.ts +167 -0
- package/src/providers/resolved-model-policy.ts +406 -0
- package/src/providers/stale-vision-classification-migration.ts +137 -0
- package/src/providers/xai-transport.ts +12 -1
- package/src/reasoning-effort.ts +8 -0
- package/src/responses/apply-patch-envelope.ts +0 -12
- package/src/responses/freeform-wrapper-scan.ts +279 -0
- package/src/responses/function-call-compat.ts +38 -1
- package/src/responses/inline-document.ts +65 -0
- package/src/responses/input-media.ts +42 -8
- package/src/responses/legacy-dotted-tool-name-repair.ts +134 -0
- package/src/responses/muse-tool-name-alias.ts +19 -0
- package/src/responses/parser-content.ts +8 -2
- package/src/responses/parser-tools.ts +3 -0
- package/src/responses/parser.ts +3 -1
- package/src/responses/progressive-freeform-input.ts +130 -0
- package/src/responses/reasoning-envelope.ts +30 -0
- package/src/responses/schema.ts +3 -0
- package/src/responses/state.ts +5 -12
- package/src/responses/tool-name-aliases.ts +15 -1
- package/src/router.ts +108 -117
- package/src/routing/compatibility/behavior.ts +9 -0
- package/src/routing/compatibility/subject.ts +16 -1
- package/src/server/adapter-resolve.ts +9 -0
- package/src/server/admission-model-scope.ts +219 -0
- package/src/server/audio-live.ts +9 -3
- package/src/server/audio-upstream.ts +18 -0
- package/src/server/auth-cors.ts +29 -0
- package/src/server/chat-completions.ts +60 -4
- package/src/server/chat-native.ts +19 -4
- package/src/server/claude-messages.ts +61 -20
- package/src/server/effort-row.ts +11 -3
- package/src/server/grok-responses-control-frame.ts +160 -1
- package/src/server/grok-responses-snapshot-repair.ts +113 -11
- package/src/server/gui-freshness.ts +103 -0
- package/src/server/gui-static.ts +7 -9
- package/src/server/images.ts +59 -6
- package/src/server/index/claude-intercept-lifecycle.ts +49 -0
- package/src/server/index/serve-options.ts +142 -39
- package/src/server/index/spend-ledger-lifecycle.ts +92 -0
- package/src/server/index/startup-warnings.ts +24 -0
- package/src/server/index/websocket-handler.ts +6 -1
- package/src/server/index.ts +34 -38
- package/src/server/lifecycle.ts +4 -4
- package/src/server/live-call-bindings.ts +6 -0
- package/src/server/live.ts +88 -3
- package/src/server/management/agent-settings-routes.ts +121 -36
- package/src/server/management/aside-profile-routes.ts +266 -7
- package/src/server/management/companion-routes.ts +77 -0
- package/src/server/management/config-routes.ts +18 -2
- package/src/server/management/context.ts +3 -0
- package/src/server/management/integration-routes.ts +287 -5
- package/src/server/management/logs-usage-routes.ts +19 -0
- package/src/server/management/metrics-routes.ts +20 -0
- package/src/server/management/model-rows.ts +224 -12
- package/src/server/management/native-integration-routes.ts +103 -6
- package/src/server/management/oauth-account-routes.ts +45 -7
- package/src/server/management/route-registry.ts +20 -0
- package/src/server/management/shared.ts +28 -4
- package/src/server/management/system-restart.ts +7 -2
- package/src/server/management/system-routes.ts +2 -0
- package/src/server/management/usage-aggregate-cache.ts +4 -0
- package/src/server/management/usage-timeline-routes.ts +44 -0
- package/src/server/management-api.ts +10 -9
- package/src/server/management-auth.ts +15 -1
- package/src/server/proxy-liveness.ts +75 -0
- package/src/server/readiness.ts +29 -10
- package/src/server/relay-eager.ts +24 -2
- package/src/server/relay.ts +138 -12
- package/src/server/request-log-failure-attribution.ts +99 -0
- package/src/server/request-log.ts +169 -2
- package/src/server/request-metrics.ts +298 -0
- package/src/server/responses/adapter-continuation.ts +3 -3
- package/src/server/responses/adapter-dispatch.ts +11 -6
- package/src/server/responses/codex-ws-wire.ts +34 -8
- package/src/server/responses/combo-stream-preflight.ts +168 -6
- package/src/server/responses/compact.ts +43 -10
- package/src/server/responses/compaction-routing.ts +111 -0
- package/src/server/responses/core-codex-account.ts +8 -3
- package/src/server/responses/core-combo.ts +7 -7
- package/src/server/responses/core-normalize.ts +6 -12
- package/src/server/responses/core-opaque-recovery.ts +91 -0
- package/src/server/responses/core-options.ts +4 -0
- package/src/server/responses/encrypted-payload.ts +20 -2
- package/src/server/responses/fetch-helpers.ts +124 -8
- package/src/server/responses/input-admission.ts +10 -0
- package/src/server/responses/passthrough-delivery.ts +45 -15
- package/src/server/responses/passthrough-dispatch.ts +215 -44
- package/src/server/responses/passthrough-error.ts +27 -8
- package/src/server/responses/policy-fallback.ts +5 -13
- package/src/server/responses/request-prepare.ts +109 -18
- package/src/server/responses/request-send-budget.ts +17 -1
- package/src/server/responses/request-sidecar-auth.ts +1 -1
- package/src/server/responses/request-transport.ts +26 -6
- package/src/server/responses/reset-replay.ts +108 -0
- package/src/server/responses/run-turn-execution.ts +25 -3
- package/src/server/responses/sidecar-execution.ts +17 -2
- package/src/server/responses/ws-upstream.ts +14 -27
- package/src/server/responses-custom-tool-repair.ts +27 -54
- package/src/server/responses-request-tool-scope.ts +214 -0
- package/src/server/responses-undeclared-tool-guard.ts +35 -2
- package/src/server/search.ts +25 -1
- package/src/server/sse-payload-rewrite.ts +1 -1
- package/src/server/usage-ledger-retention.ts +73 -0
- package/src/service/cli.ts +48 -2
- package/src/service/health.ts +3 -2
- package/src/service/install-state-contract.d.mts +27 -0
- package/src/service/install-state-contract.mjs +34 -0
- package/src/service/launchd.ts +1 -1
- package/src/service/orchestration.ts +2 -4
- package/src/service/ownership-compatibility.ts +164 -0
- package/src/service/ownership-mutation-lease.d.mts +32 -0
- package/src/service/ownership-mutation-lease.mjs +211 -0
- package/src/service/repair.ts +45 -1
- package/src/service/state-lock.ts +269 -0
- package/src/service/state-record.d.mts +36 -0
- package/src/service/state-record.mjs +138 -0
- package/src/service/state.ts +582 -68
- package/src/service/windows-taskxml.ts +11 -10
- package/src/service.ts +7 -3
- package/src/tray/windows-tray.ps1 +156 -4
- package/src/types/config.ts +48 -3
- package/src/types/provider.ts +91 -0
- package/src/types/request.ts +30 -2
- package/src/types/tools.ts +33 -0
- package/src/types.ts +4 -0
- package/src/update/index.ts +207 -63
- package/src/update/job.ts +9 -5
- package/src/update/ownership-transaction.ts +47 -0
- package/src/update/restart-ownership.ts +54 -0
- package/src/update/runtime-ownership.d.mts +40 -0
- package/src/update/runtime-ownership.mjs +122 -0
- package/src/usage/attempt-delivery.ts +198 -0
- package/src/usage/cache-diagnostic.ts +305 -0
- package/src/usage/failure-fingerprint.ts +118 -0
- package/src/usage/failure-projection-cache.ts +174 -0
- package/src/usage/failure-projection.ts +174 -0
- package/src/usage/ledger-retention.ts +165 -0
- package/src/usage/log.ts +126 -79
- package/src/usage/request-outcome.ts +150 -0
- package/src/usage/retention-contract.ts +28 -0
- package/src/usage/summary.ts +2 -2
- package/src/usage/telemetry-contract.ts +237 -0
- package/src/usage/timeline.ts +236 -0
- package/src/vision/eligibility.ts +88 -9
- package/src/vision/plan.ts +34 -10
- package/src/web-search/alpha-search.ts +21 -1
- package/src/web-search/executor.ts +41 -2
- package/src/web-search/loop.ts +6 -1
- package/gui/dist/assets/index-C5IebErG.js +0 -136
- package/gui/dist/assets/index-OESInAjC.css +0 -1
|
@@ -127,7 +127,7 @@ export function isOcxCommandLine(commandLine: string): boolean {
|
|
|
127
127
|
|| normalized.includes("src/cli/index.ts")
|
|
128
128
|
|| normalized.includes("@bitkyc08/opencodex")
|
|
129
129
|
|| /@bitkyc08\/\.opencodex-/.test(normalized)
|
|
130
|
-
|| /(?:^|[\s/"'])(?:ocx|opencodex)(?:\.cmd)?(?:$|[\s"'])/.test(normalized);
|
|
130
|
+
|| /(?:^|[\s/"'])(?:ocx|opencodex)(?:\.cmd|\.exe)?(?:$|[\s"'])/.test(normalized);
|
|
131
131
|
}
|
|
132
132
|
|
|
133
133
|
export function isOcxStartCommandLine(commandLine: string): boolean {
|
package/src/config/proxy-env.ts
CHANGED
|
@@ -143,8 +143,14 @@ export function applyProxyEnvWith(
|
|
|
143
143
|
} else {
|
|
144
144
|
const found = readWindowsSystemProxy(auto.reader, auto.platform);
|
|
145
145
|
if (found.kind === "proxy") {
|
|
146
|
-
|
|
147
|
-
|
|
146
|
+
const origins = [
|
|
147
|
+
found.httpUrl && `HTTP ${describeProxyForLog(found.httpUrl)}`,
|
|
148
|
+
found.httpsUrl && `HTTPS ${describeProxyForLog(found.httpsUrl)}`,
|
|
149
|
+
].filter(Boolean).join(", ");
|
|
150
|
+
console.log(`[opencodex] proxy "auto": using Windows system proxy ${origins}`);
|
|
151
|
+
if (found.httpUrl) process.env.HTTP_PROXY = found.httpUrl;
|
|
152
|
+
if (found.httpsUrl) process.env.HTTPS_PROXY = found.httpsUrl;
|
|
153
|
+
proxy = undefined;
|
|
148
154
|
} else {
|
|
149
155
|
const reason = found.kind === "unsupported"
|
|
150
156
|
? "only Windows system proxy discovery is supported; using direct egress on this OS"
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The `compaction.trigger` values Codex labels a compaction turn with (`CompactionTrigger`
|
|
3
|
+
* in codex-rs: a manual `/compact` versus automatic compaction). `compactionRouting.triggers`
|
|
4
|
+
* selects which of them an override applies to.
|
|
5
|
+
*
|
|
6
|
+
* This is its own leaf module and imports nothing on purpose. The request path reads it from
|
|
7
|
+
* `src/server/responses/compaction-routing.ts`; importing `leaf-validators.ts` there instead
|
|
8
|
+
* closes a cycle with `config-schema.ts` that survives typecheck and then fails at run time
|
|
9
|
+
* with "Cannot access 'runtimeRoleSchema' before initialization".
|
|
10
|
+
*/
|
|
11
|
+
export const COMPACTION_TRIGGERS = ["manual", "auto"] as const;
|
|
@@ -21,6 +21,7 @@ import {
|
|
|
21
21
|
CODEX_ACCOUNT_NAMESPACE_ACCOUNT_ID_COLLISION_ERROR,
|
|
22
22
|
codexAccountNamespacesSchema,
|
|
23
23
|
modelPinnedEffortsSchema,
|
|
24
|
+
compactionRoutingSchema,
|
|
24
25
|
modelPreferHostedToolsConfigError,
|
|
25
26
|
providerModelCostsConfigError,
|
|
26
27
|
providerRelativeSendPathConfigError,
|
|
@@ -45,6 +46,7 @@ import {
|
|
|
45
46
|
MAIN_CODEX_ACCOUNT_NAMESPACE_TARGET,
|
|
46
47
|
} from "../../codex/account-namespace-match";
|
|
47
48
|
import { UPSTREAM_HOST_CIRCUIT_MAX_THRESHOLD } from "../../codex/upstream-host-health";
|
|
49
|
+
import { MIN_USAGE_LEDGER_MAX_BYTES } from "../../usage/retention-contract";
|
|
48
50
|
import { COMBO_NAMESPACE, comboConfigIssues } from "../../combos/types";
|
|
49
51
|
import { routingProfileIssues } from "../../routing/profile";
|
|
50
52
|
import { POLICY_NAMESPACE } from "../../routing/profile-namespace";
|
|
@@ -73,12 +75,22 @@ export const configSchema = z.object({
|
|
|
73
75
|
// A malformed privacy block must never be read as "unmask": .catch(undefined) drops it and
|
|
74
76
|
// emailMaskingEnabled then falls back to masked, which is also what an absent block means.
|
|
75
77
|
privacy: z.object({ maskEmails: z.boolean().optional() }).strict().optional().catch(undefined),
|
|
78
|
+
// Malformed hand edits disable this opt-in exporter. Live writes reject them in diagnostics.ts.
|
|
79
|
+
metricsExport: z.object({ enabled: z.boolean().optional() }).strict().optional().catch(undefined),
|
|
76
80
|
// A malformed present client block must remain diagnosable from raw config and
|
|
77
81
|
// fail closed through src/client/state.ts; unrelated provider state still loads.
|
|
78
82
|
client: clientConnectionSchema.optional().catch(undefined),
|
|
79
83
|
managementUsageMaxReadBytes: z.number().int().positive().default(64 * 1024 * 1024).describe(
|
|
80
84
|
"Deprecated compatibility limit for bounded legacy usage readers; GET /api/usage always aggregates the complete ledger",
|
|
81
85
|
),
|
|
86
|
+
// Opt-in ledger ceiling. A hand edit below the floor, or a non-safe integer, disables only
|
|
87
|
+
// this limit rather than failing the config: refusing to start because history retention was
|
|
88
|
+
// mistyped would be a worse outcome than not trimming history.
|
|
89
|
+
usageLedgerMaxBytes: z.number().int()
|
|
90
|
+
.min(MIN_USAGE_LEDGER_MAX_BYTES)
|
|
91
|
+
.max(Number.MAX_SAFE_INTEGER)
|
|
92
|
+
.optional()
|
|
93
|
+
.catch(undefined),
|
|
82
94
|
// Invalid hand edits disable only this opt-in circuit. Live writes remain strict.
|
|
83
95
|
upstreamHostCircuitThreshold: z.number().int()
|
|
84
96
|
.min(0)
|
|
@@ -125,6 +137,7 @@ export const configSchema = z.object({
|
|
|
125
137
|
]).optional().catch(undefined),
|
|
126
138
|
providers: z.record(z.string(), providerConfigSchema),
|
|
127
139
|
modelPinnedEfforts: modelPinnedEffortsSchema.optional(),
|
|
140
|
+
compactionRouting: compactionRoutingSchema.optional().catch(undefined),
|
|
128
141
|
defaultProvider: z.string().min(1).default("openai"),
|
|
129
142
|
defaultModelAliases: z.boolean().optional(),
|
|
130
143
|
// Malformed hand edits disable this opt-in projection without rejecting providers.
|
|
@@ -257,7 +270,24 @@ export const configSchema = z.object({
|
|
|
257
270
|
if (claudeCode !== undefined && (!claudeCode || typeof claudeCode !== "object" || Array.isArray(claudeCode))) {
|
|
258
271
|
ctx.addIssue({ code: "custom", path: ["claudeCode"], message: "claudeCode must be an object" });
|
|
259
272
|
} else if (claudeCode) {
|
|
260
|
-
const claude = claudeCode as { desktopProfile?: unknown };
|
|
273
|
+
const claude = claudeCode as { desktopProfile?: unknown; desktopMode?: unknown; intercept?: unknown };
|
|
274
|
+
if (claude.desktopMode !== undefined && claude.desktopMode !== "first-party" && claude.desktopMode !== "gateway") {
|
|
275
|
+
ctx.addIssue({ code: "custom", path: ["claudeCode", "desktopMode"], message: "desktopMode must be \"first-party\" or \"gateway\"" });
|
|
276
|
+
}
|
|
277
|
+
if (claude.intercept !== undefined) {
|
|
278
|
+
const intercept = claude.intercept;
|
|
279
|
+
if (!intercept || typeof intercept !== "object" || Array.isArray(intercept)) {
|
|
280
|
+
ctx.addIssue({ code: "custom", path: ["claudeCode", "intercept"], message: "intercept must be an object" });
|
|
281
|
+
} else {
|
|
282
|
+
const { enabled, port } = intercept as { enabled?: unknown; port?: unknown };
|
|
283
|
+
if (enabled !== undefined && typeof enabled !== "boolean") {
|
|
284
|
+
ctx.addIssue({ code: "custom", path: ["claudeCode", "intercept", "enabled"], message: "intercept.enabled must be a boolean" });
|
|
285
|
+
}
|
|
286
|
+
if (port !== undefined && (typeof port !== "number" || !Number.isInteger(port) || port < 1 || port > 65535)) {
|
|
287
|
+
ctx.addIssue({ code: "custom", path: ["claudeCode", "intercept", "port"], message: "intercept.port must be an integer between 1 and 65535" });
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
}
|
|
261
291
|
if (claude.desktopProfile !== undefined) {
|
|
262
292
|
try {
|
|
263
293
|
parseDesktopProfile(claude.desktopProfile);
|
|
@@ -17,6 +17,7 @@ import { isCodexAccountPriorityKey } from "../../codex/account-priority";
|
|
|
17
17
|
import { parseAccountPriority } from "../../codex/pool-rotation";
|
|
18
18
|
import { credentialGroupIssues } from "../../routing/identity-domains";
|
|
19
19
|
import { providerDestinationConfigError } from "../../lib/destination-policy";
|
|
20
|
+
import { providerEgressConfigError } from "../../lib/provider-egress";
|
|
20
21
|
import { redactSecretString } from "../../lib/redact";
|
|
21
22
|
import {
|
|
22
23
|
MODEL_ADAPTER_OVERRIDE_ALLOWED,
|
|
@@ -38,12 +39,21 @@ import {
|
|
|
38
39
|
isHostedToolUnsupportedForModel,
|
|
39
40
|
} from "../../responses/hosted-tool-policy";
|
|
40
41
|
import { getConfigDir } from "../paths";
|
|
42
|
+
import { COMPACTION_TRIGGERS } from "./compaction-triggers";
|
|
41
43
|
|
|
42
44
|
/** One definition of "usable secret", shared by the schema and the warnings. */
|
|
43
45
|
export function isUsableApiKeySecret(value: unknown): value is string {
|
|
44
46
|
return typeof value === "string" && value.length > 0 && value === value.trim();
|
|
45
47
|
}
|
|
46
48
|
|
|
49
|
+
export const compactionRoutingSchema = z.object({
|
|
50
|
+
model: z.string().trim().min(1),
|
|
51
|
+
reasoningEffort: z.string().refine(value => pinnedReasoningEffortConfigError(value) === null).optional(),
|
|
52
|
+
triggers: z.array(z.enum(COMPACTION_TRIGGERS)).nonempty()
|
|
53
|
+
.refine(values => new Set(values).size === values.length, "triggers must not repeat a value")
|
|
54
|
+
.optional(),
|
|
55
|
+
}).strict();
|
|
56
|
+
|
|
47
57
|
/**
|
|
48
58
|
* Bounds for the opt-in same-target 429 wait-and-retry policy. Single source of truth
|
|
49
59
|
* shared by the config schema, the load-time sanitizer, and the management write
|
|
@@ -71,6 +81,17 @@ const transientRetryOn5xxPolicySchema = z.object({
|
|
|
71
81
|
attempts: z.number().int().min(1).max(10).optional(),
|
|
72
82
|
}).strict();
|
|
73
83
|
|
|
84
|
+
/**
|
|
85
|
+
* `retryOnReset` accepts only these keys. `replacements` counts DUPLICATE inferences the
|
|
86
|
+
* operator is willing to risk for one logical request, so the ceiling is two rather than a
|
|
87
|
+
* send budget: this is the one send the proxy otherwise refuses outright, and a third of them
|
|
88
|
+
* says the connection, not the retry policy, is the problem.
|
|
89
|
+
*/
|
|
90
|
+
export const retryOnResetPolicySchema = z.object({
|
|
91
|
+
enabled: z.boolean().optional(),
|
|
92
|
+
replacements: z.number().int().min(1).max(2).optional(),
|
|
93
|
+
}).strict();
|
|
94
|
+
|
|
74
95
|
const requestPacingRuleSchema = z.object({
|
|
75
96
|
// Keep the RPM-derived timer within the same one-hour bound as minIntervalMs.
|
|
76
97
|
requestsPerMinute: z.number().min(1 / 60).max(60_000).optional(),
|
|
@@ -212,6 +233,25 @@ const modelCapabilitiesSchema = z.unknown().superRefine((value, ctx) => {
|
|
|
212
233
|
if (error) ctx.addIssue({ code: "custom", message: error });
|
|
213
234
|
}).transform(value => mergeModelCapabilities(undefined, value));
|
|
214
235
|
|
|
236
|
+
/**
|
|
237
|
+
* Per-provider egress fields, validated by the resolver the transports themselves use.
|
|
238
|
+
*
|
|
239
|
+
* Calling `providerEgressConfigError` rather than restating the accepted forms keeps one
|
|
240
|
+
* definition of a usable value: a proxy the config loader admits is one the transport can
|
|
241
|
+
* carry, and a value rejected here is rejected at request time for the identical reason.
|
|
242
|
+
* Each field is checked on its own because neither depends on the other's value to be
|
|
243
|
+
* well-formed; how they combine is decided per request against the destination.
|
|
244
|
+
*/
|
|
245
|
+
const providerProxySchema = z.unknown().superRefine((value, ctx) => {
|
|
246
|
+
const error = providerEgressConfigError({ proxy: value as string | null | undefined });
|
|
247
|
+
if (error) ctx.addIssue({ code: "custom", message: error });
|
|
248
|
+
}).transform(value => value as string | null | undefined);
|
|
249
|
+
|
|
250
|
+
const providerNoProxySchema = z.unknown().superRefine((value, ctx) => {
|
|
251
|
+
const error = providerEgressConfigError({ noProxy: value as string | string[] | undefined });
|
|
252
|
+
if (error) ctx.addIssue({ code: "custom", message: error });
|
|
253
|
+
}).transform(value => value as string | string[] | undefined);
|
|
254
|
+
|
|
215
255
|
/**
|
|
216
256
|
* Zod schema for one provider entry: known fields are validated strictly while unknown
|
|
217
257
|
* fields pass through (preserved for runtime extensions).
|
|
@@ -249,14 +289,21 @@ export const providerConfigSchema = z.object({
|
|
|
249
289
|
requiresAdjacentResponsesToolResults: z.boolean().optional(),
|
|
250
290
|
requiresPairedResponsesToolResults: z.boolean().optional(),
|
|
251
291
|
annotateEmptyToolOutputs: z.boolean().optional(),
|
|
292
|
+
foldDeveloperRoleToSystem: z.boolean().optional(),
|
|
252
293
|
fastWire: fastWireSchema.nullable().optional(),
|
|
253
294
|
supportsServiceTier: z.boolean().optional(),
|
|
254
295
|
modelSupportsServiceTier: z.record(z.string().min(1), z.boolean()).optional(),
|
|
255
296
|
modelSuppressSyntheticMax: z.record(z.string().min(1), z.boolean()).optional(),
|
|
256
297
|
preserveResponsesReasoningContent: z.boolean().optional(),
|
|
298
|
+
dropResponsesReasoningItems: z.boolean().optional(),
|
|
299
|
+
modelReasoningEffortsAuthoritative: z.boolean().optional(),
|
|
257
300
|
decodesNativeCompactionBlobs: z.boolean().optional(),
|
|
258
301
|
allowEncryptedV2AgentTasks: z.boolean().optional(),
|
|
259
302
|
allowPrivateNetwork: z.boolean().optional(),
|
|
303
|
+
// Per-provider egress (#2894): absent inherits the global proxy decision, "direct"/null
|
|
304
|
+
// refuses it, and an http(s) or socks5 URL replaces it for this provider only.
|
|
305
|
+
proxy: providerProxySchema.optional(),
|
|
306
|
+
noProxy: providerNoProxySchema.optional(),
|
|
260
307
|
// The management API accepts `null` as "clear this", so a config written before the POST
|
|
261
308
|
// canonicalization below can hold one on disk. Rejecting it here would send the operator
|
|
262
309
|
// through invalid-config recovery for a value the API told them was fine.
|
|
@@ -268,6 +315,7 @@ export const providerConfigSchema = z.object({
|
|
|
268
315
|
// canonical ChatGPT backend WS selection is independent of this flag.
|
|
269
316
|
upstreamWebsocket: z.boolean().optional(),
|
|
270
317
|
directGeminiWireRenames: z.boolean().optional(),
|
|
318
|
+
googleToolSchemaPolicy: z.enum(["compatible", "reject-lossy"]).optional(),
|
|
271
319
|
noStructuredOutputModels: z.array(z.string().min(1))
|
|
272
320
|
.transform(normalizeNonBlankStringArray)
|
|
273
321
|
.optional(),
|
|
@@ -294,6 +342,10 @@ export const providerConfigSchema = z.object({
|
|
|
294
342
|
.optional(),
|
|
295
343
|
retryOn429: retryOn429PolicySchema.optional(),
|
|
296
344
|
transientRetryOn5xx: transientRetryOn5xxPolicySchema.optional(),
|
|
345
|
+
// Degrades to "absent" like `webSearchBridge`: a malformed hand edit of an opt-in feature
|
|
346
|
+
// that is off by default must not send the operator through invalid-config recovery. The
|
|
347
|
+
// management write boundary still rejects it loudly (`retryOnResetPolicyConfigError`).
|
|
348
|
+
retryOnReset: retryOnResetPolicySchema.optional().catch(undefined),
|
|
297
349
|
codexAccountMode: z.enum(["pool", "direct"]).optional(),
|
|
298
350
|
// Validated rather than passed through: this schema ends in `.passthrough()`, so an
|
|
299
351
|
// undeclared key survives verbatim. A misspelled `codexToolMode` therefore used to be
|
|
@@ -637,6 +689,13 @@ export const apiKeyEntrySchema = z.object({
|
|
|
637
689
|
createdAt: z.string().catch(""),
|
|
638
690
|
// A damaged overlap record must never discard the still-authoritative key.
|
|
639
691
|
pendingRotation: pendingApiKeyRotationSchema.optional().catch(undefined),
|
|
692
|
+
// Deliberately NOT `.catch`ed, unlike every field above. Degrading a damaged
|
|
693
|
+
// scope to `undefined` would silently widen the key to the whole catalog,
|
|
694
|
+
// which is the one direction a permission field must never fail. Letting the
|
|
695
|
+
// record fail instead drops the key, so a corrupted scope stops that client
|
|
696
|
+
// rather than promoting it.
|
|
697
|
+
allowedProviders: z.array(z.string().trim().min(1).max(256)).optional(),
|
|
698
|
+
allowedModels: z.array(z.string().trim().min(1).max(256)).optional(),
|
|
640
699
|
}).passthrough();
|
|
641
700
|
|
|
642
701
|
/**
|
package/src/config.ts
CHANGED
|
@@ -110,7 +110,7 @@ export {
|
|
|
110
110
|
sanitizeModelCostsForDisplay,
|
|
111
111
|
modelPreferHostedToolsConfigError,
|
|
112
112
|
} from "./config/schema/leaf-validators";
|
|
113
|
-
export { hardenExistingSecret, retryOn429PolicyConfigError } from "./config/load-degrade";
|
|
113
|
+
export { hardenExistingSecret, retryOn429PolicyConfigError, retryOnResetPolicyConfigError } from "./config/load-degrade";
|
|
114
114
|
export { backupInvalidConfig } from "./config/salvage";
|
|
115
115
|
export type { ConfigDiagnostics, ConfigAdmissionSnapshot } from "./config/diagnostics";
|
|
116
116
|
export {
|
|
@@ -170,7 +170,7 @@ import {
|
|
|
170
170
|
sanitizeModelCostsForLoad,
|
|
171
171
|
sanitizeCapabilityDeclarationsForLoad,
|
|
172
172
|
warnInheritedFastWireConflicts,
|
|
173
|
-
|
|
173
|
+
warnDegradedTopLevelOptIns,
|
|
174
174
|
warnDegradedHostname,
|
|
175
175
|
warnDegradedListeners,
|
|
176
176
|
warnDegradedApiKeys,
|
|
@@ -227,7 +227,7 @@ export function loadConfig(): OcxConfig {
|
|
|
227
227
|
if (result.success) {
|
|
228
228
|
const config = normalizeApiKeyIds(result.data as OcxConfig);
|
|
229
229
|
warnInheritedFastWireConflicts(configPath, config);
|
|
230
|
-
|
|
230
|
+
warnDegradedTopLevelOptIns(parsed, config);
|
|
231
231
|
warnDegradedHostname(parsed, config);
|
|
232
232
|
warnDegradedListeners(parsed, config);
|
|
233
233
|
warnDegradedApiKeys(parsed, config);
|