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 }