@bitkyc08/opencodex 2.83.0 → 2.86.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +0 -4
- package/bin/ocx.mjs +61 -3
- package/gui/dist/assets/App-BjlttVLy.js +58 -0
- package/gui/dist/assets/Tray-DyR9yBee.js +1 -0
- package/gui/dist/assets/{index-BAbcj51J.css → index-BB6uK6tU.css} +1 -1
- package/gui/dist/assets/index-BMssP4k3.js +94 -0
- package/gui/dist/assets/quota-summary-D8M1bc_R.js +1 -0
- package/gui/dist/index.html +2 -2
- package/package.json +2 -3
- package/src/adapters/anthropic/beta-allowlist.ts +87 -8
- package/src/adapters/anthropic/client-identity.ts +1 -1
- package/src/adapters/anthropic/passthrough.ts +33 -4
- package/src/adapters/azure.ts +19 -1
- package/src/adapters/client-fingerprint.ts +24 -0
- package/src/adapters/coding-agent/protocol.ts +15 -8
- package/src/adapters/coding-agent/turn.ts +22 -9
- package/src/adapters/cursor/arg-codec.ts +17 -5
- package/src/adapters/cursor/catalog.ts +8 -0
- package/src/adapters/cursor/effort-map.ts +3 -0
- package/src/adapters/cursor/freeform-args.ts +75 -0
- package/src/adapters/cursor/protobuf-events.ts +36 -23
- package/src/adapters/google-antigravity-wire.ts +22 -1
- package/src/adapters/google.ts +2 -2
- package/src/adapters/ollama-native.ts +29 -1
- package/src/adapters/openai-chat/messages.ts +8 -4
- package/src/adapters/openai-chat/response-events.ts +59 -1
- package/src/adapters/openai-chat.ts +8 -5
- package/src/adapters/openai-responses/empty-assistant.ts +32 -0
- package/src/adapters/openai-responses/passthrough.ts +3 -0
- package/src/adapters/openai-responses/request-strips.ts +10 -2
- package/src/adapters/qoder/adapter.ts +56 -15
- package/src/advisor/consult.ts +220 -0
- package/src/advisor/context.ts +226 -0
- package/src/advisor/disclosure.ts +20 -0
- package/src/advisor/runtime.ts +305 -0
- package/src/advisor/settings.ts +135 -0
- package/src/advisor/state.ts +369 -0
- package/src/advisor/synthetic-tool.ts +33 -0
- package/src/bridge/errors.ts +24 -0
- package/src/bridge.ts +1 -1
- package/src/chat/inbound.ts +30 -6
- package/src/chat/outbound.ts +5 -0
- package/src/claude/context-windows.ts +54 -1
- package/src/claude/desktop-3p-library.ts +43 -3
- package/src/claude/desktop-3p.ts +22 -8
- package/src/claude/desktop-picker-profile.ts +11 -4
- package/src/claude/desktop-profile.ts +10 -1
- package/src/claude/desktop-remote-store-io.ts +5 -3
- package/src/claude/inbound.ts +121 -50
- package/src/claude/intercept/connect-proxy.ts +10 -3
- package/src/claude/intercept/local-ca.ts +8 -1
- package/src/claude/intercept/picker-ca-persistence.ts +3 -1
- package/src/claude/intercept/picker-listener.ts +49 -1
- package/src/claude/intercept/settings-no-proxy.ts +146 -0
- package/src/claude/intercept/settings.ts +101 -9
- package/src/claude/model-default-settings.ts +154 -0
- package/src/claude/model-info.ts +7 -7
- package/src/claude/outbound.ts +13 -6
- package/src/cli/account-api.ts +65 -0
- package/src/cli/account-auth.ts +26 -2
- package/src/cli/account.ts +41 -5
- package/src/cli/advisor.ts +151 -0
- package/src/cli/auxiliary-listener-preflight.ts +37 -0
- package/src/cli/capabilities-access-remote.ts +8 -0
- package/src/cli/capabilities-agents-routing.ts +18 -0
- package/src/cli/capabilities-base.ts +14 -2
- package/src/cli/catalog-command-result.ts +2 -1
- package/src/cli/chatgpt-command.ts +35 -14
- package/src/cli/claude.ts +60 -11
- package/src/cli/config-command.ts +8 -2
- package/src/cli/debug.ts +8 -0
- package/src/cli/dispatch.ts +21 -4
- package/src/cli/doctor.ts +9 -0
- package/src/cli/ensure-desktop-cold-start.ts +329 -0
- package/src/cli/export-command.ts +15 -2
- package/src/cli/help.ts +2 -1
- package/src/cli/hub-disable.ts +99 -0
- package/src/cli/hub.ts +4 -2
- package/src/cli/index.ts +26 -8
- package/src/cli/integration-plan-dto.ts +2 -0
- package/src/cli/link-child.ts +104 -0
- package/src/cli/link-enrollment.ts +96 -0
- package/src/cli/link.ts +39 -24
- package/src/cli/observe-stream.ts +6 -1
- package/src/cli/observe.ts +10 -2
- package/src/cli/provider.ts +12 -0
- package/src/cli/registry.ts +20 -7
- package/src/cli/restart-scope.ts +3 -1
- package/src/cli/runtime-api.ts +27 -2
- package/src/cli/status.ts +104 -20
- package/src/client/connect.ts +39 -4
- package/src/client/hub-client.ts +14 -7
- package/src/client/hub-state.ts +25 -14
- package/src/client/link-home.ts +248 -0
- package/src/client/link-management-relay.ts +61 -0
- package/src/client/link-relay.ts +6 -1
- package/src/client/link-status.ts +14 -0
- package/src/client/machine-api.ts +14 -7
- package/src/client/machine-listener.ts +29 -4
- package/src/clients/config-export/contracts.ts +1 -0
- package/src/clients/config-export/model-metadata.ts +3 -2
- package/src/clients/config-export/qoder.ts +93 -0
- package/src/clients/config-export.ts +59 -16
- package/src/clients/omo-role-models.ts +6 -3
- package/src/codex/agent-role-models.ts +26 -8
- package/src/codex/auth-api/account-list.ts +17 -2
- package/src/codex/auth-api/account-selection.ts +17 -7
- package/src/codex/auth-api/pool-mode-gate.ts +5 -2
- package/src/codex/auth-api/routes.ts +5 -1
- package/src/codex/auth-context.ts +79 -5
- package/src/codex/autostart-health.ts +7 -1
- package/src/codex/catalog/build-entries.ts +11 -2
- package/src/codex/catalog/bundled.ts +5 -1
- package/src/codex/catalog/configured-tiers.ts +50 -0
- package/src/codex/catalog/effort.ts +6 -3
- package/src/codex/catalog/metadata.ts +4 -2
- package/src/codex/catalog/model-hints.ts +21 -3
- package/src/codex/catalog/native-models.ts +16 -2
- package/src/codex/catalog/native-ultrafast.ts +106 -0
- package/src/codex/catalog/parsing.ts +5 -0
- package/src/codex/catalog/provider-models.ts +4 -0
- package/src/codex/catalog/retained-sync.ts +2 -0
- package/src/codex/catalog/routed-gather.ts +22 -4
- package/src/codex/catalog/vendor-context.ts +82 -0
- package/src/codex/config-write-lock.ts +40 -2
- package/src/codex/convergence.ts +2 -0
- package/src/codex/desktop-app/types.ts +2 -0
- package/src/codex/desktop-app/windows.ts +29 -16
- package/src/codex/desktop-app-restart.ts +4 -2
- package/src/codex/desktop-compatibility/certificate-service.ts +99 -0
- package/src/codex/desktop-compatibility/certificate-store.ts +193 -0
- package/src/codex/desktop-compatibility/connection-store.ts +87 -0
- package/src/codex/desktop-compatibility/installed-build.ts +55 -0
- package/src/codex/desktop-compatibility/json-body.ts +29 -0
- package/src/codex/desktop-compatibility/native-identity.ts +62 -0
- package/src/codex/desktop-compatibility/relay-listener.ts +93 -0
- package/src/codex/desktop-compatibility/routing-binding.ts +10 -0
- package/src/codex/desktop-compatibility/routing-preflight.ts +69 -0
- package/src/codex/desktop-compatibility/runtime-ownership.ts +28 -0
- package/src/codex/desktop-compatibility/runtime.ts +173 -0
- package/src/codex/desktop-compatibility/service.ts +30 -0
- package/src/codex/desktop-compatibility/startup-settings.ts +50 -0
- package/src/codex/desktop-compatibility/usage-activation.ts +86 -0
- package/src/codex/desktop-compatibility/usage-controlled-fetch.ts +59 -0
- package/src/codex/desktop-compatibility/usage-controller.ts +107 -0
- package/src/codex/desktop-compatibility/usage-policy.ts +59 -0
- package/src/codex/desktop-compatibility/usage-refresh.ts +33 -0
- package/src/codex/desktop-compatibility/usage-sse-controller.ts +86 -0
- package/src/codex/desktop-compatibility/windows-activation-source.ts +44 -0
- package/src/codex/desktop-compatibility/windows-certificate-trust.ts +81 -0
- package/src/codex/desktop-compatibility/windows-key-protection.ts +59 -0
- package/src/codex/desktop-compatibility/windows-package-command.ts +86 -0
- package/src/codex/desktop-compatibility/windows-package-launch.ts +28 -0
- package/src/codex/history-provider.ts +1 -1
- package/src/codex/inject/config-write-section.ts +4 -1
- package/src/codex/inject/remove.ts +18 -6
- package/src/codex/journal.ts +16 -1
- package/src/codex/main-account.ts +99 -15
- package/src/codex/native-main-refresh-mode.ts +217 -0
- package/src/codex/native-profile-startup.ts +4 -1
- package/src/codex/prompt-journal.ts +20 -2
- package/src/codex/prompt-layers/encoding.ts +49 -0
- package/src/codex/prompt-layers/import-source.ts +30 -0
- package/src/codex/prompt-layers/toml-edit.ts +269 -37
- package/src/codex/prompt-layers/toml-read.ts +52 -4
- package/src/codex/prompt-layers.ts +383 -20
- package/src/codex/prompt-lock-claim.ts +13 -3
- package/src/codex/prompt-lock-evidence.ts +3 -3
- package/src/codex/prompt-lock-owner.ts +14 -6
- package/src/codex/prompt-text-probe.ts +34 -5
- package/src/codex/quota.ts +13 -6
- package/src/codex/role-auto-assign.ts +2 -5
- package/src/codex/routing/active-account.ts +21 -0
- package/src/codex/routing/health-store.ts +1 -1
- package/src/codex/routing/pool-recovery.ts +79 -0
- package/src/codex/routing.ts +1 -1
- package/src/codex/runtime.ts +196 -8
- package/src/codex/shim-diagnostics.ts +6 -0
- package/src/codex/shim-overlay.ts +15 -6
- package/src/codex/shim.ts +1 -1
- package/src/combos/failover.ts +3 -0
- package/src/config/api-key-reconcile.ts +34 -0
- package/src/config/diagnostics.ts +18 -1
- package/src/config/feature-flags.ts +5 -0
- package/src/config/live-reconcile.ts +56 -29
- package/src/config/live-topology.ts +29 -0
- package/src/config/load-degrade.ts +8 -2
- package/src/config/paths.ts +13 -3
- package/src/config/salvage.ts +3 -1
- package/src/config/schema/config-schema.ts +19 -0
- package/src/config/schema/desktop-compatibility.ts +9 -0
- package/src/config/schema/leaf-validators.ts +1 -0
- package/src/generated/compatibility-version.json +713 -285
- package/src/generated/model-metadata.ts +1 -1
- package/src/grok/grpc-web.ts +23 -1
- package/src/grok/reset-coupon-ledger.ts +75 -5
- package/src/grok/reset-coupons.ts +4 -2
- package/src/integrations/catalog-refresh.ts +1 -1
- package/src/integrations/config-io.ts +20 -2
- package/src/integrations/journal.ts +15 -1
- package/src/integrations/mutation-plan.ts +14 -7
- package/src/integrations/registry.ts +52 -11
- package/src/integrations/state.ts +19 -7
- package/src/integrations/store.ts +3 -0
- package/src/integrations/target.ts +42 -5
- package/src/integrations/writer.ts +24 -7
- package/src/lib/advisor-activation.ts +16 -0
- package/src/lib/app-owned-memory-stores.ts +4 -0
- package/src/lib/app-owned-memory.ts +11 -0
- package/src/lib/background-work.ts +65 -0
- package/src/lib/bounded-file-read.ts +58 -0
- package/src/lib/bun-path-runtime.d.mts +10 -1
- package/src/lib/bun-path-runtime.mjs +62 -3
- package/src/lib/desktop-proxy-route.ts +30 -0
- package/src/lib/desktop-upstream-tunnel.ts +107 -0
- package/src/lib/errors.ts +7 -0
- package/src/lib/json-byte-size.ts +31 -0
- package/src/lib/local-internal-call-capability.ts +55 -0
- package/src/lib/optional-shutdown-hooks.ts +35 -0
- package/src/lib/outbound-credential-registry.ts +210 -0
- package/src/lib/package-tree-integrity.ts +2 -2
- package/src/lib/passive-read.ts +35 -0
- package/src/lib/shadow-call.ts +44 -5
- package/src/lib/socks5-fetch.ts +48 -71
- package/src/lib/socks5-handshake.ts +112 -0
- package/src/lib/translator-budget.ts +7 -1
- package/src/link/codex-settings.ts +155 -0
- package/src/link/management-routes.ts +89 -0
- package/src/link/remote-probe.ts +38 -0
- package/src/link/ssh-argv.ts +26 -5
- package/src/link/ssh-runner.ts +58 -27
- package/src/link/status-projection.ts +22 -4
- package/src/link/supervisor.ts +144 -49
- package/src/link/tunnel-state.ts +11 -4
- package/src/oauth/anthropic-continuity.ts +4 -3
- package/src/oauth/anthropic-identity.ts +13 -2
- package/src/oauth/anthropic-model-quota.ts +13 -1
- package/src/oauth/anthropic-routing.ts +230 -23
- package/src/oauth/anthropic.ts +18 -4
- package/src/oauth/generic-account-failover.ts +29 -5
- package/src/oauth/google-antigravity.ts +24 -7
- package/src/oauth/index.ts +28 -17
- package/src/oauth/kiro-account-identity.ts +106 -0
- package/src/oauth/kiro-device-login.ts +2 -1
- package/src/oauth/kiro.ts +55 -6
- package/src/oauth/plan.ts +29 -0
- package/src/oauth/store.ts +40 -3
- package/src/oauth/types.ts +2 -0
- package/src/plugins/loader.ts +11 -0
- package/src/protocols/codecs/chat-ir.ts +467 -0
- package/src/protocols/codecs/chat.ts +10 -1
- package/src/protocols/codecs/messages-ir.ts +500 -0
- package/src/protocols/features.ts +10 -2
- package/src/protocols/path.ts +11 -1
- package/src/protocols/plan-snapshot.ts +39 -16
- package/src/protocols/plan.ts +9 -1
- package/src/protocols/settings.ts +8 -0
- package/src/providers/anthropic-billing-ownership.ts +74 -0
- package/src/providers/anthropic-billing-recovery.ts +31 -0
- package/src/providers/anthropic-billing-refusal.ts +55 -0
- package/src/providers/anthropic-reset-admission.ts +62 -0
- package/src/providers/anthropic-reset-grant-ledger.ts +28 -6
- package/src/providers/antigravity-account-roster.ts +102 -0
- package/src/providers/antigravity-models.ts +85 -7
- package/src/providers/api-key-resolve.ts +17 -2
- package/src/providers/key-failover.ts +52 -5
- package/src/providers/model-rename-fields.ts +2 -0
- package/src/providers/model-rename-migration.ts +5 -3
- package/src/providers/model-rename-startup.ts +5 -3
- package/src/providers/quota/account-cache.ts +11 -0
- package/src/providers/quota/anthropic-account-quota.ts +4 -2
- package/src/providers/quota/report-cache.ts +14 -0
- package/src/providers/quota/vendor-probes-oauth.ts +3 -3
- package/src/providers/quota.ts +4 -1
- package/src/providers/registry/entries-core.ts +21 -20
- package/src/providers/registry/entries-extended.ts +19 -1
- package/src/providers/registry/model-seeds.ts +17 -0
- package/src/providers/request-pacing.ts +9 -0
- package/src/providers/stale-no-vision-seed-migration.ts +72 -0
- package/src/responses/compaction.ts +14 -0
- package/src/responses/parser.ts +37 -20
- package/src/responses/state.ts +32 -29
- package/src/routing/history/build-file.ts +92 -0
- package/src/routing/history/indexer.ts +248 -216
- package/src/routing/history/ingest.ts +238 -0
- package/src/routing/history/rebuild-job.ts +111 -0
- package/src/routing/history/rebuild-protocol.ts +15 -0
- package/src/routing/history/rebuild-worker.ts +34 -0
- package/src/server/admission-model-scope.ts +4 -1
- package/src/server/antigravity-direct-eligibility.ts +208 -0
- package/src/server/auth-cors.ts +46 -0
- package/src/server/chat-completions.ts +75 -9
- package/src/server/claude-messages.ts +110 -20
- package/src/server/configured-credentials.ts +194 -0
- package/src/server/index/desktop-compatibility-startup.ts +56 -0
- package/src/server/index/link-management.ts +58 -0
- package/src/server/index/optional-listeners.ts +5 -1
- package/src/server/index/serve-options.ts +15 -2
- package/src/server/index/startup-warnings.ts +9 -0
- package/src/server/index/websocket-handler.ts +9 -0
- package/src/server/index.ts +13 -10
- package/src/server/inference/client-encoder-delivery.ts +6 -5
- package/src/server/lifecycle.ts +2 -1
- package/src/server/login-shell-path.ts +146 -0
- package/src/server/management/advisor-routes.ts +191 -0
- package/src/server/management/agent-settings-routes.ts +50 -14
- package/src/server/management/anthropic-reset-grant-routes.ts +17 -1
- package/src/server/management/codex-agent-role-routes.ts +19 -6
- package/src/server/management/codex-prompt-routes.ts +136 -5
- package/src/server/management/codex-role-auto-assign.ts +1 -1
- package/src/server/management/companion-routes.ts +4 -0
- package/src/server/management/config-routes.ts +2 -2
- package/src/server/management/context.ts +4 -0
- package/src/server/management/desktop-compatibility-routes.ts +46 -0
- package/src/server/management/desktop-compatibility-runtime-routes.ts +46 -0
- package/src/server/management/desktop-compatibility-settings-routes.ts +27 -0
- package/src/server/management/grok-coupon-routes.ts +78 -27
- package/src/server/management/link-enrollment.ts +192 -0
- package/src/server/management/link-route-state.ts +185 -0
- package/src/server/management/link-routes.ts +82 -402
- package/src/server/management/model-routes.ts +2 -2
- package/src/server/management/model-rows.ts +3 -1
- package/src/server/management/protocol-settings-patch.ts +1 -0
- package/src/server/management/provider-overwrite-carry.ts +10 -0
- package/src/server/management/provider-routes.ts +1 -0
- package/src/server/management/route-registry.ts +16 -3
- package/src/server/management/shared.ts +3 -0
- package/src/server/management/sibling-guard.ts +1 -0
- package/src/server/management-api.ts +9 -1
- package/src/server/messages-antigravity-direct.ts +195 -0
- package/src/server/messages-native.ts +73 -43
- package/src/server/relay-eager.ts +2 -0
- package/src/server/request-log-filter.ts +6 -1
- package/src/server/request-log-terminal-status.ts +63 -6
- package/src/server/request-log.ts +7 -0
- package/src/server/responses/adapter-continuation.ts +35 -18
- package/src/server/responses/adapter-delivery.ts +24 -2
- package/src/server/responses/adapter-dispatch.ts +261 -81
- package/src/server/responses/advisor-plan-slot.ts +27 -0
- package/src/server/responses/advisor-slot.ts +336 -0
- package/src/server/responses/code-mode-collab-surface.ts +313 -0
- package/src/server/responses/codex-ws-exchange.ts +147 -6
- package/src/server/responses/codex-ws-wire.ts +203 -0
- package/src/server/responses/collaboration.ts +36 -7
- package/src/server/responses/compact.ts +126 -48
- package/src/server/responses/context-overflow.ts +13 -1
- package/src/server/responses/core-codex-account.ts +105 -1
- package/src/server/responses/core-combo-failure.ts +24 -1
- package/src/server/responses/core-combo.ts +28 -2
- package/src/server/responses/core-errors.ts +29 -1
- package/src/server/responses/core-lifetime.ts +2 -0
- package/src/server/responses/core-normalize.ts +11 -0
- package/src/server/responses/core-options.ts +48 -0
- package/src/server/responses/core-replay.ts +7 -4
- package/src/server/responses/core.ts +1 -1
- package/src/server/responses/deferred-collab-surface.ts +158 -0
- package/src/server/responses/deferred-send-reporter.ts +25 -0
- package/src/server/responses/fetch-helpers.ts +12 -1
- package/src/server/responses/passthrough-delivery.ts +20 -11
- package/src/server/responses/passthrough-dispatch.ts +29 -7
- package/src/server/responses/request-prepare.ts +74 -9
- package/src/server/responses/request-transport.ts +22 -8
- package/src/server/responses/run-turn-execution.ts +70 -8
- package/src/server/responses/sidecar-execution.ts +89 -5
- package/src/server/responses/terminal-guard.ts +2 -1
- package/src/server/responses/ws-upstream.ts +9 -1
- package/src/server/responses-undeclared-tool-guard.ts +30 -9
- package/src/server/startup-action-control.ts +38 -4
- package/src/server/startup-health-cache.ts +5 -0
- package/src/server/system-env-shell.ts +7 -2
- package/src/server/system-env.ts +11 -1
- package/src/service/cli.ts +5 -1
- package/src/service/desktop-startup.ts +161 -34
- package/src/service/desktop-supervision.d.mts +27 -1
- package/src/service/desktop-supervision.mjs +111 -5
- package/src/service/health-sentinel-launch.ts +176 -0
- package/src/service/health-sentinel-main.ts +466 -0
- package/src/service/health-sentinel-policy.ts +241 -0
- package/src/service/health-sentinel-probe.ts +71 -0
- package/src/service/health-sentinel-windows.ts +87 -0
- package/src/service/linux-linger.ts +20 -0
- package/src/service/logging.ts +72 -0
- package/src/tray/windows-tray.ps1 +43 -24
- package/src/types/config.ts +68 -6
- package/src/types/provider.ts +7 -0
- package/src/types/request.ts +15 -0
- package/src/types/tools.ts +2 -0
- package/src/update/async-check.ts +1 -1
- package/src/update/badge.ts +2 -2
- package/src/update/index.ts +88 -15
- package/src/update/job-supervised-restart.ts +107 -0
- package/src/update/job.ts +32 -32
- package/src/update/notify.ts +1 -1
- package/src/update/refresh-scheduler.ts +2 -2
- package/src/update/supervised-recovery.d.mts +27 -0
- package/src/update/supervised-recovery.mjs +157 -0
- package/src/usage/cache-diagnostic.ts +2 -0
- package/src/usage/expected-prices.ts +16 -0
- package/src/usage/log.ts +19 -1
- package/src/web-search/gemini-executor.ts +2 -2
- package/assets/sponsors/packycode.png +0 -0
- package/gui/dist/assets/App-Ba8uG696.js +0 -54
- package/gui/dist/assets/Tray-IImbNPRy.js +0 -1
- package/gui/dist/assets/index-BHRZdJuv.js +0 -94
- package/gui/dist/assets/quota-summary-DiJO6sYY.js +0 -1
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { COMBO_NAMESPACE } from "../../combos";
|
|
2
|
+
import type { ResolvedFastPolicy } from "../../providers/fastwire";
|
|
3
|
+
import { catalogModelSlug, type CatalogModel, type RawEntry } from "./parsing";
|
|
4
|
+
import { preserveOperatorUltraFastTiers } from "./operator-tiers";
|
|
5
|
+
|
|
6
|
+
const MANAGED_ULTRAFAST = "opencodex_managed_ultrafast";
|
|
7
|
+
|
|
8
|
+
/** Advertise Ultra Fast only when the eligible final wire explicitly maps that exact tier. */
|
|
9
|
+
export function supportsConfiguredUltraFast(policy: ResolvedFastPolicy | undefined): boolean {
|
|
10
|
+
return policy?.eligibility === "eligible"
|
|
11
|
+
&& policy.fastWire?.kind === "service-tier"
|
|
12
|
+
&& policy.fastWire.canonicalToWire.ultrafast === "ultrafast";
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/** Carry captured capability to the pure merge without treating persisted metadata as authority. */
|
|
16
|
+
export function configuredUltraFastSlugs(models: readonly CatalogModel[]): ReadonlySet<string> {
|
|
17
|
+
const declarations = new Map<string, boolean>();
|
|
18
|
+
for (const model of models) {
|
|
19
|
+
const slug = catalogModelSlug(model);
|
|
20
|
+
const supported = model.provider !== COMBO_NAMESPACE && model.nativeAlias !== true
|
|
21
|
+
&& model.supportsServiceTier === true && model.supportsUltraFastTier === true;
|
|
22
|
+
// A conflicting duplicate cannot lend its capability to the surviving row.
|
|
23
|
+
declarations.set(slug, supported && declarations.get(slug) !== false);
|
|
24
|
+
}
|
|
25
|
+
return new Set([...declarations].filter(([, supported]) => supported).map(([slug]) => slug));
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/** Apply current configuration, or retain an independently supplied exact-row operator tier. */
|
|
29
|
+
export function applyConfiguredUltraFast(
|
|
30
|
+
entry: RawEntry,
|
|
31
|
+
previous: RawEntry | undefined,
|
|
32
|
+
configured: boolean,
|
|
33
|
+
retainOperatorTier: boolean,
|
|
34
|
+
): void {
|
|
35
|
+
// This marker only rejects stale generated metadata; it never authorizes a new tier.
|
|
36
|
+
const wasManaged = previous?.[MANAGED_ULTRAFAST] === entry.slug;
|
|
37
|
+
preserveOperatorUltraFastTiers(entry, wasManaged || configured ? undefined : previous, retainOperatorTier);
|
|
38
|
+
delete entry[MANAGED_ULTRAFAST];
|
|
39
|
+
if (!configured) return;
|
|
40
|
+
entry.service_tiers = [...(Array.isArray(entry.service_tiers) ? entry.service_tiers : []), {
|
|
41
|
+
id: "ultrafast",
|
|
42
|
+
name: "Ultra Fast",
|
|
43
|
+
description: "Higher speed and usage; provider access required",
|
|
44
|
+
}];
|
|
45
|
+
entry.additional_speed_tiers = [
|
|
46
|
+
...(Array.isArray(entry.additional_speed_tiers) ? entry.additional_speed_tiers : []), "ultrafast",
|
|
47
|
+
];
|
|
48
|
+
// Advertising a selectable capability does not opt the user into its increased usage.
|
|
49
|
+
entry[MANAGED_ULTRAFAST] = entry.slug;
|
|
50
|
+
}
|
|
@@ -204,6 +204,8 @@ export function applyCatalogModelMetadata(entry: RawEntry, model?: CatalogModel)
|
|
|
204
204
|
* Two real sources exist and both are consulted here, in the same precedence the
|
|
205
205
|
* writers use (`applyCatalogMetadata` runs first, the model's own fields
|
|
206
206
|
* overwrite it): the `CatalogModel` and the generated jawcode metadata table.
|
|
207
|
+
* Vendor-ID fallback windows are estimates for client budgets, recorded separately rather
|
|
208
|
+
* than promoted to serving-provider assertions.
|
|
207
209
|
* Reading only the model would silently drop every provider whose capabilities
|
|
208
210
|
* live in that table.
|
|
209
211
|
*/
|
|
@@ -230,7 +232,8 @@ function stampCapabilityProvenance(entry: RawEntry, model: CatalogModel): void {
|
|
|
230
232
|
entry.opencodex_capability_provenance = {
|
|
231
233
|
provider: model.provider,
|
|
232
234
|
model_id: model.id,
|
|
233
|
-
...(contextWindow !== undefined ? { context_window: contextWindow } : {}),
|
|
235
|
+
...(contextWindow !== undefined && !model.contextWindowInference ? { context_window: contextWindow } : {}),
|
|
236
|
+
...(model.contextWindowInference ? { inferred_context_window: contextWindow, context_window_inference: { ...model.contextWindowInference } } : {}),
|
|
234
237
|
...(inputModalities !== undefined ? { input_modalities: [...inputModalities] } : {}),
|
|
235
238
|
...(Array.isArray(model.capabilities) && model.capabilities.length > 0
|
|
236
239
|
? { capabilities: [...model.capabilities] }
|
|
@@ -620,8 +623,8 @@ export function clampCatalogModelsToCodexSupport(models: RawEntry[], deps: Bundl
|
|
|
620
623
|
removedEfforts: [...clamp.removedEfforts],
|
|
621
624
|
affectedModels: [...clamp.affectedModels],
|
|
622
625
|
};
|
|
623
|
-
|
|
624
|
-
if (
|
|
626
|
+
const changed = deps.commandCandidates ? true : persistEffortClamp(diagnostic, { configDir: deps.configDir });
|
|
627
|
+
if (changed) for (const line of formatClampLogLines(diagnostic)) console.warn(line);
|
|
625
628
|
deps.onEffortClamp?.(diagnostic);
|
|
626
629
|
} else if (!deps.commandCandidates) {
|
|
627
630
|
persistEffortClamp(null, { configDir: deps.configDir });
|
|
@@ -42,6 +42,7 @@ import { RESERVE_METADATA_SOURCE_FIELD } from "./reserve";
|
|
|
42
42
|
import {
|
|
43
43
|
ACCOUNT_GATED_NATIVE_OPENAI_MODELS,
|
|
44
44
|
NATIVE_GPT6_CONTEXT,
|
|
45
|
+
NATIVE_GPT61_SOL_CONTEXT,
|
|
45
46
|
NATIVE_DAYBREAK_BLUE_MODEL,
|
|
46
47
|
NATIVE_GPT6_ASTRA_MINOR_MODEL,
|
|
47
48
|
NATIVE_GPT6_ASTRA_MODEL,
|
|
@@ -202,8 +203,9 @@ export const NATIVE_OPENAI_CONTEXT_OVERRIDES: Record<string, { contextWindow?: n
|
|
|
202
203
|
// the row's own ceiling rather than the GPT-5.6 family's measured 922,000.
|
|
203
204
|
[NATIVE_GPT6_SOL_MODEL]: { ...NATIVE_GPT6_CONTEXT },
|
|
204
205
|
[NATIVE_GPT6_LUNA_MODEL]: { ...NATIVE_GPT6_CONTEXT },
|
|
205
|
-
// GPT-6.1 Sol's row (openai/codex models.json after #49318) ships
|
|
206
|
-
|
|
206
|
+
// GPT-6.1 Sol's row (openai/codex models.json after #49318) ships 272,000 / 872,000, but OpenAI
|
|
207
|
+
// raised its Codex & Work default to 500,000 on 2026-10-11; the 872,000 ceiling is unchanged.
|
|
208
|
+
[NATIVE_GPT61_SOL_MODEL]: { ...NATIVE_GPT61_SOL_CONTEXT },
|
|
207
209
|
// Astra Minor borrows Astra's row, so it inherits Astra's numbers. No account we hold can reach
|
|
208
210
|
// it, so this is inheritance, not a measurement.
|
|
209
211
|
[NATIVE_GPT6_ASTRA_MINOR_MODEL]: { ...NATIVE_GPT6_CONTEXT },
|
|
@@ -1,5 +1,7 @@
|
|
|
1
|
+
import { canInferVendorContext, vendorContextInference } from "./vendor-context";
|
|
1
2
|
import { effectiveProviderAlias, effectiveProviderAliasDecision } from "../../providers/default-aliases";
|
|
2
3
|
import { initialModelSelectionPending } from "../../providers/initial-model-selection";
|
|
4
|
+
import { supportsConfiguredUltraFast } from "./configured-tiers";
|
|
3
5
|
import { execFileSync } from "node:child_process";
|
|
4
6
|
import { createHash, createHmac, randomBytes } from "node:crypto";
|
|
5
7
|
import { copyFileSync, existsSync, mkdirSync, readFileSync, realpathSync } from "node:fs";
|
|
@@ -250,6 +252,7 @@ export function configuredReasoningSummarySupport(prov: OcxProviderConfig | unde
|
|
|
250
252
|
return modelRecordValue(prov.modelReasoningSummaryDelivery, id) !== undefined ? true : undefined;
|
|
251
253
|
}
|
|
252
254
|
|
|
255
|
+
/** Reapply configured limits and captured wire capabilities without trusting stale discovery hints. */
|
|
253
256
|
export function applyProviderConfigHints(
|
|
254
257
|
name: string,
|
|
255
258
|
prov: OcxProviderConfig,
|
|
@@ -309,7 +312,12 @@ export function applyProviderConfigHints(
|
|
|
309
312
|
// owns catalog publication, including an explicit provider-level false.
|
|
310
313
|
const supportsServiceTier = serviceTierSupportFromPolicy(fastPolicy);
|
|
311
314
|
const {
|
|
315
|
+
contextWindowInference: _staleContextInference,
|
|
316
|
+
contextWindow: _previousContextWindow,
|
|
317
|
+
contextCap: previousContextCap,
|
|
318
|
+
contextCapped: previousContextCapped,
|
|
312
319
|
supportsServiceTier: _staleServiceTier,
|
|
320
|
+
supportsUltraFastTier: _staleUltraFastTier,
|
|
313
321
|
fastTierDescription: _staleFastTierDescription,
|
|
314
322
|
providerAlias: _staleProviderAlias,
|
|
315
323
|
suppressSyntheticMax: _staleSuppressSyntheticMax,
|
|
@@ -317,16 +325,23 @@ export function applyProviderConfigHints(
|
|
|
317
325
|
} = model;
|
|
318
326
|
// 已发现窗口只允许被配置值压低;缺窗口时,已开的 Context cap 就是实际窗口。
|
|
319
327
|
const discoveredWindow = githubCopilotCatalogContextWindow(name, prov, model.id,
|
|
320
|
-
typeof model.contextWindow === "number" && model.contextWindow > 0 ? model.contextWindow : undefined);
|
|
328
|
+
!model.contextWindowInference && typeof model.contextWindow === "number" && model.contextWindow > 0 ? model.contextWindow : undefined);
|
|
321
329
|
const projectedLimits = clampObservedModelLimits(staticPolicy.model, {
|
|
322
330
|
...(discoveredWindow !== undefined ? { contextWindow: discoveredWindow } : {}),
|
|
323
331
|
...(typeof model.maxInputTokens === "number" && model.maxInputTokens > 0 ? { maxInputTokens: model.maxInputTokens } : {}),
|
|
324
332
|
});
|
|
333
|
+
const azureWindow = positiveSafeInteger(azureMetadata?.contextWindow);
|
|
334
|
+
const inferredWindow = projectedLimits.contextWindow === undefined && azureWindow === undefined && canInferVendorContext(name, prov)
|
|
335
|
+
? vendorContextInference(model.id) : undefined;
|
|
325
336
|
const hintedWindow = projectedLimits.contextWindow
|
|
326
|
-
??
|
|
337
|
+
?? azureWindow
|
|
338
|
+
?? inferredWindow?.contextWindow
|
|
327
339
|
?? (providerCap !== undefined ? resolveUnknownRoutedContextWindow(providerCap) : undefined);
|
|
328
340
|
const hinted = {
|
|
329
341
|
...modelWithoutServiceTier,
|
|
342
|
+
...(!model.contextWindowInference && previousContextCap !== undefined
|
|
343
|
+
? { contextCap: previousContextCap, contextCapped: previousContextCapped } : {}),
|
|
344
|
+
...(inferredWindow ? { contextWindowInference: inferredWindow } : {}),
|
|
330
345
|
...(displayName !== undefined ? { displayName } : {}),
|
|
331
346
|
...(providerAlias !== undefined ? { providerAlias } : {}),
|
|
332
347
|
...(hintedWindow !== undefined ? { contextWindow: hintedWindow } : {}),
|
|
@@ -343,6 +358,7 @@ export function applyProviderConfigHints(
|
|
|
343
358
|
...(typeof supportsReasoningSummaries === "boolean" ? { supportsReasoningSummaries } : {}),
|
|
344
359
|
...(typeof supportsVerbosity === "boolean" ? { supportsVerbosity } : {}),
|
|
345
360
|
...(typeof supportsServiceTier === "boolean" ? { supportsServiceTier } : {}),
|
|
361
|
+
supportsUltraFastTier: supportsConfiguredUltraFast(fastPolicy),
|
|
346
362
|
...(supportsServiceTier === true && fastPolicy.fastTierDescription !== undefined
|
|
347
363
|
? { fastTierDescription: fastPolicy.fastTierDescription }
|
|
348
364
|
: {}),
|
|
@@ -431,7 +447,9 @@ export function suppressedSyntheticMaxCatalogSlugs(
|
|
|
431
447
|
}
|
|
432
448
|
return slugs;
|
|
433
449
|
}
|
|
434
|
-
|
|
450
|
+
// google-antigravity: the static lineup is an entitlement superset (Claude 5.5 and Gemini 4 Argon
|
|
451
|
+
// are per-account), so a live roster that omits some of it is the expected case, not drift.
|
|
452
|
+
export const QUIET_AUTHORITATIVE_CATALOG_PROVIDERS = new Set(["kimi", "xai", "google-antigravity"]);
|
|
435
453
|
|
|
436
454
|
export const CALLABLE_CONFIGURED_COMPATIBILITY_MODELS: Readonly<Record<string, ReadonlySet<string>>> = {
|
|
437
455
|
// CodeBuddy's vendor defaults are real callable selectors — both the bundled manifests
|
|
@@ -44,7 +44,8 @@ export const NATIVE_GPT6_LUNA_MODEL = "gpt-6-luna";
|
|
|
44
44
|
* SELF-DESCRIBED: its row is pinned verbatim in `src/codex/data/roster-pinned-models.json` from
|
|
45
45
|
* openai/codex `codex-rs/models-manager/models.json` after #49318, which also made it the Codex
|
|
46
46
|
* catalog default (priority 1). Ladder low..ultra with default effort low, and the GPT-6
|
|
47
|
-
* 272,000 / 872,000 context pair
|
|
47
|
+
* 272,000 / 872,000 context pair in that pinned row; the effective native default is now 500,000
|
|
48
|
+
* (NATIVE_GPT61_SOL_CONTEXT). Ungated for the same owner decision as Sol and Luna.
|
|
48
49
|
*/
|
|
49
50
|
export const NATIVE_GPT61_SOL_MODEL = "gpt-6.1-sol";
|
|
50
51
|
|
|
@@ -62,11 +63,24 @@ export const NATIVE_GPT6_ASTRA_MINOR_MODEL = "gpt-6-astra-minor";
|
|
|
62
63
|
/**
|
|
63
64
|
* Context pair every GPT-6 native ships in its upstream row: a 272,000-token default window
|
|
64
65
|
* against an 872,000-token ceiling (and input limit) reached only through the long-window opt-in.
|
|
65
|
-
* The built-in GPT-6 rows and every configured native (below) inherit this one value
|
|
66
|
+
* The built-in GPT-6 rows and every configured native (below) inherit this one value, except
|
|
67
|
+
* GPT-6.1 Sol, whose default window is NATIVE_GPT61_SOL_CONTEXT.
|
|
66
68
|
*/
|
|
67
69
|
export const NATIVE_GPT6_CONTEXT: Readonly<{ contextWindow: number; maxContextWindow: number; maxInputTokens: number }> =
|
|
68
70
|
Object.freeze({ contextWindow: 272_000, maxContextWindow: 872_000, maxInputTokens: 872_000 });
|
|
69
71
|
|
|
72
|
+
/**
|
|
73
|
+
* GPT-6.1 Sol through Codex & Work: OpenAI raised the default context from 272k to 500k
|
|
74
|
+
* (Tibo Sottiaux, 2026-10-11, https://x.com/thsottiaux/status/2109430343346581527), while
|
|
75
|
+
* overrides stay allowed and the model maximum is described as 1M. The bundled codex-rs row
|
|
76
|
+
* still reads 272,000 / 872,000, and built-in natives never take roster values, so the default
|
|
77
|
+
* lives here. The 872,000 ceiling (and input limit) is kept on purpose: the announcement does
|
|
78
|
+
* not say how "1M" maps onto the native window and input fields, and raising maxInputTokens
|
|
79
|
+
* would assert an input allowance nobody has measured. Overrides therefore clamp to 872,000.
|
|
80
|
+
*/
|
|
81
|
+
export const NATIVE_GPT61_SOL_CONTEXT: Readonly<{ contextWindow: number; maxContextWindow: number; maxInputTokens: number }> =
|
|
82
|
+
Object.freeze({ ...NATIVE_GPT6_CONTEXT, contextWindow: 500_000 });
|
|
83
|
+
|
|
70
84
|
/** Pinned row a configured native borrows its capability metadata from: the current Sol. */
|
|
71
85
|
export const CONFIGURED_NATIVE_OPENAI_TEMPLATE_MODEL = NATIVE_GPT61_SOL_MODEL;
|
|
72
86
|
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import type { RawEntry } from "./parsing";
|
|
2
|
+
import { trustedAccountBoundNativeCatalogSlug } from "./account-models";
|
|
3
|
+
import { NATIVE_GPT6_ASTRA_MODEL, NATIVE_GPT61_SOL_MODEL } from "./native-models";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* The Ultrafast speed choice OpenAI documents for GPT-6 Astra and GPT-6.1 Sol
|
|
7
|
+
* (https://developers.openai.com/api/docs/guides/ultrafast-mode and
|
|
8
|
+
* https://learn.chatgpt.com/docs/agent-configuration/speed, checked 2026-10-13).
|
|
9
|
+
*
|
|
10
|
+
* The upstream bundled catalog lists only `priority` for both models; ChatGPT's live model
|
|
11
|
+
* list adds Ultrafast for eligible plans. Codex stops consulting that live list once
|
|
12
|
+
* `model_catalog_json` points at our generated catalog, so without this row the speed picker
|
|
13
|
+
* never offers Ultrafast. The `ultraFastTier` switch is the operator's statement that their
|
|
14
|
+
* plan is eligible; the description still says the tier requires one.
|
|
15
|
+
*/
|
|
16
|
+
export const NATIVE_ULTRAFAST_SERVICE_TIER: Readonly<{ id: string; name: string; description: string }> = Object.freeze({
|
|
17
|
+
id: "ultrafast",
|
|
18
|
+
name: "Ultrafast",
|
|
19
|
+
description: "Lower latency, increased usage; requires an eligible plan",
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
export const NATIVE_ULTRAFAST_MODELS: ReadonlySet<string> = new Set([NATIVE_GPT6_ASTRA_MODEL, NATIVE_GPT61_SOL_MODEL]);
|
|
23
|
+
|
|
24
|
+
function isUltraFastId(value: unknown): boolean {
|
|
25
|
+
return typeof value === "string" && value.trim().toLowerCase() === "ultrafast";
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function isUltraFastDescriptor(value: unknown): boolean {
|
|
29
|
+
return value !== null && typeof value === "object" && "id" in value && isUltraFastId((value as { id: unknown }).id);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Provenance marker naming the tier fields this module added to a row. Ownership is never
|
|
34
|
+
* inferred from a descriptor's text: an operator may have written the very same entry, and only
|
|
35
|
+
* a row carrying this marker has anything for the switch to withdraw.
|
|
36
|
+
*/
|
|
37
|
+
export const NATIVE_ULTRAFAST_PROVENANCE_FIELD = "opencodex_generated_service_tiers";
|
|
38
|
+
type TierField = "service_tiers" | "additional_speed_tiers";
|
|
39
|
+
|
|
40
|
+
function generatedFields(entry: RawEntry): Set<TierField> {
|
|
41
|
+
const raw = entry[NATIVE_ULTRAFAST_PROVENANCE_FIELD];
|
|
42
|
+
const fields = new Set<TierField>();
|
|
43
|
+
if (Array.isArray(raw)) {
|
|
44
|
+
for (const value of raw) if (value === "service_tiers" || value === "additional_speed_tiers") fields.add(value);
|
|
45
|
+
}
|
|
46
|
+
return fields;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
function isGeneratedDescriptor(value: unknown): boolean {
|
|
50
|
+
if (!isUltraFastDescriptor(value)) return false;
|
|
51
|
+
const tier = value as Record<string, unknown>;
|
|
52
|
+
return Object.keys(tier).length === 3
|
|
53
|
+
&& tier.id === NATIVE_ULTRAFAST_SERVICE_TIER.id
|
|
54
|
+
&& tier.name === NATIVE_ULTRAFAST_SERVICE_TIER.name
|
|
55
|
+
&& tier.description === NATIVE_ULTRAFAST_SERVICE_TIER.description;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/** Bare native rows and trusted account-bound clones of the two Ultrafast models. */
|
|
59
|
+
export function nativeUltraFastSlug(entry: RawEntry): string | undefined {
|
|
60
|
+
const slug = trustedAccountBoundNativeCatalogSlug(entry)
|
|
61
|
+
?? (typeof entry.slug === "string" && !entry.slug.includes("/") ? entry.slug : undefined);
|
|
62
|
+
return slug !== undefined && NATIVE_ULTRAFAST_MODELS.has(slug) ? slug : undefined;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Add (enabled) or withdraw (disabled) the documented Ultrafast choice on an eligible native row.
|
|
67
|
+
*
|
|
68
|
+
* Enabling appends the descriptor to `service_tiers` and "ultrafast" to the deprecated
|
|
69
|
+
* `additional_speed_tiers` mirror, after the existing Fast tier and only when absent, and records
|
|
70
|
+
* each field it filled in the provenance marker. A repeated sync is a no-op and an
|
|
71
|
+
* operator-written Ultrafast entry wins. Disabling removes only what the marker names (and only
|
|
72
|
+
* the unedited generated descriptor), then drops the marker; rows without it are left as they
|
|
73
|
+
* are. The catalog default tier is never set.
|
|
74
|
+
*/
|
|
75
|
+
export function applyNativeUltraFastTier(entry: RawEntry, enabled: boolean): void {
|
|
76
|
+
const owned = generatedFields(entry);
|
|
77
|
+
if (nativeUltraFastSlug(entry) === undefined) {
|
|
78
|
+
delete entry[NATIVE_ULTRAFAST_PROVENANCE_FIELD];
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
const tiers = Array.isArray(entry.service_tiers) ? entry.service_tiers : undefined;
|
|
82
|
+
const speeds = Array.isArray(entry.additional_speed_tiers) ? entry.additional_speed_tiers : undefined;
|
|
83
|
+
if (enabled) {
|
|
84
|
+
if (!tiers?.some(isUltraFastDescriptor)) {
|
|
85
|
+
entry.service_tiers = [...(tiers ?? []), { ...NATIVE_ULTRAFAST_SERVICE_TIER }];
|
|
86
|
+
owned.add("service_tiers");
|
|
87
|
+
}
|
|
88
|
+
if (!speeds?.some(isUltraFastId)) {
|
|
89
|
+
entry.additional_speed_tiers = [...(speeds ?? []), NATIVE_ULTRAFAST_SERVICE_TIER.id];
|
|
90
|
+
owned.add("additional_speed_tiers");
|
|
91
|
+
}
|
|
92
|
+
if (owned.size > 0) entry[NATIVE_ULTRAFAST_PROVENANCE_FIELD] = [...owned].sort();
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
delete entry[NATIVE_ULTRAFAST_PROVENANCE_FIELD];
|
|
96
|
+
if (owned.has("service_tiers") && tiers) {
|
|
97
|
+
const kept = tiers.filter(tier => !isGeneratedDescriptor(tier));
|
|
98
|
+
if (kept.length > 0) entry.service_tiers = kept;
|
|
99
|
+
else delete entry.service_tiers;
|
|
100
|
+
}
|
|
101
|
+
if (owned.has("additional_speed_tiers") && speeds) {
|
|
102
|
+
const kept = speeds.filter(speed => !isUltraFastId(speed));
|
|
103
|
+
if (kept.length > 0) entry.additional_speed_tiers = kept;
|
|
104
|
+
else delete entry.additional_speed_tiers;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { VendorContextInference } from "./vendor-context";
|
|
1
2
|
import { isCodexControlPlaneModel } from "../control-plane-models";
|
|
2
3
|
import { execFileSync } from "node:child_process";
|
|
3
4
|
import { createHash } from "node:crypto";
|
|
@@ -120,6 +121,8 @@ export interface CatalogModel {
|
|
|
120
121
|
suppressSyntheticMax?: boolean;
|
|
121
122
|
defaultReasoningEffort?: string;
|
|
122
123
|
contextWindow?: number;
|
|
124
|
+
/** Bundled fallback only; never a serving-provider capability assertion. */
|
|
125
|
+
contextWindowInference?: VendorContextInference;
|
|
123
126
|
maxInputTokens?: number;
|
|
124
127
|
/** Model-scoped output-token ceiling; omitted when no authoritative value is known. */
|
|
125
128
|
maxOutputTokens?: number;
|
|
@@ -139,6 +142,8 @@ export interface CatalogModel {
|
|
|
139
142
|
supportsVerbosity?: boolean;
|
|
140
143
|
/** Whether this exact routed model has a verified OpenAI-compatible service tier. */
|
|
141
144
|
supportsServiceTier?: boolean;
|
|
145
|
+
/** Captured eligible service-tier wire explicitly maps ultrafast to ultrafast. */
|
|
146
|
+
supportsUltraFastTier?: boolean;
|
|
142
147
|
/** Optional provider-specific copy for the advertised Fast tier. */
|
|
143
148
|
fastTierDescription?: string;
|
|
144
149
|
supportsReasoningSummaries?: boolean;
|
|
@@ -53,6 +53,7 @@ import {
|
|
|
53
53
|
import type { FastPolicyAuthority } from "../../providers/fastwire";
|
|
54
54
|
import { effectiveGoogleMode, getProviderRegistryEntry, providerMatchesRegistryTransport, registryEntryForProviderDestination } from "../../providers/registry";
|
|
55
55
|
import { parseAntigravityAvailableModels, registerAntigravityDiscoveredWireModels } from "../../providers/antigravity-models";
|
|
56
|
+
import { recordAntigravityAccountRoster } from "../../providers/antigravity-account-roster";
|
|
56
57
|
import { applyProviderContextCap, providerContextCap, resolveUnknownRoutedContextWindow } from "../../providers/context-cap";
|
|
57
58
|
import { clampAutoCompactTokenLimit } from "../../providers/auto-compact-budget";
|
|
58
59
|
import { effectiveModelAliases } from "../../providers/default-aliases";
|
|
@@ -807,6 +808,9 @@ export async function fetchProviderModelsWithAuth(
|
|
|
807
808
|
provider: name,
|
|
808
809
|
cacheGeneration,
|
|
809
810
|
});
|
|
811
|
+
// Entitlement is per account (Claude 4.6 vs 5.5, Argon): remember what THIS account
|
|
812
|
+
// lists so account selection can prefer one that serves the requested model.
|
|
813
|
+
if (auth.oauthAccountId) recordAntigravityAccountRoster(name, auth.oauthAccountId, antigravity);
|
|
810
814
|
if (!setCached(name, forCache, Date.now(), cacheGeneration)) {
|
|
811
815
|
return observed(withConfiguredRetention(configured), "degraded");
|
|
812
816
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { projectAntigravitySelectedModels } from "../../providers/antigravity-effort-families";
|
|
2
|
+
import { configuredUltraFastSlugs } from "./configured-tiers";
|
|
2
3
|
import { existsSync, readFileSync } from "node:fs";
|
|
3
4
|
import { join } from "node:path";
|
|
4
5
|
import { initializeConfigOwnership } from "../../lib/config-ownership";
|
|
@@ -509,6 +510,7 @@ function writeRetainedCatalogSync({
|
|
|
509
510
|
: [];
|
|
510
511
|
catalog.models = mergeCatalogEntriesFromObservedState({
|
|
511
512
|
ultraFastTier: ultraFastTierEnabled(config),
|
|
513
|
+
configuredUltraFastSlugs: configuredUltraFastSlugs(orderedGoModels),
|
|
512
514
|
modelPickerOrder,
|
|
513
515
|
accountSelectors,
|
|
514
516
|
catalogModels: catalogModelsForMerge,
|
|
@@ -1,5 +1,7 @@
|
|
|
1
|
+
import { canInferVendorContext } from "./vendor-context";
|
|
1
2
|
import { effectiveProviderAlias, effectiveProviderAliasDecision } from "../../providers/default-aliases";
|
|
2
3
|
import { initialModelSelectionPending } from "../../providers/initial-model-selection";
|
|
4
|
+
import { supportsConfiguredUltraFast } from "./configured-tiers";
|
|
3
5
|
import { execFileSync } from "node:child_process";
|
|
4
6
|
import { createHash, createHmac, randomBytes } from "node:crypto";
|
|
5
7
|
import { copyFileSync, existsSync, mkdirSync, readFileSync, realpathSync } from "node:fs";
|
|
@@ -318,6 +320,7 @@ function boundCustomNativeReasoning(
|
|
|
318
320
|
return bounded;
|
|
319
321
|
}
|
|
320
322
|
|
|
323
|
+
/** Gather discovered and custom rows under one captured provider policy, including speed capabilities. */
|
|
321
324
|
async function gatherRoutedModelsUncached(
|
|
322
325
|
config: OcxConfig,
|
|
323
326
|
capture: GatherFlightCapture,
|
|
@@ -358,6 +361,7 @@ async function gatherRoutedModelsUncached(
|
|
|
358
361
|
const policy = fastPolicyForModel(apiProvider.provider, model.id, apiProvider.name);
|
|
359
362
|
const supported = serviceTierSupportFromPolicy(policy);
|
|
360
363
|
if (supported !== undefined) model.supportsServiceTier = supported;
|
|
364
|
+
model.supportsUltraFastTier = supportsConfiguredUltraFast(policy);
|
|
361
365
|
if (supported === true && policy.fastTierDescription !== undefined) model.fastTierDescription = policy.fastTierDescription;
|
|
362
366
|
}
|
|
363
367
|
}
|
|
@@ -467,7 +471,7 @@ async function gatherRoutedModelsUncached(
|
|
|
467
471
|
...inherited,
|
|
468
472
|
catalogKind: CODEX_CUSTOM_MODEL_CATALOG_KIND,
|
|
469
473
|
...(typeof custom.contextWindow === "number" && custom.contextWindow > 0
|
|
470
|
-
? { contextWindow: custom.contextWindow }
|
|
474
|
+
? { contextWindow: custom.contextWindow, contextWindowInference: undefined }
|
|
471
475
|
: {}),
|
|
472
476
|
...(Array.isArray(custom.inputModalities)
|
|
473
477
|
? { inputModalities: [...custom.inputModalities] }
|
|
@@ -654,6 +658,7 @@ async function gatherRoutedModelsUncached(
|
|
|
654
658
|
...(Array.isArray(cm.reasoningEfforts) ? { reasoningEfforts: [...cm.reasoningEfforts] } : {}),
|
|
655
659
|
...(cm.defaultReasoningEffort ? { defaultReasoningEffort: cm.defaultReasoningEffort } : {}),
|
|
656
660
|
...(typeof supportsServiceTier === "boolean" ? { supportsServiceTier } : {}),
|
|
661
|
+
supportsUltraFastTier: supportsConfiguredUltraFast(fastPolicy),
|
|
657
662
|
...(supportsServiceTier === true && fastPolicy?.fastTierDescription !== undefined
|
|
658
663
|
? { fastTierDescription: fastPolicy.fastTierDescription }
|
|
659
664
|
: {}),
|
|
@@ -686,7 +691,8 @@ async function gatherRoutedModelsUncached(
|
|
|
686
691
|
: undefined;
|
|
687
692
|
const merged: CatalogModel = replaced ? {
|
|
688
693
|
...base,
|
|
689
|
-
...(base.contextWindow === undefined && replaced.contextWindow !== undefined
|
|
694
|
+
...(base.contextWindow === undefined && replaced.contextWindow !== undefined
|
|
695
|
+
? { contextWindow: replaced.contextWindow, ...(replaced.contextWindowInference ? { contextWindowInference: replaced.contextWindowInference, contextCap: replaced.contextCap, contextCapped: replaced.contextCapped } : {}) } : {}),
|
|
690
696
|
...(mergedMaxInput !== undefined ? { maxInputTokens: mergedMaxInput } : {}),
|
|
691
697
|
...(mergedMaxOutput !== undefined ? { maxOutputTokens: mergedMaxOutput } : {}),
|
|
692
698
|
...(base.autoCompactTokenLimit === undefined && replaced.autoCompactTokenLimit !== undefined
|
|
@@ -703,17 +709,29 @@ async function gatherRoutedModelsUncached(
|
|
|
703
709
|
...(base.codexToolMode === undefined && replaced.codexToolMode !== undefined ? { codexToolMode: replaced.codexToolMode } : {}),
|
|
704
710
|
...(base.capabilities === undefined && replaced.capabilities !== undefined ? { capabilities: replaced.capabilities } : {}),
|
|
705
711
|
} : base;
|
|
712
|
+
// A custom-only model may never appear in /models or the provider's configured roster.
|
|
713
|
+
// Fill only its absent context; a full hint overlay would overwrite custom capabilities.
|
|
714
|
+
const customContextHints = merged.contextWindow === undefined && effectiveProvider && canInferVendorContext(cm.provider, effectiveProvider)
|
|
715
|
+
? applyProviderConfigHints(cm.provider, effectiveProvider, { provider: cm.provider, id: cm.modelId },
|
|
716
|
+
providerContextCap(config, cm.provider), metadataModelIdCaseFoldByProvider.get(cm.provider),
|
|
717
|
+
undefined, metadataConfigDirByProvider.get(cm.provider))
|
|
718
|
+
: undefined;
|
|
719
|
+
const contextResolved: CatalogModel = customContextHints?.contextWindow !== undefined
|
|
720
|
+
? { ...merged, contextWindow: customContextHints.contextWindow,
|
|
721
|
+
...(customContextHints.contextWindowInference ? { contextWindowInference: customContextHints.contextWindowInference } : {}),
|
|
722
|
+
...(customContextHints.contextCap !== undefined ? { contextCap: customContextHints.contextCap, contextCapped: customContextHints.contextCapped } : {}) }
|
|
723
|
+
: merged;
|
|
706
724
|
// Catalog-advertised efforts are bounded whenever the model id is a pinned native
|
|
707
725
|
// slug. Desktop validates that id, so a gateway such as YYLJ/gpt-6-astra still cannot
|
|
708
726
|
// advertise none/minimal. Full native identity stays behind the alias predicate.
|
|
709
727
|
const nativeEffortSource = hasNativeOpenAiCapabilityMetadata(cm.modelId);
|
|
710
728
|
const reasoningBounded = nativeEffortSource
|
|
711
729
|
? boundCustomNativeReasoning(
|
|
712
|
-
|
|
730
|
+
contextResolved,
|
|
713
731
|
nativeReasoningEfforts(cm.modelId),
|
|
714
732
|
nativeAliasDefaultEffort ?? nativeDefaultReasoningEffort(cm.modelId),
|
|
715
733
|
)
|
|
716
|
-
:
|
|
734
|
+
: contextResolved;
|
|
717
735
|
// Vision-sidecar coverage only: when the enriched provider's shared predicate matches
|
|
718
736
|
// noVisionModels or text-without-image modelInputModalities, advertise image input so the
|
|
719
737
|
// Codex app lets images reach the sidecar (#349/#344). Deliberately NOT the full
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { listModelMetadata, resolveMetadataProvider, type ModelMetadata } from "../../generated/model-metadata";
|
|
2
|
+
import { PROVIDER_REGISTRY } from "../../providers/registry";
|
|
3
|
+
import type { OcxProviderConfig } from "../../types";
|
|
4
|
+
|
|
5
|
+
/** A bundled model-window estimate, not evidence of the serving gateway's capacity. */
|
|
6
|
+
export interface VendorContextInference {
|
|
7
|
+
source: "vendor" | "aggregator";
|
|
8
|
+
provider: string;
|
|
9
|
+
modelId: string;
|
|
10
|
+
contextWindow: number;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
// Capacity and price have different authorities: hosting vendors (Cerebras/Bedrock), Azure
|
|
14
|
+
// and the Codex subscription table must not replace the original vendor's API window.
|
|
15
|
+
const VENDORS = ["anthropic", "openai", "google", "moonshot", "minimax", "deepseek", "xai", "zai", "mistral", "xiaomi"];
|
|
16
|
+
const AGGREGATORS = ["openrouter", "opencode-go"];
|
|
17
|
+
// Snapshot names once, never consult the mutable registry after gather flight admission.
|
|
18
|
+
const BUILTIN_NAMES = new Set(PROVIDER_REGISTRY.map(entry => entry.id.toLowerCase()));
|
|
19
|
+
/**
|
|
20
|
+
* Opt-in only (#1073): an id-only custom row keeps the conservative fallback unless the
|
|
21
|
+
* operator sets `inferContextWindow: true`. Built-in names stay excluded even when set.
|
|
22
|
+
*/
|
|
23
|
+
export function canInferVendorContext(provider: string, config: Pick<OcxProviderConfig, "inferContextWindow"> | undefined): boolean {
|
|
24
|
+
return config?.inferContextWindow === true
|
|
25
|
+
&& !BUILTIN_NAMES.has(provider.toLowerCase()) && !resolveMetadataProvider(provider);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const normalize = (id: string): string => id.toLowerCase().replaceAll(".", "-");
|
|
29
|
+
type Candidate = VendorContextInference | null;
|
|
30
|
+
|
|
31
|
+
/** Build a pure lookup; conflicting windows within one authority tier fail closed. */
|
|
32
|
+
export function createVendorContextLookup(
|
|
33
|
+
vendors: readonly ModelMetadata[],
|
|
34
|
+
aggregators: readonly ModelMetadata[],
|
|
35
|
+
): (id: string) => VendorContextInference | undefined {
|
|
36
|
+
const build = (rows: readonly ModelMetadata[], source: VendorContextInference["source"]) => {
|
|
37
|
+
const exact = new Map<string, Candidate>();
|
|
38
|
+
const normalized = new Map<string, Candidate>();
|
|
39
|
+
const add = (map: Map<string, Candidate>, id: string, value: VendorContextInference) => {
|
|
40
|
+
if (!map.has(id)) map.set(id, value);
|
|
41
|
+
else if (map.get(id)?.contextWindow !== value.contextWindow) map.set(id, null);
|
|
42
|
+
};
|
|
43
|
+
for (const row of rows) {
|
|
44
|
+
const window = row.contextWindow;
|
|
45
|
+
if (!Number.isSafeInteger(window) || window! <= 0 || row.id.startsWith("~")) continue;
|
|
46
|
+
const value: VendorContextInference = { source, provider: row.provider, modelId: row.id, contextWindow: window! };
|
|
47
|
+
const ids = source === "aggregator" ? [row.id, row.id.slice(row.id.lastIndexOf("/") + 1)] : [row.id];
|
|
48
|
+
for (const id of ids) {
|
|
49
|
+
if (!id) continue;
|
|
50
|
+
add(exact, id, value);
|
|
51
|
+
add(normalized, normalize(id), value);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
return { exact, normalized };
|
|
55
|
+
};
|
|
56
|
+
const tiers = [build(vendors, "vendor"), build(aggregators, "aggregator")];
|
|
57
|
+
return rawId => {
|
|
58
|
+
const id = rawId.trim();
|
|
59
|
+
if (!id || id.startsWith("~")) return undefined;
|
|
60
|
+
for (const tier of tiers) {
|
|
61
|
+
// An exact spelling wins over its normalized alias. A conflicting key does not
|
|
62
|
+
// fall through to a lower-authority source and accidentally regain a larger window.
|
|
63
|
+
const map = tier.exact.has(id) ? tier.exact : tier.normalized;
|
|
64
|
+
const key = map === tier.exact ? id : normalize(id);
|
|
65
|
+
if (map.has(key)) {
|
|
66
|
+
const value = map.get(key);
|
|
67
|
+
return value ? { ...value } : undefined;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
return undefined;
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
let lookup: ReturnType<typeof createVendorContextLookup> | undefined;
|
|
75
|
+
export function vendorContextInference(modelId: string): VendorContextInference | undefined {
|
|
76
|
+
lookup ??= createVendorContextLookup(VENDORS.flatMap(listModelMetadata), AGGREGATORS.flatMap(listModelMetadata));
|
|
77
|
+
return lookup(modelId);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
export function vendorContextWindow(modelId: string): number | undefined {
|
|
81
|
+
return vendorContextInference(modelId)?.contextWindow;
|
|
82
|
+
}
|
|
@@ -166,15 +166,21 @@ function canonicalFileIdentity(canonical: string): string | null {
|
|
|
166
166
|
/** Capture before the first write; nested native children share the same recovery scope. */
|
|
167
167
|
export function withConfigWriteRecovery<T>(
|
|
168
168
|
configPath: string, held: LockHandle, run: () => T,
|
|
169
|
-
options: { refreshBeforeSpawn?: boolean; preimage?: Buffer } = {},
|
|
169
|
+
options: { refreshBeforeSpawn?: boolean; preimage?: Buffer; requireMatchingPreimage?: boolean } = {},
|
|
170
170
|
): T {
|
|
171
|
-
|
|
171
|
+
const nested = recoveries.get(held);
|
|
172
|
+
if (nested && !options.requireMatchingPreimage) return run();
|
|
172
173
|
let canonical: string;
|
|
173
174
|
try { canonical = assertConfigWriteDestination(configPath, held); }
|
|
174
175
|
catch { throw new ConfigWriteDestinationChanged(); }
|
|
175
176
|
const identity = canonicalFileIdentity(canonical);
|
|
176
177
|
const preimage = identity === null ? null : readFileSync(canonical);
|
|
177
178
|
if (canonicalFileIdentity(canonical) !== identity) throw new ConfigWriteDestinationChanged();
|
|
179
|
+
if (options.requireMatchingPreimage && (!options.preimage || !preimage?.equals(options.preimage))) {
|
|
180
|
+
throw new ConfigWriteDestinationChanged();
|
|
181
|
+
}
|
|
182
|
+
if (nested && (nested.canonical !== canonical || nested.identity !== identity)) throw new ConfigWriteDestinationChanged();
|
|
183
|
+
if (nested) return run();
|
|
178
184
|
const recovery: ConfigWriteRecovery = {
|
|
179
185
|
canonical, identity, preimage: options.preimage ?? preimage,
|
|
180
186
|
refreshBeforeSpawn: options.refreshBeforeSpawn === true && options.preimage === undefined,
|
|
@@ -317,6 +323,38 @@ export function publishConfigWriteTarget<T>(
|
|
|
317
323
|
});
|
|
318
324
|
}
|
|
319
325
|
|
|
326
|
+
export function removeConfigWriteEntry(configPath: string, held: LockHandle, path: string): void {
|
|
327
|
+
assertConfigWriteDestination(configPath, held);
|
|
328
|
+
watchConfigWriteTargets(held, [path]);
|
|
329
|
+
const watched = targets.get(held)!;
|
|
330
|
+
const expected = watched.get(path)!;
|
|
331
|
+
const current = destination(path);
|
|
332
|
+
if (expected.canonical !== current.canonical || expected.inode !== current.inode
|
|
333
|
+
|| current.canonical !== join(realpathSync.native(dirname(resolve(path))), basename(resolve(path)))) {
|
|
334
|
+
throw new Error("Codex artifact destination changed; files and recovery evidence were preserved.");
|
|
335
|
+
}
|
|
336
|
+
if (expected.inode === null) return;
|
|
337
|
+
|
|
338
|
+
const entry = join(realpathSync.native(dirname(resolve(path))), basename(resolve(path)));
|
|
339
|
+
const identity = (file: { dev: bigint; ino: bigint }) => `${file.dev}:${file.ino}`;
|
|
340
|
+
const before = lstatSync(entry, { bigint: true });
|
|
341
|
+
if (before.isSymbolicLink() || !before.isFile() || identity(before) !== expected.inode) {
|
|
342
|
+
throw new Error("Codex artifact destination changed; files and recovery evidence were preserved.");
|
|
343
|
+
}
|
|
344
|
+
assertConfigWriteDestination(configPath, held);
|
|
345
|
+
const now = lstatSync(entry, { bigint: true });
|
|
346
|
+
if (now.isSymbolicLink() || !now.isFile() || identity(now) !== expected.inode) {
|
|
347
|
+
throw new Error("Codex artifact destination changed; files and recovery evidence were preserved.");
|
|
348
|
+
}
|
|
349
|
+
unlinkSync(entry);
|
|
350
|
+
assertConfigWriteDestination(configPath, held);
|
|
351
|
+
const after = destination(path);
|
|
352
|
+
if (after.inode !== null || after.canonical !== expected.canonical) {
|
|
353
|
+
throw new Error("Codex artifact destination changed; recovery evidence was preserved.");
|
|
354
|
+
}
|
|
355
|
+
watched.set(path, after);
|
|
356
|
+
}
|
|
357
|
+
|
|
320
358
|
export function configWriteLockFailureMessage(failure: Exclude<ConfigWriteAcquireResult, { ok: true }>): string {
|
|
321
359
|
if (failure.error === "missing-parent") return `Codex configuration parent is missing or unresolved at ${failure.detail}; no files were changed.`;
|
|
322
360
|
return failure.error === "unsafe"
|
package/src/codex/convergence.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { projectAntigravitySelectedModels } from "../providers/antigravity-effort-families";
|
|
2
|
+
import { configuredUltraFastSlugs } from "./catalog/configured-tiers";
|
|
2
3
|
import { join } from "node:path";
|
|
3
4
|
import { sameCatalogHealPath } from "./catalog/heal-observation";
|
|
4
5
|
|
|
@@ -371,6 +372,7 @@ function prepareCatalog(
|
|
|
371
372
|
);
|
|
372
373
|
const mergedModels = mergeCatalogEntriesFromObservedState({
|
|
373
374
|
ultraFastTier: ultraFastTierEnabled(config),
|
|
375
|
+
configuredUltraFastSlugs: configuredUltraFastSlugs(ordered),
|
|
374
376
|
modelPickerOrder,
|
|
375
377
|
accountSelectors,
|
|
376
378
|
catalogModels,
|
|
@@ -51,6 +51,8 @@ export interface DesktopProcess {
|
|
|
51
51
|
createdAt: string;
|
|
52
52
|
/** Absolute executable path, used for membership and the shell predicate. */
|
|
53
53
|
executable: string;
|
|
54
|
+
/** Windows-only private launch context; never included in restart results or logs. */
|
|
55
|
+
commandLine?: string;
|
|
54
56
|
}
|
|
55
57
|
|
|
56
58
|
export interface DesktopAppAdapter {
|