agent

package
v0.7.0 Latest Latest
Warning

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

Go to latest
Published: Aug 1, 2026 License: MIT Imports: 10 Imported by: 0

Documentation

Overview

Package agent defines the provider-agnostic contract codexmon uses to drive and monitor an AI coding CLI — codex, Claude Code, or the Cursor agent.

Each concrete agent lives in a subpackage (internal/agent/codex, .../claude, .../cursor) that registers a Provider via Register from an init function. The supervisor and CLI then work only against the shared types here, so adding a new agent never touches the monitor: it just implements Provider and registers itself.

The central idea is normalization. Every agent emits a different event stream — codex's JSONL item/turn events, Claude Code's stream-json system/assistant/ result events, Cursor's tool_call lifecycle — but codexmon only cares about a handful of liveness facts: what phase the run is in, which units of work are in flight (so the watchdog can time them), the final answer, and token usage. A Provider's ParseLine collapses its native stream into the common Event here.

Index

Constants

View Source
const DefaultName = "codex"

DefaultName is the agent codexmon uses when none is selected via --agent or CODEXMON_AGENT. It is codex, so every command that worked before this tool learned other agents keeps working unchanged.

Variables

View Source
var ErrTimeout = errors.New("timed out")

ErrTimeout is returned by a RunFunc when the probed command exceeded its deadline — the very hang codexmon exists to surface — so a Provider can report it distinctly from an ordinary command failure.

Functions

func Caller added in v0.6.0

func Caller() string

Caller reports which coding agent invoked codexmon, inferred from the environment, or "" when unknown (a human shell, CI, an unrecognized agent). It exists so codexmon can avoid falling back to the very agent that is calling it. Today only Claude Code is detected: it exports CLAUDECODE=1 into the environment of every process it launches, so a codexmon run spawned from Claude Code sees it.

func FallbackChain added in v0.6.0

func FallbackChain(caller string) []string

FallbackChain is FallbackOrder with the calling agent removed: codexmon must not fall back to the agent that invoked it, which is presumably the one already rate-limited or busy. With a Claude Code caller, for instance, the chain collapses from codex→claude→cursor to codex→cursor (Cursor becomes the second and last fallback). An unknown caller leaves the full chain intact.

func FirstNonEmpty

func FirstNonEmpty(vals ...string) string

FirstNonEmpty returns the first argument that is not empty after trimming, or "" if all are empty.

func IsLimitFailure added in v0.6.0

func IsLimitFailure(texts ...string) bool

