Files
agent/backend/internal/logic/inbox/service.go

102 lines
2.9 KiB
Go

package inbox
import (
"errors"
"gorm.io/gorm"
"senlinai-agent/backend/internal/models"
)
type CaptureInput struct {
ProjectID uint
UserID uint
SourceType string
Title string
Body string
}
type Suggestion struct {
Kind string `json:"kind"`
Title string `json:"title"`
Body string `json:"body"`
}
type Analyzer interface {
Analyze(item models.SenlinAgentInboxItem, userID uint) ([]Suggestion, error)
}
type StaticAnalyzer struct {
Suggestions []Suggestion
}
func (a StaticAnalyzer) Analyze(item models.SenlinAgentInboxItem, userID uint) ([]Suggestion, error) {
return a.Suggestions, nil
}
type Service struct {
analyzer Analyzer
}
func NewService(analyzer Analyzer) *Service {
return &Service{analyzer: analyzer}
}
func (s *Service) Capture(input CaptureInput) (*models.SenlinAgentInboxItem, error) {
if input.ProjectID == 0 || input.UserID == 0 {
return nil, errors.New("project and user are required")
}
if input.SourceType == "" {
return nil, errors.New("source type is required")
}
item := &models.SenlinAgentInboxItem{
ProjectID: input.ProjectID,
CreatedBy: input.UserID,
SourceType: input.SourceType,
Title: input.Title,
Body: input.Body,
Status: "open",
}
return item, models.DBService.Create(item).Error
}
func (s *Service) Analyze(itemID uint, userID uint) ([]Suggestion, error) {
var item models.SenlinAgentInboxItem
if err := models.DBService.First(&item, itemID).Error; err != nil {
return nil, err
}
if s.analyzer == nil {
return []Suggestion{}, nil
}
return s.analyzer.Analyze(item, userID)
}
func (s *Service) Confirm(itemID uint, selected []Suggestion) error {
return models.DBService.Transaction(func(tx *gorm.DB) error {
var item models.SenlinAgentInboxItem
if err := tx.First(&item, itemID).Error; err != nil {
return err
}
sourceInboxItemID := item.ID
// Inbox 建议只有在用户确认后才创建正式对象,并把来源 ID 写入每个对象以保留可追溯性。
for _, suggestion := range selected {
switch suggestion.Kind {
case "task":
if err := tx.Create(&models.SenlinAgentTask{ProjectID: item.ProjectID, CreatedBy: item.CreatedBy, SourceInboxItemID: &sourceInboxItemID, Title: suggestion.Title, Description: suggestion.Body}).Error; err != nil {
return err
}
case "note":
if err := tx.Create(&models.SenlinAgentNote{ProjectID: item.ProjectID, CreatedBy: item.CreatedBy, SourceInboxItemID: &sourceInboxItemID, Title: suggestion.Title, Markdown: suggestion.Body}).Error; err != nil {
return err
}
case "source":
if err := tx.Create(&models.SenlinAgentSource{ProjectID: item.ProjectID, CreatedBy: item.CreatedBy, SourceInboxItemID: &sourceInboxItemID, Kind: "link", Title: suggestion.Title, ContentText: suggestion.Body}).Error; err != nil {
return err
}
default:
return errors.New("unsupported suggestion kind")
}
}
return tx.Model(&item).Update("status", "processed").Error
})
}