Add task sidebar workflow

This commit is contained in:
2026-06-24 12:28:56 +01:00
parent 45263d59f8
commit d133839194
33 changed files with 1890 additions and 134 deletions
+38
View File
@@ -60,6 +60,7 @@ type ToolHost interface {
// callers default to RoleOrchestrator (treated as a top-level peer)
// so they don't get silently denied.
CallerRole(processID string) CallerRole
CallerTask(processID string) (TaskInfo, bool)
// Lifecycle (SPEC §7).
SpawnAgent(callerID string, args SpawnAgentArgs) (ProcessInfo, error)
@@ -102,6 +103,7 @@ type ToolHost interface {
ScratchpadWrite(name, content, expectedRevision string) (revision string, err error)
ScratchpadAppend(name, content string) error
ScratchpadDelete(name string) error
RegisterTaskWorktree(callerID string, args TaskRegisterWorktreeArgs) (TaskInfo, error)
// Meta.
WhoAmI(callerID string, includeTools bool) WhoAmI
@@ -153,6 +155,7 @@ type Cursor struct {
type ProjectStatus struct {
Project ProjectMeta `json:"project"`
Caller WhoAmI `json:"caller"`
Task *TaskInfo `json:"task,omitempty"`
Processes []ProcessInfo `json:"processes"`
Scratchpads []scratchpad.Entry `json:"scratchpads"`
}
@@ -167,6 +170,26 @@ type ProjectMeta struct {
Key string `json:"key"`
}
type TaskInfo struct {
ID string `json:"id"`
Title string `json:"title"`
CreatedAt string `json:"created_at,omitempty"`
UpdatedAt string `json:"updated_at,omitempty"`
Worktrees []TaskWorktree `json:"worktrees,omitempty"`
}
type TaskWorktree struct {
Path string `json:"path"`
Branch string `json:"branch,omitempty"`
CreatedByProcessID string `json:"created_by_process_id,omitempty"`
RegisteredAt string `json:"registered_at,omitempty"`
}
type TaskRegisterWorktreeArgs struct {
Path string `json:"path"`
Branch string `json:"branch,omitempty"`
}
// ProcessOutput is the get_process_output payload. By default it is
// canonical text with light metadata; include_meta restores screen
// geometry + version, and raw requests return stream bytes.
@@ -341,6 +364,7 @@ type WhoAmI struct {
Role CallerRole `json:"role"`
ParentProcessID string `json:"parent_process_id,omitempty"`
Project ProjectMeta `json:"project"`
Task *TaskInfo `json:"task,omitempty"`
AvailableTools []string `json:"available_tools"`
}
@@ -836,6 +860,20 @@ func callTool(h ToolHost, callerID, method string, params json.RawMessage) (any,
}
return map[string]any{"ok": true}, 0, "", nil
case "task_register_worktree":
if _, ok := h.CallerTask(callerID); !ok {
return nil, codeRoleForbidden, "task_register_worktree: caller is not attached to a task", structuredKind(ErrorKindRoleForbidden)
}
var p TaskRegisterWorktreeArgs
if err := unmarshalParams(params, &p); err != nil {
return nil, codeInvalidParams, err.Error(), nil
}
if p.Path == "" {
return nil, codeInvalidParams, "task_register_worktree: path required", nil
}
info, err := h.RegisterTaskWorktree(callerID, p)
return mapToolResult(info, err)
case "whoami":
var p WhoAmIArgs
_ = unmarshalParamsOptional(params, &p)