Documentation
¶
Index ¶
- Constants
- Variables
- func ApplyDefaults(cfg *SessionConfig, ac *AdapterConfig)
- func ClassifiedErrorContent(msg string, retryable bool) string
- func ConvertToLinuxPath(path string) string
- func EscapeShellArg(arg string) string
- func ExtractText(parts []ContentPart) string
- func HasNonTextContent(parts []ContentPart) bool
- func IsNonRetryableError(msg string) bool
- func IsRetryableError(err error) bool
- func IsRetryableUpstream(msg string) bool
- func IsSandboxRejection(msg string) bool
- func NewLargeLineScanner(r io.Reader, maxTokenSize int) *bufio.Scanner
- func NormalizeExecutionMode(mode string) string
- func OverlayConfigDir(sessionDir, configDir string, allowlist []string) error
- func ParseWSLPath(path string) (distro string, linuxPath string, isWSL bool)
- func PhysicalToHostPath(physical string) string
- func ReassembleToolResultParts(events []StreamEvent) (string, error)
- func Register(name string, factory FactoryFunc)
- func Retry(ctx context.Context, cfg *RetryConfig, fn func() error) error
- func SortVFSMounts(mounts []VFSMount)
- func StripMarkdownCodeFence(text string) string
- func TruncateToolResult(content string, maxBytes int) string
- func VFSMountsToDockerArgs(mounts []VFSMount) []string
- func ValidateContentParts(parts []ContentPart) error
- func VerifyWSLRuntime(ctx context.Context, distro string, cmdName string) error
- func VfsToContainerPath(vfsPath string) string
- type AdapterConfig
- type CodingAgent
- type ContentPart
- type EventType
- type FactoryFunc
- type FallbackToolCall
- type ImageSource
- type RetryConfig
- type Session
- type SessionConfig
- type SessionOption
- func WithAgentSessionID(id string) SessionOption
- func WithAllowedTools(tools []string) SessionOption
- func WithConfigDir(dir string) SessionOption
- func WithEnvVars(vars map[string]string) SessionOption
- func WithExecutionMode(mode string) SessionOption
- func WithIdleTimeout(seconds int) SessionOption
- func WithMaxExecution(seconds int) SessionOption
- func WithMaxToolResultBytes(n int) SessionOption
- func WithMaxTurns(n int) SessionOption
- func WithModel(model string) SessionOption
- func WithPrompt(prompt string) SessionOption
- func WithScannerMaxTokenBytes(n int) SessionOption
- func WithSessionDir(dir string) SessionOption
- func WithVFSMounts(mounts []VFSMount) SessionOption
- func WithWorkDir(dir string) SessionOption
- type SessionRecord
- type SessionStore
- type StdinWriter
- type StreamEvent
- type VFSMount
- type WSLCommandBuilder
Constants ¶
const ( // ExecutionModeInteractive keeps stdin open for mid-task user responses. ExecutionModeInteractive = "interactive" // ExecutionModeSingleShot closes stdin after the initial prompt (legacy behavior). ExecutionModeSingleShot = "single_shot" )
const ( ErrorCodeUpstreamOverloaded = "upstream_overloaded" ErrorCodeUpstreamError = "upstream_error" )
const ( // DefaultMaxAttempts is the default maximum number of retry attempts. DefaultMaxAttempts = 10 // DefaultRetryInterval is the default interval between retry attempts. DefaultRetryInterval = 3 * time.Second )
const ( StatusActive = "active" StatusSuspended = "suspended" StatusCompleted = "completed" StatusError = "error" StatusClosed = "closed" )
Session status constants.
const ( // DefaultMaxSSEDataLineBytes is the max JSON size for a single SSE data line. DefaultMaxSSEDataLineBytes = 64 * 1024 // 64 KiB // DefaultSSEChunkContentBytes is the max content bytes per tool_result_part chunk. DefaultSSEChunkContentBytes = 48 * 1024 // 48 KiB )
const ( // DefaultScannerMaxTokenSize is the default max JSONL line size for agent stdout scanners. DefaultScannerMaxTokenSize = 4 * 1024 * 1024 // 4MB // DefaultMaxToolResultBytes is the default max EventToolResult content size for SSE relay. DefaultMaxToolResultBytes = 256 * 1024 // 256KB )
Variables ¶
var ErrMultimodalNotSupported = errors.New("multimodal inputs are not supported by this agent")
ErrMultimodalNotSupported is returned by agents that do not support non-text content (e.g., images).
Functions ¶
func ApplyDefaults ¶
func ApplyDefaults(cfg *SessionConfig, ac *AdapterConfig)
ApplyDefaults applies AdapterConfig default values to SessionConfig. Fields explicitly set by SessionOption are not overwritten. Priority: SessionOption > AdapterConfig.Default* > zero value
func ClassifiedErrorContent ¶ added in v0.1.14
ClassifiedErrorContent appends a stable error code tag for SSE EventError content.
func ConvertToLinuxPath ¶ added in v0.1.1
ConvertToLinuxPath converts a Windows path (which may be a WSL path) to a Linux-style path. If it is not a WSL path, it returns the input unchanged.
func EscapeShellArg ¶ added in v0.1.1
EscapeShellArg escapes a string to be safe as a shell argument inside sh -c.
func ExtractText ¶ added in v0.1.1
func ExtractText(parts []ContentPart) string
ExtractText concatenates all text blocks from a []ContentPart. Non-text blocks are ignored. Returns empty string if no text blocks exist.
func HasNonTextContent ¶ added in v0.1.1
func HasNonTextContent(parts []ContentPart) bool
HasNonTextContent returns true if any ContentPart has a type other than "text".
func IsNonRetryableError ¶ added in v0.1.15
IsNonRetryableError reports a fatal Codex CLI / auth / argv failure that must not trigger process re-exec.
func IsRetryableError ¶
IsRetryableError checks whether the error is retryable. EOF, connection reset, broken pipe, connection refused, connectex are retryable.
func IsRetryableUpstream ¶ added in v0.1.14
IsRetryableUpstream reports whether a log, stderr, or API message is a transient upstream stream failure.
func IsSandboxRejection ¶ added in v0.2.3
IsSandboxRejection reports Codex sandbox/policy rejection in stderr or log text.
func NewLargeLineScanner ¶ added in v0.1.5
NewLargeLineScanner returns a Scanner with configurable max token size. maxTokenSize <= 0 uses DefaultScannerMaxTokenSize.
func NormalizeExecutionMode ¶ added in v0.1.2
NormalizeExecutionMode returns a valid execution mode, defaulting to interactive.
func OverlayConfigDir ¶ added in v0.1.8
OverlayConfigDir copies or symlinks allowlisted names from configDir into sessionDir. Only entries that exist under configDir are applied. Existing session-only data outside the allowlist is never removed. Protected names under sessionDir are never deleted even if listed in allowlist by mistake.
func ParseWSLPath ¶ added in v0.1.1
ParseWSLPath parses a Windows path starting with a WSL prefix into (distro, linuxPath, isWSL). e.g. `\\wsl.localhost\Ubuntu\tmp` -> (`Ubuntu`, `/tmp`, true)
func PhysicalToHostPath ¶
PhysicalToHostPath converts a "file://" URI to a native file path. "file:///home/user/project" -> "/home/user/project"
func ReassembleToolResultParts ¶ added in v0.1.6
func ReassembleToolResultParts(events []StreamEvent) (string, error)
ReassembleToolResultParts joins tool_result_part content in order.
func Register ¶
func Register(name string, factory FactoryFunc)
Register registers a factory function for the given agent name. Typically called from init() in each adapter's package. Panics if name is already registered (programming error).
func Retry ¶
func Retry(ctx context.Context, cfg *RetryConfig, fn func() error) error
Retry executes fn up to MaxAttempts times. Only retryable errors trigger a retry. If ContainerCheck returns false, retry is immediately aborted.
func SortVFSMounts ¶
func SortVFSMounts(mounts []VFSMount)
SortVFSMounts sorts mounts by parent directory first (ascending VFSPath length).
func StripMarkdownCodeFence ¶
StripMarkdownCodeFence removes markdown code fences and returns the inner content. If no code fence is found, the original text is returned unchanged.
func TruncateToolResult ¶ added in v0.1.5
TruncateToolResult truncates content to maxBytes for SSE/TaskLog relay. Appends "\n... [truncated, N bytes total]" when truncated. maxBytes <= 0 uses DefaultMaxToolResultBytes.
func VFSMountsToDockerArgs ¶
VFSMountsToDockerArgs generates Docker -v arguments from VFSMount list. Returns: ["-v", "/host/path:/container/path", "-v", ...]
func ValidateContentParts ¶ added in v0.1.1
func ValidateContentParts(parts []ContentPart) error
ValidateContentParts validates a []ContentPart for correctness. Returns an error if any part is invalid.
func VerifyWSLRuntime ¶ added in v0.1.1
VerifyWSLRuntime checks if the target CLI exists in WSL.
func VfsToContainerPath ¶
VfsToContainerPath converts a VFS URI to a container path. "vfs://workspace/" -> "/workspace" "vfs://workspace/data/" -> "/workspace/data"
Types ¶
type AdapterConfig ¶
type AdapterConfig struct {
// AgentName is the agent name used for directory naming (e.g., "claudecode", "codex").
AgentName string
// GatewayURL is the LLM Gateway Proxy URL.
GatewayURL string
// Logger is the logger instance.
Logger logger.Logger
// DefaultWorkDir is the default working directory (CWD).
// Can be overridden per-session via WithWorkDir.
DefaultWorkDir string
// DefaultModel is the default model name.
// Can be overridden per-session via WithModel.
DefaultModel string
// DefaultEnvVars is the default additional environment variables.
// Can be overridden per-session via WithEnvVars.
DefaultEnvVars map[string]string
// DefaultSessionDir is the default session data storage directory.
// Can be overridden per-session via WithSessionDir.
// Falls back to WorkDir if not set.
DefaultSessionDir string
// DisableSandbox disables the CLI internal sandbox (for container execution).
// When true, CLAUDE_CODE_SKIP_SANDBOX=1 is set.
DisableSandbox bool
// ToolCallFallback enables text-to-tool-call conversion in the Gateway.
// When true, the ANTHROPIC_API_KEY includes ";fallback=true" metadata
// so the gateway proxy can apply fallback logic for models that
// sometimes emit tool calls as text instead of proper function_call.
ToolCallFallback bool
// ModelMode is the wire API mode for the adapter ("chat" or "responses").
// Used by Codex to determine config.toml wire_api value.
// Empty string defaults to "chat".
ModelMode string
// GatewayToken is the internal authentication token for LLMGP.
// Injected by server.Server on startup.
GatewayToken string
// EnableSubagent enables subagent delegation for WBS node execution.
// When true, each WBS node runs in an independent child session.
EnableSubagent bool
// MaxPromptBytes is the maximum allowed prompt size in bytes.
MaxPromptBytes int
// ExecutionMode controls stdin behavior: "interactive" or "single_shot".
ExecutionMode string
// IdleTimeoutSeconds is the max idle time without stdout/stderr output.
IdleTimeoutSeconds int
// MaxExecutionSeconds is the max wall-clock execution time.
MaxExecutionSeconds int
// ScannerMaxTokenBytes is the max JSONL line size for agent stdout scanners.
ScannerMaxTokenBytes int
// MaxToolResultBytes is the max EventToolResult content size for SSE relay.
MaxToolResultBytes int
}
AdapterConfig is the common configuration for all coding agent adapters.
type CodingAgent ¶
type CodingAgent interface {
// CreateSession starts a new agent session.
// Internally launches a CLI subprocess.
CreateSession(ctx context.Context, opts ...SessionOption) (Session, error)
// Name returns the agent backend name ("claudecode", "codex").
Name() string
// Close releases agent resources.
Close() error
}
CodingAgent is the common interface for coding agent backends. Both CLI wrapper types (Claude Code, Codex) and future direct API types can implement this interface.
func CreateAll ¶
func CreateAll(cfg *AdapterConfig) []CodingAgent
CreateAll creates all registered agents using the given config. Agents whose factory returns (nil, nil) are silently skipped (CLI not found). Agents whose factory returns an error are logged and skipped. Returns the successfully created agents.
type ContentPart ¶ added in v0.1.1
type ContentPart struct {
Type string `json:"type"` // "text" or "image"
Text string `json:"text,omitempty"` // populated when type="text"
Source *ImageSource `json:"source,omitempty"` // populated when type="image"
}
ContentPart represents a single block in a multimodal message. Supported types: "text" (plain text) and "image" (base64-encoded image).
func TextOnlyContent ¶ added in v0.1.1
func TextOnlyContent(text string) []ContentPart
TextOnlyContent creates a []ContentPart from a plain text string. Used by v1 handler to wrap legacy "message" field into content blocks.
type EventType ¶
type EventType string
EventType represents the type of a streaming event from a coding agent.
const ( // EventText is a text content event from the agent. EventText EventType = "text" // EventToolUse is a tool use event from the agent. EventToolUse EventType = "tool_use" // EventToolResult is a tool result event. EventToolResult EventType = "tool_result" // EventToolResultPart is a chunk of a large tool_result for SSE wire format. EventToolResultPart EventType = "tool_result_part" // EventResult is the final result event. EventResult EventType = "result" // EventError is an error event. EventError EventType = "error" // EventSystem is a system event (e.g., session init). EventSystem EventType = "system" // EventNodeStart indicates a WBS node has started execution. EventNodeStart EventType = "node_start" // EventNodeComplete indicates a WBS node has completed successfully. EventNodeComplete EventType = "node_complete" // EventNodeFailed indicates a WBS node execution failed. EventNodeFailed EventType = "node_failed" // EventProgress indicates WBS overall progress (e.g., "2/5"). EventProgress EventType = "progress" // EventUserInputRequired indicates the agent is waiting for user input. EventUserInputRequired EventType = "user_input_required" )
type FactoryFunc ¶
type FactoryFunc func(cfg *AdapterConfig) (CodingAgent, error)
FactoryFunc creates a CodingAgent from config. Return (nil, nil) if the agent's CLI is not available (graceful skip). Return (nil, err) if initialization fails unexpectedly.
type FallbackToolCall ¶
type FallbackToolCall struct {
Name string `json:"name"`
Arguments map[string]any `json:"arguments"`
}
FallbackToolCall is a tool call parsed from text output.
func ParseFallbackToolCalls ¶
func ParseFallbackToolCalls(text string) ([]FallbackToolCall, bool)
ParseFallbackToolCalls extracts tool calls from text output. Supported formats:
- Single object: {"name": "Write", "arguments": {...}}
- Array: [{"name": "Write", ...}, ...]
- Markdown code fence: ```json\n{...}\n```
type ImageSource ¶ added in v0.1.1
type ImageSource struct {
Type string `json:"type"` // "base64"
MediaType string `json:"media_type"` // MIME type (e.g., "image/png", "image/jpeg")
Data string `json:"data"` // Base64-encoded image data
}
ImageSource holds image data for a ContentPart of type "image".
type RetryConfig ¶
type RetryConfig struct {
MaxAttempts int
RetryInterval time.Duration
// ContainerCheck is an optional container liveness check function.
// If nil, no check is performed.
// If it returns false, retry is immediately aborted.
ContainerCheck func() bool
}
RetryConfig configures retry behavior.
func DefaultRetryConfig ¶
func DefaultRetryConfig() *RetryConfig
DefaultRetryConfig returns the default retry configuration.
type Session ¶
type Session interface {
// Send sends a message and returns a streaming event channel.
// The channel is closed when the agent response completes.
Send(ctx context.Context, message string) (<-chan StreamEvent, error)
// ID returns the session ID.
ID() string
// Close terminates the session and cleans up the subprocess.
Close() error
}
Session is an active agent session. Corresponds to the lifecycle of a CLI subprocess.
type SessionConfig ¶
type SessionConfig struct {
// Request-level options (vary per request)
Model string // Model name (e.g., "anthropic/claude-sonnet-4")
Prompt string // Initial prompt (for single-shot sessions)
AllowedTools []string // Allowed tool names
// Environment-level options (fixed at process/container start)
WorkDir string // Working directory (CWD)
EnvVars map[string]string // Additional environment variables
// Session resume
AgentSessionID string // Agent-managed session ID for context resume
// Session data storage directory.
// When set, the adapter maps this to the agent-specific env var
// (e.g., CLAUDE_CONFIG_DIR, CODEX_HOME).
// Falls back to WorkDir if not explicitly set.
SessionDir string
// ConfigDir is an optional source directory for agent config assets
// (skills, rules, settings). When set, adapters overlay allowlisted
// entries into SessionDir before launch. Empty means disabled
// (backward compatible: no overlay).
ConfigDir string
// VFS mounts (container execution)
VFSMounts []VFSMount // Host->container file mappings
// MaxTurns limits the number of agent turns. 0 means CLI default.
MaxTurns int
// ExecutionMode controls stdin behavior: "interactive" or "single_shot".
ExecutionMode string
// IdleTimeoutSeconds is the max idle time without stdout/stderr output.
IdleTimeoutSeconds int
// MaxExecutionSeconds is the max wall-clock execution time.
MaxExecutionSeconds int
// ScannerMaxTokenBytes is the max JSONL line size for agent stdout scanners.
ScannerMaxTokenBytes int
// MaxToolResultBytes is the max EventToolResult content size for SSE relay.
MaxToolResultBytes int
}
SessionConfig holds session creation parameters.
func NewSessionConfig ¶
func NewSessionConfig(opts ...SessionOption) *SessionConfig
NewSessionConfig applies the given SessionOptions and returns a SessionConfig.
type SessionOption ¶
type SessionOption func(*SessionConfig)
SessionOption configures a session at creation time.
func WithAgentSessionID ¶
func WithAgentSessionID(id string) SessionOption
WithAgentSessionID sets the agent session ID for context resume.
func WithAllowedTools ¶
func WithAllowedTools(tools []string) SessionOption
WithAllowedTools sets the allowed tool names.
func WithConfigDir ¶ added in v0.1.8
func WithConfigDir(dir string) SessionOption
WithConfigDir sets the optional agent config set directory.
func WithEnvVars ¶
func WithEnvVars(vars map[string]string) SessionOption
WithEnvVars sets additional environment variables.
func WithExecutionMode ¶ added in v0.1.2
func WithExecutionMode(mode string) SessionOption
WithExecutionMode sets the execution mode for stdin handling.
func WithIdleTimeout ¶ added in v0.1.2
func WithIdleTimeout(seconds int) SessionOption
WithIdleTimeout sets the idle timeout in seconds.
func WithMaxExecution ¶ added in v0.1.2
func WithMaxExecution(seconds int) SessionOption
WithMaxExecution sets the max execution time in seconds.
func WithMaxToolResultBytes ¶ added in v0.1.5
func WithMaxToolResultBytes(n int) SessionOption
WithMaxToolResultBytes sets the max EventToolResult content size for SSE relay.
func WithMaxTurns ¶
func WithMaxTurns(n int) SessionOption
WithMaxTurns sets the maximum number of agent turns.
func WithScannerMaxTokenBytes ¶ added in v0.1.5
func WithScannerMaxTokenBytes(n int) SessionOption
WithScannerMaxTokenBytes sets the max JSONL line size for stdout scanners.
func WithSessionDir ¶
func WithSessionDir(dir string) SessionOption
WithSessionDir sets the session data storage directory.
func WithVFSMounts ¶
func WithVFSMounts(mounts []VFSMount) SessionOption
WithVFSMounts sets the VFS mount mappings.
func WithWorkDir ¶
func WithWorkDir(dir string) SessionOption
WithWorkDir sets the working directory.
type SessionRecord ¶
type SessionRecord struct {
ID string `json:"id"`
AgentName string `json:"agent_name"`
Model string `json:"model"`
Status string `json:"status"`
Error string `json:"error,omitempty"`
WorkDir string `json:"work_dir"`
StorageRoot string `json:"storage_root,omitempty"`
AgentSessionID string `json:"agent_session_id"`
SessionDir string `json:"session_dir"`
ConfigDir string `json:"config_dir,omitempty"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}
SessionRecord is a persisted session record.
type SessionStore ¶
type SessionStore interface {
Create(session *SessionRecord) error
Get(id string) (*SessionRecord, error)
Update(session *SessionRecord) error
List() ([]*SessionRecord, error)
Delete(id string) error
}
SessionStore is the abstract interface for session persistence.
type StdinWriter ¶ added in v0.1.2
StdinWriter allows writing additional input to a running CLI session.
type StreamEvent ¶
type StreamEvent struct {
Type EventType `json:"type"`
Content string `json:"content,omitempty"`
PromptID string `json:"prompt_id,omitempty"`
Choices []string `json:"choices,omitempty"`
ToolName string `json:"tool_name,omitempty"`
ToolInput map[string]interface{} `json:"tool_input,omitempty"`
SessionID string `json:"session_id,omitempty"`
TurnID string `json:"turn_id,omitempty"`
CorrelationID string `json:"correlation_id,omitempty"`
ChunkID string `json:"chunk_id,omitempty"`
ChunkIndex int `json:"index,omitempty"`
ChunkTotal int `json:"total,omitempty"`
Error error `json:"-"`
Retryable bool `json:"-"`
}
StreamEvent is a streaming event from a coding agent.
func SplitStreamEventForSSE ¶ added in v0.1.6
func SplitStreamEventForSSE(ev StreamEvent, maxLineBytes int) ([]StreamEvent, error)
SplitStreamEventForSSE splits oversized EventToolResult into wire-safe events. Non-EventToolResult events are returned unchanged as a single-element slice. maxLineBytes <= 0 uses DefaultMaxSSEDataLineBytes.
type VFSMount ¶
type VFSMount struct {
VFSPath string // Logical path (e.g., "vfs://workspace/")
PhysicalPath string // Host physical path (e.g., "file:///home/user/project")
}
VFSMount defines a host path <-> container path mapping.