Help us shape the future of Go! Take the 2026 Go Developer Survey

droid

package
v0.8.12 Latest Latest
Warning

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

Go to latest
Published: Sep 4, 2026 License: Apache-2.0 Imports: 15 Imported by: 0

Documentation

Overview

Package droid implements agent.Adapter against Factory AI's `droid` CLI (the `droid exec` non-interactive subcommand). It mirrors agent/claude; the agent package itself stays import-free of harness specifics.

Capabilities().NativeSchema is FALSE: droid has no native JSON-schema flag. The adapter runs `droid exec -o stream-json`, parses a JSON object out of the terminal "completion" event's finalText into a map, and the engine re-validates it against the step's output_schema (engine/schema.go ValidateOutputMap). This is the spec §4.2 layer-2 path (conformance Bucket 15).

Gate independence is enforced structurally: every Launch is a fresh `droid exec`; the command line NEVER contains --session-id / --resume / --fork; ValidateConfig rejects with-keys session_id/resume/fork/continue.

Output: `droid exec -o stream-json` emits newline-delimited JSON events PROGRESSIVELY as the agent works (system/message/tool_call/tool_result, then a terminal "completion" or "error"). Launch scans those lines and emits one AgentEvent per line as droid produces it (the realtime tap renders them live), capturing the terminal completion/error for the AgentOutcome. γ contract: returns immediately with both channels open; events closes before outcome.

Index

Constants

View Source
const AdapterRef = "factory/droid"

AdapterRef is the agent-runtime identifier this package's Adapter returns from Ref(). Must match the workflow `uses:` literal byte-for-byte.

Variables

View Source
var DefaultEnvAllowlist = []string{
	"FACTORY_API_KEY",
}

DefaultEnvAllowlist is the canonical set of env-var names the droid adapter reads. Single source of truth for the CLI's --agent-env default and resume's implicit allowlist. droid authenticates headlessly only via FACTORY_API_KEY.

View Source
var ErrAuthFailureSentinel = errors.New("agent/droid: droid exec reported an authentication failure")

ErrAuthFailureSentinel marks a droid terminal "error" event whose message names auth/FACTORY_API_KEY ("set a valid FACTORY_API_KEY"). Launch wraps it as PERMANENT (agent.ErrPermissionDenied → permanent_failure): the message is a deterministic bad/missing-key signal, so retrying only burns the budget; transient auth-infra faults surface as 5xx/timeouts on the other retryable paths instead. Consistent with the claude and awf/llm adapters.

Functions

This section is empty.

Types

type Adapter

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

Adapter is the agent.Adapter implementation for Factory droid. One Adapter per CLI invocation; multiple Launch calls per Adapter; all state read-only after construction (no session state crosses Launch boundaries).

func New

func New(opts ...Option) (*Adapter, error)

New constructs an Adapter.

func (*Adapter) Capabilities

func (*Adapter) Capabilities() agent.Caps

Capabilities returns Caps{NativeSchema: false} — droid structures output via the layer-2 path; the engine validates conformance.

func (*Adapter) Launch

func (a *Adapter) Launch(ctx context.Context, handle container.Handle, inv agent.AgentInvocation) (<-chan agent.AgentEvent, <-chan agent.AgentOutcome, error)

Launch runs `droid exec -o stream-json ...` inside handle via the streaming Backend.Exec. -o stream-json emits NDJSON flushed LIVE (verified v0.138.0: a system/init line, message lines, tool_call/tool_result lines, then a terminal "completion" — or a terminal "error"). Launch scans those lines and emits ONE AgentEvent per line as it arrives (the realtime tap renders these live), capturing the terminal completion/error for the AgentOutcome. γ contract: returns IMMEDIATELY with both channels open; events closes BEFORE outcome (defer LIFO); never reuses a session.

func (*Adapter) Ref

func (*Adapter) Ref() string

Ref returns the agent-runtime identifier this adapter satisfies.

func (*Adapter) RequiredEnv

func (*Adapter) RequiredEnv() []string

RequiredEnv implements agent.CredentialNamer. Returns the CREDENTIAL env var name droid authenticates with. FACTORY_API_KEY is defined in DefaultEnvAllowlist.

func (*Adapter) ValidateConfig

func (a *Adapter) ValidateConfig(with ir.RawConfig) error

ValidateConfig enforces droid's with-schema (same deterministic order as claude: reject-inline/session → unknown-key → required-prompt → per-key types → BYOK-or-API-key policy). Deterministic (sorted keys) — runs twice per node.

func (*Adapter) Version

func (a *Adapter) Version(ctx context.Context, handle container.Handle) (string, error)

Version runs `droid --version` inside handle and parses the leading semver. Recorded in run.started.Runtimes; re-resolved on resume; drift hard-errors.

type ErrMissingAPIKey

type ErrMissingAPIKey struct {
	AvailableKeys []string
}

ErrMissingAPIKey is returned by ValidateConfig when FACTORY_API_KEY is absent from the adapter's env allowlist. droid has no headless auth fallback, so we fail at the run-start walk with an actionable message.

func (*ErrMissingAPIKey) Error

func (e *ErrMissingAPIKey) Error() string

type ErrRuntimeNotFound

type ErrRuntimeNotFound struct {
	Ref       string
	Container string
	Cause     error
}

ErrRuntimeNotFound is returned by Version when `droid --version` failed.

func (*ErrRuntimeNotFound) Error

func (e *ErrRuntimeNotFound) Error() string

func (*ErrRuntimeNotFound) Unwrap

func (e *ErrRuntimeNotFound) Unwrap() error

type ErrSessionReuseAttempted

type ErrSessionReuseAttempted struct {
	Key string
}

ErrSessionReuseAttempted is returned by ValidateConfig when a with-key names a flag that would re-use a prior droid session (session_id / resume / fork / continue). Gate independence (spec §5.5) is engine-enforced, not convention.

func (*ErrSessionReuseAttempted) Error

func (e *ErrSessionReuseAttempted) Error() string

type ErrStreamParse

type ErrStreamParse struct {
	Line  []byte
	Cause error
}

ErrStreamParse is returned by parseStreamEvent when a stdout line fails to decode as a -o stream-json event. Launch tolerates a stray non-JSON line (skips it), so this type does not itself propagate out of Launch; it backs the parse unit tests.

func (*ErrStreamParse) Error

func (e *ErrStreamParse) Error() string

func (*ErrStreamParse) Unwrap

func (e *ErrStreamParse) Unwrap() error

type ErrUnexpectedExit

type ErrUnexpectedExit struct {
	ExitCode int
	Stderr   string
}

ErrUnexpectedExit is sent (bare) on Launch's outcome channel when droid exited with no parseable result envelope on stdout AND stderr matched no known config-error pattern. The engine's classifier maps unrecognized error types to retryable_failure via its default branch, so a bare ErrUnexpectedExit is treated as transport-class (retryable) without an explicit ErrAgentLaunch wrap.

func (*ErrUnexpectedExit) Error

func (e *ErrUnexpectedExit) Error() string

type Option

type Option func(*Adapter)

Option configures the Adapter at construction time (functional-options).

func WithBackend

func WithBackend(b container.Backend) Option

WithBackend supplies the container.Backend used by Version and Launch.

func WithEnv

func WithEnv(env map[string]string) Option

WithEnv supplies the env-var allowlist forwarded into each `droid exec` exec environment. Copied into agent.SecretEnv (redacts under fmt verbs; json:"-" so secrets never reach the state log). Empty map permitted.

Jump to

Keyboard shortcuts

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