fix(setup): honored project model-role storage

Setup now writes the chosen default to the project layer via setProjectModelRole when modelRoleStorage is project, instead of unconditionally persisting to the global config. Split the setup selection test into global and project scope cases.

Fixes #5979
This commit is contained in:
roboomp
2026-07-18 11:29:20 +00:00
parent e6f108f340
commit a7b75af19f
2 changed files with 39 additions and 18 deletions
@@ -109,7 +109,11 @@ class ModelSceneController implements SetupSceneController {
this.#status = theme.fg("muted", `Saving ${selector} as the default model…`);
this.host.requestRender();
try {
await this.host.ctx.session.setModel(model, "default", { selector, persist: true });
const projectScope = this.host.ctx.settings.get("modelRoleStorage") === "project";
await this.host.ctx.session.setModel(model, "default", { selector, persist: !projectScope });
if (projectScope) {
this.host.ctx.settings.setProjectModelRole("default", selector);
}
await this.host.ctx.settings.flush();
if (!this.#disposed) this.host.finish("done");
} catch (error) {
+34 -17
View File
@@ -113,21 +113,21 @@ describe("setup wizard scene selection", () => {
});
describe("setup wizard model selection", () => {
it("discovers and saves an uncached custom model as the default", async () => {
const CUSTOM_MODEL: Model = buildModel({
id: "minimax-m3",
name: "MiniMax M3",
api: "openai-completions",
provider: "spark",
baseUrl: "http://127.0.0.1:8000/v1",
reasoning: true,
input: ["text"],
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
contextWindow: 100_000,
maxTokens: 32_000,
});
async function pickModelDuringSetup(settings: Settings): Promise<string> {
await initTheme(false, "unicode", false, "titanium", "dark");
const settings = Settings.isolated();
const model: Model = buildModel({
id: "minimax-m3",
name: "MiniMax M3",
api: "openai-completions",
provider: "spark",
baseUrl: "http://127.0.0.1:8000/v1",
reasoning: true,
input: ["text"],
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
contextWindow: 100_000,
maxTokens: 32_000,
});
let available: Model[] = [];
const finished = Promise.withResolvers<string>();
const setModel = mock(
@@ -151,7 +151,7 @@ describe("setup wizard model selection", () => {
getAvailable: () => available,
getAll: () => available,
refresh: async (strategy: string) => {
if (strategy === "online-if-uncached") available = [model];
if (strategy === "online-if-uncached") available = [CUSTOM_MODEL];
},
},
setModel,
@@ -171,10 +171,27 @@ describe("setup wizard model selection", () => {
await controller.onMount?.();
expect(controller.render?.(120).join("\n")).toContain("minimax-m3");
controller.handleInput?.("\r");
const result = await finished.promise;
return finished.promise;
}
it("discovers and saves an uncached custom model as the global default", async () => {
const settings = Settings.isolated();
const result = await pickModelDuringSetup(settings);
expect(settings.getModelRole("default")).toBe("spark/minimax-m3");
expect(result).toBe("done");
expect(settings.getGlobalModelRole("default")).toBe("spark/minimax-m3");
expect(settings.getProjectModelRole("default")).toBeUndefined();
});
it("saves to the project layer under project role storage", async () => {
const settings = Settings.isolated({ modelRoleStorage: "project" });
const result = await pickModelDuringSetup(settings);
expect(result).toBe("done");
expect(settings.getProjectModelRole("default")).toBe("spark/minimax-m3");
expect(settings.getGlobalModelRole("default")).toBeUndefined();
});
});