80 lines
2.7 KiB
Go
80 lines
2.7 KiB
Go
package policy
|
|
|
|
import (
|
|
"ai-operator/internal/dialogue/state"
|
|
"ai-operator/internal/tools"
|
|
)
|
|
|
|
type Decision struct {
|
|
Allowed bool
|
|
ToolName string
|
|
State state.ConversationState
|
|
ReasonCode string
|
|
UserMessageKey string
|
|
RequiredNextAction string
|
|
}
|
|
|
|
func AuthorizeTool(session state.ConversationSession, toolName string) Decision {
|
|
d := Decision{ToolName: toolName, State: session.State, ReasonCode: "ok"}
|
|
if !tools.Known(toolName) {
|
|
return deny(d, "unknown_tool", "denied.not_ready", "none")
|
|
}
|
|
if session.State == state.StateEnded {
|
|
return deny(d, "call_ended", "closing.started", "none")
|
|
}
|
|
if toolName == tools.SearchKnowledgeBase {
|
|
return authorizeSearch(session, d)
|
|
}
|
|
allowed := allowedByState(session.State, toolName)
|
|
if !allowed {
|
|
return deny(d, "tool_not_allowed_in_state", "denied.not_ready", nextAction(session))
|
|
}
|
|
d.Allowed = true
|
|
return d
|
|
}
|
|
|
|
func authorizeSearch(session state.ConversationSession, d Decision) Decision {
|
|
if session.State == state.StateEnded || session.State == state.StateClosing || session.State == state.StateHandoff {
|
|
return deny(d, "state_not_ready", "denied.not_ready", nextAction(session))
|
|
}
|
|
d.Allowed = true
|
|
return d
|
|
}
|
|
|
|
func allowedByState(s state.ConversationState, tool string) bool {
|
|
switch s {
|
|
case state.StateLanguageSelection:
|
|
return tool == tools.SearchKnowledgeBase || tool == tools.SetLanguage || tool == tools.SetRegion || tool == tools.RequestHumanHandoff || tool == tools.EndCall
|
|
case state.StateRegionSelection:
|
|
return tool == tools.SearchKnowledgeBase || tool == tools.SetRegion || tool == tools.SetLanguage || tool == tools.RequestHumanHandoff || tool == tools.EndCall
|
|
case state.StateReadyToHelp:
|
|
return tool == tools.SearchKnowledgeBase || tool == tools.SetLanguage || tool == tools.SetRegion || tool == tools.RequestHumanHandoff || tool == tools.EndCall
|
|
case state.StateQuestionAnswering:
|
|
return tool == tools.SearchKnowledgeBase || tool == tools.SetLanguage || tool == tools.SetRegion || tool == tools.RequestHumanHandoff || tool == tools.EndCall
|
|
case state.StateHandoff:
|
|
return tool == tools.RequestHumanHandoff || tool == tools.EndCall
|
|
case state.StateClosing:
|
|
return tool == tools.EndCall
|
|
default:
|
|
return false
|
|
}
|
|
}
|
|
|
|
func deny(d Decision, reason, key, action string) Decision {
|
|
d.Allowed = false
|
|
d.ReasonCode = reason
|
|
d.UserMessageKey = key
|
|
d.RequiredNextAction = action
|
|
return d
|
|
}
|
|
|
|
func nextAction(session state.ConversationSession) string {
|
|
if session.Language != state.LanguageRU && session.Language != state.LanguageKK {
|
|
return "infer_language"
|
|
}
|
|
if session.Region.Status != state.RegionSelected || session.Region.Code == "" {
|
|
return "use_global_or_ask_region_if_needed"
|
|
}
|
|
return "wait_for_question"
|
|
}
|