@oh-my-pi/pi-coding-agent 16.2.11 → 16.2.13
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/CHANGELOG.md +38 -0
- package/dist/cli.js +2982 -2825
- package/dist/types/cli/bench-cli.d.ts +0 -5
- package/dist/types/cli/dry-balance-cli.d.ts +0 -5
- package/dist/types/cli/models-cli.d.ts +1 -1
- package/dist/types/config/inline-tool-descriptors-mode.d.ts +1 -2
- package/dist/types/config/model-registry.d.ts +1 -23
- package/dist/types/config/model-resolver.d.ts +10 -15
- package/dist/types/config/models-config-schema.d.ts +12 -6
- package/dist/types/config/models-config.d.ts +9 -6
- package/dist/types/config/settings-schema.d.ts +31 -1
- package/dist/types/eval/py/__tests__/runner-shell-output.test.d.ts +1 -0
- package/dist/types/extensibility/extensions/runner.d.ts +15 -0
- package/dist/types/lsp/client.d.ts +9 -3
- package/dist/types/modes/controllers/tool-args-reveal.d.ts +0 -5
- package/dist/types/task/spawn-policy.d.ts +17 -0
- package/dist/types/task/spawn-policy.test.d.ts +1 -0
- package/dist/types/task/types.d.ts +8 -2
- package/dist/types/tools/__tests__/eval-description.test.d.ts +1 -0
- package/dist/types/tools/browser/cmux/cmux-tab.d.ts +2 -2
- package/dist/types/tools/browser/registry.d.ts +2 -0
- package/dist/types/tools/browser/run-cancellation.d.ts +4 -0
- package/dist/types/tools/browser/tab-supervisor.d.ts +30 -1
- package/dist/types/tools/eval.d.ts +3 -6
- package/dist/types/tools/write.d.ts +1 -1
- package/dist/types/utils/image-vision-fallback.d.ts +1 -1
- package/package.json +12 -12
- package/src/advisor/__tests__/advisor.test.ts +1 -1
- package/src/auto-thinking/classifier.ts +1 -1
- package/src/cli/bench-cli.ts +3 -12
- package/src/cli/dry-balance-cli.ts +1 -6
- package/src/cli/models-cli.ts +3 -81
- package/src/commands/models.ts +1 -2
- package/src/commit/model-selection.ts +4 -4
- package/src/config/inline-tool-descriptors-mode.ts +1 -2
- package/src/config/model-discovery.ts +32 -6
- package/src/config/model-registry.ts +11 -225
- package/src/config/model-resolver.ts +23 -135
- package/src/config/models-config-schema.ts +13 -22
- package/src/config/prompt-templates.ts +20 -0
- package/src/config/settings-schema.ts +35 -1
- package/src/config/settings.ts +60 -24
- package/src/eval/__tests__/agent-bridge.test.ts +17 -3
- package/src/eval/agent-bridge.ts +7 -9
- package/src/eval/completion-bridge.ts +1 -1
- package/src/eval/py/__tests__/runner-shell-output.test.ts +157 -0
- package/src/eval/py/runner.py +169 -18
- package/src/extensibility/extensions/model-api.ts +1 -3
- package/src/extensibility/extensions/runner.ts +62 -5
- package/src/lsp/client.ts +162 -45
- package/src/lsp/index.ts +31 -21
- package/src/main.ts +0 -1
- package/src/mcp/transports/http.ts +19 -17
- package/src/mcp/transports/stdio.test.ts +51 -1
- package/src/mcp/transports/stdio.ts +19 -9
- package/src/memories/index.ts +0 -1
- package/src/mnemopi/backend.ts +1 -1
- package/src/modes/components/model-selector.ts +32 -186
- package/src/modes/controllers/event-controller.ts +8 -39
- package/src/modes/controllers/selector-controller.ts +0 -1
- package/src/modes/controllers/tool-args-reveal.ts +0 -12
- package/src/prompts/system/subagent-system-prompt.md +2 -2
- package/src/prompts/system/tool-call-loop-redirect.md +8 -0
- package/src/prompts/tools/eval.md +2 -2
- package/src/prompts/tools/ssh.md +1 -0
- package/src/prompts/tools/task.md +1 -1
- package/src/sdk.ts +2 -9
- package/src/session/agent-session.ts +89 -8
- package/src/session/session-context.ts +2 -1
- package/src/session/session-manager.ts +2 -1
- package/src/session/unexpected-stop-classifier.ts +1 -1
- package/src/task/index.ts +23 -27
- package/src/task/spawn-policy.test.ts +63 -0
- package/src/task/spawn-policy.ts +58 -0
- package/src/task/types.ts +77 -6
- package/src/tools/__tests__/eval-description.test.ts +19 -0
- package/src/tools/browser/cmux/cmux-tab.ts +66 -24
- package/src/tools/browser/registry.ts +25 -0
- package/src/tools/browser/run-cancellation.ts +47 -0
- package/src/tools/browser/tab-supervisor.ts +120 -7
- package/src/tools/browser/tab-worker.ts +22 -10
- package/src/tools/browser.ts +1 -0
- package/src/tools/eval.ts +15 -10
- package/src/tools/inspect-image.ts +1 -1
- package/src/tools/ssh.ts +8 -1
- package/src/tools/write.ts +49 -9
- package/src/utils/commit-message-generator.ts +0 -1
- package/src/utils/image-vision-fallback.ts +2 -3
- package/src/utils/title-generator.ts +1 -1
|
@@ -51,21 +51,7 @@ const LOCAL_PROVIDER_PLACEHOLDERS = new Set<string>(["llama-cpp-local", "lm-stud
|
|
|
51
51
|
import type { ApiKeyResolver, FetchImpl } from "@oh-my-pi/pi-ai";
|
|
52
52
|
import { registerOAuthProvider, unregisterOAuthProviders } from "@oh-my-pi/pi-ai/oauth";
|
|
53
53
|
import type { OAuthCredentials, OAuthLoginCallbacks } from "@oh-my-pi/pi-ai/oauth/types";
|
|
54
|
-
import {
|
|
55
|
-
buildCanonicalModelIndex,
|
|
56
|
-
buildCanonicalModelOrder,
|
|
57
|
-
buildModelProviderPriorityRank,
|
|
58
|
-
type CanonicalModelIndex,
|
|
59
|
-
type CanonicalModelRecord,
|
|
60
|
-
type CanonicalModelVariant,
|
|
61
|
-
type CanonicalVariantPreferences,
|
|
62
|
-
formatCanonicalVariantSelector,
|
|
63
|
-
getBundledCanonicalReferenceData,
|
|
64
|
-
getBundledModelReferenceIndex,
|
|
65
|
-
type ModelEquivalenceConfig,
|
|
66
|
-
resolveCanonicalVariant,
|
|
67
|
-
resolveModelReference,
|
|
68
|
-
} from "@oh-my-pi/pi-catalog/identity";
|
|
54
|
+
import { getBundledModelReferenceIndex, resolveModelReference } from "@oh-my-pi/pi-catalog/identity";
|
|
69
55
|
import { isBunTestRuntime, isRecord, logger } from "@oh-my-pi/pi-utils";
|
|
70
56
|
import { parseModelString, resolveProviderModelReference } from "../config/model-resolver";
|
|
71
57
|
import type { AuthStorage, OAuthCredential } from "../session/auth-storage";
|
|
@@ -85,8 +71,6 @@ import { ModelsConfigFile, type ProviderValidationModel, validateProviderConfigu
|
|
|
85
71
|
import type { ModelOverride, ModelsConfig, ProviderAuthMode } from "./models-config-schema";
|
|
86
72
|
import { settings } from "./settings";
|
|
87
73
|
|
|
88
|
-
export type { CanonicalModelIndex, CanonicalModelRecord, CanonicalModelVariant, ModelEquivalenceConfig };
|
|
89
|
-
|
|
90
74
|
export const kNoAuth = "N/A";
|
|
91
75
|
|
|
92
76
|
export function isAuthenticated(apiKey: string | undefined | null): apiKey is string {
|
|
@@ -243,17 +227,6 @@ export interface ProviderDiscoveryState {
|
|
|
243
227
|
error?: string;
|
|
244
228
|
}
|
|
245
229
|
|
|
246
|
-
export interface CanonicalModelQueryOptions {
|
|
247
|
-
availableOnly?: boolean;
|
|
248
|
-
candidates?: readonly Model<Api>[];
|
|
249
|
-
}
|
|
250
|
-
|
|
251
|
-
/** A canonical record (with query-filtered variants) plus the variant model selected for it. */
|
|
252
|
-
export interface CanonicalModelSelection {
|
|
253
|
-
record: CanonicalModelRecord;
|
|
254
|
-
model: Model<Api>;
|
|
255
|
-
}
|
|
256
|
-
|
|
257
230
|
/** Result of loading custom models from models.json */
|
|
258
231
|
interface CustomModelsResult {
|
|
259
232
|
models?: CustomModelOverlay[];
|
|
@@ -262,7 +235,6 @@ interface CustomModelsResult {
|
|
|
262
235
|
keylessProviders?: Set<string>;
|
|
263
236
|
discoverableProviders?: DiscoveryProviderConfig[];
|
|
264
237
|
configuredProviders?: Set<string>;
|
|
265
|
-
equivalence?: ModelEquivalenceConfig;
|
|
266
238
|
error?: ConfigError;
|
|
267
239
|
found: boolean;
|
|
268
240
|
}
|
|
@@ -718,28 +690,17 @@ function getDisabledProviderIdsFromSettings(): Set<string> {
|
|
|
718
690
|
}
|
|
719
691
|
}
|
|
720
692
|
|
|
721
|
-
function getConfiguredProviderOrderFromSettings(): string[] {
|
|
722
|
-
try {
|
|
723
|
-
return settings.get("modelProviderOrder");
|
|
724
|
-
} catch {
|
|
725
|
-
return [];
|
|
726
|
-
}
|
|
727
|
-
}
|
|
728
|
-
|
|
729
693
|
/**
|
|
730
694
|
* Model registry - loads and manages models, resolves API keys via AuthStorage.
|
|
731
695
|
*/
|
|
732
696
|
export class ModelRegistry {
|
|
733
697
|
#models: Model<Api>[] = [];
|
|
734
|
-
#canonicalIndex: CanonicalModelIndex = { records: [], byId: new Map(), bySelector: new Map() };
|
|
735
|
-
#canonicalIndexDirty: boolean = true;
|
|
736
698
|
#customProviderApiKeys: Map<string, string> = new Map();
|
|
737
699
|
#keylessProviders: Set<string> = new Set();
|
|
738
700
|
#discoverableProviders: DiscoveryProviderConfig[] = [];
|
|
739
701
|
#customModelOverlays: CustomModelOverlay[] = [];
|
|
740
702
|
#providerOverrides: Map<string, ProviderOverride> = new Map();
|
|
741
703
|
#modelOverrides: Map<string, Map<string, ModelOverride>> = new Map();
|
|
742
|
-
#equivalenceConfig: ModelEquivalenceConfig | undefined;
|
|
743
704
|
#configError: ConfigError | undefined = undefined;
|
|
744
705
|
#modelsConfigFile: ConfigFile<ModelsConfig>;
|
|
745
706
|
#lastStaticLoadMtime: number | null = null;
|
|
@@ -759,8 +720,6 @@ export class ModelRegistry {
|
|
|
759
720
|
// Runtime model managers registered by extensions via fetchDynamicModels.
|
|
760
721
|
// Keyed by provider name; use the same SQLite cache path as builtins.
|
|
761
722
|
#runtimeModelManagers: Map<string, { options: ModelManagerOptions<Api>; sourceId: string }> = new Map();
|
|
762
|
-
#rebuildPending: boolean = false;
|
|
763
|
-
#rebuildSuspended: number = 0;
|
|
764
723
|
#fetch: FetchImpl;
|
|
765
724
|
|
|
766
725
|
#resolveCommandBackedApiKey(provider: string): CommandApiKeyResolution {
|
|
@@ -820,14 +779,9 @@ export class ModelRegistry {
|
|
|
820
779
|
* Reload models from disk (built-in + custom from models.json).
|
|
821
780
|
*/
|
|
822
781
|
async refresh(strategy: ModelRefreshStrategy = "online-if-uncached"): Promise<void> {
|
|
823
|
-
this.#
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
this.#suppressedSelectors.clear();
|
|
827
|
-
await this.#refreshRuntimeDiscoveries(strategy);
|
|
828
|
-
} finally {
|
|
829
|
-
this.#resumeRebuild();
|
|
830
|
-
}
|
|
782
|
+
this.#reloadStaticModels();
|
|
783
|
+
this.#suppressedSelectors.clear();
|
|
784
|
+
await this.#refreshRuntimeDiscoveries(strategy);
|
|
831
785
|
}
|
|
832
786
|
|
|
833
787
|
refreshInBackground(strategy: ModelRefreshStrategy = "online-if-uncached"): void {
|
|
@@ -849,18 +803,13 @@ export class ModelRegistry {
|
|
|
849
803
|
}
|
|
850
804
|
|
|
851
805
|
async refreshProvider(providerId: string, strategy: ModelRefreshStrategy = "online"): Promise<void> {
|
|
852
|
-
this.#
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
if (selector.startsWith(`${providerId}/`)) {
|
|
857
|
-
this.#suppressedSelectors.delete(selector);
|
|
858
|
-
}
|
|
806
|
+
this.#reloadStaticModels();
|
|
807
|
+
for (const selector of this.#suppressedSelectors.keys()) {
|
|
808
|
+
if (selector.startsWith(`${providerId}/`)) {
|
|
809
|
+
this.#suppressedSelectors.delete(selector);
|
|
859
810
|
}
|
|
860
|
-
await this.#refreshRuntimeDiscoveries(strategy, new Set([providerId]));
|
|
861
|
-
} finally {
|
|
862
|
-
this.#resumeRebuild();
|
|
863
811
|
}
|
|
812
|
+
await this.#refreshRuntimeDiscoveries(strategy, new Set([providerId]));
|
|
864
813
|
}
|
|
865
814
|
|
|
866
815
|
/**
|
|
@@ -910,7 +859,6 @@ export class ModelRegistry {
|
|
|
910
859
|
this.#models = this.#models.map(candidate =>
|
|
911
860
|
candidate.provider === current.provider && candidate.id === current.id ? patched : candidate,
|
|
912
861
|
);
|
|
913
|
-
this.#rebuildCanonicalIndex();
|
|
914
862
|
return patched;
|
|
915
863
|
}
|
|
916
864
|
|
|
@@ -927,18 +875,13 @@ export class ModelRegistry {
|
|
|
927
875
|
if (this.#runtimeModelManagers.size === 0) {
|
|
928
876
|
return;
|
|
929
877
|
}
|
|
930
|
-
this.#
|
|
931
|
-
try {
|
|
932
|
-
await this.#refreshRuntimeDiscoveries(strategy, new Set(this.#runtimeModelManagers.keys()));
|
|
933
|
-
} finally {
|
|
934
|
-
this.#resumeRebuild();
|
|
935
|
-
}
|
|
878
|
+
await this.#refreshRuntimeDiscoveries(strategy, new Set(this.#runtimeModelManagers.keys()));
|
|
936
879
|
}
|
|
937
880
|
|
|
938
881
|
#reloadStaticModels(): void {
|
|
939
882
|
const currentMtime = this.#modelsConfigFile.getMtimeMs();
|
|
940
883
|
if (currentMtime !== null && currentMtime === this.#lastStaticLoadMtime) {
|
|
941
|
-
// models.json unchanged since last load;
|
|
884
|
+
// models.json unchanged since last load; reloading would be redundant.
|
|
942
885
|
return;
|
|
943
886
|
}
|
|
944
887
|
this.#modelsConfigFile.invalidate();
|
|
@@ -956,7 +899,6 @@ export class ModelRegistry {
|
|
|
956
899
|
}
|
|
957
900
|
this.#providerOverrides.clear();
|
|
958
901
|
this.#modelOverrides.clear();
|
|
959
|
-
this.#equivalenceConfig = undefined;
|
|
960
902
|
this.#configError = undefined;
|
|
961
903
|
this.#providerDiscoveryStates.clear();
|
|
962
904
|
this.#loadModels();
|
|
@@ -978,7 +920,6 @@ export class ModelRegistry {
|
|
|
978
920
|
keylessProviders = new Set(),
|
|
979
921
|
discoverableProviders = [],
|
|
980
922
|
configuredProviders = new Set(),
|
|
981
|
-
equivalence,
|
|
982
923
|
error: configError,
|
|
983
924
|
} = this.#loadCustomModels();
|
|
984
925
|
this.#configError = configError;
|
|
@@ -987,7 +928,6 @@ export class ModelRegistry {
|
|
|
987
928
|
this.#customModelOverlays = customModels;
|
|
988
929
|
this.#providerOverrides = overrides;
|
|
989
930
|
this.#modelOverrides = modelOverrides;
|
|
990
|
-
this.#equivalenceConfig = equivalence;
|
|
991
931
|
|
|
992
932
|
this.#addImplicitDiscoverableProviders(configuredProviders);
|
|
993
933
|
let builtInModels = this.#applyHardcodedModelPolicies(this.#loadBuiltInModels(overrides));
|
|
@@ -1024,7 +964,6 @@ export class ModelRegistry {
|
|
|
1024
964
|
// collapse effort-tier variants here so X/X-thinking twins fold.
|
|
1025
965
|
const withModelOverrides = this.#applyModelOverrides(collapseBuiltModelVariants(combined), this.#modelOverrides);
|
|
1026
966
|
this.#models = this.#applyRuntimeProviderOverrides(withModelOverrides);
|
|
1027
|
-
this.#rebuildCanonicalIndex();
|
|
1028
967
|
this.#lastStaticLoadMtime = this.#modelsConfigFile.getMtimeMs();
|
|
1029
968
|
}
|
|
1030
969
|
|
|
@@ -1373,7 +1312,6 @@ export class ModelRegistry {
|
|
|
1373
1312
|
keylessProviders,
|
|
1374
1313
|
discoverableProviders,
|
|
1375
1314
|
configuredProviders,
|
|
1376
|
-
equivalence: value.equivalence,
|
|
1377
1315
|
found: true,
|
|
1378
1316
|
};
|
|
1379
1317
|
}
|
|
@@ -1423,7 +1361,6 @@ export class ModelRegistry {
|
|
|
1423
1361
|
const combined = this.#mergeCustomModels(withConfigModels, this.#runtimeModelOverlays);
|
|
1424
1362
|
const withModelOverrides = this.#applyModelOverrides(collapseBuiltModelVariants(combined), this.#modelOverrides);
|
|
1425
1363
|
this.#models = this.#applyRuntimeProviderOverrides(withModelOverrides);
|
|
1426
|
-
this.#rebuildCanonicalIndex();
|
|
1427
1364
|
}
|
|
1428
1365
|
|
|
1429
1366
|
#configuredDiscoveryCacheProviderId(providerConfig: DiscoveryProviderConfig): string {
|
|
@@ -1819,44 +1756,6 @@ export class ModelRegistry {
|
|
|
1819
1756
|
});
|
|
1820
1757
|
}
|
|
1821
1758
|
|
|
1822
|
-
#rebuildCanonicalIndex(): void {
|
|
1823
|
-
if (this.#rebuildSuspended > 0) {
|
|
1824
|
-
this.#rebuildPending = true;
|
|
1825
|
-
return;
|
|
1826
|
-
}
|
|
1827
|
-
// Defer the catalog-wide index build to first read. Boot model
|
|
1828
|
-
// resolution reads it only when enabledModels or a default-role pattern
|
|
1829
|
-
// is configured; the empty interactive launch never reads it pre-paint,
|
|
1830
|
-
// so the ~200ms build over the full catalog moves off the first-paint
|
|
1831
|
-
// critical path.
|
|
1832
|
-
this.#canonicalIndexDirty = true;
|
|
1833
|
-
this.#rebuildPending = false;
|
|
1834
|
-
}
|
|
1835
|
-
|
|
1836
|
-
#ensureCanonicalIndex(): CanonicalModelIndex {
|
|
1837
|
-
if (this.#canonicalIndexDirty) {
|
|
1838
|
-
this.#canonicalIndex = logger.time("buildCanonicalModelIndex", () =>
|
|
1839
|
-
buildCanonicalModelIndex(this.#models, getBundledCanonicalReferenceData(), this.#equivalenceConfig),
|
|
1840
|
-
);
|
|
1841
|
-
this.#canonicalIndexDirty = false;
|
|
1842
|
-
}
|
|
1843
|
-
return this.#canonicalIndex;
|
|
1844
|
-
}
|
|
1845
|
-
|
|
1846
|
-
#suspendRebuild(): void {
|
|
1847
|
-
this.#rebuildSuspended += 1;
|
|
1848
|
-
}
|
|
1849
|
-
|
|
1850
|
-
#resumeRebuild(): void {
|
|
1851
|
-
if (this.#rebuildSuspended > 0) {
|
|
1852
|
-
this.#rebuildSuspended -= 1;
|
|
1853
|
-
}
|
|
1854
|
-
if (this.#rebuildSuspended === 0 && this.#rebuildPending) {
|
|
1855
|
-
this.#rebuildPending = false;
|
|
1856
|
-
this.#canonicalIndexDirty = true;
|
|
1857
|
-
}
|
|
1858
|
-
}
|
|
1859
|
-
|
|
1860
1759
|
#parseModels(config: ModelsConfig): CustomModelOverlay[] {
|
|
1861
1760
|
const models: CustomModelOverlay[] = [];
|
|
1862
1761
|
for (const [providerName, providerConfig] of Object.entries(config.providers ?? {})) {
|
|
@@ -1918,115 +1817,6 @@ export class ModelRegistry {
|
|
|
1918
1817
|
};
|
|
1919
1818
|
}
|
|
1920
1819
|
|
|
1921
|
-
/**
|
|
1922
|
-
* Build the shared per-query filter state for canonical model queries.
|
|
1923
|
-
* Hoisted out of the per-record loop: building the candidate-selector set
|
|
1924
|
-
* and availability memo once per query instead of once per record is what
|
|
1925
|
-
* keeps `getCanonicalModelSelections` linear instead of O(records × candidates).
|
|
1926
|
-
*/
|
|
1927
|
-
#canonicalQueryFilters(options: CanonicalModelQueryOptions | undefined): {
|
|
1928
|
-
candidateKeys: Set<string> | undefined;
|
|
1929
|
-
isAvailable: ((model: Model<Api>) => boolean) | undefined;
|
|
1930
|
-
} {
|
|
1931
|
-
return {
|
|
1932
|
-
candidateKeys: options?.candidates
|
|
1933
|
-
? new Set(options.candidates.map(candidate => formatCanonicalVariantSelector(candidate)))
|
|
1934
|
-
: undefined,
|
|
1935
|
-
isAvailable: options?.availableOnly ? this.#createAvailabilityCheck() : undefined,
|
|
1936
|
-
};
|
|
1937
|
-
}
|
|
1938
|
-
|
|
1939
|
-
#filterCanonicalVariants(
|
|
1940
|
-
record: CanonicalModelRecord,
|
|
1941
|
-
candidateKeys: ReadonlySet<string> | undefined,
|
|
1942
|
-
isAvailable: ((model: Model<Api>) => boolean) | undefined,
|
|
1943
|
-
): CanonicalModelVariant[] {
|
|
1944
|
-
return record.variants.filter(variant => {
|
|
1945
|
-
if (candidateKeys && !candidateKeys.has(variant.selector)) {
|
|
1946
|
-
return false;
|
|
1947
|
-
}
|
|
1948
|
-
if (isAvailable && !isAvailable(variant.model)) {
|
|
1949
|
-
return false;
|
|
1950
|
-
}
|
|
1951
|
-
return true;
|
|
1952
|
-
});
|
|
1953
|
-
}
|
|
1954
|
-
|
|
1955
|
-
#variantPreferences(candidates: readonly Model<Api>[]): CanonicalVariantPreferences {
|
|
1956
|
-
return {
|
|
1957
|
-
modelOrder: buildCanonicalModelOrder(candidates),
|
|
1958
|
-
providerRank: buildModelProviderPriorityRank(getConfiguredProviderOrderFromSettings()),
|
|
1959
|
-
};
|
|
1960
|
-
}
|
|
1961
|
-
|
|
1962
|
-
getCanonicalModels(options?: CanonicalModelQueryOptions): CanonicalModelRecord[] {
|
|
1963
|
-
const { candidateKeys, isAvailable } = this.#canonicalQueryFilters(options);
|
|
1964
|
-
const records: CanonicalModelRecord[] = [];
|
|
1965
|
-
for (const record of this.#ensureCanonicalIndex().records) {
|
|
1966
|
-
const variants = this.#filterCanonicalVariants(record, candidateKeys, isAvailable);
|
|
1967
|
-
if (variants.length === 0) {
|
|
1968
|
-
continue;
|
|
1969
|
-
}
|
|
1970
|
-
records.push({
|
|
1971
|
-
id: record.id,
|
|
1972
|
-
name: record.name,
|
|
1973
|
-
variants,
|
|
1974
|
-
});
|
|
1975
|
-
}
|
|
1976
|
-
return records;
|
|
1977
|
-
}
|
|
1978
|
-
|
|
1979
|
-
/**
|
|
1980
|
-
* One-pass equivalent of `getCanonicalModels` + `resolveCanonicalModel` per
|
|
1981
|
-
* record. The per-query state (candidate-selector set, availability memo,
|
|
1982
|
-
* provider rank, candidate order) is built once, so the whole catalog
|
|
1983
|
-
* resolves in O(records + candidates) instead of O(records × candidates).
|
|
1984
|
-
* This is the path the model selector hydrates from synchronously on open.
|
|
1985
|
-
*/
|
|
1986
|
-
getCanonicalModelSelections(options?: CanonicalModelQueryOptions): CanonicalModelSelection[] {
|
|
1987
|
-
const { candidateKeys, isAvailable } = this.#canonicalQueryFilters(options);
|
|
1988
|
-
const candidates = options?.candidates ?? (options?.availableOnly ? this.getAvailable() : this.getAll());
|
|
1989
|
-
const preferences = this.#variantPreferences(candidates);
|
|
1990
|
-
const selections: CanonicalModelSelection[] = [];
|
|
1991
|
-
for (const record of this.#ensureCanonicalIndex().records) {
|
|
1992
|
-
const variants = this.#filterCanonicalVariants(record, candidateKeys, isAvailable);
|
|
1993
|
-
if (variants.length === 0) {
|
|
1994
|
-
continue;
|
|
1995
|
-
}
|
|
1996
|
-
const resolved = resolveCanonicalVariant(variants, preferences);
|
|
1997
|
-
if (!resolved) {
|
|
1998
|
-
continue;
|
|
1999
|
-
}
|
|
2000
|
-
selections.push({
|
|
2001
|
-
record: { id: record.id, name: record.name, variants },
|
|
2002
|
-
model: resolved.model,
|
|
2003
|
-
});
|
|
2004
|
-
}
|
|
2005
|
-
return selections;
|
|
2006
|
-
}
|
|
2007
|
-
|
|
2008
|
-
getCanonicalVariants(canonicalId: string, options?: CanonicalModelQueryOptions): CanonicalModelVariant[] {
|
|
2009
|
-
const record = this.#ensureCanonicalIndex().byId.get(canonicalId.trim().toLowerCase());
|
|
2010
|
-
if (!record) {
|
|
2011
|
-
return [];
|
|
2012
|
-
}
|
|
2013
|
-
const { candidateKeys, isAvailable } = this.#canonicalQueryFilters(options);
|
|
2014
|
-
return this.#filterCanonicalVariants(record, candidateKeys, isAvailable);
|
|
2015
|
-
}
|
|
2016
|
-
|
|
2017
|
-
resolveCanonicalModel(canonicalId: string, options?: CanonicalModelQueryOptions): Model<Api> | undefined {
|
|
2018
|
-
const variants = this.getCanonicalVariants(canonicalId, options);
|
|
2019
|
-
if (variants.length === 0) {
|
|
2020
|
-
return undefined;
|
|
2021
|
-
}
|
|
2022
|
-
const candidates = options?.candidates ?? (options?.availableOnly ? this.getAvailable() : this.getAll());
|
|
2023
|
-
return resolveCanonicalVariant(variants, this.#variantPreferences(candidates))?.model;
|
|
2024
|
-
}
|
|
2025
|
-
|
|
2026
|
-
getCanonicalId(model: Model<Api>): string | undefined {
|
|
2027
|
-
return this.#ensureCanonicalIndex().bySelector.get(formatCanonicalVariantSelector(model).toLowerCase());
|
|
2028
|
-
}
|
|
2029
|
-
|
|
2030
1820
|
/**
|
|
2031
1821
|
* Get only models that have auth configured.
|
|
2032
1822
|
* This is a fast check that doesn't refresh OAuth tokens.
|
|
@@ -2187,7 +1977,6 @@ export class ModelRegistry {
|
|
|
2187
1977
|
}
|
|
2188
1978
|
this.#lastStaticLoadMtime = null;
|
|
2189
1979
|
this.#reloadStaticModels();
|
|
2190
|
-
this.#rebuildCanonicalIndex();
|
|
2191
1980
|
}
|
|
2192
1981
|
|
|
2193
1982
|
/**
|
|
@@ -2316,13 +2105,11 @@ export class ModelRegistry {
|
|
|
2316
2105
|
const credential = this.authStorage.getOAuthCredential(providerName);
|
|
2317
2106
|
if (credential) {
|
|
2318
2107
|
this.#models = config.oauth.modifyModels(withRuntimeTransportOverride, credential);
|
|
2319
|
-
this.#rebuildCanonicalIndex();
|
|
2320
2108
|
return;
|
|
2321
2109
|
}
|
|
2322
2110
|
}
|
|
2323
2111
|
|
|
2324
2112
|
this.#models = withRuntimeTransportOverride;
|
|
2325
|
-
this.#rebuildCanonicalIndex();
|
|
2326
2113
|
return;
|
|
2327
2114
|
}
|
|
2328
2115
|
|
|
@@ -2393,7 +2180,6 @@ export class ModelRegistry {
|
|
|
2393
2180
|
if (m.provider !== providerName) return m;
|
|
2394
2181
|
return this.#applyProviderTransportOverride(m, transportOverride);
|
|
2395
2182
|
});
|
|
2396
|
-
this.#rebuildCanonicalIndex();
|
|
2397
2183
|
}
|
|
2398
2184
|
}
|
|
2399
2185
|
|