llm

package
v0.6.96 Latest Latest
Warning

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

Go to latest
Published: May 5, 2026 License: MIT Imports: 22 Imported by: 0

Documentation

Overview

Package llm provides a unified interface for running LLM agent CLIs (claude, codex, gemini, kimi, etc.) as subprocess backends.

Instead of implementing LLM API clients, agentbridge drives each vendor's official CLI tool as a subprocess and exposes a single Backend interface. Prompts are assembled by the caller and passed as UserText; the library is responsible only for translating a RunRequest into the correct CLI invocation and parsing the CLI's stdout/stderr back into a RunResult.

Index

Constants

View Source
const (
	ProviderCodex    = "codex"
	ProviderClaude   = "claude"
	ProviderGemini   = "gemini"
	ProviderKimi     = "kimi"
	ProviderOpenCode = "opencode"
)

Variables

View Source
var ErrInteractiveClosed = errors.New("interactive session is closed")
View Source
var ErrNoActiveTurn = errors.New("no active turn to steer")
View Source
var ErrSteerUnsupported = errString("provider does not support native steer")

Functions

This section is empty.

Types

type Backend

type Backend interface {
	Run(ctx context.Context, req RunRequest) (RunResult, error)
}

Backend runs a single LLM agent CLI.

func NewBackend

func NewBackend(cfg FactoryConfig) (Backend, error)

NewBackend is a convenience wrapper around NewProvider that returns the Backend directly.

type ClaudeConfig

type ClaudeConfig struct {
	Command      string
	Timeout      time.Duration
	Env          map[string]string
	WorkspaceDir string
	// DisableStreamJSON makes NewInteractiveProviderSession fall back to the
	// one-shot claude runner. It is intended for experimental rollback only.
	DisableStreamJSON bool
	// ProfileOverrides maps profile name → per-profile runner overrides.
	ProfileOverrides map[string]ProfileRunnerConfig
}

ClaudeConfig configures the claude CLI backend.

type CodexConfig

type CodexConfig struct {
	Command            string
	Timeout            time.Duration
	DefaultIdleTimeout time.Duration
	HighIdleTimeout    time.Duration
	XHighIdleTimeout   time.Duration
	Model              string
	ReasoningEffort    string
	Env                map[string]string
	WorkspaceDir       string
	DefaultExecPolicy  ExecPolicyConfig
	// ProfileOverrides maps profile name → per-profile runner overrides.
	ProfileOverrides map[string]ProfileRunnerConfig
}

CodexConfig configures the codex CLI backend.

type ErrUnsupportedProvider added in v0.6.94

type ErrUnsupportedProvider string

func (ErrUnsupportedProvider) Error added in v0.6.94

func (e ErrUnsupportedProvider) Error() string

type ExecPolicyConfig added in v0.4.0

type ExecPolicyConfig struct {
	Sandbox        string
	AskForApproval string
	AddDirs        []string
}

ExecPolicyConfig controls sandbox and approval settings for backends that support them (currently codex only).

type FactoryConfig

type FactoryConfig struct {
	Provider string
	Codex    CodexConfig
	Claude   ClaudeConfig
	Gemini   GeminiConfig
	Kimi     KimiConfig
	OpenCode OpenCodeConfig
}

FactoryConfig holds configuration for all supported backends. Only the fields relevant to the selected Provider need to be populated.

type GeminiConfig added in v0.5.10

type GeminiConfig struct {
	Command      string
	Timeout      time.Duration
	Env          map[string]string
	WorkspaceDir string
	// ProfileOverrides maps profile name → per-profile runner overrides.
	ProfileOverrides map[string]ProfileRunnerConfig
}

GeminiConfig configures the gemini CLI backend.

type InteractiveDriver added in v0.6.94

type InteractiveDriver interface {
	SteerMode() SteerMode
	StartTurn(ctx context.Context, req RunRequest) (TurnRef, error)
	SteerTurn(ctx context.Context, turn TurnRef, req RunRequest) error
	InterruptTurn(ctx context.Context, turn TurnRef) error
	Events() <-chan TurnEvent
	Close() error
}

