Files
kandev/apps/backend/internal/task/repository/interface.go
T

234 lines
15 KiB
Go

package repository
import (
"context"
agentdto "github.com/kandev/kandev/internal/agent/dto"
"github.com/kandev/kandev/internal/task/models"
v1 "github.com/kandev/kandev/pkg/api/v1"
)
// WorkspaceRepository handles workspace CRUD.
type WorkspaceRepository interface {
CreateWorkspace(ctx context.Context, workspace *models.Workspace) error
GetWorkspace(ctx context.Context, id string) (*models.Workspace, error)
UpdateWorkspace(ctx context.Context, workspace *models.Workspace) error
DeleteWorkspace(ctx context.Context, id string) error
ListWorkspaces(ctx context.Context) ([]*models.Workspace, error)
}
// TaskRepository handles task CRUD and workflow placement.
// Note: models.TaskRepository is a struct in internal/task/models; no Go conflict exists.
type TaskRepository interface {
CreateTask(ctx context.Context, task *models.Task) error
GetTask(ctx context.Context, id string) (*models.Task, error)
UpdateTask(ctx context.Context, task *models.Task) error
DeleteTask(ctx context.Context, id string) error
ListTasks(ctx context.Context, workflowID string) ([]*models.Task, error)
ListTasksByWorkspace(ctx context.Context, workspaceID, workflowID, repositoryID, query string, page, pageSize int, includeArchived, includeEphemeral, onlyEphemeral, excludeConfig bool) ([]*models.Task, int, error)
ListTasksByWorkflowStep(ctx context.Context, workflowStepID string) ([]*models.Task, error)
ArchiveTask(ctx context.Context, id string) error
ListTasksForAutoArchive(ctx context.Context) ([]*models.Task, error)
UpdateTaskState(ctx context.Context, id string, state v1.TaskState) error
CountTasksByWorkflow(ctx context.Context, workflowID string) (int, error)
CountTasksByWorkflowStep(ctx context.Context, stepID string) (int, error)
AddTaskToWorkflow(ctx context.Context, taskID, workflowID, workflowStepID string, position int) error
RemoveTaskFromWorkflow(ctx context.Context, taskID, workflowID string) error
}
// TaskRepoRepository handles the task↔repository junction table (models.TaskRepository rows).
// Named TaskRepoRepository to reduce reader confusion with the TaskRepository sub-interface above.
type TaskRepoRepository interface {
CreateTaskRepository(ctx context.Context, taskRepo *models.TaskRepository) error
GetTaskRepository(ctx context.Context, id string) (*models.TaskRepository, error)
ListTaskRepositories(ctx context.Context, taskID string) ([]*models.TaskRepository, error)
ListTaskRepositoriesByTaskIDs(ctx context.Context, taskIDs []string) (map[string][]*models.TaskRepository, error)
UpdateTaskRepository(ctx context.Context, taskRepo *models.TaskRepository) error
DeleteTaskRepository(ctx context.Context, id string) error
DeleteTaskRepositoriesByTask(ctx context.Context, taskID string) error
GetPrimaryTaskRepository(ctx context.Context, taskID string) (*models.TaskRepository, error)
}
// WorkflowRepository handles workflow CRUD.
type WorkflowRepository interface {
CreateWorkflow(ctx context.Context, workflow *models.Workflow) error
GetWorkflow(ctx context.Context, id string) (*models.Workflow, error)
UpdateWorkflow(ctx context.Context, workflow *models.Workflow) error
DeleteWorkflow(ctx context.Context, id string) error
ListWorkflows(ctx context.Context, workspaceID string, includeHidden bool) ([]*models.Workflow, error)
ReorderWorkflows(ctx context.Context, workspaceID string, workflowIDs []string) error
}
// MessageRepository handles message persistence and lookups.
type MessageRepository interface {
CreateMessage(ctx context.Context, message *models.Message) error
GetMessage(ctx context.Context, id string) (*models.Message, error)
GetMessageByToolCallID(ctx context.Context, sessionID, toolCallID string) (*models.Message, error)
GetMessageByPendingID(ctx context.Context, sessionID, pendingID string) (*models.Message, error)
FindMessageByPendingID(ctx context.Context, pendingID string) (*models.Message, error)
UpdateMessage(ctx context.Context, message *models.Message) error
ListMessages(ctx context.Context, sessionID string) ([]*models.Message, error)
ListMessagesPaginated(ctx context.Context, sessionID string, opts models.ListMessagesOptions) ([]*models.Message, bool, error)
SearchMessages(ctx context.Context, sessionID string, opts models.SearchMessagesOptions) ([]*models.Message, error)
DeleteMessage(ctx context.Context, id string) error
}
// TurnRepository handles conversation turn persistence.
type TurnRepository interface {
CreateTurn(ctx context.Context, turn *models.Turn) error
GetTurn(ctx context.Context, id string) (*models.Turn, error)
GetActiveTurnBySessionID(ctx context.Context, sessionID string) (*models.Turn, error)
UpdateTurn(ctx context.Context, turn *models.Turn) error
CompleteTurn(ctx context.Context, id string) error
CompletePendingToolCallsForTurn(ctx context.Context, turnID string) (int64, error)
ListTurnsBySession(ctx context.Context, sessionID string) ([]*models.Turn, error)
}
// SessionRepository handles task session lifecycle and workflow-session relationships.
type SessionRepository interface {
CreateTaskSession(ctx context.Context, session *models.TaskSession) error
GetTaskSession(ctx context.Context, id string) (*models.TaskSession, error)
GetTaskSessionByTaskID(ctx context.Context, taskID string) (*models.TaskSession, error)
GetActiveTaskSessionByTaskID(ctx context.Context, taskID string) (*models.TaskSession, error)
UpdateTaskSession(ctx context.Context, session *models.TaskSession) error
UpdateTaskSessionState(ctx context.Context, id string, state models.TaskSessionState, errorMessage string) error
ListTaskSessions(ctx context.Context, taskID string) ([]*models.TaskSession, error)
ListActiveTaskSessions(ctx context.Context) ([]*models.TaskSession, error)
ListActiveTaskSessionsByTaskID(ctx context.Context, taskID string) ([]*models.TaskSession, error)
HasActiveTaskSessionsByAgentProfile(ctx context.Context, agentProfileID string) (bool, error)
GetActiveTaskInfoByAgentProfile(ctx context.Context, agentProfileID string) ([]agentdto.ActiveTaskInfo, error)
HasActiveTaskSessionsByExecutor(ctx context.Context, executorID string) (bool, error)
HasActiveTaskSessionsByEnvironment(ctx context.Context, environmentID string) (bool, error)
HasActiveTaskSessionsByRepository(ctx context.Context, repositoryID string) (bool, error)
DeleteEphemeralTasksByAgentProfile(ctx context.Context, agentProfileID string) (int64, error)
DeleteTaskSession(ctx context.Context, id string) error
GetPrimarySessionByTaskID(ctx context.Context, taskID string) (*models.TaskSession, error)
GetPrimarySessionIDsByTaskIDs(ctx context.Context, taskIDs []string) (map[string]string, error)
GetSessionCountsByTaskIDs(ctx context.Context, taskIDs []string) (map[string]int, error)
GetPrimarySessionInfoByTaskIDs(ctx context.Context, taskIDs []string) (map[string]*models.TaskSession, error)
SetSessionPrimary(ctx context.Context, sessionID string) error
UpdateSessionReviewStatus(ctx context.Context, sessionID string, status string) error
UpdateSessionMetadata(ctx context.Context, sessionID string, metadata map[string]interface{}) error
SetSessionMetadataKey(ctx context.Context, sessionID, key string, value interface{}) error
}
// SessionWorktreeRepository handles the task session↔worktree association.
type SessionWorktreeRepository interface {
CreateTaskSessionWorktree(ctx context.Context, sessionWorktree *models.TaskSessionWorktree) error
UpdateTaskSessionWorktreeBranch(ctx context.Context, sessionID, branch string) error
ListTaskSessionWorktrees(ctx context.Context, sessionID string) ([]*models.TaskSessionWorktree, error)
ListWorktreesBySessionIDs(ctx context.Context, sessionIDs []string) (map[string][]*models.TaskSessionWorktree, error)
DeleteTaskSessionWorktree(ctx context.Context, id string) error
DeleteTaskSessionWorktreesBySession(ctx context.Context, sessionID string) error
}
// GitSnapshotRepository handles git snapshots and session commit records.
type GitSnapshotRepository interface {
CreateGitSnapshot(ctx context.Context, snapshot *models.GitSnapshot) error
GetLatestGitSnapshot(ctx context.Context, sessionID string) (*models.GitSnapshot, error)
GetFirstGitSnapshot(ctx context.Context, sessionID string) (*models.GitSnapshot, error)
GetGitSnapshotsBySession(ctx context.Context, sessionID string, limit int) ([]*models.GitSnapshot, error)
CreateSessionCommit(ctx context.Context, commit *models.SessionCommit) error
GetSessionCommits(ctx context.Context, sessionID string) ([]*models.SessionCommit, error)
GetLatestSessionCommit(ctx context.Context, sessionID string) (*models.SessionCommit, error)
DeleteSessionCommit(ctx context.Context, id string) error
}
// RepositoryEntityRepository handles git repository entity CRUD and repository scripts.
// Named RepositoryEntityRepository to avoid conflation with the Repository interface itself;
// mirrors the sqlite/repository_entity.go implementation file.
type RepositoryEntityRepository interface {
CreateRepository(ctx context.Context, repository *models.Repository) error
GetRepository(ctx context.Context, id string) (*models.Repository, error)
UpdateRepository(ctx context.Context, repository *models.Repository) error
DeleteRepository(ctx context.Context, id string) error
ListRepositories(ctx context.Context, workspaceID string) ([]*models.Repository, error)
CreateRepositoryScript(ctx context.Context, script *models.RepositoryScript) error
GetRepositoryScript(ctx context.Context, id string) (*models.RepositoryScript, error)
UpdateRepositoryScript(ctx context.Context, script *models.RepositoryScript) error
DeleteRepositoryScript(ctx context.Context, id string) error
ListRepositoryScripts(ctx context.Context, repositoryID string) ([]*models.RepositoryScript, error)
ListScriptsByRepositoryIDs(ctx context.Context, repoIDs []string) (map[string][]*models.RepositoryScript, error)
GetRepositoryByProviderInfo(ctx context.Context, workspaceID, provider, owner, name string) (*models.Repository, error)
}
// ExecutorRepository handles executor CRUD, executor profiles, and running state.
type ExecutorRepository interface {
CreateExecutor(ctx context.Context, executor *models.Executor) error
GetExecutor(ctx context.Context, id string) (*models.Executor, error)
UpdateExecutor(ctx context.Context, executor *models.Executor) error
DeleteExecutor(ctx context.Context, id string) error
ListExecutors(ctx context.Context) ([]*models.Executor, error)
CreateExecutorProfile(ctx context.Context, profile *models.ExecutorProfile) error
GetExecutorProfile(ctx context.Context, id string) (*models.ExecutorProfile, error)
UpdateExecutorProfile(ctx context.Context, profile *models.ExecutorProfile) error
DeleteExecutorProfile(ctx context.Context, id string) error
ListExecutorProfiles(ctx context.Context, executorID string) ([]*models.ExecutorProfile, error)
ListAllExecutorProfiles(ctx context.Context) ([]*models.ExecutorProfile, error)
ListExecutorsRunning(ctx context.Context) ([]*models.ExecutorRunning, error)
UpsertExecutorRunning(ctx context.Context, running *models.ExecutorRunning) error
GetExecutorRunningBySessionID(ctx context.Context, sessionID string) (*models.ExecutorRunning, error)
DeleteExecutorRunningBySessionID(ctx context.Context, sessionID string) error
// HasExecutorRunningRow returns true if a row exists for the session.
// Used to decide "session has been launched at least once" without loading the full row.
HasExecutorRunningRow(ctx context.Context, sessionID string) (bool, error)
// UpdateResumeToken performs a CAS-style narrow update of resume_token + last_message_uuid
// scoped to the row's current agent_execution_id. If the row's agent_execution_id no longer
// matches expectedExecID (i.e. a new execution has taken over), returns models.ErrExecutionRotated
// and writes nothing. Use when persisting state from a specific execution that may have been
// replaced concurrently — typically resume tokens emitted by ACP session events.
UpdateResumeToken(ctx context.Context, sessionID, expectedExecID, resumeToken, lastMessageUUID string) error
}
// EnvironmentRepository handles environment CRUD.
type EnvironmentRepository interface {
CreateEnvironment(ctx context.Context, environment *models.Environment) error
GetEnvironment(ctx context.Context, id string) (*models.Environment, error)
UpdateEnvironment(ctx context.Context, environment *models.Environment) error
DeleteEnvironment(ctx context.Context, id string) error
ListEnvironments(ctx context.Context) ([]*models.Environment, error)
}
// TaskEnvironmentRepository handles per-task execution environment instances
// and their per-repository child rows.
type TaskEnvironmentRepository interface {
CreateTaskEnvironment(ctx context.Context, env *models.TaskEnvironment) error
GetTaskEnvironment(ctx context.Context, id string) (*models.TaskEnvironment, error)
GetTaskEnvironmentByTaskID(ctx context.Context, taskID string) (*models.TaskEnvironment, error)
UpdateTaskEnvironment(ctx context.Context, env *models.TaskEnvironment) error
DeleteTaskEnvironment(ctx context.Context, id string) error
DeleteTaskEnvironmentsByTask(ctx context.Context, taskID string) error
CreateTaskEnvironmentRepo(ctx context.Context, repo *models.TaskEnvironmentRepo) error
ListTaskEnvironmentRepos(ctx context.Context, envID string) ([]*models.TaskEnvironmentRepo, error)
UpdateTaskEnvironmentRepo(ctx context.Context, repo *models.TaskEnvironmentRepo) error
DeleteTaskEnvironmentRepo(ctx context.Context, id string) error
DeleteTaskEnvironmentReposByEnv(ctx context.Context, envID string) error
}
// ReviewRepository handles session file review records.
type ReviewRepository interface {
UpsertSessionFileReview(ctx context.Context, review *models.SessionFileReview) error
GetSessionFileReviews(ctx context.Context, sessionID string) ([]*models.SessionFileReview, error)
DeleteSessionFileReviews(ctx context.Context, sessionID string) error
}
// PlanRepository handles task plan CRUD and its revision history.
type PlanRepository interface {
CreateTaskPlan(ctx context.Context, plan *models.TaskPlan) error
GetTaskPlan(ctx context.Context, taskID string) (*models.TaskPlan, error)
UpdateTaskPlan(ctx context.Context, plan *models.TaskPlan) error
DeleteTaskPlan(ctx context.Context, taskID string) error
// Revision history
InsertTaskPlanRevision(ctx context.Context, rev *models.TaskPlanRevision) error
UpdateTaskPlanRevision(ctx context.Context, rev *models.TaskPlanRevision) error
GetTaskPlanRevision(ctx context.Context, id string) (*models.TaskPlanRevision, error)
GetLatestTaskPlanRevision(ctx context.Context, taskID string) (*models.TaskPlanRevision, error)
ListTaskPlanRevisions(ctx context.Context, taskID string, limit int) ([]*models.TaskPlanRevision, error)
NextTaskPlanRevisionNumber(ctx context.Context, taskID string) (int, error)
// WritePlanRevision atomically upserts the HEAD plan and writes/merges a revision in a
// single transaction. Pass a non-nil coalesceLatestID to merge into an existing revision;
// otherwise a new revision is appended with revision_number computed inside the tx.
WritePlanRevision(ctx context.Context, head *models.TaskPlan, rev *models.TaskPlanRevision, coalesceLatestID *string) error
}