feat(ai): unify model discovery and effort handling

This commit is contained in:
Guoyu Su authored and GitHub committed 2026-07-28 21:37:55 +08:00
1 parent c54b95e274
commit c7e7b7c9d9
41 files changed
+3291 -634

No files matched your search

@@ -1,5 +1,5 @@
import { describe, expect, it } from "vitest";
import { getAiConfigModelIds, isAiConfigModelCandidate } from "@/lib/ai/aiConfigCandidates";
import { isAiConfigModelCandidate } from "@/lib/ai/aiConfigCandidates";
import type { AiConfig } from "@/types/ai";
function config(overrides: Partial<AiConfig> = {}): AiConfig {
@@ -39,16 +39,3 @@ describe("isAiConfigModelCandidate", () => {
).toBe(true);
});
});
describe("getAiConfigModelIds", () => {
it("includes the default model once while preserving configured model order", () => {
expect(
getAiConfigModelIds(
config({
model: "gpt-default",
models: [{ name: "gpt-fast" }, { name: "gpt-default" }, { name: "gpt-default" }],
}),
),
).toEqual(["gpt-fast", "gpt-default"]);
});
});
@@ -0,0 +1,44 @@
import { describe, expect, it } from "vitest";
import { effortPreferenceUpdateForCapability, runtimeEffortFromPreference } from "@/lib/ai/aiEffortPreference";
import { normalizeAiConfig } from "@/stores/settingsStore";
import type { AiEffortCapability } from "@/types/ai";
const enumCapability: AiEffortCapability = {
kind: "enum",
options: [
{ id: "low", label: "Low", selection: { kind: "enum", value: "low" } },
{ id: "high", label: "High", selection: { kind: "enum", value: "high" } },
],
default: { kind: "enum", value: "low" },
source: "localCli",
};
describe("runtimeEffortFromPreference", () => {
it("leaves runtime effort absent so legacy effort settings remain available", () => {
const config = normalizeAiConfig({
provider: "codex-cli",
enableThinking: false,
reasoningLevel: "high",
runtimeEffort: runtimeEffortFromPreference(null),
});
expect(config.runtimeEffort).toBeUndefined();
expect(config.enableThinking).toBe(false);
expect(config.reasoningLevel).toBe("high");
expect(JSON.parse(JSON.stringify(config))).not.toHaveProperty("runtimeEffort");
});
it("preserves an explicitly selected provider default", () => {
expect(runtimeEffortFromPreference({ kind: "providerDefault" })).toEqual({ kind: "providerDefault" });
});
});
describe("effortPreferenceUpdateForCapability", () => {
it("does not create a preference while capability data loads", () => {
expect(effortPreferenceUpdateForCapability(enumCapability, null)).toBeUndefined();
});
it("preserves existing correction behavior for an unsupported explicit preference", () => {
expect(effortPreferenceUpdateForCapability(enumCapability, { kind: "enum", value: "future" })).toEqual({ kind: "enum", value: "low" });
});
});
-29
View File
@@ -1,29 +0,0 @@
import { describe, expect, it } from "vitest";
import { normalizeAiModelEffortLevels, normalizeClaudeCodeReasoningLevel } from "@/lib/ai/aiModelEffort";
import type { AiModelInfo } from "@/lib/backend/tauri";
describe("normalizeAiModelEffortLevels", () => {
it("preserves the CLI order while removing duplicates and unknown levels", () => {
expect(normalizeAiModelEffortLevels(["low", "high", "xhigh", "high", "future", null, "max"])).toEqual(["low", "high", "xhigh", "max"]);
});
it("returns no configurable levels when metadata is unavailable", () => {
expect(normalizeAiModelEffortLevels(undefined)).toEqual([]);
});
});
describe("normalizeClaudeCodeReasoningLevel", () => {
const model: AiModelInfo = {
id: "claude-sonnet-5",
supportedEffortLevels: ["low", "medium", "high", "xhigh", "max"],
};
it("keeps an effort level reported by the selected model", () => {
expect(normalizeClaudeCodeReasoningLevel("xhigh", model)).toBe("xhigh");
});
it("falls back to default for unsupported or missing model metadata", () => {
expect(normalizeClaudeCodeReasoningLevel("minimal", model)).toBe("default");
expect(normalizeClaudeCodeReasoningLevel("max", { id: "default" })).toBe("default");
});
});