98 lines
2.8 KiB
Go
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)}
|
|
}
|