110 lines
3.7 KiB
Go
110 lines
3.7 KiB
Go
package backendapp
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"fmt"
|
|
|
|
"github.com/kandev/kandev/internal/github"
|
|
"github.com/kandev/kandev/internal/task/models"
|
|
taskrepo "github.com/kandev/kandev/internal/task/repository/sqlite"
|
|
taskservice "github.com/kandev/kandev/internal/task/service"
|
|
)
|
|
|
|
// turnServiceAdapter adapts the task service to the orchestrator.TurnService interface.
|
|
type turnServiceAdapter struct {
|
|
svc *taskservice.Service
|
|
}
|
|
|
|
func (a *turnServiceAdapter) StartTurn(ctx context.Context, sessionID string) (*models.Turn, error) {
|
|
return a.svc.StartTurn(ctx, sessionID)
|
|
}
|
|
|
|
func (a *turnServiceAdapter) CompleteTurn(ctx context.Context, turnID string) error {
|
|
return a.svc.CompleteTurn(ctx, turnID)
|
|
}
|
|
|
|
func (a *turnServiceAdapter) GetActiveTurn(ctx context.Context, sessionID string) (*models.Turn, error) {
|
|
return a.svc.GetActiveTurn(ctx, sessionID)
|
|
}
|
|
|
|
func (a *turnServiceAdapter) UpdateTurn(ctx context.Context, turn *models.Turn) error {
|
|
return a.svc.UpdateTurn(ctx, turn)
|
|
}
|
|
|
|
func (a *turnServiceAdapter) AbandonOpenTurns(ctx context.Context, sessionID string) error {
|
|
return a.svc.AbandonOpenTurns(ctx, sessionID)
|
|
}
|
|
|
|
func newTurnServiceAdapter(svc *taskservice.Service) *turnServiceAdapter {
|
|
return &turnServiceAdapter{svc: svc}
|
|
}
|
|
|
|
// taskSessionCheckerAdapter adapts the task repository for github.TaskSessionChecker.
|
|
type taskSessionCheckerAdapter struct {
|
|
repo interface {
|
|
ListTaskSessions(ctx context.Context, taskID string) ([]*models.TaskSession, error)
|
|
ListMessages(ctx context.Context, sessionID string) ([]*models.Message, error)
|
|
}
|
|
}
|
|
|
|
// HasUserAuthoredMessage reports whether the user has authored any message
|
|
// on this task that wasn't created by an automated trigger (workflow
|
|
// auto-start, PR/issue watch, Jira/Linear integration). Auto-start messages
|
|
// are tagged with metadata.auto_start = true; the check ignores them so a
|
|
// task whose only "user" message is the agent's auto-injected prompt counts
|
|
// as untouched and is eligible for cleanup when its PR/issue merges.
|
|
func (a *taskSessionCheckerAdapter) HasUserAuthoredMessage(ctx context.Context, taskID string) (bool, error) {
|
|
sessions, err := a.repo.ListTaskSessions(ctx, taskID)
|
|
if err != nil {
|
|
return false, err
|
|
}
|
|
for _, sess := range sessions {
|
|
messages, err := a.repo.ListMessages(ctx, sess.ID)
|
|
if err != nil {
|
|
return false, err
|
|
}
|
|
for _, m := range messages {
|
|
if m.AuthorType != models.MessageAuthorUser {
|
|
continue
|
|
}
|
|
// New code paths tag both auto_start and workflow_auto_start.
|
|
// Legacy rows (pre-cleanup-policy upgrade) carry only the
|
|
// workflow_auto_start tag from the old recordAutoStartMessage
|
|
// implementation — recognize it too so the install-wide
|
|
// cleanup button actually drains piled-up tasks after upgrade.
|
|
if metaFlag(m.Metadata, "auto_start") || metaFlag(m.Metadata, "workflow_auto_start") {
|
|
continue
|
|
}
|
|
return true, nil
|
|
}
|
|
}
|
|
return false, nil
|
|
}
|
|
|
|
// metaFlag returns true when meta[key] is a bool with value true. Returns
|
|
// false for missing keys, nil maps, non-bool values, and false values.
|
|
func metaFlag(meta map[string]interface{}, key string) bool {
|
|
v, ok := meta[key].(bool)
|
|
return ok && v
|
|
}
|
|
|
|
// taskDeleterAdapter satisfies github.TaskDeleter and translates the task
|
|
// repository's ErrTaskNotFound sentinel to github.ErrTaskNotFound so the
|
|
// github cleanup paths can classify the "already gone" case via errors.Is
|
|
// without importing the task repository's package.
|
|
type taskDeleterAdapter struct {
|
|
svc *taskservice.Service
|
|
}
|
|
|
|
func (a *taskDeleterAdapter) DeleteTask(ctx context.Context, taskID string) error {
|
|
err := a.svc.DeleteTask(ctx, taskID)
|
|
if err == nil {
|
|
return nil
|
|
}
|
|
if errors.Is(err, taskrepo.ErrTaskNotFound) {
|
|
return fmt.Errorf("%w: %w", github.ErrTaskNotFound, err)
|
|
}
|
|
return err
|
|
}
|