agent

package
v0.1.2 Latest Latest
Warning

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

Go to latest
Published: Mar 21, 2026 License: GPL-3.0 Imports: 20 Imported by: 0

Documentation

Overview

Package agent manages agent processes with PTY allocation.

pogod spawns each agent with its own PTY. The master file descriptor stays with pogod for interactive access (attach), input injection (nudge), and output monitoring. The slave end becomes the agent process's controlling terminal.

Index

Constants

View Source
const DefaultIdleThreshold = 2 * time.Second

DefaultIdleThreshold is how long the PTY output must be quiet before the agent is considered idle.

View Source
const DefaultNudgeTimeout = 30 * time.Second

DefaultNudgeTimeout is how long to wait for idle before giving up.

Variables

This section is empty.

Functions

func CrewPromptDir

func CrewPromptDir() string

CrewPromptDir is the directory where crew agent prompt files live. Default: ~/.pogo/agents/crew/

func ExpandTemplate

func ExpandTemplate(templatePath string, vars TemplateVars) (string, error)

ExpandTemplate reads a template file and expands {{.Variable}} placeholders with the provided vars. Uses Go text/template syntax.

func ExpandTemplateToFile

func ExpandTemplateToFile(templatePath string, vars TemplateVars) (string, error)

ExpandTemplateToFile expands a template and writes it to a temporary file. The caller is responsible for removing the temp file when done. Returns the path to the generated file.

func InitPromptDirs

func InitPromptDirs() error

InitPromptDirs creates the ~/.pogo/agents/ directory structure.

func ProcessName

func ProcessName(agentType AgentType, name string) string

ProcessName returns the pgrep-discoverable process name for an agent. Crew: pogo-crew-<name>, Polecat: pogo-cat-<name>

func PromptDir

func PromptDir() string

PromptDir returns the root directory for agent prompt files. Default: ~/.pogo/agents/

func ResolveCrewPrompt

func ResolveCrewPrompt(name string) (string, error)

ResolveCrewPrompt returns the path to a crew agent's prompt file. Returns an error if the file does not exist.

func ResolveMayorPrompt

func ResolveMayorPrompt() (string, error)

ResolveMayorPrompt returns the path to the mayor's prompt file. Returns an error if the file does not exist.

func ResolveTemplate

func ResolveTemplate(name string) (string, error)

ResolveTemplate returns the path to a polecat template file. Returns an error if the file does not exist.

func TemplateDir

func TemplateDir() string

TemplateDir returns the directory for polecat prompt templates. Default: ~/.pogo/agents/templates/

Types

type Agent

type Agent struct {
	Name      string      `json:"name"`
	PID       int         `json:"pid"`
	Type      AgentType   `json:"type"`
	StartTime time.Time   `json:"start_time"`
	Command   []string    `json:"command"`
	Status    AgentStatus `json:"status"`

	// ExitTime records when the process exited, for accurate uptime on exited agents.
	ExitTime time.Time `json:"exit_time,omitempty"`

	// ExitCode is set after the process exits (-1 if signaled).
	ExitCode int `json:"exit_code,omitempty"`

	// RestartCount tracks how many times a crew agent has been restarted.
	RestartCount int `json:"restart_count,omitempty"`

	// PromptFile is the path to the agent's prompt file (if any).
	PromptFile string `json:"prompt_file,omitempty"`

	// Dir is the working directory for the agent process.
	Dir string `json:"dir,omitempty"`

	// WorktreeDir is the git worktree path for polecat isolation (cleanup on exit).
	WorktreeDir string `json:"worktree_dir,omitempty"`
	// SourceRepo is the original repo path used to create/remove the worktree.
	SourceRepo string `json:"source_repo,omitempty"`
	// contains filtered or unexported fields
}

Agent represents a running agent process with its PTY.

func (*Agent) Cleanup

func (a *Agent) Cleanup()

Cleanup closes PTY and socket. Exported for use by lifecycle callbacks.

func (*Agent) Done

func (a *Agent) Done() <-chan struct{}

Done returns a channel that closes when the agent process exits.

func (*Agent) ExitErr

func (a *Agent) ExitErr() error

ExitErr returns the process exit error, or nil if still running.

func (*Agent) GetStatus added in v0.1.1

func (a *Agent) GetStatus() AgentStatus

GetStatus returns the agent's current status, safe for concurrent use.

