@bitkyc08/opencodex 2.81.0 → 2.83.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/bin/ocx.mjs +166 -73
- package/gui/dist/assets/App-Ba8uG696.js +54 -0
- package/gui/dist/assets/{Tray-EwAOsP0S.js → Tray-IImbNPRy.js} +1 -1
- package/gui/dist/assets/{index-Brk6F3fn.css → index-BAbcj51J.css} +1 -1
- package/gui/dist/assets/{index-RsoaAxXY.js → index-BHRZdJuv.js} +13 -13
- package/gui/dist/assets/{quota-summary-D2lN8tDm.js → quota-summary-DiJO6sYY.js} +1 -1
- package/gui/dist/index.html +2 -2
- package/package.json +1 -1
- package/src/adapters/anthropic.ts +1 -1
- package/src/adapters/cursor/catalog.ts +2 -2
- package/src/adapters/cursor/effort-map.ts +1 -1
- package/src/adapters/devin/live-models.ts +2 -2
- package/src/adapters/google-truncation.ts +22 -0
- package/src/adapters/google.ts +7 -3
- package/src/adapters/ollama-native.ts +18 -14
- package/src/adapters/openai-responses/compaction-search-history.ts +109 -0
- package/src/adapters/openai-responses/passthrough.ts +11 -4
- package/src/adapters/openai-responses/plaintext-reasoning-notice.ts +85 -0
- package/src/adapters/openai-responses/reasoning.ts +11 -1
- package/src/adapters/openai-responses/tool-output-recovery.ts +20 -0
- package/src/bridge/errors.ts +7 -1
- package/src/claude/agents-inject.ts +14 -3
- package/src/claude/context-windows.ts +22 -20
- package/src/claude/desktop-3p.ts +88 -12
- package/src/claude/desktop-picker.ts +1 -1
- package/src/claude/desktop-profile.ts +2 -1
- package/src/claude/gateway-cache.ts +18 -1
- package/src/claude/inbound.ts +77 -3
- package/src/claude/intercept/cli-catalog.ts +3 -0
- package/src/claude/intercept/picker-ca-persistence.ts +7 -6
- 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-auth.ts +20 -12
- package/src/cli/agent.ts +9 -5
- package/src/cli/aside-profile-recovery.ts +33 -0
- package/src/cli/capabilities-base.ts +5 -5
- package/src/cli/capabilities-integrations.ts +2 -2
- package/src/cli/cli-path-diagnostics.ts +132 -0
- package/src/cli/desktop-runtime-guidance.ts +65 -0
- package/src/cli/dispatch.ts +5 -0
- package/src/cli/doctor.ts +16 -3
- package/src/cli/index.ts +14 -9
- package/src/cli/integration-aside-sync.ts +2 -1
- package/src/cli/integrations.ts +16 -3
- package/src/cli/resolve.ts +26 -3
- 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/model-metadata.ts +16 -0
- package/src/clients/config-export/zcode-store.ts +46 -11
- package/src/clients/config-export/zcode.ts +3 -5
- package/src/clients/config-export.ts +1 -1
- package/src/clients/lazycodex.ts +1 -1
- package/src/clients/omo-role-models.ts +32 -7
- package/src/codex/auth-api/account-selection.ts +107 -0
- package/src/codex/auth-api/pool-mode-gate.ts +4 -5
- package/src/codex/auth-api/routes.ts +10 -49
- package/src/codex/auth-context.ts +28 -4
- package/src/codex/autostart-health.ts +12 -3
- package/src/codex/catalog/build-entries.ts +18 -0
- package/src/codex/catalog/bundled.ts +155 -26
- package/src/codex/catalog/combo-member.ts +3 -2
- package/src/codex/catalog/effort.ts +26 -5
- package/src/codex/catalog/gather-capture.ts +5 -0
- package/src/codex/catalog/model-hints.ts +15 -8
- package/src/codex/catalog/model-visibility.ts +3 -1
- package/src/codex/catalog/native-models.ts +1 -1
- package/src/codex/catalog/operator-tiers.ts +38 -0
- package/src/codex/catalog/provider-models.ts +68 -35
- 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/convergence.ts +2 -1
- package/src/codex/desktop-app/darwin.ts +1 -1
- package/src/codex/desktop-app/handoff.ts +1 -1
- package/src/codex/desktop-app/linux.ts +1 -1
- package/src/codex/desktop-app/lock.ts +1 -1
- package/src/codex/desktop-app/types.ts +1 -1
- package/src/codex/desktop-app/windows.ts +1 -1
- package/src/codex/desktop-app-restart.ts +1 -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/main-account.ts +6 -7
- 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-service-exchange.ts +281 -0
- package/src/combos/jev.ts +34 -220
- package/src/config/atomic-write.ts +1 -1
- package/src/config/codex-ws-reuse-setting.ts +10 -0
- package/src/config/live-reconcile.ts +17 -0
- package/src/config/load-degrade.ts +8 -0
- package/src/config/rebase-provenance.ts +11 -0
- package/src/config/schema/config-schema.ts +4 -0
- package/src/generated/compatibility-version.json +375 -227
- package/src/generated/model-metadata.ts +2 -2
- package/src/grok/inject.ts +276 -206
- package/src/grok/reset-coupon-ledger.ts +223 -57
- package/src/grok/reset-coupons.ts +13 -6
- package/src/grok/sync.ts +2 -1
- package/src/images/loop.ts +29 -11
- package/src/integrations/aside-profiles.ts +10 -3
- package/src/integrations/catalog-refresh.ts +18 -2
- package/src/integrations/cursor-detect.ts +1 -1
- package/src/integrations/writer.ts +9 -3
- 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/errors.ts +25 -0
- package/src/lib/redact.ts +2 -2
- package/src/lib/request-execution-budget.ts +8 -0
- 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/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/oauth/anthropic-account-refusal.ts +39 -1
- package/src/oauth/anthropic-routing.ts +1 -1
- package/src/oauth/anthropic-send-ownership.ts +3 -3
- package/src/oauth/chatgpt.ts +113 -41
- package/src/oauth/index.ts +7 -3
- package/src/oauth/meta-muse-device.ts +1 -1
- package/src/oauth/store.ts +1 -1
- package/src/oauth/types.ts +1 -1
- package/src/providers/anthropic-fast.ts +1 -1
- package/src/providers/anthropic-reset-grant-ledger.ts +1 -1
- package/src/providers/azure-model-metadata.ts +115 -0
- package/src/providers/derive.ts +21 -0
- package/src/providers/devin-cli-authmode-migration.ts +1 -1
- package/src/providers/devin-provider-merge-migration.ts +1 -1
- package/src/providers/github-copilot-auto.ts +169 -0
- package/src/providers/model-presets.ts +1 -1
- package/src/providers/muse-subscription-usage.ts +1 -1
- package/src/providers/quota/vendor-probes-key.ts +127 -17
- package/src/providers/quota.ts +1 -1
- package/src/providers/registry/entries-core.ts +6 -6
- package/src/providers/registry/entries-extended.ts +4 -0
- package/src/providers/registry/model-seeds.ts +3 -3
- package/src/providers/xai-fast-model.ts +1 -1
- package/src/responses/reasoning-envelope.ts +29 -1
- package/src/responses/reasoning-replay-cache.ts +17 -1
- package/src/responses/spill-store.ts +15 -2
- package/src/responses/state/metrics.ts +8 -0
- package/src/responses/state/spill-failure.ts +12 -0
- package/src/responses/state/spill-queue.ts +12 -5
- package/src/responses/state.ts +18 -10
- package/src/responses/task-input.ts +17 -0
- package/src/server/background-lifecycle.ts +27 -0
- package/src/server/chat-completions.ts +1 -0
- package/src/server/chat-native.ts +28 -12
- package/src/server/claude-messages.ts +43 -6
- package/src/server/inbound-body-admission.ts +25 -7
- package/src/server/index/claude-intercept-lifecycle.ts +3 -1
- package/src/server/index/link-listener.ts +30 -17
- package/src/server/index/serve-options.ts +18 -4
- package/src/server/index/spend-ledger-lifecycle.ts +2 -1
- package/src/server/index/startup-warnings.ts +19 -0
- package/src/server/index.ts +2 -1
- package/src/server/lifecycle.ts +31 -4
- package/src/server/management/agent-settings-routes.ts +93 -32
- 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 +59 -8
- package/src/server/management/context.ts +2 -2
- package/src/server/management/grok-coupon-routes.ts +277 -52
- package/src/server/management/link-routes.ts +42 -20
- package/src/server/management/route-registry.ts +2 -2
- package/src/server/management/shared.ts +3 -3
- package/src/server/messages-native-oauth.ts +9 -8
- package/src/server/messages-native.ts +49 -13
- package/src/server/messages-response-headers.ts +14 -0
- package/src/server/relay-eager.ts +2 -0
- package/src/server/relay.ts +18 -7
- package/src/server/request-log-conversation.ts +48 -5
- package/src/server/request-log-failure-attribution.ts +3 -0
- package/src/server/request-log-terminal-status.ts +186 -0
- package/src/server/request-log.ts +15 -89
- package/src/server/responses/adapter-continuation.ts +11 -3
- package/src/server/responses/adapter-dispatch.ts +99 -19
- 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 +3 -2
- package/src/server/responses/core-codex-account.ts +22 -1
- package/src/server/responses/core-combo-native.ts +20 -3
- package/src/server/responses/core-combo.ts +22 -14
- package/src/server/responses/core-lifetime.ts +3 -36
- package/src/server/responses/core-opaque-recovery.ts +5 -5
- package/src/server/responses/core-options.ts +5 -0
- package/src/server/responses/core-replay.ts +73 -0
- package/src/server/responses/core.ts +9 -9
- package/src/server/responses/empty-completion-guard.ts +18 -2
- package/src/server/responses/fetch-helpers.ts +26 -3
- package/src/server/responses/jev-model-invoke.ts +1 -1
- package/src/server/responses/passthrough-delivery.ts +24 -2
- package/src/server/responses/passthrough-dispatch.ts +134 -62
- package/src/server/responses/passthrough-execution.ts +3 -3
- package/src/server/responses/request-prepare.ts +4 -0
- package/src/server/responses/request-send-budget.ts +112 -49
- package/src/server/responses/request-transport.ts +125 -5
- package/src/server/responses/response-effects.ts +1 -0
- package/src/server/responses/run-turn-execution.ts +15 -5
- package/src/server/responses/sidecar-execution.ts +30 -16
- package/src/server/responses/sidecar-send-budget.ts +58 -0
- package/src/server/responses/spend-storage-error.ts +33 -0
- package/src/server/responses/ws-upstream.ts +19 -6
- package/src/server/startup-health-cache.ts +2 -1
- package/src/server/workflow-refusal.ts +3 -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/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/storage/policy-job.ts +5 -1
- package/src/storage/policy-worker.ts +3 -1
- package/src/storage/policy.ts +9 -0
- package/src/types/config.ts +21 -0
- package/src/types/request.ts +10 -0
- package/src/types/wire.ts +1 -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/expected-prices.ts +1 -1
- package/src/web-search/loop.ts +5 -2
- package/gui/dist/assets/App-7yhoys8a.js +0 -54
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
import { fetchCopilotAutoModels, copilotPickerModels, copilotRequiresAuto } from "../../providers/github-copilot-auto";
|
|
2
|
+
import { resolveGithubCopilotTransport } from "../../providers/github-copilot-transport";
|
|
3
|
+
import { resolveCopilotApiBaseUrl } from "../../oauth/github-copilot";
|
|
1
4
|
import { isAnthropicOAuthInstance } from "../../providers/anthropic-instance";
|
|
2
5
|
import { effectiveProviderAlias, effectiveProviderAliasDecision } from "../../providers/default-aliases";
|
|
3
6
|
import { initialModelSelectionPending } from "../../providers/initial-model-selection";
|
|
@@ -41,6 +44,7 @@ import { CODEX_REASONING_LEVELS, codexEffortRank, configuredReasoningEfforts, mo
|
|
|
41
44
|
import { isModelVisionSidecarConsumer } from "../../vision/eligibility";
|
|
42
45
|
import { getModelMetadata, getModelMetadataCaseInsensitive, listModelMetadata, resolveMetadataProvider, type ModelMetadata } from "../../generated/model-metadata";
|
|
43
46
|
import { enrichProviderFromRegistry, shouldCaseFoldMetadataModelId } from "../../providers/derive";
|
|
47
|
+
import { isAzureModelMetadataDestination, refreshAzureModelMetadata } from "../../providers/azure-model-metadata";
|
|
44
48
|
import {
|
|
45
49
|
captureFastPolicyAuthority,
|
|
46
50
|
fastPolicyForModel,
|
|
@@ -163,13 +167,15 @@ export function observedModelsAuthResolver(
|
|
|
163
167
|
},
|
|
164
168
|
};
|
|
165
169
|
}
|
|
170
|
+
/** Project captured discovery through config hints and retention; Auto-only Copilot exposes only Auto. */
|
|
166
171
|
export async function fetchProviderModelsWithAuth(
|
|
167
172
|
captured: CapturedProviderGather,
|
|
168
173
|
ttlMs: number,
|
|
169
174
|
contextCap: number | undefined,
|
|
170
175
|
resolveAuth: ModelsAuthResolver,
|
|
171
176
|
): Promise<ProviderModelsResult> {
|
|
172
|
-
const { name, provider: prov, discovery, metadataModelIdCaseFold } = captured;
|
|
177
|
+
const { name, provider: prov, discovery, metadataModelIdCaseFold, metadataConfigDir } = captured;
|
|
178
|
+
const azureMetadata = isAzureModelMetadataDestination(prov.baseUrl);
|
|
173
179
|
const observed = (
|
|
174
180
|
models: CatalogModel[],
|
|
175
181
|
state: CatalogGatherProviderModelOutcome["state"],
|
|
@@ -185,6 +191,7 @@ export async function fetchProviderModelsWithAuth(
|
|
|
185
191
|
const anthropicSelection = isAnthropicOAuthInstance(name) && prov.authMode === "oauth" && mayResolveModelsOAuth(name, prov)
|
|
186
192
|
? captureOAuthAccountSelection(name) : null;
|
|
187
193
|
if (prov.authMode === "forward") return observed([], "authoritative"); // ChatGPT backend has no /models
|
|
194
|
+
if (azureMetadata) await refreshAzureModelMetadata(prov.baseUrl, metadataConfigDir);
|
|
188
195
|
const seedVertexDefault = prov.adapter === "google"
|
|
189
196
|
&& prov.googleMode === "vertex"
|
|
190
197
|
&& (prov.models?.length ?? 0) === 0
|
|
@@ -203,7 +210,7 @@ export async function fetchProviderModelsWithAuth(
|
|
|
203
210
|
const configured: CatalogModel[] = configuredIds.map(id => ({
|
|
204
211
|
id,
|
|
205
212
|
provider: name,
|
|
206
|
-
...catalogHintsFromProviderConfig(name, prov, id, contextCap, metadataModelIdCaseFold, captured.effectiveAlias),
|
|
213
|
+
...catalogHintsFromProviderConfig(name, prov, id, contextCap, metadataModelIdCaseFold, captured.effectiveAlias, metadataConfigDir),
|
|
207
214
|
}));
|
|
208
215
|
const withConfiguredRetention = (
|
|
209
216
|
models: CatalogModel[],
|
|
@@ -219,6 +226,7 @@ export async function fetchProviderModelsWithAuth(
|
|
|
219
226
|
seedVertexDefault,
|
|
220
227
|
retainComboTargets: options?.retainComboTargets,
|
|
221
228
|
metadataModelIdCaseFold,
|
|
229
|
+
metadataConfigDir,
|
|
222
230
|
});
|
|
223
231
|
if (
|
|
224
232
|
options?.warnDrops === true
|
|
@@ -251,7 +259,7 @@ export async function fetchProviderModelsWithAuth(
|
|
|
251
259
|
}
|
|
252
260
|
return observed(ids.map(id => {
|
|
253
261
|
const hints = catalogHintsFromProviderConfig(name, prov, id, contextCap,
|
|
254
|
-
metadataModelIdCaseFold, captured.effectiveAlias);
|
|
262
|
+
metadataModelIdCaseFold, captured.effectiveAlias, metadataConfigDir);
|
|
255
263
|
const observedWindow = kiroObservedContextWindow(id);
|
|
256
264
|
return { id, provider: name, ...hints,
|
|
257
265
|
...(observedWindow !== undefined
|
|
@@ -278,6 +286,27 @@ export async function fetchProviderModelsWithAuth(
|
|
|
278
286
|
: { apiKey: await resolveModelsAuthToken(name, prov), observed: false }
|
|
279
287
|
: resolveAuth.resolve(name, prov));
|
|
280
288
|
const apiKey = auth.apiKey;
|
|
289
|
+
if (name === "github-copilot" && apiKey) {
|
|
290
|
+
const transport = resolveGithubCopilotTransport({ ...prov, apiKey }, prov.authMode === "oauth"
|
|
291
|
+
? resolveCopilotApiBaseUrl(auth.oauthApiBaseUrl) : undefined);
|
|
292
|
+
try {
|
|
293
|
+
const models = await fetchCopilotAutoModels(transport, AbortSignal.timeout(8_000), undefined, ttlMs);
|
|
294
|
+
const picker = copilotPickerModels(prov, models).map(/** Apply configured hints to the permission-filtered account catalog without changing upstream metadata. */
|
|
295
|
+
model => applyProviderConfigHints(name, prov, {
|
|
296
|
+
id: model.id, provider: name,
|
|
297
|
+
...catalogHintsFromModelsApiItem(name, model as ProviderModelsApiItem),
|
|
298
|
+
}, contextCap, metadataModelIdCaseFold, captured.effectiveAlias));
|
|
299
|
+
if (!isCurrentCacheGeneration()) return observed(configured, "degraded");
|
|
300
|
+
markProviderDiscoveryOk(name, picker.length);
|
|
301
|
+
// Retain callable manual/combo selectors, but do not advertise named selection
|
|
302
|
+
// for an Auto-only account even when its saved configuration still contains it.
|
|
303
|
+
return observed(copilotRequiresAuto(prov, models)
|
|
304
|
+
? picker : withConfiguredRetention(picker, { warnDrops: true }), "authoritative");
|
|
305
|
+
} catch {
|
|
306
|
+
if (isCurrentCacheGeneration()) markProviderDiscoveryFailed(name, { reason: "provider" });
|
|
307
|
+
return observed(configured, "degraded");
|
|
308
|
+
}
|
|
309
|
+
}
|
|
281
310
|
const maySendAnthropicDiscovery = () => {
|
|
282
311
|
if (!isAnthropicOAuthInstance(name) || prov.authMode !== "oauth") return true;
|
|
283
312
|
if (!mayResolveModelsOAuth(name, prov)) return false;
|
|
@@ -296,7 +325,7 @@ export async function fetchProviderModelsWithAuth(
|
|
|
296
325
|
: [{
|
|
297
326
|
id: prov.defaultModel,
|
|
298
327
|
provider: name,
|
|
299
|
-
...catalogHintsFromProviderConfig(name, prov, prov.defaultModel, contextCap, metadataModelIdCaseFold, captured.effectiveAlias),
|
|
328
|
+
...catalogHintsFromProviderConfig(name, prov, prov.defaultModel, contextCap, metadataModelIdCaseFold, captured.effectiveAlias, metadataConfigDir),
|
|
300
329
|
}];
|
|
301
330
|
const vertexDefaultSeed = seedVertexDefault ? configured[0] : undefined;
|
|
302
331
|
const withVertexDefaultSeed = (models: CatalogModel[]): CatalogModel[] => (
|
|
@@ -318,13 +347,13 @@ export async function fetchProviderModelsWithAuth(
|
|
|
318
347
|
const fresh = getFreshCached(name, ttlMs, Date.now(), authorityIdentity);
|
|
319
348
|
if (fresh) {
|
|
320
349
|
return observed(withConfiguredRetention(
|
|
321
|
-
applyConfigHintsToCachedModels(name, prov, fresh, contextCap, metadataModelIdCaseFold, captured.effectiveAlias),
|
|
350
|
+
applyConfigHintsToCachedModels(name, prov, fresh, contextCap, metadataModelIdCaseFold, captured.effectiveAlias, metadataConfigDir),
|
|
322
351
|
), "authoritative");
|
|
323
352
|
}
|
|
324
353
|
const scopedStale = getStaleCached(name, authorityIdentity);
|
|
325
354
|
if (isModelsFetchCoolingDown(name, undefined, undefined, authorityIdentity) && scopedStale) {
|
|
326
355
|
return observed(withConfiguredRetention(
|
|
327
|
-
applyConfigHintsToCachedModels(name, prov, scopedStale, contextCap, metadataModelIdCaseFold, captured.effectiveAlias),
|
|
356
|
+
applyConfigHintsToCachedModels(name, prov, scopedStale, contextCap, metadataModelIdCaseFold, captured.effectiveAlias, metadataConfigDir),
|
|
328
357
|
), "degraded");
|
|
329
358
|
}
|
|
330
359
|
const live = await fetchCodeBuddyModels(profile, apiKey);
|
|
@@ -332,7 +361,7 @@ export async function fetchProviderModelsWithAuth(
|
|
|
332
361
|
const discovered = live.models.map(id => ({
|
|
333
362
|
id,
|
|
334
363
|
provider: name,
|
|
335
|
-
...catalogHintsFromProviderConfig(name, prov, id, contextCap, metadataModelIdCaseFold, captured.effectiveAlias),
|
|
364
|
+
...catalogHintsFromProviderConfig(name, prov, id, contextCap, metadataModelIdCaseFold, captured.effectiveAlias, metadataConfigDir),
|
|
336
365
|
}));
|
|
337
366
|
const forCache = withConfiguredRetention(discovered, { retainComboTargets: false });
|
|
338
367
|
if (!setCached(name, forCache, Date.now(), cacheGeneration, authorityIdentity)) {
|
|
@@ -348,7 +377,7 @@ export async function fetchProviderModelsWithAuth(
|
|
|
348
377
|
}
|
|
349
378
|
const stale = getStaleCached(name, authorityIdentity);
|
|
350
379
|
return observed(withConfiguredRetention(
|
|
351
|
-
stale ? applyConfigHintsToCachedModels(name, prov, stale, contextCap, metadataModelIdCaseFold, captured.effectiveAlias) : configured,
|
|
380
|
+
stale ? applyConfigHintsToCachedModels(name, prov, stale, contextCap, metadataModelIdCaseFold, captured.effectiveAlias, metadataConfigDir) : configured,
|
|
352
381
|
), "degraded");
|
|
353
382
|
}
|
|
354
383
|
if (name === "zed" && prov.adapter === "zed") {
|
|
@@ -361,14 +390,14 @@ export async function fetchProviderModelsWithAuth(
|
|
|
361
390
|
const cached = getFreshCached(name, ttlMs, Date.now(), authorityIdentity);
|
|
362
391
|
if (cached) {
|
|
363
392
|
return observed(
|
|
364
|
-
withConfiguredRetention(applyConfigHintsToCachedModels(name, prov, cached, contextCap, metadataModelIdCaseFold, captured.effectiveAlias)),
|
|
393
|
+
withConfiguredRetention(applyConfigHintsToCachedModels(name, prov, cached, contextCap, metadataModelIdCaseFold, captured.effectiveAlias, metadataConfigDir)),
|
|
365
394
|
"authoritative",
|
|
366
395
|
);
|
|
367
396
|
}
|
|
368
397
|
const stale = getStaleCached(name, authorityIdentity);
|
|
369
398
|
if (isModelsFetchCoolingDown(name, undefined, undefined, authorityIdentity) && stale) {
|
|
370
399
|
return observed(
|
|
371
|
-
withConfiguredRetention(applyConfigHintsToCachedModels(name, prov, stale, contextCap, metadataModelIdCaseFold, captured.effectiveAlias)),
|
|
400
|
+
withConfiguredRetention(applyConfigHintsToCachedModels(name, prov, stale, contextCap, metadataModelIdCaseFold, captured.effectiveAlias, metadataConfigDir)),
|
|
372
401
|
"degraded",
|
|
373
402
|
);
|
|
374
403
|
}
|
|
@@ -388,7 +417,7 @@ export async function fetchProviderModelsWithAuth(
|
|
|
388
417
|
...(model.maxOutputTokens ? { maxOutputTokens: model.maxOutputTokens } : {}),
|
|
389
418
|
...(model.supportsImages ? { inputModalities: ["text", "image"] } : {}),
|
|
390
419
|
...(reasoningEfforts?.length ? { reasoningEfforts } : {}),
|
|
391
|
-
...catalogHintsFromProviderConfig(name, prov, model.id, contextCap, metadataModelIdCaseFold, captured.effectiveAlias),
|
|
420
|
+
...catalogHintsFromProviderConfig(name, prov, model.id, contextCap, metadataModelIdCaseFold, captured.effectiveAlias, metadataConfigDir),
|
|
392
421
|
} as CatalogModel;
|
|
393
422
|
});
|
|
394
423
|
const forCache = withConfiguredRetention(discovered, { retainComboTargets: false });
|
|
@@ -403,7 +432,7 @@ export async function fetchProviderModelsWithAuth(
|
|
|
403
432
|
markProviderDiscoveryFailed(name, { reason: "provider" });
|
|
404
433
|
}
|
|
405
434
|
return observed(
|
|
406
|
-
withConfiguredRetention(stale ? applyConfigHintsToCachedModels(name, prov, stale, contextCap, metadataModelIdCaseFold, captured.effectiveAlias) : configured),
|
|
435
|
+
withConfiguredRetention(stale ? applyConfigHintsToCachedModels(name, prov, stale, contextCap, metadataModelIdCaseFold, captured.effectiveAlias, metadataConfigDir) : configured),
|
|
407
436
|
"degraded",
|
|
408
437
|
);
|
|
409
438
|
}
|
|
@@ -419,13 +448,13 @@ export async function fetchProviderModelsWithAuth(
|
|
|
419
448
|
const fresh = getFreshCached(name, ttlMs, Date.now(), authorityIdentity);
|
|
420
449
|
if (fresh) {
|
|
421
450
|
return observed(withConfiguredRetention(
|
|
422
|
-
applyConfigHintsToCachedModels(name, prov, fresh, contextCap, metadataModelIdCaseFold, captured.effectiveAlias),
|
|
451
|
+
applyConfigHintsToCachedModels(name, prov, fresh, contextCap, metadataModelIdCaseFold, captured.effectiveAlias, metadataConfigDir),
|
|
423
452
|
), "authoritative");
|
|
424
453
|
}
|
|
425
454
|
const scopedStale = getStaleCached(name, authorityIdentity);
|
|
426
455
|
if (isModelsFetchCoolingDown(name) && scopedStale) {
|
|
427
456
|
return observed(withConfiguredRetention(
|
|
428
|
-
applyConfigHintsToCachedModels(name, prov, scopedStale, contextCap, metadataModelIdCaseFold, captured.effectiveAlias),
|
|
457
|
+
applyConfigHintsToCachedModels(name, prov, scopedStale, contextCap, metadataModelIdCaseFold, captured.effectiveAlias, metadataConfigDir),
|
|
429
458
|
), "degraded");
|
|
430
459
|
}
|
|
431
460
|
const live = await fetchQoderModels(profile, apiKey);
|
|
@@ -433,7 +462,7 @@ export async function fetchProviderModelsWithAuth(
|
|
|
433
462
|
const discovered = live.models.map(id => ({
|
|
434
463
|
id,
|
|
435
464
|
provider: name,
|
|
436
|
-
...catalogHintsFromProviderConfig(name, prov, id, contextCap, metadataModelIdCaseFold, captured.effectiveAlias),
|
|
465
|
+
...catalogHintsFromProviderConfig(name, prov, id, contextCap, metadataModelIdCaseFold, captured.effectiveAlias, metadataConfigDir),
|
|
437
466
|
}));
|
|
438
467
|
const forCache = withConfiguredRetention(discovered, { retainComboTargets: false });
|
|
439
468
|
if (!setCached(name, forCache, Date.now(), cacheGeneration, authorityIdentity)) {
|
|
@@ -449,7 +478,7 @@ export async function fetchProviderModelsWithAuth(
|
|
|
449
478
|
}
|
|
450
479
|
const stale = getStaleCached(name, authorityIdentity);
|
|
451
480
|
return observed(withConfiguredRetention(
|
|
452
|
-
stale ? applyConfigHintsToCachedModels(name, prov, stale, contextCap, metadataModelIdCaseFold, captured.effectiveAlias) : configured,
|
|
481
|
+
stale ? applyConfigHintsToCachedModels(name, prov, stale, contextCap, metadataModelIdCaseFold, captured.effectiveAlias, metadataConfigDir) : configured,
|
|
453
482
|
), "degraded");
|
|
454
483
|
}
|
|
455
484
|
if (prov.adapter === "devin") {
|
|
@@ -464,7 +493,7 @@ export async function fetchProviderModelsWithAuth(
|
|
|
464
493
|
const cachedDevin = getFreshCached(name, ttlMs, Date.now(), authorityIdentity);
|
|
465
494
|
if (cachedDevin) {
|
|
466
495
|
return observed(
|
|
467
|
-
withConfiguredRetention(applyConfigHintsToCachedModels(name, prov, cachedDevin)),
|
|
496
|
+
withConfiguredRetention(applyConfigHintsToCachedModels(name, prov, cachedDevin, undefined, undefined, undefined, metadataConfigDir)),
|
|
468
497
|
"authoritative",
|
|
469
498
|
);
|
|
470
499
|
}
|
|
@@ -472,7 +501,7 @@ export async function fetchProviderModelsWithAuth(
|
|
|
472
501
|
const cooling = getStaleCached(name, authorityIdentity);
|
|
473
502
|
return observed(
|
|
474
503
|
withConfiguredRetention(
|
|
475
|
-
cooling ? applyConfigHintsToCachedModels(name, prov, cooling) : configured,
|
|
504
|
+
cooling ? applyConfigHintsToCachedModels(name, prov, cooling, undefined, undefined, undefined, metadataConfigDir) : configured,
|
|
476
505
|
),
|
|
477
506
|
"degraded",
|
|
478
507
|
);
|
|
@@ -514,7 +543,7 @@ export async function fetchProviderModelsWithAuth(
|
|
|
514
543
|
// record and the vision-sidecar rewrite keep winning — the live
|
|
515
544
|
// value survives only when none of them applies.
|
|
516
545
|
...(liveResult.inputModalities[id]?.length ? { inputModalities: liveResult.inputModalities[id] } : {}),
|
|
517
|
-
...catalogHintsFromProviderConfig(name, prov, id, contextCap, metadataModelIdCaseFold, captured.effectiveAlias),
|
|
546
|
+
...catalogHintsFromProviderConfig(name, prov, id, contextCap, metadataModelIdCaseFold, captured.effectiveAlias, metadataConfigDir),
|
|
518
547
|
} as CatalogModel;
|
|
519
548
|
});
|
|
520
549
|
const forCache = withConfiguredRetention(result, { retainComboTargets: false });
|
|
@@ -530,7 +559,7 @@ export async function fetchProviderModelsWithAuth(
|
|
|
530
559
|
}
|
|
531
560
|
const stale = getStaleCached(name, authorityIdentity);
|
|
532
561
|
return observed(
|
|
533
|
-
withConfiguredRetention(stale ? applyConfigHintsToCachedModels(name, prov, stale) : configured),
|
|
562
|
+
withConfiguredRetention(stale ? applyConfigHintsToCachedModels(name, prov, stale, undefined, undefined, undefined, metadataConfigDir) : configured),
|
|
534
563
|
"degraded",
|
|
535
564
|
);
|
|
536
565
|
}
|
|
@@ -547,7 +576,7 @@ export async function fetchProviderModelsWithAuth(
|
|
|
547
576
|
const cachedCursor = getFreshCached(name, ttlMs, Date.now(), authorityIdentity);
|
|
548
577
|
if (cachedCursor) {
|
|
549
578
|
return observed(
|
|
550
|
-
withConfiguredRetention(applyConfigHintsToCachedModels(name, prov, cachedCursor, undefined, metadataModelIdCaseFold, captured.effectiveAlias)),
|
|
579
|
+
withConfiguredRetention(applyConfigHintsToCachedModels(name, prov, cachedCursor, undefined, metadataModelIdCaseFold, captured.effectiveAlias, metadataConfigDir)),
|
|
551
580
|
"authoritative",
|
|
552
581
|
);
|
|
553
582
|
}
|
|
@@ -555,7 +584,7 @@ export async function fetchProviderModelsWithAuth(
|
|
|
555
584
|
const cooling = getStaleCached(name, authorityIdentity);
|
|
556
585
|
return observed(
|
|
557
586
|
withConfiguredRetention(
|
|
558
|
-
cooling ? applyConfigHintsToCachedModels(name, prov, cooling, undefined, metadataModelIdCaseFold, captured.effectiveAlias) : configured,
|
|
587
|
+
cooling ? applyConfigHintsToCachedModels(name, prov, cooling, undefined, metadataModelIdCaseFold, captured.effectiveAlias, metadataConfigDir) : configured,
|
|
559
588
|
),
|
|
560
589
|
"degraded",
|
|
561
590
|
);
|
|
@@ -601,7 +630,7 @@ export async function fetchProviderModelsWithAuth(
|
|
|
601
630
|
const staleCursor = getStaleCached(name, authorityIdentity);
|
|
602
631
|
return observed(
|
|
603
632
|
withConfiguredRetention(
|
|
604
|
-
staleCursor ? applyConfigHintsToCachedModels(name, prov, staleCursor, undefined, metadataModelIdCaseFold, captured.effectiveAlias) : configured,
|
|
633
|
+
staleCursor ? applyConfigHintsToCachedModels(name, prov, staleCursor, undefined, metadataModelIdCaseFold, captured.effectiveAlias, metadataConfigDir) : configured,
|
|
605
634
|
),
|
|
606
635
|
"degraded",
|
|
607
636
|
);
|
|
@@ -619,7 +648,7 @@ export async function fetchProviderModelsWithAuth(
|
|
|
619
648
|
if (fresh) {
|
|
620
649
|
return observed(
|
|
621
650
|
withConfiguredRetention(
|
|
622
|
-
withVertexDefaultSeed(applyConfigHintsToCachedModels(name, prov, fresh, contextCap, metadataModelIdCaseFold, captured.effectiveAlias)),
|
|
651
|
+
withVertexDefaultSeed(applyConfigHintsToCachedModels(name, prov, fresh, contextCap, metadataModelIdCaseFold, captured.effectiveAlias, metadataConfigDir)),
|
|
623
652
|
),
|
|
624
653
|
"authoritative",
|
|
625
654
|
); // dedups Codex's frequent /v1/models polling within the TTL
|
|
@@ -631,7 +660,7 @@ export async function fetchProviderModelsWithAuth(
|
|
|
631
660
|
return observed(
|
|
632
661
|
withConfiguredRetention(
|
|
633
662
|
stale
|
|
634
|
-
? withVertexDefaultSeed(applyConfigHintsToCachedModels(name, prov, stale, contextCap, metadataModelIdCaseFold, captured.effectiveAlias))
|
|
663
|
+
? withVertexDefaultSeed(applyConfigHintsToCachedModels(name, prov, stale, contextCap, metadataModelIdCaseFold, captured.effectiveAlias, metadataConfigDir))
|
|
635
664
|
: failedDiscoveryConfigured,
|
|
636
665
|
),
|
|
637
666
|
"degraded",
|
|
@@ -676,7 +705,7 @@ export async function fetchProviderModelsWithAuth(
|
|
|
676
705
|
return {
|
|
677
706
|
models: withConfiguredRetention(
|
|
678
707
|
stale
|
|
679
|
-
? withVertexDefaultSeed(applyConfigHintsToCachedModels(name, prov, stale, contextCap, metadataModelIdCaseFold, captured.effectiveAlias))
|
|
708
|
+
? withVertexDefaultSeed(applyConfigHintsToCachedModels(name, prov, stale, contextCap, metadataModelIdCaseFold, captured.effectiveAlias, metadataConfigDir))
|
|
680
709
|
: failedDiscoveryConfigured,
|
|
681
710
|
),
|
|
682
711
|
fallback: stale ? "stale" : "configured",
|
|
@@ -754,7 +783,7 @@ export async function fetchProviderModelsWithAuth(
|
|
|
754
783
|
return observed(models, "degraded");
|
|
755
784
|
}
|
|
756
785
|
if (antigravity) {
|
|
757
|
-
const
|
|
786
|
+
const upstream: CatalogModel[] = antigravity.map(model => ({
|
|
758
787
|
id: model.id,
|
|
759
788
|
provider: name,
|
|
760
789
|
// Only an exact discovered wire map proves a new model's selectable effort ladder.
|
|
@@ -766,8 +795,9 @@ export async function fetchProviderModelsWithAuth(
|
|
|
766
795
|
} : {}),
|
|
767
796
|
...(model.contextWindow ? { contextWindow: model.contextWindow } : {}),
|
|
768
797
|
...(model.inputModalities ? { inputModalities: model.inputModalities } : {}),
|
|
769
|
-
}
|
|
770
|
-
const
|
|
798
|
+
}));
|
|
799
|
+
const live = applyConfigHintsToCachedModels(name, prov, upstream, contextCap, metadataModelIdCaseFold, captured.effectiveAlias, metadataConfigDir);
|
|
800
|
+
const forCache = azureMetadata ? upstream : withConfiguredRetention(live, { retainComboTargets: false });
|
|
771
801
|
if (!isCurrentCacheGeneration()) {
|
|
772
802
|
return observed(withConfiguredRetention(configured), "degraded");
|
|
773
803
|
}
|
|
@@ -781,7 +811,7 @@ export async function fetchProviderModelsWithAuth(
|
|
|
781
811
|
return observed(withConfiguredRetention(configured), "degraded");
|
|
782
812
|
}
|
|
783
813
|
markProviderDiscoveryOk(name, live.length);
|
|
784
|
-
return observed(withConfiguredRetention(forCache, { warnDrops: true }), "authoritative");
|
|
814
|
+
return observed(withConfiguredRetention(azureMetadata ? live : forCache, { warnDrops: true }), "authoritative");
|
|
785
815
|
}
|
|
786
816
|
const googleAiStudio = effectiveGoogleMode(name, prov) === "ai-studio"
|
|
787
817
|
? extractGoogleAiStudioModelItems(bounded.value, discovery.maxModels)
|
|
@@ -820,7 +850,7 @@ export async function fetchProviderModelsWithAuth(
|
|
|
820
850
|
provider: prov,
|
|
821
851
|
}).catch(() => undefined)
|
|
822
852
|
: undefined;
|
|
823
|
-
const
|
|
853
|
+
const upstream: CatalogModel[] = items.map(m => {
|
|
824
854
|
const ownedBy = boundedOwnedBy(m.owned_by);
|
|
825
855
|
// Precedence: the authoritative /v1/models row wins; /api/show fills only metadata the
|
|
826
856
|
// models-API row does not carry. applyProviderConfigHints then applies explicit
|
|
@@ -836,22 +866,25 @@ export async function fetchProviderModelsWithAuth(
|
|
|
836
866
|
? { inputModalities: ["text", "image"] as string[] }
|
|
837
867
|
: {}),
|
|
838
868
|
};
|
|
839
|
-
return
|
|
869
|
+
return {
|
|
840
870
|
id: m.id,
|
|
841
871
|
provider: name,
|
|
842
872
|
...(ownedBy ? { owned_by: ownedBy } : {}),
|
|
843
873
|
...discoveredHints,
|
|
844
|
-
}
|
|
874
|
+
};
|
|
845
875
|
})
|
|
846
876
|
.filter(m => shouldExposeProviderModel(name, m.id));
|
|
877
|
+
const live = applyConfigHintsToCachedModels(name, prov, upstream, contextCap, metadataModelIdCaseFold, captured.effectiveAlias, metadataConfigDir);
|
|
847
878
|
// Capture the count BEFORE the alias/configured augmentation below pushes extra rows into
|
|
848
879
|
// `live`; otherwise configured entries would be reported as discovered ones.
|
|
849
880
|
const liveModelCount = live.length;
|
|
850
881
|
// Dated-release aliases + configured retention (compat allow-list, combo targets,
|
|
851
882
|
// Vertex default). Cache without combo retention so a later gather re-applies the
|
|
852
883
|
// current capture's retain set on read (warm-cache OCX-111 / #1308).
|
|
853
|
-
|
|
854
|
-
|
|
884
|
+
// Azure hints depend on the admitted config root. Keep only upstream evidence in the
|
|
885
|
+
// shared TTL/stale cache; every read reapplies metadata and retention for its own root.
|
|
886
|
+
const forCache = azureMetadata ? upstream : withConfiguredRetention(live, { retainComboTargets: false });
|
|
887
|
+
const returned = withConfiguredRetention(azureMetadata ? live : forCache, { warnDrops: true });
|
|
855
888
|
const droppedConfiguredIds = configured
|
|
856
889
|
.map(model => model.id)
|
|
857
890
|
.filter(id => !returned.some(model => model.id === id));
|
|
@@ -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 {
|
package/src/codex/catalog.ts
CHANGED
|
@@ -4,7 +4,7 @@ export { isMediaGenerationModelId, shouldExposeRoutedModel, readCodexCatalogPath
|
|
|
4
4
|
export type { CatalogModel, MultiAgentMode } from "./catalog/parsing";
|
|
5
5
|
export { accountBoundNativeOpenAiSlugs, accountBoundNativeOpenAiSlugsBySelector, CODEX_NATIVE_ALIAS_CATALOG_KIND, NATIVE_DAYBREAK_BLUE_MODEL, NATIVE_GPT6_ASTRA_MODEL, NATIVE_GPT56_CONTEXT_WINDOW, NATIVE_GPT56_MAX_INPUT_TOKENS, NATIVE_GPT56_OPT_IN_CONTEXT_WINDOW, NATIVE_OPENAI_CAPABILITY_ALIAS_MODELS, NATIVE_OPENAI_MODELS, configuredNativeAliasSlugs, desktopAllowlistSuppressedNativeSlugs, isNativeAliasCatalogEntry, isNativeOpenAiCapabilityAliasModel, nativeContextLimits, nativeOpenAiCapabilitySourceSlug, nativeOpenAiContextWindow, nativeOpenAiMaxInputTokens, nativeOpenAiMaxOutputTokens, nativeOpenAiContextTier, disabledNativeSlugs, visibleNativeSlugs, desktopVisibleNativeSlugs, nativeModelRows, applyNativeVisibility, observedAccountBoundNativeEntries, observedAccountBoundNativeOpenAiSlugs, upstreamNativeEntry, nativeOpenAiSlugs, listCatalogNativeSlugs, nativeInputModalities, nativeReasoningEfforts, nativeDefaultReasoningEffort, shouldIncludeAccountBoundNativeOpenAi, shouldIncludeNativeOpenAi, type NativeContextLimits, type NativeContextLimitsInput } from "./catalog/metadata";
|
|
6
6
|
export { isSpawnableCodexCandidate, codexExecInvocation, loadBundledCodexCatalog, materializeBundledCodexCatalog, loadCatalogTemplate } from "./catalog/bundled";
|
|
7
|
-
export { nativeEffortClamp, shouldApplyNativeEffortClamp, catalogModelEfforts, codexSupportedReasoningEfforts, clampedDefaultEffort, clampEntryToCodexSupportedEfforts, clampCatalogModelsToCodexSupport } from "./catalog/effort";
|
|
7
|
+
export { nativeEffortClamp, shouldApplyNativeEffortClamp, catalogModelEfforts, catalogModelLadders, codexSupportedReasoningEfforts, clampedDefaultEffort, clampEntryToCodexSupportedEfforts, clampCatalogModelsToCodexSupport } from "./catalog/effort";
|
|
8
8
|
export { applyProviderConfigHints, isDatedVariantId, filterCatalogVisibleModels, gatherRoutedModels, clearGatherRoutedModelsInflight, augmentRoutedModelsWithRegistryOpenAiApiRows, augmentRoutedModelsWithMetadata, resolveComboCatalogMember, configuredComboTargetModelsByProvider } from "./catalog/provider-fetch";
|
|
9
9
|
export { deriveComboCatalogModel, exactComboCatalogSlugs, getLastComboCatalogOmissions, resetOpenAiApiCatalogWarningStateForTests, uniqueCatalogModelsForPublicList, uniqueCatalogModelsForRawPublicList, buildComboCatalogOmission, comboCatalogOmissionReason, summarizeComboCatalogOmissions } from "./catalog/aggregation";
|
|
10
10
|
export type { ComboCatalogOmission, ComboCatalogOmissionReason } from "./catalog/aggregation";
|
|
@@ -39,6 +39,9 @@ function provenAbsent(path: string): boolean {
|
|
|
39
39
|
catch (error) { return absent(error) && provenAbsent(parent); }
|
|
40
40
|
}
|
|
41
41
|
|
|
42
|
+
/** A missing directory entry is a no-op; dangling links and unreadable homes are not. */
|
|
43
|
+
export function codexHomeIsAbsent(home: string): boolean { return provenAbsent(home); }
|
|
44
|
+
|
|
42
45
|
function validJournal(value: unknown): value is Record<string, unknown> {
|
|
43
46
|
if (!value || typeof value !== "object" || Array.isArray(value)) return false;
|
|
44
47
|
const journal = value as Record<string, unknown>;
|