IsLimitFailure reports whether any of the given texts (typically a failed run's error message and final output) indicates the agent stopped because it ran out of a usage, rate, or quota limit — the cue codexmon uses to fall back to the next agent rather than surfacing the failure.

func Names

func Names() []string

Names returns the registered agent names, sorted.

func Register

func Register(p Provider)

Register adds a provider to the global registry. Providers call this from an init function; registering two providers under the same name panics, since that can only be a programming error.

func ResolveBin

func ResolveBin(p Provider, override string) (string, error)

ResolveBin locates a provider's executable. An explicit override (e.g. --agent-bin) wins; then the provider's BinEnv environment variable; then the first of its BinCandidates found on PATH.

func ReviewPrompt

func ReviewPrompt(spec ReviewSpec) string

ReviewPrompt builds a provider-neutral code-review instruction for agents that have no purpose-built reviewer (Claude Code, Cursor). It tells the agent which diff to look at and to stay strictly read-only.

func Shorten

func Shorten(s string, limit int) string

Shorten collapses runs of whitespace in s and truncates it to limit bytes, appending an ellipsis when it had to cut. Providers use it to keep one-line status summaries tidy.

func UsageSummary

func UsageSummary(u *Usage) string

UsageSummary renders token usage as " (N in / M out tokens)", or "" when nil, for appending to a completion summary.

Types

type ActiveItem

type ActiveItem struct {
	ID    string
	Kind  ItemKind
	Label string // short human label, used in stuck-tool kill reasons
}

ActiveItem is a unit of work an agent reported starting. The watchdog tracks it by ID until a matching completion arrives, timing it per its Kind.

type Analysis

type Analysis struct {
	JSONMode bool
	Args     []string
	Title    string
}

Analysis is the outcome of inspecting the args destined for one agent: the (possibly flag-augmented) args to actually run, whether codexmon will monitor the run as a JSON event stream, and a short human title.

type DoctorReport

type DoctorReport struct {
	Agent      string          `json:"agent"`
	Ready      bool            `json:"ready"`
	Bin        string          `json:"bin"`
	Version    string          `json:"version,omitempty"`
	HealthName string          `json:"health_name,omitempty"` // probe used, e.g. "codex doctor"
	HealthOK   bool            `json:"health_ok"`
	Detail     json.RawMessage `json:"detail,omitempty"`      // structured probe output, if any
	DetailText string          `json:"detail_text,omitempty"` // textual probe output, if any
	Problems   []string        `json:"problems,omitempty"`
}

DoctorReport is the normalized result of a Provider's readiness check.

type Event

type Event struct {
	Phase    Phase
	Summary  string
	Started  []ActiveItem // units of work that began on this line
	Finished []string     // IDs of units that completed or failed on this line
	Result   string       // final/most-recent answer text carried by this line
	ThreadID string       // session/thread id, when this line establishes one
	Usage    *Usage       // token usage, when this line reports it
	Failure  bool         // a hard error / failed-turn line
	FailMsg  string       // failure detail (used when Failure is true)
}

Event is the normalized interpretation of one line of an agent's output stream. A Provider's ParseLine fills only the fields a given line implies; the monitor merges them into the live status. Two conventions keep parsers simple: Phase == "" means "keep the previous phase", and Summary == "" means "log nothing for this line" (the line still counts as activity).

type ItemKind

type ItemKind int

ItemKind buckets an in-flight unit of work so the watchdog can apply the right liveness rule: a shell command may legitimately run for minutes (wall-clock only), an MCP/tool call should be quick (its own stuck-timeout), and anything else is generic activity governed by the idle ceiling.

const (
	KindOther   ItemKind = iota // generic activity
	KindCommand                 // a shell command — may legitimately run long
	KindTool                    // an MCP / tool / web call — should return quickly
)

type Phase

type Phase string

Phase is a coarse, human-meaningful stage label derived from an agent's event stream. It is what `codexmon status` shows so a watcher can tell *what* the agent is doing — regardless of which agent it is.

const (
	PhaseStarting    Phase = "starting"
	PhaseThinking    Phase = "thinking"
	PhaseRunning     Phase = "running"
	PhaseVerifying   Phase = "verifying"
	PhaseEditing     Phase = "editing"
	PhaseInvestigate Phase = "investigating"
	PhaseSearching   Phase = "searching"
	PhaseReviewing   Phase = "reviewing"
	PhaseWriting     Phase = "writing"
	PhaseFinalizing  Phase = "finalizing"
	PhaseCompleted   Phase = "completed"
	PhaseFailed      Phase = "failed"
)

type Provider

type Provider interface {
	// Name is the canonical id used by --agent and CODEXMON_AGENT.
	Name() string

	// BinEnv is the environment variable that overrides the binary path
	// (e.g. CODEXMON_CODEX). It is also used in "not found" diagnostics.
	BinEnv() string

	// BinCandidates lists the executables to look up on PATH, in preference
	// order (Cursor ships both "cursor-agent" and "agent", for instance).
	BinCandidates() []string

	// Analyze inspects the args headed for the agent, optionally injects the
	// flags codexmon needs to monitor a JSON event stream and capture the final
	// answer, and reports whether the run will be JSON-monitored.
	Analyze(args []string, resultFile string, allowJSON bool) Analysis

	// ReviewArgs builds the agent-native args for a code review from a
	// high-level ReviewSpec. The result is then fed through Analyze.
	ReviewArgs(spec ReviewSpec) ([]string, error)

	// ParseLine normalizes one line of the agent's stdout stream into an Event.
	// ok is false for blank or non-event lines.
	ParseLine(line string) (Event, bool)

	// Doctor reports whether the agent is installed and usable, using run for
	// bounded version/health probes.
	Doctor(bin string, run RunFunc) DoctorReport
}

Provider adapts one AI coding CLI to codexmon's monitor.

func Get

func Get(name string) (Provider, error)

Get returns the registered provider for name, or an error naming the agents that are available.

type ReviewScope

type ReviewScope string

ReviewScope selects which changes `codexmon review` asks the agent to review.

const (
	ScopeUncommitted ReviewScope = "uncommitted" // the working tree (default)
	ScopeBase        ReviewScope = "base"        // current branch vs a base ref
)

type ReviewSpec

type ReviewSpec struct {
	Scope ReviewScope
	Base  string // base ref when Scope == ScopeBase
}

ReviewSpec is the high-level, agent-independent description of a review that the `codexmon review` command turns into native args via Provider.ReviewArgs.

type RunFunc

type RunFunc func(timeout time.Duration, name string, args ...string) (string, error)

RunFunc runs a short, bounded command and returns its combined output. On a deadline it returns ErrTimeout. Providers use it for version/health probes in Doctor; the CLI supplies an implementation that kills the whole process group on timeout so a wedged agent can never hang `codexmon doctor`.

type Usage

type Usage struct {
	InputTokens           int `json:"input_tokens"`
	CachedInputTokens     int `json:"cached_input_tokens"`
	CacheCreationTokens   int `json:"cache_creation_tokens,omitempty"`
	OutputTokens          int `json:"output_tokens"`
	ReasoningOutputTokens int `json:"reasoning_output_tokens"`
}

Usage is normalized token accounting. Agents leave fields they do not report at zero (Cursor, for instance, reports no token usage at all).

Directories

Path Synopsis
Package all registers every built-in agent provider as an import side effect.
Package all registers every built-in agent provider as an import side effect.
Package claude adapts Anthropic's Claude Code CLI (`claude`) to codexmon's agent contract.
Package claude adapts Anthropic's Claude Code CLI (`claude`) to codexmon's agent contract.
Package codex adapts the OpenAI Codex CLI (`codex`) to codexmon's agent contract: it locates the binary, injects the `exec --json` / `--output-last-message` flags that make a run observable, and parses codex's JSONL event stream into the normalized agent.Event the monitor consumes.
Package codex adapts the OpenAI Codex CLI (`codex`) to codexmon's agent contract: it locates the binary, injects the `exec --json` / `--output-last-message` flags that make a run observable, and parses codex's JSONL event stream into the normalized agent.Event the monitor consumes.
Package cursor adapts the Cursor agent CLI (`cursor-agent`, also installed as `agent`) to codexmon's agent contract.
Package cursor adapts the Cursor agent CLI (`cursor-agent`, also installed as `agent`) to codexmon's agent contract.

Jump to

Keyboard shortcuts

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