package model import ( "encoding/json" ) // --- Auto-Reply Rule Model --- // Reference: M12 PRD §Captain AI — Auto-Reply Rules // Table: captain_auto_reply_rules // // AutoReplyRule defines conditions and responses for automated replies. // When a conversation matches the rule conditions, Captain can auto-send // a predefined response or use LLM to generate a contextual reply. type AutoReplyRuleStatus string const ( AutoReplyRuleStatusActive AutoReplyRuleStatus = "active" AutoReplyRuleStatusDraft AutoReplyRuleStatus = "draft" AutoReplyRuleStatusPaused AutoReplyRuleStatus = "paused" ) type AutoReplyRuleMode string const ( AutoReplyRuleModeStatic AutoReplyRuleMode = "static" // predefined response text AutoReplyRuleModeLLM AutoReplyRuleMode = "llm" // LLM-generated contextual response AutoReplyRuleModeMixed AutoReplyRuleMode = "mixed" // static intro + LLM contextual body ) type CaptainAutoReplyRule struct { Base AccountID uint `gorm:"index;not null" json:"account_id"` AssistantID uint `gorm:"index;not null" json:"assistant_id"` InboxID *uint `gorm:"index" json:"inbox_id,omitempty"` // optional: scope to specific inbox Name string `gorm:"size:255;not null" json:"name"` Description string `gorm:"type:text" json:"description,omitempty"` Status AutoReplyRuleStatus `gorm:"size:50;default:draft;not null" json:"status"` Mode AutoReplyRuleMode `gorm:"size:50;default:static;not null" json:"mode"` Priority int `gorm:"default:0;not null" json:"priority"` // higher = evaluated first // Conditions: JSONB array of condition objects that must all match // Each condition: {"field": "message_content", "operator": "contains", "value": "urgent"} // Fields: message_content, sender_type, conversation_status, language, keywords Conditions json.RawMessage `gorm:"type:jsonb;serializer:json" json:"conditions"` // Response config for static/mixed mode ResponseText string `gorm:"type:text" json:"response_text,omitempty"` // static reply text // LLM prompt override for llm/mixed mode LLMPromptOverride string `gorm:"type:text" json:"llm_prompt_override,omitempty"` // Delay before auto-reply (seconds, 0 = immediate) DelaySeconds int `gorm:"default:0;not null" json:"delay_seconds"` // Only auto-reply once per conversation OneTimeOnly bool `gorm:"default:true;not null" json:"one_time_only"` } func (CaptainAutoReplyRule) TableName() string { return "captain_auto_reply_rules" } // AutoReplyCondition represents a single matching condition. type AutoReplyCondition struct { Field string `json:"field"` // "message_content", "sender_type", "language", "keywords" Operator string `json:"operator"` // "contains", "equals", "regex", "starts_with", "language_is" Value string `json:"value"` // the value to match against } // GetConditions unmarshals the conditions JSON. func (r *CaptainAutoReplyRule) GetConditions() ([]AutoReplyCondition, error) { if len(r.Conditions) == 0 || string(r.Conditions) == "null" || string(r.Conditions) == "[]" { return nil, nil } var conditions []AutoReplyCondition if err := json.Unmarshal(r.Conditions, &conditions); err != nil { return nil, err } return conditions, nil }