func (*Agent) IsIdle

func (a *Agent) IsIdle(quiescence time.Duration) bool

IsIdle returns true if no output has been written to the agent's PTY for at least the given duration. An agent with no output yet (just spawned) is not considered idle.

func (*Agent) Nudge

func (a *Agent) Nudge(message string) error

Nudge writes a message to an agent's PTY master fd. The agent sees this as typed input.

func (*Agent) NudgeWithMode

func (a *Agent) NudgeWithMode(msg string, mode NudgeMode, timeout time.Duration) error

NudgeWithMode delivers a message to the agent's PTY using the specified mode. In wait-idle mode, it blocks until the agent is idle (or timeout expires). In immediate mode, it writes directly (same as Nudge).

func (*Agent) RecentOutput

func (a *Agent) RecentOutput(n int) []byte

RecentOutput returns the most recent buffered output.

func (*Agent) SocketPath

func (a *Agent) SocketPath() string

SocketPath returns the unix socket path for attach.

func (*Agent) WaitIdle

func (a *Agent) WaitIdle(ctx context.Context, quiescence time.Duration) error

WaitIdle blocks until the agent's PTY output has been quiet for the given threshold, or the context is cancelled. Polls at half the threshold interval.

type AgentInfo

type AgentInfo struct {
	Name         string      `json:"name"`
	PID          int         `json:"pid"`
	Type         AgentType   `json:"type"`
	StartTime    time.Time   `json:"start_time"`
	Command      []string    `json:"command"`
	SocketPath   string      `json:"socket_path"`
	Status       AgentStatus `json:"status"`
	ExitCode     int         `json:"exit_code,omitempty"`
	RestartCount int         `json:"restart_count,omitempty"`
	PromptFile   string      `json:"prompt_file,omitempty"`
	ProcessName  string      `json:"process_name"`
	Uptime       string      `json:"uptime"`
}

AgentInfo is the JSON representation of an agent for the API.

type AgentStatus

type AgentStatus string

AgentStatus represents the current state of an agent.

const (
	StatusRunning    AgentStatus = "running"
	StatusExited     AgentStatus = "exited"
	StatusRestarting AgentStatus = "restarting"
)

type AgentType

type AgentType string

AgentType distinguishes long-running crew agents from ephemeral polecats.

const (
	TypeCrew    AgentType = "crew"
	TypePolecat AgentType = "polecat"
)

type InstallResult

type InstallResult struct {
	Installed []string `json:"installed"`         // files written (new)
	Updated   []string `json:"updated,omitempty"` // files updated (stale)
	Skipped   []string `json:"skipped"`           // files already up-to-date
}

InstallResult describes what happened during prompt installation.

func InstallPrompts

func InstallPrompts(force bool) (*InstallResult, error)

InstallPrompts copies the default prompt files embedded in the binary to ~/.pogo/agents/. Stale files are auto-updated by comparing content hashes. If force is true, all files are overwritten regardless of hash.

type NudgeAPIRequest

type NudgeAPIRequest struct {
	Message string `json:"message"`
	// Mode: "wait-idle" (default) or "immediate".
	Mode string `json:"mode,omitempty"`
	// Timeout in seconds for wait-idle mode. Default: 30.
	Timeout int `json:"timeout,omitempty"`
}

NudgeAPIRequest is the JSON body for POST /agents/:name/nudge.

type NudgeAPIResponse

type NudgeAPIResponse struct {
	Status string `json:"status"` // "delivered" or "not_running"
	Agent  string `json:"agent"`
}

NudgeAPIResponse is returned for wait-idle nudges to report delivery status.

type NudgeMode

type NudgeMode string

NudgeMode controls how a nudge message is delivered.

const (
	// NudgeWaitIdle waits for the agent to be idle before delivering.
	NudgeWaitIdle NudgeMode = "wait-idle"

	// NudgeImmediate writes directly to the PTY without waiting.
	NudgeImmediate NudgeMode = "immediate"
)

type PromptInfo

type PromptInfo struct {
	Name     string `json:"name"`     // File stem (e.g., "arch", "polecat")
	Path     string `json:"path"`     // Full filesystem path
	Category string `json:"category"` // "crew", "templates", or "mayor"
}

PromptInfo describes a discovered prompt file.

func ListPrompts

func ListPrompts() ([]PromptInfo, error)

