@bitkyc08/opencodex 2.81.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/bin/ocx.mjs +166 -73
- package/gui/dist/assets/App-Ds_qL7o8.js +54 -0
- package/gui/dist/assets/{Tray-EwAOsP0S.js → Tray-BqHF5Trd.js} +1 -1
- package/gui/dist/assets/{index-Brk6F3fn.css → index-BAbcj51J.css} +1 -1
- package/gui/dist/assets/{index-RsoaAxXY.js → index-D3FBCNiP.js} +13 -13
- package/gui/dist/assets/{quota-summary-D2lN8tDm.js → quota-summary-DTBC8n7-.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/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/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.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/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 +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/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/routes.ts +10 -49
- package/src/codex/auth-context.ts +20 -1
- 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/operator-tiers.ts +38 -0
- package/src/codex/catalog/provider-models.ts +43 -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/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-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 +303 -171
- package/src/generated/model-metadata.ts +2 -2
- package/src/grok/inject.ts +50 -4
- 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/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/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 +6 -2
- package/src/oauth/store.ts +1 -1
- package/src/providers/azure-model-metadata.ts +115 -0
- package/src/providers/derive.ts +21 -0
- package/src/providers/quota/vendor-probes-key.ts +127 -17
- package/src/providers/quota.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 +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 +2 -1
- package/src/server/index/startup-warnings.ts +19 -0
- package/src/server/index.ts +1 -0
- 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/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/request-log-conversation.ts +48 -5
- package/src/server/request-log.ts +31 -2
- package/src/server/responses/adapter-continuation.ts +2 -2
- package/src/server/responses/adapter-dispatch.ts +34 -13
- 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/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-options.ts +5 -0
- package/src/server/responses/core-replay.ts +73 -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 +24 -2
- package/src/server/responses/passthrough-dispatch.ts +19 -2
- package/src/server/responses/request-prepare.ts +4 -0
- package/src/server/responses/request-send-budget.ts +112 -49
- package/src/server/responses/response-effects.ts +1 -0
- package/src/server/responses/run-turn-execution.ts +2 -0
- package/src/server/responses/sidecar-execution.ts +25 -16
- package/src/server/responses/sidecar-send-budget.ts +58 -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 +5 -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/web-search/loop.ts +5 -2
- package/gui/dist/assets/App-7yhoys8a.js +0 -54
|
@@ -41,6 +41,7 @@ import { CODEX_REASONING_LEVELS, codexEffortRank, configuredReasoningEfforts, mo
|
|
|
41
41
|
import { isModelVisionSidecarConsumer } from "../../vision/eligibility";
|
|
42
42
|
import { getModelMetadata, getModelMetadataCaseInsensitive, listModelMetadata, resolveMetadataProvider, type ModelMetadata } from "../../generated/model-metadata";
|
|
43
43
|
import { enrichProviderFromRegistry, shouldCaseFoldMetadataModelId } from "../../providers/derive";
|
|
44
|
+
import { isAzureModelMetadataDestination, refreshAzureModelMetadata } from "../../providers/azure-model-metadata";
|
|
44
45
|
import {
|
|
45
46
|
captureFastPolicyAuthority,
|
|
46
47
|
fastPolicyForModel,
|
|
@@ -169,7 +170,8 @@ export async function fetchProviderModelsWithAuth(
|
|
|
169
170
|
contextCap: number | undefined,
|
|
170
171
|
resolveAuth: ModelsAuthResolver,
|
|
171
172
|
): Promise<ProviderModelsResult> {
|
|
172
|
-
const { name, provider: prov, discovery, metadataModelIdCaseFold } = captured;
|
|
173
|
+
const { name, provider: prov, discovery, metadataModelIdCaseFold, metadataConfigDir } = captured;
|
|
174
|
+
const azureMetadata = isAzureModelMetadataDestination(prov.baseUrl);
|
|
173
175
|
const observed = (
|
|
174
176
|
models: CatalogModel[],
|
|
175
177
|
state: CatalogGatherProviderModelOutcome["state"],
|
|
@@ -185,6 +187,7 @@ export async function fetchProviderModelsWithAuth(
|
|
|
185
187
|
const anthropicSelection = isAnthropicOAuthInstance(name) && prov.authMode === "oauth" && mayResolveModelsOAuth(name, prov)
|
|
186
188
|
? captureOAuthAccountSelection(name) : null;
|
|
187
189
|
if (prov.authMode === "forward") return observed([], "authoritative"); // ChatGPT backend has no /models
|
|
190
|
+
if (azureMetadata) await refreshAzureModelMetadata(prov.baseUrl, metadataConfigDir);
|
|
188
191
|
const seedVertexDefault = prov.adapter === "google"
|
|
189
192
|
&& prov.googleMode === "vertex"
|
|
190
193
|
&& (prov.models?.length ?? 0) === 0
|
|
@@ -203,7 +206,7 @@ export async function fetchProviderModelsWithAuth(
|
|
|
203
206
|
const configured: CatalogModel[] = configuredIds.map(id => ({
|
|
204
207
|
id,
|
|
205
208
|
provider: name,
|
|
206
|
-
...catalogHintsFromProviderConfig(name, prov, id, contextCap, metadataModelIdCaseFold, captured.effectiveAlias),
|
|
209
|
+
...catalogHintsFromProviderConfig(name, prov, id, contextCap, metadataModelIdCaseFold, captured.effectiveAlias, metadataConfigDir),
|
|
207
210
|
}));
|
|
208
211
|
const withConfiguredRetention = (
|
|
209
212
|
models: CatalogModel[],
|
|
@@ -219,6 +222,7 @@ export async function fetchProviderModelsWithAuth(
|
|
|
219
222
|
seedVertexDefault,
|
|
220
223
|
retainComboTargets: options?.retainComboTargets,
|
|
221
224
|
metadataModelIdCaseFold,
|
|
225
|
+
metadataConfigDir,
|
|
222
226
|
});
|
|
223
227
|
if (
|
|
224
228
|
options?.warnDrops === true
|
|
@@ -251,7 +255,7 @@ export async function fetchProviderModelsWithAuth(
|
|
|
251
255
|
}
|
|
252
256
|
return observed(ids.map(id => {
|
|
253
257
|
const hints = catalogHintsFromProviderConfig(name, prov, id, contextCap,
|
|
254
|
-
metadataModelIdCaseFold, captured.effectiveAlias);
|
|
258
|
+
metadataModelIdCaseFold, captured.effectiveAlias, metadataConfigDir);
|
|
255
259
|
const observedWindow = kiroObservedContextWindow(id);
|
|
256
260
|
return { id, provider: name, ...hints,
|
|
257
261
|
...(observedWindow !== undefined
|
|
@@ -296,7 +300,7 @@ export async function fetchProviderModelsWithAuth(
|
|
|
296
300
|
: [{
|
|
297
301
|
id: prov.defaultModel,
|
|
298
302
|
provider: name,
|
|
299
|
-
...catalogHintsFromProviderConfig(name, prov, prov.defaultModel, contextCap, metadataModelIdCaseFold, captured.effectiveAlias),
|
|
303
|
+
...catalogHintsFromProviderConfig(name, prov, prov.defaultModel, contextCap, metadataModelIdCaseFold, captured.effectiveAlias, metadataConfigDir),
|
|
300
304
|
}];
|
|
301
305
|
const vertexDefaultSeed = seedVertexDefault ? configured[0] : undefined;
|
|
302
306
|
const withVertexDefaultSeed = (models: CatalogModel[]): CatalogModel[] => (
|
|
@@ -318,13 +322,13 @@ export async function fetchProviderModelsWithAuth(
|
|
|
318
322
|
const fresh = getFreshCached(name, ttlMs, Date.now(), authorityIdentity);
|
|
319
323
|
if (fresh) {
|
|
320
324
|
return observed(withConfiguredRetention(
|
|
321
|
-
applyConfigHintsToCachedModels(name, prov, fresh, contextCap, metadataModelIdCaseFold, captured.effectiveAlias),
|
|
325
|
+
applyConfigHintsToCachedModels(name, prov, fresh, contextCap, metadataModelIdCaseFold, captured.effectiveAlias, metadataConfigDir),
|
|
322
326
|
), "authoritative");
|
|
323
327
|
}
|
|
324
328
|
const scopedStale = getStaleCached(name, authorityIdentity);
|
|
325
329
|
if (isModelsFetchCoolingDown(name, undefined, undefined, authorityIdentity) && scopedStale) {
|
|
326
330
|
return observed(withConfiguredRetention(
|
|
327
|
-
applyConfigHintsToCachedModels(name, prov, scopedStale, contextCap, metadataModelIdCaseFold, captured.effectiveAlias),
|
|
331
|
+
applyConfigHintsToCachedModels(name, prov, scopedStale, contextCap, metadataModelIdCaseFold, captured.effectiveAlias, metadataConfigDir),
|
|
328
332
|
), "degraded");
|
|
329
333
|
}
|
|
330
334
|
const live = await fetchCodeBuddyModels(profile, apiKey);
|
|
@@ -332,7 +336,7 @@ export async function fetchProviderModelsWithAuth(
|
|
|
332
336
|
const discovered = live.models.map(id => ({
|
|
333
337
|
id,
|
|
334
338
|
provider: name,
|
|
335
|
-
...catalogHintsFromProviderConfig(name, prov, id, contextCap, metadataModelIdCaseFold, captured.effectiveAlias),
|
|
339
|
+
...catalogHintsFromProviderConfig(name, prov, id, contextCap, metadataModelIdCaseFold, captured.effectiveAlias, metadataConfigDir),
|
|
336
340
|
}));
|
|
337
341
|
const forCache = withConfiguredRetention(discovered, { retainComboTargets: false });
|
|
338
342
|
if (!setCached(name, forCache, Date.now(), cacheGeneration, authorityIdentity)) {
|
|
@@ -348,7 +352,7 @@ export async function fetchProviderModelsWithAuth(
|
|
|
348
352
|
}
|
|
349
353
|
const stale = getStaleCached(name, authorityIdentity);
|
|
350
354
|
return observed(withConfiguredRetention(
|
|
351
|
-
stale ? applyConfigHintsToCachedModels(name, prov, stale, contextCap, metadataModelIdCaseFold, captured.effectiveAlias) : configured,
|
|
355
|
+
stale ? applyConfigHintsToCachedModels(name, prov, stale, contextCap, metadataModelIdCaseFold, captured.effectiveAlias, metadataConfigDir) : configured,
|
|
352
356
|
), "degraded");
|
|
353
357
|
}
|
|
354
358
|
if (name === "zed" && prov.adapter === "zed") {
|
|
@@ -361,14 +365,14 @@ export async function fetchProviderModelsWithAuth(
|
|
|
361
365
|
const cached = getFreshCached(name, ttlMs, Date.now(), authorityIdentity);
|
|
362
366
|
if (cached) {
|
|
363
367
|
return observed(
|
|
364
|
-
withConfiguredRetention(applyConfigHintsToCachedModels(name, prov, cached, contextCap, metadataModelIdCaseFold, captured.effectiveAlias)),
|
|
368
|
+
withConfiguredRetention(applyConfigHintsToCachedModels(name, prov, cached, contextCap, metadataModelIdCaseFold, captured.effectiveAlias, metadataConfigDir)),
|
|
365
369
|
"authoritative",
|
|
366
370
|
);
|
|
367
371
|
}
|
|
368
372
|
const stale = getStaleCached(name, authorityIdentity);
|
|
369
373
|
if (isModelsFetchCoolingDown(name, undefined, undefined, authorityIdentity) && stale) {
|
|
370
374
|
return observed(
|
|
371
|
-
withConfiguredRetention(applyConfigHintsToCachedModels(name, prov, stale, contextCap, metadataModelIdCaseFold, captured.effectiveAlias)),
|
|
375
|
+
withConfiguredRetention(applyConfigHintsToCachedModels(name, prov, stale, contextCap, metadataModelIdCaseFold, captured.effectiveAlias, metadataConfigDir)),
|
|
372
376
|
"degraded",
|
|
373
377
|
);
|
|
374
378
|
}
|
|
@@ -388,7 +392,7 @@ export async function fetchProviderModelsWithAuth(
|
|
|
388
392
|
...(model.maxOutputTokens ? { maxOutputTokens: model.maxOutputTokens } : {}),
|
|
389
393
|
...(model.supportsImages ? { inputModalities: ["text", "image"] } : {}),
|
|
390
394
|
...(reasoningEfforts?.length ? { reasoningEfforts } : {}),
|
|
391
|
-
...catalogHintsFromProviderConfig(name, prov, model.id, contextCap, metadataModelIdCaseFold, captured.effectiveAlias),
|
|
395
|
+
...catalogHintsFromProviderConfig(name, prov, model.id, contextCap, metadataModelIdCaseFold, captured.effectiveAlias, metadataConfigDir),
|
|
392
396
|
} as CatalogModel;
|
|
393
397
|
});
|
|
394
398
|
const forCache = withConfiguredRetention(discovered, { retainComboTargets: false });
|
|
@@ -403,7 +407,7 @@ export async function fetchProviderModelsWithAuth(
|
|
|
403
407
|
markProviderDiscoveryFailed(name, { reason: "provider" });
|
|
404
408
|
}
|
|
405
409
|
return observed(
|
|
406
|
-
withConfiguredRetention(stale ? applyConfigHintsToCachedModels(name, prov, stale, contextCap, metadataModelIdCaseFold, captured.effectiveAlias) : configured),
|
|
410
|
+
withConfiguredRetention(stale ? applyConfigHintsToCachedModels(name, prov, stale, contextCap, metadataModelIdCaseFold, captured.effectiveAlias, metadataConfigDir) : configured),
|
|
407
411
|
"degraded",
|
|
408
412
|
);
|
|
409
413
|
}
|
|
@@ -419,13 +423,13 @@ export async function fetchProviderModelsWithAuth(
|
|
|
419
423
|
const fresh = getFreshCached(name, ttlMs, Date.now(), authorityIdentity);
|
|
420
424
|
if (fresh) {
|
|
421
425
|
return observed(withConfiguredRetention(
|
|
422
|
-
applyConfigHintsToCachedModels(name, prov, fresh, contextCap, metadataModelIdCaseFold, captured.effectiveAlias),
|
|
426
|
+
applyConfigHintsToCachedModels(name, prov, fresh, contextCap, metadataModelIdCaseFold, captured.effectiveAlias, metadataConfigDir),
|
|
423
427
|
), "authoritative");
|
|
424
428
|
}
|
|
425
429
|
const scopedStale = getStaleCached(name, authorityIdentity);
|
|
426
430
|
if (isModelsFetchCoolingDown(name) && scopedStale) {
|
|
427
431
|
return observed(withConfiguredRetention(
|
|
428
|
-
applyConfigHintsToCachedModels(name, prov, scopedStale, contextCap, metadataModelIdCaseFold, captured.effectiveAlias),
|
|
432
|
+
applyConfigHintsToCachedModels(name, prov, scopedStale, contextCap, metadataModelIdCaseFold, captured.effectiveAlias, metadataConfigDir),
|
|
429
433
|
), "degraded");
|
|
430
434
|
}
|
|
431
435
|
const live = await fetchQoderModels(profile, apiKey);
|
|
@@ -433,7 +437,7 @@ export async function fetchProviderModelsWithAuth(
|
|
|
433
437
|
const discovered = live.models.map(id => ({
|
|
434
438
|
id,
|
|
435
439
|
provider: name,
|
|
436
|
-
...catalogHintsFromProviderConfig(name, prov, id, contextCap, metadataModelIdCaseFold, captured.effectiveAlias),
|
|
440
|
+
...catalogHintsFromProviderConfig(name, prov, id, contextCap, metadataModelIdCaseFold, captured.effectiveAlias, metadataConfigDir),
|
|
437
441
|
}));
|
|
438
442
|
const forCache = withConfiguredRetention(discovered, { retainComboTargets: false });
|
|
439
443
|
if (!setCached(name, forCache, Date.now(), cacheGeneration, authorityIdentity)) {
|
|
@@ -449,7 +453,7 @@ export async function fetchProviderModelsWithAuth(
|
|
|
449
453
|
}
|
|
450
454
|
const stale = getStaleCached(name, authorityIdentity);
|
|
451
455
|
return observed(withConfiguredRetention(
|
|
452
|
-
stale ? applyConfigHintsToCachedModels(name, prov, stale, contextCap, metadataModelIdCaseFold, captured.effectiveAlias) : configured,
|
|
456
|
+
stale ? applyConfigHintsToCachedModels(name, prov, stale, contextCap, metadataModelIdCaseFold, captured.effectiveAlias, metadataConfigDir) : configured,
|
|
453
457
|
), "degraded");
|
|
454
458
|
}
|
|
455
459
|
if (prov.adapter === "devin") {
|
|
@@ -464,7 +468,7 @@ export async function fetchProviderModelsWithAuth(
|
|
|
464
468
|
const cachedDevin = getFreshCached(name, ttlMs, Date.now(), authorityIdentity);
|
|
465
469
|
if (cachedDevin) {
|
|
466
470
|
return observed(
|
|
467
|
-
withConfiguredRetention(applyConfigHintsToCachedModels(name, prov, cachedDevin)),
|
|
471
|
+
withConfiguredRetention(applyConfigHintsToCachedModels(name, prov, cachedDevin, undefined, undefined, undefined, metadataConfigDir)),
|
|
468
472
|
"authoritative",
|
|
469
473
|
);
|
|
470
474
|
}
|
|
@@ -472,7 +476,7 @@ export async function fetchProviderModelsWithAuth(
|
|
|
472
476
|
const cooling = getStaleCached(name, authorityIdentity);
|
|
473
477
|
return observed(
|
|
474
478
|
withConfiguredRetention(
|
|
475
|
-
cooling ? applyConfigHintsToCachedModels(name, prov, cooling) : configured,
|
|
479
|
+
cooling ? applyConfigHintsToCachedModels(name, prov, cooling, undefined, undefined, undefined, metadataConfigDir) : configured,
|
|
476
480
|
),
|
|
477
481
|
"degraded",
|
|
478
482
|
);
|
|
@@ -514,7 +518,7 @@ export async function fetchProviderModelsWithAuth(
|
|
|
514
518
|
// record and the vision-sidecar rewrite keep winning — the live
|
|
515
519
|
// value survives only when none of them applies.
|
|
516
520
|
...(liveResult.inputModalities[id]?.length ? { inputModalities: liveResult.inputModalities[id] } : {}),
|
|
517
|
-
...catalogHintsFromProviderConfig(name, prov, id, contextCap, metadataModelIdCaseFold, captured.effectiveAlias),
|
|
521
|
+
...catalogHintsFromProviderConfig(name, prov, id, contextCap, metadataModelIdCaseFold, captured.effectiveAlias, metadataConfigDir),
|
|
518
522
|
} as CatalogModel;
|
|
519
523
|
});
|
|
520
524
|
const forCache = withConfiguredRetention(result, { retainComboTargets: false });
|
|
@@ -530,7 +534,7 @@ export async function fetchProviderModelsWithAuth(
|
|
|
530
534
|
}
|
|
531
535
|
const stale = getStaleCached(name, authorityIdentity);
|
|
532
536
|
return observed(
|
|
533
|
-
withConfiguredRetention(stale ? applyConfigHintsToCachedModels(name, prov, stale) : configured),
|
|
537
|
+
withConfiguredRetention(stale ? applyConfigHintsToCachedModels(name, prov, stale, undefined, undefined, undefined, metadataConfigDir) : configured),
|
|
534
538
|
"degraded",
|
|
535
539
|
);
|
|
536
540
|
}
|
|
@@ -547,7 +551,7 @@ export async function fetchProviderModelsWithAuth(
|
|
|
547
551
|
const cachedCursor = getFreshCached(name, ttlMs, Date.now(), authorityIdentity);
|
|
548
552
|
if (cachedCursor) {
|
|
549
553
|
return observed(
|
|
550
|
-
withConfiguredRetention(applyConfigHintsToCachedModels(name, prov, cachedCursor, undefined, metadataModelIdCaseFold, captured.effectiveAlias)),
|
|
554
|
+
withConfiguredRetention(applyConfigHintsToCachedModels(name, prov, cachedCursor, undefined, metadataModelIdCaseFold, captured.effectiveAlias, metadataConfigDir)),
|
|
551
555
|
"authoritative",
|
|
552
556
|
);
|
|
553
557
|
}
|
|
@@ -555,7 +559,7 @@ export async function fetchProviderModelsWithAuth(
|
|
|
555
559
|
const cooling = getStaleCached(name, authorityIdentity);
|
|
556
560
|
return observed(
|
|
557
561
|
withConfiguredRetention(
|
|
558
|
-
cooling ? applyConfigHintsToCachedModels(name, prov, cooling, undefined, metadataModelIdCaseFold, captured.effectiveAlias) : configured,
|
|
562
|
+
cooling ? applyConfigHintsToCachedModels(name, prov, cooling, undefined, metadataModelIdCaseFold, captured.effectiveAlias, metadataConfigDir) : configured,
|
|
559
563
|
),
|
|
560
564
|
"degraded",
|
|
561
565
|
);
|
|
@@ -601,7 +605,7 @@ export async function fetchProviderModelsWithAuth(
|
|
|
601
605
|
const staleCursor = getStaleCached(name, authorityIdentity);
|
|
602
606
|
return observed(
|
|
603
607
|
withConfiguredRetention(
|
|
604
|
-
staleCursor ? applyConfigHintsToCachedModels(name, prov, staleCursor, undefined, metadataModelIdCaseFold, captured.effectiveAlias) : configured,
|
|
608
|
+
staleCursor ? applyConfigHintsToCachedModels(name, prov, staleCursor, undefined, metadataModelIdCaseFold, captured.effectiveAlias, metadataConfigDir) : configured,
|
|
605
609
|
),
|
|
606
610
|
"degraded",
|
|
607
611
|
);
|
|
@@ -619,7 +623,7 @@ export async function fetchProviderModelsWithAuth(
|
|
|
619
623
|
if (fresh) {
|
|
620
624
|
return observed(
|
|
621
625
|
withConfiguredRetention(
|
|
622
|
-
withVertexDefaultSeed(applyConfigHintsToCachedModels(name, prov, fresh, contextCap, metadataModelIdCaseFold, captured.effectiveAlias)),
|
|
626
|
+
withVertexDefaultSeed(applyConfigHintsToCachedModels(name, prov, fresh, contextCap, metadataModelIdCaseFold, captured.effectiveAlias, metadataConfigDir)),
|
|
623
627
|
),
|
|
624
628
|
"authoritative",
|
|
625
629
|
); // dedups Codex's frequent /v1/models polling within the TTL
|
|
@@ -631,7 +635,7 @@ export async function fetchProviderModelsWithAuth(
|
|
|
631
635
|
return observed(
|
|
632
636
|
withConfiguredRetention(
|
|
633
637
|
stale
|
|
634
|
-
? withVertexDefaultSeed(applyConfigHintsToCachedModels(name, prov, stale, contextCap, metadataModelIdCaseFold, captured.effectiveAlias))
|
|
638
|
+
? withVertexDefaultSeed(applyConfigHintsToCachedModels(name, prov, stale, contextCap, metadataModelIdCaseFold, captured.effectiveAlias, metadataConfigDir))
|
|
635
639
|
: failedDiscoveryConfigured,
|
|
636
640
|
),
|
|
637
641
|
"degraded",
|
|
@@ -676,7 +680,7 @@ export async function fetchProviderModelsWithAuth(
|
|
|
676
680
|
return {
|
|
677
681
|
models: withConfiguredRetention(
|
|
678
682
|
stale
|
|
679
|
-
? withVertexDefaultSeed(applyConfigHintsToCachedModels(name, prov, stale, contextCap, metadataModelIdCaseFold, captured.effectiveAlias))
|
|
683
|
+
? withVertexDefaultSeed(applyConfigHintsToCachedModels(name, prov, stale, contextCap, metadataModelIdCaseFold, captured.effectiveAlias, metadataConfigDir))
|
|
680
684
|
: failedDiscoveryConfigured,
|
|
681
685
|
),
|
|
682
686
|
fallback: stale ? "stale" : "configured",
|
|
@@ -754,7 +758,7 @@ export async function fetchProviderModelsWithAuth(
|
|
|
754
758
|
return observed(models, "degraded");
|
|
755
759
|
}
|
|
756
760
|
if (antigravity) {
|
|
757
|
-
const
|
|
761
|
+
const upstream: CatalogModel[] = antigravity.map(model => ({
|
|
758
762
|
id: model.id,
|
|
759
763
|
provider: name,
|
|
760
764
|
// Only an exact discovered wire map proves a new model's selectable effort ladder.
|
|
@@ -766,8 +770,9 @@ export async function fetchProviderModelsWithAuth(
|
|
|
766
770
|
} : {}),
|
|
767
771
|
...(model.contextWindow ? { contextWindow: model.contextWindow } : {}),
|
|
768
772
|
...(model.inputModalities ? { inputModalities: model.inputModalities } : {}),
|
|
769
|
-
}
|
|
770
|
-
const
|
|
773
|
+
}));
|
|
774
|
+
const live = applyConfigHintsToCachedModels(name, prov, upstream, contextCap, metadataModelIdCaseFold, captured.effectiveAlias, metadataConfigDir);
|
|
775
|
+
const forCache = azureMetadata ? upstream : withConfiguredRetention(live, { retainComboTargets: false });
|
|
771
776
|
if (!isCurrentCacheGeneration()) {
|
|
772
777
|
return observed(withConfiguredRetention(configured), "degraded");
|
|
773
778
|
}
|
|
@@ -781,7 +786,7 @@ export async function fetchProviderModelsWithAuth(
|
|
|
781
786
|
return observed(withConfiguredRetention(configured), "degraded");
|
|
782
787
|
}
|
|
783
788
|
markProviderDiscoveryOk(name, live.length);
|
|
784
|
-
return observed(withConfiguredRetention(forCache, { warnDrops: true }), "authoritative");
|
|
789
|
+
return observed(withConfiguredRetention(azureMetadata ? live : forCache, { warnDrops: true }), "authoritative");
|
|
785
790
|
}
|
|
786
791
|
const googleAiStudio = effectiveGoogleMode(name, prov) === "ai-studio"
|
|
787
792
|
? extractGoogleAiStudioModelItems(bounded.value, discovery.maxModels)
|
|
@@ -820,7 +825,7 @@ export async function fetchProviderModelsWithAuth(
|
|
|
820
825
|
provider: prov,
|
|
821
826
|
}).catch(() => undefined)
|
|
822
827
|
: undefined;
|
|
823
|
-
const
|
|
828
|
+
const upstream: CatalogModel[] = items.map(m => {
|
|
824
829
|
const ownedBy = boundedOwnedBy(m.owned_by);
|
|
825
830
|
// Precedence: the authoritative /v1/models row wins; /api/show fills only metadata the
|
|
826
831
|
// models-API row does not carry. applyProviderConfigHints then applies explicit
|
|
@@ -836,22 +841,25 @@ export async function fetchProviderModelsWithAuth(
|
|
|
836
841
|
? { inputModalities: ["text", "image"] as string[] }
|
|
837
842
|
: {}),
|
|
838
843
|
};
|
|
839
|
-
return
|
|
844
|
+
return {
|
|
840
845
|
id: m.id,
|
|
841
846
|
provider: name,
|
|
842
847
|
...(ownedBy ? { owned_by: ownedBy } : {}),
|
|
843
848
|
...discoveredHints,
|
|
844
|
-
}
|
|
849
|
+
};
|
|
845
850
|
})
|
|
846
851
|
.filter(m => shouldExposeProviderModel(name, m.id));
|
|
852
|
+
const live = applyConfigHintsToCachedModels(name, prov, upstream, contextCap, metadataModelIdCaseFold, captured.effectiveAlias, metadataConfigDir);
|
|
847
853
|
// Capture the count BEFORE the alias/configured augmentation below pushes extra rows into
|
|
848
854
|
// `live`; otherwise configured entries would be reported as discovered ones.
|
|
849
855
|
const liveModelCount = live.length;
|
|
850
856
|
// Dated-release aliases + configured retention (compat allow-list, combo targets,
|
|
851
857
|
// Vertex default). Cache without combo retention so a later gather re-applies the
|
|
852
858
|
// current capture's retain set on read (warm-cache OCX-111 / #1308).
|
|
853
|
-
|
|
854
|
-
|
|
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 });
|
|
855
863
|
const droppedConfiguredIds = configured
|
|
856
864
|
.map(model => model.id)
|
|
857
865
|
.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>;
|