subagent

package
v0.0.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Mar 17, 2026 License: MIT Imports: 12 Imported by: 0

Documentation

Index

Constants

View Source
const DefaultPoolSize = 5

DefaultPoolSize is the default maximum number of concurrent subagents.

Variables

View Source
var AgentTypes = map[string]AgentTypeDef{
	"explore": {
		Role:     "smol",
		Worktree: false,
		Instruction: `You are an exploration agent. Your job is to quickly find and return specific information from the codebase.

Strategy — work top-down, stop as soon as you have the answer:
1. Orient: run tree (depth 2-3) or ls to understand project layout.
2. Narrow: use grep/find to locate the exact files, functions, or types relevant to the query.
3. Read: read only the relevant sections (use offset/limit for large files).
4. Answer: return a concise, structured answer — file paths, line numbers, code snippets, and a short explanation.

Rules:
- Never read entire large files — target the specific section you need.
- Prefer grep over reading files sequentially. Search for symbols, strings, types, and patterns.
- If one search doesn't find it, try alternative names, casing, or patterns — don't give up after one attempt.
- Limit output to what the caller needs. No filler, no preamble, no restating the question.
- Include file:line references so the caller can jump to the source.
- If the answer requires understanding multiple files, summarize the relationship between them.`,
		Tools: []string{"read", "grep", "find", "tree", "ls"},
	},
	"plan": {
		Role:     "plan",
		Worktree: false,
		Instruction: `You are a planning agent. Analyze the codebase and create detailed implementation plans.

Strategy:
1. Orient: tree/ls to understand project structure, then grep to find the modules relevant to the task.
2. Read key files: focus on interfaces, types, and entry points — not every line of implementation.
3. Plan: produce a numbered step-by-step plan with file:line references. For each step, specify what changes and why.
4. Flag risks: note trade-offs, edge cases, and dependencies between steps.

Keep plans actionable — each step should be a single, testable change.`,
		Tools: []string{"read", "grep", "find", "tree", "ls", "git-overview"},
	},
	"designer": {
		Role:     "slow",
		Worktree: true,
		Instruction: `You are a design agent working in an isolated worktree. Create and modify code following established patterns.

Workflow:
1. Read the existing code around your change point — grep for the symbol, read the relevant section.
2. Match the project's style: naming, error handling, file organization, test patterns.
3. Implement the change using edit for existing files, write only for new files.
4. Run bash to build/compile and verify no errors. Fix any issues before finishing.
5. Return a summary: what changed, file:line references, and build status.

Rules:
- Write clean, idiomatic code that looks like a human wrote it in the style of this project.
- One logical change per edit — do not combine unrelated modifications.
- No dead code, no commented-out code, no TODO placeholders unless explicitly requested.`,
		Tools: []string{"read", "write", "edit", "grep", "find", "tree", "ls", "bash"},
	},
	"reviewer": {
		Role:     "slow",
		Worktree: false,
		Instruction: `You are a code review agent. Examine changes for bugs, correctness, and style issues.

Workflow:
1. Use git-overview to see what changed. Use git-file-diff and git-hunk for details.
2. Read surrounding context with grep/read to understand intent.
3. Check: correctness, error handling, edge cases, naming, test coverage.
4. Report findings as a structured list: file:line, severity (bug/warning/nit), description, suggested fix.

Focus on what matters — bugs and correctness first, style nits last. Be constructive.`,
		Tools: []string{"read", "grep", "find", "git-overview", "git-file-diff", "git-hunk"},
	},
	"task": {
		Role:     "default",
		Worktree: true,
		Instruction: `You are a task execution agent working in an isolated worktree. Complete the assigned coding task end-to-end.

Workflow:
1. Understand: grep for the relevant code, read the targeted sections. Do not read unrelated files.
2. Implement: make the smallest correct change. Edit existing files, match existing patterns.
3. Verify: run bash to build/compile after each edit. Run tests if they exist. Fix failures immediately.
4. Complete: return what you changed (file:line), build/test status, and any notes.

Rules:
- One change at a time — edit, build, confirm, then move to the next.
- If the build fails, read the error, fix the cause, rebuild. Do not retry blindly.
- Match the project's style exactly — naming, error handling, imports, test structure.
- Keep changes minimal. Do not refactor or "improve" untouched code.`,
		Tools: []string{"read", "write", "edit", "bash", "grep", "find", "tree", "ls", "git-overview"},
	},
	"quick_task": {
		Role:     "smol",
		Worktree: false,
		Instruction: `You are a quick task agent. Complete small, focused tasks with minimal overhead.

Workflow:
1. grep to find the exact location to change.
2. Read only the lines you need.
3. Make the edit. Run bash to verify it compiles.
4. Return: what changed, file:line, build status.

Rules:
- Absolute minimum changes — touch only what is necessary.
- No exploration beyond what the task requires.
- If the task is ambiguous, do the simplest reasonable interpretation.`,
		Tools: []string{"read", "write", "edit", "bash", "grep", "find"},
	},
}

