mirror of
https://github.com/tiennm99/goclaw.git
synced 2026-06-10 04:10:26 +00:00
b231878a85
- Add limit parameter to ListTasks interface (dashboard=200, agent=30) - Add teams.tasks.get-light WS method returning task only (no comments/events) - Truncate dashboard response to exact limit (fix off-by-one from limit+1) - Update all 7 ListTasks callers with explicit limit values
463 lines
21 KiB
Go
463 lines
21 KiB
Go
package store
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"errors"
|
|
"time"
|
|
|
|
"github.com/google/uuid"
|
|
)
|
|
|
|
// RecoveredTaskInfo contains minimal info for leader notification after batch recovery/stale.
|
|
type RecoveredTaskInfo struct {
|
|
ID uuid.UUID
|
|
TeamID uuid.UUID
|
|
TaskNumber int
|
|
Subject string
|
|
Channel string // task's origin channel for notification routing
|
|
ChatID string // task scope for notification routing
|
|
}
|
|
|
|
// ErrFileLocked is returned when a workspace file is being written by another agent.
|
|
var ErrFileLocked = errors.New("file is being written by another agent, try again shortly")
|
|
|
|
// ErrTaskNotFound is returned when a task does not exist.
|
|
var ErrTaskNotFound = errors.New("task not found")
|
|
|
|
// Team status constants.
|
|
const (
|
|
TeamStatusActive = "active"
|
|
TeamStatusArchived = "archived"
|
|
)
|
|
|
|
// Team member role constants.
|
|
const (
|
|
TeamRoleLead = "lead"
|
|
TeamRoleMember = "member"
|
|
TeamRoleReviewer = "reviewer"
|
|
)
|
|
|
|
// Team task status constants.
|
|
const (
|
|
TeamTaskStatusPending = "pending"
|
|
TeamTaskStatusInProgress = "in_progress"
|
|
TeamTaskStatusCompleted = "completed"
|
|
TeamTaskStatusBlocked = "blocked"
|
|
TeamTaskStatusFailed = "failed"
|
|
TeamTaskStatusInReview = "in_review"
|
|
TeamTaskStatusCancelled = "cancelled"
|
|
TeamTaskStatusStale = "stale"
|
|
)
|
|
|
|
// Team task list filter constants (for ListTasks statusFilter parameter).
|
|
const (
|
|
TeamTaskFilterActive = "active" // pending + in_progress + blocked
|
|
TeamTaskFilterInReview = "in_review" // only in_review tasks
|
|
TeamTaskFilterCompleted = "completed" // only completed tasks
|
|
TeamTaskFilterAll = "all" // all statuses (default when "" passed)
|
|
)
|
|
|
|
// Team message type constants.
|
|
const (
|
|
TeamMessageTypeChat = "chat"
|
|
TeamMessageTypeBroadcast = "broadcast"
|
|
)
|
|
|
|
// TeamData represents an agent team.
|
|
type TeamData struct {
|
|
BaseModel
|
|
Name string `json:"name"`
|
|
LeadAgentID uuid.UUID `json:"lead_agent_id"`
|
|
Description string `json:"description,omitempty"`
|
|
Status string `json:"status"`
|
|
Settings json.RawMessage `json:"settings,omitempty"`
|
|
CreatedBy string `json:"created_by"`
|
|
|
|
// Joined fields (populated by queries that JOIN agents table)
|
|
LeadAgentKey string `json:"lead_agent_key,omitempty"`
|
|
LeadDisplayName string `json:"lead_display_name,omitempty"`
|
|
|
|
// Enriched fields (populated by ListTeams)
|
|
MemberCount int `json:"member_count"`
|
|
Members []TeamMemberData `json:"members,omitempty"`
|
|
}
|
|
|
|
// TeamMemberData represents a team member.
|
|
type TeamMemberData struct {
|
|
TeamID uuid.UUID `json:"team_id"`
|
|
AgentID uuid.UUID `json:"agent_id"`
|
|
Role string `json:"role"`
|
|
JoinedAt time.Time `json:"joined_at"`
|
|
|
|
// Joined fields
|
|
AgentKey string `json:"agent_key,omitempty"`
|
|
DisplayName string `json:"display_name,omitempty"`
|
|
Frontmatter string `json:"frontmatter,omitempty"`
|
|
Emoji string `json:"emoji,omitempty"`
|
|
}
|
|
|
|
// TeamTaskData represents a task in the team's shared task list.
|
|
type TeamTaskData struct {
|
|
BaseModel
|
|
TeamID uuid.UUID `json:"team_id"`
|
|
Subject string `json:"subject"`
|
|
Description string `json:"description,omitempty"`
|
|
Status string `json:"status"`
|
|
OwnerAgentID *uuid.UUID `json:"owner_agent_id,omitempty"`
|
|
BlockedBy []uuid.UUID `json:"blocked_by,omitempty"`
|
|
Priority int `json:"priority"`
|
|
Result *string `json:"result,omitempty"`
|
|
Metadata map[string]any `json:"metadata,omitempty"`
|
|
UserID string `json:"user_id,omitempty"`
|
|
Channel string `json:"channel,omitempty"`
|
|
|
|
// V2 fields
|
|
TaskType string `json:"task_type"`
|
|
TaskNumber int `json:"task_number,omitempty"`
|
|
Identifier string `json:"identifier,omitempty"`
|
|
CreatedByAgentID *uuid.UUID `json:"created_by_agent_id,omitempty"`
|
|
AssigneeUserID string `json:"assignee_user_id,omitempty"`
|
|
ParentID *uuid.UUID `json:"parent_id,omitempty"`
|
|
ChatID string `json:"chat_id,omitempty"`
|
|
LockedAt *time.Time `json:"locked_at,omitempty"`
|
|
LockExpiresAt *time.Time `json:"lock_expires_at,omitempty"`
|
|
ProgressPercent int `json:"progress_percent,omitempty"`
|
|
ProgressStep string `json:"progress_step,omitempty"`
|
|
|
|
// Follow-up reminder fields
|
|
FollowupAt *time.Time `json:"followup_at,omitempty"`
|
|
FollowupCount int `json:"followup_count,omitempty"`
|
|
FollowupMax int `json:"followup_max,omitempty"`
|
|
FollowupMessage string `json:"followup_message,omitempty"`
|
|
FollowupChannel string `json:"followup_channel,omitempty"`
|
|
FollowupChatID string `json:"followup_chat_id,omitempty"`
|
|
|
|
// Joined fields
|
|
OwnerAgentKey string `json:"owner_agent_key,omitempty"`
|
|
CreatedByAgentKey string `json:"created_by_agent_key,omitempty"`
|
|
}
|
|
|
|
// TeamTaskCommentData represents a comment on a team task.
|
|
type TeamTaskCommentData struct {
|
|
ID uuid.UUID `json:"id"`
|
|
TaskID uuid.UUID `json:"task_id"`
|
|
AgentID *uuid.UUID `json:"agent_id,omitempty"`
|
|
UserID string `json:"user_id,omitempty"`
|
|
Content string `json:"content"`
|
|
CreatedAt time.Time `json:"created_at"`
|
|
|
|
// Joined
|
|
AgentKey string `json:"agent_key,omitempty"`
|
|
}
|
|
|
|
// TeamTaskEventData represents an audit event on a team task.
|
|
type TeamTaskEventData struct {
|
|
ID uuid.UUID `json:"id"`
|
|
TaskID uuid.UUID `json:"task_id"`
|
|
EventType string `json:"event_type"`
|
|
ActorType string `json:"actor_type"` // "agent" | "human"
|
|
ActorID string `json:"actor_id"`
|
|
Data json.RawMessage `json:"data,omitempty"`
|
|
CreatedAt time.Time `json:"created_at"`
|
|
}
|
|
|
|
// TeamTaskAttachmentData represents a workspace file attached to a team task.
|
|
type TeamTaskAttachmentData struct {
|
|
ID uuid.UUID `json:"id"`
|
|
TaskID uuid.UUID `json:"task_id"`
|
|
FileID uuid.UUID `json:"file_id"`
|
|
AddedBy *uuid.UUID `json:"added_by,omitempty"`
|
|
CreatedAt time.Time `json:"created_at"`
|
|
|
|
// Joined
|
|
FileName string `json:"file_name,omitempty"`
|
|
}
|
|
|
|
// DelegationHistoryData represents a persisted delegation record.
|
|
type DelegationHistoryData struct {
|
|
BaseModel
|
|
SourceAgentID uuid.UUID `json:"source_agent_id"`
|
|
TargetAgentID uuid.UUID `json:"target_agent_id"`
|
|
TeamID *uuid.UUID `json:"team_id,omitempty"`
|
|
TeamTaskID *uuid.UUID `json:"team_task_id,omitempty"`
|
|
UserID string `json:"user_id,omitempty"`
|
|
Task string `json:"task"`
|
|
Mode string `json:"mode"`
|
|
Status string `json:"status"`
|
|
Result *string `json:"result,omitempty"`
|
|
Error *string `json:"error,omitempty"`
|
|
Iterations int `json:"iterations"`
|
|
TraceID *uuid.UUID `json:"trace_id,omitempty"`
|
|
DurationMS int `json:"duration_ms"`
|
|
CompletedAt *time.Time `json:"completed_at,omitempty"`
|
|
Metadata map[string]any `json:"metadata,omitempty"`
|
|
|
|
// Joined fields
|
|
SourceAgentKey string `json:"source_agent_key,omitempty"`
|
|
TargetAgentKey string `json:"target_agent_key,omitempty"`
|
|
}
|
|
|
|
// DelegationHistoryListOpts configures delegation history queries.
|
|
type DelegationHistoryListOpts struct {
|
|
SourceAgentID *uuid.UUID
|
|
TargetAgentID *uuid.UUID
|
|
TeamID *uuid.UUID
|
|
UserID string
|
|
Status string // "completed", "failed", "" = all
|
|
Limit int
|
|
Offset int
|
|
}
|
|
|
|
// TeamMessageData represents a message in the team mailbox.
|
|
type TeamMessageData struct {
|
|
ID uuid.UUID `json:"id"`
|
|
TeamID uuid.UUID `json:"team_id"`
|
|
FromAgentID uuid.UUID `json:"from_agent_id"`
|
|
ToAgentID *uuid.UUID `json:"to_agent_id,omitempty"`
|
|
Content string `json:"content"`
|
|
MessageType string `json:"message_type"`
|
|
Read bool `json:"read"`
|
|
TaskID *uuid.UUID `json:"task_id,omitempty"`
|
|
Metadata map[string]any `json:"metadata,omitempty"`
|
|
CreatedAt time.Time `json:"created_at"`
|
|
|
|
// Joined fields
|
|
FromAgentKey string `json:"from_agent_key,omitempty"`
|
|
ToAgentKey string `json:"to_agent_key,omitempty"`
|
|
}
|
|
|
|
// TeamWorkspaceFileData represents a file in the team's shared workspace.
|
|
type TeamWorkspaceFileData struct {
|
|
ID uuid.UUID `json:"id"`
|
|
TeamID uuid.UUID `json:"team_id"`
|
|
Channel string `json:"channel"`
|
|
ChatID string `json:"chat_id"`
|
|
FileName string `json:"file_name"`
|
|
MimeType string `json:"mime_type,omitempty"`
|
|
FilePath string `json:"-"`
|
|
SizeBytes int64 `json:"size_bytes"`
|
|
UploadedBy uuid.UUID `json:"uploaded_by"`
|
|
TaskID *uuid.UUID `json:"task_id,omitempty"`
|
|
Pinned bool `json:"pinned"`
|
|
Tags []string `json:"tags,omitempty"`
|
|
Metadata json.RawMessage `json:"metadata,omitempty"`
|
|
ArchivedAt *time.Time `json:"archived_at,omitempty"`
|
|
CreatedAt time.Time `json:"created_at"`
|
|
UpdatedAt time.Time `json:"updated_at"`
|
|
|
|
// Joined
|
|
UploadedByKey string `json:"uploaded_by_key,omitempty"`
|
|
}
|
|
|
|
// TeamWorkspaceFileVersionData represents a version of a workspace file.
|
|
type TeamWorkspaceFileVersionData struct {
|
|
ID uuid.UUID `json:"id"`
|
|
FileID uuid.UUID `json:"file_id"`
|
|
Version int `json:"version"`
|
|
FilePath string `json:"-"`
|
|
SizeBytes int64 `json:"size_bytes"`
|
|
UploadedBy uuid.UUID `json:"uploaded_by"`
|
|
CreatedAt time.Time `json:"created_at"`
|
|
|
|
// Joined
|
|
UploadedByKey string `json:"uploaded_by_key,omitempty"`
|
|
}
|
|
|
|
// TeamWorkspaceCommentData represents a comment on a workspace file.
|
|
type TeamWorkspaceCommentData struct {
|
|
ID uuid.UUID `json:"id"`
|
|
FileID uuid.UUID `json:"file_id"`
|
|
AgentID uuid.UUID `json:"agent_id"`
|
|
Content string `json:"content"`
|
|
CreatedAt time.Time `json:"created_at"`
|
|
|
|
// Joined
|
|
AgentKey string `json:"agent_key,omitempty"`
|
|
}
|
|
|
|
// ScopeEntry represents a unique channel+chatID scope across tasks and workspace.
|
|
type ScopeEntry struct {
|
|
Channel string `json:"channel"`
|
|
ChatID string `json:"chat_id"`
|
|
}
|
|
|
|
// TeamStore manages agent teams, tasks, and messages.
|
|
type TeamStore interface {
|
|
// Team CRUD
|
|
CreateTeam(ctx context.Context, team *TeamData) error
|
|
GetTeam(ctx context.Context, teamID uuid.UUID) (*TeamData, error)
|
|
UpdateTeam(ctx context.Context, teamID uuid.UUID, updates map[string]any) error
|
|
DeleteTeam(ctx context.Context, teamID uuid.UUID) error
|
|
ListTeams(ctx context.Context) ([]TeamData, error)
|
|
|
|
// Members
|
|
AddMember(ctx context.Context, teamID, agentID uuid.UUID, role string) error
|
|
RemoveMember(ctx context.Context, teamID, agentID uuid.UUID) error
|
|
ListMembers(ctx context.Context, teamID uuid.UUID) ([]TeamMemberData, error)
|
|
// ListIdleMembers returns team members (non-lead) that have no in_progress tasks.
|
|
ListIdleMembers(ctx context.Context, teamID uuid.UUID) ([]TeamMemberData, error)
|
|
|
|
// GetTeamForAgent returns the team that the given agent belongs to.
|
|
// Returns nil, nil if the agent is not in any team.
|
|
GetTeamForAgent(ctx context.Context, agentID uuid.UUID) (*TeamData, error)
|
|
|
|
// KnownUserIDs returns distinct user IDs from sessions of team member agents.
|
|
// Used by team settings UI to populate user select boxes.
|
|
KnownUserIDs(ctx context.Context, teamID uuid.UUID, limit int) ([]string, error)
|
|
|
|
// Scopes (channel+chatID discovery across tasks and workspace)
|
|
ListTaskScopes(ctx context.Context, teamID uuid.UUID) ([]ScopeEntry, error)
|
|
|
|
// Tasks (shared task list)
|
|
CreateTask(ctx context.Context, task *TeamTaskData) error
|
|
UpdateTask(ctx context.Context, taskID uuid.UUID, updates map[string]any) error
|
|
// ListTasks returns tasks for a team. orderBy: "priority" or "newest".
|
|
// statusFilter: "" = non-completed (default), "completed", "all".
|
|
// userID: if non-empty, filter to tasks created by this user.
|
|
// channel+chatID: if either is non-empty, filter to that exact scope.
|
|
// limit: max rows to return; 0 uses the default (30).
|
|
ListTasks(ctx context.Context, teamID uuid.UUID, orderBy string, statusFilter string, userID string, channel string, chatID string, limit int, offset int) ([]TeamTaskData, error)
|
|
// GetTask returns a single task by ID with joined agent info.
|
|
GetTask(ctx context.Context, taskID uuid.UUID) (*TeamTaskData, error)
|
|
// GetTasksByIDs returns multiple tasks by IDs in a single query.
|
|
GetTasksByIDs(ctx context.Context, ids []uuid.UUID) ([]TeamTaskData, error)
|
|
// SearchTasks performs FTS search over task subject+description.
|
|
// userID: if non-empty, filter to tasks created by this user.
|
|
SearchTasks(ctx context.Context, teamID uuid.UUID, query string, limit int, userID string) ([]TeamTaskData, error)
|
|
// DeleteTask permanently removes a terminal-status task (completed/failed/cancelled).
|
|
// Returns ErrTaskNotFound if the task does not exist or is not in a terminal status.
|
|
DeleteTask(ctx context.Context, taskID, teamID uuid.UUID) error
|
|
// DeleteTasks permanently removes multiple terminal-status tasks in a single query.
|
|
// Returns the list of IDs that were actually deleted.
|
|
DeleteTasks(ctx context.Context, taskIDs []uuid.UUID, teamID uuid.UUID) ([]uuid.UUID, error)
|
|
|
|
// ClaimTask atomically transitions a task from pending to in_progress.
|
|
// Only one agent can claim a given task (row-level lock, race-safe).
|
|
// teamID is validated in the WHERE clause to prevent cross-team task claiming.
|
|
ClaimTask(ctx context.Context, taskID, agentID, teamID uuid.UUID) error
|
|
|
|
// AssignTask admin-assigns a pending task to a specific agent.
|
|
// teamID is validated in the WHERE clause to prevent cross-team assignment.
|
|
AssignTask(ctx context.Context, taskID, agentID, teamID uuid.UUID) error
|
|
|
|
// CompleteTask marks a task as completed and unblocks dependent tasks.
|
|
// teamID is validated in the WHERE clause to prevent cross-team task completion.
|
|
CompleteTask(ctx context.Context, taskID, teamID uuid.UUID, result string) error
|
|
|
|
// CancelTask marks a non-completed task as cancelled (status=completed, result="CANCELLED: ..."),
|
|
// unblocks dependent tasks, and transitions blocked→pending when all blockers are resolved.
|
|
// Returns error if the task is already completed or not found.
|
|
CancelTask(ctx context.Context, taskID, teamID uuid.UUID, reason string) error
|
|
|
|
// FailTask marks an in_progress task as failed and stores the error message.
|
|
// Unblocks dependent tasks so they aren't stuck.
|
|
FailTask(ctx context.Context, taskID, teamID uuid.UUID, errMsg string) error
|
|
// FailPendingTask marks a pending or blocked task as failed (post-turn validation).
|
|
// Unlike FailTask, accepts pending/blocked source statuses.
|
|
FailPendingTask(ctx context.Context, taskID, teamID uuid.UUID, errMsg string) error
|
|
|
|
// Review workflow
|
|
ReviewTask(ctx context.Context, taskID, teamID uuid.UUID) error
|
|
ApproveTask(ctx context.Context, taskID, teamID uuid.UUID, comment string) error
|
|
RejectTask(ctx context.Context, taskID, teamID uuid.UUID, reason string) error
|
|
|
|
// Task comments
|
|
AddTaskComment(ctx context.Context, comment *TeamTaskCommentData) error
|
|
ListTaskComments(ctx context.Context, taskID uuid.UUID) ([]TeamTaskCommentData, error)
|
|
|
|
// Audit events
|
|
RecordTaskEvent(ctx context.Context, event *TeamTaskEventData) error
|
|
ListTaskEvents(ctx context.Context, taskID uuid.UUID) ([]TeamTaskEventData, error)
|
|
// ListTeamEvents returns recent events across all tasks in a team.
|
|
ListTeamEvents(ctx context.Context, teamID uuid.UUID, limit, offset int) ([]TeamTaskEventData, error)
|
|
|
|
// Attachments
|
|
AttachFileToTask(ctx context.Context, att *TeamTaskAttachmentData) error
|
|
ListTaskAttachments(ctx context.Context, taskID uuid.UUID) ([]TeamTaskAttachmentData, error)
|
|
DetachFileFromTask(ctx context.Context, taskID, fileID uuid.UUID) error
|
|
|
|
// Follow-up reminders
|
|
SetTaskFollowup(ctx context.Context, taskID, teamID uuid.UUID, followupAt time.Time, max int, message, channel, chatID string) error
|
|
ClearTaskFollowup(ctx context.Context, taskID uuid.UUID) error
|
|
// ListAllFollowupDueTasks returns due followup tasks across all v2 active teams (batch).
|
|
ListAllFollowupDueTasks(ctx context.Context) ([]TeamTaskData, error)
|
|
IncrementFollowupCount(ctx context.Context, taskID uuid.UUID, nextAt *time.Time) error
|
|
|
|
// Auto follow-up guardrails (system-level, no LLM dependency)
|
|
// ClearFollowupByScope clears followup on all in_progress tasks for a given channel+chatID scope.
|
|
ClearFollowupByScope(ctx context.Context, channel, chatID string) (int, error)
|
|
// SetFollowupForActiveTasks sets followup on in_progress tasks that don't already have one.
|
|
// Matches tasks scoped to the given channel+chatID, or unscoped tasks in the same team.
|
|
SetFollowupForActiveTasks(ctx context.Context, teamID uuid.UUID, channel, chatID string, followupAt time.Time, max int, message string) (int, error)
|
|
// HasActiveMemberTasks returns true if there are pending/in_progress/blocked tasks
|
|
// assigned to agents other than the given agent (typically the lead).
|
|
// Used to suppress auto-followup when the lead is waiting for teammates, not the user.
|
|
HasActiveMemberTasks(ctx context.Context, teamID uuid.UUID, excludeAgentID uuid.UUID) (bool, error)
|
|
|
|
// Progress
|
|
UpdateTaskProgress(ctx context.Context, taskID, teamID uuid.UUID, percent int, step string) error
|
|
|
|
// Lock renewal (heartbeat to prevent stale recovery of long-running tasks)
|
|
RenewTaskLock(ctx context.Context, taskID, teamID uuid.UUID) error
|
|
|
|
// Stale recovery (batch — all v2 active teams in single query)
|
|
// RecoverAllStaleTasks resets in_progress tasks with expired locks back to pending.
|
|
RecoverAllStaleTasks(ctx context.Context) ([]RecoveredTaskInfo, error)
|
|
// ForceRecoverAllTasks resets ALL in_progress tasks back to pending (ignoring lock expiry).
|
|
// Used on startup when no agents are running.
|
|
ForceRecoverAllTasks(ctx context.Context) ([]RecoveredTaskInfo, error)
|
|
// ListRecoverableTasks returns all pending tasks (including stale in_progress with expired locks).
|
|
// Per-team: used by DispatchUnblockedTasks after task completion.
|
|
ListRecoverableTasks(ctx context.Context, teamID uuid.UUID) ([]TeamTaskData, error)
|
|
// MarkAllStaleTasks sets pending tasks older than olderThan to stale status across all v2 active teams.
|
|
MarkAllStaleTasks(ctx context.Context, olderThan time.Time) ([]RecoveredTaskInfo, error)
|
|
// ResetTaskStatus resets a stale or failed task back to pending for retry.
|
|
ResetTaskStatus(ctx context.Context, taskID, teamID uuid.UUID) error
|
|
|
|
// Delegation history
|
|
SaveDelegationHistory(ctx context.Context, record *DelegationHistoryData) error
|
|
ListDelegationHistory(ctx context.Context, opts DelegationHistoryListOpts) ([]DelegationHistoryData, int, error)
|
|
GetDelegationHistory(ctx context.Context, id uuid.UUID) (*DelegationHistoryData, error)
|
|
|
|
// Messages (mailbox)
|
|
SendMessage(ctx context.Context, msg *TeamMessageData) error
|
|
GetUnread(ctx context.Context, teamID, agentID uuid.UUID) ([]TeamMessageData, error)
|
|
MarkRead(ctx context.Context, messageID uuid.UUID) error
|
|
// ListMessages returns paginated team messages ordered by created_at DESC.
|
|
ListMessages(ctx context.Context, teamID uuid.UUID, limit, offset int) ([]TeamMessageData, int, error)
|
|
|
|
// Workspace files
|
|
// UpsertWorkspaceFile acquires an advisory lock, calls diskWriteFn (if non-nil)
|
|
// to perform disk I/O under that lock, then upserts DB metadata — all within one tx.
|
|
// diskWriteFn receives isNew (true if this is a new file, false if update).
|
|
UpsertWorkspaceFile(ctx context.Context, file *TeamWorkspaceFileData, diskWriteFn func(isNew bool) error) (isNew bool, err error)
|
|
GetWorkspaceFile(ctx context.Context, teamID uuid.UUID, channel, chatID, fileName string) (*TeamWorkspaceFileData, error)
|
|
// ListWorkspaceFiles returns non-archived files for a team.
|
|
// When both channel and chatID are empty, all files for the team are returned
|
|
// regardless of scope (used by the Workspace UI tab).
|
|
// When either is non-empty, results are filtered to that exact channel+chatID scope.
|
|
ListWorkspaceFiles(ctx context.Context, teamID uuid.UUID, channel, chatID string) ([]TeamWorkspaceFileData, error)
|
|
DeleteWorkspaceFile(ctx context.Context, teamID uuid.UUID, channel, chatID, fileName string) (filePath string, err error)
|
|
CountWorkspaceFiles(ctx context.Context, teamID uuid.UUID, channel, chatID string) (int, error)
|
|
PinWorkspaceFile(ctx context.Context, teamID uuid.UUID, channel, chatID, fileName string, pinned bool) error
|
|
TagWorkspaceFile(ctx context.Context, teamID uuid.UUID, channel, chatID, fileName string, tags []string) error
|
|
ListDeliverableFiles(ctx context.Context, teamID uuid.UUID, channel, chatID string) ([]TeamWorkspaceFileData, error)
|
|
ArchiveWorkspaceFilesByTask(ctx context.Context, taskID uuid.UUID) error
|
|
ListOrphanWorkspaceFiles(ctx context.Context, teamID uuid.UUID, olderThan time.Time) ([]TeamWorkspaceFileData, error)
|
|
CopyFilesToTeam(ctx context.Context, fileIDs []uuid.UUID, targetTeamID uuid.UUID, targetChannel, targetChatID, dataDir string) error
|
|
|
|
// Workspace versioning
|
|
CreateFileVersion(ctx context.Context, version *TeamWorkspaceFileVersionData) error
|
|
ListFileVersions(ctx context.Context, fileID uuid.UUID) ([]TeamWorkspaceFileVersionData, error)
|
|
GetFileVersion(ctx context.Context, fileID uuid.UUID, version int) (*TeamWorkspaceFileVersionData, error)
|
|
PruneOldVersions(ctx context.Context, fileID uuid.UUID, keepN int) ([]string, error) // returns pruned file paths
|
|
|
|
// Workspace comments
|
|
AddFileComment(ctx context.Context, comment *TeamWorkspaceCommentData) error
|
|
ListFileComments(ctx context.Context, fileID uuid.UUID) ([]TeamWorkspaceCommentData, error)
|
|
|
|
// Workspace quota
|
|
GetWorkspaceTotalSize(ctx context.Context, teamID uuid.UUID) (int64, error)
|
|
}
|