


















@@ -271,6 +271,77 @@ describe("createModelSelectionState catalog loading", () => {
271271expect(loadModelCatalog).toHaveBeenCalledOnce();
272272});
273273274+it("does not reject wildcard-only policy before an explicit model directive is resolved", async () => {
275+vi.mocked(loadModelCatalog).mockClear();
276+vi.mocked(loadModelCatalog).mockResolvedValueOnce([]);
277+const cfg = {
278+agents: {
279+defaults: {
280+model: { primary: "anthropic/claude-opus-4-5" },
281+models: {
282+"vllm/*": {},
283+},
284+},
285+},
286+} as OpenClawConfig;
287+288+const state = await createModelSelectionState({
289+ cfg,
290+agentCfg: cfg.agents?.defaults,
291+defaultProvider: "anthropic",
292+defaultModel: "claude-opus-4-5",
293+provider: "anthropic",
294+model: "claude-opus-4-5",
295+hasModelDirective: true,
296+});
297+298+expect(state.provider).toBe("anthropic");
299+expect(state.model).toBe("claude-opus-4-5");
300+expect(state.allowedModelKeys.has("vllm/*")).toBe(true);
301+expect(loadModelCatalog).toHaveBeenCalledOnce();
302+});
303+304+it("keeps a stored dynamic provider wildcard model when the catalog has no rows yet", async () => {
305+vi.mocked(loadModelCatalog).mockClear();
306+vi.mocked(loadModelCatalog).mockResolvedValueOnce([]);
307+const cfg = {
308+agents: {
309+defaults: {
310+model: { primary: "anthropic/claude-opus-4-5" },
311+models: {
312+"vllm/*": {},
313+},
314+},
315+},
316+} as OpenClawConfig;
317+const sessionEntry: SessionEntry = {
318+sessionId: "s1",
319+updatedAt: 1,
320+providerOverride: "vllm",
321+modelOverride: "new-local-model",
322+modelOverrideSource: "user",
323+};
324+const sessionStore = { main: sessionEntry };
325+326+const state = await createModelSelectionState({
327+ cfg,
328+agentCfg: cfg.agents?.defaults,
329+defaultProvider: "anthropic",
330+defaultModel: "claude-opus-4-5",
331+provider: "anthropic",
332+model: "claude-opus-4-5",
333+hasModelDirective: false,
334+ sessionEntry,
335+ sessionStore,
336+sessionKey: "main",
337+});
338+339+expect(state.provider).toBe("vllm");
340+expect(state.model).toBe("new-local-model");
341+expect(sessionStore.main.modelOverride).toBe("new-local-model");
342+expect(loadModelCatalog).toHaveBeenCalledOnce();
343+});
344+274345it("preserves OpenAI API-key session auth when model policy explicitly pins PI", async () => {
275346authProfileStoreMock.store = {
276347version: 1,
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。