agents

package
v0.1.0 Latest Latest
Warning

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

Go to latest
Published: Jun 2, 2026 License: MIT Imports: 17 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func AcquireSlot

func AcquireSlot(ctx context.Context, a Agent) error

AcquireSlot blocks until a test slot is available for the agent or the context is cancelled. Returns a non-nil error if the context expires before a slot opens.

func DefaultDroidModel

func DefaultDroidModel() string

DefaultDroidModel returns the default model string for Droid BYOK configuration. Format is "custom:<baseModelID>" which the Droid API expects for custom model selection.

func Register

func Register(a Agent)

func RegisterGate

func RegisterGate(name string, defaultMax int)

RegisterGate sets a concurrency limit for an agent's tests. Tests call AcquireSlot/ReleaseSlot to respect this limit. The limit can be overridden via E2E_CONCURRENT_TEST_LIMIT.

func ReleaseSlot

func ReleaseSlot(a Agent)

ReleaseSlot frees a test slot for the agent.

Types

type Agent

type Agent interface {
	Name() string
	// Binary returns the CLI binary name (e.g. "claude", "gemini").
	Binary() string
	TraceAgent() string
	PromptPattern() string
	// TimeoutMultiplier returns a factor applied to per-test timeouts.
	// Slower agents (e.g. Gemini) return values > 1.
	TimeoutMultiplier() float64
	RunPrompt(ctx context.Context, dir string, prompt string, opts ...Option) (Output, error)
	StartSession(ctx context.Context, dir string) (Session, error)
	// Bootstrap performs one-time CI setup (auth config, warmup, etc.).
	// Called before any tests run. Implementations should be idempotent.
	Bootstrap() error
	// IsTransientError returns true if the error from RunPrompt looks like
	// a transient API failure (e.g. 500, rate limit, network error) that
	// is worth retrying.
	IsTransientError(out Output, err error) bool
}

func All

func All() []Agent

type Claude

type Claude struct{}

func (*Claude) Binary

func (c *Claude) Binary() string

func (*Claude) Bootstrap

func (c *Claude) Bootstrap() error

func (*Claude) IsTransientError

func (c *Claude) IsTransientError(out Output, _ error) bool

func (*Claude) Name

func (c *Claude) Name() string

func (*Claude) PromptPattern

func (c *Claude) PromptPattern() string

func (*Claude) RunPrompt

func (c *Claude) RunPrompt(ctx context.Context, dir string, prompt string, opts ...Option) (Output, error)

func (*Claude) StartSession

func (c *Claude) StartSession(ctx context.Context, dir string) (Session, error)

func (*Claude) TimeoutMultiplier

func (c *Claude) TimeoutMultiplier() float64

func (*Claude) TraceAgent

func (c *Claude) TraceAgent() string

type Codex

type Codex struct{}

Codex implements the E2E Agent interface for OpenAI's Codex CLI.

func (*Codex) Binary

func (c *Codex) Binary() string

func (*Codex) Bootstrap

func (c *Codex) Bootstrap() error

func (*Codex) IsTransientError

func (c *Codex) IsTransientError(out Output, err error) bool

func (*Codex) Name

func (c *Codex) Name() string

func (*Codex) PromptPattern

func (c *Codex) PromptPattern() string

func (*Codex) ResumeSession

func (c *Codex) ResumeSession(ctx context.Context, dir, home, sessionID string) (Session, error)

func (*Codex) RunPrompt

func (c *Codex) RunPrompt(ctx context.Context, dir string, prompt string, opts ...Option) (Output, error)

func (*Codex) StartSession

func (c *Codex) StartSession(ctx context.Context, dir string) (Session, error)

func (*Codex) TimeoutMultiplier

func (c *Codex) TimeoutMultiplier() float64

func (*Codex) TraceAgent

func (c *Codex) TraceAgent() string

type CodexSession

type CodexSession struct {
	*TmuxSession
	// contains filtered or unexported fields
}

func (*CodexSession) Home

func (s *CodexSession) Home() string

type CopilotCLI

type CopilotCLI struct{}

func (*CopilotCLI) Binary

func (c *CopilotCLI) Binary() string

func (*CopilotCLI) Bootstrap

func (c *CopilotCLI) Bootstrap() error

func (*CopilotCLI) IsTransientError

func (c *CopilotCLI) IsTransientError(out Output, err error) bool

func (*CopilotCLI) Name

func (c *CopilotCLI) Name() string

func (*CopilotCLI) PromptPattern

func (c *CopilotCLI) PromptPattern() string

func (*CopilotCLI) RunPrompt

func (c *CopilotCLI) RunPrompt(ctx context.Context, dir string, prompt string, opts ...Option) (Output, error)

func (*CopilotCLI) StartSession

func (c *CopilotCLI) StartSession(ctx context.Context, dir string) (Session, error)

func (*CopilotCLI) TimeoutMultiplier

func (c *CopilotCLI) TimeoutMultiplier() float64

func (*CopilotCLI) TraceAgent

func (c *CopilotCLI) TraceAgent() string

type CopilotSession

