diff --git a/src/resources/extensions/sf/model-registry.ts b/src/resources/extensions/sf/model-registry.ts index bef59ab73..dbd240f30 100644 --- a/src/resources/extensions/sf/model-registry.ts +++ b/src/resources/extensions/sf/model-registry.ts @@ -80,11 +80,11 @@ export interface ResolvedModel { * Entries that are already canonical (e.g. provider="kimi-coding", wire_id="kimi-k2.6") * can be omitted; the resolver falls back to wire_id when no mapping exists. * - * NOTE: Many entries below (especially those where wire_id === canonical_id) are - * now also covered by the dynamic resolver in canonicalIdFromDiscovery(), which - * consults ~/.sf/agent/discovery-cache.json at runtime. The static entries are - * kept as a fast path and to handle cases where the canonical form intentionally - * diverges from the wire id (e.g. kimi-coding/kimi-for-coding → kimi-k2.6). + * NOTE: Identity-strip entries (where canonical_id == wire_id) have been + * REMOVED for any provider present in ~/.sf/agent/discovery-cache.json. Those + * routes are now resolved dynamically by canonicalIdFromDiscovery(). Only real + * aliases (canonical ≠ wire_id) and entries for providers NOT in the discovery + * cache are kept here. See commit notes for the removed list. */ const CANONICAL_BY_ROUTE: Record = { // ── amazon-bedrock ──────────────────────────────────────────────────────── @@ -305,15 +305,12 @@ const CANONICAL_BY_ROUTE: Record = { // devstral-medium-2507 → devstral-medium-latest is a real alias (kept). "mistral/devstral-medium-2507": "devstral-medium-latest", // ── zai (direct, not via openrouter) ───────────────────────────────────── - "zai/glm-4.5": "glm-4.5", - "zai/glm-4.5-air": "glm-4.5-air", + // glm-4.5, glm-4.5-air, glm-4.6, glm-4.7, glm-5, glm-5-turbo, glm-5.1 + // removed: identity-strip aliases now resolved dynamically via discovery + // cache (zai provider present). + // glm-4.5-flash and glm-4.7-flash are NOT in the discovery cache → kept. "zai/glm-4.5-flash": "glm-4.5-flash", - "zai/glm-4.6": "glm-4.6", - "zai/glm-4.7": "glm-4.7", "zai/glm-4.7-flash": "glm-4.7-flash", - "zai/glm-5": "glm-5", - "zai/glm-5-turbo": "glm-5-turbo", - "zai/glm-5.1": "glm-5.1", // ── openrouter ──────────────────────────────────────────────────────────── "openrouter/anthropic/claude-3-haiku": "claude-3-haiku", "openrouter/anthropic/claude-3.5-haiku": "claude-3-5-haiku", @@ -973,9 +970,9 @@ export function canonicalIdFor( ): CanonicalId | null { // Fast path 1: static alias table (wins over dynamic — allows canonical // remapping where the wire id differs from the desired canonical id, e.g. - // kimi-coding/kimi-for-coding → kimi-k2.6). - // NOTE: the 23+ static aliases added in commit 089bf0cbe are now also covered - // by the dynamic resolver below, but kept here as a fast path. + // kimi-coding/kimi-for-coding → kimi-k2.6). Identity-strip entries for + // providers present in the discovery cache have been removed; those routes + // fall through to the dynamic resolver below. if (routeKey in CANONICAL_BY_ROUTE) { return CANONICAL_BY_ROUTE[routeKey]; } diff --git a/src/resources/extensions/sf/tests/canonical-id-dynamic.test.mjs b/src/resources/extensions/sf/tests/canonical-id-dynamic.test.mjs index 14c68adc3..257832ca2 100644 --- a/src/resources/extensions/sf/tests/canonical-id-dynamic.test.mjs +++ b/src/resources/extensions/sf/tests/canonical-id-dynamic.test.mjs @@ -107,3 +107,154 @@ describe("canonicalIdFor — dynamic discovery cache fallback", () => { expect(canonicalIdFor("newprovider/gamma-3.0")).toBeNull(); }); }); + +// ── Regression: removed identity-strip aliases still resolve via dynamic cache ── +// +// 15 entries were removed from CANONICAL_BY_ROUTE (commit that pruned +// identity-strip aliases) because the provider is in the discovery cache and +// canonical == bare model id. These tests verify each removed entry still +// resolves correctly through canonicalIdFromDiscovery(). + +describe("canonicalIdFor — removed identity-strip aliases resolve via discovery cache", () => { + afterEach(() => { + __setDiscoveryCacheForTest(undefined); + }); + + // Inject a fake cache that mirrors the real discovery-cache providers. + // Tests use __setDiscoveryCacheForTest so no filesystem access is needed. + + it("minimax/MiniMax-M2.7 resolves to MiniMax-M2.7 via discovery cache", () => { + __setDiscoveryCacheForTest({ + entries: { + minimax: { models: [{ id: "MiniMax-M2.7" }] }, + }, + }); + expect(canonicalIdFor("minimax/MiniMax-M2.7")).toBe("MiniMax-M2.7"); + }); + + it("minimax/MiniMax-M2.7-highspeed resolves to MiniMax-M2.7-highspeed via discovery cache", () => { + __setDiscoveryCacheForTest({ + entries: { + minimax: { models: [{ id: "MiniMax-M2.7-highspeed" }] }, + }, + }); + expect(canonicalIdFor("minimax/MiniMax-M2.7-highspeed")).toBe("MiniMax-M2.7-highspeed"); + }); + + it("mistral/codestral-latest resolves to codestral-latest via discovery cache", () => { + __setDiscoveryCacheForTest({ + entries: { + mistral: { models: [{ id: "codestral-latest" }] }, + }, + }); + expect(canonicalIdFor("mistral/codestral-latest")).toBe("codestral-latest"); + }); + + it("mistral/devstral-2512 resolves to devstral-2512 via discovery cache", () => { + __setDiscoveryCacheForTest({ + entries: { + mistral: { models: [{ id: "devstral-2512" }] }, + }, + }); + expect(canonicalIdFor("mistral/devstral-2512")).toBe("devstral-2512"); + }); + + it("mistral/devstral-small-2507 resolves to devstral-small-2507 via discovery cache", () => { + __setDiscoveryCacheForTest({ + entries: { + mistral: { models: [{ id: "devstral-small-2507" }] }, + }, + }); + expect(canonicalIdFor("mistral/devstral-small-2507")).toBe("devstral-small-2507"); + }); + + it("mistral/mistral-large-latest resolves to mistral-large-latest via discovery cache", () => { + __setDiscoveryCacheForTest({ + entries: { + mistral: { models: [{ id: "mistral-large-latest" }] }, + }, + }); + expect(canonicalIdFor("mistral/mistral-large-latest")).toBe("mistral-large-latest"); + }); + + it("mistral/mistral-medium-latest resolves to mistral-medium-latest via discovery cache", () => { + __setDiscoveryCacheForTest({ + entries: { + mistral: { models: [{ id: "mistral-medium-latest" }] }, + }, + }); + expect(canonicalIdFor("mistral/mistral-medium-latest")).toBe("mistral-medium-latest"); + }); + + it("mistral/mistral-small-latest resolves to mistral-small-latest via discovery cache", () => { + __setDiscoveryCacheForTest({ + entries: { + mistral: { models: [{ id: "mistral-small-latest" }] }, + }, + }); + expect(canonicalIdFor("mistral/mistral-small-latest")).toBe("mistral-small-latest"); + }); + + it("zai/glm-4.5 resolves to glm-4.5 via discovery cache", () => { + __setDiscoveryCacheForTest({ + entries: { + zai: { models: [{ id: "glm-4.5" }] }, + }, + }); + expect(canonicalIdFor("zai/glm-4.5")).toBe("glm-4.5"); + }); + + it("zai/glm-4.5-air resolves to glm-4.5-air via discovery cache", () => { + __setDiscoveryCacheForTest({ + entries: { + zai: { models: [{ id: "glm-4.5-air" }] }, + }, + }); + expect(canonicalIdFor("zai/glm-4.5-air")).toBe("glm-4.5-air"); + }); + + it("zai/glm-4.6 resolves to glm-4.6 via discovery cache", () => { + __setDiscoveryCacheForTest({ + entries: { + zai: { models: [{ id: "glm-4.6" }] }, + }, + }); + expect(canonicalIdFor("zai/glm-4.6")).toBe("glm-4.6"); + }); + + it("zai/glm-4.7 resolves to glm-4.7 via discovery cache", () => { + __setDiscoveryCacheForTest({ + entries: { + zai: { models: [{ id: "glm-4.7" }] }, + }, + }); + expect(canonicalIdFor("zai/glm-4.7")).toBe("glm-4.7"); + }); + + it("zai/glm-5 resolves to glm-5 via discovery cache", () => { + __setDiscoveryCacheForTest({ + entries: { + zai: { models: [{ id: "glm-5" }] }, + }, + }); + expect(canonicalIdFor("zai/glm-5")).toBe("glm-5"); + }); + + it("zai/glm-5-turbo resolves to glm-5-turbo via discovery cache", () => { + __setDiscoveryCacheForTest({ + entries: { + zai: { models: [{ id: "glm-5-turbo" }] }, + }, + }); + expect(canonicalIdFor("zai/glm-5-turbo")).toBe("glm-5-turbo"); + }); + + it("zai/glm-5.1 resolves to glm-5.1 via discovery cache", () => { + __setDiscoveryCacheForTest({ + entries: { + zai: { models: [{ id: "glm-5.1" }] }, + }, + }); + expect(canonicalIdFor("zai/glm-5.1")).toBe("glm-5.1"); + }); +});