AgentTypes maps type names to their definitions.

Functions

func ValidateType

func ValidateType(typeName string) error

ValidateType checks if the given type name is a known agent type.

Types

type AgentInput

type AgentInput struct {
	Type        string `json:"type"`                   // Agent type name
	Prompt      string `json:"prompt"`                 // Task prompt for the agent
	Worktree    *bool  `json:"worktree,omitempty"`     // Override worktree setting
	WorkDir     string `json:"work_dir,omitempty"`     // Override working directory (e.g. existing worktree path)
	Background  bool   `json:"background,omitempty"`   // Run in background
	SkipCleanup bool   `json:"skip_cleanup,omitempty"` // Don't auto-cleanup worktree on completion
}

AgentInput is the input to spawn a subagent.

type AgentOutput

type AgentOutput struct {
	AgentID  string `json:"agent_id"`
	Type     string `json:"type"`
	Result   string `json:"result"`
	Error    string `json:"error,omitempty"`
	Duration string `json:"duration"`
}

AgentOutput is the result of a completed subagent.

type AgentStatus

type AgentStatus struct {
	AgentID   string    `json:"agent_id"`
	Type      string    `json:"type"`
	Status    string    `json:"status"` // "running", "completed", "failed", "cancelled"
	Prompt    string    `json:"prompt"`
	StartedAt time.Time `json:"started_at"`
	Duration  string    `json:"duration,omitempty"`
}

AgentStatus represents the current state of a subagent.

type AgentTypeDef

type AgentTypeDef struct {
	Role        string   // Config role name for model resolution
	Worktree    bool     // Whether this type runs in an isolated git worktree
	Instruction string   // System instruction for the subagent
	Tools       []string // Tool names available to this type
}

AgentTypeDef defines the configuration for a subagent type.

type Event

type Event struct {
	Type    string `json:"type"`              // "text_delta", "tool_call", "tool_result", "message_end", "error"
	Content string `json:"content,omitempty"` // Text content for text_delta
	Error   string `json:"error,omitempty"`   // Error message for error events
}

Event is a streaming event from a subagent process.

type Orchestrator

type Orchestrator struct {
	// contains filtered or unexported fields
}

Orchestrator composes Pool, Spawner, and WorktreeManager to manage subagent lifecycle.

func NewOrchestrator

func NewOrchestrator(cfg *config.Config, repoRoot string) *Orchestrator

NewOrchestrator creates an Orchestrator from config. repoRoot is the git repository root (empty string disables worktree support).

func (*Orchestrator) Cancel

func (o *Orchestrator) Cancel(agentID string) error

Cancel cancels a running agent by ID.

func (*Orchestrator) List

func (o *Orchestrator) List() []AgentStatus

List returns the status of all tracked agents.

func (*Orchestrator) Shutdown

func (o *Orchestrator) Shutdown()

Shutdown cancels all running agents and cleans up worktrees.

func (*Orchestrator) Spawn

func (o *Orchestrator) Spawn(ctx context.Context, input AgentInput) (<-chan Event, string, error)

