


























@@ -302,8 +302,8 @@ vi.mock("./model-catalog.js", () => ({
302302loadManifestModelCatalog: state.loadManifestModelCatalogMock,
303303}));
304304305-vi.mock("./model-selection.js", () => ({
306-buildAllowedModelSet: ({
305+vi.mock("./model-selection.js", () => {
306+const buildAllowedModelSet = ({
307307 cfg,
308308 catalog,
309309 defaultProvider,
@@ -369,83 +369,122 @@ vi.mock("./model-selection.js", () => ({
369369),
370370allowAny: false,
371371};
372-},
373-buildConfiguredModelCatalog: ({ cfg }: { cfg?: unknown }) => {
374-const providers = (cfg as { models?: { providers?: Record<string, { models?: unknown[] }> } })
375-?.models?.providers;
376-if (!providers) {
377-return [];
378-}
379-return Object.entries(providers).flatMap(([provider, entry]) =>
380-Array.isArray(entry?.models)
381- ? entry.models
382-.filter(
383-(model): model is Record<string, unknown> => !!model && typeof model === "object",
384-)
385-.map((model) => {
386-const id = typeof model.id === "string" ? model.id : "";
387-return {
388- provider,
389- id,
390-name: typeof model.name === "string" ? model.name : id,
391-reasoning: typeof model.reasoning === "boolean" ? model.reasoning : undefined,
392-compat: model.compat,
393-};
394-})
395-.filter((model) => model.id)
396- : [],
397-);
398-},
399-isModelKeyAllowedBySet: (allowedKeys: ReadonlySet<string>, key: string) => {
400-if (allowedKeys.has(key)) {
401-return true;
402-}
403-const slash = key.indexOf("/");
404-return slash > 0 && allowedKeys.has(`${key.slice(0, slash)}/*`);
405-},
406-resolveAllowedModelSelection: ({
407- provider,
408- model,
409- allowAny,
410- allowedKeys,
411- allowedCatalog,
412-}: {
413-provider: string;
414-model: string;
415-allowAny: boolean;
416-allowedKeys: ReadonlySet<string>;
417-allowedCatalog: Array<{ provider: string; id: string }>;
418-}) => {
419-const key = `${provider}/${model}`;
420-if (
421-allowAny ||
422-allowedKeys.has(key) ||
423-(key.includes("/") && allowedKeys.has(`${key.slice(0, key.indexOf("/"))}/*`))
424-) {
425-return { provider, model };
426-}
427-const fallback = allowedCatalog[0];
428-return fallback ? { provider: fallback.provider, model: fallback.id } : null;
429-},
430-modelKey: (p: string, m: string) => `${p}/${m}`,
431-normalizeModelRef: (p: string, m: string) => ({ provider: p, model: m }),
432-parseModelRef: (m: string, p: string) => ({ provider: p, model: m }),
433-resolveConfiguredModelRef: ({ cfg }: { cfg?: unknown }) => {
434-const raw = (cfg as { agents?: { defaults?: { model?: string | { primary?: string } } } })
435-?.agents?.defaults?.model;
436-const primary = typeof raw === "string" ? raw : raw?.primary;
437-const [provider, ...modelParts] = (primary ?? "anthropic/claude").split("/");
438-return { provider, model: modelParts.join("/") || "claude" };
439-},
440-resolveDefaultModelForAgent: ({ cfg }: { cfg?: unknown }) => {
441-const raw = (cfg as { agents?: { defaults?: { model?: string | { primary?: string } } } })
442-?.agents?.defaults?.model;
443-const primary = typeof raw === "string" ? raw : raw?.primary;
444-const [provider, ...modelParts] = (primary ?? "anthropic/claude").split("/");
445-return { provider, model: modelParts.join("/") || "claude" };
446-},
447-resolveThinkingDefault: (args: unknown) => state.resolveThinkingDefaultMock(args),
448-}));
372+};
373+374+return {
375+ buildAllowedModelSet,
376+createModelVisibilityPolicy: (params: {
377+cfg?: unknown;
378+catalog?: Array<{ provider: string; id: string }>;
379+defaultProvider: string;
380+defaultModel?: string;
381+}) => {
382+const allowed = buildAllowedModelSet(params);
383+const allowsKey = (key: string) => {
384+if (allowed.allowAny || allowed.allowedKeys.has(key)) {
385+return true;
386+}
387+const slash = key.indexOf("/");
388+return slash > 0 && allowed.allowedKeys.has(`${key.slice(0, slash)}/*`);
389+};
390+return {
391+ ...allowed,
392+exactModelRefs: [],
393+providerWildcards: new Set<string>(),
394+hasConfiguredEntries: !allowed.allowAny,
395+hasProviderWildcards: [...allowed.allowedKeys].some((key) => key.endsWith("/*")),
396+ allowsKey,
397+allows: ({ provider, model }: { provider: string; model: string }) =>
398+allowsKey(`${provider}/${model}`),
399+resolveSelection: ({ provider, model }: { provider: string; model: string }) => {
400+const key = `${provider}/${model}`;
401+if (allowsKey(key)) {
402+return { provider, model };
403+}
404+const fallback = allowed.allowedCatalog[0];
405+return fallback ? { provider: fallback.provider, model: fallback.id } : null;
406+},
407+visibleCatalog: ({ catalog }: { catalog: Array<{ provider: string; id: string }> }) =>
408+catalog,
409+};
410+},
411+buildConfiguredModelCatalog: ({ cfg }: { cfg?: unknown }) => {
412+const providers = (cfg as { models?: { providers?: Record<string, { models?: unknown[] }> } })
413+?.models?.providers;
414+if (!providers) {
415+return [];
416+}
417+return Object.entries(providers).flatMap(([provider, entry]) =>
418+Array.isArray(entry?.models)
419+ ? entry.models
420+.filter(
421+(model): model is Record<string, unknown> => !!model && typeof model === "object",
422+)
423+.map((model) => {
424+const id = typeof model.id === "string" ? model.id : "";
425+return {
426+ provider,
427+ id,
428+name: typeof model.name === "string" ? model.name : id,
429+reasoning: typeof model.reasoning === "boolean" ? model.reasoning : undefined,
430+compat: model.compat,
431+};
432+})
433+.filter((model) => model.id)
434+ : [],
435+);
436+},
437+isModelKeyAllowedBySet: (allowedKeys: ReadonlySet<string>, key: string) => {
438+if (allowedKeys.has(key)) {
439+return true;
440+}
441+const slash = key.indexOf("/");
442+return slash > 0 && allowedKeys.has(`${key.slice(0, slash)}/*`);
443+},
444+resolveAllowedModelSelection: ({
445+ provider,
446+ model,
447+ allowAny,
448+ allowedKeys,
449+ allowedCatalog,
450+}: {
451+provider: string;
452+model: string;
453+allowAny: boolean;
454+allowedKeys: ReadonlySet<string>;
455+allowedCatalog: Array<{ provider: string; id: string }>;
456+}) => {
457+const key = `${provider}/${model}`;
458+if (
459+allowAny ||
460+allowedKeys.has(key) ||
461+(key.includes("/") && allowedKeys.has(`${key.slice(0, key.indexOf("/"))}/*`))
462+) {
463+return { provider, model };
464+}
465+const fallback = allowedCatalog[0];
466+return fallback ? { provider: fallback.provider, model: fallback.id } : null;
467+},
468+modelKey: (p: string, m: string) => `${p}/${m}`,
469+normalizeModelRef: (p: string, m: string) => ({ provider: p, model: m }),
470+parseModelRef: (m: string, p: string) => ({ provider: p, model: m }),
471+resolveConfiguredModelRef: ({ cfg }: { cfg?: unknown }) => {
472+const raw = (cfg as { agents?: { defaults?: { model?: string | { primary?: string } } } })
473+?.agents?.defaults?.model;
474+const primary = typeof raw === "string" ? raw : raw?.primary;
475+const [provider, ...modelParts] = (primary ?? "anthropic/claude").split("/");
476+return { provider, model: modelParts.join("/") || "claude" };
477+},
478+resolveDefaultModelForAgent: ({ cfg }: { cfg?: unknown }) => {
479+const raw = (cfg as { agents?: { defaults?: { model?: string | { primary?: string } } } })
480+?.agents?.defaults?.model;
481+const primary = typeof raw === "string" ? raw : raw?.primary;
482+const [provider, ...modelParts] = (primary ?? "anthropic/claude").split("/");
483+return { provider, model: modelParts.join("/") || "claude" };
484+},
485+resolveThinkingDefault: (args: unknown) => state.resolveThinkingDefaultMock(args),
486+};
487+});
449488450489vi.mock("./provider-auth-aliases.js", () => ({
451490resolveProviderAuthAliasMap: () => ({}),
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。