tâches planifiées : prompts cron persistés, outil scheduler, conversations liées aux tâches, rattrapage des exécutions manquées au redémarrage (go-cron MissedRunOnce)

This commit is contained in:
fabien committed 2026-10-06 22:15:59 +02:00
1 parent bedb6c98e7
commit 058370830f
71 files changed
+1627 -100

No files matched your search

+49 -22
View File
@@ -3,6 +3,7 @@ package chat
import (
"context"
_ "embed"
"fmt"
"log/slog"
"sync"
@@ -87,43 +88,69 @@ func (s *ChatSession) run(ctx context.Context) error {
for _, tc := range msg.ToolCalls {
toolImpl := s.toolService.GetToolImpl(tc.Function.Name)
slog.Info("Execute tool", "name", tc.Function.Name, "impl", toolImpl)
toolRecord, err := s.toolService.GetToolByName(s.userID, s.teamID, toolImpl.Name())
if err != nil {
slog.Info("Execute tool", "error", err)
toolResponse := &domain.Message{
ChatID: s.chatID,
TeamID: s.teamID,
ToolCallID: tc.ID,
Role: string(domain.RoleTool),
Content: "ERROR: " + err.Error(),
var toolRecord *domain.Tool
var executeErr error
if toolImpl == nil {
executeErr = fmt.Errorf("unknown tool %s", tc.Function.Name)
slog.Info("Execute tool", "error", executeErr)
} else {
slog.Info("Execute tool", "name", tc.Function.Name, "impl", toolImpl)
var err error
toolRecord, err = s.toolService.GetToolByName(s.userID, s.teamID, toolImpl.Name())
if err != nil {
// l'outil n'est pas encore enregistré pour l'équipe :
// auto-enregistrement (comme le fait la liste des outils)
toolRecord, err = s.toolService.CreateTool(s.userID, &domain.Tool{
TeamID: s.teamID,
Name: toolImpl.Name(),
Enabled: true,
})
}
if err != nil {
executeErr = err
slog.Info("Execute tool", "error", err)
}
s.repoChat.CreateChatMessage(s.userID, toolResponse)
}
output, err := toolImpl.Execute(ctx, []byte(tc.Function.Arguments), toolRecord.Configuration)
var toolResponse *domain.Message
if err != nil {
if executeErr != nil {
toolResponse = &domain.Message{
ChatID: s.chatID,
TeamID: s.teamID,
ToolCallID: tc.ID,
Role: string(domain.RoleTool),
Content: "ERROR: " + err.Error(),
Content: "ERROR: " + executeErr.Error(),
}
} else {
toolResponse = &domain.Message{
ChatID: s.chatID,
TeamID: s.teamID,
ToolCallID: tc.ID,
Role: string(domain.RoleTool),
Content: string(output),
var output []byte
output, executeErr = toolImpl.Execute(
domain.WithToolContext(ctx, s.userID, s.teamID, s.modelID),
[]byte(tc.Function.Arguments),
toolRecord.Configuration,
)
if executeErr != nil {
toolResponse = &domain.Message{
ChatID: s.chatID,
TeamID: s.teamID,
ToolCallID: tc.ID,
Role: string(domain.RoleTool),
Content: "ERROR: " + executeErr.Error(),
}
} else {
toolResponse = &domain.Message{
ChatID: s.chatID,
TeamID: s.teamID,
ToolCallID: tc.ID,
Role: string(domain.RoleTool),
Content: string(output),
}
}
}
toolResponse, err = s.repoChat.CreateChatMessage(s.userID, toolResponse)
persisted, err := s.repoChat.CreateChatMessage(s.userID, toolResponse)
if err != nil {
return err
}
s.messages = append(s.messages, toolResponse)
s.messages = append(s.messages, persisted)
}
} else {