Files
tutti/packages/agent/gui/agent-gui/agentGuiNode/model/composerModelChoiceHistory.spec.ts
agent-radar 2ed3415fb7
Publish Claude Code Binaries / Stage and publish binaries (push) Canceled after 0s
Publish Tutti App Runtime / Build darwin-arm64 (push) Canceled after 0s
Publish Tutti App Runtime / Build darwin-amd64 (push) Canceled after 0s
Publish Tutti App Runtime / Build linux-amd64 (push) Canceled after 0s
Publish Tutti App Runtime / Build windows-amd64 (push) Canceled after 0s
Sync Tutti Agent Skills / sync (push) Canceled after 0s
Windows Agent Adapters / Test Windows agent adapters (push) Canceled after 0s
Windows Daemon Adapters / Test Windows daemon adapters (push) Canceled after 0s
Publish Tutti App Runtime / Publish runtime catalog (push) Canceled after 0s
源码快照 @ 2026-09-01 (source-only, 剔除非源码素材)
2026-09-01 20:17:27 +08:00

88 lines
2.9 KiB
TypeScript

import { describe, expect, it } from "vitest";
import {
MAX_RECENT_COMPOSER_MODELS,
composerModelFavoritesStorageKey,
composerModelRecentsStorageKey,
parseComposerModelIdList,
reconcileRecentComposerModels,
recordRecentComposerModel,
serializeComposerModelIdList,
toggleFavoriteComposerModel,
type ComposerModelHistoryVerdict
} from "./composerModelChoiceHistory";
describe("composerModelChoiceHistory", () => {
it("scopes storage keys per agent target with a default bucket", () => {
expect(composerModelRecentsStorageKey("target-1")).toBe(
"agent-gui:composer-model-recents:target-1"
);
expect(composerModelFavoritesStorageKey("target-1")).toBe(
"agent-gui:composer-model-favorites:target-1"
);
expect(composerModelRecentsStorageKey(" ")).toBe(
"agent-gui:composer-model-recents:default"
);
expect(composerModelFavoritesStorageKey(null)).toBe(
"agent-gui:composer-model-favorites:default"
);
});
it("round-trips id lists and drops malformed entries", () => {
expect(parseComposerModelIdList(null)).toEqual([]);
expect(parseComposerModelIdList("not json")).toEqual([]);
expect(parseComposerModelIdList('{"a":1}')).toEqual([]);
expect(parseComposerModelIdList('["m1", "", 3, "m1", " m2 "]')).toEqual([
"m1",
"m2"
]);
expect(serializeComposerModelIdList(["m1", "m1", " m2 "])).toBe(
'["m1","m2"]'
);
});
it("records recents most-recent-first capped at five", () => {
let recents: readonly string[] = [];
for (const modelId of ["m1", "m2", "m3", "m4", "m5", "m6"]) {
recents = recordRecentComposerModel(recents, modelId);
}
expect(recents).toEqual(["m6", "m5", "m4", "m3", "m2"]);
expect(recents).toHaveLength(MAX_RECENT_COMPOSER_MODELS);
// Re-picking an existing model moves it to the front without duplicates.
expect(recordRecentComposerModel(recents, "m4")).toEqual([
"m4",
"m6",
"m5",
"m3",
"m2"
]);
// Blank picks leave the list untouched.
expect(recordRecentComposerModel(recents, " ")).toEqual(recents);
});
it("toggles favorites on and off", () => {
const withFavorite = toggleFavoriteComposerModel([], "m1");
expect(withFavorite).toEqual(["m1"]);
expect(toggleFavoriteComposerModel(withFavorite, "m2")).toEqual([
"m1",
"m2"
]);
expect(toggleFavoriteComposerModel(withFavorite, "m1")).toEqual([]);
expect(toggleFavoriteComposerModel(withFavorite, " ")).toEqual(["m1"]);
});
it("removes only positively rejected recent models", () => {
const verdicts = new Map<string, ComposerModelHistoryVerdict>([
["old", "rejected"],
["valid", "verified"],
["unknown", "unverifiable"]
]);
expect(
reconcileRecentComposerModels(
["old", "valid", "unknown"],
(modelId) => verdicts.get(modelId) ?? "unverifiable"
)
).toEqual(["valid", "unknown"]);
});
});