InteractiveDriver is implemented by provider-specific long-lived transports.

type InteractiveSession added in v0.6.94

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

InteractiveSession serializes user input for one logical conversation.

If the driver supports native steer/enqueue, Submit injects or appends new input into the active provider session. Otherwise Submit queues input and starts the next turn after completion.

func NewInteractiveProviderSession added in v0.6.94

func NewInteractiveProviderSession(cfg FactoryConfig) (*InteractiveSession, error)

NewInteractiveProviderSession creates one logical interactive conversation for the configured provider.

func NewInteractiveSession added in v0.6.94

func NewInteractiveSession(driver InteractiveDriver) *InteractiveSession

NewInteractiveSession wraps a provider driver with common steer/queue state.

func (*InteractiveSession) Close added in v0.6.94

func (s *InteractiveSession) Close() error

Close stops the underlying provider process.

func (*InteractiveSession) Events added in v0.6.94

func (s *InteractiveSession) Events() <-chan TurnEvent

Events returns the normalized event stream for this conversation.

func (*InteractiveSession) Interrupt added in v0.6.94

func (s *InteractiveSession) Interrupt(ctx context.Context) error

Interrupt requests cancellation of the active turn.

func (*InteractiveSession) Steer added in v0.6.94

Steer injects/appends input into the active turn and fails if there is no active provider-native turn. It never starts a new turn.

func (*InteractiveSession) SteerMode added in v0.6.94

func (s *InteractiveSession) SteerMode() SteerMode

SteerMode returns the active provider's busy-turn behavior.

func (*InteractiveSession) Submit added in v0.6.94

Submit starts a turn, steers the active turn, or queues the input depending on the provider capability and current state.

type KimiConfig

type KimiConfig struct {
	Command      string
	Timeout      time.Duration
	Env          map[string]string
	WorkspaceDir string
	// ProfileOverrides maps profile name → per-profile runner overrides.
	ProfileOverrides map[string]ProfileRunnerConfig
}

KimiConfig configures the kimi CLI backend.

type MultiBackend added in v0.5.18

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

MultiBackend routes Run calls to one of several backends based on RunRequest.Provider, falling back to the default provider when unset.

func NewMultiBackend added in v0.5.18

func NewMultiBackend(defaultProvider string, backends map[string]Backend) (*MultiBackend, error)

NewMultiBackend constructs a MultiBackend. At least one backend must be provided. When defaultProvider is empty and exactly one backend is registered, that backend becomes the default.

func (*MultiBackend) Run added in v0.5.18

func (m *MultiBackend) Run(ctx context.Context, req RunRequest) (RunResult, error)

Run dispatches to the backend for req.Provider, or the default backend when req.Provider is empty.

type OpenCodeConfig added in v0.6.94

type OpenCodeConfig struct {
	Command      string
	Timeout      time.Duration
	Model        string
	Variant      string
	Env          map[string]string
	WorkspaceDir string
	// ServerURL connects to an already-running opencode server instead of
	// spawning `opencode serve`.
	ServerURL string
	// DisableAppServer makes NewInteractiveProviderSession fall back to the
	// one-shot `opencode run` wrapper. It is intended for experimental rollback.
	DisableAppServer bool
	// ProfileOverrides maps profile name → per-profile runner overrides.
	ProfileOverrides map[string]ProfileRunnerConfig
}

OpenCodeConfig configures the opencode CLI backend.

type ProfileRunnerConfig added in v0.6.3

type ProfileRunnerConfig struct {
	Command         string
	Timeout         time.Duration
	ProviderProfile string
	ExecPolicy      ExecPolicyConfig
}

ProfileRunnerConfig carries per-profile overrides keyed by the profile name (e.g. "executor", "reviewer").

type ProgressFunc

