mirror of
https://github.com/tiennm99/goclaw.git
synced 2026-06-11 10:10:53 +00:00
97cacfe68b
- Fix progress event payload missing TaskNumber, Subject, OwnerAgentKey, ProgressPercent, ProgressStep — notifications were rendering empty - Fix progress notification format to include task name (consistent with dispatched/failed) and guard empty ProgressStep - Change percent tool schema from number to integer for clarity - Add pre-run member task reminder injecting task context before LLM loop - Add mid-loop progress nudge every 10 iterations with suggested percent based on iteration ratio (handles maxIter=0 unlimited case) - Enhance leader cross-session reminder to show progress % when available - Strengthen TEAM.md member guidance: focus, result quality, progress rules - Add progress bar to task list table view (matches kanban card pattern)
157 lines
5.5 KiB
Go
157 lines
5.5 KiB
Go
package tools
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
)
|
|
|
|
// TeamTasksTool exposes the shared team task list to agents.
|
|
// Actions: list, get, create, claim, complete, cancel, search, review, comment, progress, attach, update.
|
|
type TeamTasksTool struct {
|
|
manager *TeamToolManager
|
|
}
|
|
|
|
func NewTeamTasksTool(manager *TeamToolManager) *TeamTasksTool {
|
|
return &TeamTasksTool{manager: manager}
|
|
}
|
|
|
|
func (t *TeamTasksTool) Name() string { return "team_tasks" }
|
|
|
|
func (t *TeamTasksTool) Description() string {
|
|
return "Manage the shared team task list (create, claim, complete, track progress). See TEAM.md for available actions and team context."
|
|
}
|
|
|
|
func (t *TeamTasksTool) Parameters() map[string]any {
|
|
return map[string]any{
|
|
"type": "object",
|
|
"properties": map[string]any{
|
|
"action": map[string]any{
|
|
"type": "string",
|
|
"description": "'list', 'get', 'create', 'claim', 'complete', 'cancel', 'approve', 'reject', 'search', 'review', 'comment', 'progress', 'attach', 'update', 'ask_user', or 'clear_ask_user'. " +
|
|
"ask_user: set a periodic reminder that is sent to the USER (not the team) when you need the user's input/decision to continue (e.g. 'Which design do you prefer?'). ONLY use when you have a question for the user. Do NOT use for status updates, waiting for teammates, or notifications — use 'progress' instead. " +
|
|
"clear_ask_user: cancel a previously set ask_user reminder. " +
|
|
"retry: re-dispatch a stale or failed task.",
|
|
},
|
|
"task_id": map[string]any{
|
|
"type": "string",
|
|
"description": "Task UUID (required for most actions except list, create, search). When working on a dispatched task, this is auto-resolved from context — you can omit it for complete/progress/comment.",
|
|
},
|
|
"subject": map[string]any{
|
|
"type": "string",
|
|
"description": "Task subject (required for create, optional for update)",
|
|
},
|
|
"description": map[string]any{
|
|
"type": "string",
|
|
"description": "Task description (for create or update)",
|
|
},
|
|
"result": map[string]any{
|
|
"type": "string",
|
|
"description": "Result summary (required for complete)",
|
|
},
|
|
"text": map[string]any{
|
|
"type": "string",
|
|
"description": "Text content: comment text, cancel/reject reason, progress update, or ask_user reminder question (must be a question asking the user for input/decision)",
|
|
},
|
|
"status": map[string]any{
|
|
"type": "string",
|
|
"description": "Filter for list: '' (all, default), 'active', 'completed', 'in_review'",
|
|
},
|
|
"query": map[string]any{
|
|
"type": "string",
|
|
"description": "Search query for action=search",
|
|
},
|
|
"priority": map[string]any{
|
|
"type": "number",
|
|
"description": "Priority, higher = more important (for create, default 0)",
|
|
},
|
|
"blocked_by": map[string]any{
|
|
"type": "array",
|
|
"items": map[string]any{"type": "string"},
|
|
"description": "Task IDs that must complete first (for create/update)",
|
|
},
|
|
"require_approval": map[string]any{
|
|
"type": "boolean",
|
|
"description": "Require user approval before claim (for create, default false)",
|
|
},
|
|
"percent": map[string]any{
|
|
"type": "integer",
|
|
"description": "Progress percentage 0-100 (for progress action)",
|
|
},
|
|
"file_id": map[string]any{
|
|
"type": "string",
|
|
"description": "Workspace file ID (for attach)",
|
|
},
|
|
"assignee": map[string]any{
|
|
"type": "string",
|
|
"description": "Agent key to assign task to (REQUIRED for create). Auto-dispatches to that team member.",
|
|
},
|
|
"page": map[string]any{
|
|
"type": "number",
|
|
"description": "Page number for list/search (default 1, 30 per page)",
|
|
},
|
|
},
|
|
"required": []string{"action"},
|
|
}
|
|
}
|
|
|
|
// v2Actions lists team_tasks actions that require team version >= 2.
|
|
var v2Actions = map[string]bool{
|
|
"approve": true, "reject": true, "review": true, "comment": true,
|
|
"progress": true, "attach": true, "update": true,
|
|
"ask_user": true, "clear_ask_user": true, "retry": true,
|
|
}
|
|
|
|
func (t *TeamTasksTool) Execute(ctx context.Context, args map[string]any) *Result {
|
|
action, _ := args["action"].(string)
|
|
|
|
// Gate v2-only actions: resolve team once and check version.
|
|
if v2Actions[action] {
|
|
team, _, err := t.manager.resolveTeam(ctx)
|
|
if err != nil {
|
|
return ErrorResult(err.Error())
|
|
}
|
|
if !IsTeamV2(team) {
|
|
return ErrorResult(fmt.Sprintf("action '%s' requires team version 2 — upgrade in team settings", action))
|
|
}
|
|
}
|
|
|
|
switch action {
|
|
case "list":
|
|
return t.executeList(ctx, args)
|
|
case "get":
|
|
return t.executeGet(ctx, args)
|
|
case "create":
|
|
return t.executeCreate(ctx, args)
|
|
case "claim":
|
|
return t.executeClaim(ctx, args)
|
|
case "complete":
|
|
return t.executeComplete(ctx, args)
|
|
case "cancel":
|
|
return t.executeCancel(ctx, args)
|
|
case "approve":
|
|
return t.executeApprove(ctx, args)
|
|
case "reject":
|
|
return t.executeReject(ctx, args)
|
|
case "search":
|
|
return t.executeSearch(ctx, args)
|
|
case "review":
|
|
return t.executeReview(ctx, args)
|
|
case "comment":
|
|
return t.executeComment(ctx, args)
|
|
case "progress":
|
|
return t.executeProgress(ctx, args)
|
|
case "attach":
|
|
return t.executeAttach(ctx, args)
|
|
case "update":
|
|
return t.executeUpdate(ctx, args)
|
|
case "ask_user":
|
|
return t.executeAskUser(ctx, args)
|
|
case "clear_ask_user":
|
|
return t.executeClearAskUser(ctx, args)
|
|
case "retry":
|
|
return t.executeRetry(ctx, args)
|
|
default:
|
|
return ErrorResult(fmt.Sprintf("unknown action: %s (use list, get, create, claim, complete, cancel, search, review, comment, progress, attach, update, ask_user, clear_ask_user, or retry)", action))
|
|
}
|
|
}
|