sync: migrate ai-operator to Gitea (2026-08-10)
This commit is contained in:
@@ -0,0 +1,97 @@
|
||||
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)}
|
||||
}
|
||||
Reference in New Issue
Block a user