Help us shape the future of Go! Take the 2026 Go Developer Survey

agent

package
v2.0.0 Latest Latest
Warning

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

Go to latest
Published: Oct 9, 2026 License: MIT Imports: 40 Imported by: 0

Documentation

Index

Constants

View Source
const (
	StatusRunning           = "running"
	StatusCompleted         = "completed"
	StatusFailed            = "failed"
	StatusMaxTurnsReached   = "max_turns_reached"
	StatusNoProgressStopped = "no_progress_stopped"
	StatusCancelled         = "cancelled"
)
View Source
const (
	PhasePlanning     = "planning"
	PhaseExecution    = "execution"
	PhaseVerification = "verification"
)
View Source
const (
	PlanStatusPending    = "pending"
	PlanStatusInProgress = "in_progress"
	PlanStatusCompleted  = "completed"
)

Variables

View Source
var ErrGoalBlocked = errors.New("goal blocked by a UserPromptSubmit hook")

ErrGoalBlocked matches (errors.Is) a goal a UserPromptSubmit hook blocked: a deny, or a hook that failed. The error's text adds the hook's reason.

Functions

func KeepTurnStats

func KeepTurnStats(m map[int]TurnStats, st TurnStats)

KeepTurnStats stores st as its turn's stats for a progress display, unless it is a reply a stream rule dropped (2.0 W3): that turn re-runs, and the re-run's stats are the ones to show.

func SmallModelSummarizer

func SmallModelSummarizer(base *llm.Config, model string) compact.SummarizeFunc

SmallModelSummarizer returns a SummarizeFunc on its own client for the small-model role, so summaries don't disturb the agent client's system prompt or tools. The client is base.Plain(): a summary always sends its own system prompt, whatever the run's persona and xAI settings are.

func WatchdogOracle

func WatchdogOracle(cfg *config.Config, workspace string, logf func(string)) decide.Oracle

WatchdogOracle is the oracle the config names for the watchdog ballot, or nil (the heuristic) when the watchdog is off: no key is read and no notice printed for a feature that is not on. oracle "llm" asks the small model on a client of its own, one call at a time, so a background ballot never shares a client with a compaction summary. That client is a plain completion (no xAI collections or features). workspace makes paths in what the oracle sends workspace-relative (jev.RedactPaths). The chat, MCP chat and agent runs share it.

Types

type BenchmarkCase

type BenchmarkCase struct {
	Name           string   `json:"name"`
	Goal           string   `json:"goal"`
	Iterations     int      `json:"iterations,omitempty"`
	MaxTurns       int      `json:"max_turns,omitempty"`
	MustContain    []string `json:"must_contain,omitempty"`
	MustNotContain []string `json:"must_not_contain,omitempty"`
	VerifyCommands []string `json:"verify_commands,omitempty"`
}

type BenchmarkReport

type BenchmarkReport struct {
	SuiteName   string            `json:"suite_name"`
	GeneratedAt time.Time         `json:"generated_at"`
	TotalCases  int               `json:"total_cases"`
	PassedCases int               `json:"passed_cases"`
	FailedCases int               `json:"failed_cases"`
	Results     []BenchmarkResult `json:"results"`
}

type BenchmarkResult

type BenchmarkResult struct {
	CaseName          string   `json:"case_name"`
	Iterations        int      `json:"iterations"`
	PassedIterations  int      `json:"passed_iterations"`
	FailedIterations  int      `json:"failed_iterations"`
	PassRate          float64  `json:"pass_rate"`
	AverageTurns      float64  `json:"average_turns"`
	AverageToolCalls  float64  `json:"average_tool_calls"`
	AverageDurationMS float64  `json:"average_duration_ms"`
	LastStatus        string   `json:"last_status"`
	FailureReasons    []string `json:"failure_reasons,omitempty"`
}

type BenchmarkSuite

type BenchmarkSuite struct {
	Name       string          `json:"name,omitempty"`
	Iterations int             `json:"iterations,omitempty"`
	Cases      []BenchmarkCase `json:"cases"`
}

func LoadBenchmarkSuite

func LoadBenchmarkSuite(path string) (BenchmarkSuite, error)

type CheckpointStore

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

func NewCheckpointStore

func NewCheckpointStore(baseDir string) (*CheckpointStore, error)

