mirror of
https://github.com/tiennm99/goclaw.git
synced 2026-08-01 12:21:59 +00:00
* feat(teams): refactor attachments, remove team_message, add task comments UI Major team system refactoring: - Drop team_workspace_files, team_workspace_file_versions, team_workspace_comments, team_messages tables; replace team_task_attachments with path-based schema - Add denormalized comment_count/attachment_count on team_tasks for dashboard perf - Auto-track file writes as task attachments via WorkspaceInterceptor - Remove team_message tool entirely (tool, store, i18n, builtin_tools, MCP bridge) - Members communicate via task comments; approve/reject use comments for audit trail - Add commented/new_task notification types to TeamNotifyConfig - Enrich task completion announce with member comments - User-created tasks stay pending (backlog) — no auto-assign to leader - Configurable member request tasks (member_requests.enabled in team settings) - Structured task description template in TEAM.md for v2 leads - HTTP attachment download endpoint with IDOR + path traversal protection - Web UI: count badges on task list, comments section with input, download button - Team settings UI: completed/commented/new_task toggles, member requests section * feat(teams): priority dispatch, compact prompting, realtime comments - Priority dispatch: DispatchUnblockedTasks dispatches only 1 task per owner per round (highest priority first). Fixes cancel bug where CancelSession killed innocent queued tasks. - Prompt rework: Replace verbose Task Decomposition (25 lines) with compact Task Planning (8 lines). Add explicit UUID warning and sequencing guidance for weak models (Qwen, MiniMax). - Recent comments in dispatch: buildRecentCommentsSummary appends 3 most recent comments to re-dispatched tasks (reject, retry, stale). - Enrich comment event payload with TaskNumber, Subject, CommentText (truncated 500 runes, UTF-8 safe). - UI: Board subscribes to TEAM_TASK_COMMENTED for realtime comment_count badge updates. Task detail dialog auto-refreshes comments on event. - Tool description hint: guide models to write self-contained task descriptions with clear objectives and context. * perf(teams): add ListRecentTaskComments with SQL LIMIT Dispatch only needs 3 most recent comments — avoid fetching all. New ListRecentTaskComments(ctx, taskID, limit) uses ORDER BY DESC LIMIT N then reverses to chronological order. * feat(teams): add subject embedding for semantic task search + improve prompting - Add vector(1536) embedding column to team_tasks with HNSW index - Implement hybrid search: FTS (0.3) + cosine similarity (0.7) with graceful fallback - Auto-generate embeddings on task create/update, backfill existing tasks on startup - Wire embedding provider into PGTeamStore via gateway_setup - Change FTS from OR to AND with prefix matching for precise keyword search - Reduce search page size from 30 to 5 to save tokens - Rename migration 000023 → 000024, bump RequiredSchemaVersion to 24 - Update TEAM.md hints: prefer search over list, batch task creation with blocked_by - Add anti-pattern examples to prevent sequential task creation
205 lines
8.8 KiB
Go
205 lines
8.8 KiB
Go
package protocol
|
|
|
|
// DelegationEventPayload is the typed payload for delegation lifecycle events
|
|
// (started, completed, failed, cancelled).
|
|
type DelegationEventPayload struct {
|
|
DelegationID string `json:"delegation_id"`
|
|
SourceAgentID string `json:"source_agent_id"`
|
|
SourceAgentKey string `json:"source_agent_key"`
|
|
SourceDisplayName string `json:"source_display_name,omitempty"`
|
|
TargetAgentID string `json:"target_agent_id"`
|
|
TargetAgentKey string `json:"target_agent_key"`
|
|
TargetDisplayName string `json:"target_display_name,omitempty"`
|
|
UserID string `json:"user_id"`
|
|
Channel string `json:"channel"`
|
|
ChatID string `json:"chat_id"`
|
|
Mode string `json:"mode"`
|
|
Task string `json:"task,omitempty"`
|
|
TeamID string `json:"team_id,omitempty"`
|
|
TeamTaskID string `json:"team_task_id,omitempty"`
|
|
Status string `json:"status,omitempty"`
|
|
ElapsedMS int `json:"elapsed_ms,omitempty"`
|
|
Error string `json:"error,omitempty"`
|
|
CreatedAt string `json:"created_at"`
|
|
}
|
|
|
|
// DelegationProgressItem describes one active delegation in a progress report.
|
|
type DelegationProgressItem struct {
|
|
DelegationID string `json:"delegation_id"`
|
|
TargetAgentKey string `json:"target_agent_key"`
|
|
TargetDisplayName string `json:"target_display_name,omitempty"`
|
|
ElapsedMS int `json:"elapsed_ms"`
|
|
TeamTaskID string `json:"team_task_id,omitempty"`
|
|
Activity string `json:"activity,omitempty"` // "thinking", "tool_exec", "compacting"
|
|
Tool string `json:"tool,omitempty"` // current tool name (when Activity == "tool_exec")
|
|
}
|
|
|
|
// DelegationProgressPayload is emitted periodically for async delegations.
|
|
type DelegationProgressPayload struct {
|
|
SourceAgentID string `json:"source_agent_id"`
|
|
SourceAgentKey string `json:"source_agent_key"`
|
|
UserID string `json:"user_id"`
|
|
Channel string `json:"channel"`
|
|
ChatID string `json:"chat_id"`
|
|
TeamID string `json:"team_id,omitempty"`
|
|
Active []DelegationProgressItem `json:"active_delegations"`
|
|
}
|
|
|
|
// DelegationAccumulatedPayload is emitted when an async delegation completes
|
|
// but siblings are still running (result accumulated, not yet announced).
|
|
type DelegationAccumulatedPayload struct {
|
|
DelegationID string `json:"delegation_id"`
|
|
SourceAgentID string `json:"source_agent_id"`
|
|
SourceAgentKey string `json:"source_agent_key"`
|
|
TargetAgentKey string `json:"target_agent_key"`
|
|
TargetDisplayName string `json:"target_display_name,omitempty"`
|
|
UserID string `json:"user_id"`
|
|
Channel string `json:"channel"`
|
|
ChatID string `json:"chat_id"`
|
|
TeamID string `json:"team_id,omitempty"`
|
|
TeamTaskID string `json:"team_task_id,omitempty"`
|
|
SiblingsRemaining int `json:"siblings_remaining"`
|
|
ElapsedMS int `json:"elapsed_ms,omitempty"`
|
|
}
|
|
|
|
// DelegationAnnounceResultSummary describes one delegation result in the announce payload.
|
|
type DelegationAnnounceResultSummary struct {
|
|
AgentKey string `json:"agent_key"`
|
|
DisplayName string `json:"display_name,omitempty"`
|
|
HasMedia bool `json:"has_media"`
|
|
ContentPreview string `json:"content_preview,omitempty"`
|
|
}
|
|
|
|
// DelegationAnnouncePayload is emitted when the last sibling delegation completes
|
|
// and all accumulated results are announced back to the lead agent.
|
|
type DelegationAnnouncePayload struct {
|
|
SourceAgentID string `json:"source_agent_id"`
|
|
SourceAgentKey string `json:"source_agent_key"`
|
|
SourceDisplayName string `json:"source_display_name,omitempty"`
|
|
UserID string `json:"user_id"`
|
|
Channel string `json:"channel"`
|
|
ChatID string `json:"chat_id"`
|
|
TeamID string `json:"team_id,omitempty"`
|
|
Results []DelegationAnnounceResultSummary `json:"results"`
|
|
CompletedTaskIDs []string `json:"completed_task_ids,omitempty"`
|
|
TotalElapsedMS int `json:"total_elapsed_ms"`
|
|
HasMedia bool `json:"has_media"`
|
|
}
|
|
|
|
// TeamTaskEventPayload is the typed payload for team task lifecycle events
|
|
// (created, claimed, completed, cancelled, approved, rejected).
|
|
type TeamTaskEventPayload struct {
|
|
TeamID string `json:"team_id"`
|
|
TaskID string `json:"task_id"`
|
|
TaskNumber int `json:"task_number,omitempty"`
|
|
Subject string `json:"subject,omitempty"`
|
|
Status string `json:"status"`
|
|
OwnerAgentKey string `json:"owner_agent_key,omitempty"`
|
|
OwnerDisplayName string `json:"owner_display_name,omitempty"`
|
|
Reason string `json:"reason,omitempty"`
|
|
UserID string `json:"user_id"`
|
|
Channel string `json:"channel"`
|
|
ChatID string `json:"chat_id"`
|
|
Timestamp string `json:"timestamp"`
|
|
|
|
// Comment text preview (for team.task.commented events, truncated).
|
|
CommentText string `json:"comment_text,omitempty"`
|
|
|
|
// Progress (for team.task.progress events).
|
|
ProgressPercent int `json:"progress_percent,omitempty"`
|
|
ProgressStep string `json:"progress_step,omitempty"`
|
|
|
|
// Actor info for audit trail (recorded to team_task_events by subscriber).
|
|
ActorType string `json:"actor_type,omitempty"` // "agent", "human", "system"
|
|
ActorID string `json:"actor_id,omitempty"` // agent key, user ID, or system identifier
|
|
}
|
|
|
|
// TeamMessageEventPayload is the typed payload for team.message.sent events.
|
|
type TeamMessageEventPayload struct {
|
|
TeamID string `json:"team_id"`
|
|
FromAgentKey string `json:"from_agent_key"`
|
|
FromDisplayName string `json:"from_display_name,omitempty"`
|
|
ToAgentKey string `json:"to_agent_key"`
|
|
ToDisplayName string `json:"to_display_name,omitempty"`
|
|
MessageType string `json:"message_type"`
|
|
Preview string `json:"preview"`
|
|
TaskID string `json:"task_id,omitempty"`
|
|
UserID string `json:"user_id"`
|
|
Channel string `json:"channel"`
|
|
ChatID string `json:"chat_id"`
|
|
}
|
|
|
|
// --- Team CRUD event payloads ---
|
|
|
|
// TeamCreatedPayload is emitted when a new team is created via RPC.
|
|
type TeamCreatedPayload struct {
|
|
TeamID string `json:"team_id"`
|
|
TeamName string `json:"team_name"`
|
|
LeadAgentKey string `json:"lead_agent_key"`
|
|
LeadDisplayName string `json:"lead_display_name,omitempty"`
|
|
MemberCount int `json:"member_count"`
|
|
}
|
|
|
|
// TeamUpdatedPayload is emitted when team settings are updated via RPC.
|
|
type TeamUpdatedPayload struct {
|
|
TeamID string `json:"team_id"`
|
|
TeamName string `json:"team_name"`
|
|
Changes []string `json:"changes"`
|
|
}
|
|
|
|
// TeamDeletedPayload is emitted when a team is deleted via RPC.
|
|
type TeamDeletedPayload struct {
|
|
TeamID string `json:"team_id"`
|
|
TeamName string `json:"team_name"`
|
|
}
|
|
|
|
// TeamMemberAddedPayload is emitted when a member is added to a team.
|
|
type TeamMemberAddedPayload struct {
|
|
TeamID string `json:"team_id"`
|
|
TeamName string `json:"team_name"`
|
|
AgentID string `json:"agent_id"`
|
|
AgentKey string `json:"agent_key"`
|
|
DisplayName string `json:"display_name,omitempty"`
|
|
Role string `json:"role"`
|
|
}
|
|
|
|
// TeamMemberRemovedPayload is emitted when a member is removed from a team.
|
|
type TeamMemberRemovedPayload struct {
|
|
TeamID string `json:"team_id"`
|
|
TeamName string `json:"team_name"`
|
|
AgentID string `json:"agent_id"`
|
|
AgentKey string `json:"agent_key"`
|
|
DisplayName string `json:"display_name,omitempty"`
|
|
}
|
|
|
|
// --- Agent link event payloads ---
|
|
|
|
// AgentLinkCreatedPayload is emitted when a new agent link is created.
|
|
type AgentLinkCreatedPayload struct {
|
|
LinkID string `json:"link_id"`
|
|
SourceAgentID string `json:"source_agent_id"`
|
|
SourceAgentKey string `json:"source_agent_key"`
|
|
TargetAgentID string `json:"target_agent_id"`
|
|
TargetAgentKey string `json:"target_agent_key"`
|
|
Direction string `json:"direction"`
|
|
TeamID string `json:"team_id,omitempty"`
|
|
Status string `json:"status"`
|
|
}
|
|
|
|
// AgentLinkUpdatedPayload is emitted when an agent link is updated.
|
|
type AgentLinkUpdatedPayload struct {
|
|
LinkID string `json:"link_id"`
|
|
SourceAgentKey string `json:"source_agent_key"`
|
|
TargetAgentKey string `json:"target_agent_key"`
|
|
Direction string `json:"direction,omitempty"`
|
|
Status string `json:"status,omitempty"`
|
|
Changes []string `json:"changes"`
|
|
}
|
|
|
|
// AgentLinkDeletedPayload is emitted when an agent link is deleted.
|
|
type AgentLinkDeletedPayload struct {
|
|
LinkID string `json:"link_id"`
|
|
SourceAgentKey string `json:"source_agent_key"`
|
|
TargetAgentKey string `json:"target_agent_key"`
|
|
}
|