File size: 3,537 Bytes
e67ab0e
 
 
 
 
 
 
 
 
bec283e
e67ab0e
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
bec283e
 
 
 
 
 
 
 
e67ab0e
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
import { config } from "$lib/server/config";
import { archSelectRoute } from "$lib/server/router/arch";
import { getRoutes, resolveRouteModels } from "$lib/server/router/policy";
import {
	hasActiveToolsSelection,
	isRouterToolsBypassEnabled,
	pickToolsCapableModel,
	ROUTER_TOOLS_ROUTE,
} from "$lib/server/router/toolsRoute";
import { findConfiguredMultimodalModel } from "$lib/server/router/multimodal";
import type { EndpointMessage } from "../../endpoints/endpoints";
import { stripReasoningFromMessageForRouting } from "../utils/routing";
import type { ProcessedModel } from "../../models";
import { logger } from "../../logger";

export interface RouterResolutionInput {
	model: ProcessedModel;
	messages: EndpointMessage[];
	conversationId: string;
	hasImageInput: boolean;
	locals: App.Locals | undefined;
}

export interface RouterResolutionResult {
	runMcp: boolean;
	targetModel: ProcessedModel;
	candidateModelId?: string;
	resolvedRoute?: string;
}

export async function resolveRouterTarget({
	model,
	messages,
	conversationId,
	hasImageInput,
	locals,
}: RouterResolutionInput): Promise<RouterResolutionResult> {
	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[];

		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";
			}
		} else {
			// If tools are enabled and at least one MCP server is active, prefer a tools-capable model
			const toolsEnabled = isRouterToolsBypassEnabled();
			const hasToolsActive = hasActiveToolsSelection(locals);

			if (toolsEnabled && hasToolsActive) {
				const found = pickToolsCapableModel(allModels);
				if (found) {
					targetModel = found;
					candidateModelId = found.id ?? found.name;
					resolvedRoute = ROUTER_TOOLS_ROUTE;
					// Continue; runMcp remains true
					return { runMcp, targetModel, candidateModelId, resolvedRoute };
				}
				// No tools-capable model found; fall back to normal Arch routing below
			}
			const routes = await getRoutes();
			const sanitized = messages.map(stripReasoningFromMessageForRouting);
			const { routeName } = await archSelectRoute(sanitized, conversationId, locals);
			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 };
}