feat(agent): let users choose model route

This commit is contained in:
ginnoir
2026-07-08 19:50:46 -05:00
parent b279f16ba0
commit ec3f96dab1
13 changed files with 235 additions and 45 deletions
+1 -1
View File
@@ -32,7 +32,7 @@ export async function POST(request: Request) {
return apiError(parsed.error.issues[0]?.message ?? "Validation error", 400);
}
const modelList = await listLlmModels();
const modelList = await listLlmModels({ route: assistant.modelRoute });
const modelResolution = resolveAssistantModel({
requestedModel: parsed.data.model,
savedModel: assistant.model,
+10 -3
View File
@@ -1,7 +1,7 @@
import { apiError, apiJson } from "@/lib/api-handler";
import { resolveApiAuth } from "@/lib/api-auth";
import { getAssistantPreferences } from "@/lib/assistant-preference";
import { listLlmModels, resolveAssistantModel } from "@/lib/llm/models";
import { isValidAssistantModelRoute, listLlmModels, resolveAssistantModel } from "@/lib/llm/models";
export const dynamic = "force-dynamic";
@@ -21,10 +21,16 @@ export async function GET(request: Request) {
return noStore(apiError("Assistant not enabled", 403));
}
const modelList = await listLlmModels();
const requestedRoute = new URL(request.url).searchParams.get("route");
if (requestedRoute !== null && !isValidAssistantModelRoute(requestedRoute)) {
return noStore(apiError("Invalid assistant model route", 400));
}
const modelRoute = requestedRoute ?? assistant.modelRoute;
const modelList = await listLlmModels({ route: modelRoute });
const resolved = resolveAssistantModel({
requestedModel: null,
savedModel: assistant.model,
savedModel: requestedRoute === null ? assistant.model : null,
fallbackModel: modelList.fallbackModel,
models: modelList.models,
});
@@ -34,6 +40,7 @@ export async function GET(request: Request) {
models: modelList.models,
selectedModel: resolved.model,
fallbackModel: modelList.fallbackModel,
route: modelList.route,
degraded: modelList.degraded,
}),
);
+4
View File
@@ -104,6 +104,7 @@ export default async function RootLayout({ children }: { children: React.ReactNo
let signedIn = false;
let assistantEnabled = false;
let assistantName = DEFAULT_ASSISTANT_NAME;
let assistantModelRoute: string | null = null;
let assistantModel: string | null = null;
const session = await auth();
@@ -118,6 +119,7 @@ export default async function RootLayout({ children }: { children: React.ReactNo
themeNavStyle: users.themeNavStyle,
assistantEnabled: users.assistantEnabled,
assistantName: users.assistantName,
assistantModelRoute: users.assistantModelRoute,
assistantModel: users.assistantModel,
})
.from(users)
@@ -131,6 +133,7 @@ export default async function RootLayout({ children }: { children: React.ReactNo
navStyle = row.themeNavStyle as NavStyle;
assistantEnabled = row.assistantEnabled;
assistantName = row.assistantName?.trim() || DEFAULT_ASSISTANT_NAME;
assistantModelRoute = row.assistantModelRoute?.trim() || null;
assistantModel = row.assistantModel?.trim() || null;
}
userDashboards = await db
@@ -189,6 +192,7 @@ export default async function RootLayout({ children }: { children: React.ReactNo
configured={isLlmConfigured()}
userId={session.user.id}
assistantName={assistantName}
assistantModelRoute={assistantModelRoute}
assistantModel={assistantModel}
/>
) : null}
+22 -2
View File
@@ -9,9 +9,15 @@ import {
MAX_ASSISTANT_NAME_LENGTH,
MAX_ASSISTANT_SYSTEM_PROMPT_LENGTH,
} from "@/lib/assistant-config";
import { isValidLlmModelId, listLlmModels } from "@/lib/llm/models";
import {
isValidAssistantModelRoute,
isValidLlmModelId,
listLlmModels,
type AssistantModelRoute,
} from "@/lib/llm/models";
import { users } from "@/modules/_core/schema";
import { getCurrentSession } from "@/lib/session";
import { getAssistantPreferences } from "@/lib/assistant-preference";
const assistantNameSchema = z
.string()
@@ -51,6 +57,19 @@ export async function setAssistantSystemPrompt(prompt: string | null): Promise<v
revalidateAssistantSurfaces();
}
export async function setAssistantModelRoute(route: AssistantModelRoute): Promise<void> {
if (!isValidAssistantModelRoute(route)) {
throw new Error("Invalid assistant model route");
}
const { user } = await getCurrentSession();
await db
.update(users)
.set({ assistantModelRoute: route, assistantModel: null })
.where(eq(users.id, user.id));
revalidateAssistantSurfaces();
}
export async function setAssistantModel(model: string | null): Promise<void> {
const { user } = await getCurrentSession();
const normalized = model?.trim() || null;
@@ -59,7 +78,8 @@ export async function setAssistantModel(model: string | null): Promise<void> {
throw new Error("Invalid assistant model");
}
const available = await listLlmModels();
const assistant = await getAssistantPreferences(user.id);
const available = await listLlmModels({ route: assistant.modelRoute });
const requested = normalized === available.fallbackModel ? null : normalized;
if (requested !== null && !available.models.some((option) => option.id === requested)) {