Spawn starts a new subagent and returns an event channel. It acquires a pool slot, optionally creates a worktree, and spawns the pi process.

func (*Orchestrator) Worktree

func (o *Orchestrator) Worktree() *WorktreeManager

Worktree returns the WorktreeManager (may be nil if worktrees are disabled).

type Pool

type Pool struct {
	// contains filtered or unexported fields
}

Pool manages concurrency for subagent processes using a buffered channel semaphore.

func NewPool

func NewPool(maxConcurrent int) *Pool

NewPool creates a concurrency pool that allows at most maxConcurrent active agents.

func (*Pool) Acquire

func (p *Pool) Acquire(ctx context.Context) error

Acquire blocks until a slot is available or the context is cancelled.

func (*Pool) Available

func (p *Pool) Available() int

Available returns the number of currently available slots.

func (*Pool) Release

func (p *Pool) Release()

Release returns a slot to the pool. Must be called after Acquire.

func (*Pool) Size

func (p *Pool) Size() int

Size returns the maximum concurrency limit.

type Process

type Process struct {
	// contains filtered or unexported fields
}

Process represents a running subagent pi process.

func (*Process) Cancel

func (p *Process) Cancel()

Cancel kills the subagent process.

func (*Process) Events

func (p *Process) Events() <-chan Event

Events returns a channel that receives streaming events from the subagent. The channel is closed when the process exits.

func (*Process) Wait

func (p *Process) Wait() (string, error)

Wait blocks until the process exits and returns the accumulated result or an error.

type SpawnOpts

type SpawnOpts struct {
	AgentID     string // Unique ID for this agent
	Model       string // Model name to use
	WorkDir     string // Working directory for the process
	Prompt      string // Task prompt to send
	Instruction string // System instruction for the subagent
}

SpawnOpts holds options for spawning a subagent process.

type Spawner

type Spawner struct {
	// PiBinary is the path to the pi binary. Defaults to "pi" (from PATH).
	PiBinary string
}

Spawner creates and manages subagent pi processes.

func NewSpawner

func NewSpawner(piBinary string) *Spawner

NewSpawner creates a new Spawner. If piBinary is empty, uses "pi" from PATH.

func (*Spawner) Spawn

func (s *Spawner) Spawn(ctx context.Context, opts SpawnOpts) (*Process, error)

Spawn starts a pi subprocess in JSON mode and returns a Process handle for streaming events.

type WorktreeManager

type WorktreeManager struct {
	// contains filtered or unexported fields
}

WorktreeManager manages git worktrees for isolated subagent execution.

func NewWorktreeManager

func NewWorktreeManager(repoRoot string) *WorktreeManager

NewWorktreeManager creates a new WorktreeManager rooted at the given git repo.

func (*WorktreeManager) Active

func (m *WorktreeManager) Active() int

Active returns the number of active worktrees.

func (*WorktreeManager) Cleanup

func (m *WorktreeManager) Cleanup(agentID string) error

Cleanup removes the worktree and branch for the given agent ID. After CleanupAll has started (closed=true), late Cleanup calls are no-ops — CleanupAll owns all remaining entries at that point.

func (*WorktreeManager) CleanupAll

func (m *WorktreeManager) CleanupAll() error

CleanupAll removes all active worktrees. Used during shutdown. It sets the closed flag to reject late Cleanup calls from completion goroutines, waits for in-flight cleanups, then retries remaining entries up to maxPasses.

func (*WorktreeManager) Create

func (m *WorktreeManager) Create(agentID string) (string, error)

Create creates a new git worktree for the given agent ID. Returns the filesystem path to the worktree.

func (*WorktreeManager) MergeBack

func (m *WorktreeManager) MergeBack(agentID string) (string, error)

MergeBack merges the worktree branch back into the current branch of the main worktree. Returns the merge output.

func (*WorktreeManager) PathFor

func (m *WorktreeManager) PathFor(agentID string) string

PathFor returns the worktree path for the given agent ID, or empty string if none.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL