package main import ( "sort" "git.cin.su/m/Assistant/contracts/capability" interactiondomain "git.cin.su/m/Assistant/modules/interaction/domain" ) type chatRouteKind string const ( chatRouteResearch chatRouteKind = "RESEARCH" chatRouteConversation chatRouteKind = "CONVERSATION" chatRouteMedia chatRouteKind = "MEDIA" chatRouteAction chatRouteKind = "ACTION" chatRouteAgent chatRouteKind = "AGENT" ) type chatRoute struct { Kind chatRouteKind Capability capability.CapabilityKind Profile string Order int } // buildChatRoutePlan creates one bounded route per meaning-bearing capability. // A failed research route must not suppress the local conversational route or // an unrelated action route. func buildChatRoutePlan(result interactiondomain.SemanticResult) []chatRoute { seen := make(map[capability.CapabilityKind]struct{}) routes := make([]chatRoute, 0, len(result.CapabilityHints)+1) add := func(kind chatRouteKind, capabilityKind capability.CapabilityKind, profile string, order int) { if capabilityKind != "" { if _, exists := seen[capabilityKind]; exists { return } seen[capabilityKind] = struct{}{} } routes = append(routes, chatRoute{Kind: kind, Capability: capabilityKind, Profile: profile, Order: order}) } for _, hint := range result.CapabilityHints { switch capability.CapabilityKind(hint) { case capability.CapabilityKindWebResearch: add(chatRouteResearch, capability.CapabilityKindWebResearch, "truth-research-v1", 10) case capability.CapabilityKindImageGeneration: add(chatRouteMedia, capability.CapabilityKindImageGeneration, "local-image-generation-v1", 5) case capability.CapabilityKindCognitiveReasoning, capability.CapabilityKindVerifyFact: add(chatRouteConversation, capability.CapabilityKind(hint), "local-reasoning-v1", 20) case capability.CapabilityKindScheduleReminder: add(chatRouteAction, capability.CapabilityKindScheduleReminder, "continuity-reminder-v1", 30) case capability.CapabilityKindModifyCode, capability.CapabilityKindRunTests, capability.CapabilityKindInspectProject: add(chatRouteAgent, capability.CapabilityKind(hint), "software-agent-v1", 40) case capability.CapabilityKindSendEmail, capability.CapabilityKindReadEmail: add(chatRouteAgent, capability.CapabilityKind(hint), "communication-agent-v1", 50) case capability.CapabilityKindReadDatabase, capability.CapabilityKindQueryLogs: add(chatRouteAgent, capability.CapabilityKind(hint), "diagnostics-agent-v1", 60) } } if result.NeedsCognition || len(routes) == 0 { add(chatRouteConversation, capability.CapabilityKindCognitiveReasoning, "local-reasoning-v1", 20) } sort.SliceStable(routes, func(i, j int) bool { return routes[i].Order < routes[j].Order }) return routes } func hasChatRoute(routes []chatRoute, kind chatRouteKind) bool { for _, route := range routes { if route.Kind == kind { return true } } return false } // specializedRouteBypassesGeneralInterpretation keeps a concrete capability // route stable. General cognition may still be used later to assess evidence, // but it must not replace an executable research or media route with a vague // conversational clarification before the capability is attempted. func specializedRouteBypassesGeneralInterpretation(routes []chatRoute) bool { return hasChatRoute(routes, chatRouteMedia) || hasChatRoute(routes, chatRouteResearch) }