























@@ -0,0 +1,229 @@
1+import { describe, it, expect } from "vitest";
2+import { LEGACY_CONFIG_MIGRATIONS_RUNTIME_MODELS } from "./legacy-config-migrations.runtime.models.js";
3+4+describe("stale contextWindow migration", () => {
5+const migration = LEGACY_CONFIG_MIGRATIONS_RUNTIME_MODELS.find(
6+(m) => m.id === "models.providers.*.models.*.contextWindow-stale",
7+);
8+9+it("repairs deepseek-v4-flash contextWindow from 200K to 1M", () => {
10+const changes: string[] = [];
11+const raw = {
12+models: {
13+providers: {
14+deepseek: {
15+models: [
16+{
17+id: "deepseek-v4-flash",
18+contextWindow: 200_000,
19+maxTokens: 61_440,
20+},
21+],
22+},
23+},
24+},
25+};
26+27+expect(migration!.legacyRules?.[0]?.match?.(raw.models.providers, raw)).toBe(true);
28+29+migration!.apply(raw, changes);
30+31+expect(raw.models.providers.deepseek.models[0].contextWindow).toBe(1_000_000);
32+expect(changes).toHaveLength(1);
33+expect(changes[0]).toContain("200000 → 1000000");
34+expect(migration!.legacyRules?.[0]?.match?.(raw.models.providers, raw)).toBe(false);
35+});
36+37+it("does not modify correct contextWindow values", () => {
38+const changes: string[] = [];
39+const raw = {
40+models: {
41+providers: {
42+deepseek: {
43+models: [
44+{
45+id: "deepseek-v4-flash",
46+contextWindow: 1_000_000,
47+maxTokens: 61_440,
48+},
49+],
50+},
51+},
52+},
53+};
54+55+migration!.apply(raw, changes);
56+57+expect(raw.models.providers.deepseek.models[0].contextWindow).toBe(1_000_000);
58+expect(changes).toHaveLength(0);
59+});
60+61+it("preserves non-stale custom contextWindow values", () => {
62+const changes: string[] = [];
63+const raw = {
64+models: {
65+providers: {
66+deepseek: {
67+models: [
68+{
69+id: "deepseek-v4-flash",
70+contextWindow: 500_000,
71+maxTokens: 61_440,
72+},
73+],
74+},
75+},
76+},
77+};
78+79+migration!.apply(raw, changes);
80+81+expect(raw.models.providers.deepseek.models[0].contextWindow).toBe(500_000);
82+expect(changes).toHaveLength(0);
83+});
84+85+it("does not modify bare ids from other providers", () => {
86+const changes: string[] = [];
87+const raw = {
88+models: {
89+providers: {
90+custom: {
91+models: [
92+{
93+id: "deepseek-v4-flash",
94+contextWindow: 200_000,
95+maxTokens: 61_440,
96+},
97+],
98+},
99+},
100+},
101+};
102+103+migration!.apply(raw, changes);
104+105+expect(raw.models.providers.custom.models[0].contextWindow).toBe(200_000);
106+expect(changes).toHaveLength(0);
107+expect(migration!.legacyRules?.[0]?.match?.(raw.models.providers, raw)).toBe(false);
108+});
109+110+it("handles provider-prefixed model IDs under the native provider", () => {
111+const changes: string[] = [];
112+const raw = {
113+models: {
114+providers: {
115+deepseek: {
116+models: [
117+{
118+id: "deepseek/deepseek-v4-flash",
119+contextWindow: 200_000,
120+maxTokens: 61_440,
121+},
122+],
123+},
124+},
125+},
126+};
127+128+migration!.apply(raw, changes);
129+130+expect(raw.models.providers.deepseek.models[0].contextWindow).toBe(1_000_000);
131+expect(changes).toHaveLength(1);
132+});
133+134+it("does not modify provider-prefixed ids from other providers", () => {
135+const changes: string[] = [];
136+const raw = {
137+models: {
138+providers: {
139+openrouter: {
140+models: [
141+{
142+id: "deepseek/deepseek-v4-flash",
143+contextWindow: 200_000,
144+maxTokens: 61_440,
145+},
146+],
147+},
148+},
149+},
150+};
151+152+migration!.apply(raw, changes);
153+154+expect(raw.models.providers.openrouter.models[0].contextWindow).toBe(200_000);
155+expect(changes).toHaveLength(0);
156+expect(migration!.legacyRules?.[0]?.match?.(raw.models.providers, raw)).toBe(false);
157+});
158+159+it("skips models not in the stale fixes registry", () => {
160+const changes: string[] = [];
161+const raw = {
162+models: {
163+providers: {
164+openai: {
165+models: [
166+{
167+id: "gpt-4o",
168+contextWindow: 128_000,
169+maxTokens: 16_384,
170+},
171+],
172+},
173+},
174+},
175+};
176+177+migration!.apply(raw, changes);
178+179+expect(raw.models.providers.openai.models[0].contextWindow).toBe(128_000);
180+expect(changes).toHaveLength(0);
181+});
182+183+it("handles missing providers gracefully", () => {
184+const changes: string[] = [];
185+const raw = {};
186+187+migration!.apply(raw, changes);
188+189+expect(changes).toHaveLength(0);
190+});
191+192+it("handles non-array models gracefully", () => {
193+const changes: string[] = [];
194+const raw = {
195+models: {
196+providers: {
197+deepseek: {
198+models: "not-an-array",
199+},
200+},
201+},
202+};
203+204+migration!.apply(raw, changes);
205+206+expect(changes).toHaveLength(0);
207+});
208+209+it("handles missing model id gracefully", () => {
210+const changes: string[] = [];
211+const raw = {
212+models: {
213+providers: {
214+deepseek: {
215+models: [
216+{
217+contextWindow: 200_000,
218+},
219+],
220+},
221+},
222+},
223+};
224+225+migration!.apply(raw, changes);
226+227+expect(changes).toHaveLength(0);
228+});
229+});
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。