
























@@ -163,6 +163,54 @@ function configuredTextModel(id: string, name: string) {
163163};
164164}
165165166+type MockCallSource = {
167+mock: {
168+calls: ArrayLike<ReadonlyArray<unknown>>;
169+};
170+};
171+172+function requireRecord(value: unknown, label: string): Record<string, unknown> {
173+expect(value, label).toBeTypeOf("object");
174+expect(value, label).not.toBeNull();
175+return value as Record<string, unknown>;
176+}
177+178+function mockArg(source: MockCallSource, callIndex: number, argIndex: number, label: string) {
179+const call = source.mock.calls[callIndex];
180+if (!call) {
181+throw new Error(`expected mock call: ${label}`);
182+}
183+return call[argIndex];
184+}
185+186+function pickerParams(source: MockCallSource, callIndex = 0) {
187+return requireRecord(mockArg(source, callIndex, 0, `picker call ${callIndex}`), "picker params");
188+}
189+190+function pickerOptions(source: MockCallSource, callIndex = 0) {
191+const options = pickerParams(source, callIndex).options;
192+expect(options, "picker options").toBeInstanceOf(Array);
193+return options as Array<Record<string, unknown>>;
194+}
195+196+function optionValues(options: Array<Record<string, unknown>>) {
197+return options.map((option) => option.value);
198+}
199+200+function requireOption(options: Array<Record<string, unknown>>, value: string) {
201+const option = options.find((candidate) => candidate.value === value);
202+if (!option) {
203+throw new Error(`expected picker option: ${value}`);
204+}
205+return option;
206+}
207+208+function providerCallProviders() {
209+return resolveOwningPluginIdsForProvider.mock.calls.map(
210+([params]) => requireRecord(params, "provider ownership params").provider,
211+);
212+}
213+166214beforeEach(() => {
167215vi.clearAllMocks();
168216loadStaticManifestCatalogRowsForList.mockReturnValue([]);
@@ -210,19 +258,11 @@ describe("promptDefaultModel", () => {
210258ignoreAllowlist: true,
211259});
212260213-const options = select.mock.calls[0]?.[0]?.options ?? [];
214-expect(options).toEqual(
215-expect.arrayContaining([
216-expect.objectContaining({
217-value: "openai/gpt-5.5",
218-hint: expect.stringContaining("Codex runtime route"),
219-}),
220-expect.objectContaining({
221-value: "openai-codex/gpt-5.5",
222-hint: expect.stringContaining("legacy Codex OAuth route"),
223-}),
224-]),
225-);
261+const options = pickerOptions(select as MockCallSource);
262+const canonical = requireOption(options, "openai/gpt-5.5");
263+expect(canonical.hint).toContain("Codex runtime route");
264+const legacy = requireOption(options, "openai-codex/gpt-5.5");
265+expect(legacy.hint).toContain("legacy Codex OAuth route");
226266});
227267228268it("hides unauthenticated catalog entries from default model choices", async () => {
@@ -324,14 +364,15 @@ describe("promptDefaultModel", () => {
324364});
325365326366expect(result.model).toBe("google/gemini-3.1-pro-preview");
327-expect(select.mock.calls[0]?.[0]?.options).toEqual([
328-expect.objectContaining({ value: "google/gemini-3.1-pro-preview" }),
367+expect(optionValues(pickerOptions(select as MockCallSource))).toEqual([
368+"google/gemini-3.1-pro-preview",
329369]);
330-expect(runProviderModelSelectedHook).toHaveBeenCalledWith(
331-expect.objectContaining({
332-model: "google/gemini-3.1-pro-preview",
333-}),
334-);
370+expect(
371+requireRecord(
372+mockArg(runProviderModelSelectedHook as MockCallSource, 0, 0, "provider selected hook"),
373+"provider selected hook params",
374+).model,
375+).toBe("google/gemini-3.1-pro-preview");
335376});
336377337378it("uses configured provider models for default picker without loading the full catalog in replace mode", async () => {
@@ -364,12 +405,11 @@ describe("promptDefaultModel", () => {
364405});
365406366407expect(loadModelCatalog).not.toHaveBeenCalled();
367-expect(select.mock.calls[0]?.[0]?.options).toEqual([
368-expect.objectContaining({
369-value: "minimax/MiniMax-M2.7-highspeed",
370-hint: expect.stringContaining("MiniMax M2.7 Highspeed"),
371-}),
372-]);
408+const minimaxOption = requireOption(
409+pickerOptions(select as MockCallSource),
410+"minimax/MiniMax-M2.7-highspeed",
411+);
412+expect(minimaxOption.hint).toContain("MiniMax M2.7 Highspeed");
373413expect(result.model).toBe("minimax/MiniMax-M2.7-highspeed");
374414});
375415@@ -412,12 +452,8 @@ describe("promptDefaultModel", () => {
412452expect(optionValues[1]).toBe("byteplus-plan/ark-code-latest");
413453expect(select.mock.calls[0]?.[0]?.initialValue).toBe("byteplus-plan/ark-code-latest");
414454expect(result.model).toBe("byteplus-plan/ark-code-latest");
415-expect(resolveOwningPluginIdsForProvider).toHaveBeenCalledWith(
416-expect.objectContaining({ provider: "byteplus" }),
417-);
418-expect(resolveOwningPluginIdsForProvider).toHaveBeenCalledWith(
419-expect.objectContaining({ provider: "byteplus-plan" }),
420-);
455+expect(providerCallProviders()).toContain("byteplus");
456+expect(providerCallProviders()).toContain("byteplus-plan");
421457});
422458423459it("shows literal double-prefix labels for providers that preserve literal prefixes", async () => {
@@ -453,18 +489,12 @@ describe("promptDefaultModel", () => {
453489ignoreAllowlist: true,
454490});
455491456-const options = select.mock.calls[0]?.[0]?.options ?? [];
457-expect(options).toEqual(
458-expect.arrayContaining([
459-expect.objectContaining({
460-value: "__keep__",
461-label: "Keep current (nvidia/nvidia/nemotron-3-super-120b-a12b)",
462-}),
463-expect.objectContaining({
464-value: "nvidia/nemotron-3-super-120b-a12b",
465-label: "nvidia/nvidia/nemotron-3-super-120b-a12b",
466-}),
467-]),
492+const options = pickerOptions(select as MockCallSource);
493+expect(requireOption(options, "__keep__").label).toBe(
494+"Keep current (nvidia/nvidia/nemotron-3-super-120b-a12b)",
495+);
496+expect(requireOption(options, "nvidia/nemotron-3-super-120b-a12b").label).toBe(
497+"nvidia/nvidia/nemotron-3-super-120b-a12b",
468498);
469499});
470500@@ -498,18 +528,14 @@ describe("promptDefaultModel", () => {
498528499529expect(result).toStrictEqual({});
500530expect(loadModelCatalog).not.toHaveBeenCalled();
501-expect(select.mock.calls[0]?.[0]).toMatchObject({
502-searchable: false,
503-initialValue: "__keep__",
504-});
505-expect(select.mock.calls[0]?.[0]?.options).toEqual([
506-expect.objectContaining({
507-value: "__keep__",
508-label: "Keep current (nvidia/nvidia/nemotron-3-super-120b-a12b)",
509-}),
510-expect.objectContaining({ value: "__manual__" }),
511-expect.objectContaining({ value: "__browse__" }),
512-]);
531+const params = pickerParams(select as MockCallSource);
532+expect(params.searchable).toBe(false);
533+expect(params.initialValue).toBe("__keep__");
534+const options = pickerOptions(select as MockCallSource);
535+expect(optionValues(options)).toEqual(["__keep__", "__manual__", "__browse__"]);
536+expect(requireOption(options, "__keep__").label).toBe(
537+"Keep current (nvidia/nvidia/nemotron-3-super-120b-a12b)",
538+);
513539});
514540515541it("keeps current preferred-provider models cold until browsing is requested", async () => {
@@ -535,14 +561,13 @@ describe("promptDefaultModel", () => {
535561536562expect(result).toStrictEqual({});
537563expect(loadModelCatalog).not.toHaveBeenCalled();
538-expect(select.mock.calls[0]?.[0]).toMatchObject({
539-searchable: false,
540-initialValue: "__keep__",
541-});
542-expect(select.mock.calls[0]?.[0]?.options).toEqual([
543-expect.objectContaining({ value: "__keep__" }),
544-expect.objectContaining({ value: "__manual__" }),
545-expect.objectContaining({ value: "__browse__" }),
564+const params = pickerParams(select as MockCallSource);
565+expect(params.searchable).toBe(false);
566+expect(params.initialValue).toBe("__keep__");
567+expect(optionValues(pickerOptions(select as MockCallSource))).toEqual([
568+"__keep__",
569+"__manual__",
570+"__browse__",
546571]);
547572});
548573@@ -656,7 +681,7 @@ describe("promptDefaultModel", () => {
656681mode: "setup",
657682});
658683expect(result.model).toBe("vllm/meta-llama/Meta-Llama-3-8B-Instruct");
659-expect(result.config?.models?.providers?.vllm).toMatchObject({
684+expect(result.config?.models?.providers?.vllm).toEqual({
660685baseUrl: "http://127.0.0.1:8000/v1",
661686api: "openai-completions",
662687apiKey: "VLLM_API_KEY", // pragma: allowlist secret
@@ -713,12 +738,9 @@ describe("promptDefaultModel", () => {
713738});
714739715740expect(providerModelPickerContributionRuntime.resolve).toHaveBeenCalledOnce();
716-expect(select.mock.calls[0]?.[0]?.options).toEqual(
717-expect.arrayContaining([expect.objectContaining({ value: "ollama", label: "Ollama" })]),
718-);
719-expect(select.mock.calls[0]?.[0]?.options).not.toEqual(
720-expect.arrayContaining([expect.objectContaining({ value: "legacy-entry" })]),
721-);
741+const options = pickerOptions(select as MockCallSource);
742+expect(requireOption(options, "ollama").label).toBe("Ollama");
743+expect(optionValues(options)).not.toContain("legacy-entry");
722744});
723745724746it("keeps skip-auth model selection cold when catalog loading is disabled", async () => {
@@ -748,10 +770,10 @@ describe("promptDefaultModel", () => {
748770expect(loadModelCatalog).not.toHaveBeenCalled();
749771expect(resolveProviderModelPickerEntries).not.toHaveBeenCalled();
750772expect(providerModelPickerContributionRuntime.resolve).not.toHaveBeenCalled();
751-expect(select.mock.calls[0]?.[0]?.options).toEqual([
752-expect.objectContaining({ value: "__keep__" }),
753-expect.objectContaining({ value: "__manual__" }),
754-expect.objectContaining({ value: "openai/gpt-5.5" }),
773+expect(optionValues(pickerOptions(select as MockCallSource))).toEqual([
774+"__keep__",
775+"__manual__",
776+"openai/gpt-5.5",
755777]);
756778});
757779@@ -796,14 +818,10 @@ describe("promptDefaultModel", () => {
796818runtime: {} as never,
797819});
798820799-expect(select.mock.calls[0]?.[0]?.options).toEqual(
800-expect.arrayContaining([
801-expect.objectContaining({
802-value: "provider-plugin:nvidia:api-key",
803-label: "NVIDIA (custom)",
804-}),
805-]),
806-);
821+expect(
822+requireOption(pickerOptions(select as MockCallSource), "provider-plugin:nvidia:api-key")
823+.label,
824+).toBe("NVIDIA (custom)");
807825});
808826});
809827@@ -1221,8 +1239,8 @@ describe("promptModelAllowlist", () => {
12211239});
1222124012231241expect(loadModelCatalog).not.toHaveBeenCalled();
1224-expect(multiselect.mock.calls[0]?.[0]?.options).toEqual([
1225-expect.objectContaining({ value: "openai-codex/gpt-5.5" }),
1242+expect(optionValues(pickerOptions(multiselect as MockCallSource))).toEqual([
1243+"openai-codex/gpt-5.5",
12261244]);
12271245expect(multiselect.mock.calls[0]?.[0]?.initialValues).toEqual(["openai-codex/gpt-5.5"]);
12281246expect(result).toEqual({
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。