fix: sync assistant runtime preferences
This commit is contained in:
1 parent
3245356f0f
commit
d562706c8b
6 files changed
+94
-10
No files matched your search
@@ -256,6 +256,7 @@ export const AssistantConfiguration = () => {
|
||||
await Promise.all([
|
||||
utils.assistant.getAdminConfiguration.invalidate(),
|
||||
utils.assistant.getAvailability.invalidate(),
|
||||
utils.assistant.getRuntimeOptions.invalidate(),
|
||||
]);
|
||||
showSuccessNotification({
|
||||
title: t("notification.saved.title"),
|
||||
|
||||
@@ -988,6 +988,10 @@
|
||||
flex: 1 1 auto;
|
||||
}
|
||||
|
||||
.modelButton :global(.mantine-Button-label) {
|
||||
font-size: var(--mantine-font-size-xs);
|
||||
}
|
||||
|
||||
.reasoningButton {
|
||||
min-width: 7.5rem;
|
||||
max-width: 10.5rem;
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
import { describe, expect, test } from "vitest";
|
||||
|
||||
import { resolveAssistantPreferenceModelId } from "./assistant-preferences";
|
||||
|
||||
const models = [
|
||||
{ id: "provider/default", name: "Default", inputModalities: ["text"] },
|
||||
{ id: "provider/alternate", name: "Alternate", inputModalities: ["text"] },
|
||||
];
|
||||
|
||||
describe("resolveAssistantPreferenceModelId", () => {
|
||||
test("uses the server default when preferences first load", () => {
|
||||
expect(
|
||||
resolveAssistantPreferenceModelId({
|
||||
currentModelId: null,
|
||||
previousDefaultModelId: undefined,
|
||||
defaultModelId: "provider/default",
|
||||
models,
|
||||
}),
|
||||
).toBe("provider/default");
|
||||
});
|
||||
|
||||
test("adopts a changed server default even when the old model remains available", () => {
|
||||
expect(
|
||||
resolveAssistantPreferenceModelId({
|
||||
currentModelId: "provider/default",
|
||||
previousDefaultModelId: "provider/default",
|
||||
defaultModelId: "provider/alternate",
|
||||
models,
|
||||
}),
|
||||
).toBe("provider/alternate");
|
||||
});
|
||||
|
||||
test("preserves an available conversation selection while the default is unchanged", () => {
|
||||
expect(
|
||||
resolveAssistantPreferenceModelId({
|
||||
currentModelId: "provider/alternate",
|
||||
previousDefaultModelId: "provider/default",
|
||||
defaultModelId: "provider/default",
|
||||
models,
|
||||
}),
|
||||
).toBe("provider/alternate");
|
||||
});
|
||||
|
||||
test("falls back to the default when the selected model is no longer available", () => {
|
||||
expect(
|
||||
resolveAssistantPreferenceModelId({
|
||||
currentModelId: "provider/removed",
|
||||
previousDefaultModelId: "provider/default",
|
||||
defaultModelId: "provider/default",
|
||||
models,
|
||||
}),
|
||||
).toBe("provider/default");
|
||||
});
|
||||
});
|
||||
@@ -5,3 +5,19 @@ export type AssistantRuntimeModelOption = {
|
||||
name: string;
|
||||
inputModalities: string[];
|
||||
};
|
||||
|
||||
export const resolveAssistantPreferenceModelId = ({
|
||||
currentModelId,
|
||||
previousDefaultModelId,
|
||||
defaultModelId,
|
||||
models,
|
||||
}: {
|
||||
currentModelId: string | null;
|
||||
previousDefaultModelId: string | null | undefined;
|
||||
defaultModelId: string | null;
|
||||
models: readonly AssistantRuntimeModelOption[];
|
||||
}) => {
|
||||
if (previousDefaultModelId !== defaultModelId) return defaultModelId;
|
||||
if (currentModelId && models.some((model) => model.id === currentModelId)) return currentModelId;
|
||||
return defaultModelId;
|
||||
};
|
||||
@@ -30,6 +30,7 @@ import { AssistantAskUserTool, AssistantConfigureAppTool } from "./assistant-hum
|
||||
import { AssistantPanel } from "./assistant-panel";
|
||||
import { getPendingAssistantAction } from "./assistant-pending-action";
|
||||
import type { AssistantReasoningMode, AssistantRuntimeModelOption } from "./assistant-preferences";
|
||||
import { resolveAssistantPreferenceModelId } from "./assistant-preferences";
|
||||
import { AssistantRuntimeProviderWithTools } from "./assistant-runtime-provider";
|
||||
import { sendAssistantPrompt as sendPromptThroughComposer } from "./assistant-send";
|
||||
import { createAssistantPromptInteraction } from "./assistant-spotlight";
|
||||
@@ -163,6 +164,7 @@ const AssistantPreferencesProvider = ({ children }: PropsWithChildren) => {
|
||||
});
|
||||
const [modelId, setModelIdState] = useState<string | null>(null);
|
||||
const [reasoning, setReasoningState] = useState<AssistantReasoningMode>("auto");
|
||||
const previousDefaultModelIdRef = useRef<string | null | undefined>(undefined);
|
||||
const preferencesRef = useRef<{ modelId: string | null; reasoning: AssistantReasoningMode }>({
|
||||
modelId: null,
|
||||
reasoning: "auto",
|
||||
@@ -190,10 +192,17 @@ const AssistantPreferencesProvider = ({ children }: PropsWithChildren) => {
|
||||
|
||||
useEffect(() => {
|
||||
if (!data) return;
|
||||
const currentModelId = preferencesRef.current.modelId;
|
||||
if (currentModelId && data.models.some((model) => model.id === currentModelId)) return;
|
||||
setModelId(data.defaultModelId);
|
||||
}, [data, setModelId]);
|
||||
const nextModelId = resolveAssistantPreferenceModelId({
|
||||
currentModelId: preferencesRef.current.modelId,
|
||||
previousDefaultModelId: previousDefaultModelIdRef.current,
|
||||
defaultModelId: data.defaultModelId,
|
||||
models: data.models,
|
||||
});
|
||||
previousDefaultModelIdRef.current = data.defaultModelId;
|
||||
if (nextModelId === preferencesRef.current.modelId) return;
|
||||
preferencesRef.current.modelId = nextModelId;
|
||||
setModelIdState(nextModelId);
|
||||
}, [data]);
|
||||
|
||||
const value = useMemo(
|
||||
() => ({
|
||||
|
||||
@@ -1554,12 +1554,12 @@
|
||||
"noModels": "No models available",
|
||||
"thinking": "Thinking mode",
|
||||
"reasoning": {
|
||||
"auto": "Thinking: Auto",
|
||||
"none": "Thinking: Off",
|
||||
"minimal": "Thinking: Minimal",
|
||||
"low": "Thinking: Low",
|
||||
"medium": "Thinking: Medium",
|
||||
"high": "Thinking: High"
|
||||
"auto": "Auto",
|
||||
"none": "Off",
|
||||
"minimal": "Minimal",
|
||||
"low": "Low",
|
||||
"medium": "Medium",
|
||||
"high": "High"
|
||||
}
|
||||
},
|
||||
"stop": "Stop response",
|
||||
|
||||
Reference in new issue
Block a user