Preserve Claude model and thinking preferences (#2912)
* fix(agents): preserve Claude thinking selections Model switches now resolve thinking against the target model's saved preference instead of resetting to the catalog default. Claude owns its configured-model defaults and legacy Fable alias handling, while persisted permission modes remain unchanged. * chore(claude): tag Fable compatibility shim * fix(app): resolve persisted model aliases * fix(models): preserve aliases for older clients * fix(models): hide compatibility aliases from listings * fix(settings): hide compatibility model aliases * test(claude): cover legacy catalog entry * test(app): expect mock thinking controls in schedules * fix(app): preserve queued thinking preferences * fix(app): reconcile schedule provider snapshots * fix(app): preserve schedule model selections * fix(claude): preserve exact configured model ids * fix(app): preserve committed thinking preferences * fix(app): preserve aliased schedule thinking
This commit is contained in:
@@ -74,6 +74,8 @@ export type ProviderStatus = "ready" | "loading" | "error" | "unavailable";
|
||||
export interface AgentModelDefinition {
|
||||
provider: AgentProvider;
|
||||
id: string;
|
||||
aliases?: string[];
|
||||
isSelectable?: boolean;
|
||||
label: string;
|
||||
description?: string;
|
||||
isDefault?: boolean;
|
||||
|
||||
@@ -259,6 +259,8 @@ export const AgentFeatureSchema = z.discriminatedUnion("type", [
|
||||
const AgentModelDefinitionSchema = z.object({
|
||||
provider: AgentProviderSchema,
|
||||
id: z.string(),
|
||||
aliases: z.array(z.string()).optional(),
|
||||
isSelectable: z.boolean().optional(),
|
||||
label: z.string(),
|
||||
description: z.string().optional(),
|
||||
isDefault: z.boolean().optional(),
|
||||
|
||||
@@ -175,6 +175,13 @@ const MOCK_LOAD_TEST_MODES: AgentProviderModeDefinition[] = [
|
||||
icon: "ShieldOff",
|
||||
colorTier: "dangerous",
|
||||
},
|
||||
{
|
||||
id: "approval-test",
|
||||
label: "Approval Test",
|
||||
description: "Alternate development-only permission mode for preference tests",
|
||||
icon: "ShieldCheck",
|
||||
colorTier: "safe",
|
||||
},
|
||||
];
|
||||
|
||||
const MOCK_SLOW_MODES: AgentProviderModeDefinition[] = [
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
import type { ProviderSnapshotEntry } from "./agent-types.js";
|
||||
import { CompactProviderSnapshotSchema } from "./messages.js";
|
||||
import { compactProviderSnapshot, expandProviderSnapshot } from "./provider-snapshot-codec.js";
|
||||
|
||||
const sharedThinking = [
|
||||
@@ -21,6 +22,8 @@ function providerEntry(): ProviderSnapshotEntry {
|
||||
{
|
||||
provider: "pi",
|
||||
id: "openai/gpt-a",
|
||||
aliases: ["openai/gpt-a-legacy"],
|
||||
isSelectable: false,
|
||||
label: "GPT A",
|
||||
description: "openai/gpt-a",
|
||||
metadata: { provider: "openai", modelId: "gpt-a" },
|
||||
@@ -48,6 +51,9 @@ describe("provider snapshot codec", () => {
|
||||
|
||||
expect(compact.thinkingSets).toHaveLength(1);
|
||||
expect(compact.entries[0]?.models?.map((model) => model.thinkingSet)).toEqual([0, 0]);
|
||||
expect(CompactProviderSnapshotSchema.parse(compact)).toEqual(compact);
|
||||
expect(compact.entries[0]?.models?.[0]?.aliases).toEqual(["openai/gpt-a-legacy"]);
|
||||
expect(compact.entries[0]?.models?.[0]?.isSelectable).toBe(false);
|
||||
expect(expanded).toEqual(original);
|
||||
expect(expanded[0]?.models?.[0]?.thinkingOptions).toBe(
|
||||
expanded[0]?.models?.[1]?.thinkingOptions,
|
||||
|
||||
Reference in New Issue
Block a user