func (*CheckpointStore) List

func (s *CheckpointStore) List(limit int) ([]RunSummary, error)

func (*CheckpointStore) Load

func (s *CheckpointStore) Load(runID string) (*RunState, error)

func (*CheckpointStore) Save

func (s *CheckpointStore) Save(state *RunState) error

type EvalCase

type EvalCase struct {
	Name           string   `json:"name"`
	Goal           string   `json:"goal"`
	MaxTurns       int      `json:"max_turns,omitempty"`
	MustContain    []string `json:"must_contain,omitempty"`
	MustNotContain []string `json:"must_not_contain,omitempty"`
}

func LoadEvalCases

func LoadEvalCases(path string) ([]EvalCase, error)

type EvalResult

type EvalResult struct {
	CaseName string
	RunID    string
	Status   string
	Passed   bool
	Reason   string
}

type EvalSuite

type EvalSuite struct {
	Cases []EvalCase `json:"cases"`
}

type Options

type Options struct {
	Workspace                     string        `json:"workspace"`
	MaxTurns                      int           `json:"max_turns"`
	MaxToolCallsPerTurn           int           `json:"max_tool_calls_per_turn"`
	MaxConsecutiveNoToolTurns     int           `json:"max_consecutive_no_tool_turns"`
	MaxConsecutiveInvalidToolArgs int           `json:"max_consecutive_invalid_tool_args"`
	RequestTimeout                time.Duration `json:"request_timeout"`
	ToolTimeout                   time.Duration `json:"tool_timeout"`
	RequireCompletionMarker       bool          `json:"require_completion_marker"`
	CompletionMarker              string        `json:"completion_marker"`
	EnablePlanning                bool          `json:"enable_planning"`
	PlanMaxSteps                  int           `json:"plan_max_steps"`
	RequireVerification           bool          `json:"require_verification"`
	// RequestTimeoutExplicit records that RequestTimeout was set deliberately by
	// the caller, so NewRunner must not raise it for conductor models. Same
	// contract as PlanningExplicit below.
	RequestTimeoutExplicit bool `json:"-"`
	// MaxTurnsExplicit records that MaxTurns was set deliberately (agent
	// --max-turns), so Resume applies it over the run's saved limit: a run
	// that hit max_turns_reached can continue under a larger cap. Not
	// serialised, like the other *Explicit fields.
	MaxTurnsExplicit bool `json:"-"`
	// PlanningExplicit records that EnablePlanning was set deliberately by the
	// caller, so NewRunner must not override it for conductor models. Not
	// serialised: it describes how this run was launched, not its state.
	PlanningExplicit bool `json:"-"`
	// VerificationExplicit is the same guarantee for RequireVerification.
	VerificationExplicit bool          `json:"-"`
	VerificationCommands []string      `json:"verification_commands,omitempty"`
	VerifyTimeout        time.Duration `json:"verify_timeout"`
	// Model overrides the LLM model for this run (the model-router seam). Empty
	// uses cfg.Model. Agent/orchestrate/subagent callers set this to
	// cfg.ResolveAgentModel() so agent work can use a tool-capable/reasoning model.
	Model string `json:"model,omitempty"`
	// AutoApproveTools runs the permission checker in Trust mode (allow all).
	// Set for subagents, which are headless and would otherwise deny every
	// write/exec tool ("Ask" with no prompt). Spawning the subagent is the
	// approval. Never set for the interactive main agent.
	AutoApproveTools bool `json:"auto_approve_tools"`
	// Sliders overrides slider.json for this run's voice modulation (a
	// subagent's persona override). Nil uses slider.json.
	Sliders *config.SliderConfig `json:"-"`
	// ExtraTools are registered on the run's own registry before ToolFilter
	// applies (a typed subagent's submit_result, 2.0 W4e).
	ExtraTools []tools.Tool `json:"-"`
	// ToolFilter, when set, keeps only the tools it accepts in the run's own
	// registry (Registry.Retain); a call to any other tool fails as unknown.
	// The parent's registry is never touched. Typed subagents set it (2.0 W4e).
	ToolFilter func(tools.Tool) bool `json:"-"`
	// PersonaLevel is the system prompt's persona level: empty is agent
	// mode's profile (spine, stepped down on a small window, W5); the
	// explore and review subagent types and orchestrator lanes set
	// prompts.PersonaOff (identity, honesty rule and voice boundary). The
	// agent contract stays.
	PersonaLevel prompts.PersonaLevel `json:"-"`
	// PromptFunc asks the user to approve a tool the permission policy
	// resolves to Ask. The TUI's /agent sets it to its permission modal (#172);
	// without it, Ask means deny.
	PromptFunc tools.PromptFunc `json:"-"`
	// Nested marks a runner started by another run (a subagent, an
	// orchestrator lane, the TUI's /agent). It skips SessionStart and Stop
	// hooks, which belong to the top-level run; a subagent fires
	// SubagentStop instead (AgentID).
	Nested bool `json:"-"`
	// AgentID names a subagent for SubagentStop hooks: the ID spawn_agent
	// returned, kept across a resume. A Nested runner with an AgentID fires
	// SubagentStop when it finishes as completed; one without (an
	// orchestrator lane, /agent) fires neither.
	AgentID string `json:"-"`
	// CheckGoal runs the goal through UserPromptSubmit once, before any
	// model call (2.0 F2e): set where the goal is the user's own text
	// (celeste agent, MCP mode:"agent", /agent). A blocked goal ends RunGoal
	// with ErrGoalBlocked. Subagents and orchestrator lanes leave it false:
	// a model wrote their goal. Resume never re-checks.
	CheckGoal bool `json:"-"`
	// Warn receives setup and hook warnings. Nil writes them to errOut.
	Warn func(string) `json:"-"`
	// ParentEnv, when set, is the environment of the run that started this
	// one (the subagent manager's or an orchestrator run's loop.Parent, or a
	// Setup Env). NewRunner builds its Env with ParentEnv.Nested instead of
	// loop.Setup, sharing MCP clients, hooks and the code graph, and the run
	// is Nested. The runner never closes ParentEnv; its owner does.
	ParentEnv loop.Nester `json:"-"`
	// ResumeRunID is the run a Resume will continue: its ID, not a new
	// one, names the run's session (hooks' session_id and file
	// checkpoints, 2.0 F4). Ignored with ParentEnv (the parent's session).
	ResumeRunID string `json:"-"`
	// Client, when set, is used instead of building an llm.Client from the
	// config. Tests inject a client around a fake backend (2.0 F1).
	Client *llm.Client `json:"-"`
	// FailOnBlockedTools makes NewRunner refuse to start when the policy would
	// send a mutating tool to an approval prompt that does not exist. Set by the
	// `celeste agent` CLI, which can offer -auto-approve as the remedy. Other
	// callers (TUI /agent, orchestrator) leave it false so this does not change
	// their behaviour; they share the same underlying gap, tracked separately.
	FailOnBlockedTools bool   `json:"fail_on_blocked_tools"`
	EmitArtifacts      bool   `json:"emit_artifacts"`
	ArtifactDir        string `json:"artifact_dir,omitempty"`
	DisableCheckpoints bool   `json:"disable_checkpoints"`
	Verbose            bool   `json:"verbose"`
	// OnProgress is an optional callback invoked at key agent events.
	// text is a human-readable label. turn/maxTurns are 0 for non-turn events.
	// This field is not serialised to JSON (func types are not JSON-safe).
	OnProgress func(kind ProgressKind, text string, turn, maxTurns int) `json:"-"`
	// OnTurnStats is an optional callback fired after each LLM API call completes.
	// It carries timing and token usage data for that call.
	OnTurnStats func(TurnStats) `json:"-"`
}

