feat: 设置页新增模型卡片,支持为7种能力配置默认模型

This commit is contained in:
2026-06-07 09:51:04 +08:00
parent 43b14a94a3
commit 074ea0bb1a
8 changed files with 338 additions and 25 deletions

View File

@@ -113,4 +113,45 @@ describe("设置数据访问层", () => {
expect(result).toEqual({ compact: false, theme: "dark" });
});
});
test("updateSettings 写入 defaultModels 并读取", () => {
withSettingsDb((db) => {
const updated = updateSettings(
db,
{ defaultModels: { text: "model-1", imageRecognition: null } },
createNoopLogger(),
);
expect(updated.defaultModels).toEqual({ text: "model-1", imageRecognition: null });
expect(updated.compact).toBe(false);
expect(updated.theme).toBe("system");
const read = getSettings(db);
expect(read.defaultModels).toEqual({ text: "model-1", imageRecognition: null });
});
});
test("defaultModels 与 theme/compact 合并持久化", () => {
withSettingsDb((db) => {
updateSettings(db, { theme: "dark", compact: true }, createNoopLogger());
const result = updateSettings(db, { defaultModels: { imageGeneration: "model-2" } }, createNoopLogger());
expect(result).toEqual({
compact: true,
defaultModels: { imageGeneration: "model-2" },
theme: "dark",
});
});
});
test("defaultModels 全量替换——前端负责深度合并", () => {
withSettingsDb((db) => {
updateSettings(db, { defaultModels: { text: "model-1", imageRecognition: "model-2" } }, createNoopLogger());
// 前端在 onChange 中负责合并 old + newField提交完整对象
const result = updateSettings(
db,
{ defaultModels: { text: "model-3", imageRecognition: "model-2" } },
createNoopLogger(),
);
expect(result.defaultModels).toEqual({ text: "model-3", imageRecognition: "model-2" });
});
});
});

View File

@@ -2,7 +2,7 @@ import type Database from "bun:sqlite";
import { describe, expect, test } from "bun:test";
import type { RuntimeMode } from "../../../src/shared/api";
import type { RuntimeMode, SettingsData } from "../../../src/shared/api";
import { createNoopLogger } from "../../../src/server/logger";
import { createMigratedMemoryTestDatabase } from "../../helpers";
@@ -191,4 +191,48 @@ describe("设置 API 路由", () => {
expect(body).toEqual({ compact: true, theme: "dark" });
});
});
test("PUT /api/settings 写入 defaultModels 后 GET 返回包含该字段", async () => {
await withRouteDb(async (db) => {
const putReq = new Request("http://localhost/api/settings", {
body: JSON.stringify({ defaultModels: { text: "model-1", imageRecognition: null } }),
headers: { "Content-Type": "application/json" },
method: "PUT",
});
const putRes = await updateSettingsViaHandler(putReq, db);
expect(putRes.status).toBe(200);
const putBody = (await putRes.json()) as SettingsData;
expect(putBody.defaultModels).toEqual({ text: "model-1", imageRecognition: null });
expect(putBody.compact).toBe(false);
expect(putBody.theme).toBe("system");
const getReq = new Request("http://localhost/api/settings");
const getRes = await getSettingsViaHandler(getReq, db);
expect(getRes.status).toBe(200);
const getBody = (await getRes.json()) as SettingsData;
expect(getBody.defaultModels).toEqual({ text: "model-1", imageRecognition: null });
});
});
test("PUT /api/settings defaultModels 与 theme 合并持久化不丢失", async () => {
await withRouteDb(async (db) => {
const req1 = new Request("http://localhost/api/settings", {
body: JSON.stringify({ theme: "dark" }),
headers: { "Content-Type": "application/json" },
method: "PUT",
});
await updateSettingsViaHandler(req1, db);
const req2 = new Request("http://localhost/api/settings", {
body: JSON.stringify({ defaultModels: { videoGeneration: "model-v" } }),
headers: { "Content-Type": "application/json" },
method: "PUT",
});
const res2 = await updateSettingsViaHandler(req2, db);
expect(res2.status).toBe(200);
const body = (await res2.json()) as SettingsData;
expect(body.theme).toBe("dark");
expect(body.defaultModels).toEqual({ videoGeneration: "model-v" });
});
});
});