@yansigit/opencodex 2.32.0 → 2.33.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/gui/dist/assets/index-DKLr4LTE.js +102 -0
- package/gui/dist/assets/index-DrSQdTRd.css +1 -0
- package/gui/dist/index.html +2 -2
- package/package.json +6 -5
- package/src/adapters/anthropic.ts +20 -6
- package/src/adapters/azure.ts +20 -4
- package/src/adapters/base.ts +3 -1
- package/src/adapters/command-code.ts +40 -7
- package/src/adapters/cursor/live-transport.ts +1 -1
- package/src/adapters/cursor/protobuf-events.ts +158 -7
- package/src/adapters/cursor/protobuf-request.ts +33 -15
- package/src/adapters/cursor/request-builder.ts +4 -3
- package/src/adapters/cursor/tool-definitions.ts +27 -1
- package/src/adapters/cursor/types.ts +4 -3
- package/src/adapters/cursor.ts +9 -0
- package/src/adapters/google-antigravity-replay.ts +2 -2
- package/src/adapters/google-antigravity-wire.ts +7 -0
- package/src/adapters/google-errors.ts +6 -2
- package/src/adapters/google-http.ts +30 -7
- package/src/adapters/google-truncation.ts +5 -0
- package/src/adapters/google-wire-compiler.ts +38 -6
- package/src/adapters/google.ts +148 -26
- package/src/adapters/kiro-tools.ts +20 -9
- package/src/adapters/openai-chat.ts +9 -0
- package/src/adapters/openai-responses.ts +1 -1
- package/src/bridge.ts +112 -9
- package/src/claude/context-windows.ts +16 -9
- package/src/cli/doctor.ts +2 -2
- package/src/cli/index.ts +9 -2
- package/src/cli/provider.ts +6 -0
- package/src/cli/status.ts +23 -0
- package/src/codex/auth-api.ts +4 -2
- package/src/codex/autostart-health.ts +16 -0
- package/src/codex/catalog/aggregation.ts +12 -12
- package/src/codex/catalog/effort.ts +18 -3
- package/src/codex/catalog/metadata.ts +27 -1
- package/src/codex/catalog/model-metadata.ts +39 -12
- package/src/codex/catalog/parsing.ts +38 -27
- package/src/codex/catalog/provider-fetch.ts +198 -133
- package/src/codex/catalog/sync.ts +1 -1
- package/src/codex/convergence.ts +5 -0
- package/src/codex/shim.ts +56 -3
- package/src/config/provider-validation.ts +37 -0
- package/src/config.ts +78 -2
- package/src/generated/compatibility-version.json +120 -96
- package/src/images/loop.ts +37 -6
- package/src/lib/azure-identity.ts +154 -0
- package/src/lib/debug.ts +42 -0
- package/src/lib/errors.ts +14 -0
- package/src/lib/provider-outbound.ts +45 -33
- package/src/lib/provider-tls-profile.ts +309 -0
- package/src/lib/proxy-env.ts +49 -0
- package/src/lib/redact.ts +10 -1
- package/src/oauth/antigravity-routing.ts +282 -236
- package/src/oauth/callback-server.ts +22 -2
- package/src/oauth/command-code.ts +5 -16
- package/src/oauth/google-antigravity.ts +42 -5
- package/src/oauth/index.ts +15 -3
- package/src/oauth/kimi.ts +9 -1
- package/src/oauth/open-browser-choice.ts +26 -0
- package/src/oauth/store.ts +6 -0
- package/src/providers/antigravity-quota.ts +3 -1
- package/src/providers/api-keys.ts +2 -1
- package/src/providers/auto-compact-budget.ts +65 -0
- package/src/providers/derive.ts +4 -0
- package/src/providers/key-failover.ts +5 -1
- package/src/providers/openai-tiers.ts +5 -0
- package/src/providers/provider-id-rewrite.ts +1 -0
- package/src/providers/quota.ts +59 -13
- package/src/providers/registry.ts +3 -1
- package/src/providers/request-pacing.ts +33 -6
- package/src/providers/xai-transport.ts +21 -0
- package/src/responses/google-provider-options.ts +36 -0
- package/src/responses/namespace-tool-compat.ts +84 -4
- package/src/responses/parser.ts +11 -0
- package/src/responses/provider-opaque-metadata.ts +3 -3
- package/src/responses/schema.ts +37 -0
- package/src/responses/state.ts +94 -4
- package/src/router.ts +8 -2
- package/src/server/auth-cors.ts +28 -0
- package/src/server/images.ts +19 -35
- package/src/server/management/agent-settings-routes.ts +205 -15
- package/src/server/management/combo-routes.ts +6 -0
- package/src/server/management/config-routes.ts +31 -5
- package/src/server/management/model-rows.ts +4 -0
- package/src/server/management/oauth-account-routes.ts +25 -4
- package/src/server/management/provider-routes.ts +113 -15
- package/src/server/management/routing-profile-routes.ts +3 -0
- package/src/server/request-log.ts +21 -0
- package/src/server/responses/agent-task-recovery.ts +1 -1
- package/src/server/responses/compact.ts +30 -1
- package/src/server/responses/core.ts +359 -153
- package/src/server/responses/empty-completion-guard.ts +35 -6
- package/src/server/responses/fetch-helpers.ts +18 -5
- package/src/server/responses/v2-native-parent-override.ts +59 -0
- package/src/server/responses/ws-upstream.ts +75 -2
- package/src/server/responses-undeclared-tool-guard.ts +90 -8
- package/src/service.ts +1 -1
- package/src/types/config.ts +16 -1
- package/src/types/provider.ts +16 -0
- package/src/types/request.ts +28 -0
- package/src/types/tools.ts +27 -0
- package/src/types.ts +6 -0
- package/src/web-search/gemini-executor.ts +6 -4
- package/src/web-search/loop.ts +42 -6
- package/gui/dist/assets/index-BG43zwVe.js +0 -102
- package/gui/dist/assets/index-CiSI-jrP.css +0 -1
|
@@ -41,7 +41,8 @@ import type { FastPolicyAuthority } from "../../providers/fastwire";
|
|
|
41
41
|
import { effectiveGoogleMode, getProviderRegistryEntry, providerMatchesRegistryTransport } from "../../providers/registry";
|
|
42
42
|
import { parseAntigravityAvailableModels, registerAntigravityDiscoveredWireModels } from "../../providers/antigravity-models";
|
|
43
43
|
import { applyProviderContextCap, providerContextCap, resolveUnknownRoutedContextWindow } from "../../providers/context-cap";
|
|
44
|
-
import {
|
|
44
|
+
import { clampAutoCompactTokenLimit } from "../../providers/auto-compact-budget";
|
|
45
|
+
import { routedSlug, slugEquals, slugEquivalenceKey, slugsEquivalent } from "../../providers/slug-codec";
|
|
45
46
|
import { CODEX_GPT5_IDENTITY_LINE } from "../../adapters/identity";
|
|
46
47
|
import { filterCursorConfiguredModelsByLiveDiscovery } from "../../adapters/cursor/discovery";
|
|
47
48
|
import { fetchCursorUsableModels } from "../../adapters/cursor/live-models";
|
|
@@ -60,6 +61,7 @@ import {
|
|
|
60
61
|
providerOutboundPost,
|
|
61
62
|
providerRedirectError,
|
|
62
63
|
} from "../../lib/provider-outbound";
|
|
64
|
+
import { isAntigravityOAuthProvider } from "../../lib/provider-tls-profile";
|
|
63
65
|
import { redactSecretString } from "../../lib/redact";
|
|
64
66
|
import {
|
|
65
67
|
extractProviderModelItems,
|
|
@@ -75,8 +77,7 @@ import { createAdmissionGate, ResourceAdmissionError, type AdmissionMetrics } fr
|
|
|
75
77
|
|
|
76
78
|
import { CODEX_CUSTOM_MODEL_CATALOG_KIND, JAWCODE_CATALOG_AUGMENT_PROVIDERS, catalogModelSlug, shouldExposeRoutedModel } from "./parsing";
|
|
77
79
|
import type { CatalogModel } from "./parsing";
|
|
78
|
-
import {
|
|
79
|
-
import { disabledNativeSlugs, hasComboTargets, isNativeOpenAiCapabilityAliasModel, NATIVE_GPT56_MAX_INPUT_TOKENS, nativeContextLimits, nativeDefaultReasoningEffort, nativeInputModalities, nativeOpenAiContextWindow, nativeOpenAiMaxInputTokens, nativeOpenAiSlugs, nativeParallelToolCalls, nativeReasoningEfforts } from "./metadata";
|
|
80
|
+
import { disabledNativeSlugs, hasComboTargets, isNativeOpenAiCapabilityAliasModel, NATIVE_GPT56_MAX_INPUT_TOKENS, nativeContextLimits, nativeDefaultReasoningEffort, nativeInputModalities, nativeOpenAiAutoCompactTokenLimit, nativeOpenAiContextWindow, nativeOpenAiMaxInputTokens, nativeOpenAiSlugs, nativeParallelToolCalls, nativeReasoningEfforts } from "./metadata";
|
|
80
81
|
import { deriveComboCatalogModel, normalizedOpenAiApiSignature, openAiApiCollisionWarnings, replaceLastComboCatalogOmissions, warnUncataloguedComboOnce } from "./aggregation";
|
|
81
82
|
import type { ComboCatalogOmission } from "./aggregation";
|
|
82
83
|
import type { CatalogGatherProviderAuthEvidence } from "./filesystem-evidence";
|
|
@@ -572,6 +573,7 @@ function providerCatalogFingerprint(name: string, prov: OcxProviderConfig): Reco
|
|
|
572
573
|
ctx: prov.contextWindow ?? null,
|
|
573
574
|
ctxW: prov.modelContextWindows ?? null,
|
|
574
575
|
maxIn: prov.modelMaxInputTokens ?? null,
|
|
576
|
+
autoCompact: prov.modelAutoCompactTokenLimits ?? null,
|
|
575
577
|
inMod: prov.modelInputModalities ?? null,
|
|
576
578
|
re: prov.modelReasoningEfforts ?? null,
|
|
577
579
|
defRe: prov.modelDefaultReasoningEfforts ?? null,
|
|
@@ -626,6 +628,17 @@ export function configuredMaxInputTokens(prov: OcxProviderConfig, id: string): n
|
|
|
626
628
|
return typeof configured === "number" && configured > 0 ? configured : undefined;
|
|
627
629
|
}
|
|
628
630
|
|
|
631
|
+
export function configuredAutoCompactTokenLimit(
|
|
632
|
+
prov: OcxProviderConfig | undefined,
|
|
633
|
+
id: string,
|
|
634
|
+
): number | undefined {
|
|
635
|
+
if (!prov) return undefined;
|
|
636
|
+
const configured = modelRecordValue(prov.modelAutoCompactTokenLimits, id);
|
|
637
|
+
return typeof configured === "number" && Number.isSafeInteger(configured) && configured > 0
|
|
638
|
+
? configured
|
|
639
|
+
: undefined;
|
|
640
|
+
}
|
|
641
|
+
|
|
629
642
|
function configuredReasoningSummarySupport(prov: OcxProviderConfig | undefined, id: string): boolean | undefined {
|
|
630
643
|
if (!prov) return undefined;
|
|
631
644
|
const explicit = modelRecordValue(prov.modelSupportsReasoningSummaries, id);
|
|
@@ -637,6 +650,7 @@ export function applyProviderConfigHints(name: string, prov: OcxProviderConfig,
|
|
|
637
650
|
void name;
|
|
638
651
|
const configuredCap = configuredContextWindow(prov, model.id);
|
|
639
652
|
const configuredMaxInput = configuredMaxInputTokens(prov, model.id);
|
|
653
|
+
const configuredAutoCompact = configuredAutoCompactTokenLimit(prov, model.id);
|
|
640
654
|
let inputModalities = configuredInputModalities(prov, model.id);
|
|
641
655
|
// Vision-sidecar coverage: `noVisionModels` marks models whose images the PROXY describes
|
|
642
656
|
// (src/vision/index.ts). The catalog must still advertise image input for them — the Codex app
|
|
@@ -663,16 +677,9 @@ export function applyProviderConfigHints(name: string, prov: OcxProviderConfig,
|
|
|
663
677
|
const hintedWindow = discoveredWindow !== undefined
|
|
664
678
|
? (configuredCap !== undefined ? Math.min(discoveredWindow, configuredCap) : discoveredWindow)
|
|
665
679
|
: (configuredCap ?? (providerCap !== undefined ? resolveUnknownRoutedContextWindow(providerCap) : undefined));
|
|
666
|
-
const capFilledMissingWindow = discoveredWindow === undefined && hintedWindow !== undefined;
|
|
667
680
|
const hinted = {
|
|
668
681
|
...modelWithoutServiceTier,
|
|
669
682
|
...(hintedWindow !== undefined ? { contextWindow: hintedWindow } : {}),
|
|
670
|
-
...(discoveredWindow !== undefined
|
|
671
|
-
? { detectedContextWindow: model.detectedContextWindow ?? discoveredWindow }
|
|
672
|
-
: {}),
|
|
673
|
-
...(capFilledMissingWindow && !model.metadataSource
|
|
674
|
-
? { metadataSource: "config_fallback" as const }
|
|
675
|
-
: {}),
|
|
676
683
|
...(inputModalities ? { inputModalities } : {}),
|
|
677
684
|
...(reasoningEfforts !== undefined ? { reasoningEfforts } : {}),
|
|
678
685
|
...(configuredMaxInput !== undefined
|
|
@@ -697,26 +704,31 @@ export function applyProviderConfigHints(name: string, prov: OcxProviderConfig,
|
|
|
697
704
|
...(prov.codexToolMode !== undefined ? { codexToolMode: prov.codexToolMode } : {}),
|
|
698
705
|
};
|
|
699
706
|
const capped = applyProviderContextCap(hinted.contextWindow, providerCap);
|
|
700
|
-
const
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
&& (
|
|
705
|
-
capped !== hinted.contextWindow
|
|
706
|
-
|| (typeof detectedContextWindow === "number" && detectedContextWindow > capped)
|
|
707
|
-
|| hinted.contextCapped === true
|
|
708
|
-
);
|
|
709
|
-
if (providerCap !== undefined && capped !== hinted.contextWindow) {
|
|
710
|
-
return {
|
|
711
|
-
...hinted,
|
|
712
|
-
contextWindow: capped,
|
|
713
|
-
contextCap: providerCap,
|
|
714
|
-
contextCapped,
|
|
715
|
-
};
|
|
716
|
-
}
|
|
717
|
-
return providerCap !== undefined
|
|
718
|
-
? { ...hinted, contextCap: providerCap, contextCapped }
|
|
707
|
+
const withCap = providerCap !== undefined
|
|
708
|
+
? capped !== hinted.contextWindow
|
|
709
|
+
? { ...hinted, contextWindow: capped, contextCap: providerCap, contextCapped: true }
|
|
710
|
+
: { ...hinted, contextCap: providerCap, contextCapped: false }
|
|
719
711
|
: hinted;
|
|
712
|
+
const contextWindow = typeof withCap.contextWindow === "number" && withCap.contextWindow > 0
|
|
713
|
+
? withCap.contextWindow
|
|
714
|
+
: undefined;
|
|
715
|
+
const boundedMaxInput = typeof withCap.maxInputTokens === "number" && withCap.maxInputTokens > 0
|
|
716
|
+
? (contextWindow !== undefined ? Math.min(withCap.maxInputTokens, contextWindow) : withCap.maxInputTokens)
|
|
717
|
+
: undefined;
|
|
718
|
+
const withHardBounds = boundedMaxInput !== undefined && boundedMaxInput !== withCap.maxInputTokens
|
|
719
|
+
? { ...withCap, maxInputTokens: boundedMaxInput }
|
|
720
|
+
: withCap;
|
|
721
|
+
const softCandidates = [model.autoCompactTokenLimit, configuredAutoCompact]
|
|
722
|
+
.filter((value): value is number => typeof value === "number" && value > 0);
|
|
723
|
+
if (contextWindow === undefined || softCandidates.length === 0) return withHardBounds;
|
|
724
|
+
return {
|
|
725
|
+
...withHardBounds,
|
|
726
|
+
autoCompactTokenLimit: clampAutoCompactTokenLimit(
|
|
727
|
+
contextWindow,
|
|
728
|
+
boundedMaxInput,
|
|
729
|
+
Math.min(...softCandidates),
|
|
730
|
+
),
|
|
731
|
+
};
|
|
720
732
|
}
|
|
721
733
|
|
|
722
734
|
export function catalogHintsFromProviderConfig(name: string, prov: OcxProviderConfig, id: string, contextCap?: number): Partial<CatalogModel> {
|
|
@@ -743,6 +755,7 @@ interface ComboCatalogMemberFallback {
|
|
|
743
755
|
readonly contextWindow?: number;
|
|
744
756
|
/** Input ceiling when it is lower than the window (native GPT-5.6: 922k under 1.05M). */
|
|
745
757
|
readonly maxInputTokens?: number;
|
|
758
|
+
readonly autoCompactTokenLimit?: number;
|
|
746
759
|
readonly inputModalities?: readonly string[];
|
|
747
760
|
readonly reasoningEfforts?: readonly string[];
|
|
748
761
|
}
|
|
@@ -771,26 +784,33 @@ export function resolveComboCatalogMember(
|
|
|
771
784
|
if (prov?.disabled === true) return undefined;
|
|
772
785
|
|
|
773
786
|
const withFallbackMetadata = (member: CatalogModel): CatalogModel => {
|
|
774
|
-
if (!fallback) return member;
|
|
775
787
|
const contextWindow = typeof member.contextWindow === "number" && member.contextWindow > 0
|
|
776
788
|
? member.contextWindow
|
|
777
789
|
: undefined;
|
|
778
|
-
const addMaxInput = contextWindow !== undefined
|
|
790
|
+
const addMaxInput = fallback !== undefined && contextWindow !== undefined
|
|
779
791
|
&& !(typeof member.maxInputTokens === "number" && member.maxInputTokens > 0);
|
|
792
|
+
const effectiveMaxInput = addMaxInput
|
|
793
|
+
? Math.min(fallback?.maxInputTokens ?? contextWindow!, contextWindow!)
|
|
794
|
+
: member.maxInputTokens;
|
|
795
|
+
const softCandidates = [member.autoCompactTokenLimit, fallback?.autoCompactTokenLimit]
|
|
796
|
+
.filter((value): value is number => typeof value === "number" && value > 0);
|
|
797
|
+
const autoCompactTokenLimit = contextWindow !== undefined && softCandidates.length > 0
|
|
798
|
+
? clampAutoCompactTokenLimit(contextWindow, effectiveMaxInput, Math.min(...softCandidates))
|
|
799
|
+
: member.autoCompactTokenLimit;
|
|
800
|
+
const adjustAutoCompact = autoCompactTokenLimit !== member.autoCompactTokenLimit;
|
|
780
801
|
const addModalities = (!Array.isArray(member.inputModalities) || member.inputModalities.length === 0)
|
|
781
|
-
&& fallback
|
|
802
|
+
&& fallback?.inputModalities !== undefined;
|
|
782
803
|
const addReasoning = member.reasoningEfforts === undefined
|
|
783
|
-
&& fallback
|
|
784
|
-
if (!addMaxInput && !addModalities && !addReasoning) return member;
|
|
804
|
+
&& fallback?.reasoningEfforts !== undefined;
|
|
805
|
+
if (!addMaxInput && !adjustAutoCompact && !addModalities && !addReasoning) return member;
|
|
785
806
|
return {
|
|
786
807
|
...member,
|
|
787
808
|
// Never claim a larger input budget than the window, and prefer the model's own
|
|
788
809
|
// measured ceiling when the fallback carries one.
|
|
789
|
-
...(addMaxInput
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
...(
|
|
793
|
-
...(addReasoning ? { reasoningEfforts: [...fallback.reasoningEfforts!] } : {}),
|
|
810
|
+
...(addMaxInput ? { maxInputTokens: effectiveMaxInput } : {}),
|
|
811
|
+
...(adjustAutoCompact && autoCompactTokenLimit !== undefined ? { autoCompactTokenLimit } : {}),
|
|
812
|
+
...(addModalities ? { inputModalities: [...fallback!.inputModalities!] } : {}),
|
|
813
|
+
...(addReasoning ? { reasoningEfforts: [...fallback!.reasoningEfforts!] } : {}),
|
|
794
814
|
};
|
|
795
815
|
};
|
|
796
816
|
|
|
@@ -871,6 +891,20 @@ export function resolveComboCatalogMember(
|
|
|
871
891
|
const maxInputTokens = effectiveMaxInput !== undefined
|
|
872
892
|
? Math.min(effectiveMaxInput, contextWindow)
|
|
873
893
|
: contextWindow;
|
|
894
|
+
const softCandidates = [
|
|
895
|
+
hinted.autoCompactTokenLimit,
|
|
896
|
+
base.autoCompactTokenLimit,
|
|
897
|
+
fallback?.autoCompactTokenLimit,
|
|
898
|
+
configuredAutoCompactTokenLimit(prov, target.model),
|
|
899
|
+
].filter((value): value is number => typeof value === "number" && value > 0);
|
|
900
|
+
// A generic 128k synthesis is a catalog compatibility fallback, not evidence
|
|
901
|
+
// that a configured soft policy has an authoritative window to clamp against.
|
|
902
|
+
const hasAuthoritativeAutoCompactBasis = hintedContext !== undefined
|
|
903
|
+
|| fallbackContext !== undefined
|
|
904
|
+
|| contextCap !== undefined;
|
|
905
|
+
const autoCompactTokenLimit = hasAuthoritativeAutoCompactBasis && softCandidates.length > 0
|
|
906
|
+
? clampAutoCompactTokenLimit(contextWindow, maxInputTokens, Math.min(...softCandidates))
|
|
907
|
+
: undefined;
|
|
874
908
|
|
|
875
909
|
return {
|
|
876
910
|
...hinted,
|
|
@@ -878,6 +912,7 @@ export function resolveComboCatalogMember(
|
|
|
878
912
|
...(reasoningEfforts !== undefined ? { reasoningEfforts } : {}),
|
|
879
913
|
contextWindow,
|
|
880
914
|
maxInputTokens,
|
|
915
|
+
...(autoCompactTokenLimit !== undefined ? { autoCompactTokenLimit } : {}),
|
|
881
916
|
...(fallbackCapped ? { contextCap, contextCapped: true as const } : {}),
|
|
882
917
|
};
|
|
883
918
|
}
|
|
@@ -1088,9 +1123,6 @@ export function catalogHintsFromModelsApiItem(providerName: string, item: Provid
|
|
|
1088
1123
|
item.max_input_length,
|
|
1089
1124
|
item.max_prompt_tokens,
|
|
1090
1125
|
);
|
|
1091
|
-
// Output ceilings only. A top-level `max_tokens` is ambiguous (some catalogs
|
|
1092
|
-
// use it as context) and generated jawcode `maxTokens` is output-only — never
|
|
1093
|
-
// treat either as a context window.
|
|
1094
1126
|
const maxOutputTokens = positiveSafeInteger(
|
|
1095
1127
|
limits?.max_output_tokens,
|
|
1096
1128
|
item.max_output_tokens,
|
|
@@ -1219,8 +1251,10 @@ async function fetchProviderModelsWithAuth(
|
|
|
1219
1251
|
clearProviderDiscoveryStatus(name);
|
|
1220
1252
|
return observed(configured, "authoritative");
|
|
1221
1253
|
}
|
|
1254
|
+
const cloudCodeAssist = effectiveGoogleMode(name, prov) === "cloud-code-assist";
|
|
1255
|
+
const antigravityOAuth = isAntigravityOAuthProvider(name, prov);
|
|
1222
1256
|
const auth: ModelsAuthResolution = captured.observedAuth ?? (resolveAuth.kind === "refreshing"
|
|
1223
|
-
?
|
|
1257
|
+
? antigravityOAuth && cloudCodeAssist
|
|
1224
1258
|
? await getValidAccessTokenSnapshot(name)
|
|
1225
1259
|
.then(snapshot => ({
|
|
1226
1260
|
apiKey: snapshot.accessToken,
|
|
@@ -1304,14 +1338,14 @@ async function fetchProviderModelsWithAuth(
|
|
|
1304
1338
|
"degraded",
|
|
1305
1339
|
);
|
|
1306
1340
|
}
|
|
1307
|
-
if (prov.authMode === "oauth" && !apiKey) {
|
|
1341
|
+
if ((prov.authMode === "oauth" || antigravityOAuth) && !apiKey) {
|
|
1308
1342
|
// No usable token (logged out, or account marked needsReauth). Still surface the
|
|
1309
1343
|
// configured static catalog so the GUI Models tab / rail counts are not empty —
|
|
1310
1344
|
// matching Cursor's !apiKey → configured degradation and fetch-failure fallback.
|
|
1311
1345
|
return observed(configured, "degraded");
|
|
1312
1346
|
}
|
|
1313
|
-
|
|
1314
|
-
const project = prov.project ?? auth.oauthProjectId;
|
|
1347
|
+
if (antigravityOAuth && !cloudCodeAssist) return observed(configured, "degraded");
|
|
1348
|
+
const project = antigravityOAuth ? auth.oauthProjectId : prov.project ?? auth.oauthProjectId;
|
|
1315
1349
|
if (cloudCodeAssist && !project) return observed(configured, "degraded");
|
|
1316
1350
|
const fresh = getFreshCached(name, ttlMs);
|
|
1317
1351
|
if (fresh) {
|
|
@@ -1328,13 +1362,9 @@ async function fetchProviderModelsWithAuth(
|
|
|
1328
1362
|
const stale = getStaleCached(name);
|
|
1329
1363
|
return observed(
|
|
1330
1364
|
withConfiguredRetention(
|
|
1331
|
-
|
|
1365
|
+
stale
|
|
1332
1366
|
? withVertexDefaultSeed(applyConfigHintsToCachedModels(name, prov, stale, contextCap))
|
|
1333
|
-
: failedDiscoveryConfigured
|
|
1334
|
-
).map(model => enrichCatalogModelMetadata(model, {
|
|
1335
|
-
liveFresh: false,
|
|
1336
|
-
caps: capsFromProvider(prov, model.id, contextCap),
|
|
1337
|
-
})),
|
|
1367
|
+
: failedDiscoveryConfigured,
|
|
1338
1368
|
),
|
|
1339
1369
|
"degraded",
|
|
1340
1370
|
);
|
|
@@ -1361,14 +1391,12 @@ async function fetchProviderModelsWithAuth(
|
|
|
1361
1391
|
markModelsFetchFailure(name);
|
|
1362
1392
|
markProviderDiscoveryFailed(name, failure);
|
|
1363
1393
|
const stale = getStaleCached(name);
|
|
1364
|
-
const fallbackModels = stale
|
|
1365
|
-
? withVertexDefaultSeed(applyConfigHintsToCachedModels(name, prov, stale, contextCap))
|
|
1366
|
-
: failedDiscoveryConfigured;
|
|
1367
1394
|
return {
|
|
1368
|
-
models: withConfiguredRetention(
|
|
1369
|
-
|
|
1370
|
-
|
|
1371
|
-
|
|
1395
|
+
models: withConfiguredRetention(
|
|
1396
|
+
stale
|
|
1397
|
+
? withVertexDefaultSeed(applyConfigHintsToCachedModels(name, prov, stale, contextCap))
|
|
1398
|
+
: failedDiscoveryConfigured,
|
|
1399
|
+
),
|
|
1372
1400
|
fallback: stale ? "stale" : "configured",
|
|
1373
1401
|
shouldLog,
|
|
1374
1402
|
};
|
|
@@ -1435,40 +1463,19 @@ async function fetchProviderModelsWithAuth(
|
|
|
1435
1463
|
return observed(models, "degraded");
|
|
1436
1464
|
}
|
|
1437
1465
|
if (antigravity) {
|
|
1438
|
-
const
|
|
1439
|
-
|
|
1440
|
-
|
|
1441
|
-
|
|
1442
|
-
|
|
1443
|
-
|
|
1444
|
-
|
|
1445
|
-
|
|
1446
|
-
|
|
1447
|
-
};
|
|
1448
|
-
if (model.contextWindow || model.inputModalities) {
|
|
1449
|
-
snapshotRows.push({
|
|
1450
|
-
id: model.id,
|
|
1451
|
-
...(model.contextWindow ? { contextWindow: model.contextWindow } : {}),
|
|
1452
|
-
...(model.inputModalities ? { inputModalities: model.inputModalities } : {}),
|
|
1453
|
-
observedAt,
|
|
1454
|
-
});
|
|
1455
|
-
}
|
|
1456
|
-
const enriched = enrichCatalogModelMetadata({
|
|
1457
|
-
id: model.id,
|
|
1458
|
-
provider: name,
|
|
1459
|
-
...hints,
|
|
1460
|
-
...(model.contextWindow ? { metadataSource: "live" as const, metadataObservedAt: observedAt } : {}),
|
|
1461
|
-
}, {
|
|
1462
|
-
liveFresh: true,
|
|
1463
|
-
caps: capsFromProvider(prov, model.id, contextCap),
|
|
1464
|
-
});
|
|
1465
|
-
return applyProviderConfigHints(name, prov, enriched, contextCap);
|
|
1466
|
-
});
|
|
1466
|
+
const live = antigravity.map(model => applyProviderConfigHints(name, prov, {
|
|
1467
|
+
id: model.id,
|
|
1468
|
+
provider: name,
|
|
1469
|
+
// CCA only exposes a numeric thinking budget. Until the adapter owns an exact Codex
|
|
1470
|
+
// effort-to-wire mapping for a newly discovered model, do not advertise a false ladder.
|
|
1471
|
+
reasoningEfforts: [],
|
|
1472
|
+
...(model.contextWindow ? { contextWindow: model.contextWindow } : {}),
|
|
1473
|
+
...(model.inputModalities ? { inputModalities: model.inputModalities } : {}),
|
|
1474
|
+
}, contextCap));
|
|
1467
1475
|
const forCache = withConfiguredRetention(live, { retainComboTargets: false });
|
|
1468
1476
|
if (!setCached(name, forCache, Date.now(), cacheGeneration)) {
|
|
1469
1477
|
return observed(withConfiguredRetention(configured), "degraded");
|
|
1470
1478
|
}
|
|
1471
|
-
persistLiveModelMetadata(name, snapshotRows, { writerGeneration: cacheGeneration, observedAt });
|
|
1472
1479
|
registerAntigravityDiscoveredWireModels(prov.baseUrl, antigravity, {
|
|
1473
1480
|
provider: name,
|
|
1474
1481
|
cacheGeneration,
|
|
@@ -1493,30 +1500,22 @@ async function fetchProviderModelsWithAuth(
|
|
|
1493
1500
|
return observed(models, "degraded");
|
|
1494
1501
|
}
|
|
1495
1502
|
const items = extracted.items;
|
|
1496
|
-
const observedAt = new Date().toISOString();
|
|
1497
|
-
const snapshotRows: LiveSnapshotRow[] = [];
|
|
1498
1503
|
const live = items.map(m => {
|
|
1499
1504
|
const ownedBy = boundedOwnedBy(m.owned_by);
|
|
1500
|
-
|
|
1501
|
-
const discovered = Boolean(hints.contextWindow || hints.maxInputTokens || hints.maxOutputTokens
|
|
1502
|
-
|| hints.inputModalities || hints.capabilities || hints.reasoningEfforts);
|
|
1503
|
-
if (discovered) {
|
|
1504
|
-
snapshotRows.push({ id: m.id, ...hints, observedAt });
|
|
1505
|
-
}
|
|
1506
|
-
const enriched = enrichCatalogModelMetadata({
|
|
1505
|
+
return applyProviderConfigHints(name, prov, {
|
|
1507
1506
|
id: m.id,
|
|
1508
1507
|
provider: name,
|
|
1509
1508
|
...(ownedBy ? { owned_by: ownedBy } : {}),
|
|
1510
|
-
...
|
|
1511
|
-
|
|
1512
|
-
}, {
|
|
1513
|
-
liveFresh: true,
|
|
1514
|
-
caps: capsFromProvider(prov, m.id, contextCap),
|
|
1515
|
-
});
|
|
1516
|
-
return applyProviderConfigHints(name, prov, enriched, contextCap);
|
|
1509
|
+
...catalogHintsFromModelsApiItem(name, m),
|
|
1510
|
+
}, contextCap);
|
|
1517
1511
|
})
|
|
1518
1512
|
.filter(m => shouldExposeProviderModel(name, m.id));
|
|
1513
|
+
// Capture the count BEFORE the alias/configured augmentation below pushes extra rows into
|
|
1514
|
+
// `live`; otherwise configured entries would be reported as discovered ones.
|
|
1519
1515
|
const liveModelCount = live.length;
|
|
1516
|
+
// Dated-release aliases + configured retention (compat allow-list, combo targets,
|
|
1517
|
+
// Vertex default). Cache without combo retention so a later gather re-applies the
|
|
1518
|
+
// current capture's retain set on read (warm-cache OCX-111 / #1308).
|
|
1520
1519
|
const forCache = withConfiguredRetention(live, { retainComboTargets: false });
|
|
1521
1520
|
const returned = withConfiguredRetention(forCache, { warnDrops: true });
|
|
1522
1521
|
const droppedConfiguredIds = configured
|
|
@@ -1530,7 +1529,6 @@ async function fetchProviderModelsWithAuth(
|
|
|
1530
1529
|
if (!setCached(name, forCache, Date.now(), cacheGeneration)) {
|
|
1531
1530
|
return observed(withConfiguredRetention(configured), "degraded");
|
|
1532
1531
|
}
|
|
1533
|
-
persistLiveModelMetadata(name, snapshotRows, { writerGeneration: cacheGeneration, observedAt });
|
|
1534
1532
|
markProviderDiscoveryOk(name, liveModelCount);
|
|
1535
1533
|
return observed(returned, "authoritative");
|
|
1536
1534
|
} catch (error) {
|
|
@@ -1641,7 +1639,24 @@ export function filterCatalogVisibleModels(
|
|
|
1641
1639
|
const allowByProvider = new Map<string, Set<string>>();
|
|
1642
1640
|
for (const [name, prov] of Object.entries(config.providers)) {
|
|
1643
1641
|
const sel = prov.selectedModels;
|
|
1644
|
-
|
|
1642
|
+
// Keyed the way `sync.ts` keys the same list, so a slash-bearing native id and
|
|
1643
|
+
// the encoded slug the Codex picker displays are one entry rather than two. A
|
|
1644
|
+
// bare `Set(sel)` matched only the native form, so an allowlist written from the
|
|
1645
|
+
// displayed slug — which `ocx models remove` also accepts — hid every model it
|
|
1646
|
+
// was meant to keep.
|
|
1647
|
+
//
|
|
1648
|
+
// The key is deliberately lossy: `p/a/b` and `p/a-b` collapse to one entry, so a
|
|
1649
|
+
// provider publishing both spellings has them selected together. That is a real
|
|
1650
|
+
// limitation, pinned by the tests below and tracked as a follow-up; it is NOT
|
|
1651
|
+
// fixed here. Resolving selections against the current roster instead was tried
|
|
1652
|
+
// and rejected — the roster is an incomplete dictionary (live discovery can omit
|
|
1653
|
+
// a published id), so it produces the same over-grant while additionally
|
|
1654
|
+
// disagreeing with the `slugEquivalenceKey` contract `sync.ts` uses at merge time.
|
|
1655
|
+
// Two catalog stages with different equivalence relations is the exact bug class
|
|
1656
|
+
// this change exists to remove.
|
|
1657
|
+
if (Array.isArray(sel) && sel.length > 0) {
|
|
1658
|
+
allowByProvider.set(name, new Set(sel.map(model => slugEquivalenceKey(routedSlug(name, model)))));
|
|
1659
|
+
}
|
|
1645
1660
|
}
|
|
1646
1661
|
return models.filter(m => {
|
|
1647
1662
|
const nativeAlias = m.provider === COMBO_NAMESPACE && m.nativeAlias === true;
|
|
@@ -1653,7 +1668,7 @@ export function filterCatalogVisibleModels(
|
|
|
1653
1668
|
if (slugEquals(stored, m.provider, m.id)) return false;
|
|
1654
1669
|
}
|
|
1655
1670
|
const allow = allowByProvider.get(m.provider);
|
|
1656
|
-
return !allow || allow.has(m.id);
|
|
1671
|
+
return !allow || allow.has(slugEquivalenceKey(routedSlug(m.provider, m.id)));
|
|
1657
1672
|
});
|
|
1658
1673
|
}
|
|
1659
1674
|
|
|
@@ -1838,6 +1853,7 @@ async function gatherRoutedModelsUncached(
|
|
|
1838
1853
|
// stay separate fields because routed/API rows of the same family run a wider window.
|
|
1839
1854
|
// Falls back to the window for slugs with no separate ceiling.
|
|
1840
1855
|
maxInputTokens: Math.min(nativeOpenAiMaxInputTokens(slug, openaiContextCap) ?? contextWindow, contextWindow),
|
|
1856
|
+
autoCompactTokenLimit: nativeOpenAiAutoCompactTokenLimit(slug, openaiContextCap),
|
|
1841
1857
|
inputModalities: nativeInputModalities(slug),
|
|
1842
1858
|
reasoningEfforts: nativeReasoningEfforts(slug),
|
|
1843
1859
|
...(nativeParallelToolCalls(slug) ? { parallelToolCalls: true } : {}),
|
|
@@ -1854,18 +1870,23 @@ async function gatherRoutedModelsUncached(
|
|
|
1854
1870
|
for (const id of listComboIds(config)) {
|
|
1855
1871
|
const combo = getCombo(config, id);
|
|
1856
1872
|
if (!combo) continue;
|
|
1873
|
+
const comboNativeLimits = nativeContextLimits(config);
|
|
1857
1874
|
const nativeContextWindow = combo.nativeAlias && combo.alias
|
|
1858
|
-
? nativeOpenAiContextWindow(combo.alias,
|
|
1875
|
+
? nativeOpenAiContextWindow(combo.alias, comboNativeLimits)
|
|
1859
1876
|
: undefined;
|
|
1860
1877
|
const nativeAliasMaxInput = combo.nativeAlias && combo.alias
|
|
1861
1878
|
? (combo.alias.startsWith("gpt-5.6-") || combo.alias.includes("daybreak")
|
|
1862
1879
|
? NATIVE_GPT56_MAX_INPUT_TOKENS
|
|
1863
1880
|
: nativeOpenAiMaxInputTokens(combo.alias) ?? nativeOpenAiContextWindow(combo.alias))
|
|
1864
1881
|
: undefined;
|
|
1882
|
+
const nativeAliasAutoCompact = combo.nativeAlias && combo.alias
|
|
1883
|
+
? nativeOpenAiAutoCompactTokenLimit(combo.alias, comboNativeLimits)
|
|
1884
|
+
: undefined;
|
|
1865
1885
|
const nativeAliasFallback = combo.nativeAlias && combo.alias && nativeContextWindow !== undefined
|
|
1866
1886
|
? {
|
|
1867
1887
|
contextWindow: nativeContextWindow,
|
|
1868
1888
|
...(nativeAliasMaxInput !== undefined ? { maxInputTokens: nativeAliasMaxInput } : {}),
|
|
1889
|
+
...(nativeAliasAutoCompact !== undefined ? { autoCompactTokenLimit: nativeAliasAutoCompact } : {}),
|
|
1869
1890
|
inputModalities: nativeInputModalities(combo.alias),
|
|
1870
1891
|
reasoningEfforts: nativeReasoningEfforts(combo.alias),
|
|
1871
1892
|
}
|
|
@@ -1928,9 +1949,23 @@ async function gatherRoutedModelsUncached(
|
|
|
1928
1949
|
const nativeAliasMaxInputTokens = codexForwardNativeCapabilityAlias
|
|
1929
1950
|
? nativeOpenAiMaxInputTokens(cm.modelId, customNativeLimits)
|
|
1930
1951
|
: undefined;
|
|
1931
|
-
const
|
|
1932
|
-
?
|
|
1933
|
-
:
|
|
1952
|
+
const configuredMaxInput = rawProvider
|
|
1953
|
+
? configuredMaxInputTokens(rawProvider, cm.modelId)
|
|
1954
|
+
: undefined;
|
|
1955
|
+
const hardMaxCandidates = [nativeAliasMaxInputTokens, configuredMaxInput]
|
|
1956
|
+
.filter((value): value is number => typeof value === "number" && value > 0);
|
|
1957
|
+
const customMaxInputTokens = hardMaxCandidates.length > 0
|
|
1958
|
+
? Math.min(
|
|
1959
|
+
...hardMaxCandidates,
|
|
1960
|
+
...(customContextWindow !== undefined ? [customContextWindow] : []),
|
|
1961
|
+
)
|
|
1962
|
+
: undefined;
|
|
1963
|
+
const configuredAutoCompact = configuredAutoCompactTokenLimit(rawProvider, cm.modelId);
|
|
1964
|
+
const customAutoCompactTokenLimit = codexForwardNativeCapabilityAlias
|
|
1965
|
+
? nativeOpenAiAutoCompactTokenLimit(cm.modelId, customNativeLimits)
|
|
1966
|
+
: customContextWindow !== undefined && configuredAutoCompact !== undefined
|
|
1967
|
+
? clampAutoCompactTokenLimit(customContextWindow, customMaxInputTokens, configuredAutoCompact)
|
|
1968
|
+
: undefined;
|
|
1934
1969
|
const nativeAliasDefaultEffort = codexForwardNativeCapabilityAlias
|
|
1935
1970
|
? nativeDefaultReasoningEffort(cm.modelId)
|
|
1936
1971
|
: undefined;
|
|
@@ -1951,6 +1986,7 @@ async function gatherRoutedModelsUncached(
|
|
|
1951
1986
|
: codexForwardNativeCapabilityAlias ? { displayName: "Daybreak Blue" } : {}),
|
|
1952
1987
|
...(customContextWindow !== undefined ? { contextWindow: customContextWindow } : {}),
|
|
1953
1988
|
...(customMaxInputTokens !== undefined ? { maxInputTokens: customMaxInputTokens } : {}),
|
|
1989
|
+
...(customAutoCompactTokenLimit !== undefined ? { autoCompactTokenLimit: customAutoCompactTokenLimit } : {}),
|
|
1954
1990
|
...(cm.inputModalities
|
|
1955
1991
|
? { inputModalities: cm.inputModalities }
|
|
1956
1992
|
: codexForwardNativeCapabilityAlias ? { inputModalities: nativeInputModalities(cm.modelId) } : {}),
|
|
@@ -1996,10 +2032,18 @@ async function gatherRoutedModelsUncached(
|
|
|
1996
2032
|
// along when it is actually a member — otherwise a provider default like "xhigh" would
|
|
1997
2033
|
// re-apply onto a narrower custom ladder and override the fallback in applyReasoningLevels.
|
|
1998
2034
|
const effectiveLadder = base.reasoningEfforts ?? replaced?.reasoningEfforts;
|
|
2035
|
+
const mergedMaxInputCandidates = [base.maxInputTokens, replaced?.maxInputTokens]
|
|
2036
|
+
.filter((value): value is number => typeof value === "number" && value > 0);
|
|
2037
|
+
const mergedMaxInput = mergedMaxInputCandidates.length > 0
|
|
2038
|
+
? Math.min(...mergedMaxInputCandidates)
|
|
2039
|
+
: undefined;
|
|
1999
2040
|
const merged: CatalogModel = replaced ? {
|
|
2000
2041
|
...base,
|
|
2001
2042
|
...(base.contextWindow === undefined && replaced.contextWindow !== undefined ? { contextWindow: replaced.contextWindow } : {}),
|
|
2002
|
-
...(
|
|
2043
|
+
...(mergedMaxInput !== undefined ? { maxInputTokens: mergedMaxInput } : {}),
|
|
2044
|
+
...(base.autoCompactTokenLimit === undefined && replaced.autoCompactTokenLimit !== undefined
|
|
2045
|
+
? { autoCompactTokenLimit: replaced.autoCompactTokenLimit }
|
|
2046
|
+
: {}),
|
|
2003
2047
|
...(base.inputModalities === undefined && replaced.inputModalities !== undefined ? { inputModalities: replaced.inputModalities } : {}),
|
|
2004
2048
|
...(base.reasoningEfforts === undefined && replaced.reasoningEfforts !== undefined ? { reasoningEfforts: replaced.reasoningEfforts } : {}),
|
|
2005
2049
|
...(base.defaultReasoningEffort === undefined && replaced.defaultReasoningEffort !== undefined
|
|
@@ -2016,14 +2060,36 @@ async function gatherRoutedModelsUncached(
|
|
|
2016
2060
|
// (#349/#344). Deliberately NOT the full applyProviderConfigHints pass — custom rows are a
|
|
2017
2061
|
// user override, so their explicit contextWindow / inputModalities / reasoning fields must be
|
|
2018
2062
|
// preserved verbatim (the hint pass would cap context and overwrite modalities from registry).
|
|
2063
|
+
const mergedContext = typeof merged.contextWindow === "number" && merged.contextWindow > 0
|
|
2064
|
+
? merged.contextWindow
|
|
2065
|
+
: undefined;
|
|
2066
|
+
const boundedMergedMaxInput = typeof merged.maxInputTokens === "number" && merged.maxInputTokens > 0
|
|
2067
|
+
? (mergedContext !== undefined ? Math.min(merged.maxInputTokens, mergedContext) : merged.maxInputTokens)
|
|
2068
|
+
: undefined;
|
|
2069
|
+
const mergedWithHardBounds = boundedMergedMaxInput !== undefined
|
|
2070
|
+
&& boundedMergedMaxInput !== merged.maxInputTokens
|
|
2071
|
+
? { ...merged, maxInputTokens: boundedMergedMaxInput }
|
|
2072
|
+
: merged;
|
|
2073
|
+
const mergedSoftCandidates = [mergedWithHardBounds.autoCompactTokenLimit, configuredAutoCompact]
|
|
2074
|
+
.filter((value): value is number => typeof value === "number" && value > 0);
|
|
2075
|
+
const mergedWithAutoCompact: CatalogModel = mergedContext !== undefined && mergedSoftCandidates.length > 0
|
|
2076
|
+
? {
|
|
2077
|
+
...mergedWithHardBounds,
|
|
2078
|
+
autoCompactTokenLimit: clampAutoCompactTokenLimit(
|
|
2079
|
+
mergedContext,
|
|
2080
|
+
boundedMergedMaxInput,
|
|
2081
|
+
Math.min(...mergedSoftCandidates),
|
|
2082
|
+
),
|
|
2083
|
+
}
|
|
2084
|
+
: mergedWithHardBounds;
|
|
2019
2085
|
const enrichedProvider = enrichedByName.get(cm.provider) ?? rawProvider;
|
|
2020
|
-
if (enrichedProvider && modelInList(enrichedProvider.noVisionModels,
|
|
2021
|
-
const current =
|
|
2086
|
+
if (enrichedProvider && modelInList(enrichedProvider.noVisionModels, mergedWithAutoCompact.id)) {
|
|
2087
|
+
const current = mergedWithAutoCompact.inputModalities ?? ["text"];
|
|
2022
2088
|
if (!current.includes("image")) {
|
|
2023
|
-
return { ...
|
|
2089
|
+
return { ...mergedWithAutoCompact, inputModalities: [...current, "image"] };
|
|
2024
2090
|
}
|
|
2025
2091
|
}
|
|
2026
|
-
return
|
|
2092
|
+
return mergedWithAutoCompact;
|
|
2027
2093
|
});
|
|
2028
2094
|
// Custom rows override discovered rows that encode to the same Codex-facing slug.
|
|
2029
2095
|
const customKeys = new Set(customModels.map(c => routedSlug(c.provider, c.id)));
|
|
@@ -2079,7 +2145,15 @@ function augmentRoutedModelsWithCapturedOpenAiApiRows(
|
|
|
2079
2145
|
? Math.min(officialContext, userContext ?? officialContext, providerCap ?? officialContext)
|
|
2080
2146
|
: undefined;
|
|
2081
2147
|
const maxInputTokens = typeof officialMaxInput === "number"
|
|
2082
|
-
? Math.min(
|
|
2148
|
+
? Math.min(
|
|
2149
|
+
officialMaxInput,
|
|
2150
|
+
userMaxInput ?? officialMaxInput,
|
|
2151
|
+
contextWindow ?? officialMaxInput,
|
|
2152
|
+
)
|
|
2153
|
+
: undefined;
|
|
2154
|
+
const configuredAutoCompact = configuredAutoCompactTokenLimit(configured, id);
|
|
2155
|
+
const autoCompactTokenLimit = contextWindow !== undefined && configuredAutoCompact !== undefined
|
|
2156
|
+
? clampAutoCompactTokenLimit(contextWindow, maxInputTokens, configuredAutoCompact)
|
|
2083
2157
|
: undefined;
|
|
2084
2158
|
return {
|
|
2085
2159
|
provider: OPENAI_API_PROVIDER_ID,
|
|
@@ -2087,6 +2161,7 @@ function augmentRoutedModelsWithCapturedOpenAiApiRows(
|
|
|
2087
2161
|
owned_by: OPENAI_API_PROVIDER_ID,
|
|
2088
2162
|
...(contextWindow ? { contextWindow } : {}),
|
|
2089
2163
|
...(maxInputTokens ? { maxInputTokens } : {}),
|
|
2164
|
+
...(autoCompactTokenLimit !== undefined ? { autoCompactTokenLimit } : {}),
|
|
2090
2165
|
...(policy.modelInputModalities?.[id] ? { inputModalities: [...policy.modelInputModalities[id]!] } : {}),
|
|
2091
2166
|
...(policy.modelReasoningEfforts?.[id] ? { reasoningEfforts: [...policy.modelReasoningEfforts[id]!] } : {}),
|
|
2092
2167
|
};
|
|
@@ -2116,14 +2191,7 @@ export function augmentRoutedModelsWithMetadata(
|
|
|
2116
2191
|
providers?: Record<string, OcxProviderConfig>,
|
|
2117
2192
|
caps?: Pick<OcxConfig, "providerContextCaps">,
|
|
2118
2193
|
): CatalogModel[] {
|
|
2119
|
-
const out = models
|
|
2120
|
-
const provider = providers?.[model.provider];
|
|
2121
|
-
const contextCap = caps ? providerContextCap(caps, model.provider) : undefined;
|
|
2122
|
-
return enrichCatalogModelMetadata(model, {
|
|
2123
|
-
liveFresh: model.metadataSource === "live" && model.metadataStale !== true,
|
|
2124
|
-
caps: capsFromProvider(provider, model.id, contextCap),
|
|
2125
|
-
});
|
|
2126
|
-
});
|
|
2194
|
+
const out = [...models];
|
|
2127
2195
|
const seen = new Set(out.map(m => `${m.provider}/${m.id}`));
|
|
2128
2196
|
for (const provider of providerNames) {
|
|
2129
2197
|
if (!JAWCODE_CATALOG_AUGMENT_PROVIDERS.has(provider)) continue;
|
|
@@ -2142,13 +2210,10 @@ export function augmentRoutedModelsWithMetadata(
|
|
|
2142
2210
|
...(typeof meta.contextWindow === "number" && meta.contextWindow > 0 ? { contextWindow: meta.contextWindow } : {}),
|
|
2143
2211
|
...(Array.isArray(meta.input) && meta.input.length > 0 ? { inputModalities: [...meta.input] } : {}),
|
|
2144
2212
|
};
|
|
2145
|
-
|
|
2146
|
-
|
|
2147
|
-
:
|
|
2148
|
-
|
|
2149
|
-
liveFresh: false,
|
|
2150
|
-
caps: capsFromProvider(providers?.[provider], meta.id, contextCap),
|
|
2151
|
-
}));
|
|
2213
|
+
out.push({
|
|
2214
|
+
...model,
|
|
2215
|
+
...(providers?.[provider] ? applyProviderConfigHints(provider, providers[provider], model, contextCap) : {}),
|
|
2216
|
+
});
|
|
2152
2217
|
}
|
|
2153
2218
|
}
|
|
2154
2219
|
return out;
|
|
@@ -1158,7 +1158,7 @@ export function mergeCatalogEntriesForSync(
|
|
|
1158
1158
|
isNativeAliasCatalogEntry(entry) && typeof entry.slug === "string" ? [entry.slug] : []
|
|
1159
1159
|
)),
|
|
1160
1160
|
),
|
|
1161
|
-
openaiContextCap?:
|
|
1161
|
+
openaiContextCap?: NativeContextLimitsInput,
|
|
1162
1162
|
keepNativeChatGptOnV1 = false,
|
|
1163
1163
|
): RawEntry[] {
|
|
1164
1164
|
// Retained for source compatibility with the original helper contract. Raw provider ids must
|
package/src/codex/convergence.ts
CHANGED
|
@@ -54,6 +54,7 @@ import {
|
|
|
54
54
|
disabledNativeSlugs,
|
|
55
55
|
desktopAllowlistSuppressedNativeSlugs,
|
|
56
56
|
NATIVE_OPENAI_MODELS,
|
|
57
|
+
nativeContextLimits,
|
|
57
58
|
shouldIncludeAccountBoundNativeOpenAi,
|
|
58
59
|
shouldIncludeNativeOpenAi,
|
|
59
60
|
} from "./catalog/metadata";
|
|
@@ -286,6 +287,7 @@ function prepareCatalog(
|
|
|
286
287
|
// selector-qualified rows when a live selector is configured.
|
|
287
288
|
const observedNativeSlugs: string[] = [];
|
|
288
289
|
const disabledNative = disabledNativeSlugs(config);
|
|
290
|
+
const openaiContextCap = nativeContextLimits(config);
|
|
289
291
|
const nativeCatalogModels = mergeCatalogModelsWithNativeRecovery(
|
|
290
292
|
active?.models ?? catalog.models ?? [],
|
|
291
293
|
[catalog.models ?? [], ...nativeRecoverySources],
|
|
@@ -304,6 +306,7 @@ function prepareCatalog(
|
|
|
304
306
|
suppressedBareNativeSlugs,
|
|
305
307
|
disabledNativeAccountSlugs: new Set(),
|
|
306
308
|
multiAgentV2Enabled,
|
|
309
|
+
openaiContextCap,
|
|
307
310
|
});
|
|
308
311
|
const accountBoundEntries = accountSelectors.length === 0
|
|
309
312
|
? []
|
|
@@ -320,6 +323,7 @@ function prepareCatalog(
|
|
|
320
323
|
disabledNativeAccountSlugs: new Set([...disabledNative].filter(slug => suppressedBareNativeSlugs.has(slug))),
|
|
321
324
|
multiAgentV2Enabled,
|
|
322
325
|
keepNativeChatGptOnV1: config.keepNativeChatGptOnV1 === true,
|
|
326
|
+
openaiContextCap,
|
|
323
327
|
accountNativeSlugs,
|
|
324
328
|
accountNativeSlugsBySelector,
|
|
325
329
|
}).filter(entry => trustedAccountBoundNativeCatalogSlug(entry) !== undefined);
|
|
@@ -352,6 +356,7 @@ function prepareCatalog(
|
|
|
352
356
|
includeNativeOpenAi,
|
|
353
357
|
accountBoundEntries,
|
|
354
358
|
suppressedBareNativeSlugs,
|
|
359
|
+
openaiContextCap,
|
|
355
360
|
policy: {
|
|
356
361
|
...CANONICAL_NATIVE_CATALOG_CONTENT_POLICY,
|
|
357
362
|
nativeBackfillSlugs: [...availableBareNativeSlugs, ...observedNativeSlugs],
|