type CopilotSession struct {
	*TmuxSession
}

CopilotSession wraps TmuxSession to handle Copilot CLI's dual input modes. Copilot CLI can be in "Chat" mode (Enter submits) or "Edit" mode (Ctrl+S submits). After completing a prompt, copilot may return to either mode non-deterministically. This wrapper detects Edit mode after sending Enter and falls back to Ctrl+S if needed.

func (*CopilotSession) Send

func (cs *CopilotSession) Send(input string) error

type CursorCLI

type CursorCLI struct{}

CursorCLI implements the E2E Agent interface for the Cursor Agent CLI binary. The CLI binary is called "agent" and uses Cursor's hooks system via .cursor/hooks.json. It maps to the same Trace agent as Cursor IDE ("cursor").

All E2E interactions use interactive (tmux) mode so that the full hook lifecycle fires (sessionStart, beforeSubmitPrompt, stop, sessionEnd). Headless (-p) mode skips beforeSubmitPrompt and stop hooks.

func (*CursorCLI) Binary

func (a *CursorCLI) Binary() string

func (*CursorCLI) Bootstrap

func (a *CursorCLI) Bootstrap() error

func (*CursorCLI) IsTransientError

func (a *CursorCLI) IsTransientError(out Output, err error) bool

func (*CursorCLI) Name

func (a *CursorCLI) Name() string

func (*CursorCLI) PromptPattern

func (a *CursorCLI) PromptPattern() string

PromptPattern returns a regex matching Cursor's ready-state prompt markers. Cursor has used multiple startup/completion markers across releases.

func (*CursorCLI) RunPrompt

func (a *CursorCLI) RunPrompt(ctx context.Context, dir string, prompt string, opts ...Option) (Output, error)

func (*CursorCLI) StartSession

func (a *CursorCLI) StartSession(ctx context.Context, dir string) (Session, error)

func (*CursorCLI) TimeoutMultiplier

func (a *CursorCLI) TimeoutMultiplier() float64

func (*CursorCLI) TraceAgent

func (a *CursorCLI) TraceAgent() string

type Droid

type Droid struct{}

Droid implements the Agent interface for Factory AI Droid.

func (*Droid) Binary

func (d *Droid) Binary() string

func (*Droid) Bootstrap

func (d *Droid) Bootstrap() error

func (*Droid) IsTransientError

func (d *Droid) IsTransientError(out Output, err error) bool

func (*Droid) Name

func (d *Droid) Name() string

func (*Droid) PromptPattern

func (d *Droid) PromptPattern() string

func (*Droid) RunPrompt

func (d *Droid) RunPrompt(ctx context.Context, dir string, prompt string, opts ...Option) (Output, error)

func (*Droid) StartSession

func (d *Droid) StartSession(ctx context.Context, dir string) (Session, error)

func (*Droid) TimeoutMultiplier

func (d *Droid) TimeoutMultiplier() float64

func (*Droid) TraceAgent

func (d *Droid) TraceAgent() string

type ExternalAgent

type ExternalAgent interface {
	IsExternalAgent() bool
}

ExternalAgent is an optional interface for agents discovered via the external agent protocol (trace-agent-* binaries). SetupRepo uses this to pre-configure external_agents in settings before running `trace enable`.

type Gemini

type Gemini struct{}

func (*Gemini) Binary

func (g *Gemini) Binary() string

func (*Gemini) Bootstrap

func (g *Gemini) Bootstrap() error

func (*Gemini) IsTransientError

func (g *Gemini) IsTransientError(out Output, err error) bool

func (*Gemini) Name

func (g *Gemini) Name() string

func (*Gemini) PromptPattern

func (g *Gemini) PromptPattern() string

func (*Gemini) RunPrompt

func (g *Gemini) RunPrompt(ctx context.Context, dir string, prompt string, opts ...Option) (Output, error)

func (*Gemini) StartSession

func (g *Gemini) StartSession(_ context.Context, dir string) (Session, error)

func (*Gemini) TimeoutMultiplier

func (g *Gemini) TimeoutMultiplier() float64

func (*Gemini) TraceAgent

func (g *Gemini) TraceAgent() string

type Option

type Option func(*runConfig)

func WithModel

func WithModel(model string) Option

func WithPermissionMode

func WithPermissionMode(mode string) Option

func WithPromptTimeout

func WithPromptTimeout(d time.Duration) Option

type Output

type Output struct {
	Command  string
	Stdout   string
	Stderr   string
	ExitCode int
}

type Pi

type Pi struct{}

Pi implements the E2E Agent interface for the Pi coding agent.

func (*Pi) Binary

func (p *Pi) Binary() string

func (*Pi) Bootstrap

func (p *Pi) Bootstrap() error

func (*Pi) IsTransientError

func (p *Pi) IsTransientError(out Output, _ error) bool

func (*Pi) Name

func (p *Pi) Name() string

func (*Pi) PromptPattern

func (p *Pi) PromptPattern() string

func (*Pi) RunPrompt

func (p *Pi) RunPrompt(ctx context.Context, dir string, prompt string, opts ...Option) (Output, error)

func (*Pi) StartSession

