Documentation
¶
Index ¶
- Constants
- Variables
- func KeepTurnStats(m map[int]TurnStats, st TurnStats)
- func SmallModelSummarizer(base *llm.Config, model string) compact.SummarizeFunc
- func WatchdogOracle(cfg *config.Config, workspace string, logf func(string)) decide.Oracle
- type BenchmarkCase
- type BenchmarkReport
- type BenchmarkResult
- type BenchmarkSuite
- type CheckpointStore
- type EvalCase
- type EvalResult
- type EvalSuite
- type Options
- type PlanStep
- type ProgressKind
- type RunState
- type RunSummary
- type Runner
- func (r *Runner) Close()
- func (r *Runner) ListRuns(limit int) ([]RunSummary, error)
- func (r *Runner) Resume(ctx context.Context, runID string) (*RunState, error)
- func (r *Runner) RunBenchmark(ctx context.Context, suite BenchmarkSuite) (*BenchmarkReport, error)
- func (r *Runner) RunEval(ctx context.Context, cases []EvalCase) ([]EvalResult, error)
- func (r *Runner) RunGoal(ctx context.Context, goal string) (*RunState, error)
- type Step
- type TurnStats
- type VerificationCheck
Constants ¶
const ( StatusRunning = "running" StatusCompleted = "completed" StatusFailed = "failed" StatusMaxTurnsReached = "max_turns_reached" StatusNoProgressStopped = "no_progress_stopped" StatusCancelled = "cancelled" )
const ( PhasePlanning = "planning" PhaseExecution = "execution" PhaseVerification = "verification" )
const ( PlanStatusPending = "pending" PlanStatusInProgress = "in_progress" PlanStatusCompleted = "completed" )
Variables ¶
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 ¶
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 ¶
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 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) 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 ¶
type EvalResult ¶
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 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 ¶
type RunSummary ¶
type Runner ¶
type Runner struct {
// contains filtered or unexported fields
}
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) RunBenchmark ¶
func (r *Runner) RunBenchmark(ctx context.Context, suite BenchmarkSuite) (*BenchmarkReport, error)
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.