feat: add feature to speak with the AI and create report from contexts

This commit is contained in:
2026-04-19 18:27:42 +02:00
parent eb1fb5ca78
commit 7ef93276e1
19 changed files with 656 additions and 33 deletions

View File

@ -10,12 +10,13 @@ import (
)
type Handler struct {
repo *models.Repository
cfg *config.Config
enc *crypto.Encryptor
registry *scraper.Registry
pipeline *ai.Pipeline
scheduler *scheduler.Scheduler
repo *models.Repository
cfg *config.Config
enc *crypto.Encryptor
registry *scraper.Registry
pipeline *ai.Pipeline
scheduler *scheduler.Scheduler
reportManager *ai.ReportManager
}
func New(
@ -27,11 +28,12 @@ func New(
sched *scheduler.Scheduler,
) *Handler {
return &Handler{
repo: repo,
cfg: cfg,
enc: enc,
registry: registry,
pipeline: pipeline,
scheduler: sched,
repo: repo,
cfg: cfg,
enc: enc,
registry: registry,
pipeline: pipeline,
scheduler: sched,
reportManager: ai.NewReportManager(),
}
}

View File

@ -0,0 +1,84 @@
package handlers
import (
"net/http"
"strings"
"github.com/gin-gonic/gin"
"github.com/tradarr/backend/internal/httputil"
)
type reportRequest struct {
SummaryID string `json:"summary_id"`
Excerpts []string `json:"excerpts" binding:"required,min=1"`
Question string `json:"question" binding:"required"`
}
func (h *Handler) CreateReport(c *gin.Context) {
userID := c.GetString("userID")
var req reportRequest
if err := c.ShouldBindJSON(&req); err != nil {
httputil.BadRequest(c, err)
return
}
var summaryID *string
if req.SummaryID != "" {
summaryID = &req.SummaryID
}
// Joindre les extraits avec un séparateur visuel
excerpt := buildExcerptContext(req.Excerpts)
// Créer le rapport en DB avec status=generating, retourner immédiatement
report, err := h.repo.CreatePendingReport(userID, summaryID, excerpt, req.Question)
if err != nil {
httputil.InternalError(c, err)
return
}
// Lancer la génération en arrière-plan
h.pipeline.GenerateReportAsync(report.ID, excerpt, req.Question, h.reportManager)
c.JSON(http.StatusCreated, report)
}
func (h *Handler) ListReports(c *gin.Context) {
userID := c.GetString("userID")
reports, err := h.repo.ListReports(userID)
if err != nil {
httputil.InternalError(c, err)
return
}
httputil.OK(c, reports)
}
func (h *Handler) DeleteReport(c *gin.Context) {
userID := c.GetString("userID")
id := c.Param("id")
// Annuler la goroutine si elle tourne encore
h.reportManager.Cancel(id)
if err := h.repo.DeleteReport(id, userID); err != nil {
httputil.InternalError(c, err)
return
}
c.Status(http.StatusNoContent)
}
func (h *Handler) GetGeneratingStatus(c *gin.Context) {
httputil.OK(c, gin.H{"generating": h.pipeline.IsGenerating()})
}
func buildExcerptContext(excerpts []string) string {
if len(excerpts) == 1 {
return excerpts[0]
}
var sb strings.Builder
for i, e := range excerpts {
if i > 0 {
sb.WriteString("\n\n---\n\n")
}
sb.WriteString(e)
}
return sb.String()
}