Documentation
¶
Overview ¶
Package runner contains provider adapters. Every adapter exposes the same durable-session boundary so workflow code can be tested entirely with fakes.
Index ¶
- Constants
- Variables
- func BuildAntigravityArgs(req Request) ([]string, error)
- func BuildClaudeArgs(req Request) ([]string, error)
- func BuildCodexArgs(req Request, schemaPath string) ([]string, error)
- func ClaudeFirstPartyRouteSupported(runtime task.RuntimeSnapshot, environ []string) bool
- func ClaudePXPipeServerEnvironment(providerEnv []string) []string
- func CodexChatGPTRouteSupported(runtime task.RuntimeSnapshot, environ []string) bool
- func CodexChatGPTRuntimeOverlay(runtime task.RuntimeSnapshot) task.RuntimeSnapshot
- func CodexConfigOverrides(runtime task.RuntimeSnapshot) ([]string, error)
- func CopilotEnvelopePrompt(role Role) string
- func CopilotPermissionHandler(req Request) copilot.PermissionHandlerFunc
- func CopilotReadOnlyTools() []string
- func CopilotTools(role Role) []string
- func DetectPXPipePath(environ []string) string
- func NativeSchema(role Role) string
- func PXPipeServerEnvironment(providerEnv []string) []string
- func ParseCodexLoginStatus(data []byte) (bool, string, error)
- func PathWithinRepo(repoRoot, candidate string) (string, error)
- func ResolveExecutable(envName, fallback string, environ []string) (string, error)
- func RunInteractiveProcess(ctx context.Context, path string, args []string, dir string, env []string, ...) error
- func SafeURL(raw string) bool
- func SanitizedEnv(environ []string) []string
- func UsageFromMap(values map[string]any, inputIncludesCache bool) task.TokenUsage
- func UsageFromMapWithPresence(values map[string]any, inputIncludesCache bool) (task.TokenUsage, bool)
- func ValidateEnvelope(env Envelope, expected Role) error
- func ValidateSelection(role Role, model, effort, speed string, models []ModelInfo, adapter Adapter) error
- func VerifyReportedSelection(provider string, req Request, response Response) error
- func WritePathWithinRepo(repoRoot, candidate string) (string, string, error)
- type Adapter
- type Antigravity
- func (a *Antigravity) Auth(ctx context.Context) (AuthStatus, error)
- func (a *Antigravity) ListModels(ctx context.Context, req ModelListRequest) (ModelPage, error)
- func (a *Antigravity) LocalAuthHint() AuthStatus
- func (a *Antigravity) Login(ctx context.Context, req LoginRequest) error
- func (a *Antigravity) Probe(ctx context.Context) error
- func (a *Antigravity) Run(ctx context.Context, req Request, callbacks Callbacks) (Response, error)
- func (a *Antigravity) SupportsRole(Role) error
- func (a *Antigravity) Version(ctx context.Context) (string, error)
- type AuthStatus
- type Authenticator
- type BudgetError
- type Callbacks
- type CapabilityProber
- type Claude
- func (c *Claude) Auth(ctx context.Context) (AuthStatus, error)
- func (c *Claude) ListModels(ctx context.Context, req ModelListRequest) (ModelPage, error)
- func (c *Claude) Login(ctx context.Context, req LoginRequest) error
- func (c *Claude) Probe(ctx context.Context) error
- func (c *Claude) Run(ctx context.Context, req Request, callbacks Callbacks) (Response, error)
- func (c *Claude) Version(ctx context.Context) (string, error)
- type Codex
- func (c *Codex) Auth(ctx context.Context) (AuthStatus, error)
- func (c *Codex) ListModels(ctx context.Context, req ModelListRequest) (ModelPage, error)
- func (c *Codex) Login(ctx context.Context, req LoginRequest) error
- func (c *Codex) Probe(ctx context.Context) error
- func (c *Codex) Run(ctx context.Context, req Request, callbacks Callbacks) (Response, error)
- func (c *Codex) Version(ctx context.Context) (string, error)
- type CodexAuthEvidence
- type CodexAuthMode
- type CodexAuthProbe
- type CodexTaskLauncher
- type Copilot
- func (c *Copilot) Auth(ctx context.Context) (AuthStatus, error)
- func (c *Copilot) ListModels(ctx context.Context, req ModelListRequest) (ModelPage, error)
- func (c *Copilot) Login(ctx context.Context, req LoginRequest) error
- func (c *Copilot) Run(ctx context.Context, req Request, callbacks Callbacks) (Response, error)
- func (c *Copilot) SupportsRole(Role) error
- func (c *Copilot) Version(ctx context.Context) (string, error)
- type Envelope
- type Event
- type Factory
- type InteractiveProcessFunc
- type LocalAuthHinter
- type LoginRequest
- type ModelInfo
- type ModelListRequest
- type ModelOption
- type ModelPage
- type PXPipeCapabilityCheck
- type PXPipeLaunchError
- type PXPipeLaunchSpec
- type PXPipeLauncher
- type PXPipePortChooser
- type PXPipeServer
- type PXPipeServerFactory
- type PXPipeServerSpec
- type PXPipeTaskLauncher
- type ProcessFunc
- type ProcessResult
- type ProcessSpec
- type ProviderError
- type Registry
- type Request
- type Response
- type Role
- type RoleSupporter
- type TokenUsage
- type UsageStatus
Constants ¶
const ( UsageComplete UsageStatus = "complete" UsageIncomplete UsageStatus = "incomplete" UsageUnreported UsageStatus = "unreported" // UsageStatus* aliases keep the field-oriented names convenient for // callers while Usage* follows the package's other typed-constant APIs. UsageStatusComplete = UsageComplete UsageStatusIncomplete = UsageIncomplete UsageStatusUnreported = UsageUnreported )
const CopilotSDKVersion = "v1.0.13-preview.4"
Variables ¶
var ( ErrUnsupportedProvider = errors.New("unsupported provider operation") ErrOutputLimit = errors.New("provider output exceeds configured limit") ErrMissingSession = errors.New("provider did not emit a durable session ID") ErrInvalidEnvelope = errors.New("provider returned an invalid JSON envelope") )
var ErrBudgetExceeded = errors.New("role execution budget exceeded")
Functions ¶
func BuildAntigravityArgs ¶
func BuildClaudeArgs ¶
func ClaudeFirstPartyRouteSupported ¶
func ClaudeFirstPartyRouteSupported(runtime task.RuntimeSnapshot, environ []string) bool
ClaudeFirstPartyRouteSupported prevents pxpipe from silently replacing a configured gateway, Bedrock, Vertex, or Foundry transport.
func ClaudePXPipeServerEnvironment ¶
ClaudePXPipeServerEnvironment builds a private Claude pxpipe-server environment. Provider credentials stay in the Claude child and are carried by the intercepted request; they are not copied into the helper process.
func CodexChatGPTRouteSupported ¶
func CodexChatGPTRouteSupported(runtime task.RuntimeSnapshot, environ []string) bool
CodexChatGPTRouteSupported reports whether the current routing snapshot and environment positively identify the supported first-party ChatGPT route. An empty snapshot is the default route only when authentication evidence has already established ChatGPT login; it is never authentication evidence by itself.
func CodexChatGPTRuntimeOverlay ¶
func CodexChatGPTRuntimeOverlay(runtime task.RuntimeSnapshot) task.RuntimeSnapshot
CodexChatGPTRuntimeOverlay returns an immutable, ephemeral routing copy for the verified ChatGPT transport. It intentionally discards custom auth and gateway fields while retaining the selected CLI path and credential refs.
func CodexConfigOverrides ¶
func CodexConfigOverrides(runtime task.RuntimeSnapshot) ([]string, error)
CodexConfigOverrides returns deterministic, non-secret `-c key=value` arguments for the exact safe routing snapshot. Runtime.SDKSettings is a typed-at-the-workflow boundary represented as JSON-compatible values so it can survive a restart without retaining credentials.
func CopilotEnvelopePrompt ¶
func CopilotPermissionHandler ¶
func CopilotPermissionHandler(req Request) copilot.PermissionHandlerFunc
func CopilotReadOnlyTools ¶
func CopilotReadOnlyTools() []string
func CopilotTools ¶
func DetectPXPipePath ¶
DetectPXPipePath discovers only an executable. Discovery is not evidence of provider authentication, a supported route, or model eligibility.
func NativeSchema ¶
NativeSchema returns the inline schema supplied to Codex/Claude. The schema is deliberately generated locally and contains no provider data.
func PXPipeServerEnvironment ¶
PXPipeServerEnvironment builds a private Codex pxpipe-server environment.
func ParseCodexLoginStatus ¶
ParseCodexLoginStatus answers the broader question used by doctor and configure: can this CLI run authenticated turns? It intentionally accepts Codex auth modes that are not safe for the ChatGPT-only pxpipe overlay. ParseCodexAuthStatus remains the stricter routing gate.
func PathWithinRepo ¶
PathWithinRepo canonicalizes both the repository and candidate path and rejects missing paths, symlink escapes, and arbitrary host reads.
func ResolveExecutable ¶
func RunInteractiveProcess ¶
func SanitizedEnv ¶
SanitizedEnv removes known provider bypass/auto-approval controls. It does not log or otherwise expose the remaining values.
func UsageFromMap ¶
func UsageFromMap(values map[string]any, inputIncludesCache bool) task.TokenUsage
UsageFromMap normalizes snake_case and camelCase usage payloads. For OpenAI and Copilot, cached tokens are a subset of input tokens; Anthropic reports cache read/write tokens separately, so callers select the correct total.
func UsageFromMapWithPresence ¶ added in v0.1.2
func UsageFromMapWithPresence(values map[string]any, inputIncludesCache bool) (task.TokenUsage, bool)
UsageFromMapWithPresence is UsageFromMap plus whether values contained at least one recognized numeric usage counter. Presence is deliberately independent from the counter values so an explicitly reported zero remains distinguishable from an absent usage report.
func ValidateEnvelope ¶
func ValidateSelection ¶
func ValidateSelection(role Role, model, effort, speed string, models []ModelInfo, adapter Adapter) error
ValidateSelection checks a provider-advertised model/effort/speed tuple. Empty effort and standard speed are valid defaults; every non-default value must be explicitly advertised by the selected model.
func VerifyReportedSelection ¶
func WritePathWithinRepo ¶
WritePathWithinRepo validates a file-write target, including a not-yet-created file. Every existing path component is resolved so a symlink cannot redirect the write outside the repository. The returned relative path uses slashes for matching against RoleMux's repository-relative scope syntax.
Types ¶
type Antigravity ¶
type Antigravity struct {
Path string
Process ProcessFunc
InteractiveProcess InteractiveProcessFunc
Env []string
}
Antigravity adapts Google's `agy` CLI. The CLI owns authentication, conversations, model discovery, sandboxing, and effort validation.
func NewAntigravity ¶
func NewAntigravity(path string) (*Antigravity, error)
func (*Antigravity) Auth ¶
func (a *Antigravity) Auth(ctx context.Context) (AuthStatus, error)
func (*Antigravity) ListModels ¶
func (a *Antigravity) ListModels(ctx context.Context, req ModelListRequest) (ModelPage, error)
func (*Antigravity) LocalAuthHint ¶
func (a *Antigravity) LocalAuthHint() AuthStatus
func (*Antigravity) Login ¶
func (a *Antigravity) Login(ctx context.Context, req LoginRequest) error
func (*Antigravity) SupportsRole ¶
func (a *Antigravity) SupportsRole(Role) error
type AuthStatus ¶
type AuthStatus struct {
Authenticated bool `json:"authenticated"`
Version string `json:"version,omitempty"`
Message string `json:"message,omitempty"`
// Account is used only as an in-memory cache discriminator. Catalog cache
// files persist its hash, never the raw account identifier.
Account string `json:"-"`
}
type Authenticator ¶
type Authenticator interface {
Login(context.Context, LoginRequest) error
}
Authenticator is optional so third-party adapters can remain read-only. Built-in CLI adapters implement it with their official interactive login.
type BudgetError ¶ added in v0.1.2
func (*BudgetError) Error ¶ added in v0.1.2
func (e *BudgetError) Error() string
func (*BudgetError) Unwrap ¶ added in v0.1.2
func (e *BudgetError) Unwrap() error
type Callbacks ¶
type Callbacks struct {
// SessionStarted must durably record an ID before a fresh call is
// considered successful. Adapters invoke it as soon as the provider emits
// its durable session/thread event.
SessionStarted func(string) error
Event func(Event) error
// Diagnostic receives concise, non-secret launch diagnostics. Adapters do
// not persist these messages and callers may leave it nil.
Diagnostic func(string)
}
type CapabilityProber ¶
CapabilityProber is implemented by adapters whose security contract relies on a particular installed CLI flag surface.
type Claude ¶
type Claude struct {
Path string
Process ProcessFunc
InteractiveProcess InteractiveProcessFunc
Env []string
Custom []ModelInfo
PXPipePath string
TaskLauncher PXPipeLauncher
}
func (*Claude) ListModels ¶
type Codex ¶
type Codex struct {
Path string
Process ProcessFunc
InteractiveProcess InteractiveProcessFunc
Env []string
// PXPipePath is discovered once for the adapter, then checked again at
// launch time so installing/removing the optional helper between turns is
// safe. TaskLauncher is an injectable lifecycle boundary for tests.
PXPipePath string
TaskLauncher CodexTaskLauncher
AuthProbe CodexAuthProbe
// ModelPages is a deterministic seam for discovery tests. Production uses
// the app-server model/list protocol when it is nil.
ModelPages func(context.Context, task.RuntimeSnapshot) ([]ModelInfo, string, string, error)
}
func (*Codex) ListModels ¶
type CodexAuthEvidence ¶
type CodexAuthEvidence struct {
Mode CodexAuthMode
Reason string
}
type CodexAuthMode ¶
type CodexAuthMode string
CodexAuthMode is transient evidence from the selected Codex executable's own login-status command. It is deliberately not part of RuntimeSnapshot.
const ( CodexAuthChatGPT CodexAuthMode = "chatgpt" CodexAuthAPIKey CodexAuthMode = "api_key" CodexAuthUnauthenticated CodexAuthMode = "unauthenticated" CodexAuthUnknown CodexAuthMode = "unknown" )
func ParseCodexAuthStatus ¶
func ParseCodexAuthStatus(data []byte) (CodexAuthMode, error)
ParseCodexAuthStatus recognizes the supported Codex 0.153.x status output without retaining account identifiers or token material. Unknown and contradictory output is intentionally rejected so callers can fall back to the untouched provider invocation.
type CodexAuthProbe ¶
CodexAuthProbe is injectable so the task-launch gate can be tested without invoking a real provider CLI. Implementations must not return credentials.
type CodexTaskLauncher ¶
type CodexTaskLauncher = PXPipeLauncher
CodexTaskLauncher remains an alias for compatibility with the Codex adapter tests while Claude and future providers share the generic lifecycle.
type Copilot ¶
type Copilot struct {
Path string
BaseDirectory string
InteractiveProcess InteractiveProcessFunc
Env []string
// Discover is a deterministic seam for catalog tests. Production uses the
// pinned SDK's ListModels method.
Discover func(context.Context) ([]copilot.ModelInfo, error)
}
func NewCopilot ¶
func (*Copilot) ListModels ¶
func (*Copilot) SupportsRole ¶
type Envelope ¶
type Envelope struct {
Role string `json:"role"`
Status string `json:"status,omitempty"`
Verdict string `json:"verdict,omitempty"`
Plan string `json:"plan,omitempty"`
Question string `json:"question,omitempty"`
Complexity string `json:"complexity,omitempty"`
WorkUnits []task.WorkUnit `json:"work_units,omitempty"`
Findings []task.Finding `json:"findings,omitempty"`
}
Envelope is the only model output accepted by the workflow. Fields are intentionally small: natural-language prose cannot substitute for status or verdict, and strict decoding rejects additions that could be misinterpreted.
type Event ¶
type Event struct {
Type string `json:"type"`
SessionID string `json:"session_id,omitempty"`
Model string `json:"model,omitempty"`
Effort string `json:"effort,omitempty"`
// Activity is a heartbeat that advances last_activity without changing
// model-turn or tool-call accounting.
Activity bool `json:"activity,omitempty"`
AgentTurn bool `json:"agent_turn,omitempty"`
ToolCall bool `json:"tool_call,omitempty"`
ToolName string `json:"tool_name,omitempty"`
Raw json.RawMessage `json:"raw,omitempty"`
}
func EventsFromLine ¶ added in v0.1.2
EventsFromLine reduces provider-specific JSONL into non-secret lifecycle facts. Raw arguments, command output, and model prose are never forwarded.
type Factory ¶
Factory constructs one provider adapter and returns its resolved executable path. repoRoot is available for adapters that keep repository-private state.
type InteractiveProcessFunc ¶
type InteractiveProcessFunc func(context.Context, string, []string, string, []string, io.Reader, io.Writer, io.Writer) error
InteractiveProcessFunc is the terminal-attached process seam used by provider login commands.
type LocalAuthHinter ¶
type LocalAuthHinter interface {
LocalAuthHint() AuthStatus
}
LocalAuthHinter lets an adapter report credential presence without starting the provider. Configure may use this to stay responsive; doctor and task execution still use the adapter's authoritative live checks.
type LoginRequest ¶
type ModelInfo ¶
type ModelInfo struct {
ID string `json:"id"`
Label string `json:"label,omitempty"`
Description string `json:"description,omitempty"`
Provider string `json:"provider"`
Origin string `json:"origin"`
Availability string `json:"availability"`
AgeSeconds int64 `json:"age_seconds,omitempty"`
ContextWindowTokens int `json:"context_window_tokens,omitempty"`
MaxContextWindowTokens int `json:"max_context_window_tokens,omitempty"`
MaxPromptTokens int `json:"max_prompt_tokens,omitempty"`
MaxOutputTokens int `json:"max_output_tokens,omitempty"`
IsDefault bool `json:"is_default,omitempty"`
Efforts []string `json:"efforts,omitempty"`
EffortOptions []ModelOption `json:"effort_options,omitempty"`
DefaultEffort string `json:"default_effort,omitempty"`
SpeedOptions []ModelOption `json:"speed_options,omitempty"`
DefaultSpeed string `json:"default_speed,omitempty"`
Aliases []string `json:"aliases,omitempty"`
Custom bool `json:"custom"`
Account string `json:"-"`
}
func PaginateModelPages ¶
func PaginateModelPages(ctx context.Context, first func(context.Context, string) (ModelPage, error)) ([]ModelInfo, string, error)
PaginateModelPages follows every non-empty cursor and detects cursor loops. The function is used by live Codex discovery and is independently testable.
type ModelListRequest ¶
type ModelListRequest struct {
Refresh bool
Runtime task.RuntimeSnapshot
}
type ModelOption ¶
type ModelOption struct {
ID string `json:"id"`
Label string `json:"label,omitempty"`
Description string `json:"description,omitempty"`
}
ModelOption is a provider-advertised setting value. Descriptions are kept optional because not every CLI exposes them.
type PXPipeCapabilityCheck ¶
type PXPipeCapabilityCheck func(context.Context, ProcessSpec) error
type PXPipeLaunchError ¶
PXPipeLaunchError records whether a helper failure happened before the provider could have accepted the task. Only that phase is eligible for a direct fallback; after the boundary, replaying the prompt could duplicate work.
func (*PXPipeLaunchError) Error ¶
func (e *PXPipeLaunchError) Error() string
func (*PXPipeLaunchError) Unwrap ¶
func (e *PXPipeLaunchError) Unwrap() error
type PXPipeLaunchSpec ¶
type PXPipeLaunchSpec struct {
PXPipePath string
Provider ProcessSpec
ProviderName string
ServerEnv []string
EventsFile string
RoutePrefix string
TaskStartsOnLaunch bool
Diagnostic func(string)
}
PXPipeLaunchSpec is the boundary between provider transport preparation and the helper lifecycle. Provider fields are copied into the private server environment; the helper never receives RoleMux's durable runtime snapshot.
type PXPipeLauncher ¶
type PXPipeLauncher interface {
Launch(context.Context, PXPipeLaunchSpec) (ProcessResult, error)
}
PXPipeLauncher changes only a provider task launch. It is intentionally separate from ProcessFunc so auth, version, login, discovery, and selection probes cannot accidentally pass through pxpipe.
type PXPipeServer ¶
type PXPipeServerFactory ¶
type PXPipeServerFactory func(context.Context, PXPipeServerSpec) (PXPipeServer, error)
type PXPipeServerSpec ¶
type PXPipeServerSpec struct {
Path string
Env []string
Dir string
Port int
StartupTimeout time.Duration
Readiness func(context.Context, string) error
}
PXPipeServerSpec and PXPipeServer are injectable seams for lifecycle tests. The production server requires its owned child to announce the configured address and then pass an HTTP readiness check before it is accepted.
type PXPipeTaskLauncher ¶
type PXPipeTaskLauncher struct {
Path string
Process ProcessFunc
ServerFactory PXPipeServerFactory
PortChooser PXPipePortChooser
CapabilityCheck PXPipeCapabilityCheck
MaxAttempts int
StartupTimeout time.Duration
ShutdownTimeout time.Duration
}
PXPipeTaskLauncher owns one foreground server for one provider turn. It never talks to, reconfigures, or stops an existing user daemon.
func (*PXPipeTaskLauncher) Launch ¶
func (p *PXPipeTaskLauncher) Launch(ctx context.Context, spec PXPipeLaunchSpec) (ProcessResult, error)
type ProcessFunc ¶
type ProcessFunc func(context.Context, ProcessSpec) (ProcessResult, error)
ProcessFunc is injectable for adapter tests. Production adapters use RunProcess, which drains both pipes concurrently.
type ProcessResult ¶
type ProcessResult struct {
Stdout []byte
Stderr []byte
ExitCode int
// ProcessStarted is true only after the OS accepted the child. A false
// value is reliable evidence that no provider/helper process could run.
// Injectable ProcessFunc implementations should set it when they start a
// child before returning a setup error.
ProcessStarted bool
}
func RunProcess ¶
func RunProcess(ctx context.Context, spec ProcessSpec) (ProcessResult, error)
type ProcessSpec ¶
type ProcessSpec struct {
Path string
Args []string
Dir string
Env []string
Stdin string
MaxOutputBytes int64
// StdoutLine is invoked as each complete stdout line arrives. It is used
// for durable provider session events that must be saved before the child
// exits. The complete stdout stream is still returned in ProcessResult.
StdoutLine func([]byte) error
}
type ProviderError ¶
type ProviderError struct {
Code string `json:"code"`
Message string `json:"message"`
Retryable bool `json:"retryable"`
KnownSession bool `json:"known_session"`
SessionID string `json:"session_id,omitempty"`
Cause error `json:"-"`
}
func (*ProviderError) Error ¶
func (e *ProviderError) Error() string
func (*ProviderError) Unwrap ¶
func (e *ProviderError) Unwrap() error
type Registry ¶
type Registry struct {
// contains filtered or unexported fields
}
Registry is the only provider-construction boundary used by the CLI. A new provider adds an Adapter implementation and registers one factory; workflow, catalog, picker, and command code remain provider-agnostic.
func BuiltinRegistry ¶
func BuiltinRegistry() *Registry
BuiltinRegistry contains the adapters shipped in this binary.
func NewRegistry ¶
func NewRegistry() *Registry
type Request ¶
type Request struct {
Role Role
Operation string
Prompt string
Model string
Effort string
Speed string
RepoRoot string
Scope string
// SkillDirectories are provider-native roots selected by RoleMux. Adapters
// that expose an explicit skill-loading API may use them; others rely on
// their native discovery while receiving the same bounded metadata note.
SkillDirectories []string
SessionID string
Resume bool
Sandbox string
Runtime task.RuntimeSnapshot
Budget task.RoleBudget
// MaxOutputBytes is a hard process-output bound. Zero uses a safe default.
MaxOutputBytes int64
}
type Response ¶
type Response struct {
Text string `json:"text,omitempty"`
SessionID string `json:"session_id"`
ReportedModel string `json:"reported_model,omitempty"`
ReportedEffort string `json:"reported_effort,omitempty"`
Envelope *Envelope `json:"envelope,omitempty"`
Raw json.RawMessage `json:"raw,omitempty"`
Usage task.TokenUsage `json:"usage,omitempty"`
UsageStatus UsageStatus `json:"usage_status,omitempty"`
// UsageCumulative means token counters cover the whole resumed provider
// conversation rather than only this invocation.
UsageCumulative bool `json:"usage_cumulative,omitempty"`
}
type RoleSupporter ¶
RoleSupporter lets an adapter fail before model selection when it cannot safely perform a role. Adapters that omit it are assumed to support all roles.
type TokenUsage ¶
type TokenUsage = task.TokenUsage
type UsageStatus ¶ added in v0.1.2
type UsageStatus string