func DefaultOptions

func DefaultOptions() Options

DefaultOptions leaves RequestTimeout at 0, "the request cap": NewRunner sets it from the profile's timeout unless it was set explicitly, and normalizeOptions falls back to the cap of the default stall timeout.

type PlanStep

type PlanStep struct {
	Index  int    `json:"index"`
	Title  string `json:"title"`
	Status string `json:"status"`
}

type ProgressKind

type ProgressKind int

ProgressKind identifies an agent progress event.

const (
	ProgressTurnStart ProgressKind = iota
	ProgressToolCall
	ProgressStepDone
	ProgressResponse
	ProgressComplete
	ProgressError
)

type RunState

type RunState struct {
	RunID                      string              `json:"run_id"`
	Goal                       string              `json:"goal"`
	Status                     string              `json:"status"`
	CreatedAt                  time.Time           `json:"created_at"`
	UpdatedAt                  time.Time           `json:"updated_at"`
	CompletedAt                *time.Time          `json:"completed_at,omitempty"`
	Turn                       int                 `json:"turn"`
	ConsecutiveNoToolTurns     int                 `json:"consecutive_no_tool_turns"`
	ConsecutiveInvalidToolArgs int                 `json:"consecutive_invalid_tool_args"`
	ToolCallCount              int                 `json:"tool_call_count"`
	Messages                   []tui.ChatMessage   `json:"messages"`
	Steps                      []Step              `json:"steps"`
	Phase                      string              `json:"phase"`
	Plan                       []PlanStep          `json:"plan,omitempty"`
	ActivePlanStep             int                 `json:"active_plan_step,omitempty"`
	Verification               []VerificationCheck `json:"verification,omitempty"`
	LastAssistantResponse      string              `json:"last_assistant_response,omitempty"`
	ArtifactBundlePath         string              `json:"artifact_bundle_path,omitempty"`
	Error                      string              `json:"error,omitempty"`
	// StopReason is the loop's reason when a guard stopped the run
	// ("identical", "progress", "invalid_args"); empty otherwise.
	StopReason string `json:"stop_reason,omitempty"`
	// GateVetoes counts completions the gate rejected (2.0 W3; at most one).
	GateVetoes int     `json:"gate_vetoes,omitempty"`
	Options    Options `json:"options"`
}