ListPrompts discovers all prompt files under ~/.pogo/agents/.

type Registry

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

Registry is the in-memory agent registry. Thread-safe.

func NewRegistry

func NewRegistry(socketDir string) (*Registry, error)

NewRegistry creates an agent registry. socketDir is created if needed.

func (*Registry) Get

func (r *Registry) Get(name string) *Agent

Get returns an agent by name, or nil if not found.

func (*Registry) List

func (r *Registry) List() []*Agent

List returns all running agents.

func (*Registry) RegisterHandlers

func (r *Registry) RegisterHandlers(mux *http.ServeMux)

RegisterHandlers registers agent API endpoints on the given mux.

func (*Registry) Remove

func (r *Registry) Remove(name string)

Remove removes an agent from the registry. Does not stop it.

func (*Registry) Respawn

func (r *Registry) Respawn(name string) (*Agent, error)

Respawn restarts a stopped agent in-place, preserving its name and config. Used by crew monitoring to restart crashed agents.

func (*Registry) SetOnExit

func (r *Registry) SetOnExit(fn func(a *Agent, err error))

SetOnExit sets the callback invoked when any agent exits.

func (*Registry) Spawn

func (r *Registry) Spawn(req SpawnRequest) (*Agent, error)

Spawn starts a new agent process with a PTY.

func (*Registry) Stop

func (r *Registry) Stop(name string, timeout time.Duration) error

Stop signals an agent to exit and waits up to timeout for it.

func (*Registry) StopAll

func (r *Registry) StopAll(timeout time.Duration)

StopAll stops all agents.

type RingBuffer

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

RingBuffer is a fixed-size circular buffer for agent output. Thread-safe. When full, old data is overwritten.

func NewRingBuffer

func NewRingBuffer(size int) *RingBuffer

NewRingBuffer creates a ring buffer of the given size.

func (*RingBuffer) Last

func (r *RingBuffer) Last(n int) []byte

Last returns the most recent n bytes of output. Returns fewer bytes if less than n have been written.

func (*RingBuffer) LastWriteTime

func (r *RingBuffer) LastWriteTime() time.Time

LastWriteTime returns the time of the most recent write.

func (*RingBuffer) Len

func (r *RingBuffer) Len() int

Len returns the total number of bytes currently stored.

func (*RingBuffer) Write

func (r *RingBuffer) Write(p []byte) (int, error)

Write appends data to the buffer, overwriting old data if full.

type SpawnAPIRequest

type SpawnAPIRequest struct {
	Name       string    `json:"name"`
	Type       AgentType `json:"type"`
	Command    []string  `json:"command"`
	Env        []string  `json:"env,omitempty"`
	PromptFile string    `json:"prompt_file,omitempty"`
}

SpawnAPIRequest is the JSON body for POST /agents.

type SpawnPolecatAPIRequest

type SpawnPolecatAPIRequest struct {
	Name     string   `json:"name"`           // Agent name (e.g., short ID)
	Template string   `json:"template"`       // Template name (default: "polecat")
	Task     string   `json:"task,omitempty"` // Work item title
	Body     string   `json:"body,omitempty"` // Work item body
	Id       string   `json:"id,omitempty"`   // Work item ID
	Repo     string   `json:"repo,omitempty"` // Target repository path
	Env      []string `json:"env,omitempty"`  // Additional env vars
}

SpawnPolecatAPIRequest is the JSON body for POST /agents/spawn-polecat. Spawns a polecat from a template with variable expansion.

type SpawnRequest

type SpawnRequest struct {
	Name       string
	Type       AgentType
	Command    []string // e.g. ["claude", "--append-system-prompt", "<prompt content>"]
	Env        []string // additional env vars
	PromptFile string   // path to prompt file (optional)
	Dir        string   // working directory for the process (optional)
}

SpawnRequest contains everything needed to spawn an agent.

type StartAPIRequest

type StartAPIRequest struct {
	Name string `json:"name"`
}

StartAPIRequest is the JSON body for POST /agents/start. Starts a crew agent by name, looking up the prompt file automatically.

type TemplateVars

type TemplateVars struct {
	Task string // Work item title
	Body string // Work item body (markdown)
	Id   string // Work item ID
	Repo string // Target repository path
}

TemplateVars holds the variables available during polecat template expansion.

Jump to

Keyboard shortcuts

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