type ProgressFunc func(step string)

ProgressFunc is called with intermediate agent messages while a run is in progress. Code-editing backends may also emit file-change notifications prefixed with "[file_change] ".

type Provider

type Provider interface {
	Backend() Backend
}

Provider wraps a Backend and is returned by NewProvider.

func NewProvider

func NewProvider(cfg FactoryConfig) (Provider, error)

NewProvider constructs a Provider for the backend specified by cfg.Provider. An empty Provider defaults to codex.

type RawEvent added in v0.6.94

type RawEvent struct {
	// Kind identifies the event category:
	//   "stdout_line" – every raw stdout JSON-line from the CLI
	//   "reasoning"   – a reasoning/thinking block (codex)
	//   "tool_call"   – a command_execution item (codex)
	//   "tool_use"    – a tool/tool_use block in an assistant message (claude, kimi, opencode)
	Kind string
	// Line is the original JSON-lines string from the CLI stdout (always set).
	Line string
	// Detail is a human-readable parsed summary (set for reasoning, tool_call,
	// and tool_use; empty for stdout_line).
	Detail string
}

RawEvent is a raw backend-internal event emitted before higher-level filtering. It is delivered via RunRequest.OnRawEvent when non-nil.

type RawEventFunc added in v0.6.94

type RawEventFunc func(event RawEvent)

RawEventFunc is called with each raw backend-internal event. It is optional; nil disables raw event delivery.

type RunRequest

type RunRequest struct {
	// ThreadID resumes an existing session when non-empty.
	ThreadID string
	// AgentName is informational metadata; not passed to the CLI.
	AgentName string
	// UserText is the fully assembled prompt sent to the CLI.
	UserText string
	// Scene is caller-defined metadata; not passed to the CLI.
	Scene string
	// Provider selects which backend to use when running through a MultiBackend.
	Provider string
	// Model overrides the default model for this request.
	Model string
	// Variant overrides the default variant for this request (e.g. "max", "high", "minimal").
	Variant string
	// Profile selects a named configuration profile defined in the backend config.
	Profile string
	// ReasoningEffort is forwarded to backends that support it (codex).
	ReasoningEffort string
	// Personality is forwarded to backends that accept it as a CLI flag (codex).
	Personality string
	// WorkspaceDir overrides the working directory for this request.
	WorkspaceDir string
	// ExecPolicy overrides sandbox/approval settings for this request (codex).
	ExecPolicy ExecPolicyConfig
	// Env is merged over the process environment before spawning the CLI.
	Env map[string]string
	// OnProgress receives streaming progress updates during execution.
	OnProgress ProgressFunc
	// OnRawEvent optionally receives low-level backend-internal events before
	// any higher-level filtering is applied. See RawEvent for the delivered
	// kinds. Nil disables raw event delivery.
	OnRawEvent RawEventFunc
}

RunRequest is the input to Backend.Run. The caller is responsible for assembling the final prompt in UserText; the library does not perform any prompt templating.

type RunResult

type RunResult struct {
	// Reply is the final assistant message produced by the CLI.
	Reply string
	// NextThreadID is the session/thread ID to pass as ThreadID on the next
	// call to continue the conversation.
	NextThreadID string
	// GoalDone indicates that the agent has signalled goal completion.
	GoalDone bool
	// Usage contains token counts if the backend reported them.
	Usage Usage
}

RunResult is the output from Backend.Run.

type SteerMode added in v0.6.94

type SteerMode string

SteerMode describes how a provider handles input submitted while a turn is already running.

const (
	// SteerModeNative means the provider can inject input into the active turn.
	SteerModeNative SteerMode = "native"
	// SteerModeNativeEnqueue means the provider can append input to the active
	// session without agentbridge waiting for the current turn to finish. The
	// provider may consume it at the next model/tool boundary.
	SteerModeNativeEnqueue SteerMode = "native_enqueue"
	// SteerModeQueueWhenBusy means agentbridge queues input until the turn is idle.
	SteerModeQueueWhenBusy SteerMode = "queue_when_busy"
	// SteerModeInterruptOnly means the provider has no safe enqueue semantics.
	SteerModeInterruptOnly SteerMode = "interrupt_only"
)

