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:
@@ -32,6 +32,7 @@ import {
|
||||
buildSelectableProviderSelectorProviders,
|
||||
type ProviderSelectorProvider,
|
||||
} from "@/provider-selection/provider-selection";
|
||||
import { filterSelectableModels } from "@/provider-selection/model-catalog";
|
||||
import { useSessionStore } from "@/stores/session-store";
|
||||
import { useProvidersSnapshot } from "@/hooks/use-providers-snapshot";
|
||||
import { resolveProviderDefinition } from "@/utils/provider-definitions";
|
||||
@@ -1448,7 +1449,7 @@ export const AgentControls = memo(function AgentControls({
|
||||
[snapshotEntries, agent?.provider],
|
||||
);
|
||||
|
||||
const models = snapshotSelectedEntry?.models ?? null;
|
||||
const models = filterSelectableModels(snapshotSelectedEntry?.models ?? null);
|
||||
const selectedProviderIsLoading = snapshotSelectedEntry?.status === "loading";
|
||||
|
||||
const agentProviderDefinitions = useMemo(
|
||||
|
||||
@@ -53,6 +53,28 @@ describe("normalizeModelId", () => {
|
||||
});
|
||||
|
||||
describe("resolveAgentModelSelection", () => {
|
||||
it("resolves a configured model alias to its canonical catalog model", () => {
|
||||
const selection = resolveAgentModelSelection({
|
||||
models: [
|
||||
{
|
||||
provider: "claude",
|
||||
id: "claude-fable-5",
|
||||
aliases: ["claude-fable-5[1m]"],
|
||||
label: "Fable 5",
|
||||
thinkingOptions: [{ id: "high", label: "High" }],
|
||||
defaultThinkingOptionId: "high",
|
||||
},
|
||||
],
|
||||
runtimeModelId: null,
|
||||
configuredModelId: "claude-fable-5[1m]",
|
||||
explicitThinkingOptionId: null,
|
||||
});
|
||||
|
||||
expect(selection.activeModelId).toBe("claude-fable-5");
|
||||
expect(selection.displayModel).toBe("Fable 5");
|
||||
expect(selection.selectedThinkingId).toBe("high");
|
||||
});
|
||||
|
||||
it("prefers runtime model over configured model", () => {
|
||||
const selection = resolveAgentModelSelection({
|
||||
models: [
|
||||
|
||||
@@ -55,7 +55,11 @@ function findModelById(
|
||||
if (!models || !modelId) {
|
||||
return null;
|
||||
}
|
||||
return models.find((model) => model.id === modelId) ?? null;
|
||||
return (
|
||||
models.find((model) => model.id === modelId) ??
|
||||
models.find((model) => model.aliases?.includes(modelId)) ??
|
||||
null
|
||||
);
|
||||
}
|
||||
|
||||
function getFallbackModel(models: AgentModelDefinition[] | null): AgentModelDefinition | null {
|
||||
|
||||
Reference in New Issue
Block a user