Documentation
¶
Index ¶
- Variables
- func DetectTurnStage(messages []types.Message, turnID types.TurnID) prompt.ExecutionStage
- type CompactionSnapshot
- type Config
- type ContinueTransition
- type Engine
- func (e *Engine) AutoModeAvailable() bool
- func (e *Engine) Fork(systemPrompt, modelStr string) *Engine
- func (e *Engine) GetMonitoring() *monitoring.System
- func (e *Engine) HookExecutor() *hooks.Executor
- func (e *Engine) HookRegistry() *hooks.Registry
- func (e *Engine) NewSession(ctx context.Context) (*Session, error)
- func (e *Engine) NewSessionFromState(ctx context.Context, sessionID types.SessionID, ...) (*Session, error)
- func (e *Engine) OpenSession(ctx context.Context, sessionID types.SessionID) (*Session, error)
- func (e *Engine) SetAPIClient(apiClient *providers.Client)
- func (e *Engine) SetOnSessionTitled(fn func(types.SessionID, string))
- func (e *Engine) SetPromptFn(fn types.PromptFn)
- func (e *Engine) SetTitleAPIClient(apiClient *providers.Client)
- func (e *Engine) SetTitleGenerator(generator TitleGenerator)
- type Loop
- type LoopConfig
- type MutableState
- type PromptRefresh
- type RecoveryContext
- type RecoveryType
- type RunRequest
- type RunResult
- type Runner
- type RunnerConfig
- type RunnerRequest
- type RunnerResult
- type Session
- func (s *Session) ClearPlanMode()
- func (s *Session) Close() error
- func (s *Session) ForcePlanMode()
- func (s *Session) GetEventQueue() *execution.EventQueue
- func (s *Session) GetExecutionMode() string
- func (s *Session) GetMessages() []types.Message
- func (s *Session) GetMetadata() *types.SessionMetadata
- func (s *Session) GetPermissionContext() *types.PermissionContext
- func (s *Session) GetPermissionMode() types.PermissionMode
- func (s *Session) GetRuntimeEventQueue() *execution.RuntimeEventQueue
- func (s *Session) GetSessionID() types.SessionID
- func (s *Session) GetToolNames() []string
- func (s *Session) GetTotalTokens() int
- func (s *Session) GetTurnNumber() int
- func (s *Session) Interrupt() error
- func (s *Session) RegisterTool(t tool.Tool) error
- func (s *Session) RegisterTools(tools []tool.Tool) error
- func (s *Session) SetAppendSystemPrompt(text string)
- func (s *Session) SetPermissionMode(mode types.PermissionMode)
- func (s *Session) SetProgressCallback(fn func(types.ToolProgress))
- func (s *Session) SetResponseChunkCallback(fn func(types.APIResponseChunk))
- func (s *Session) SetRuntimeEventCallback(fn func(types.RuntimeEvent))
- func (s *Session) SetSystemPromptTemplate(text string)
- func (s *Session) SetWorkingDirectory(path string)
- func (s *Session) SubmitMessage(ctx context.Context, content string) (*SessionResponse, error)
- func (s *Session) SubmitMessageWithContent(ctx context.Context, text string, images []types.ImageContent) (*SessionResponse, error)
- func (s *Session) UnregisterTool(name string) error
- type SessionResponse
- type SessionState
- func (s *SessionState) AdvanceTurn(usage *types.TokenUsage, updatedMessages []types.Message)
- func (s *SessionState) CloneMessages() []types.Message
- func (s *SessionState) CurrentExecutionMode() string
- func (s *SessionState) CurrentPermissionMode() types.PermissionMode
- func (s *SessionState) DenialTrackingState() *types.DenialTrackingState
- func (s *SessionState) EffectiveToolSurface(reg *tool.Registry) map[string]tool.Tool
- func (s *SessionState) GetLastRecoveryContext() *RecoveryContext
- func (s *SessionState) MarkClosed()
- func (s *SessionState) MarkInterrupted()
- func (s *SessionState) MetadataSnapshot() *types.SessionMetadata
- func (s *SessionState) PendingDeferredToolNames(reg *tool.Registry) []string
- func (s *SessionState) PermissionContextSnapshot() *types.PermissionContext
- func (s *SessionState) RegisterDiscoveredDeferredTools(names []string)
- func (s *SessionState) ReplaceMessages(messages []types.Message)
- func (s *SessionState) SetPermissionContext(permissionContext *types.PermissionContext)
- func (s *SessionState) StoreRecoveryContext(ctx *RecoveryContext)
- func (s *SessionState) ToolSurface() map[string]tool.Tool
- type SessionStore
- type StopHook
- type StopHookConfig
- type StopHookInput
- type StopHookResult
- type TerminalTransition
- type TitleGenerator
- type Transition
- type TurnProgress
Constants ¶
This section is empty.
Variables ¶
var GetCurrentTime = func() time.Time { return time.Now() }
GetCurrentTime returns the current time (overridable for testing).
Functions ¶
func DetectTurnStage ¶
DetectTurnStage examines the messages generated after the initial user message for this turn and returns the prompt.ExecutionStage that best matches the current loop context.
Rules applied in order (highest priority first):
- Last user message (after turn start) contains ToolResultContent → StageToolResult
- Last user message (after turn start) is text-only and follows an assistant message within the turn → StageContinuation (loop-injected nudge)
- Otherwise → StageDefault (fresh turn or no in-turn history yet)
The turnID is used to locate the first user message of the current turn so that messages from previous turns are excluded from stage detection.
Types ¶
type CompactionSnapshot ¶
type CompactionSnapshot struct {
PreCompactionTokenCount int
PostCompactionTokenCount int
FirstPreservedMessageID types.MessageID
LastPreservedMessageID types.MessageID
PreservedTailHash string
BoundaryVersion int
}
CompactionSnapshot captures the state of compaction at interruption.
type Config ¶
type Config struct {
MaxTurns int `json:"max_turns"`
AutoCompact bool `json:"auto_compact"`
PermissionMode types.PermissionMode `json:"permission_mode"`
Model types.ModelIdentifier `json:"model"`
TitleModel types.ModelIdentifier `json:"title_model,omitempty"`
// CompactSummaryModel overrides which model generates compaction summaries.
// Zero value means "use Model" (the session's own model), so compaction
// works on any provider without needing an Anthropic key.
CompactSummaryModel types.ModelIdentifier `json:"compact_summary_model,omitempty"`
// TrustProjectInstructions gates SESHAT.md/AGENTS.md/.seshat/instructions.md
// found in the working directory behind project trust before they are
// injected into the system prompt (see docs/project-trust.md and
// readTrustedProjectInstructions). nil fails closed: no project's own
// instructions are ever injected without a host wiring this in - e.g. to
// the same hash-based trust store it already uses for the project's other
// configuration files.
TrustProjectInstructions func(path string, content []byte) bool `json:"-"`
MaxTokens int `json:"max_tokens"`
WorkingDirectory string `json:"working_directory,omitempty"`
SystemPromptTemplate string `json:"system_prompt_template"`
MCPServers []mcp.ServerConfig `json:"mcp_servers"`
EnableMemory bool `json:"enable_memory"`
EnableMonitoring bool `json:"enable_monitoring"`
// MaxIterations caps model→tool→model cycles per turn. 0 = loop default
// (100 - see DefaultLoopConfig; this comment previously said 10, which
// was never the actual default - M3 in TODO.md).
MaxIterations int `json:"max_iterations"`
// TurnTokenBudget enables token-budget continuation when > 0.
TurnTokenBudget int `json:"turn_token_budget"`
// BudgetContinuationLimit caps how many budget-continuation cycles may occur.
// 0 = loop default.
BudgetContinuationLimit int `json:"budget_continuation_limit"`
// ContinuationNudgeLimit caps how many text-signal nudges the loop sends.
// 0 = loop default (3).
ContinuationNudgeLimit int `json:"continuation_nudge_limit"`
// StopHooks are post-turn policy hooks that may request one more cycle.
StopHooks []StopHook `json:"-"`
// MaxConsecutiveDenials is the number of back-to-back permission denials that
// trigger orchestrator fallback. 0 = use the default (3).
MaxConsecutiveDenials int `json:"max_consecutive_denials"`
// PromptStage sets the execution stage overlay injected into the dynamic
// section of the system prompt every turn.
PromptStage prompt.ExecutionStage `json:"prompt_stage,omitempty"`
// PromptStageOverrides replaces built-in stage overlay text per stage.
PromptStageOverrides map[prompt.ExecutionStage]string `json:"-"`
// PromptToolHints provides per-tool extra guidance appended to provider-facing
// tool descriptions. Key is the canonical tool name.
PromptToolHints map[string]string `json:"-"`
// AppendSystemPrompt is appended to the system prompt after all other sections.
AppendSystemPrompt string `json:"append_system_prompt,omitempty"`
// ManagedInstructions is text imposed by whoever runs the host (an organization).
// It is appended after everything else, including a per-session append prompt,
// so a session setter cannot replace or drop it.
ManagedInstructions string `json:"-"`
// BrowserManager manages native browser sessions for browser tools.
BrowserManager browsercore.Manager `json:"-"`
// DisableStreaming opts out of server-sent-event streaming. Streaming is
// enabled by default; set this to true only when the provider or test
// harness does not support SSE.
DisableStreaming bool `json:"disable_streaming,omitempty"`
}
Config represents the engine configuration.
func DefaultConfig ¶
func DefaultConfig() *Config
DefaultConfig returns default engine configuration.
type ContinueTransition ¶
type ContinueTransition struct {
// Reason explains why we're continuing
Reason string
// RecoveryType indicates the type of recovery (if any)
RecoveryType RecoveryType
}
ContinueTransition indicates the loop should continue
func (ContinueTransition) IsContinue ¶
func (c ContinueTransition) IsContinue() bool
IsContinue returns true
func (ContinueTransition) IsTerminal ¶
func (c ContinueTransition) IsTerminal() bool
IsTerminal returns false
type Engine ¶
type Engine struct {
// contains filtered or unexported fields
}
Engine orchestrates query sessions.
func NewEngine ¶
func NewEngine( apiClient *providers.Client, orchestrator *execution.Orchestrator, compactor *compact.Engine, promptAssembler *prompt.Assembler, permissionIntegrator *permissions.Integrator, toolRegistry *tool.Registry, sessionStore SessionStore, config *Config, memoryService *memory.Service, monitoringSys *monitoring.System, ) *Engine
NewEngine creates a new query engine.
func NewEngineWithRegistry ¶
func NewEngineWithRegistry( ctx context.Context, apiClient *providers.Client, toolRegistry *tool.Registry, config *Config, ) (*Engine, error)
NewEngineWithRegistry creates a new query engine with a custom tool registry
func (*Engine) AutoModeAvailable ¶
AutoModeAvailable reports whether the permission integrator has an AI-backed auto-mode classifier wired up and ready.
func (*Engine) Fork ¶
Fork returns a new Engine configured for a specific agent persona. It shares read-only resources (apiClient, orchestrator, compactor, promptAssembler, permissionIntegrator, toolRegistry, sessionStore, monitoring, browserManager) with the parent but creates an independent Loop so concurrent agent sessions never race on shared mutable loop state.
systemPrompt is injected as the session's system-prompt template verbatim. modelStr, when non-empty, must be in "provider:model" format and overrides the parent model; pass an empty string to keep the parent model.
func (*Engine) GetMonitoring ¶
func (e *Engine) GetMonitoring() *monitoring.System
GetMonitoring returns the monitoring system for external integration.
func (*Engine) HookExecutor ¶
HookExecutor returns the engine's hook executor for external use.
func (*Engine) HookRegistry ¶
HookRegistry returns the engine's hook registry for external hook registration.
func (*Engine) NewSession ¶
NewSession creates a new session.
func (*Engine) NewSessionFromState ¶
func (e *Engine) NewSessionFromState( ctx context.Context, sessionID types.SessionID, metadata *types.SessionMetadata, messages []types.Message, ) (*Session, error)
NewSessionFromState creates a session from existing state or initializes a new one.
func (*Engine) OpenSession ¶
OpenSession loads a previously persisted session by ID so it can receive new turns. Returns an error if the store does not support session restoration or if the session is not found.
func (*Engine) SetAPIClient ¶
SetAPIClient swaps the loop-facing API client.
func (*Engine) SetOnSessionTitled ¶
SetOnSessionTitled registers a callback that is invoked once — as soon as the session's first message is submitted, running concurrently with that first turn rather than waiting for it to finish — with the AI-generated session title. Passing nil disables the feature.
func (*Engine) SetPromptFn ¶
SetPromptFn wires the runtime prompt bridge into permissions and prompt-aware tools.
func (*Engine) SetTitleAPIClient ¶
SetTitleAPIClient sets the provider client used only for session title generation. Passing nil falls back to the main API client.
func (*Engine) SetTitleGenerator ¶
func (e *Engine) SetTitleGenerator(generator TitleGenerator)
SetTitleGenerator sets a local title generator. When present it is tried before the provider-backed title client.
type Loop ¶
type Loop struct {
// contains filtered or unexported fields
}
Loop represents the main query loop state machine.
func NewLoop ¶
func NewLoop( apiClient *providers.Client, orchestrator *execution.Orchestrator, compactor compact.CompactionStrategy, promptAssembler *prompt.Assembler, permissionIntegrator *permissions.Integrator, hookExecutor *hooks.Executor, config *LoopConfig, monitoringSys *monitoring.System, providerConfigs ...*providers.Config, ) *Loop
NewLoop creates a new query loop.
type LoopConfig ¶
type LoopConfig struct {
MaxIterations int `json:"max_iterations"`
AutoCompact bool `json:"auto_compact"`
// MaxTurns is currently dead weight: nothing in this file reads it. The
// live session-turn limit is engine.Config.MaxTurns, enforced by
// Session.enforceMaxTurns (M3 in TODO.md - its default used to disagree
// with this one, 200 vs 100, despite neither mattering here).
MaxTurns int `json:"max_turns"`
EnableStreaming bool `json:"enable_streaming"`
MaxOutputTokensRecoveryLimit int `json:"max_output_tokens_recovery_limit"`
ContinuationNudgeLimit int `json:"continuation_nudge_limit"`
TurnTokenBudget int `json:"turn_token_budget,omitempty"`
BudgetContinuationLimit int `json:"budget_continuation_limit,omitempty"`
BudgetCompletionThreshold float64 `json:"budget_completion_threshold,omitempty"`
BudgetDiminishingThreshold int `json:"budget_diminishing_threshold,omitempty"`
StopHooks []StopHook `json:"-"`
// StopHookConfig controls stop hook execution behavior
StopHookTimeout int `json:"stop_hook_timeout,omitempty"` // milliseconds, 0 = no timeout
StopHookMode string `json:"stop_hook_mode,omitempty"` // "first" (default) or "all"
StopHookContinueOnError bool `json:"stop_hook_continue_on_error,omitempty"` // continue if hook errors
// Additional recovery options
MaxRecoveryAttempts int `json:"max_recovery_attempts,omitempty"` // total recovery attempts per turn
RecoveryBackoffMultiplier int `json:"recovery_backoff_multiplier,omitempty"` // milliseconds; base delay for attempt 1, doubled each attempt after
RecoveryBackoffMaxDelay int `json:"recovery_backoff_max_delay_ms,omitempty"` // milliseconds; caps the exponential growth, 0 = default (30s)
}
LoopConfig represents the loop configuration.
func DefaultLoopConfig ¶
func DefaultLoopConfig() *LoopConfig
DefaultLoopConfig returns default loop configuration.
MaxIterations is the number of model-call rounds the engine executes within a single RunPrompt/StreamPrompt call. Each iteration is one LLM call plus any tool executions that follow. Increasing this allows complex autonomous tasks (many sequential tool-use rounds) without requiring multiple user messages.
MaxTurns is the session-level turn counter limit across all RunPrompt calls.
type MutableState ¶
type MutableState struct {
// Messages are the conversation messages
Messages []types.Message
// ToolUses are all tool uses executed
ToolUses []types.ToolUseContent
// ToolResults are all tool results
ToolResults []tool.CallResult
// DiscoveredDeferred tracks deferred tools discovered during the current run.
DiscoveredDeferred []string
// Usage is token usage information
Usage *types.TokenUsage
// StopReason is why the loop stopped
StopReason string
// Compacted indicates if compaction occurred
Compacted bool
// CompactPreTokens and CompactPostTokens carry the token counts from the
// most recent compaction this turn (zero unless Compacted is true) - see
// maybeAutoCompact. Threaded through RunResult/SessionResponse so a host
// can show a before/after "saved N tokens" toast instead of compaction
// happening completely silently.
CompactPreTokens int
CompactPostTokens int
// PreviousResponseID and PreviousResponseMessageCount enable a provider
// that supports server-side conversation continuation (currently:
// Codex's Responses API previous_response_id) to send only the messages
// appended since the last successful same-provider response, instead of
// resending the whole growing Messages list on every internal iteration
// of a single turn's tool-use loop (up to MaxIterations). Populated in
// Loop.recordPreviousResponse after each successful model call;
// invalidated (reset to zero) the moment compaction changes Messages or
// a different provider answers, so a stale/mismatched reference can
// never be sent - worst case on invalidation is just falling back to
// the existing full-resend behavior. Scoped to a single Loop.Run call
// (one turn): MutableState is rebuilt fresh per turn, so there is no
// cross-turn or cross-restart persistence to keep consistent.
PreviousResponseID string
PreviousResponseMessageCount int
// Iterations is the number of iterations performed
Iterations int
// TurnCount is the turn count
TurnCount int
// MaxOutputTokensRecoveryCount is recovery attempt count
MaxOutputTokensRecoveryCount int
// HasAttemptedReactiveCompact indicates if reactive compact was tried
HasAttemptedReactiveCompact bool
// MaxOutputTokensOverride is the override for max tokens
MaxOutputTokensOverride int
// ContinuationNudgeCount is continuation nudge count
ContinuationNudgeCount int
// Transition is the previous transition (undefined on first iteration)
Transition Transition
// StopHookActive indicates if a stop hook is active
StopHookActive *bool
// AutoCompactFailureCount tracks consecutive auto-compact failures.
AutoCompactFailureCount int
// TotalTurnTokens accumulates API usage across iterations of the turn.
TotalTurnTokens int
// BudgetContinuationCount tracks how many budget-based continuations fired.
BudgetContinuationCount int
// LastBudgetCheckTokens is the previous total token count seen by budget logic.
LastBudgetCheckTokens int
// LastBudgetDelta stores the last token delta for diminishing-returns checks.
LastBudgetDelta int
// RecoveryContext tracks details needed to properly resume after interruption
RecoveryContext *RecoveryContext
// CurrentStage is the prompt.ExecutionStage detected at the start of the last
// iteration. Used to avoid redundant system-prompt rebuilds.
CurrentStage prompt.ExecutionStage
// PermissionContext is the evolving permission context owned by the loop
// during this turn. Initialized from RunRequest at turn start; updated after
// each tool execution batch. Session reads it back via RunResult.
PermissionContext *types.PermissionContext
// PermissionMode mirrors PermissionContext.Mode for fast access without a
// nil check on every iteration.
PermissionMode types.PermissionMode
}
MutableState is the per-turn working set owned by the query loop. It is intentionally mutable and short-lived: each Run starts from canonical SessionState, mutates this structure across iterations, then folds the final result back into SessionState via AdvanceTurn.
func NewMutableState ¶
func NewMutableState(initialMessages []types.Message) *MutableState
NewMutableState creates the short-lived per-turn state for one loop run.
func (*MutableState) Clone ¶
func (s *MutableState) Clone() *MutableState
Clone creates a deep copy of the state
type PromptRefresh ¶
type PromptRefresh struct {
SystemPrompt string
SystemPromptBlocks []types.SystemPromptBlock
}
type RecoveryContext ¶
type RecoveryContext struct {
LastTransitionReason string
LastRecoveryType RecoveryType
LastStopReason string
CompactionSnapshot *CompactionSnapshot
TurnProgress *TurnProgress
}
RecoveryContext tracks details needed to properly resume after interruption.
type RecoveryType ¶
type RecoveryType string
RecoveryType represents the type of recovery
const ( // RecoveryTypeNone means no recovery RecoveryTypeNone RecoveryType = "none" // RecoveryTypeMaxOutputTokens means max_output_tokens recovery RecoveryTypeMaxOutputTokens RecoveryType = "max_output_tokens" // RecoveryTypePromptTooLong means prompt_too_long recovery RecoveryTypePromptTooLong RecoveryType = "prompt_too_long" // RecoveryTypeContinuationNudge means continuation nudge RecoveryTypeContinuationNudge RecoveryType = "continuation_nudge" // RecoveryTypeAPIRetry means a narrow retry of a retryable API failure. RecoveryTypeAPIRetry RecoveryType = "api_retry" // RecoveryTypeTokenBudget means a budget-based continuation nudge fired. RecoveryTypeTokenBudget RecoveryType = "token_budget" // RecoveryTypeStopHook means a stop hook requested continuation. RecoveryTypeStopHook RecoveryType = "stop_hook" )
type RunRequest ¶
type RunRequest struct {
Messages []types.Message `json:"messages"`
SystemPrompt string `json:"system_prompt"`
SystemPromptBlocks []types.SystemPromptBlock `json:"system_prompt_blocks,omitempty"`
ProviderTools []types.APIToolDefinition `json:"tools,omitempty"`
Tools map[string]tool.Tool `json:"-"`
// Toolsets are resolved dynamically at the start of each iteration.
// Their tools are merged into Tools each iteration (Toolset wins on name collision).
Toolsets []tool.Toolset `json:"-"`
ToolRegistry *tool.Registry `json:"-"`
RefreshSystemPrompt func(ctx context.Context, tools map[string]tool.Tool, pendingDeferred []string, stage prompt.ExecutionStage) (PromptRefresh, error) `json:"-"`
// AutoDetectStage enables per-iteration stage detection. The engine sets this
// when no static PromptStage is configured so that stage overlays fire
// automatically without manual configuration.
AutoDetectStage bool `json:"-"`
SessionID types.SessionID `json:"session_id"`
TurnID types.TurnID `json:"turn_id"`
WorkingDirectory string `json:"working_directory,omitempty"`
PermissionMode types.PermissionMode `json:"permission_mode"`
PermissionContext *types.PermissionContext `json:"-"`
PermissionCheck types.CanUseToolFn `json:"-"`
DenialTracking *types.DenialTrackingState `json:"-"`
Model types.ModelIdentifier `json:"model"`
MaxTokens int `json:"max_tokens"`
ProgressCallback func(types.ToolProgress) `json:"-"`
ResponseChunkCallback func(types.APIResponseChunk) `json:"-"`
// EventQueue receives every streaming chunk emitted during this turn.
// Callers read from EventQueue.Recv() in a separate goroutine to avoid
// blocking the loop. Overflow is counted but never blocks.
EventQueue *execution.EventQueue `json:"-"`
TurnTokenBudget int `json:"turn_token_budget,omitempty"`
// OutputSchema, when set, constrains the model to return JSON matching the
// schema. Passed through to types.APIRequest.OutputSchema.
OutputSchema *schema.StructuredOutputInfo `json:"-"`
// AutoCompactFailureCount carries the session's consecutive auto-compact
// failure count into this turn, so the circuit breaker in
// compact.Engine.AutoCompact persists across turns instead of resetting
// to zero every Run. The caller (Session.SubmitMessage) is responsible
// for threading RunResult.AutoCompactFailureCount back in on the next turn.
AutoCompactFailureCount int `json:"auto_compact_failure_count,omitempty"`
}
RunRequest represents a request to run the query loop.
type RunResult ¶
type RunResult struct {
Messages []types.Message `json:"messages"`
StopReason string `json:"stop_reason"`
ToolUses []types.ToolUseContent `json:"tool_uses"`
ToolResults []tool.CallResult `json:"tool_results"`
Usage *types.TokenUsage `json:"usage"`
PermissionContext *types.PermissionContext `json:"-"`
Compacted bool `json:"compacted"`
CompactPreTokens int `json:"compact_pre_tokens,omitempty"`
CompactPostTokens int `json:"compact_post_tokens,omitempty"`
Iterations int `json:"iterations"`
DiscoveredDeferred []string `json:"discovered_deferred,omitempty"`
Error error `json:"error,omitempty"`
// RecoveryContext captures the turn execution state at loop exit.
// Persisted by the engine into session metadata so that interrupted or
// errored sessions can expose what was in-flight at the time of failure.
RecoveryContext *RecoveryContext `json:"-"`
// AutoCompactFailureCount is the session's consecutive auto-compact
// failure count after this turn. The caller must store it (e.g. on
// SessionState) and pass it back in as the next turn's
// RunRequest.AutoCompactFailureCount for the circuit breaker to work
// across turns.
AutoCompactFailureCount int `json:"auto_compact_failure_count,omitempty"`
}
RunResult represents the result of running the loop.
type Runner ¶
type Runner struct {
// contains filtered or unexported fields
}
Runner executes a single turn through the canonical query loop.
func NewRunner ¶
func NewRunner( apiClient *providers.Client, orchestrator *execution.Orchestrator, compactor *compact.Engine, promptAssembler *prompt.Assembler, permissionIntegrator *permissions.Integrator, config *RunnerConfig, ) *Runner
NewRunner creates a new turn runner.
func (*Runner) Run ¶
func (r *Runner) Run(ctx context.Context, req RunnerRequest) (RunnerResult, error)
Run executes a single turn by delegating to the canonical query loop.
type RunnerConfig ¶
type RunnerConfig struct {
MaxIterations int `json:"max_iterations"`
AutoCompact bool `json:"auto_compact"`
MaxTurns int `json:"max_turns"`
}
RunnerConfig represents the runner configuration.
func DefaultRunnerConfig ¶
func DefaultRunnerConfig() *RunnerConfig
DefaultRunnerConfig returns default runner configuration.
type RunnerRequest ¶
type RunnerRequest struct {
Messages []types.Message `json:"messages"`
SystemPrompt string `json:"system_prompt"`
Tools map[string]tool.Tool `json:"-"`
SessionID types.SessionID `json:"session_id"`
TurnID types.TurnID `json:"turn_id"`
PermissionMode types.PermissionMode `json:"permission_mode"`
PermissionCheck types.CanUseToolFn `json:"-"`
DenialTracking *types.DenialTrackingState `json:"-"`
Model types.ModelIdentifier `json:"model"`
MaxTokens int `json:"max_tokens"`
ProgressCallback func(types.ToolProgress) `json:"-"`
PromptVariables map[string]string `json:"prompt_variables,omitempty"`
}
RunnerRequest represents a request to run a turn through the runner facade.
type RunnerResult ¶
type RunnerResult struct {
Messages []types.Message `json:"messages"`
StopReason string `json:"stop_reason"`
ToolUses []types.ToolUseContent `json:"tool_uses"`
ToolResults []tool.CallResult `json:"tool_results"`
Usage *types.TokenUsage `json:"usage"`
Compacted bool `json:"compacted"`
CompactPreTokens int `json:"compact_pre_tokens,omitempty"`
CompactPostTokens int `json:"compact_post_tokens,omitempty"`
Iterations int `json:"iterations"`
}
RunnerResult represents the result of running a turn through the runner facade.
type Session ¶
type Session struct {
// contains filtered or unexported fields
}
Session represents an active query session.
func (*Session) ClearPlanMode ¶
func (s *Session) ClearPlanMode()
ClearPlanMode exits plan mode in the session permission context, restoring the previous permission mode. This mirrors what exit_plan_mode.Call does via its ContextModifier, allowing the TUI to pre-exit plan mode on user approval without waiting for the model to call exit_plan_mode itself.
func (*Session) Close ¶
Close closes the session, persists memory, and releases the browser session. Idempotent (a second call is a no-op) and safe to call while a turn is running: it cancels that turn first, before tearing down the event queues underneath it.
func (*Session) ForcePlanMode ¶
func (s *Session) ForcePlanMode()
ForcePlanMode enters plan mode in the session permission context directly. This mirrors what enter_plan_mode.Call does via its ContextModifier, allowing a host application to force a session into plan mode without waiting for the model to call enter_plan_mode itself. Like ClearPlanMode below, this stays a pure state mutation — no runtime event is emitted and no plan-file bookkeeping (internal/modes/execution's planCache) is touched, since both live behind a context.Context-scoped emitter/session id not available to this parameterless setter. Safe to call unconditionally (including when already in plan mode, which is a harmless no-op: Mode itself is untouched by plan mode, only PrePlanMode/ExecutionMode change).
func (*Session) GetEventQueue ¶
func (s *Session) GetEventQueue() *execution.EventQueue
GetEventQueue returns the session's streaming event queue.
func (*Session) GetExecutionMode ¶
func (*Session) GetMessages ¶
func (*Session) GetMetadata ¶
func (s *Session) GetMetadata() *types.SessionMetadata
func (*Session) GetPermissionContext ¶
func (s *Session) GetPermissionContext() *types.PermissionContext
func (*Session) GetPermissionMode ¶
func (s *Session) GetPermissionMode() types.PermissionMode
func (*Session) GetRuntimeEventQueue ¶
func (s *Session) GetRuntimeEventQueue() *execution.RuntimeEventQueue
GetRuntimeEventQueue returns the session's structured runtime event queue.
func (*Session) GetSessionID ¶
GetSessionID returns the stable identifier for this session.
func (*Session) GetToolNames ¶
func (*Session) GetTotalTokens ¶
func (*Session) GetTurnNumber ¶
func (*Session) Interrupt ¶
Interrupt cancels the current turn and marks the session as interrupted. Not gated by beginTurn/endTurn: it targets whatever IS currently running, so it must work regardless of the single-flight guard.
func (*Session) SetAppendSystemPrompt ¶
SetAppendSystemPrompt sets a per-session override for the append system prompt.
func (*Session) SetPermissionMode ¶
func (s *Session) SetPermissionMode(mode types.PermissionMode)
func (*Session) SetProgressCallback ¶
func (s *Session) SetProgressCallback(fn func(types.ToolProgress))
SetProgressCallback wires a host-level observer for tool execution progress.
func (*Session) SetResponseChunkCallback ¶
func (s *Session) SetResponseChunkCallback(fn func(types.APIResponseChunk))
SetResponseChunkCallback wires a host-level observer for live model chunks.
func (*Session) SetRuntimeEventCallback ¶
func (s *Session) SetRuntimeEventCallback(fn func(types.RuntimeEvent))
SetRuntimeEventCallback wires a host-level observer for structured runtime events.
func (*Session) SetSystemPromptTemplate ¶
SetSystemPromptTemplate sets a per-session override that fully replaces the default system prompt. Pass an empty string to clear the override.
func (*Session) SetWorkingDirectory ¶
SetWorkingDirectory overrides the working directory for this session's turns.
func (*Session) SubmitMessage ¶
SubmitMessage submits a plain-text user message to the session.
func (*Session) SubmitMessageWithContent ¶
func (s *Session) SubmitMessageWithContent(ctx context.Context, text string, images []types.ImageContent) (*SessionResponse, error)
SubmitMessageWithContent submits a user message that may include image content blocks.
func (*Session) UnregisterTool ¶
UnregisterTool removes a tool from the session by name.
type SessionResponse ¶
type SessionResponse struct {
Messages []types.Message `json:"messages"`
StopReason string `json:"stop_reason"`
ToolUses []types.ToolUseContent `json:"tool_uses"`
ToolResults []tool.CallResult `json:"tool_results"`
Usage *types.TokenUsage `json:"usage"`
TotalTokens int `json:"total_tokens"`
TurnNumber int `json:"turn_number"`
Compacted bool `json:"compacted"`
CompactPreTokens int `json:"compact_pre_tokens,omitempty"`
CompactPostTokens int `json:"compact_post_tokens,omitempty"`
}
SessionResponse represents the response from a session turn.
func (*SessionResponse) GetLastAssistantMessage ¶
func (r *SessionResponse) GetLastAssistantMessage() (types.Message, bool)
GetLastAssistantMessage returns the last assistant message.
func (*SessionResponse) GetLastToolResults ¶
func (r *SessionResponse) GetLastToolResults() []tool.CallResult
GetLastToolResults returns the last tool results.
func (*SessionResponse) IsComplete ¶
func (r *SessionResponse) IsComplete() bool
IsComplete returns true if the session is complete.
type SessionState ¶
type SessionState struct {
SessionID types.SessionID
TurnID types.TurnID
Messages []types.Message
Tools map[string]tool.Tool
DiscoveredDeferred []string
PermissionContext *types.PermissionContext
DenialTracking *types.DenialTrackingState
TurnNumber int
TotalTokens int
Metadata *types.SessionMetadata
LastCompaction *types.CompactionMetadata
CompactionCount int
CanonicalTranscript int
// AutoCompactFailureCount tracks consecutive auto-compact failures across
// turns, so the circuit breaker in compact.Engine.AutoCompact can actually
// trip. MutableState's own copy of this is per-turn scratch space seeded
// from here and folded back after each Run (see Loop.initializeState /
// Session.SubmitMessage).
AutoCompactFailureCount int
}
SessionState is the long-lived, session-owned conversation state.
The query loop owns short-lived per-turn execution details in MutableState; this struct keeps only the canonical transcript, tool surface, and aggregate counters that must survive across turns and restores.
func NewSessionState ¶
func (*SessionState) AdvanceTurn ¶
func (s *SessionState) AdvanceTurn(usage *types.TokenUsage, updatedMessages []types.Message)
AdvanceTurn folds a completed loop result back into the canonical session state. This is the handoff point between per-turn runtime execution and the long-lived conversation owner.
func (*SessionState) CloneMessages ¶
func (s *SessionState) CloneMessages() []types.Message
func (*SessionState) CurrentExecutionMode ¶
func (s *SessionState) CurrentExecutionMode() string
func (*SessionState) CurrentPermissionMode ¶
func (s *SessionState) CurrentPermissionMode() types.PermissionMode
func (*SessionState) DenialTrackingState ¶
func (s *SessionState) DenialTrackingState() *types.DenialTrackingState
func (*SessionState) EffectiveToolSurface ¶
func (*SessionState) GetLastRecoveryContext ¶
func (s *SessionState) GetLastRecoveryContext() *RecoveryContext
GetLastRecoveryContext returns the most recent recovery context for resume
func (*SessionState) MarkClosed ¶
func (s *SessionState) MarkClosed()
func (*SessionState) MarkInterrupted ¶
func (s *SessionState) MarkInterrupted()
func (*SessionState) MetadataSnapshot ¶
func (s *SessionState) MetadataSnapshot() *types.SessionMetadata
func (*SessionState) PendingDeferredToolNames ¶
func (s *SessionState) PendingDeferredToolNames(reg *tool.Registry) []string
func (*SessionState) PermissionContextSnapshot ¶
func (s *SessionState) PermissionContextSnapshot() *types.PermissionContext
func (*SessionState) RegisterDiscoveredDeferredTools ¶
func (s *SessionState) RegisterDiscoveredDeferredTools(names []string)
func (*SessionState) ReplaceMessages ¶
func (s *SessionState) ReplaceMessages(messages []types.Message)
func (*SessionState) SetPermissionContext ¶
func (s *SessionState) SetPermissionContext(permissionContext *types.PermissionContext)
func (*SessionState) StoreRecoveryContext ¶
func (s *SessionState) StoreRecoveryContext(ctx *RecoveryContext)
StoreRecoveryContext stores recovery context in metadata for persistence
func (*SessionState) ToolSurface ¶
func (s *SessionState) ToolSurface() map[string]tool.Tool
type SessionStore ¶
type SessionStore interface {
SaveSessionState(sessionID types.SessionID, metadata *types.SessionMetadata, previousMessages []types.Message, currentMessages []types.Message) error
}
SessionStore persists canonical session metadata and transcript state.
type StopHook ¶
type StopHook interface {
Name() string
Priority() int
Execute(ctx context.Context, input StopHookInput) (StopHookResult, error)
}
StopHook is the post-turn extension point for runtime policy checks. Hooks run after the model/tool phase has produced a candidate terminal state, and may either append messages or request one more loop iteration.
type StopHookConfig ¶
type StopHookConfig struct {
// Timeout in milliseconds, 0 = no timeout
Timeout int
// Mode: "first" stops at first Continue, "all" runs all hooks
Mode string
// ContinueOnError continues loop if hook errors
ContinueOnError bool
}
StopHookConfig controls stop hook execution
type StopHookInput ¶
type StopHookInput struct {
SessionID types.SessionID
TurnID types.TurnID
StopReason string
Messages []types.Message
ToolUses []types.ToolUseContent
Usage *types.TokenUsage
Iterations int
Compacted bool
// Additional context for richer hook decisions
RecoveryContext *RecoveryContext
TotalTurnTokens int
Model types.ModelIdentifier
}
type StopHookResult ¶
type TerminalTransition ¶
type TerminalTransition struct {
// Reason explains why we're stopping
Reason string
// StopReason is the API stop reason
StopReason string
}
TerminalTransition indicates the loop should stop
func (TerminalTransition) IsContinue ¶
func (t TerminalTransition) IsContinue() bool
IsContinue returns false
func (TerminalTransition) IsTerminal ¶
func (t TerminalTransition) IsTerminal() bool
IsTerminal returns true
type TitleGenerator ¶
type TitleGenerator interface {
GenerateTitle(ctx context.Context, firstUserMsg string) (string, error)
}
TitleGenerator can generate a short title without going through the regular provider client. Hosts use it for local-only title models.
type Transition ¶
Transition represents a state transition in the query loop Based on OpenClaude's query.ts transitions
func ContinueWithRecovery ¶
func ContinueWithRecovery(reason string, recoveryType RecoveryType) Transition
ContinueWithRecovery creates a continue transition with recovery
func Terminate ¶
func Terminate(reason string, stopReason string) Transition
Terminate creates a terminal transition
type TurnProgress ¶
type TurnProgress struct {
IterationsCompleted int
LastAssistantMessageID types.MessageID
PendingToolUses []types.ToolUseContent
PendingToolResults []tool.CallResult
TotalTokensUsed int
}
TurnProgress captures the turn execution state at interruption.
Source Files
¶
- browser_runtime_events.go
- config.go
- engine.go
- engine_helpers.go
- errors.go
- factory.go
- fork.go
- loop.go
- project_instructions.go
- runner.go
- session.go
- session_config.go
- session_events.go
- session_memory.go
- session_prompt.go
- session_response.go
- stage.go
- state.go
- stop_hooks.go
- streaming_tools.go
- token_budget.go
- tool_result_validator.go