func NewRunState

func NewRunState(goal string, options Options) *RunState

type RunSummary

type RunSummary struct {
	RunID     string
	Goal      string
	Status    string
	UpdatedAt time.Time
	Turn      int
	ToolCalls int
}

type Runner

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

func NewRunner

func NewRunner(cfg *config.Config, options Options, out io.Writer, errOut io.Writer) (*Runner, error)

func (*Runner) Close

func (r *Runner) Close()

Close releases resources held by the runner (e.g. code graph DB). After it returns, no Warn, OnProgress or OnTurnStats call reaches the caller, even from a tool goroutine the run abandoned.

func (*Runner) ListRuns

func (r *Runner) ListRuns(limit int) ([]RunSummary, error)

func (*Runner) Resume

func (r *Runner) Resume(ctx context.Context, runID string) (*RunState, error)

func (*Runner) RunBenchmark

func (r *Runner) RunBenchmark(ctx context.Context, suite BenchmarkSuite) (*BenchmarkReport, error)

func (*Runner) RunEval

func (r *Runner) RunEval(ctx context.Context, cases []EvalCase) ([]EvalResult, error)

func (*Runner) RunGoal

func (r *Runner) RunGoal(ctx context.Context, goal string) (*RunState, error)

type Step

type Step struct {
	Turn      int       `json:"turn"`
	Type      string    `json:"type"`
	Name      string    `json:"name,omitempty"`
	Content   string    `json:"content,omitempty"`
	ToolCall  string    `json:"tool_call_id,omitempty"`
	Timestamp time.Time `json:"timestamp"`
}

type TurnStats

type TurnStats struct {
	Turn         int
	MaxTurns     int
	Elapsed      time.Duration
	InputTokens  int
	OutputTokens int
	// Cache reads and 5-minute/1-hour cache writes within InputTokens,
	// so a session cost prices them at their own rates (#312).
	CacheReadTokens    int
	CacheWriteTokens   int
	CacheWrite1hTokens int
	Response           string   // full assistant content for this turn (may be empty for pure tool-call turns)
	ToolCalls          []string // names of tools called this turn
	// Dropped: a stream rule cut this reply short and the turn re-runs
	// (2.0 W3). The provider billed it; nothing else about it is kept.
	Dropped bool
}

TurnStats carries per-turn performance data from a completed LLM call.

type VerificationCheck

type VerificationCheck struct {
	Command   string    `json:"command"`
	Passed    bool      `json:"passed"`
	ExitCode  int       `json:"exit_code"`
	Output    string    `json:"output,omitempty"`
	TimedOut  bool      `json:"timed_out,omitempty"`
	Timestamp time.Time `json:"timestamp"`
}

Jump to

Keyboard shortcuts

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