import { config } from "$lib/server/config"; import { heuristicSelectRoute, MULTIMODAL_ROUTE, AGENTIC_ROUTE, } from "$lib/server/router/heuristics"; import { getRoutes, resolveRouteModels } from "$lib/server/router/policy"; import { hasActiveToolsSelection, isRouterToolsBypassEnabled, pickToolsCapableModel, } from "$lib/server/router/toolsRoute"; import { findConfiguredMultimodalModel } from "$lib/server/router/multimodal"; import type { ProcessedModel } from "../../models"; import { logger } from "../../logger"; export interface RouterResolutionInput { model: ProcessedModel; hasImageInput: boolean; locals: App.Locals | undefined; } export interface RouterResolutionResult { runMcp: boolean; targetModel: ProcessedModel; candidateModelId?: string; resolvedRoute?: string; } export async function resolveRouterTarget({ model, hasImageInput, locals, }: RouterResolutionInput): Promise { let targetModel = model; let candidateModelId: string | undefined; let resolvedRoute: string | undefined; let runMcp = true; if (!model.isRouter) { return { runMcp, targetModel }; } try { const mod = await import("../../models"); const allModels = mod.models as ProcessedModel[]; // Multimodal bypass if (hasImageInput) { const multimodalCandidate = findConfiguredMultimodalModel(allModels); if (!multimodalCandidate) { runMcp = false; logger.warn( { configuredModel: config.LLM_ROUTER_MULTIMODAL_MODEL }, "[mcp] multimodal input but configured model missing or invalid; skipping MCP route" ); } else { targetModel = multimodalCandidate; candidateModelId = multimodalCandidate.id ?? multimodalCandidate.name; resolvedRoute = MULTIMODAL_ROUTE; } return { runMcp, targetModel, candidateModelId, resolvedRoute }; } // Tools bypass const toolsEnabled = isRouterToolsBypassEnabled(); const hasToolsActive = hasActiveToolsSelection(locals); if (toolsEnabled && hasToolsActive) { const found = pickToolsCapableModel(allModels); if (found) { targetModel = found; candidateModelId = found.id ?? found.name; resolvedRoute = AGENTIC_ROUTE; return { runMcp, targetModel, candidateModelId, resolvedRoute }; } // No tools-capable model found; fall back to default routing below } // Heuristic-based route selection (no external API call). Tools-active is masked by // the bypass flag so disabling tools keeps the agentic route off the heuristic path // too (image input has already returned above and is implicitly false here). const routes = await getRoutes(); const { routeName } = await heuristicSelectRoute({ hasImageInput, hasToolsActive: toolsEnabled && hasToolsActive, }); resolvedRoute = routeName; const fallbackModel = config.LLM_ROUTER_FALLBACK_MODEL || model.id; const { candidates } = resolveRouteModels(routeName, routes, fallbackModel); const primaryCandidateId = candidates[0]; if (!primaryCandidateId || primaryCandidateId === fallbackModel) { runMcp = false; } else { const found = allModels?.find( (candidate) => candidate.id === primaryCandidateId || candidate.name === primaryCandidateId ); if (found) { targetModel = found; candidateModelId = primaryCandidateId; } else { runMcp = false; } } } catch (error) { logger.warn({ err: String(error) }, "[mcp] routing preflight failed"); runMcp = false; } return { runMcp, targetModel, candidateModelId, resolvedRoute }; }