type SubmitMode added in v0.6.94

type SubmitMode string

SubmitMode describes how a submitted user message was accepted.

const (
	SubmitStarted SubmitMode = "started"
	SubmitSteered SubmitMode = "steered"
	SubmitQueued  SubmitMode = "queued"
)

type SubmitResult added in v0.6.94

type SubmitResult struct {
	ThreadID   string
	TurnID     string
	Mode       SubmitMode
	QueueDepth int
}

SubmitResult is returned immediately after input is accepted.

type TurnEvent added in v0.6.94

type TurnEvent struct {
	Provider string
	ThreadID string
	TurnID   string
	Kind     TurnEventKind
	Text     string
	Usage    Usage
	Err      error
	Raw      string
}

TurnEvent is the provider-neutral event stream used by interactive sessions.

type TurnEventKind added in v0.6.94

type TurnEventKind string

TurnEventKind is a normalized event emitted by interactive backends.

const (
	TurnEventStarted TurnEventKind = "turn_started"
	// TurnEventAssistantText contains a complete assistant message. Providers
	// that stream chunks coalesce them before emitting this normalized event.
	TurnEventAssistantText TurnEventKind = "assistant_text"
	// TurnEventUserText contains user-authored text observed on a provider
	// event stream.
	TurnEventUserText      TurnEventKind = "user_text"
	TurnEventReasoning     TurnEventKind = "reasoning"
	TurnEventToolUse       TurnEventKind = "tool_use"
	TurnEventFileChange    TurnEventKind = "file_change"
	TurnEventSteerConsumed TurnEventKind = "steer_consumed"
	TurnEventCompleted     TurnEventKind = "turn_completed"
	TurnEventInterrupted   TurnEventKind = "turn_interrupted"
	TurnEventError         TurnEventKind = "error"
)

type TurnRef added in v0.6.94

type TurnRef struct {
	ThreadID string
	TurnID   string
}

TurnRef identifies an in-flight provider turn.

type Usage added in v0.5.27

type Usage struct {
	InputTokens       int64
	CachedInputTokens int64
	OutputTokens      int64
}

Usage holds token consumption reported by the CLI backend. Fields are zero when the backend does not expose usage information.

func (Usage) HasUsage added in v0.5.27

func (u Usage) HasUsage() bool

HasUsage reports whether any token counts were captured.

func (Usage) TotalTokens added in v0.5.27

func (u Usage) TotalTokens() int64

TotalTokens returns InputTokens + OutputTokens.

Directories

Path Synopsis
internal
providers
claude
Package claude drives the claude CLI as a subprocess and parses its stream-json output into a plain text reply.
Package claude drives the claude CLI as a subprocess and parses its stream-json output into a plain text reply.
codex
Package codex drives the codex CLI as a subprocess and parses its JSON-lines output into a plain text reply with optional file-change events.
Package codex drives the codex CLI as a subprocess and parses its JSON-lines output into a plain text reply with optional file-change events.
gemini
Package gemini drives the gemini CLI as a subprocess and parses its JSON output into a plain text reply.
Package gemini drives the gemini CLI as a subprocess and parses its JSON output into a plain text reply.
kimi
Package kimi drives the kimi CLI as a subprocess and parses its stream-json output into a plain text reply.
Package kimi drives the kimi CLI as a subprocess and parses its stream-json output into a plain text reply.
opencode
Package opencode drives the opencode CLI as a subprocess and parses its JSON-lines output into a plain text reply, session ID, and token usage.
Package opencode drives the opencode CLI as a subprocess and parses its JSON-lines output into a plain text reply, session ID, and token usage.

Jump to

Keyboard shortcuts

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