using System; using System.Collections.Generic; using System.Linq; using AxCopilot.Models; namespace AxCopilot.Services; public class ModelRouterService { private readonly SettingsService _settings; public ModelRouterService(SettingsService settings) { _settings = settings; } public ModelRouteResult? Route(string userMessage) { LlmSettings llm = _settings.Settings.Llm; if (!llm.EnableAutoRouter) { return null; } var (category, num) = IntentDetector.Detect(userMessage); if (num < llm.AutoRouterConfidence) { return null; } if (category == "general") { return null; } List list = GatherCandidates(llm); if (list.Count == 0) { return null; } string currentService = llm.Service.ToLowerInvariant(); string currentModel = ResolveCurrentModel(llm); ModelCapability modelCapability = (from c in list where c.Scores.ContainsKey(category) orderby c.Scores[category] descending select c).FirstOrDefault(); if (modelCapability == null) { return null; } ModelCapability modelCapability2 = list.FirstOrDefault((ModelCapability c) => c.Service.Equals(currentService, StringComparison.OrdinalIgnoreCase) && c.Model.Equals(currentModel, StringComparison.OrdinalIgnoreCase)); if (modelCapability2 != null && modelCapability2.Scores.TryGetValue(category, out var value) && modelCapability.Scores[category] - value < 0.1) { return null; } return new ModelRouteResult(modelCapability.Service, modelCapability.Model, modelCapability.Alias, category, num); } private List GatherCandidates(LlmSettings llm) { List list = new List(); foreach (ModelCapability modelCapability in llm.ModelCapabilities) { if (modelCapability.Enabled && IsServiceAvailable(llm, modelCapability.Service)) { list.Add(modelCapability); } } List defaultCapabilities = GetDefaultCapabilities(); foreach (ModelCapability def in defaultCapabilities) { if (IsServiceAvailable(llm, def.Service) && !list.Any((ModelCapability c) => c.Service.Equals(def.Service, StringComparison.OrdinalIgnoreCase) && c.Model.Equals(def.Model, StringComparison.OrdinalIgnoreCase))) { list.Add(def); } } return list; } private static bool IsServiceAvailable(LlmSettings llm, string service) { string text = service.ToLowerInvariant(); if (1 == 0) { } bool result = text switch { "gemini" => !string.IsNullOrEmpty(llm.GeminiApiKey), "claude" => !string.IsNullOrEmpty(llm.ClaudeApiKey), "ollama" => !string.IsNullOrEmpty(llm.OllamaEndpoint), "vllm" => !string.IsNullOrEmpty(llm.VllmEndpoint), _ => false, }; if (1 == 0) { } return result; } private static string ResolveCurrentModel(LlmSettings llm) { string service = llm.Service; bool flag = ((service == "ollama" || service == "vllm") ? true : false); if (flag && !string.IsNullOrEmpty(llm.Model)) { return CryptoService.DecryptIfEnabled(llm.Model, llm.EncryptionEnabled); } string text = llm.Service.ToLowerInvariant(); if (1 == 0) { } service = ((text == "gemini") ? llm.GeminiModel : ((!(text == "claude")) ? llm.Model : llm.ClaudeModel)); if (1 == 0) { } return service; } public static List GetDefaultCapabilities() { return new List { new ModelCapability { Service = "gemini", Model = "gemini-2.5-flash", Alias = "Gemini 2.5 Flash", Scores = new Dictionary { ["coding"] = 0.7, ["translation"] = 0.7, ["analysis"] = 0.85, ["creative"] = 0.65, ["document"] = 0.7, ["math"] = 0.9 } }, new ModelCapability { Service = "gemini", Model = "gemini-2.5-pro", Alias = "Gemini 2.5 Pro", Scores = new Dictionary { ["coding"] = 0.85, ["translation"] = 0.8, ["analysis"] = 0.9, ["creative"] = 0.75, ["document"] = 0.8, ["math"] = 0.95 } }, new ModelCapability { Service = "claude", Model = "claude-sonnet-4-6", Alias = "Claude Sonnet 4.6", Scores = new Dictionary { ["coding"] = 0.9, ["translation"] = 0.85, ["analysis"] = 0.9, ["creative"] = 0.9, ["document"] = 0.85, ["math"] = 0.8 } }, new ModelCapability { Service = "claude", Model = "claude-opus-4-6", Alias = "Claude Opus 4.6", Scores = new Dictionary { ["coding"] = 0.95, ["translation"] = 0.9, ["analysis"] = 0.95, ["creative"] = 0.95, ["document"] = 0.9, ["math"] = 0.85 } }, new ModelCapability { Service = "claude", Model = "claude-haiku-4-5", Alias = "Claude Haiku 4.5", Scores = new Dictionary { ["coding"] = 0.65, ["translation"] = 0.7, ["analysis"] = 0.65, ["creative"] = 0.6, ["document"] = 0.6, ["math"] = 0.6 } } }; } }