func (p *Pi) StartSession(_ context.Context, dir string) (Session, error)

func (*Pi) TimeoutMultiplier

func (p *Pi) TimeoutMultiplier() float64

func (*Pi) TraceAgent

func (p *Pi) TraceAgent() string

type PiSession

type PiSession struct {
	*TmuxSession
	// contains filtered or unexported fields
}

PiSession exposes the per-test isolated Pi home so test fixtures can inspect or clean it up.

func (*PiSession) Home

func (s *PiSession) Home() string

type RogerRoger

type RogerRoger struct{}

RogerRoger implements the Agent interface using a deterministic external agent binary that creates files and fires hooks without making any API calls. Unlike built-in agents (Vogon, Claude Code, etc.), roger-roger is discovered via the external agent protocol (trace-agent-roger-roger binary in $PATH).

func (*RogerRoger) Binary

func (r *RogerRoger) Binary() string

func (*RogerRoger) Bootstrap

func (r *RogerRoger) Bootstrap() error

func (*RogerRoger) IsExternalAgent

func (r *RogerRoger) IsExternalAgent() bool

IsExternalAgent returns true — roger-roger is discovered via the external agent protocol.

func (*RogerRoger) IsTransientError

func (r *RogerRoger) IsTransientError(_ Output, _ error) bool

func (*RogerRoger) Name

func (r *RogerRoger) Name() string

func (*RogerRoger) PromptPattern

func (r *RogerRoger) PromptPattern() string

func (*RogerRoger) RunPrompt

func (r *RogerRoger) RunPrompt(ctx context.Context, dir string, prompt string, opts ...Option) (Output, error)

func (*RogerRoger) StartSession

func (r *RogerRoger) StartSession(_ context.Context, dir string) (Session, error)

func (*RogerRoger) TimeoutMultiplier

func (r *RogerRoger) TimeoutMultiplier() float64

func (*RogerRoger) TraceAgent

func (r *RogerRoger) TraceAgent() string

type Session

type Session interface {
	Send(input string) error
	WaitFor(pattern string, timeout time.Duration) (string, error)
	Capture() string
	Close() error
}

type TmuxSession

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

TmuxSession implements Session using tmux for PTY-based interactive agents.

func NewTmuxSession

func NewTmuxSession(name string, dir string, unsetEnv []string, command string, args ...string) (*TmuxSession, error)

NewTmuxSession creates a new tmux session running the given command in dir. unsetEnv lists environment variable names to strip from the session.

The command is wrapped with `env` to propagate PATH from the current process. tmux sessions inherit the tmux server's environment (not the client's), so without this, binaries added to PATH by the test runner (e.g., freshly built `trace` and `vogon`) would not be found inside the session.

func (*TmuxSession) Capture

func (s *TmuxSession) Capture() string

func (*TmuxSession) Close

func (s *TmuxSession) Close() error

func (*TmuxSession) IsPaneDead

func (s *TmuxSession) IsPaneDead() bool

IsPaneDead returns true if the process inside the tmux pane has exited. This relies on the remain-on-exit option being set (which NewTmuxSession does).

func (*TmuxSession) OnClose

func (s *TmuxSession) OnClose(fn func())

OnClose registers a function to run when the session is closed.

func (*TmuxSession) Send

func (s *TmuxSession) Send(input string) error

func (*TmuxSession) SendKeys

func (s *TmuxSession) SendKeys(keys ...string) error

SendKeys sends raw tmux key names without appending Enter.

func (*TmuxSession) WaitFor

func (s *TmuxSession) WaitFor(pattern string, timeout time.Duration) (string, error)

type Vogon

type Vogon struct{}

Vogon implements the Agent interface using a deterministic binary that creates files and fires hooks without making any API calls. Named after the Vogons from The Hitchhiker's Guide to the Galaxy.

func (*Vogon) Binary

func (v *Vogon) Binary() string

func (*Vogon) Bootstrap

func (v *Vogon) Bootstrap() error

func (*Vogon) IsTransientError

func (v *Vogon) IsTransientError(_ Output, _ error) bool

func (*Vogon) Name

func (v *Vogon) Name() string

func (*Vogon) PromptPattern

func (v *Vogon) PromptPattern() string

func (*Vogon) RunPrompt

func (v *Vogon) RunPrompt(ctx context.Context, dir string, prompt string, opts ...Option) (Output, error)

func (*Vogon) StartSession

func (v *Vogon) StartSession(_ context.Context, dir string) (Session, error)

func (*Vogon) TimeoutMultiplier

func (v *Vogon) TimeoutMultiplier() float64

func (*Vogon) TraceAgent

func (v *Vogon) TraceAgent() string

func (*Vogon) WriteSessionTranscript

func (v *Vogon) WriteSessionTranscript(ctx context.Context, dir string, extraEnv []string, sessionID, userPrompt, assistantMessage string) (Output, error)

WriteSessionTranscript creates a deterministic vogon session transcript without firing hooks or mutating the repository. Attach E2E tests use this to prepare a session that `trace attach` can import.

Jump to

Keyboard shortcuts

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