Add task sidebar workflow
This commit is contained in:
+35
-10
@@ -29,7 +29,7 @@ var serverInfo = map[string]any{
|
||||
"version": "0.1.0",
|
||||
}
|
||||
|
||||
// serverInstructions is returned in the MCP `initialize` response. MCP
|
||||
// baseServerInstructions is returned in the MCP `initialize` response. MCP
|
||||
// clients show this to the underlying LLM as context for how to use
|
||||
// the server. Failure modes we've seen and want to head off:
|
||||
// - The agent assumes patterm is something it has to launch (running
|
||||
@@ -45,7 +45,14 @@ var serverInfo = map[string]any{
|
||||
// up as sub-agents and won't be tied into the patterm lifecycle.
|
||||
//
|
||||
// Keep this short — clients vary in how much they surface to the LLM.
|
||||
const serverInstructions = "You are inside patterm. Use these MCP tools; do not launch patterm or poke its Unix socket yourself. Use spawn_agent for sub-agents, close spawned panes when done, and use timer_fire_when_idle_* instead of wait_for_pattern to wait for send_message replies."
|
||||
const baseServerInstructions = "You are inside patterm. Use these MCP tools; do not launch patterm or poke its Unix socket yourself. Use spawn_agent for sub-agents, close spawned panes when done, and use timer_fire_when_idle_* instead of wait_for_pattern to wait for send_message replies."
|
||||
|
||||
func serverInstructions(taskBound bool) string {
|
||||
if !taskBound {
|
||||
return baseServerInstructions
|
||||
}
|
||||
return baseServerInstructions + " This MCP connection is task-bound; call whoami for the task, and register git worktrees you create or use with task_register_worktree."
|
||||
}
|
||||
|
||||
// toolDescriptor is the shape returned by `tools/list`. inputSchema is
|
||||
// a JSON Schema object — we provide a minimal `{type: "object"}` schema
|
||||
@@ -108,7 +115,7 @@ func arrayOfStringsProp(desc string) map[string]any {
|
||||
// toolCatalog is the full list advertised via tools/list. Descriptions
|
||||
// are intentionally short — clients are expected to fetch help() for
|
||||
// detail. Schemas mirror the param structs in tools.go.
|
||||
func toolCatalog(role CallerRole) []toolDescriptor {
|
||||
func toolCatalog(role CallerRole, taskBound bool) []toolDescriptor {
|
||||
tools := []toolDescriptor{
|
||||
{
|
||||
Name: "spawn_agent",
|
||||
@@ -382,6 +389,14 @@ func toolCatalog(role CallerRole) []toolDescriptor {
|
||||
"name": stringProp("Scratchpad name."),
|
||||
}, []string{"name"}),
|
||||
},
|
||||
{
|
||||
Name: "task_register_worktree",
|
||||
Description: "Register a git worktree path for the current task.",
|
||||
InputSchema: objectSchema(map[string]any{
|
||||
"path": stringProp("Absolute path, or path relative to this process working directory."),
|
||||
"branch": stringProp("Git branch name, if known."),
|
||||
}, []string{"path"}),
|
||||
},
|
||||
{
|
||||
Name: "whoami",
|
||||
Description: "Return caller identity, role, parent, and project metadata.",
|
||||
@@ -397,14 +412,15 @@ func toolCatalog(role CallerRole) []toolDescriptor {
|
||||
}, nil),
|
||||
},
|
||||
}
|
||||
if role != RoleSubAgent {
|
||||
return tools
|
||||
}
|
||||
filtered := tools[:0]
|
||||
for _, tool := range tools {
|
||||
if tool.Name != "spawn_agent" {
|
||||
filtered = append(filtered, tool)
|
||||
if role == RoleSubAgent && tool.Name == "spawn_agent" {
|
||||
continue
|
||||
}
|
||||
if !taskBound && tool.Name == "task_register_worktree" {
|
||||
continue
|
||||
}
|
||||
filtered = append(filtered, tool)
|
||||
}
|
||||
return filtered
|
||||
}
|
||||
@@ -426,13 +442,20 @@ func (s *Server) handleProtocolMethod(callerID, method string, params json.RawMe
|
||||
if protoVersion == "" {
|
||||
protoVersion = supportedProtocolVersion
|
||||
}
|
||||
taskBound := false
|
||||
s.mu.Lock()
|
||||
host := s.host
|
||||
s.mu.Unlock()
|
||||
if host != nil {
|
||||
_, taskBound = host.CallerTask(callerID)
|
||||
}
|
||||
result := map[string]any{
|
||||
"protocolVersion": protoVersion,
|
||||
"capabilities": map[string]any{
|
||||
"tools": map[string]any{"listChanged": false},
|
||||
},
|
||||
"serverInfo": serverInfo,
|
||||
"instructions": serverInstructions,
|
||||
"instructions": serverInstructions(taskBound),
|
||||
}
|
||||
return result, true, 0, "", nil
|
||||
|
||||
@@ -446,13 +469,15 @@ func (s *Server) handleProtocolMethod(callerID, method string, params json.RawMe
|
||||
|
||||
case "tools/list":
|
||||
role := RoleOrchestrator
|
||||
taskBound := false
|
||||
s.mu.Lock()
|
||||
host := s.host
|
||||
s.mu.Unlock()
|
||||
if host != nil {
|
||||
role = host.CallerRole(callerID)
|
||||
_, taskBound = host.CallerTask(callerID)
|
||||
}
|
||||
return map[string]any{"tools": toolCatalog(role)}, true, 0, "", nil
|
||||
return map[string]any{"tools": toolCatalog(role, taskBound)}, true, 0, "", nil
|
||||
|
||||
case "tools/call":
|
||||
var p struct {
|
||||
|
||||
Reference in New Issue
Block a user