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
88 lines
2.9 KiB
TypeScript
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"]);
|
|
});
|
|
});
|