@bitkyc08/opencodex 2.80.0 → 2.82.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -3
- package/bin/ocx.mjs +166 -73
- package/gui/dist/assets/App-Ds_qL7o8.js +54 -0
- package/gui/dist/assets/Tray-BqHF5Trd.js +1 -0
- package/gui/dist/assets/{index-Brk6F3fn.css → index-BAbcj51J.css} +1 -1
- package/gui/dist/assets/index-D3FBCNiP.js +94 -0
- package/gui/dist/assets/quota-summary-DTBC8n7-.js +1 -0
- package/gui/dist/index.html +2 -2
- package/gui/dist/provider-icons/claude-green.svg +1 -0
- package/package.json +3 -2
- package/src/adapters/anthropic-model-contract.ts +8 -2
- package/src/adapters/anthropic.ts +8 -3
- package/src/adapters/codebuddy/mcp-server.ts +2 -25
- package/src/adapters/codebuddy/tool-bridge.ts +1 -7
- package/src/adapters/coding-agent/mcp-server.ts +33 -0
- package/src/adapters/coding-agent/protocol.ts +122 -17
- package/src/adapters/coding-agent/tool-catalog.ts +75 -0
- package/src/adapters/coding-agent/turn.ts +101 -44
- package/src/adapters/cursor/catalog.ts +8 -0
- package/src/adapters/cursor/effort-map.ts +2 -0
- package/src/adapters/devin/live-models.ts +2 -0
- package/src/adapters/kiro-retry.ts +9 -4
- package/src/adapters/openai-chat/messages.ts +7 -6
- package/src/adapters/openai-responses/compaction-search-history.ts +109 -0
- package/src/adapters/openai-responses/passthrough.ts +9 -4
- package/src/adapters/openai-responses/tool-output-recovery.ts +20 -0
- package/src/adapters/physical-send.ts +8 -5
- package/src/adapters/qoder/adapter.ts +41 -6
- package/src/adapters/qoder/scaffold-guard.ts +2 -3
- package/src/adapters/zed.ts +16 -1
- package/src/claude/agents-inject.ts +14 -3
- package/src/claude/context-windows.ts +19 -17
- package/src/claude/desktop-3p.ts +88 -12
- package/src/claude/desktop-profile.ts +2 -1
- package/src/claude/gateway-cache.ts +18 -1
- package/src/claude/inbound-cache-stabilize.ts +4 -9
- package/src/claude/inbound.ts +78 -3
- package/src/claude/intercept/cli-catalog.ts +3 -0
- package/src/claude/intercept/model-bindings.ts +1 -0
- package/src/claude/intercept/picker-ca-persistence.ts +7 -6
- package/src/claude/intercept/picker-listener.ts +71 -4
- package/src/claude/intercept/picker-models.ts +14 -6
- package/src/claude/intercept/settings.ts +3 -0
- package/src/claude/long-context.ts +66 -0
- package/src/claude/model-info.ts +19 -16
- package/src/claude/outbound.ts +94 -9
- package/src/claude/subagent-model.ts +40 -11
- package/src/cli/account-anthropic-threshold.ts +14 -5
- package/src/cli/account-api.ts +3 -1
- package/src/cli/account-extended.ts +13 -9
- package/src/cli/account-policy-dto.ts +1 -1
- package/src/cli/account-policy.ts +13 -4
- package/src/cli/account.ts +3 -3
- package/src/cli/agent.ts +9 -5
- package/src/cli/aside-profile-recovery.ts +33 -0
- package/src/cli/capabilities-accounts.ts +2 -2
- package/src/cli/capabilities-agents-routing.ts +24 -0
- package/src/cli/capabilities-base.ts +5 -5
- package/src/cli/capabilities-integrations.ts +18 -2
- package/src/cli/cli-path-diagnostics.ts +132 -0
- package/src/cli/codex-shim-autorestore.ts +3 -0
- package/src/cli/desktop-runtime-guidance.ts +65 -0
- package/src/cli/dispatch.ts +15 -1
- package/src/cli/doctor.ts +16 -3
- package/src/cli/help.ts +4 -1
- package/src/cli/index.ts +25 -14
- package/src/cli/integration-aside-sync.ts +2 -1
- package/src/cli/integration-plan-dto.ts +1 -0
- package/src/cli/integration-preview.ts +8 -1
- package/src/cli/integrations.ts +48 -6
- package/src/cli/message-args.ts +34 -0
- package/src/cli/message-command.ts +43 -0
- package/src/cli/message-runtime.ts +6 -0
- package/src/cli/observe.ts +3 -1
- package/src/cli/provider.ts +29 -6
- package/src/cli/registry.ts +24 -2
- package/src/cli/resolve.ts +25 -2
- package/src/cli/root.ts +4 -2
- package/src/cli/status.ts +64 -12
- package/src/cli/update-restart-child.ts +4 -2
- package/src/cli/update-restart-home.ts +28 -10
- package/src/cli/update-restart-service-record.ts +116 -0
- package/src/cli/update-restart-supervision.ts +96 -0
- package/src/cli/update-restart.ts +59 -13
- package/src/cli/v2.ts +27 -20
- package/src/cli/version-skew-notice.ts +77 -0
- package/src/clients/config-export/commandcode.ts +131 -0
- package/src/clients/config-export/contracts.ts +12 -0
- package/src/clients/config-export.ts +64 -1
- package/src/clients/lazycodex.ts +1 -1
- package/src/clients/omo-role-models.ts +32 -7
- package/src/codex/auth-api/account-list.ts +11 -3
- package/src/codex/auth-api/account-selection.ts +107 -0
- package/src/codex/auth-api/main-account-probe.ts +25 -8
- package/src/codex/auth-api/pool-mode-gate.ts +33 -9
- package/src/codex/auth-api/pool-quota-probe.ts +15 -1
- package/src/codex/auth-api/routes.ts +11 -49
- package/src/codex/auth-context.ts +20 -1
- package/src/codex/autostart-health.ts +12 -3
- package/src/codex/catalog/auto-review.ts +13 -6
- package/src/codex/catalog/build-entries.ts +33 -7
- package/src/codex/catalog/bundled.ts +155 -26
- package/src/codex/catalog/combo-member.ts +3 -2
- package/src/codex/catalog/control-plane.ts +45 -0
- package/src/codex/catalog/effort.ts +37 -6
- package/src/codex/catalog/gather-capture.ts +10 -3
- package/src/codex/catalog/model-hints.ts +15 -8
- package/src/codex/catalog/model-visibility.ts +3 -1
- package/src/codex/catalog/operator-tiers.ts +38 -0
- package/src/codex/catalog/parsing.ts +2 -1
- package/src/codex/catalog/provider-models.ts +58 -44
- package/src/codex/catalog/retained-sync.ts +7 -5
- package/src/codex/catalog/routed-gather.ts +15 -1
- package/src/codex/catalog-auto-refresh-sources.ts +3 -4
- package/src/codex/catalog-auto-refresh.ts +19 -0
- package/src/codex/catalog.ts +1 -1
- package/src/codex/codex-home-owner.ts +3 -0
- package/src/codex/config-write-lock.ts +333 -0
- package/src/codex/control-plane-models.ts +6 -0
- package/src/codex/convergence.ts +2 -1
- package/src/codex/features.ts +257 -200
- package/src/codex/inject/config-write-section.ts +34 -0
- package/src/codex/inject/multi-agent-v2.ts +14 -6
- package/src/codex/inject/remove.ts +36 -11
- package/src/codex/inject/restore.ts +85 -20
- package/src/codex/inject-coordination.ts +15 -6
- package/src/codex/inject.ts +62 -20
- package/src/codex/journal.ts +62 -17
- package/src/codex/main-account-cache.ts +43 -0
- package/src/codex/paths.ts +2 -0
- package/src/codex/prepared-home.ts +18 -0
- package/src/codex/prompt-journal.ts +25 -12
- package/src/codex/prompt-layers.ts +49 -26
- package/src/codex/prompt-lock-claim.ts +134 -0
- package/src/codex/prompt-lock-evidence.ts +26 -0
- package/src/codex/prompt-lock-io.ts +16 -0
- package/src/codex/prompt-lock-owner.ts +130 -0
- package/src/codex/prompt-lock.ts +84 -53
- package/src/codex/routing/failure-window.ts +146 -0
- package/src/codex/routing/selection.ts +4 -1
- package/src/codex/routing.ts +13 -17
- package/src/codex/runtime.ts +106 -18
- package/src/codex/shim.ts +45 -19
- package/src/combos/jev-decision-contract.ts +25 -2
- package/src/combos/jev-service-exchange.ts +281 -0
- package/src/combos/jev.ts +34 -219
- package/src/combos/types.ts +1 -1
- package/src/config/atomic-write.ts +1 -1
- package/src/config/codex-ws-reuse-setting.ts +10 -0
- package/src/config/diagnostics.ts +27 -16
- package/src/config/live-reconcile.ts +17 -0
- package/src/config/load-degrade.ts +42 -0
- package/src/config/rebase-provenance.ts +11 -0
- package/src/config/schema/anthropic-account-pool.ts +143 -0
- package/src/config/schema/config-schema.ts +11 -1
- package/src/config/schema/leaf-validators.ts +4 -0
- package/src/config.ts +2 -0
- package/src/generated/compatibility-version.json +566 -298
- package/src/generated/model-metadata.ts +7 -6
- package/src/grok/inject.ts +50 -4
- package/src/grok/sync.ts +2 -1
- package/src/images/loop.ts +30 -11
- package/src/integrations/aside-profiles.ts +10 -3
- package/src/integrations/catalog-refresh.ts +19 -3
- package/src/integrations/mutation-plan.ts +7 -0
- package/src/integrations/registry.ts +8 -0
- package/src/integrations/state.ts +9 -2
- package/src/integrations/writer.ts +17 -5
- package/src/lib/bun-path-runtime.d.mts +32 -0
- package/src/lib/bun-path-runtime.mjs +95 -0
- package/src/lib/bun-runtime-preflight.ts +140 -0
- package/src/lib/desktop-cli-handoff.d.mts +20 -0
- package/src/lib/desktop-cli-handoff.mjs +92 -0
- package/src/lib/desktop-cli-record.d.mts +29 -0
- package/src/lib/desktop-cli-record.mjs +102 -0
- package/src/lib/lab-live-route-production.ts +9 -1
- package/src/lib/request-execution-budget.ts +244 -58
- package/src/lib/spend-pool-alias-validation.ts +79 -0
- package/src/lib/spend-pool-continuity.ts +34 -0
- package/src/lib/spend-reservation-ledger.ts +412 -50
- package/src/lib/state-store-registrations.ts +20 -3
- package/src/lib/synced-state-location.ts +46 -6
- package/src/lib/test-home-guard.ts +87 -1
- package/src/lib/translator-budget.ts +17 -4
- package/src/lib/upstream-retry.ts +17 -5
- package/src/lib/windows-atomic-replace.ts +38 -16
- package/src/lib/windows-elevation.ts +6 -0
- package/src/lib/windows-secret-acl.ts +92 -25
- package/src/lib/winsw.ts +2 -3
- package/src/lib/workflow-budget.ts +53 -11
- package/src/messaging/budget.ts +45 -0
- package/src/messaging/discovery.ts +57 -0
- package/src/messaging/envelope.ts +49 -0
- package/src/messaging/input.ts +37 -0
- package/src/messaging/rpc.ts +196 -0
- package/src/messaging/send.ts +58 -0
- package/src/messaging/socket.ts +72 -0
- package/src/messaging/types.ts +29 -0
- package/src/oauth/anthropic-account-refusal.ts +90 -18
- package/src/oauth/anthropic-account-threshold.ts +8 -2
- package/src/oauth/anthropic-continuity.ts +15 -1
- package/src/oauth/anthropic-model-quota.ts +120 -48
- package/src/oauth/anthropic-model-routes.ts +11 -3
- package/src/oauth/anthropic-oauth-definitions.ts +98 -0
- package/src/oauth/anthropic-pool-config.ts +30 -0
- package/src/oauth/anthropic-rate-limit-policy.ts +64 -9
- package/src/oauth/anthropic-routing.ts +1202 -866
- package/src/oauth/anthropic-send-ownership.ts +41 -0
- package/src/oauth/anthropic.ts +4 -1
- package/src/oauth/chatgpt.ts +113 -41
- package/src/oauth/generic-account-failover.ts +3 -1
- package/src/oauth/health.ts +8 -6
- package/src/oauth/index.ts +96 -175
- package/src/oauth/kiro.ts +22 -9
- package/src/oauth/login-cli.ts +2 -0
- package/src/oauth/model-discovery-auth.ts +43 -0
- package/src/oauth/pool-kernel.ts +11 -5
- package/src/oauth/pool-settings-capability.ts +5 -3
- package/src/oauth/store-anthropic-instance.ts +87 -0
- package/src/oauth/store.ts +68 -10
- package/src/oauth/token-guardian.ts +2 -0
- package/src/oauth/types.ts +2 -0
- package/src/protocols/plan-snapshot.ts +5 -0
- package/src/protocols/settings.ts +20 -5
- package/src/providers/anthropic-instance-id.ts +47 -0
- package/src/providers/anthropic-instance.ts +48 -0
- package/src/providers/anthropic-reset-grant-ledger.ts +11 -1
- package/src/providers/azure-model-metadata.ts +115 -0
- package/src/providers/derive.ts +23 -0
- package/src/providers/kiro-models.ts +3 -0
- package/src/providers/label.ts +1 -1
- package/src/providers/model-rename-fields.ts +2 -0
- package/src/providers/quota/account-cache.ts +37 -11
- package/src/providers/quota/anthropic-account-quota.ts +93 -0
- package/src/providers/quota/anthropic-cooldown-recovery.ts +222 -111
- package/src/providers/quota/report-cache.ts +24 -1
- package/src/providers/quota/vendor-probes-key.ts +127 -17
- package/src/providers/quota/vendor-probes-oauth.ts +46 -14
- package/src/providers/quota.ts +23 -33
- package/src/providers/registry/entries-core.ts +35 -30
- package/src/providers/registry/model-ids.ts +1 -0
- package/src/providers/registry/model-seeds.ts +7 -4
- package/src/providers/registry/types.ts +3 -0
- package/src/providers/registry.ts +3 -3
- package/src/responses/reasoning-envelope.ts +29 -1
- package/src/responses/reasoning-replay-cache.ts +17 -1
- package/src/responses/spill-store.ts +20 -3
- package/src/responses/state/metrics.ts +95 -0
- package/src/responses/state/snapshot-codec.ts +6 -0
- package/src/responses/state/spill-failure.ts +12 -0
- package/src/responses/state/spill-queue.ts +13 -5
- package/src/responses/state/unforced-store-false.ts +55 -0
- package/src/responses/state.ts +68 -76
- package/src/responses/task-input.ts +17 -0
- package/src/router.ts +28 -4
- package/src/routing/compatibility/assemble.ts +1 -1
- package/src/routing/quota.ts +7 -3
- package/src/server/auth-cors.ts +5 -0
- package/src/server/background-lifecycle.ts +27 -0
- package/src/server/chat-completions.ts +7 -1
- package/src/server/chat-native.ts +64 -28
- package/src/server/claude-messages.ts +59 -8
- package/src/server/gui-static.ts +38 -4
- package/src/server/inbound-body-admission.ts +1 -0
- package/src/server/index/claude-intercept-lifecycle.ts +3 -1
- package/src/server/index/serve-options.ts +10 -2
- package/src/server/index/spend-ledger-lifecycle.ts +12 -5
- package/src/server/index/startup-warnings.ts +19 -0
- package/src/server/index.ts +5 -2
- package/src/server/inference/context.ts +1 -1
- package/src/server/lifecycle.ts +1 -1
- package/src/server/management/agent-settings-routes.ts +123 -38
- package/src/server/management/anthropic-account-threshold.ts +12 -9
- package/src/server/management/anthropic-pool-settings.ts +72 -0
- package/src/server/management/anthropic-reset-grant-routes.ts +98 -39
- package/src/server/management/codex-agent-role-routes.ts +4 -2
- package/src/server/management/codex-prompt-routes.ts +1 -0
- package/src/server/management/codex-role-auto-assign.ts +13 -2
- package/src/server/management/config-routes.ts +85 -14
- package/src/server/management/context.ts +2 -2
- package/src/server/management/decision-routes.ts +2 -1
- package/src/server/management/integration-routes.ts +25 -2
- package/src/server/management/oauth-account-routes.ts +79 -98
- package/src/server/management/provider-instance-ownership.ts +44 -0
- package/src/server/management/provider-routes.ts +21 -28
- package/src/server/management/route-registry.ts +3 -1
- package/src/server/management/routing-profile-routes.ts +4 -4
- package/src/server/management/shared.ts +3 -3
- package/src/server/management/system-restart.ts +44 -14
- package/src/server/management/system-routes.ts +24 -2
- package/src/server/management/vision-sidecar-options.ts +9 -6
- package/src/server/management/web-search-sidecar-options.ts +51 -2
- package/src/server/management-auth.ts +6 -0
- package/src/server/messages-native-eligibility.ts +3 -2
- package/src/server/messages-native-oauth.ts +91 -45
- package/src/server/messages-native-selector.ts +39 -0
- package/src/server/messages-native.ts +133 -38
- package/src/server/messages-response-headers.ts +14 -0
- package/src/server/request-log-conversation.ts +48 -5
- package/src/server/request-log.ts +36 -2
- package/src/server/responses/adapter-continuation.ts +31 -19
- package/src/server/responses/adapter-dispatch.ts +75 -24
- package/src/server/responses/antigravity-validation-refusal.ts +20 -6
- package/src/server/responses/codex-ws-exchange.ts +17 -2
- package/src/server/responses/codex-ws-pool.ts +100 -13
- package/src/server/responses/codex-ws-wire.ts +9 -0
- package/src/server/responses/combo-requested-effort.ts +3 -1
- package/src/server/responses/compact.ts +25 -8
- package/src/server/responses/compaction-recovery.ts +1 -1
- package/src/server/responses/core-codex-account.ts +22 -1
- package/src/server/responses/core-combo-native.ts +24 -4
- package/src/server/responses/core-combo.ts +38 -25
- package/src/server/responses/core-lifetime.ts +3 -36
- package/src/server/responses/core-normalize.ts +1 -0
- package/src/server/responses/core-options.ts +8 -1
- package/src/server/responses/core-replay.ts +78 -0
- package/src/server/responses/core.ts +3 -3
- package/src/server/responses/fetch-helpers.ts +26 -3
- package/src/server/responses/passthrough-delivery.ts +30 -4
- package/src/server/responses/passthrough-dispatch.ts +39 -9
- package/src/server/responses/request-prepare.ts +41 -5
- package/src/server/responses/request-send-budget.ts +150 -50
- package/src/server/responses/request-spend.ts +325 -33
- package/src/server/responses/request-transport.ts +132 -52
- package/src/server/responses/response-effects.ts +1 -0
- package/src/server/responses/run-turn-execution.ts +13 -3
- package/src/server/responses/sidecar-execution.ts +113 -22
- package/src/server/responses/sidecar-send-budget.ts +58 -0
- package/src/server/responses/ws-upstream.ts +19 -6
- package/src/server/responses-undeclared-tool-guard.ts +5 -1
- package/src/server/startup-health-cache.ts +2 -1
- package/src/server/workflow-refusal.ts +33 -0
- package/src/service/cli.ts +20 -4
- package/src/service/desktop-command-guard.ts +32 -0
- package/src/service/desktop-startup.ts +66 -40
- package/src/service/desktop-supervision.d.mts +26 -0
- package/src/service/desktop-supervision.mjs +140 -0
- package/src/service/managing-cli.ts +1 -0
- package/src/service/orchestration.ts +46 -20
- package/src/service/ownership-mutation-lease.d.mts +1 -1
- package/src/service/ownership-mutation-lease.mjs +5 -7
- package/src/service/repair.ts +25 -9
- package/src/service/state.ts +4 -3
- package/src/service/systemd.ts +17 -8
- package/src/service/windows-ops.ts +61 -22
- package/src/sidecar/anthropic-binding.ts +79 -0
- package/src/sidecar/auth.ts +76 -2
- package/src/storage/policy-job.ts +5 -1
- package/src/storage/policy-worker.ts +3 -1
- package/src/storage/policy.ts +9 -0
- package/src/types/anthropic-account-pool.ts +33 -0
- package/src/types/config.ts +33 -28
- package/src/types/provider.ts +5 -0
- package/src/types/request.ts +5 -0
- package/src/types/tools.ts +7 -0
- package/src/types/wire.ts +1 -0
- package/src/types.ts +4 -0
- package/src/update/index.ts +57 -9
- package/src/update/restart-ownership.ts +10 -3
- package/src/update/runtime-ownership.d.mts +6 -0
- package/src/update/runtime-ownership.mjs +23 -7
- package/src/usage/cost.ts +3 -2
- package/src/usage/expected-prices.ts +66 -14
- package/src/vision/anthropic-describe.ts +16 -3
- package/src/vision/index.ts +3 -0
- package/src/vision/plan.ts +19 -6
- package/src/web-search/alpha-search.ts +7 -1
- package/src/web-search/anthropic-executor.ts +16 -4
- package/src/web-search/index.ts +7 -3
- package/src/web-search/loop.ts +32 -7
- package/src/web-search/passthrough-bridge.ts +4 -1
- package/src/web-search/sidecar-providers.ts +4 -3
- package/gui/dist/assets/App-MbDVfUeC.js +0 -54
- package/gui/dist/assets/Tray-CzkxK82A.js +0 -1
- package/gui/dist/assets/index-UJt6npXk.js +0 -94
- package/gui/dist/assets/quota-summary-DU3sD6Z-.js +0 -1
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import type { RawEntry } from "./parsing";
|
|
2
|
+
|
|
3
|
+
/** Match the opt-in tier spelling without coercing malformed catalog values to strings. */
|
|
4
|
+
function isUltraFast(value: unknown): boolean {
|
|
5
|
+
return typeof value === "string" && value.trim().toLowerCase() === "ultrafast";
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
/** Recognize an explicitly supplied Ultra Fast descriptor by its string-valued id. */
|
|
9
|
+
function isUltraFastDescriptor(value: unknown): boolean {
|
|
10
|
+
return value !== null && typeof value === "object" && "id" in value && isUltraFast(value.id);
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
/** Restore only exact-row operator metadata, after fresh provider capabilities are applied. */
|
|
14
|
+
export function preserveOperatorUltraFastTiers(entry: RawEntry, previous: RawEntry | undefined, enabled: boolean): void {
|
|
15
|
+
// A native template or stale row is not authority for this opt-in. Keep all other fresh
|
|
16
|
+
// tier policy, including Fast, while replacing only Ultra Fast from the exact persisted row.
|
|
17
|
+
for (const [field, matches] of [
|
|
18
|
+
["service_tiers", isUltraFastDescriptor],
|
|
19
|
+
["additional_speed_tiers", isUltraFast],
|
|
20
|
+
] as const) {
|
|
21
|
+
const current = entry[field];
|
|
22
|
+
const fresh = Array.isArray(current) ? current.filter(value => !matches(value)) : [];
|
|
23
|
+
const old = previous?.[field];
|
|
24
|
+
const supplied = enabled && Array.isArray(old) ? old.find(matches) : undefined;
|
|
25
|
+
if (supplied !== undefined) {
|
|
26
|
+
entry[field] = [...fresh, structuredClone(supplied)];
|
|
27
|
+
} else if (Array.isArray(current) && fresh.length !== current.length) {
|
|
28
|
+
if (fresh.length > 0) entry[field] = fresh;
|
|
29
|
+
else delete entry[field];
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
const hasDeclaration = (Array.isArray(entry.service_tiers) && entry.service_tiers.some(isUltraFastDescriptor))
|
|
33
|
+
|| (Array.isArray(entry.additional_speed_tiers) && entry.additional_speed_tiers.some(isUltraFast));
|
|
34
|
+
for (const field of ["service_tier", "default_service_tier"] as const) {
|
|
35
|
+
if (enabled && hasDeclaration && previous && isUltraFast(previous[field])) entry[field] = previous[field];
|
|
36
|
+
else if (isUltraFast(entry[field])) delete entry[field];
|
|
37
|
+
}
|
|
38
|
+
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { isCodexControlPlaneModel } from "../control-plane-models";
|
|
1
2
|
import { execFileSync } from "node:child_process";
|
|
2
3
|
import { createHash } from "node:crypto";
|
|
3
4
|
import { copyFileSync, existsSync, mkdirSync, readFileSync, realpathSync } from "node:fs";
|
|
@@ -700,7 +701,7 @@ export function catalogEntryIsNativeChatGpt(entry: RawEntry): boolean {
|
|
|
700
701
|
&& entry.use_responses_lite === true
|
|
701
702
|
&& hasNativeOpenAiCapabilityMetadata(routedNativeSlug)
|
|
702
703
|
) return true;
|
|
703
|
-
if (UPSTREAM_NATIVE_ENTRIES.has(slug) || SUPPORTED_NATIVE_OPENAI_SLUGS.has(slug)) return true;
|
|
704
|
+
if (isCodexControlPlaneModel(slug) || UPSTREAM_NATIVE_ENTRIES.has(slug) || SUPPORTED_NATIVE_OPENAI_SLUGS.has(slug)) return true;
|
|
704
705
|
return false;
|
|
705
706
|
}
|
|
706
707
|
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { isAnthropicOAuthInstance } from "../../providers/anthropic-instance";
|
|
1
2
|
import { effectiveProviderAlias, effectiveProviderAliasDecision } from "../../providers/default-aliases";
|
|
2
3
|
import { initialModelSelectionPending } from "../../providers/initial-model-selection";
|
|
3
4
|
import { execFileSync } from "node:child_process";
|
|
@@ -28,17 +29,19 @@ import {
|
|
|
28
29
|
} from "../model-cache";
|
|
29
30
|
import {
|
|
30
31
|
buildModelsRequest,
|
|
31
|
-
|
|
32
|
+
getModelsOAuthAccessSnapshot,
|
|
32
33
|
observeActiveOAuthAccessToken,
|
|
33
34
|
resolveModelsAuthToken,
|
|
34
35
|
type OAuthActiveTokenObservation,
|
|
35
36
|
} from "../../oauth";
|
|
37
|
+
import { mayResolveModelsOAuth } from "../../oauth/model-discovery-auth";
|
|
36
38
|
import type { OcxConfig, OcxProviderConfig } from "../../types";
|
|
37
39
|
import { modelInList } from "../../types";
|
|
38
40
|
import { CODEX_REASONING_LEVELS, codexEffortRank, configuredReasoningEfforts, modelRecordValue, sanitizeCodexReasoningEfforts } from "../../reasoning-effort";
|
|
39
41
|
import { isModelVisionSidecarConsumer } from "../../vision/eligibility";
|
|
40
42
|
import { getModelMetadata, getModelMetadataCaseInsensitive, listModelMetadata, resolveMetadataProvider, type ModelMetadata } from "../../generated/model-metadata";
|
|
41
43
|
import { enrichProviderFromRegistry, shouldCaseFoldMetadataModelId } from "../../providers/derive";
|
|
44
|
+
import { isAzureModelMetadataDestination, refreshAzureModelMetadata } from "../../providers/azure-model-metadata";
|
|
42
45
|
import {
|
|
43
46
|
captureFastPolicyAuthority,
|
|
44
47
|
fastPolicyForModel,
|
|
@@ -145,7 +148,8 @@ export function observedModelsAuthResolver(
|
|
|
145
148
|
return { apiKey: resolveProviderApiKey(provider.apiKey), observed: true };
|
|
146
149
|
}
|
|
147
150
|
|
|
148
|
-
const observation =
|
|
151
|
+
const observation: OAuthActiveTokenObservation = mayResolveModelsOAuth(name, provider)
|
|
152
|
+
? observeActiveOAuthAccessToken(name, authStoreBuffer) : { kind: "missing" };
|
|
149
153
|
outcomes.push({ provider: name, state: observation.kind });
|
|
150
154
|
if (observation.kind !== "available") return { apiKey: undefined, observed: true };
|
|
151
155
|
return {
|
|
@@ -166,7 +170,8 @@ export async function fetchProviderModelsWithAuth(
|
|
|
166
170
|
contextCap: number | undefined,
|
|
167
171
|
resolveAuth: ModelsAuthResolver,
|
|
168
172
|
): Promise<ProviderModelsResult> {
|
|
169
|
-
const { name, provider: prov, discovery, metadataModelIdCaseFold } = captured;
|
|
173
|
+
const { name, provider: prov, discovery, metadataModelIdCaseFold, metadataConfigDir } = captured;
|
|
174
|
+
const azureMetadata = isAzureModelMetadataDestination(prov.baseUrl);
|
|
170
175
|
const observed = (
|
|
171
176
|
models: CatalogModel[],
|
|
172
177
|
state: CatalogGatherProviderModelOutcome["state"],
|
|
@@ -179,9 +184,10 @@ export async function fetchProviderModelsWithAuth(
|
|
|
179
184
|
// generation, so a request started with the former account cannot later publish its result.
|
|
180
185
|
const cacheGeneration = captureModelCacheGeneration(name);
|
|
181
186
|
const isCurrentCacheGeneration = () => isModelCacheGenerationCurrent(name, cacheGeneration);
|
|
182
|
-
const anthropicSelection = name
|
|
187
|
+
const anthropicSelection = isAnthropicOAuthInstance(name) && prov.authMode === "oauth" && mayResolveModelsOAuth(name, prov)
|
|
183
188
|
? captureOAuthAccountSelection(name) : null;
|
|
184
189
|
if (prov.authMode === "forward") return observed([], "authoritative"); // ChatGPT backend has no /models
|
|
190
|
+
if (azureMetadata) await refreshAzureModelMetadata(prov.baseUrl, metadataConfigDir);
|
|
185
191
|
const seedVertexDefault = prov.adapter === "google"
|
|
186
192
|
&& prov.googleMode === "vertex"
|
|
187
193
|
&& (prov.models?.length ?? 0) === 0
|
|
@@ -200,7 +206,7 @@ export async function fetchProviderModelsWithAuth(
|
|
|
200
206
|
const configured: CatalogModel[] = configuredIds.map(id => ({
|
|
201
207
|
id,
|
|
202
208
|
provider: name,
|
|
203
|
-
...catalogHintsFromProviderConfig(name, prov, id, contextCap, metadataModelIdCaseFold, captured.effectiveAlias),
|
|
209
|
+
...catalogHintsFromProviderConfig(name, prov, id, contextCap, metadataModelIdCaseFold, captured.effectiveAlias, metadataConfigDir),
|
|
204
210
|
}));
|
|
205
211
|
const withConfiguredRetention = (
|
|
206
212
|
models: CatalogModel[],
|
|
@@ -216,6 +222,7 @@ export async function fetchProviderModelsWithAuth(
|
|
|
216
222
|
seedVertexDefault,
|
|
217
223
|
retainComboTargets: options?.retainComboTargets,
|
|
218
224
|
metadataModelIdCaseFold,
|
|
225
|
+
metadataConfigDir,
|
|
219
226
|
});
|
|
220
227
|
if (
|
|
221
228
|
options?.warnDrops === true
|
|
@@ -248,7 +255,7 @@ export async function fetchProviderModelsWithAuth(
|
|
|
248
255
|
}
|
|
249
256
|
return observed(ids.map(id => {
|
|
250
257
|
const hints = catalogHintsFromProviderConfig(name, prov, id, contextCap,
|
|
251
|
-
metadataModelIdCaseFold, captured.effectiveAlias);
|
|
258
|
+
metadataModelIdCaseFold, captured.effectiveAlias, metadataConfigDir);
|
|
252
259
|
const observedWindow = kiroObservedContextWindow(id);
|
|
253
260
|
return { id, provider: name, ...hints,
|
|
254
261
|
...(observedWindow !== undefined
|
|
@@ -257,9 +264,11 @@ export async function fetchProviderModelsWithAuth(
|
|
|
257
264
|
}
|
|
258
265
|
return observed(configured, "authoritative");
|
|
259
266
|
}
|
|
260
|
-
const auth: ModelsAuthResolution =
|
|
267
|
+
const auth: ModelsAuthResolution = prov.authMode === "oauth" && !mayResolveModelsOAuth(name, prov)
|
|
268
|
+
? { apiKey: undefined, observed: resolveAuth.kind === "observed" }
|
|
269
|
+
: captured.observedAuth ?? (resolveAuth.kind === "refreshing"
|
|
261
270
|
? prov.authMode === "oauth"
|
|
262
|
-
? await
|
|
271
|
+
? await getModelsOAuthAccessSnapshot(name, prov)
|
|
263
272
|
.then(snapshot => ({
|
|
264
273
|
apiKey: snapshot.accessToken,
|
|
265
274
|
observed: false,
|
|
@@ -274,7 +283,8 @@ export async function fetchProviderModelsWithAuth(
|
|
|
274
283
|
: resolveAuth.resolve(name, prov));
|
|
275
284
|
const apiKey = auth.apiKey;
|
|
276
285
|
const maySendAnthropicDiscovery = () => {
|
|
277
|
-
if (name
|
|
286
|
+
if (!isAnthropicOAuthInstance(name) || prov.authMode !== "oauth") return true;
|
|
287
|
+
if (!mayResolveModelsOAuth(name, prov)) return false;
|
|
278
288
|
const selected = captureOAuthAccountSelection(name);
|
|
279
289
|
const row = auth.oauthAccountId ? getAccountCredentialWithStatus(name, auth.oauthAccountId) : null;
|
|
280
290
|
return !!anthropicSelection && !!selected && !!row && !row.paused && !row.needsReauth
|
|
@@ -290,7 +300,7 @@ export async function fetchProviderModelsWithAuth(
|
|
|
290
300
|
: [{
|
|
291
301
|
id: prov.defaultModel,
|
|
292
302
|
provider: name,
|
|
293
|
-
...catalogHintsFromProviderConfig(name, prov, prov.defaultModel, contextCap, metadataModelIdCaseFold, captured.effectiveAlias),
|
|
303
|
+
...catalogHintsFromProviderConfig(name, prov, prov.defaultModel, contextCap, metadataModelIdCaseFold, captured.effectiveAlias, metadataConfigDir),
|
|
294
304
|
}];
|
|
295
305
|
const vertexDefaultSeed = seedVertexDefault ? configured[0] : undefined;
|
|
296
306
|
const withVertexDefaultSeed = (models: CatalogModel[]): CatalogModel[] => (
|
|
@@ -312,13 +322,13 @@ export async function fetchProviderModelsWithAuth(
|
|
|
312
322
|
const fresh = getFreshCached(name, ttlMs, Date.now(), authorityIdentity);
|
|
313
323
|
if (fresh) {
|
|
314
324
|
return observed(withConfiguredRetention(
|
|
315
|
-
applyConfigHintsToCachedModels(name, prov, fresh, contextCap, metadataModelIdCaseFold, captured.effectiveAlias),
|
|
325
|
+
applyConfigHintsToCachedModels(name, prov, fresh, contextCap, metadataModelIdCaseFold, captured.effectiveAlias, metadataConfigDir),
|
|
316
326
|
), "authoritative");
|
|
317
327
|
}
|
|
318
328
|
const scopedStale = getStaleCached(name, authorityIdentity);
|
|
319
329
|
if (isModelsFetchCoolingDown(name, undefined, undefined, authorityIdentity) && scopedStale) {
|
|
320
330
|
return observed(withConfiguredRetention(
|
|
321
|
-
applyConfigHintsToCachedModels(name, prov, scopedStale, contextCap, metadataModelIdCaseFold, captured.effectiveAlias),
|
|
331
|
+
applyConfigHintsToCachedModels(name, prov, scopedStale, contextCap, metadataModelIdCaseFold, captured.effectiveAlias, metadataConfigDir),
|
|
322
332
|
), "degraded");
|
|
323
333
|
}
|
|
324
334
|
const live = await fetchCodeBuddyModels(profile, apiKey);
|
|
@@ -326,7 +336,7 @@ export async function fetchProviderModelsWithAuth(
|
|
|
326
336
|
const discovered = live.models.map(id => ({
|
|
327
337
|
id,
|
|
328
338
|
provider: name,
|
|
329
|
-
...catalogHintsFromProviderConfig(name, prov, id, contextCap, metadataModelIdCaseFold, captured.effectiveAlias),
|
|
339
|
+
...catalogHintsFromProviderConfig(name, prov, id, contextCap, metadataModelIdCaseFold, captured.effectiveAlias, metadataConfigDir),
|
|
330
340
|
}));
|
|
331
341
|
const forCache = withConfiguredRetention(discovered, { retainComboTargets: false });
|
|
332
342
|
if (!setCached(name, forCache, Date.now(), cacheGeneration, authorityIdentity)) {
|
|
@@ -342,7 +352,7 @@ export async function fetchProviderModelsWithAuth(
|
|
|
342
352
|
}
|
|
343
353
|
const stale = getStaleCached(name, authorityIdentity);
|
|
344
354
|
return observed(withConfiguredRetention(
|
|
345
|
-
stale ? applyConfigHintsToCachedModels(name, prov, stale, contextCap, metadataModelIdCaseFold, captured.effectiveAlias) : configured,
|
|
355
|
+
stale ? applyConfigHintsToCachedModels(name, prov, stale, contextCap, metadataModelIdCaseFold, captured.effectiveAlias, metadataConfigDir) : configured,
|
|
346
356
|
), "degraded");
|
|
347
357
|
}
|
|
348
358
|
if (name === "zed" && prov.adapter === "zed") {
|
|
@@ -355,14 +365,14 @@ export async function fetchProviderModelsWithAuth(
|
|
|
355
365
|
const cached = getFreshCached(name, ttlMs, Date.now(), authorityIdentity);
|
|
356
366
|
if (cached) {
|
|
357
367
|
return observed(
|
|
358
|
-
withConfiguredRetention(applyConfigHintsToCachedModels(name, prov, cached, contextCap, metadataModelIdCaseFold, captured.effectiveAlias)),
|
|
368
|
+
withConfiguredRetention(applyConfigHintsToCachedModels(name, prov, cached, contextCap, metadataModelIdCaseFold, captured.effectiveAlias, metadataConfigDir)),
|
|
359
369
|
"authoritative",
|
|
360
370
|
);
|
|
361
371
|
}
|
|
362
372
|
const stale = getStaleCached(name, authorityIdentity);
|
|
363
373
|
if (isModelsFetchCoolingDown(name, undefined, undefined, authorityIdentity) && stale) {
|
|
364
374
|
return observed(
|
|
365
|
-
withConfiguredRetention(applyConfigHintsToCachedModels(name, prov, stale, contextCap, metadataModelIdCaseFold, captured.effectiveAlias)),
|
|
375
|
+
withConfiguredRetention(applyConfigHintsToCachedModels(name, prov, stale, contextCap, metadataModelIdCaseFold, captured.effectiveAlias, metadataConfigDir)),
|
|
366
376
|
"degraded",
|
|
367
377
|
);
|
|
368
378
|
}
|
|
@@ -382,7 +392,7 @@ export async function fetchProviderModelsWithAuth(
|
|
|
382
392
|
...(model.maxOutputTokens ? { maxOutputTokens: model.maxOutputTokens } : {}),
|
|
383
393
|
...(model.supportsImages ? { inputModalities: ["text", "image"] } : {}),
|
|
384
394
|
...(reasoningEfforts?.length ? { reasoningEfforts } : {}),
|
|
385
|
-
...catalogHintsFromProviderConfig(name, prov, model.id, contextCap, metadataModelIdCaseFold, captured.effectiveAlias),
|
|
395
|
+
...catalogHintsFromProviderConfig(name, prov, model.id, contextCap, metadataModelIdCaseFold, captured.effectiveAlias, metadataConfigDir),
|
|
386
396
|
} as CatalogModel;
|
|
387
397
|
});
|
|
388
398
|
const forCache = withConfiguredRetention(discovered, { retainComboTargets: false });
|
|
@@ -397,7 +407,7 @@ export async function fetchProviderModelsWithAuth(
|
|
|
397
407
|
markProviderDiscoveryFailed(name, { reason: "provider" });
|
|
398
408
|
}
|
|
399
409
|
return observed(
|
|
400
|
-
withConfiguredRetention(stale ? applyConfigHintsToCachedModels(name, prov, stale, contextCap, metadataModelIdCaseFold, captured.effectiveAlias) : configured),
|
|
410
|
+
withConfiguredRetention(stale ? applyConfigHintsToCachedModels(name, prov, stale, contextCap, metadataModelIdCaseFold, captured.effectiveAlias, metadataConfigDir) : configured),
|
|
401
411
|
"degraded",
|
|
402
412
|
);
|
|
403
413
|
}
|
|
@@ -413,13 +423,13 @@ export async function fetchProviderModelsWithAuth(
|
|
|
413
423
|
const fresh = getFreshCached(name, ttlMs, Date.now(), authorityIdentity);
|
|
414
424
|
if (fresh) {
|
|
415
425
|
return observed(withConfiguredRetention(
|
|
416
|
-
applyConfigHintsToCachedModels(name, prov, fresh, contextCap, metadataModelIdCaseFold, captured.effectiveAlias),
|
|
426
|
+
applyConfigHintsToCachedModels(name, prov, fresh, contextCap, metadataModelIdCaseFold, captured.effectiveAlias, metadataConfigDir),
|
|
417
427
|
), "authoritative");
|
|
418
428
|
}
|
|
419
429
|
const scopedStale = getStaleCached(name, authorityIdentity);
|
|
420
430
|
if (isModelsFetchCoolingDown(name) && scopedStale) {
|
|
421
431
|
return observed(withConfiguredRetention(
|
|
422
|
-
applyConfigHintsToCachedModels(name, prov, scopedStale, contextCap, metadataModelIdCaseFold, captured.effectiveAlias),
|
|
432
|
+
applyConfigHintsToCachedModels(name, prov, scopedStale, contextCap, metadataModelIdCaseFold, captured.effectiveAlias, metadataConfigDir),
|
|
423
433
|
), "degraded");
|
|
424
434
|
}
|
|
425
435
|
const live = await fetchQoderModels(profile, apiKey);
|
|
@@ -427,7 +437,7 @@ export async function fetchProviderModelsWithAuth(
|
|
|
427
437
|
const discovered = live.models.map(id => ({
|
|
428
438
|
id,
|
|
429
439
|
provider: name,
|
|
430
|
-
...catalogHintsFromProviderConfig(name, prov, id, contextCap, metadataModelIdCaseFold, captured.effectiveAlias),
|
|
440
|
+
...catalogHintsFromProviderConfig(name, prov, id, contextCap, metadataModelIdCaseFold, captured.effectiveAlias, metadataConfigDir),
|
|
431
441
|
}));
|
|
432
442
|
const forCache = withConfiguredRetention(discovered, { retainComboTargets: false });
|
|
433
443
|
if (!setCached(name, forCache, Date.now(), cacheGeneration, authorityIdentity)) {
|
|
@@ -443,7 +453,7 @@ export async function fetchProviderModelsWithAuth(
|
|
|
443
453
|
}
|
|
444
454
|
const stale = getStaleCached(name, authorityIdentity);
|
|
445
455
|
return observed(withConfiguredRetention(
|
|
446
|
-
stale ? applyConfigHintsToCachedModels(name, prov, stale, contextCap, metadataModelIdCaseFold, captured.effectiveAlias) : configured,
|
|
456
|
+
stale ? applyConfigHintsToCachedModels(name, prov, stale, contextCap, metadataModelIdCaseFold, captured.effectiveAlias, metadataConfigDir) : configured,
|
|
447
457
|
), "degraded");
|
|
448
458
|
}
|
|
449
459
|
if (prov.adapter === "devin") {
|
|
@@ -458,7 +468,7 @@ export async function fetchProviderModelsWithAuth(
|
|
|
458
468
|
const cachedDevin = getFreshCached(name, ttlMs, Date.now(), authorityIdentity);
|
|
459
469
|
if (cachedDevin) {
|
|
460
470
|
return observed(
|
|
461
|
-
withConfiguredRetention(applyConfigHintsToCachedModels(name, prov, cachedDevin)),
|
|
471
|
+
withConfiguredRetention(applyConfigHintsToCachedModels(name, prov, cachedDevin, undefined, undefined, undefined, metadataConfigDir)),
|
|
462
472
|
"authoritative",
|
|
463
473
|
);
|
|
464
474
|
}
|
|
@@ -466,7 +476,7 @@ export async function fetchProviderModelsWithAuth(
|
|
|
466
476
|
const cooling = getStaleCached(name, authorityIdentity);
|
|
467
477
|
return observed(
|
|
468
478
|
withConfiguredRetention(
|
|
469
|
-
cooling ? applyConfigHintsToCachedModels(name, prov, cooling) : configured,
|
|
479
|
+
cooling ? applyConfigHintsToCachedModels(name, prov, cooling, undefined, undefined, undefined, metadataConfigDir) : configured,
|
|
470
480
|
),
|
|
471
481
|
"degraded",
|
|
472
482
|
);
|
|
@@ -508,7 +518,7 @@ export async function fetchProviderModelsWithAuth(
|
|
|
508
518
|
// record and the vision-sidecar rewrite keep winning — the live
|
|
509
519
|
// value survives only when none of them applies.
|
|
510
520
|
...(liveResult.inputModalities[id]?.length ? { inputModalities: liveResult.inputModalities[id] } : {}),
|
|
511
|
-
...catalogHintsFromProviderConfig(name, prov, id, contextCap, metadataModelIdCaseFold, captured.effectiveAlias),
|
|
521
|
+
...catalogHintsFromProviderConfig(name, prov, id, contextCap, metadataModelIdCaseFold, captured.effectiveAlias, metadataConfigDir),
|
|
512
522
|
} as CatalogModel;
|
|
513
523
|
});
|
|
514
524
|
const forCache = withConfiguredRetention(result, { retainComboTargets: false });
|
|
@@ -524,7 +534,7 @@ export async function fetchProviderModelsWithAuth(
|
|
|
524
534
|
}
|
|
525
535
|
const stale = getStaleCached(name, authorityIdentity);
|
|
526
536
|
return observed(
|
|
527
|
-
withConfiguredRetention(stale ? applyConfigHintsToCachedModels(name, prov, stale) : configured),
|
|
537
|
+
withConfiguredRetention(stale ? applyConfigHintsToCachedModels(name, prov, stale, undefined, undefined, undefined, metadataConfigDir) : configured),
|
|
528
538
|
"degraded",
|
|
529
539
|
);
|
|
530
540
|
}
|
|
@@ -541,7 +551,7 @@ export async function fetchProviderModelsWithAuth(
|
|
|
541
551
|
const cachedCursor = getFreshCached(name, ttlMs, Date.now(), authorityIdentity);
|
|
542
552
|
if (cachedCursor) {
|
|
543
553
|
return observed(
|
|
544
|
-
withConfiguredRetention(applyConfigHintsToCachedModels(name, prov, cachedCursor, undefined, metadataModelIdCaseFold, captured.effectiveAlias)),
|
|
554
|
+
withConfiguredRetention(applyConfigHintsToCachedModels(name, prov, cachedCursor, undefined, metadataModelIdCaseFold, captured.effectiveAlias, metadataConfigDir)),
|
|
545
555
|
"authoritative",
|
|
546
556
|
);
|
|
547
557
|
}
|
|
@@ -549,7 +559,7 @@ export async function fetchProviderModelsWithAuth(
|
|
|
549
559
|
const cooling = getStaleCached(name, authorityIdentity);
|
|
550
560
|
return observed(
|
|
551
561
|
withConfiguredRetention(
|
|
552
|
-
cooling ? applyConfigHintsToCachedModels(name, prov, cooling, undefined, metadataModelIdCaseFold, captured.effectiveAlias) : configured,
|
|
562
|
+
cooling ? applyConfigHintsToCachedModels(name, prov, cooling, undefined, metadataModelIdCaseFold, captured.effectiveAlias, metadataConfigDir) : configured,
|
|
553
563
|
),
|
|
554
564
|
"degraded",
|
|
555
565
|
);
|
|
@@ -595,7 +605,7 @@ export async function fetchProviderModelsWithAuth(
|
|
|
595
605
|
const staleCursor = getStaleCached(name, authorityIdentity);
|
|
596
606
|
return observed(
|
|
597
607
|
withConfiguredRetention(
|
|
598
|
-
staleCursor ? applyConfigHintsToCachedModels(name, prov, staleCursor, undefined, metadataModelIdCaseFold, captured.effectiveAlias) : configured,
|
|
608
|
+
staleCursor ? applyConfigHintsToCachedModels(name, prov, staleCursor, undefined, metadataModelIdCaseFold, captured.effectiveAlias, metadataConfigDir) : configured,
|
|
599
609
|
),
|
|
600
610
|
"degraded",
|
|
601
611
|
);
|
|
@@ -613,7 +623,7 @@ export async function fetchProviderModelsWithAuth(
|
|
|
613
623
|
if (fresh) {
|
|
614
624
|
return observed(
|
|
615
625
|
withConfiguredRetention(
|
|
616
|
-
withVertexDefaultSeed(applyConfigHintsToCachedModels(name, prov, fresh, contextCap, metadataModelIdCaseFold, captured.effectiveAlias)),
|
|
626
|
+
withVertexDefaultSeed(applyConfigHintsToCachedModels(name, prov, fresh, contextCap, metadataModelIdCaseFold, captured.effectiveAlias, metadataConfigDir)),
|
|
617
627
|
),
|
|
618
628
|
"authoritative",
|
|
619
629
|
); // dedups Codex's frequent /v1/models polling within the TTL
|
|
@@ -625,7 +635,7 @@ export async function fetchProviderModelsWithAuth(
|
|
|
625
635
|
return observed(
|
|
626
636
|
withConfiguredRetention(
|
|
627
637
|
stale
|
|
628
|
-
? withVertexDefaultSeed(applyConfigHintsToCachedModels(name, prov, stale, contextCap, metadataModelIdCaseFold, captured.effectiveAlias))
|
|
638
|
+
? withVertexDefaultSeed(applyConfigHintsToCachedModels(name, prov, stale, contextCap, metadataModelIdCaseFold, captured.effectiveAlias, metadataConfigDir))
|
|
629
639
|
: failedDiscoveryConfigured,
|
|
630
640
|
),
|
|
631
641
|
"degraded",
|
|
@@ -633,7 +643,7 @@ export async function fetchProviderModelsWithAuth(
|
|
|
633
643
|
}
|
|
634
644
|
// The captured request predates any refresh, so a refreshing gather rebuilds it
|
|
635
645
|
// from the auth it resolved: the token and its origin, together.
|
|
636
|
-
const request = resolveAuth.kind === "refreshing"
|
|
646
|
+
const request = resolveAuth.kind === "refreshing" && name !== "anthropic2"
|
|
637
647
|
? captureModelsRequest(name, prov, auth.oauthApiBaseUrl)
|
|
638
648
|
: captured.request;
|
|
639
649
|
const url = request.url;
|
|
@@ -653,7 +663,7 @@ export async function fetchProviderModelsWithAuth(
|
|
|
653
663
|
const failedDiscoveryFallback = (
|
|
654
664
|
failure: ProviderModelDiscoveryFailure,
|
|
655
665
|
): { models: CatalogModel[]; fallback: "stale" | "configured"; shouldLog: boolean } => {
|
|
656
|
-
if (!isCurrentCacheGeneration()) {
|
|
666
|
+
if (!isCurrentCacheGeneration() || !maySendAnthropicDiscovery()) {
|
|
657
667
|
return {
|
|
658
668
|
models: withConfiguredRetention(failedDiscoveryConfigured),
|
|
659
669
|
fallback: "configured",
|
|
@@ -670,7 +680,7 @@ export async function fetchProviderModelsWithAuth(
|
|
|
670
680
|
return {
|
|
671
681
|
models: withConfiguredRetention(
|
|
672
682
|
stale
|
|
673
|
-
? withVertexDefaultSeed(applyConfigHintsToCachedModels(name, prov, stale, contextCap, metadataModelIdCaseFold, captured.effectiveAlias))
|
|
683
|
+
? withVertexDefaultSeed(applyConfigHintsToCachedModels(name, prov, stale, contextCap, metadataModelIdCaseFold, captured.effectiveAlias, metadataConfigDir))
|
|
674
684
|
: failedDiscoveryConfigured,
|
|
675
685
|
),
|
|
676
686
|
fallback: stale ? "stale" : "configured",
|
|
@@ -748,7 +758,7 @@ export async function fetchProviderModelsWithAuth(
|
|
|
748
758
|
return observed(models, "degraded");
|
|
749
759
|
}
|
|
750
760
|
if (antigravity) {
|
|
751
|
-
const
|
|
761
|
+
const upstream: CatalogModel[] = antigravity.map(model => ({
|
|
752
762
|
id: model.id,
|
|
753
763
|
provider: name,
|
|
754
764
|
// Only an exact discovered wire map proves a new model's selectable effort ladder.
|
|
@@ -760,8 +770,9 @@ export async function fetchProviderModelsWithAuth(
|
|
|
760
770
|
} : {}),
|
|
761
771
|
...(model.contextWindow ? { contextWindow: model.contextWindow } : {}),
|
|
762
772
|
...(model.inputModalities ? { inputModalities: model.inputModalities } : {}),
|
|
763
|
-
}
|
|
764
|
-
const
|
|
773
|
+
}));
|
|
774
|
+
const live = applyConfigHintsToCachedModels(name, prov, upstream, contextCap, metadataModelIdCaseFold, captured.effectiveAlias, metadataConfigDir);
|
|
775
|
+
const forCache = azureMetadata ? upstream : withConfiguredRetention(live, { retainComboTargets: false });
|
|
765
776
|
if (!isCurrentCacheGeneration()) {
|
|
766
777
|
return observed(withConfiguredRetention(configured), "degraded");
|
|
767
778
|
}
|
|
@@ -775,7 +786,7 @@ export async function fetchProviderModelsWithAuth(
|
|
|
775
786
|
return observed(withConfiguredRetention(configured), "degraded");
|
|
776
787
|
}
|
|
777
788
|
markProviderDiscoveryOk(name, live.length);
|
|
778
|
-
return observed(withConfiguredRetention(forCache, { warnDrops: true }), "authoritative");
|
|
789
|
+
return observed(withConfiguredRetention(azureMetadata ? live : forCache, { warnDrops: true }), "authoritative");
|
|
779
790
|
}
|
|
780
791
|
const googleAiStudio = effectiveGoogleMode(name, prov) === "ai-studio"
|
|
781
792
|
? extractGoogleAiStudioModelItems(bounded.value, discovery.maxModels)
|
|
@@ -814,7 +825,7 @@ export async function fetchProviderModelsWithAuth(
|
|
|
814
825
|
provider: prov,
|
|
815
826
|
}).catch(() => undefined)
|
|
816
827
|
: undefined;
|
|
817
|
-
const
|
|
828
|
+
const upstream: CatalogModel[] = items.map(m => {
|
|
818
829
|
const ownedBy = boundedOwnedBy(m.owned_by);
|
|
819
830
|
// Precedence: the authoritative /v1/models row wins; /api/show fills only metadata the
|
|
820
831
|
// models-API row does not carry. applyProviderConfigHints then applies explicit
|
|
@@ -830,22 +841,25 @@ export async function fetchProviderModelsWithAuth(
|
|
|
830
841
|
? { inputModalities: ["text", "image"] as string[] }
|
|
831
842
|
: {}),
|
|
832
843
|
};
|
|
833
|
-
return
|
|
844
|
+
return {
|
|
834
845
|
id: m.id,
|
|
835
846
|
provider: name,
|
|
836
847
|
...(ownedBy ? { owned_by: ownedBy } : {}),
|
|
837
848
|
...discoveredHints,
|
|
838
|
-
}
|
|
849
|
+
};
|
|
839
850
|
})
|
|
840
851
|
.filter(m => shouldExposeProviderModel(name, m.id));
|
|
852
|
+
const live = applyConfigHintsToCachedModels(name, prov, upstream, contextCap, metadataModelIdCaseFold, captured.effectiveAlias, metadataConfigDir);
|
|
841
853
|
// Capture the count BEFORE the alias/configured augmentation below pushes extra rows into
|
|
842
854
|
// `live`; otherwise configured entries would be reported as discovered ones.
|
|
843
855
|
const liveModelCount = live.length;
|
|
844
856
|
// Dated-release aliases + configured retention (compat allow-list, combo targets,
|
|
845
857
|
// Vertex default). Cache without combo retention so a later gather re-applies the
|
|
846
858
|
// current capture's retain set on read (warm-cache OCX-111 / #1308).
|
|
847
|
-
|
|
848
|
-
|
|
859
|
+
// Azure hints depend on the admitted config root. Keep only upstream evidence in the
|
|
860
|
+
// shared TTL/stale cache; every read reapplies metadata and retention for its own root.
|
|
861
|
+
const forCache = azureMetadata ? upstream : withConfiguredRetention(live, { retainComboTargets: false });
|
|
862
|
+
const returned = withConfiguredRetention(azureMetadata ? live : forCache, { warnDrops: true });
|
|
849
863
|
const droppedConfiguredIds = configured
|
|
850
864
|
.map(model => model.id)
|
|
851
865
|
.filter(id => !returned.some(model => model.id === id));
|
|
@@ -854,7 +868,7 @@ export async function fetchProviderModelsWithAuth(
|
|
|
854
868
|
`[opencodex] Provider model discovery for "${name}" returned an authoritative empty catalog; ${droppedConfiguredIds.length > 0 ? `dropping configured model ids: ${droppedConfiguredIds.join(", ")}` : "no models will be exposed"}.`,
|
|
855
869
|
);
|
|
856
870
|
}
|
|
857
|
-
if (!setCached(name, forCache, Date.now(), cacheGeneration)) {
|
|
871
|
+
if (!maySendAnthropicDiscovery() || !setCached(name, forCache, Date.now(), cacheGeneration)) {
|
|
858
872
|
return observed(withConfiguredRetention(configured), "degraded");
|
|
859
873
|
}
|
|
860
874
|
markProviderDiscoveryOk(name, liveModelCount);
|
|
@@ -2,7 +2,7 @@ import { projectAntigravitySelectedModels } from "../../providers/antigravity-ef
|
|
|
2
2
|
import { existsSync, readFileSync } from "node:fs";
|
|
3
3
|
import { join } from "node:path";
|
|
4
4
|
import { initializeConfigOwnership } from "../../lib/config-ownership";
|
|
5
|
-
import { getConfigDir, loadConfig, websocketsEnabled, withConfigMutationLockSync } from "../../config";
|
|
5
|
+
import { getConfigDir, loadConfig, ultraFastTierEnabled, websocketsEnabled, withConfigMutationLockSync } from "../../config";
|
|
6
6
|
import { shouldSyncCodexOnStart } from "../desired-state";
|
|
7
7
|
import { legacyCustomModelCatalogSlugs } from "../custom-model-catalog-migration";
|
|
8
8
|
import { getCodexHome } from "../paths";
|
|
@@ -54,7 +54,7 @@ import {
|
|
|
54
54
|
upstreamNativeEntry,
|
|
55
55
|
} from "./metadata";
|
|
56
56
|
import { trustedAccountBoundNativeCatalogSlug } from "./account-models";
|
|
57
|
-
import { bundledCatalogCacheState,
|
|
57
|
+
import { bundledCatalogCacheState, bundledCodexCatalogSnapshot, loadBundledCodexCatalogAsync } from "./bundled";
|
|
58
58
|
import { isMultiAgentV2Enabled } from "../features";
|
|
59
59
|
import { clampCatalogModelsToCodexSupport } from "./effort";
|
|
60
60
|
import { suppressedSyntheticMaxCatalogSlugs } from "./model-hints";
|
|
@@ -155,7 +155,7 @@ function optionalFileBytes(path: string): string | null {
|
|
|
155
155
|
}
|
|
156
156
|
|
|
157
157
|
function loadCatalogForRetainedSync(path: string): RawCatalog | null {
|
|
158
|
-
const bundled = isDefaultCatalogPath(path) ?
|
|
158
|
+
const bundled = isDefaultCatalogPath(path) ? bundledCodexCatalogSnapshot() : null;
|
|
159
159
|
if (bundled) return JSON.parse(JSON.stringify(bundled)) as RawCatalog;
|
|
160
160
|
const active = readCatalog(path);
|
|
161
161
|
// A valid configured custom file remains the content authority even when it has no bare native
|
|
@@ -508,6 +508,7 @@ function writeRetainedCatalogSync({
|
|
|
508
508
|
}).filter(entry => trustedAccountBoundNativeCatalogSlug(entry) !== undefined)
|
|
509
509
|
: [];
|
|
510
510
|
catalog.models = mergeCatalogEntriesFromObservedState({
|
|
511
|
+
ultraFastTier: ultraFastTierEnabled(config),
|
|
511
512
|
modelPickerOrder,
|
|
512
513
|
accountSelectors,
|
|
513
514
|
catalogModels: catalogModelsForMerge,
|
|
@@ -542,7 +543,7 @@ function writeRetainedCatalogSync({
|
|
|
542
543
|
},
|
|
543
544
|
});
|
|
544
545
|
applyNativeAccessPrograms(catalog.models, modelEntitlements, accountTargets);
|
|
545
|
-
clampCatalogModelsToCodexSupport(catalog.models);
|
|
546
|
+
clampCatalogModelsToCodexSupport(catalog.models, { observedCatalog: bundledCodexCatalogSnapshot() });
|
|
546
547
|
finalizeAutoReviewModelOverride(catalog.models, catalogModelsForMerge, config);
|
|
547
548
|
// Last mutation before serialization; see `enforceCatalogSlugUniqueness` for why the ordering
|
|
548
549
|
// against the effort clamp is load-bearing rather than cosmetic.
|
|
@@ -623,6 +624,8 @@ export async function syncCatalogModels(
|
|
|
623
624
|
await resolvePendingInitialModelSelection(config);
|
|
624
625
|
}
|
|
625
626
|
const owningCodexHome = getCodexHome();
|
|
627
|
+
// Settle before reading content and its matching evidence; no pre-refresh catalog is reused.
|
|
628
|
+
await loadBundledCodexCatalogAsync();
|
|
626
629
|
const preflightRead = readRetainedCatalogSync(config);
|
|
627
630
|
if (preflightRead === null) {
|
|
628
631
|
return {
|
|
@@ -643,7 +646,6 @@ export async function syncCatalogModels(
|
|
|
643
646
|
// The persisted runtime selection is covered by the filesystem evidence above
|
|
644
647
|
// rather than by a process epoch; see `retainedCatalogProcessEvidence` for why
|
|
645
648
|
// the in-memory runtime memo cannot be baselined honestly from this path.
|
|
646
|
-
loadBundledCodexCatalog();
|
|
647
649
|
const prepared: RetainedCatalogSyncRead = {
|
|
648
650
|
...preflightRead,
|
|
649
651
|
evidence: retainedCatalogSyncEvidence(config, preflightRead.catalogPath, preflightRead.catalog),
|
|
@@ -347,6 +347,7 @@ async function gatherRoutedModelsUncached(
|
|
|
347
347
|
lists.flat(),
|
|
348
348
|
config,
|
|
349
349
|
capture.openAiApiPolicy,
|
|
350
|
+
activeProviders.find(provider => provider.name === OPENAI_API_PROVIDER_ID)?.metadataConfigDir,
|
|
350
351
|
);
|
|
351
352
|
const apiProvider = activeProviders.find(provider => provider.name === OPENAI_API_PROVIDER_ID);
|
|
352
353
|
// Trusted reconstruction replaces whole rows, including the earlier Fast hints.
|
|
@@ -363,12 +364,16 @@ async function gatherRoutedModelsUncached(
|
|
|
363
364
|
const metadataModelIdCaseFoldByProvider = new Map(
|
|
364
365
|
activeProviders.map(provider => [provider.name, provider.metadataModelIdCaseFold]),
|
|
365
366
|
);
|
|
367
|
+
const metadataConfigDirByProvider = new Map(
|
|
368
|
+
activeProviders.map(provider => [provider.name, provider.metadataConfigDir]),
|
|
369
|
+
);
|
|
366
370
|
const all = augmentRoutedModelsWithMetadata(
|
|
367
371
|
apiAugmented,
|
|
368
372
|
activeProviders.map(provider => provider.name),
|
|
369
373
|
config.providers,
|
|
370
374
|
config,
|
|
371
375
|
metadataModelIdCaseFoldByProvider,
|
|
376
|
+
metadataConfigDirByProvider,
|
|
372
377
|
)
|
|
373
378
|
// Drop image/video generation models (e.g. Grok image/video) by default. Cursor's static catalog
|
|
374
379
|
// intentionally mirrors Cursor's public model table, including Gemini image preview, so the
|
|
@@ -511,6 +516,7 @@ async function gatherRoutedModelsUncached(
|
|
|
511
516
|
providerContextCap(config, target.provider),
|
|
512
517
|
nativeAliasFallback,
|
|
513
518
|
metadataModelIdCaseFoldByProvider.get(target.provider),
|
|
519
|
+
metadataConfigDirByProvider.get(target.provider),
|
|
514
520
|
))
|
|
515
521
|
.filter((member): member is CatalogModel => member !== undefined);
|
|
516
522
|
const derived = deriveComboCatalogModel(id, combo, members);
|
|
@@ -591,7 +597,7 @@ async function gatherRoutedModelsUncached(
|
|
|
591
597
|
id: cm.modelId,
|
|
592
598
|
provider: cm.provider,
|
|
593
599
|
...(nativeAliasMaxOutputTokens !== undefined ? { maxOutputTokens: nativeAliasMaxOutputTokens } : {}),
|
|
594
|
-
}, cm.modelId, metadataModelIdCaseFoldByProvider.get(cm.provider))
|
|
600
|
+
}, cm.modelId, metadataModelIdCaseFoldByProvider.get(cm.provider), metadataConfigDirByProvider.get(cm.provider))
|
|
595
601
|
: nativeAliasMaxOutputTokens;
|
|
596
602
|
const configuredAutoCompact = configuredAutoCompactTokenLimit(rawProvider, cm.modelId);
|
|
597
603
|
const customAutoCompactTokenLimit = codexForwardNativeCapabilityAlias
|
|
@@ -827,6 +833,7 @@ function augmentRoutedModelsWithCapturedOpenAiApiRows(
|
|
|
827
833
|
models: CatalogModel[],
|
|
828
834
|
config: OcxConfig,
|
|
829
835
|
policy: CatalogTrustedOpenAiApiPolicySnapshot,
|
|
836
|
+
metadataConfigDir?: string,
|
|
830
837
|
): CatalogModel[] {
|
|
831
838
|
if (policy.state !== "captured" || !policy.models) return models;
|
|
832
839
|
const configured = config.providers[OPENAI_API_PROVIDER_ID];
|
|
@@ -862,6 +869,8 @@ function augmentRoutedModelsWithCapturedOpenAiApiRows(
|
|
|
862
869
|
? { provider: OPENAI_API_PROVIDER_ID, id, maxOutputTokens: policy.modelMaxOutputTokens[id] }
|
|
863
870
|
: existingById.get(id) ?? { provider: OPENAI_API_PROVIDER_ID, id },
|
|
864
871
|
policy.virtualModels?.[id]?.wireModelId ?? id,
|
|
872
|
+
undefined,
|
|
873
|
+
metadataConfigDir,
|
|
865
874
|
);
|
|
866
875
|
return {
|
|
867
876
|
provider: OPENAI_API_PROVIDER_ID,
|
|
@@ -920,6 +929,7 @@ export function augmentRoutedModelsWithMetadata(
|
|
|
920
929
|
providers?: Record<string, OcxProviderConfig>,
|
|
921
930
|
caps?: Pick<OcxConfig, "providerContextCaps">,
|
|
922
931
|
metadataModelIdCaseFoldByProvider?: ReadonlyMap<string, boolean>,
|
|
932
|
+
metadataConfigDirByProvider?: ReadonlyMap<string, string>,
|
|
923
933
|
): CatalogModel[] {
|
|
924
934
|
const out = [...models];
|
|
925
935
|
const indexByKey = new Map(out.map((model, index) => [`${model.provider}/${model.id}`, index]));
|
|
@@ -947,6 +957,8 @@ export function augmentRoutedModelsWithMetadata(
|
|
|
947
957
|
seeded,
|
|
948
958
|
contextCap,
|
|
949
959
|
metadataModelIdCaseFoldByProvider?.get(provider),
|
|
960
|
+
undefined,
|
|
961
|
+
metadataConfigDirByProvider?.get(provider),
|
|
950
962
|
)
|
|
951
963
|
: seeded;
|
|
952
964
|
continue;
|
|
@@ -969,6 +981,8 @@ export function augmentRoutedModelsWithMetadata(
|
|
|
969
981
|
model,
|
|
970
982
|
contextCap,
|
|
971
983
|
metadataModelIdCaseFoldByProvider?.get(provider),
|
|
984
|
+
undefined,
|
|
985
|
+
metadataConfigDirByProvider?.get(provider),
|
|
972
986
|
)
|
|
973
987
|
: {}),
|
|
974
988
|
});
|
|
@@ -34,10 +34,9 @@ export async function refreshCatalogAutoRefreshSources(
|
|
|
34
34
|
current: () => boolean,
|
|
35
35
|
): Promise<void> {
|
|
36
36
|
// Runtime selection also supplies the roster's trusted client version after an upgrade.
|
|
37
|
-
await bestEffortSource(async active => {
|
|
38
|
-
const {
|
|
39
|
-
if (active() && current())
|
|
40
|
-
// The synchronous loader bounds its selected-runtime subprocess probes itself.
|
|
37
|
+
await bestEffortSource(async (active, signal) => {
|
|
38
|
+
const { loadBundledCodexCatalogAsync } = await import("./catalog/bundled");
|
|
39
|
+
if (active() && current()) await loadBundledCodexCatalogAsync({}, () => active() && current(), signal);
|
|
41
40
|
});
|
|
42
41
|
if (!current()) return;
|
|
43
42
|
await bestEffortSource(async active => {
|
|
@@ -50,6 +50,14 @@ let generation = 0;
|
|
|
50
50
|
/** setInterval does not skip a firing while the previous callback is still awaiting. */
|
|
51
51
|
let inFlight = false;
|
|
52
52
|
|
|
53
|
+
/** Refreshes already-connected clients after a changed catalog; owned by the server lifecycle. */
|
|
54
|
+
export type CatalogChangedClientFanout =
|
|
55
|
+
(isCurrent: () => boolean) => Promise<ReadonlyArray<{ readonly ok: boolean }>>;
|
|
56
|
+
let clientFanout: CatalogChangedClientFanout | null = null;
|
|
57
|
+
export function setCatalogAutoRefreshClientFanout(fanout: CatalogChangedClientFanout | null): void {
|
|
58
|
+
clientFanout = fanout;
|
|
59
|
+
}
|
|
60
|
+
|
|
53
61
|
/** Read only a regular file, with a byte limit even if it grows after the stat. */
|
|
54
62
|
function readBoundedRegularFile(path: string, maxBytes: number): string | null {
|
|
55
63
|
let fd: number | undefined;
|
|
@@ -259,6 +267,17 @@ async function tick(): Promise<void> {
|
|
|
259
267
|
? "[catalog-auto-refresh] served model set changed; running Codex sessions keep the old list until restarted (ocx sync --restart-codex)"
|
|
260
268
|
: "[catalog-auto-refresh] served model set changed");
|
|
261
269
|
}
|
|
270
|
+
const fanout = clientFanout;
|
|
271
|
+
if (outcome.changed && fanout) {
|
|
272
|
+
const current = () => entryGeneration === generation;
|
|
273
|
+
try {
|
|
274
|
+
const failed = (await fanout(current)).filter(result => !result.ok).length;
|
|
275
|
+
// Outcomes can contain private paths and reasons; only the failure count leaves this hook.
|
|
276
|
+
if (current() && failed > 0) console.warn(`[catalog-auto-refresh] ${failed} client integration(s) were not refreshed; ocx sync retries them`);
|
|
277
|
+
} catch {
|
|
278
|
+
if (current()) console.warn("[catalog-auto-refresh] client integrations were not refreshed; ocx sync retries them");
|
|
279
|
+
}
|
|
280
|
+
}
|
|
262
281
|
} catch {
|
|
263
282
|
// A failed refresh is not an error worth surfacing: the next tick tries again.
|
|
264
283
|
} finally {
|