Documentation
¶
Overview ¶
Package harness drives AI coding command-line tools through a common API.
Index ¶
- Constants
- func AccountErrorResumable(s string) bool
- func CostFromUsage(model string, usage Usage) float64
- func DirectivePaths() (dirs, files []string)
- func FormatEvent(e Event) string
- func Name(h Harness) string
- func Names() string
- func PreferAccountErrorText(current, candidate string) string
- func ResumableReset(errText string, limit *RateLimitInfo) *time.Time
- func Run(ctx context.Context, h Harness, j Job, emit func(Event)) error
- func StripDirectives(root string) (int, error)
- func WriteSystemPrompt(h Harness, j Job) error
- type AccountError
- type ClaudeHarness
- func (ClaudeHarness) AccountErrorText(s string) string
- func (ClaudeHarness) Args(j Job) []string
- func (ClaudeHarness) Binary() string
- func (ClaudeHarness) DefaultModels() []ModelDefault
- func (ClaudeHarness) EgressHosts() []string
- func (ClaudeHarness) Env(baseURL string) []string
- func (ClaudeHarness) GuideFilename() string
- func (ClaudeHarness) ParseStream(r io.Reader, emit func(Event))
- func (ClaudeHarness) Prompt(j Job) string
- func (ClaudeHarness) SkillDir(workspace, name string) string
- func (ClaudeHarness) StateEnv(dir string) []string
- func (ClaudeHarness) SystemPromptViaArgs() bool
- type CodexHarness
- func (CodexHarness) AccountErrorText(s string) string
- func (CodexHarness) Args(j Job) []string
- func (CodexHarness) Binary() string
- func (CodexHarness) DefaultModels() []ModelDefault
- func (CodexHarness) EgressHosts() []string
- func (CodexHarness) Env(_ string) []string
- func (CodexHarness) GuideFilename() string
- func (CodexHarness) ParseStream(r io.Reader, emit func(Event))
- func (CodexHarness) Prompt(j Job) string
- func (CodexHarness) SkillDir(workspace, name string) string
- func (CodexHarness) StateEnv(dir string) []string
- func (CodexHarness) SystemPromptViaArgs() bool
- type CopilotHarness
- func (CopilotHarness) AccountErrorText(s string) string
- func (CopilotHarness) Args(j Job) []string
- func (CopilotHarness) Binary() string
- func (CopilotHarness) DefaultModels() []ModelDefault
- func (CopilotHarness) EgressHosts() []string
- func (CopilotHarness) Env(baseURL string) []string
- func (CopilotHarness) GuideFilename() string
- func (CopilotHarness) ParseStream(r io.Reader, emit func(Event))
- func (CopilotHarness) Prompt(j Job) string
- func (CopilotHarness) SkillDir(workspace, name string) string
- func (CopilotHarness) StateEnv(dir string) []string
- func (CopilotHarness) SystemPromptViaArgs() bool
- type Event
- type Harness
- type Job
- type ModelDefault
- type OpencodeHarness
- func (OpencodeHarness) AccountErrorText(s string) string
- func (OpencodeHarness) Args(j Job) []string
- func (OpencodeHarness) Binary() string
- func (OpencodeHarness) DefaultModels() []ModelDefault
- func (OpencodeHarness) EgressHosts() []string
- func (OpencodeHarness) Env(_ string) []string
- func (OpencodeHarness) GuideFilename() string
- func (OpencodeHarness) ParseStream(r io.Reader, emit func(Event))
- func (OpencodeHarness) Prompt(j Job) string
- func (OpencodeHarness) SkillDir(workspace, name string) string
- func (OpencodeHarness) StateEnv(dir string) []string
- func (OpencodeHarness) SystemPromptViaArgs() bool
- type RateLimitInfo
- type Usage
Constants ¶
const ( KindThinking = "thinking" KindText = "text" KindTool = "tool" KindResult = "result" KindError = "error" KindSession = "session" KindRateLimit = "rate_limit" )
const DefaultMaxTurns = 30
Variables ¶
This section is empty.
Functions ¶
func AccountErrorResumable ¶
AccountErrorResumable reports whether an account error describes a transient limit. Revoked access wins when both permanent and transient phrases appear.
func CostFromUsage ¶
CostFromUsage calculates a result event's list-price cost. It returns zero for an unknown model rather than presenting an incorrect estimate.
InputTokens includes all prompt tokens. CacheReadTokens is a discounted subset. CacheWriteTokens is separate only for models with a dedicated write rate; it remains ordinary input when CacheWrite is zero.
func DirectivePaths ¶ added in v0.1.5
func DirectivePaths() (dirs, files []string)
DirectivePaths returns directory and file basename patterns that agent CLIs automatically load as project instructions or configuration. Matching is case-insensitive and follows path.Match semantics. The returned slices are copies and may be modified by the caller.
func FormatEvent ¶
FormatEvent renders an event as one plain-text log line.
func Name ¶
Name returns the registered name of h. Comparing concrete types avoids an interface equality panic if a future implementation contains a slice or map. An unregistered implementation falls back to its binary name.
func Names ¶
func Names() string
Names returns the registered backend names in lexical order, excluding the empty default alias.
func PreferAccountErrorText ¶
PreferAccountErrorText keeps the first account error unless a later message identifies revoked access. This prevents a permanent failure from being scheduled for retry because an earlier line happened to describe a limit.
func ResumableReset ¶
func ResumableReset(errText string, limit *RateLimitInfo) *time.Time
ResumableReset returns a rejected limit's reset time only when the associated account error is transient. Revoked access always requires manual action.
func StripDirectives ¶ added in v0.1.5
StripDirectives removes files and directories below root whose basenames match DirectivePaths. A removed directory counts as one item regardless of its contents. The .git subtree is skipped. A missing root is a no-op.
func WriteSystemPrompt ¶
WriteSystemPrompt writes j.SystemPrompt to the guide file used by h. A backend that passes the system prompt in Args has no file to write.
Types ¶
type AccountError ¶
AccountError reports a provider-level account problem for which immediately retrying the command is unlikely to help.
func (*AccountError) Error ¶
func (e *AccountError) Error() string
type ClaudeHarness ¶
type ClaudeHarness struct{}
ClaudeHarness drives Claude Code in print mode. It is the default backend because the original caller used Claude before the shared interface existed.
func (ClaudeHarness) AccountErrorText ¶
func (ClaudeHarness) AccountErrorText(s string) string
func (ClaudeHarness) Args ¶
func (ClaudeHarness) Args(j Job) []string
Args builds the claude -p invocation. An allowed-tools list uses acceptEdits only when the job has a legitimate output file; otherwise the default permission mode keeps the requested read-only boundary intact.
func (ClaudeHarness) Binary ¶
func (ClaudeHarness) Binary() string
func (ClaudeHarness) DefaultModels ¶
func (ClaudeHarness) DefaultModels() []ModelDefault
func (ClaudeHarness) EgressHosts ¶
func (ClaudeHarness) EgressHosts() []string
func (ClaudeHarness) Env ¶
func (ClaudeHarness) Env(baseURL string) []string
func (ClaudeHarness) GuideFilename ¶
func (ClaudeHarness) GuideFilename() string
func (ClaudeHarness) ParseStream ¶
func (ClaudeHarness) ParseStream(r io.Reader, emit func(Event))
ParseStream reads Claude's stream-json output. scanJSONL uses a buffered reader rather than Scanner so an oversized thinking or tool-result line cannot discard the later result event that carries usage and turn counts.
func (ClaudeHarness) Prompt ¶
func (ClaudeHarness) Prompt(j Job) string
func (ClaudeHarness) SkillDir ¶
func (ClaudeHarness) SkillDir(workspace, name string) string
func (ClaudeHarness) StateEnv ¶
func (ClaudeHarness) StateEnv(dir string) []string
func (ClaudeHarness) SystemPromptViaArgs ¶
func (ClaudeHarness) SystemPromptViaArgs() bool
type CodexHarness ¶
type CodexHarness struct{}
CodexHarness drives Codex in headless exec mode. Codex reads AGENTS.md as project guidance and stores resumable threads under CODEX_HOME.
func (CodexHarness) AccountErrorText ¶
func (CodexHarness) AccountErrorText(s string) string
func (CodexHarness) Args ¶
func (CodexHarness) Args(j Job) []string
Args builds codex exec argv. Headless Codex has no slash-style skill invocation, so Prompt names the staged SKILL.md. Resume inserts the thread id after "exec resume". Codex has no per-turn cap, so Job.MaxTurns is intentionally ignored.
func (CodexHarness) Binary ¶
func (CodexHarness) Binary() string
func (CodexHarness) DefaultModels ¶
func (CodexHarness) DefaultModels() []ModelDefault
func (CodexHarness) EgressHosts ¶
func (CodexHarness) EgressHosts() []string
func (CodexHarness) Env ¶
func (CodexHarness) Env(_ string) []string
func (CodexHarness) GuideFilename ¶
func (CodexHarness) GuideFilename() string
func (CodexHarness) ParseStream ¶
func (CodexHarness) ParseStream(r io.Reader, emit func(Event))
ParseStream maps codex exec --json output onto backend-neutral events. Session announcements enable resume, item completions carry text and tools, and unknown or non-JSON lines pass through as text. Codex has no max-turns event because its exec command has no turn cap.
func (CodexHarness) Prompt ¶
func (CodexHarness) Prompt(j Job) string
func (CodexHarness) SkillDir ¶
func (CodexHarness) SkillDir(workspace, name string) string
func (CodexHarness) StateEnv ¶
func (CodexHarness) StateEnv(dir string) []string
func (CodexHarness) SystemPromptViaArgs ¶
func (CodexHarness) SystemPromptViaArgs() bool
type CopilotHarness ¶
type CopilotHarness struct{}
CopilotHarness drives GitHub Copilot CLI in non-interactive prompt mode. Its arguments and JSONL mapping are based on Copilot CLI 1.0.75.
func (CopilotHarness) AccountErrorText ¶
func (CopilotHarness) AccountErrorText(s string) string
func (CopilotHarness) Args ¶
func (CopilotHarness) Args(j Job) []string
Args enables autopilot and tool use without interactive confirmation. The caller must isolate the process and workspace because --allow-all grants the CLI every tool it exposes.
func (CopilotHarness) Binary ¶
func (CopilotHarness) Binary() string
func (CopilotHarness) DefaultModels ¶
func (CopilotHarness) DefaultModels() []ModelDefault
func (CopilotHarness) EgressHosts ¶
func (CopilotHarness) EgressHosts() []string
func (CopilotHarness) Env ¶
func (CopilotHarness) Env(baseURL string) []string
func (CopilotHarness) GuideFilename ¶
func (CopilotHarness) GuideFilename() string
func (CopilotHarness) ParseStream ¶
func (CopilotHarness) ParseStream(r io.Reader, emit func(Event))
ParseStream combines per-call assistant.usage and per-turn assistant.turn_end records into one result emitted after the stream ends. This gives callers the same single-run totals exposed by the other backends and prevents consumers that retain only the last result from losing usage.
func (CopilotHarness) Prompt ¶
func (CopilotHarness) Prompt(j Job) string
func (CopilotHarness) SkillDir ¶
func (CopilotHarness) SkillDir(workspace, name string) string
func (CopilotHarness) StateEnv ¶
func (CopilotHarness) StateEnv(dir string) []string
func (CopilotHarness) SystemPromptViaArgs ¶
func (CopilotHarness) SystemPromptViaArgs() bool
type Event ¶
type Event struct {
Kind string
Tool string
Text string
CostUSD float64
Turns int
Usage Usage
SessionID string
RateLimit *RateLimitInfo
}
Event is one backend-neutral item from an agent's output stream. Tool, CostUSD, Turns, Usage, SessionID, and RateLimit are populated only for their corresponding Kind.
type Harness ¶
type Harness interface {
// Binary is the executable name expected on PATH.
Binary() string
// Args returns argv without the binary for one job.
Args(Job) []string
// Prompt returns the final user prompt passed by Args.
Prompt(Job) string
// ParseStream maps the backend's combined output onto Event values.
ParseStream(io.Reader, func(Event))
// SkillDir returns the directory where the backend discovers a staged
// SKILL.md and its sibling files.
SkillDir(workspace, name string) string
// GuideFilename is the workspace-relative project instruction file loaded
// by the backend.
GuideFilename() string
// SystemPromptViaArgs reports whether Args passes Job.SystemPrompt itself.
// When false, WriteSystemPrompt writes it to GuideFilename instead.
SystemPromptViaArgs() bool
// EgressHosts lists the model and authentication hosts needed by the
// backend, using "*.example.com" for wildcard suffixes.
EgressHosts() []string
// Env returns backend environment entries. A bare key asks a process
// runner to pass through the caller's value.
Env(baseURL string) []string
// StateEnv points the backend at a caller-owned persistent state directory
// so a later process can resume the same session.
StateEnv(dir string) []string
// AccountErrorText returns the matching provider account error, or an empty
// string. Callers should consult it only after a non-zero process exit so
// ordinary model text cannot pause retries.
AccountErrorText(string) string
// DefaultModels returns the built-in model picker entries. The first entry
// is the backend default.
DefaultModels() []ModelDefault
}
Harness describes the CLI-specific parts of an agent invocation. It owns the binary, arguments, stream format, project guide, skill discovery, provider environment, and default models. Process placement and isolation remain the caller's responsibility.
type Job ¶
type Job struct {
// Workspace is the command's working directory. Paths passed to a CLI are
// relative to it.
Workspace string
// SrcDir is the workspace-relative repository directory used in generated
// prompts. It defaults to "src"; use "." when Workspace is the repository
// root.
SrcDir string
// SkillName selects a staged SKILL.md directory. An empty value means no
// staged skill.
SkillName string
// Prompt is the user turn for a fresh run. When it is empty and SkillName
// is set, the harness builds an activation prompt.
Prompt string
// SystemPrompt supplies additional instructions. Claude receives it via
// --system-prompt. Run writes it to the project guide file used by the
// other backends.
SystemPrompt string
Model string
Effort string
MaxTurns int
// OutputFile is a workspace-relative path the skill should write. It is
// empty for free-form runs.
OutputFile string
// ValidationHint is appended to generated prompts after the OutputFile
// clause when OutputFile ends in .json. It lets a caller tell the agent
// how to validate its output (an API endpoint, a staged validator) in
// terms of the caller's own context. When empty, a generic instruction
// to check against ./schema.json is used.
ValidationHint string
// AllowedTools is Claude's comma-separated tool allowlist. Other backends
// leave tool restrictions to their caller's sandbox.
AllowedTools string
// BaseURL overrides the model API endpoint where the backend supports it.
BaseURL string
// ResumeSessionID continues a prior conversation. ResumePrompt is the
// corrective turn used for the resumed invocation.
ResumeSessionID string
ResumePrompt string
}
Job contains the resolved inputs for one CLI invocation.
type ModelDefault ¶
ModelDefault is one model offered by a backend. Tier is "mid", "high", "max", or empty when the model is selectable but not a tier default.
type OpencodeHarness ¶
type OpencodeHarness struct{}
OpencodeHarness drives OpenCode in headless run mode. OpenCode is provider-neutral, so its environment and egress list cover Anthropic, OpenAI, and OpenCode's model registry by default.
func (OpencodeHarness) AccountErrorText ¶
func (OpencodeHarness) AccountErrorText(s string) string
func (OpencodeHarness) Args ¶
func (OpencodeHarness) Args(j Job) []string
Args builds opencode run argv. OpenCode discovers SKILL.md but does not invoke a named skill itself, so Prompt points at the staged file. --auto suppresses interactive permission prompts and --format json selects JSONL. The caller remains responsible for process isolation.
func (OpencodeHarness) Binary ¶
func (OpencodeHarness) Binary() string
func (OpencodeHarness) DefaultModels ¶
func (OpencodeHarness) DefaultModels() []ModelDefault
func (OpencodeHarness) EgressHosts ¶
func (OpencodeHarness) EgressHosts() []string
func (OpencodeHarness) Env ¶
func (OpencodeHarness) Env(_ string) []string
Env ignores baseURL because OpenCode has no single provider endpoint. A caller can configure each provider through OPENCODE_CONFIG_CONTENT.
func (OpencodeHarness) GuideFilename ¶
func (OpencodeHarness) GuideFilename() string
func (OpencodeHarness) ParseStream ¶
func (OpencodeHarness) ParseStream(r io.Reader, emit func(Event))
func (OpencodeHarness) Prompt ¶
func (OpencodeHarness) Prompt(j Job) string
func (OpencodeHarness) SkillDir ¶
func (OpencodeHarness) SkillDir(workspace, name string) string
func (OpencodeHarness) StateEnv ¶
func (OpencodeHarness) StateEnv(dir string) []string
func (OpencodeHarness) SystemPromptViaArgs ¶
func (OpencodeHarness) SystemPromptViaArgs() bool
type RateLimitInfo ¶
type RateLimitInfo struct {
Status string `json:"status"`
OverageStatus string `json:"overageStatus"`
IsUsingOverage bool `json:"isUsingOverage"`
ResetsAt int64 `json:"resetsAt"`
Type string `json:"rateLimitType"`
}
RateLimitInfo contains subscription limit status reported by a backend.
func PreferRateLimitReset ¶
func PreferRateLimitReset(current, candidate *RateLimitInfo) *RateLimitInfo
PreferRateLimitReset returns the rejected rate limit with the later reset so a retry is not scheduled while another reported window still blocks use.
func (*RateLimitInfo) Rejected ¶
func (r *RateLimitInfo) Rejected() bool
Rejected reports whether the limit currently blocks requests.
func (*RateLimitInfo) ResetTime ¶
func (r *RateLimitInfo) ResetTime() *time.Time
ResetTime converts ResetsAt to UTC. It returns nil for an absent or invalid reset time.
Source Files
¶
Directories
¶
| Path | Synopsis |
|---|---|
|
Package egress provides an authenticated outbound proxy with a hostname allowlist and a helper for Claude workspace sandbox settings.
|
Package egress provides an authenticated outbound proxy with a hostname allowlist and a helper for Claude workspace sandbox settings. |
|
Package llm provides small, structured one-shot model calls for work that does not need a full agent workspace or tool loop.
|
Package llm provides small, structured one-shot model calls for work that does not need a full agent workspace or tool loop. |
|
Package skills parses, filters, and stages agent skill directories.
|
Package skills parses, filters, and stages agent skill directories. |