Files
ai-operator/internal/handoff/fallback.go
T

98 lines
2.8 KiB
Go

package handoff
import "time"
type FallbackCounters struct {
LanguageFailures int
RegionFailures int
NoAnswerCount int
KBUnavailable int
AIProviderErrors int
MediaErrors int
ToolErrors int
StartedAt time.Time
}
type FallbackConfig struct {
MaxLanguageFailures int
MaxRegionFailures int
MaxNoAnswer int
MaxKBUnavailable int
MaxAIErrors int
MaxMediaErrors int
MaxToolErrors int
CallTimeout time.Duration
}
type FallbackDecision struct {
ShouldOfferHandoff bool
ShouldClose bool
ReasonCode HandoffReasonCode
MessageKey string
Message string
}
type FallbackManager struct {
Config FallbackConfig
}
func NewFallbackManager(cfg FallbackConfig) *FallbackManager {
if cfg.MaxLanguageFailures == 0 {
cfg.MaxLanguageFailures = 3
}
if cfg.MaxRegionFailures == 0 {
cfg.MaxRegionFailures = 3
}
if cfg.MaxNoAnswer == 0 {
cfg.MaxNoAnswer = 2
}
if cfg.MaxKBUnavailable == 0 {
cfg.MaxKBUnavailable = 1
}
if cfg.MaxAIErrors == 0 {
cfg.MaxAIErrors = 1
}
if cfg.MaxMediaErrors == 0 {
cfg.MaxMediaErrors = 1
}
if cfg.MaxToolErrors == 0 {
cfg.MaxToolErrors = 2
}
if cfg.CallTimeout == 0 {
cfg.CallTimeout = 5 * time.Minute
}
return &FallbackManager{Config: cfg}
}
func (m *FallbackManager) Evaluate(c FallbackCounters, language string, now time.Time) FallbackDecision {
if !c.StartedAt.IsZero() && now.Sub(c.StartedAt) >= m.Config.CallTimeout {
return m.decision(true, HandoffReasonTimeout, "fallback.timeout", language)
}
if c.KBUnavailable >= m.Config.MaxKBUnavailable {
return m.decision(false, HandoffReasonKBUnavailable, "fallback.kb_unavailable", language)
}
if c.NoAnswerCount >= m.Config.MaxNoAnswer {
return m.decision(false, HandoffReasonRepeatedNoAnswer, "fallback.no_answer", language)
}
if c.LanguageFailures >= m.Config.MaxLanguageFailures {
return m.decision(false, HandoffReasonLanguageFailures, "fallback.language_failures", language)
}
if c.RegionFailures >= m.Config.MaxRegionFailures {
return m.decision(false, HandoffReasonRegionFailures, "fallback.region_failures", language)
}
if c.AIProviderErrors >= m.Config.MaxAIErrors {
return m.decision(false, HandoffReasonAIProviderError, "fallback.ai_error", language)
}
if c.MediaErrors >= m.Config.MaxMediaErrors {
return m.decision(false, HandoffReasonMediaError, "fallback.media_error", language)
}
if c.ToolErrors >= m.Config.MaxToolErrors {
return m.decision(false, HandoffReasonToolError, "fallback.tool_error", language)
}
return FallbackDecision{}
}
func (m *FallbackManager) decision(close bool, reason HandoffReasonCode, key string, language string) FallbackDecision {
return FallbackDecision{ShouldOfferHandoff: !close, ShouldClose: close, ReasonCode: reason, MessageKey: key, Message: Message(key, language)}
}