83 lines
3.3 KiB
Go
83 lines
3.3 KiB
Go
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)
|
|
}
|