@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
|
@@ -11,7 +11,9 @@
|
|
|
11
11
|
import { commitProviderApiKeySelection } from "./api-key-selection";
|
|
12
12
|
import type { ProviderApiKeySelection } from "../types/provider";
|
|
13
13
|
import { routedProviderConfig } from "../router";
|
|
14
|
-
import
|
|
14
|
+
import { getProviderRegistryEntry } from "./registry";
|
|
15
|
+
import { normalizedBaseUrl } from "./quota/vendor-probes-key";
|
|
16
|
+
import type { OcxConfig, OcxProviderConfig, RateLimitRetryPolicy, ResetReplayPolicy, TransientRetryPolicy } from "../types";
|
|
15
17
|
import { OPENCODE_GO_SESSION_HEADER } from "./opencode-go-transport";
|
|
16
18
|
import { resolveProviderTransport, type OcxProviderTransport } from "./xai-transport";
|
|
17
19
|
import { sweepExpiredOnWrite } from "../lib/state-store-sweeper";
|
|
@@ -278,6 +280,43 @@ const DEFAULT_RATE_LIMIT_RETRY = {
|
|
|
278
280
|
respectRetryAfter: true,
|
|
279
281
|
} as const satisfies Required<RateLimitRetryPolicy>;
|
|
280
282
|
|
|
283
|
+
/**
|
|
284
|
+
* Patient same-target 429 fallback for the OpenCode Go destination
|
|
285
|
+
* (https://opencode.ai/zen/go/v1), which serves subscription traffic such as Muse Spark.
|
|
286
|
+
* Single-key pools cannot fail over, so without this a burst 429 surfaces immediately and
|
|
287
|
+
* the client retry budget aborts the goal. Six 10s-paced attempts absorb a short burst
|
|
288
|
+
* window (effective replays are additionally bounded by the shared per-request send
|
|
289
|
+
* budget); Retry-After is still honored and capped. An explicit `retryOn429` (including
|
|
290
|
+
* `enabled: false`) always overrides this fallback.
|
|
291
|
+
*/
|
|
292
|
+
const OPENCODE_GO_RATE_LIMIT_RETRY = {
|
|
293
|
+
enabled: true,
|
|
294
|
+
attempts: 6,
|
|
295
|
+
intervalMs: 10_000,
|
|
296
|
+
maxIntervalMs: 60_000,
|
|
297
|
+
respectRetryAfter: true,
|
|
298
|
+
} as const satisfies Required<RateLimitRetryPolicy>;
|
|
299
|
+
|
|
300
|
+
/** True when the provider row points at the OpenCode Go destination. */
|
|
301
|
+
export function isOpenCodeGoDestination(
|
|
302
|
+
provider: Partial<Pick<OcxProviderConfig, "baseUrl" | "authMode">>,
|
|
303
|
+
): boolean {
|
|
304
|
+
const raw = typeof provider.baseUrl === "string" ? provider.baseUrl : "";
|
|
305
|
+
if (!raw.trim()) return false;
|
|
306
|
+
// Endpoint identity, not adapter identity: the runtime adapter is already overridden
|
|
307
|
+
// per model by the time the recovery loop runs (muse-spark rides `openai-responses`
|
|
308
|
+
// while the preset declares `openai-chat`), so an adapter-strict lookup misses it.
|
|
309
|
+
// Canonicalize with the shared quota-probe normalizer so host case and explicit
|
|
310
|
+
// default ports compare equal; userinfo, query, and fragment never match
|
|
311
|
+
// (follow-up to the review on #5067).
|
|
312
|
+
const endpoint = normalizedBaseUrl(raw.trim());
|
|
313
|
+
if (!endpoint) return false;
|
|
314
|
+
const entry = getProviderRegistryEntry("opencode-go");
|
|
315
|
+
if (!entry) return false;
|
|
316
|
+
const candidates = [entry.baseUrl, ...(entry.destinationAliases ?? []).map(alias => alias.baseUrl)];
|
|
317
|
+
return candidates.some(url => normalizedBaseUrl(url.trim()) === endpoint);
|
|
318
|
+
}
|
|
319
|
+
|
|
281
320
|
/**
|
|
282
321
|
* Default transient-5xx retry used when a provider opts in with a bare
|
|
283
322
|
* `transientRetryOn5xx: {}`. `attempts` is a TOTAL send budget, not extra retries.
|
|
@@ -287,6 +326,16 @@ const DEFAULT_TRANSIENT_RETRY = {
|
|
|
287
326
|
attempts: 3,
|
|
288
327
|
} as const satisfies Required<TransientRetryPolicy>;
|
|
289
328
|
|
|
329
|
+
/**
|
|
330
|
+
* Default used when a provider opts in with a bare `retryOnReset: {}`: one replacement for
|
|
331
|
+
* the whole logical request. `replacements` counts duplicate inferences the operator accepts,
|
|
332
|
+
* not retries and not sends.
|
|
333
|
+
*/
|
|
334
|
+
const DEFAULT_RESET_REPLAY = {
|
|
335
|
+
enabled: true,
|
|
336
|
+
replacements: 1,
|
|
337
|
+
} as const satisfies Required<ResetReplayPolicy>;
|
|
338
|
+
|
|
290
339
|
/** Map<`${providerName}\0${keyId}`, KeyCooldown> */
|
|
291
340
|
const keyCooldowns = new Map<string, KeyCooldown>();
|
|
292
341
|
|
|
@@ -513,29 +562,38 @@ export function selectProactiveApiKeyTransport(
|
|
|
513
562
|
}
|
|
514
563
|
|
|
515
564
|
/**
|
|
516
|
-
* Normalize a provider's `retryOn429` policy
|
|
517
|
-
*
|
|
518
|
-
*
|
|
519
|
-
*
|
|
520
|
-
*
|
|
565
|
+
* Normalize a provider's `retryOn429` policy. An explicit object always wins (including
|
|
566
|
+
* `enabled: false` to opt out). When the knob is absent, the OpenCode Go destination
|
|
567
|
+
* (subscription traffic such as Muse Spark) falls back to a patient same-key policy so a
|
|
568
|
+
* burst 429 waits and replays instead of surfacing to the client and aborting a long
|
|
569
|
+
* session; every other provider without the knob keeps today's fail-fast behavior.
|
|
570
|
+
* OAuth/forward/local credentials are never replayed on the same token. The returned
|
|
571
|
+
* policy is fully defaulted so callers never re-check fields.
|
|
521
572
|
*/
|
|
522
573
|
export function rateLimitRetryPolicyFor(
|
|
523
|
-
provider: Pick<OcxProviderConfig, "retryOn429" | "authMode"
|
|
574
|
+
provider: Pick<OcxProviderConfig, "retryOn429" | "authMode"> &
|
|
575
|
+
Partial<Pick<OcxProviderConfig, "baseUrl" | "adapter">>,
|
|
524
576
|
): Required<RateLimitRetryPolicy> | null {
|
|
525
577
|
const policy = provider.retryOn429;
|
|
526
|
-
if (
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
578
|
+
if (policy) {
|
|
579
|
+
if (policy.enabled === false) return null;
|
|
580
|
+
// Fail closed: only explicit key auth or the documented omitted-default (undefined == key for
|
|
581
|
+
// custom API-key providers) may use same-key replays. OAuth/forward are never replayed on the
|
|
582
|
+
// same token, local runtimes have no remote key to preserve, and unknown/custom values are
|
|
583
|
+
// rejected rather than guessed at.
|
|
584
|
+
if (provider.authMode !== undefined && provider.authMode !== "key") return null;
|
|
585
|
+
return {
|
|
586
|
+
enabled: policy.enabled ?? DEFAULT_RATE_LIMIT_RETRY.enabled,
|
|
587
|
+
attempts: policy.attempts ?? DEFAULT_RATE_LIMIT_RETRY.attempts,
|
|
588
|
+
intervalMs: policy.intervalMs ?? DEFAULT_RATE_LIMIT_RETRY.intervalMs,
|
|
589
|
+
maxIntervalMs: policy.maxIntervalMs ?? DEFAULT_RATE_LIMIT_RETRY.maxIntervalMs,
|
|
590
|
+
respectRetryAfter: policy.respectRetryAfter ?? DEFAULT_RATE_LIMIT_RETRY.respectRetryAfter,
|
|
591
|
+
};
|
|
592
|
+
}
|
|
593
|
+
// No explicit knob: patient fallback for the OpenCode Go destination only.
|
|
531
594
|
if (provider.authMode !== undefined && provider.authMode !== "key") return null;
|
|
532
|
-
return
|
|
533
|
-
|
|
534
|
-
attempts: policy.attempts ?? DEFAULT_RATE_LIMIT_RETRY.attempts,
|
|
535
|
-
intervalMs: policy.intervalMs ?? DEFAULT_RATE_LIMIT_RETRY.intervalMs,
|
|
536
|
-
maxIntervalMs: policy.maxIntervalMs ?? DEFAULT_RATE_LIMIT_RETRY.maxIntervalMs,
|
|
537
|
-
respectRetryAfter: policy.respectRetryAfter ?? DEFAULT_RATE_LIMIT_RETRY.respectRetryAfter,
|
|
538
|
-
};
|
|
595
|
+
if (!isOpenCodeGoDestination(provider)) return null;
|
|
596
|
+
return { ...OPENCODE_GO_RATE_LIMIT_RETRY };
|
|
539
597
|
}
|
|
540
598
|
|
|
541
599
|
/**
|
|
@@ -568,6 +626,26 @@ export function transientRetryPolicyFor(
|
|
|
568
626
|
};
|
|
569
627
|
}
|
|
570
628
|
|
|
629
|
+
/**
|
|
630
|
+
* Normalize a provider's `retryOnReset` policy, or return null when it is absent or explicitly
|
|
631
|
+
* disabled.
|
|
632
|
+
*
|
|
633
|
+
* No auth-mode gate: the canonical ChatGPT backend is `forward` auth and is the send this
|
|
634
|
+
* policy exists for. Whether a given REQUEST may be replaced is a per-body decision made in
|
|
635
|
+
* src/server/responses/reset-replay.ts, and how many replacements the request gets is the
|
|
636
|
+
* shared allowance on its execution budget. This function only reads the operator's intent.
|
|
637
|
+
*/
|
|
638
|
+
export function resetReplayPolicyFor(
|
|
639
|
+
provider: Pick<OcxProviderConfig, "retryOnReset">,
|
|
640
|
+
): Required<ResetReplayPolicy> | null {
|
|
641
|
+
const policy = provider.retryOnReset;
|
|
642
|
+
if (!policy || policy.enabled === false) return null;
|
|
643
|
+
return {
|
|
644
|
+
enabled: policy.enabled ?? DEFAULT_RESET_REPLAY.enabled,
|
|
645
|
+
replacements: policy.replacements ?? DEFAULT_RESET_REPLAY.replacements,
|
|
646
|
+
};
|
|
647
|
+
}
|
|
648
|
+
|
|
571
649
|
/**
|
|
572
650
|
* Wait before the next same-target replay: upstream Retry-After (seconds or HTTP-date) when
|
|
573
651
|
* `respectRetryAfter` is on and the header parses, capped at `maxIntervalMs`; otherwise the
|
|
@@ -1,7 +1,34 @@
|
|
|
1
|
-
import { createRequire } from "node:module";
|
|
2
1
|
import { resolveEnvValue, saveConfigPreservingClaudeCode } from "../config";
|
|
3
2
|
import type { OcxConfig, OcxProviderConfig } from "../types";
|
|
4
3
|
import type { ProviderRegistryEntry } from "./registry";
|
|
4
|
+
import {
|
|
5
|
+
KEYCHAIN_REFERENCE_PREFIX,
|
|
6
|
+
invalidateResolvedProviderKeyCache,
|
|
7
|
+
isKeychainReference,
|
|
8
|
+
keychainAccount,
|
|
9
|
+
keychainReferenceBelongsToProvider,
|
|
10
|
+
probeProviderKeychain,
|
|
11
|
+
providerKeychainEntry,
|
|
12
|
+
} from "./api-key-resolve";
|
|
13
|
+
|
|
14
|
+
// The read-path (reference predicates, the OS entry factory, resolveProviderApiKey, the probe
|
|
15
|
+
// and the kind classification) lives in ./api-key-resolve -- a leaf module that
|
|
16
|
+
// reasoning-metadata can also import without pulling the ../config barrel into its
|
|
17
|
+
// cycle-sensitive graph. Re-exported here so existing key-store consumers keep working.
|
|
18
|
+
export {
|
|
19
|
+
KEYCHAIN_REFERENCE_PREFIX,
|
|
20
|
+
PROVIDER_KEYCHAIN_SERVICE,
|
|
21
|
+
isKeychainReference,
|
|
22
|
+
probeProviderKeychain,
|
|
23
|
+
providerKeyStoreKind,
|
|
24
|
+
resolveProviderApiKey,
|
|
25
|
+
setProviderKeychainEntryFactoryForTests,
|
|
26
|
+
} from "./api-key-resolve";
|
|
27
|
+
export type {
|
|
28
|
+
ProviderKeychainEntry,
|
|
29
|
+
ProviderKeychainEntryFactory,
|
|
30
|
+
ProviderKeyStoreKind,
|
|
31
|
+
} from "./api-key-resolve";
|
|
5
32
|
|
|
6
33
|
/** Shared with routing: a key-mode override is effective only while its key resolves. */
|
|
7
34
|
export function providerUsesKeyAuthOverride(
|
|
@@ -27,109 +54,8 @@ export function providerUsesKeyAuthOverride(
|
|
|
27
54
|
* (headless service, locked session) refuses rather than half-migrating.
|
|
28
55
|
*/
|
|
29
56
|
|
|
30
|
-
export const KEYCHAIN_REFERENCE_PREFIX = "keychain:";
|
|
31
|
-
export const PROVIDER_KEYCHAIN_SERVICE = "opencodex.provider-api-key.v1";
|
|
32
|
-
|
|
33
|
-
export interface ProviderKeychainEntry {
|
|
34
|
-
getPassword(): string | null;
|
|
35
|
-
setPassword(password: string): void;
|
|
36
|
-
deletePassword(): boolean;
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
export type ProviderKeychainEntryFactory = (service: string, account: string) => ProviderKeychainEntry;
|
|
40
|
-
|
|
41
|
-
const nodeRequire = createRequire(import.meta.url);
|
|
42
|
-
|
|
43
|
-
function defaultEntryFactory(service: string, account: string): ProviderKeychainEntry {
|
|
44
|
-
const { Entry } = nodeRequire("@napi-rs/keyring") as { Entry: new (s: string, a: string) => ProviderKeychainEntry };
|
|
45
|
-
return new Entry(service, account);
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
let entryFactory: ProviderKeychainEntryFactory = defaultEntryFactory;
|
|
49
|
-
const resolvedCache = new Map<string, string>();
|
|
50
|
-
const warnedAccounts = new Set<string>();
|
|
51
|
-
|
|
52
|
-
/** Test seam: swap the OS entry for an in-memory one and drop caches. */
|
|
53
|
-
export function setProviderKeychainEntryFactoryForTests(factory: ProviderKeychainEntryFactory | null): void {
|
|
54
|
-
entryFactory = factory ?? defaultEntryFactory;
|
|
55
|
-
resolvedCache.clear();
|
|
56
|
-
warnedAccounts.clear();
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
export function isKeychainReference(value: string | undefined): value is string {
|
|
60
|
-
return typeof value === "string" && value.startsWith(KEYCHAIN_REFERENCE_PREFIX) && value.length > KEYCHAIN_REFERENCE_PREFIX.length;
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
function keychainAccount(reference: string): string {
|
|
64
|
-
return reference.slice(KEYCHAIN_REFERENCE_PREFIX.length);
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
/**
|
|
68
|
-
* A reference belongs to `name` only when its account is that provider's own active account
|
|
69
|
-
* or one of its pool accounts. `storeProviderKeyInKeychain` writes exactly those two shapes,
|
|
70
|
-
* so anything else in a provider's config names another provider's secret.
|
|
71
|
-
*/
|
|
72
|
-
function keychainReferenceBelongsToProvider(reference: string, name: string): boolean {
|
|
73
|
-
const account = keychainAccount(reference);
|
|
74
|
-
return account === name || account.startsWith(`${name}/`);
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
function readKeychain(account: string): string | undefined {
|
|
78
|
-
const cached = resolvedCache.get(account);
|
|
79
|
-
if (cached !== undefined) return cached;
|
|
80
|
-
try {
|
|
81
|
-
const value = entryFactory(PROVIDER_KEYCHAIN_SERVICE, account).getPassword();
|
|
82
|
-
if (typeof value === "string" && value.trim()) {
|
|
83
|
-
resolvedCache.set(account, value);
|
|
84
|
-
return value;
|
|
85
|
-
}
|
|
86
|
-
} catch {
|
|
87
|
-
// fall through to the single warning below
|
|
88
|
-
}
|
|
89
|
-
if (!warnedAccounts.has(account)) {
|
|
90
|
-
warnedAccounts.add(account);
|
|
91
|
-
console.warn(`[opencodex] provider key reference keychain:${account} could not be read from the OS keychain; requests for this provider have no credential until the keychain is available (no plaintext fallback)`);
|
|
92
|
-
}
|
|
93
|
-
return undefined;
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
/**
|
|
97
|
-
* Single resolver for provider key material: env references, keychain references, or the
|
|
98
|
-
* literal value. Every request-time read of `apiKey` goes through here.
|
|
99
|
-
*/
|
|
100
|
-
export function resolveProviderApiKey(value: string | undefined): string | undefined {
|
|
101
|
-
if (!value) return undefined;
|
|
102
|
-
if (isKeychainReference(value)) return readKeychain(keychainAccount(value));
|
|
103
|
-
return resolveEnvValue(value);
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
export type ProviderKeyStoreKind = "keychain" | "env" | "file" | "none";
|
|
107
|
-
|
|
108
|
-
export function providerKeyStoreKind(provider: Pick<OcxProviderConfig, "apiKey"> | undefined): ProviderKeyStoreKind {
|
|
109
|
-
const key = provider?.apiKey;
|
|
110
|
-
if (!key) return "none";
|
|
111
|
-
if (isKeychainReference(key)) return "keychain";
|
|
112
|
-
if (/^\$\{?\w+\}?$/.test(key)) return "env";
|
|
113
|
-
return "file";
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
/** Probe the OS keychain with a throwaway account: write, read back, delete. */
|
|
117
|
-
export function probeProviderKeychain(): { available: true } | { available: false; reason: string } {
|
|
118
|
-
const account = `probe-${process.pid}-${Date.now()}`;
|
|
119
|
-
try {
|
|
120
|
-
const entry = entryFactory(PROVIDER_KEYCHAIN_SERVICE, account);
|
|
121
|
-
entry.setPassword("ok");
|
|
122
|
-
const back = entry.getPassword();
|
|
123
|
-
try { entry.deletePassword(); } catch { /* best effort */ }
|
|
124
|
-
if (back !== "ok") return { available: false, reason: "keychain read-back did not match" };
|
|
125
|
-
return { available: true };
|
|
126
|
-
} catch (error) {
|
|
127
|
-
return { available: false, reason: error instanceof Error ? error.message : "keychain unavailable" };
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
|
|
131
57
|
function writeVerified(account: string, secret: string): void {
|
|
132
|
-
const entry =
|
|
58
|
+
const entry = providerKeychainEntry(account);
|
|
133
59
|
entry.setPassword(secret);
|
|
134
60
|
if (entry.getPassword() !== secret) throw new Error(`keychain read-back mismatch for ${account}`);
|
|
135
61
|
}
|
|
@@ -177,13 +103,12 @@ export function storeProviderKeyInKeychain(config: OcxConfig, name: string): { o
|
|
|
177
103
|
}
|
|
178
104
|
} catch (error) {
|
|
179
105
|
for (const account of written) {
|
|
180
|
-
try {
|
|
106
|
+
try { providerKeychainEntry(account).deletePassword(); } catch { /* best effort */ }
|
|
181
107
|
}
|
|
182
108
|
return { ok: false, error: `OS keychain write failed: ${error instanceof Error ? error.message : "unknown"}`, status: 503 };
|
|
183
109
|
}
|
|
184
110
|
for (const apply of planned) apply();
|
|
185
|
-
|
|
186
|
-
warnedAccounts.clear();
|
|
111
|
+
invalidateResolvedProviderKeyCache();
|
|
187
112
|
saveConfigPreservingClaudeCode(config);
|
|
188
113
|
return { ok: true, moved: written.length };
|
|
189
114
|
}
|
|
@@ -211,7 +136,7 @@ export function restoreProviderKeyFromKeychain(config: OcxConfig, name: string):
|
|
|
211
136
|
const account = keychainAccount(ref);
|
|
212
137
|
if (resolved.has(account)) continue;
|
|
213
138
|
let value: string | null = null;
|
|
214
|
-
try { value =
|
|
139
|
+
try { value = providerKeychainEntry(account).getPassword(); } catch { value = null; }
|
|
215
140
|
if (!value) return { ok: false, error: `OS keychain has no readable secret for ${ref}; config left unchanged`, status: 503 };
|
|
216
141
|
resolved.set(account, value);
|
|
217
142
|
}
|
|
@@ -220,10 +145,9 @@ export function restoreProviderKeyFromKeychain(config: OcxConfig, name: string):
|
|
|
220
145
|
}
|
|
221
146
|
if (isKeychainReference(provider.apiKey)) provider.apiKey = resolved.get(keychainAccount(provider.apiKey))!;
|
|
222
147
|
for (const account of resolved.keys()) {
|
|
223
|
-
try {
|
|
148
|
+
try { providerKeychainEntry(account).deletePassword(); } catch { /* best effort */ }
|
|
224
149
|
}
|
|
225
|
-
|
|
226
|
-
warnedAccounts.clear();
|
|
150
|
+
invalidateResolvedProviderKeyCache();
|
|
227
151
|
saveConfigPreservingClaudeCode(config);
|
|
228
152
|
return { ok: true, restored: resolved.size };
|
|
229
153
|
}
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
import type { OcxProviderConfig } from "../types";
|
|
2
|
+
|
|
3
|
+
// Every provider field receives a deliberate identity role. A new field fails typecheck
|
|
4
|
+
// until its model-id semantics are classified; credentials and provider-wide policy are none.
|
|
5
|
+
type ModelRenameRole = "none" | "record" | "list" | "scalar" | "nested-models";
|
|
6
|
+
export const PROVIDER_MODEL_RENAME_ROLES = {
|
|
7
|
+
alias: "none",
|
|
8
|
+
modelAliases: "record",
|
|
9
|
+
modelDisplayNames: "record",
|
|
10
|
+
defaultAliases: "none",
|
|
11
|
+
adapter: "none",
|
|
12
|
+
codexToolMode: "none",
|
|
13
|
+
requestPacing: "nested-models",
|
|
14
|
+
mcpMaxTools: "none",
|
|
15
|
+
mcpMaxSchemaBytes: "none",
|
|
16
|
+
mcpMaxResultBytes: "none",
|
|
17
|
+
modelAdapters: "record",
|
|
18
|
+
fastWire: "none",
|
|
19
|
+
baseUrl: "none",
|
|
20
|
+
responsesPath: "none",
|
|
21
|
+
chatCompletionsPath: "none",
|
|
22
|
+
commandCodeVersion: "none",
|
|
23
|
+
statelessResponses: "none",
|
|
24
|
+
requiresAdjacentResponsesToolResults: "none",
|
|
25
|
+
requiresPairedResponsesToolResults: "none",
|
|
26
|
+
annotateEmptyToolOutputs: "none",
|
|
27
|
+
supportsServiceTier: "none",
|
|
28
|
+
modelSupportsServiceTier: "record",
|
|
29
|
+
preserveResponsesReasoningContent: "none",
|
|
30
|
+
modelReasoningEffortsAuthoritative: "none",
|
|
31
|
+
dropResponsesReasoningItems: "none",
|
|
32
|
+
decodesNativeCompactionBlobs: "none",
|
|
33
|
+
allowEncryptedV2AgentTasks: "none",
|
|
34
|
+
allowPrivateNetwork: "none",
|
|
35
|
+
proxy: "none",
|
|
36
|
+
noProxy: "none",
|
|
37
|
+
upstreamHttpVersion: "none",
|
|
38
|
+
upstreamWebsocket: "none",
|
|
39
|
+
directGeminiWireRenames: "none",
|
|
40
|
+
disabled: "none",
|
|
41
|
+
codexAccountMode: "none",
|
|
42
|
+
apiKey: "none",
|
|
43
|
+
apiKeyTransport: "none",
|
|
44
|
+
apiKeyPool: "none",
|
|
45
|
+
apiKeyPoolStrategy: "none",
|
|
46
|
+
apiKeySelectionRevision: "none",
|
|
47
|
+
_apiKeyAttempt: "none",
|
|
48
|
+
defaultModel: "scalar",
|
|
49
|
+
models: "list",
|
|
50
|
+
liveModels: "none",
|
|
51
|
+
selectedModels: "list",
|
|
52
|
+
initialModelSelection: "none",
|
|
53
|
+
retainModels: "list",
|
|
54
|
+
newModelPolicy: "none",
|
|
55
|
+
modelPreset: "none",
|
|
56
|
+
contextWindow: "none",
|
|
57
|
+
modelContextWindows: "record",
|
|
58
|
+
modelInputModalities: "record",
|
|
59
|
+
modelCapabilities: "record",
|
|
60
|
+
modelMaxInputTokens: "record",
|
|
61
|
+
modelAutoCompactTokenLimits: "record",
|
|
62
|
+
defaultMaxOutputTokens: "none",
|
|
63
|
+
modelMaxOutputTokens: "record",
|
|
64
|
+
modelCosts: "record",
|
|
65
|
+
autoReviewModel: "none",
|
|
66
|
+
autoReviewModelOverrides: "record",
|
|
67
|
+
headers: "none",
|
|
68
|
+
openRouterRouting: "none",
|
|
69
|
+
modelOpenRouterRouting: "record",
|
|
70
|
+
vercelGatewayRouting: "none",
|
|
71
|
+
modelVercelGatewayRouting: "record",
|
|
72
|
+
authMode: "none",
|
|
73
|
+
oauthAccountFailover: "none",
|
|
74
|
+
keyOptional: "none",
|
|
75
|
+
freeTier: "none",
|
|
76
|
+
note: "none",
|
|
77
|
+
modelSuffixBracketStrip: "none",
|
|
78
|
+
refreshPolicy: "none",
|
|
79
|
+
reasoningEfforts: "none",
|
|
80
|
+
modelReasoningEfforts: "record",
|
|
81
|
+
modelSuppressSyntheticMax: "record",
|
|
82
|
+
modelDefaultReasoningEfforts: "record",
|
|
83
|
+
pinnedReasoningEffort: "none",
|
|
84
|
+
modelPinnedReasoningEfforts: "record",
|
|
85
|
+
modelSupportsReasoningSummaries: "record",
|
|
86
|
+
modelSupportsVerbosity: "record",
|
|
87
|
+
supportsVerbosity: "none",
|
|
88
|
+
modelReasoningSummaryDelivery: "record",
|
|
89
|
+
modelPreferHostedTools: "record",
|
|
90
|
+
supportsOpenAiWebSearchToolFields: "none",
|
|
91
|
+
xaiResponsesXSearch: "none",
|
|
92
|
+
xaiResponsesDefaultVersion: "none",
|
|
93
|
+
zaiResponsesDefaultVersion: "none",
|
|
94
|
+
supportsResponsesCustomTools: "none",
|
|
95
|
+
unsupportedHostedTools: "none",
|
|
96
|
+
responsesSnapshotRepair: "none",
|
|
97
|
+
webSearchBridge: "none",
|
|
98
|
+
reasoningEffortMap: "none",
|
|
99
|
+
modelReasoningEffortMap: "record",
|
|
100
|
+
reasoningWireFormat: "none",
|
|
101
|
+
noReasoningModels: "list",
|
|
102
|
+
noTemperatureModels: "list",
|
|
103
|
+
noTopPModels: "list",
|
|
104
|
+
noPenaltyModels: "list",
|
|
105
|
+
noStructuredOutputModels: "list",
|
|
106
|
+
noJsonSchemaModels: "list",
|
|
107
|
+
omitReasoningEffortWithToolsModels: "list",
|
|
108
|
+
parallelToolCalls: "none",
|
|
109
|
+
pinParallelToolCallsFalse: "none",
|
|
110
|
+
terminalContinuationGuard: "none",
|
|
111
|
+
openaiChatEofTolerance: "none",
|
|
112
|
+
foldDeveloperRoleToSystem: "none",
|
|
113
|
+
promptCacheKey: "none",
|
|
114
|
+
chatServiceTier: "none",
|
|
115
|
+
responsesItemIdRepair: "none",
|
|
116
|
+
autoToolChoiceOnlyModels: "list",
|
|
117
|
+
preserveReasoningContentModels: "list",
|
|
118
|
+
requiresReasoningPlaceholderModels: "list",
|
|
119
|
+
showThinkingSummary: "none",
|
|
120
|
+
retryOn429: "none",
|
|
121
|
+
transientRetryOn5xx: "none",
|
|
122
|
+
retryOnReset: "none",
|
|
123
|
+
reasoningSplitModels: "list",
|
|
124
|
+
reasoningDetailsModels: "list",
|
|
125
|
+
thinkingToggleModels: "list",
|
|
126
|
+
thinkingBudgetModels: "list",
|
|
127
|
+
escapeBuiltinToolNames: "none",
|
|
128
|
+
anthropicEofTolerance: "none",
|
|
129
|
+
noVisionModels: "list",
|
|
130
|
+
googleMode: "none",
|
|
131
|
+
googleToolSchemaPolicy: "none",
|
|
132
|
+
project: "none",
|
|
133
|
+
location: "none",
|
|
134
|
+
mcpServers: "none",
|
|
135
|
+
desktopExecutor: "none",
|
|
136
|
+
unsafeAllowNativeLocalExec: "none",
|
|
137
|
+
nativeLocalExec: "none",
|
|
138
|
+
} as const satisfies Record<keyof OcxProviderConfig, ModelRenameRole>;
|
|
139
|
+
|
|
140
|
+
function fieldsWithRole(role: ModelRenameRole): string[] {
|
|
141
|
+
return Object.entries(PROVIDER_MODEL_RENAME_ROLES).filter(([, value]) => value === role).map(([key]) => key);
|
|
142
|
+
}
|
|
143
|
+
export const MODEL_KEYED_RECORDS = fieldsWithRole("record");
|
|
144
|
+
// Legacy persisted registry field, no longer part of the public provider config interface.
|
|
145
|
+
export const MODEL_ID_LISTS = [...fieldsWithRole("list"), "directReasoningEffortModels"];
|
|
146
|
+
export const MODEL_ID_SCALARS = fieldsWithRole("scalar");
|
|
147
|
+
export const MODEL_NESTED_RECORDS = fieldsWithRole("nested-models");
|