Documentation
¶
Overview ¶
Shell-mutation tracking for ChangeTracker.
The base ChangeTracker (change_tracking.go) only captures writes the agent performs via the structured file tools (write_file, edit_file, patch_structured_file, write_structured_file). Plenty of legitimate agent actions mutate files outside those tools — `sed -i`, `mv`, `rm`, `cp`, `tee`, `awk -i inplace`, build scripts, formatters, etc. — and none of them currently appear in the manifest the subagent returns to its primary.
This file adds a "before/after" snapshot pass around every shell_command invocation:
- Before the shell runs, walk the workspace tree and capture file bytes for everything inside size/binary limits, skipping well-known bloat directories (.git, node_modules, dist, …). Works whether or not the workspace is a git repo — no git dependency, no reliance on git's tracked/untracked classification.
- Run the shell command.
- Walk again afterwards. Diff against the "before" map. Each deletion, modification, or creation that isn't already in the tracker becomes a new TrackedFileChange with the captured original content (when available — preserved so a user can recover an accidentally-deleted file from the session buffer, git-tracked or not).
Size + binary filters keep this cheap and safe: 1 MiB ceiling per file (so we don't buffer node_modules-style giants), plus a null-byte sniff in the first 8 KiB so binaries aren't stored as text. A per-snapshot total-bytes budget caps memory.
Persistence for the ChangeTracker's adaptive auto-skip set.
The walker learns "fat directories" on first visit (those with more immediate child files than autoSkipFileCountThreshold) and skips them on subsequent walks within the same session. Without persistence, every new agent session re-learns from scratch — paying the first-walk cost over and over for the same dirs.
This file persists the learned set to `~/.config/sprout/shell_skip_dirs.json`, keyed by absolute workspace root, so subsequent sessions in the same workspace inherit the learning. The file is best-effort: read failures fall back to an empty set (re-learn), write failures log a warning.
Package agent provides error definitions for the agent package.
Consolidated memory tool.
One handler that dispatches on `operation` to the existing per-op helpers — replaces add_memory / read_memory / list_memories / delete_memory / search_memories so the LLM only sees one entry for memory management.
Package agent provides typed error classification for tool error retry decisions.
The retry package defines a classification system that uses the typed AgentError system from pkg/errors to determine appropriate retry behavior instead of relying on string matching against error messages.
Classification is driven by the error category:
- TransientError → Retry (backoff)
- RateLimitError → Retry (longer backoff)
- SecurityError → Escalate (ask user/LLM)
- InvalidInputError → Fail (input must be fixed)
- ContextError → Fail (context overflow, needs compaction)
- PermanentError → Fail (non-recoverable)
- ProviderError → Fail (auth/config) or Retry (server errors) depending on Retryable field
- Unknown errors → Retry once then Fail
Package agent provides the seed integration layer — a thin adapter that delegates the seed conversation loop to sprout's existing provider, executor, and event bus.
seed/core types are the canonical definitions (seed/core/types.go). sprout/agent_api/types.go re-exports these via type aliases so sprout consumes them directly. The conversion helpers below are identity functions now that the types match.
The adapter lives here because it bridges seed/core.Provider and seed/core.ToolExecutor interfaces to sprout's ClientInterface and ToolExecutor.
Destructive shell command classifier.
Peer to shellLooksReadOnly. Identifies shell commands that are likely to clobber the user's active changes — either by reverting working-tree edits (`git checkout .`, `git reset --hard`, `git restore .`) or by deleting untracked work (`git clean -fd`, `git stash drop`, etc.).
When the change tracker sees a destructive command, it pivots to a safer (slower) mode:
- The adaptive autoSkipDirs set is IGNORED for the walk (and the walk doesn't add to it during a destructive run). A directory that was learned as "fat" during a build might contain edits the user wants back after a `git checkout .` — we'd rather pay the walk cost than silently drop the recovery payload.
- The bulk-rollup branch in RecordShellMutations is BYPASSED so every mutation lands as a per-file entry with full OriginalCode for recovery. A 300-file `git checkout .` produces 300 recoverable rows, not one opaque "src/ — 300 files" row.
- Truncation (50k file / 500ms / 32 MiB caps) gets promoted from a log line to a user-visible manifest entry so partial coverage during a destructive op is impossible to miss.
Bias: CONSERVATIVE in the opposite direction from shellLooksReadOnly. False positive ("said destructive when it wasn't") means we run a fuller walk and emit per-file for a normal command — cheap. False negative ("missed a destructive op") means we might silently drop a recoverable change — expensive. So unrecognised flags or subcommands on a known-destructive program err toward "destructive".
Read-only shell command classifier.
Used to short-circuit the shell-snapshot pass for commands that provably can't mutate the filesystem. Skipping the snapshot avoids the ~10 ms warm-walk cost (and the full prime cost when uncached) on every `ls`, `grep`, `cat`, `git status`, etc. — by far the most common shell_command invocations.
Bias: the classifier is CONSERVATIVE. False positive ("said read-only when it wasn't") means we miss tracking the mutation — bad. False negative ("said write when it was read-only") means we pay the snapshot cost we didn't need — cheap. So any unknown program, chaining operator, redirect, subshell, or known-dangerous flag forces the snapshot.
Package agent provides subagent management via the SubagentRunner, which supports both serial (Run) and parallel (RunParallel) execution of subagent tasks.
SubagentRunner Concurrency Invariants:
MaxConcurrentSubagents: When > 0, a buffered channel semaphore limits the number of concurrently executing subagents. Tasks waiting for a slot respect parent context cancellation and return Cancelled=true.
FleetTokenBudget: When > 0, tracks cumulative token usage across the fleet via atomic.Int64. Once the budget is reached, not-yet-started tasks are skipped with BudgetExceeded=true. Currently running tasks are NOT interrupted.
Order Preservation: RunParallel returns results in the same order as the input tasks, regardless of execution order.
Consolidated task queue tool.
One handler that dispatches on `operation` to the existing per-op helpers — replaces task_queue_read / task_queue_publish / task_queue_add so the LLM only sees one entry for queue management.
Tool call formatting: display-friendly representations of tool calls for logging, progress output, and CLI status reporting.
Tool executor: core struct, constructor, and orchestration entry point.
Companions (all in this package):
Execution: tool_executor_sequential.go, tool_executor_parallel.go Config: tool_executor_config.go Context: tool_execution_context.go, tool_executor_helpers.go Safety: tool_executor_circuit_breaker.go Observability: tool_executor_trace.go Formatting: tool_call_format.go Constraint: tool_result_constraint.go Todo events: tool_executor_todo_events.go JSON repair: tool_json_repair.go
Circuit breaker: prevents infinite tool-execution loops by tracking repeated identical actions within a sliding time window.
Tool executor configuration: timeout defaults and constants.
Tool executor helpers: small utility functions that support the tool execution lifecycle (MCP delegation, stop conditions, ID generation, numeric normalization).
Tool executor: parallel batch execution for safe, independent tools.
Tool executor: sequential and single tool call execution.
Todo event publishing: detects changes in todo checklists after TodoWrite tool calls and publishes structured update events.
Trace recording: captures tool execution data into the trace session for observability, replay, and post-hoc analysis.
Agent-facing tools backed by the ChangeTracker's session buffer.
After the SP-061-2 consolidation this file ships only two tools — the rest were folded into options on these:
list_changes Manifest of the session's changes, with three optional knobs: include_diff: bool per-file unified diff (was show_my_change) group_by: "block"|"" activity-block summary (was summarize_my_session) include_persisted: bool merge hot+warm history (was my_recent_changes) Plus the existing filters: since, tool, path_pattern.
revert_my_changes Bulk undo by scope ("all" or "since"). The previous file= scope was removed because recover_file(scope="session_start") does the same thing with clearer semantics.
Recovery of an individual file (or bulk entry, or session-start state) lives in tool_handlers_recover.go.
recover_file tool: restores a file's tracked content from the ChangeTracker's session buffer. Closes the loop between "we captured original bytes" and "user/agent can put them back".
The SP-061-2 consolidation rolled three behaviours into one tool via the `scope` argument:
scope="latest" (default) Restore the file to the state immediately before its most-recent tracked change. The historical recover_file shape.
scope="session_start" Restore to the EARLIEST captured original — the file as it was before the agent touched it at all this session. Replaces the revert_my_changes(file=…) scope.
scope="bulk" Treat `path` as a bulk entry's FilePath (a command label like "git checkout ." or a dir like "webui/src/"). Walks the entry's BulkItems and restores every packed file. Replaces the standalone recover_bulk tool.
Selection rules:
- Most-recent matching change for `path` wins for scope="latest" (the tracker records changes in append order).
- Earliest matching change wins for scope="session_start".
- The change must have a recoverable OriginalCode (non-empty, not the redacted sentinel, not the path-only sentinel).
- For "create" entries (no original existed), recovery is a delete: removing a created file restores the workspace to pre-creation state.
Safety:
- Refuses paths outside the workspace root (no cross-workspace restores).
- Refuses when the file would resolve to a directory or symlink target.
- Returns a structured JSON result so the LLM can reason about success vs. why-it-couldn't.
Package agent provides the shell command handler with a two-gate security model.
Gate 1 (Global Static Classifier): pkg/agent_tools/security_classifier.go:ClassifyToolCall() Inspects tool name + arguments using string-based heuristics. Always runs regardless of persona. Can block (ShouldBlock) or prompt (ShouldPrompt) for dangerous operations.
Gate 2 (Persona Risk Cascade): pkg/agent/agent_getters.go:EvaluateOperationRisk() Evaluates commands against the active persona's auto_approve_rules. Returns Low/Medium/High.
INVARIANT: Neither gate may suppress or bypass the other. Both evaluate independently. The more restrictive result always wins.
Package agent provides the core agent functionality including tool registry and handlers.
Tool functionality is organized across:
- tool_definitions.go: Tool configuration structs and registry initialization
- tool_handlers.go: Tool handler implementations
- self_review_tool.go: Self-review tool handler
Tool result constraint: truncation and compaction of tool results before they are sent to the model context window.
Index ¶
- Constants
- Variables
- func BuildScopedSessionPathForTesting(stateDir, sessionID, workingDir string) (string, error)
- func DecrementActiveSubagents()
- func DeleteMemory(name string) error
- func DeleteMemoryEmbedding(mgr *embedding.EmbeddingManager, name string) error
- func DeleteSession(sessionID string) error
- func DeleteSessionScoped(sessionID, workingDir string) error
- func DetectLanguages(dir string) []string
- func EmbedAndStoreTurn(ctx context.Context, mgr *embedding.EmbeddingManager, turn *ConversationTurn) error
- func EmbedMemory(ctx context.Context, mgr *embedding.EmbeddingManager, name string, ...) error
- func EstimateTokens(text string) int
- func ExportStateToJSON(state *ConversationState) ([]byte, error)
- func FormatCLIMessage(similarity float64, threshold float64) string
- func FormatProactiveContext(results []ProactiveContextResult, config ProactiveContextConfig, now time.Time) string
- func GetActiveSubagents() int
- func GetEmbeddedPlanningPrompt(createTodos bool) (string, error)
- func GetEmbeddedSystemPrompt() (string, error)
- func GetEmbeddedSystemPromptWithProvider(provider string) (string, error)
- func GetSessionName(sessionID string) string
- func GetSessionNameScoped(sessionID, workingDir string) string
- func GetSessionPreview(sessionID string) string
- func GetSessionPreviewScoped(sessionID, workingDir string) string
- func GetSkillManifest(content string) (map[string]string, string, error)
- func GetStateDir() (string, error)
- func HasUserApproval(ctx context.Context) bool
- func IncrementActiveSubagents()
- func InitializeToolRegistry()
- func IsInteractiveTool(name string) bool
- func ListSessions() ([]string, error)
- func LoadContextFiles() (string, error)
- func LoadMemoriesForPrompt() string
- func LoadMemoryContent(name string) (string, error)
- func MigrateMemories(ctx context.Context, mgr *embedding.EmbeddingManager)
- func NewConversationPruner(debug bool) *core.ConversationPruner
- func NewSeedToolRegistry(agent *Agent) *core.ToolRegistry
- func NewSproutProvider(agent *Agent, client api.ClientInterface) (core.Provider, error)
- func NewSproutToolExecutor(agent *Agent, exec *ToolExecutor) core.ToolExecutor
- func ParseAgentsMd(path string) (name string, description string)
- func PublishModel(model string)
- func RenameSession(sessionID string, newName string) error
- func RenameSessionScoped(sessionID, newName, workingDir string) error
- func ResetMigrationForTesting()
- func SaveMemory(name string, content string) error
- func SetGetStateDirForTest(dir string) func() (string, error)
- func SetGetStateDirForTestError(msg string) func() (string, error)
- func SetGetStateDirFunc(fn func() (string, error)) func() (string, error)
- func SetPackageDebugLogging(enabled bool)
- func SetPackageLogger(l *AgentLogger)
- func SetStateDirFuncForTesting(fn func() (string, error)) func()
- func SweepExpiredEntries(retentionDays int, storePath string) (int, error)
- func UseSeedLoop() bool
- func ValidateStreamConfig(sc *StreamConfig) error
- func WithUserApproved(ctx context.Context) context.Context
- func WriteTestSessionFile(stateDir, sessionID, workingDir string, state *ConversationState) error
- type Agent
- func NewAgent() (*Agent, error)
- func NewAgentWithClient(client api.ClientInterface, clientType api.ClientType, ...) (*Agent, error)
- func NewAgentWithConfigDir(configDir, model string) (*Agent, error)
- func NewAgentWithLayers(globalDir, workspaceDir, model string) (*Agent, error)
- func NewAgentWithModel(model string) (*Agent, error)
- func NewTestAgent() *Agent
- func (a *Agent) AddMessage(message api.Message)
- func (a *Agent) AddSessionAllowedFolder(folder string)
- func (a *Agent) AddTaskAction(actionType, description, details string)
- func (a *Agent) AddToHistory(command string)
- func (a *Agent) ApplyPersona(personaID string) error
- func (a *Agent) ApplyState(state *ConversationState)
- func (a *Agent) ApplySyncOp(op SyncOp, workspaceRoot string) SyncOpResult
- func (a *Agent) ApplySyncOpBatch(ops []SyncOp, workspaceRoot string) []SyncOpResult
- func (a *Agent) BuildCheckpointCompactedMessages(messages []api.Message) ([]api.Message, []TurnCheckpoint)
- func (a *Agent) CanSpawnSubagents() bool
- func (a *Agent) CheckFileContentSecurity(filePath string, content string)
- func (a *Agent) CheckForInterrupt() bool
- func (a *Agent) CheckPatchConflict(path string) (bool, string)
- func (a *Agent) ClearActivePersona()
- func (a *Agent) ClearConversationHistory()
- func (a *Agent) ClearInputInjectionContext()
- func (a *Agent) ClearInterrupt()
- func (a *Agent) ClearSessionOverrides()
- func (a *Agent) ClearShellCommandHistory()
- func (a *Agent) ClearTrackedChanges()
- func (a *Agent) CommitChanges(llmResponse string) error
- func (a *Agent) ConsumePendingStrictSwitchNotice() string
- func (a *Agent) DeferredMessageCount() int
- func (a *Agent) DisableAutoPruning()
- func (a *Agent) DisableChangeTracking()
- func (a *Agent) DisableEmbeddingIndex()
- func (a *Agent) DisableStreaming()
- func (a *Agent) DrainDeferredMessages() []string
- func (a *Agent) ElevateSessionToPermissive()
- func (a *Agent) EnableAutoPruning()
- func (a *Agent) EnableChangeTracking(instructions string)
- func (a *Agent) EnableEmbeddingIndex() error
- func (a *Agent) EnableStreaming(callback func(string))
- func (a *Agent) EnqueueDeferredMessage(text string)
- func (a *Agent) EvaluateOperationRisk(command string) configuration.RiskLevel
- func (a *Agent) ExportState() ([]byte, error)
- func (a *Agent) FleetBudgetExceeded() bool
- func (a *Agent) GenerateActionSummary() string
- func (a *Agent) GenerateCompactSummary() string
- func (a *Agent) GenerateConversationSummary() string
- func (a *Agent) GenerateResponse(messages []api.Message) (string, error)
- func (a *Agent) GenerateSessionSummary() string
- func (a *Agent) GetActivePersona() string
- func (a *Agent) GetActiveRiskProfile() configuration.RiskProfile
- func (a *Agent) GetAllShellCommandHistory() map[string]*ShellCommandResult
- func (a *Agent) GetAvailablePersonaIDs() []string
- func (a *Agent) GetAvailableToolNames() []string
- func (a *Agent) GetAverageTPS() float64
- func (a *Agent) GetBackgroundProcessManager() *tools.BackgroundProcessManager
- func (a *Agent) GetCachedCostSavings() float64
- func (a *Agent) GetCachedTokens() int
- func (a *Agent) GetChangeCount() int
- func (a *Agent) GetChangeTracker() *ChangeTracker
- func (a *Agent) GetChangesSummary() string
- func (a *Agent) GetCompletionTokens() int
- func (a *Agent) GetConfig() *configuration.Config
- func (a *Agent) GetConfigManager() *configuration.Manager
- func (a *Agent) GetConfigOverrides() map[string]interface{}
- func (a *Agent) GetContextTokens() (used, limit int)
- func (a *Agent) GetContextWarningIssued() bool
- func (a *Agent) GetCurrentContextTokens() int
- func (a *Agent) GetCurrentIteration() int
- func (a *Agent) GetCurrentTPS() float64
- func (a *Agent) GetDebugLogPath() string
- func (a *Agent) GetElevationGate() *security.ElevationGate
- func (a *Agent) GetEmbeddingManager() *embedding.EmbeddingManager
- func (a *Agent) GetEstimatedTokenResponses() int
- func (a *Agent) GetEventBus() *events.EventBus
- func (a *Agent) GetEventChatID() string
- func (a *Agent) GetEventClientID() string
- func (a *Agent) GetEventUserID() string
- func (a *Agent) GetFileMetadata(path string) (WorkspaceFileMetadata, bool)
- func (a *Agent) GetHistory() []string
- func (a *Agent) GetHistoryCommand(index int) string
- func (a *Agent) GetHistorySize() int
- func (a *Agent) GetInputInjectionContext() <-chan string
- func (a *Agent) GetLLMCallCount() int
- func (a *Agent) GetLastMessages(n int) []api.Message
- func (a *Agent) GetLastPreparedToolNames() []string
- func (a *Agent) GetLastRunTerminationReason() string
- func (a *Agent) GetLastTPS() float64
- func (a *Agent) GetMaxContextTokens() int
- func (a *Agent) GetMaxIterations() int
- func (a *Agent) GetMessages() []api.Message
- func (a *Agent) GetModel() string
- func (a *Agent) GetOptimizationStats() map[string]interface{}
- func (a *Agent) GetOutputRedactor() *security.OutputRedactor
- func (a *Agent) GetPersonaProviderModel(personaID string) (string, string, error)
- func (a *Agent) GetPreviousSummary() string
- func (a *Agent) GetPromptTokens() int
- func (a *Agent) GetProvider() string
- func (a *Agent) GetProviderType() api.ClientType
- func (a *Agent) GetPruningStats() map[string]interface{}
- func (a *Agent) GetRevisionID() string
- func (a *Agent) GetSecurityApprovalMgr() *security.ApprovalManager
- func (a *Agent) GetSessionID() string
- func (a *Agent) GetShellCommandHistoryEntry(command string) (*ShellCommandResult, bool)
- func (a *Agent) GetShellCwd() string
- func (a *Agent) GetSubagentRunner() *SubagentRunner
- func (a *Agent) GetSyncStatus() map[string]WorkspaceFileMetadata
- func (a *Agent) GetSystemPrompt() string
- func (a *Agent) GetTPSStats() map[string]float64
- func (a *Agent) GetTaskActions() []TaskAction
- func (a *Agent) GetTerminalManager() tools.TerminalAccess
- func (a *Agent) GetTodoManager() *tools.TodoManager
- func (a *Agent) GetTotalCost() float64
- func (a *Agent) GetTotalTokens() int
- func (a *Agent) GetTrackedFiles() []string
- func (a *Agent) GetUnsafeMode() bool
- func (a *Agent) GetValidator() *validation.Validator
- func (a *Agent) GetWorkspaceRoot() string
- func (a *Agent) HandleInterrupt() string
- func (a *Agent) HasActiveWebUIClients() bool
- func (a *Agent) HasSessionOverrides() bool
- func (a *Agent) HasTurnCheckpoints() bool
- func (a *Agent) ImportState(data []byte) error
- func (a *Agent) InjectInputContext(input string) error
- func (a *Agent) InjectProactiveContext(ctx context.Context, query string) error
- func (a *Agent) InjectWebUIManagers(approvalMgr *security.ApprovalManager, askUserMgr *tools.AskUserManager)
- func (a *Agent) InterruptCtx() context.Context
- func (a *Agent) IsChangeTrackingEnabled() bool
- func (a *Agent) IsDebugMode() bool
- func (a *Agent) IsEmbeddingIndexEnabled() bool
- func (a *Agent) IsFolderSessionAllowed(absPath string) bool
- func (a *Agent) IsInteractiveMode() bool
- func (a *Agent) IsInterrupted() bool
- func (a *Agent) IsLocalMode() bool
- func (a *Agent) IsSecurityBypassApproved() bool
- func (a *Agent) IsSessionElevated() bool
- func (a *Agent) IsShellCommandAllowlisted(command string) bool
- func (a *Agent) IsStreamingEnabled() bool
- func (a *Agent) IsSubagent() bool
- func (a *Agent) ListChanges(args map[string]interface{}) (string, error)
- func (a *Agent) LoadState(sessionID string) (*ConversationState, error)
- func (a *Agent) LoadStateFromFile(filename string) error
- func (a *Agent) LoadStateScoped(sessionID, workingDir string) (*ConversationState, error)
- func (a *Agent) LoadSummaryFromFile(filename string) error
- func (a *Agent) LogToolCall(tc api.ToolCall, phase string)
- func (a *Agent) Logger() *AgentLogger
- func (a *Agent) MarkEstimatedTokenUsageResponse()
- func (a *Agent) MaxSubagentDepth() int
- func (a *Agent) MergeEventMetadata(extras map[string]interface{})
- func (a *Agent) MyRecentChanges(since string) (string, error)
- func (a *Agent) NavigateHistory(direction int, currentIndex int) (string, int)
- func (a *Agent) OutputRouter() *OutputRouter
- func (a *Agent) PersistShellCommandAllowlist(command string) error
- func (a *Agent) PrintCompactProgress()
- func (a *Agent) PrintConciseSummary()
- func (a *Agent) PrintConversationSummary(forceFull bool)
- func (a *Agent) PrintLine(text string)
- func (a *Agent) PrintLineAsync(text string)
- func (a *Agent) PrintTerminalOnly(text string)
- func (a *Agent) ProcessQuery(userQuery string) (string, error)
- func (a *Agent) ProcessQueryWithContinuity(userQuery string) (string, error)
- func (a *Agent) PromptChoice(prompt string, choices []ChoiceOption) (string, error)
- func (a *Agent) PublishAgentMessage(category, message string, extra map[string]interface{})
- func (a *Agent) PublishFileChange(filePath, action, content string)
- func (a *Agent) PublishQueryProgress(message string, iteration int, tokensUsed int)
- func (a *Agent) PublishStreamChunk(chunk string, contentType string)
- func (a *Agent) PublishTodoUpdate(todos []map[string]interface{})
- func (a *Agent) PublishToolEnd(toolCallID, toolName, status, result, errorMessage string, ...)
- func (a *Agent) PublishToolExecution(toolName, action string, details map[string]interface{})
- func (a *Agent) PublishToolStart(toolName, toolCallID, arguments, displayName, persona string, isSubagent bool, ...)
- func (a *Agent) ReadFileContent(path string) (string, error)
- func (a *Agent) RecordFileReadThisTurn(path string)
- func (a *Agent) RecordTurnCheckpoint(startIndex, endIndex int)
- func (a *Agent) RecordTurnCheckpointAsync(startIndex, endIndex int)
- func (a *Agent) RecoverFile(path string) (string, error)
- func (a *Agent) RefreshMCPTools() error
- func (a *Agent) ReplaceTurnCheckpoints(checkpoints []TurnCheckpoint)
- func (a *Agent) ResetFileReadsForNewTurn()
- func (a *Agent) ResetHistoryIndex()
- func (a *Agent) RestoreEmbeddingIndex()
- func (a *Agent) RevertMyChanges(scope, file, since string) (string, error)
- func (a *Agent) SaveConversationSummary() error
- func (a *Agent) SaveState(sessionID string) error
- func (a *Agent) SaveStateScoped(sessionID, workingDir string) error
- func (a *Agent) SaveStateToFile(filename string) error
- func (a *Agent) SelectProvider() error
- func (a *Agent) SetBackgroundProcessManager(bpm *tools.BackgroundProcessManager)
- func (a *Agent) SetBaseSystemPrompt(prompt string)
- func (a *Agent) SetConfigOverrides(overrides map[string]interface{})
- func (a *Agent) SetConversationOptimization(enabled bool)
- func (a *Agent) SetElevationGatePrompter()
- func (a *Agent) SetEventBus(eventBus *events.EventBus)
- func (a *Agent) SetEventMetadata(metadata map[string]interface{})
- func (a *Agent) SetFileMetadata(path string, md WorkspaceFileMetadata)
- func (a *Agent) SetFleetBudget(tracker *atomic.Int64, limit int64)
- func (a *Agent) SetFlushCallback(callback func())
- func (a *Agent) SetHasActiveWebUIClients(fn func() bool)
- func (a *Agent) SetInterruptHandler(ch chan struct{})
- func (a *Agent) SetLastPreparedToolNames(tools []api.Tool)
- func (a *Agent) SetMaxIterations(max int)
- func (a *Agent) SetMessages(messages []api.Message)
- func (a *Agent) SetModel(model string) error
- func (a *Agent) SetModelPersisted(model string) error
- func (a *Agent) SetOutputMutex(mutex *sync.Mutex)
- func (a *Agent) SetPreviousSummary(summary string)
- func (a *Agent) SetProvider(provider api.ClientType) error
- func (a *Agent) SetProviderPersisted(provider api.ClientType) error
- func (a *Agent) SetPruningSlidingWindowSize(size int)
- func (a *Agent) SetPruningStrategy(strategy PruningStrategy)
- func (a *Agent) SetPruningThreshold(threshold float64)
- func (a *Agent) SetRecentMessagesToKeep(count int)
- func (a *Agent) SetRiskProfileOverride(profile configuration.RiskProfile)
- func (a *Agent) SetSessionID(sessionID string)
- func (a *Agent) SetSessionName(name string)
- func (a *Agent) SetShellCommandHistoryEntry(command string, result *ShellCommandResult)
- func (a *Agent) SetShellCwd(dir string)
- func (a *Agent) SetStatsUpdateCallback(callback func(int, float64))
- func (a *Agent) SetStreamingCallback(callback func(string))
- func (a *Agent) SetStreamingEnabled(enabled bool)
- func (a *Agent) SetSystemPrompt(prompt string)
- func (a *Agent) SetSystemPromptFromFile(filePath string) error
- func (a *Agent) SetTerminalManager(tm tools.TerminalAccess)
- func (a *Agent) SetTraceSession(traceSession interface{})
- func (a *Agent) SetUI(ui UI)
- func (a *Agent) SetUnsafeMode(unsafe bool)
- func (a *Agent) SetWorkspaceRoot(workspaceRoot string)
- func (a *Agent) ShowColoredDiff(oldContent, newContent string, maxLines int)
- func (a *Agent) ShowDropdown(items interface{}, options DropdownOptions) (interface{}, error)
- func (a *Agent) ShowMyChange(path string) (string, error)
- func (a *Agent) ShowQuickPrompt(prompt string, options []QuickOption, horizontal bool) (QuickOption, error)
- func (a *Agent) Shutdown()
- func (a *Agent) SnapshotSessionAllowedFolders() []string
- func (a *Agent) SubagentDepth() int
- func (a *Agent) SummarizeMySession() (string, error)
- func (a *Agent) ToolLog(action string, target string)
- func (a *Agent) TrackFileEdit(filePath string, originalContent string, newContent string) error
- func (a *Agent) TrackFileWrite(filePath string, content string) error
- func (a *Agent) TrackMetricsFromResponse(promptTokens, completionTokens, totalTokens int, estimatedCost float64, ...)
- func (a *Agent) TriggerInterrupt()
- type AgentLogger
- func (l *AgentLogger) Debug(format string, args ...interface{})
- func (l *AgentLogger) Error(format string, args ...interface{})
- func (l *AgentLogger) Info(format string, args ...interface{})
- func (l *AgentLogger) SetJSONMode(jsonMode bool)
- func (l *AgentLogger) Warn(format string, args ...interface{})
- func (l *AgentLogger) WithFields(fields map[string]string) *LogContext
- type AgentMCPManager
- func (m *AgentMCPManager) GetInitError() error
- func (m *AgentMCPManager) GetManager() mcp.MCPManager
- func (m *AgentMCPManager) GetToolsCache() []api.Tool
- func (m *AgentMCPManager) IsInitialized() bool
- func (m *AgentMCPManager) LockInit()
- func (m *AgentMCPManager) SetInitError(err error)
- func (m *AgentMCPManager) SetInitialized(initialized bool)
- func (m *AgentMCPManager) SetManager(mgr mcp.MCPManager)
- func (m *AgentMCPManager) SetToolsCache(tools []api.Tool)
- func (m *AgentMCPManager) UnlockInit()
- type AgentOutputManager
- func (m *AgentOutputManager) EnsureAsyncOutputWorker(fn func())
- func (m *AgentOutputManager) GetAsyncBufferSize() int
- func (m *AgentOutputManager) GetAsyncOutput() chan string
- func (m *AgentOutputManager) GetEventMetadata() map[string]interface{}
- func (m *AgentOutputManager) GetEventMetadataMutex() *sync.RWMutex
- func (m *AgentOutputManager) GetFlushCallback() func()
- func (m *AgentOutputManager) GetOutputMutex() *sync.Mutex
- func (m *AgentOutputManager) GetOutputRouter() *OutputRouter
- func (m *AgentOutputManager) GetReasoningBuffer() *strings.Builder
- func (m *AgentOutputManager) GetReasoningCallback() func(string)
- func (m *AgentOutputManager) GetStreamingBuffer() *strings.Builder
- func (m *AgentOutputManager) GetStreamingCallback() func(string)
- func (m *AgentOutputManager) GetTerminalWriter() func(string)
- func (m *AgentOutputManager) IsStreamingEnabled() bool
- func (m *AgentOutputManager) SetAsyncBufferSize(size int)
- func (m *AgentOutputManager) SetAsyncOutput(ch chan string)
- func (m *AgentOutputManager) SetEventMetadata(meta map[string]interface{})
- func (m *AgentOutputManager) SetEventMetadataUnlocked(meta map[string]interface{})
- func (m *AgentOutputManager) SetFlushCallback(cb func())
- func (m *AgentOutputManager) SetOutputMutex(mu *sync.Mutex)
- func (m *AgentOutputManager) SetOutputRouter(router *OutputRouter)
- func (m *AgentOutputManager) SetReasoningCallback(cb func(string))
- func (m *AgentOutputManager) SetStreamingCallback(cb func(string))
- func (m *AgentOutputManager) SetStreamingEnabled(enabled bool)
- func (m *AgentOutputManager) SetTerminalWriter(fn func(string))
- type AgentSecurityManager
- func (m *AgentSecurityManager) AddSessionAllowedFolder(folder string)
- func (m *AgentSecurityManager) GetAskUserMgr() *agenttools.AskUserManager
- func (m *AgentSecurityManager) GetElevationGate() *security.ElevationGate
- func (m *AgentSecurityManager) GetOutputRedactor() *security.OutputRedactor
- func (m *AgentSecurityManager) GetSecurityApprovalMgr() *security.ApprovalManager
- func (m *AgentSecurityManager) GetUnsafeMode() bool
- func (m *AgentSecurityManager) HasActiveWebUIClients() bool
- func (m *AgentSecurityManager) IsConcernIgnored(filePath, concern string) bool
- func (m *AgentSecurityManager) IsFolderSessionAllowed(absPath string) bool
- func (m *AgentSecurityManager) IsSecurityBypassApproved() bool
- func (m *AgentSecurityManager) SetApprovalMgr(mgr *security.ApprovalManager)
- func (m *AgentSecurityManager) SetAskUserMgr(mgr *agenttools.AskUserManager)
- func (m *AgentSecurityManager) SetConcernIgnored(filePath, concern string)
- func (m *AgentSecurityManager) SetElevationGate(gate *security.ElevationGate)
- func (m *AgentSecurityManager) SetHasActiveWebUIClients(fn func() bool)
- func (m *AgentSecurityManager) SetUnsafeMode(unsafe bool)
- func (m *AgentSecurityManager) SnapshotSessionAllowedFolders() []string
- type AgentState
- type AgentStateManager
- func (s *AgentStateManager) AddCost(c float64)
- func (s *AgentStateManager) AddMessage(msg api.Message)
- func (s *AgentStateManager) AddTaskAction(action TaskAction)
- func (s *AgentStateManager) AddTurnCheckpoint(cp TurnCheckpoint)
- func (s *AgentStateManager) GetActivePersona() string
- func (s *AgentStateManager) GetActiveSkills() []string
- func (s *AgentStateManager) GetCachedCostSavings() float64
- func (s *AgentStateManager) GetCachedTokens() int
- func (s *AgentStateManager) GetCheckpointMutex() *sync.RWMutex
- func (s *AgentStateManager) GetCircuitBreaker() *CircuitBreakerState
- func (s *AgentStateManager) GetCommandHistory() []string
- func (s *AgentStateManager) GetCompletionTokens() int
- func (s *AgentStateManager) GetConfigOverrides() map[string]interface{}
- func (s *AgentStateManager) GetConversationPruner() *ConversationPruner
- func (s *AgentStateManager) GetCurrentContextTokens() int
- func (s *AgentStateManager) GetCurrentIteration() int
- func (s *AgentStateManager) GetEstimatedTokenResponses() int
- func (s *AgentStateManager) GetHistoryIndex() int
- func (s *AgentStateManager) GetHistoryMutex() *sync.Mutex
- func (s *AgentStateManager) GetLLMCallCount() int
- func (s *AgentStateManager) GetLastProviderError() *ProviderErrorInfo
- func (s *AgentStateManager) GetLastRunTerminationReason() string
- func (s *AgentStateManager) GetMaxContextTokens() int
- func (s *AgentStateManager) GetMessages() []api.Message
- func (s *AgentStateManager) GetOptimizer() *ConversationOptimizer
- func (s *AgentStateManager) GetPauseMutex() *sync.Mutex
- func (s *AgentStateManager) GetPauseState() *PauseState
- func (s *AgentStateManager) GetPendingStrictSwitchNotice() string
- func (s *AgentStateManager) GetPendingSwitchContextRefresh() string
- func (s *AgentStateManager) GetPendingSystemSupplement() string
- func (s *AgentStateManager) GetPreviousSummary() string
- func (s *AgentStateManager) GetPromptTokens() int
- func (s *AgentStateManager) GetSessionID() string
- func (s *AgentStateManager) GetSessionIntentEmbedding() []float32
- func (s *AgentStateManager) GetSessionModel() string
- func (s *AgentStateManager) GetSessionProvider() api.ClientType
- func (s *AgentStateManager) GetTaskActions() []TaskAction
- func (s *AgentStateManager) GetTaskActionsMutex() *sync.RWMutex
- func (s *AgentStateManager) GetTotalCost() float64
- func (s *AgentStateManager) GetTotalTokens() int
- func (s *AgentStateManager) GetTotalToolCalls() int
- func (s *AgentStateManager) GetTraceSession() interface{}
- func (s *AgentStateManager) GetTurnCheckpoints() []TurnCheckpoint
- func (s *AgentStateManager) IncrementLLMCallCount()
- func (s *AgentStateManager) IncrementTotalToolCalls()
- func (s *AgentStateManager) IsContextWarningIssued() bool
- func (s *AgentStateManager) IsFalseStopDetectionEnabled() bool
- func (s *AgentStateManager) IsToolCallGuidanceAdded() bool
- func (s *AgentStateManager) SetActivePersona(p string)
- func (s *AgentStateManager) SetActiveSkills(skills []string)
- func (s *AgentStateManager) SetCachedCostSavings(c float64)
- func (s *AgentStateManager) SetCachedTokens(n int)
- func (s *AgentStateManager) SetCircuitBreaker(cb *CircuitBreakerState)
- func (s *AgentStateManager) SetCommandHistory(h []string)
- func (s *AgentStateManager) SetCompletionTokens(n int)
- func (s *AgentStateManager) SetConfigOverrides(overrides map[string]interface{})
- func (s *AgentStateManager) SetContextWarningIssued(v bool)
- func (s *AgentStateManager) SetConversationPruner(pruner *ConversationPruner)
- func (s *AgentStateManager) SetCurrentContextTokens(n int)
- func (s *AgentStateManager) SetCurrentIteration(iter int)
- func (s *AgentStateManager) SetEstimatedTokenResponses(n int)
- func (s *AgentStateManager) SetFalseStopDetectionEnabled(v bool)
- func (s *AgentStateManager) SetHistoryIndex(i int)
- func (s *AgentStateManager) SetLLMCallCount(n int)
- func (s *AgentStateManager) SetLastProviderError(err *ProviderErrorInfo)
- func (s *AgentStateManager) SetLastRunTerminationReason(reason string)
- func (s *AgentStateManager) SetMaxContextTokens(n int)
- func (s *AgentStateManager) SetMessages(msgs []api.Message)
- func (s *AgentStateManager) SetOptimizer(o *ConversationOptimizer)
- func (s *AgentStateManager) SetPauseState(ps *PauseState)
- func (s *AgentStateManager) SetPendingStrictSwitchNotice(v string)
- func (s *AgentStateManager) SetPendingSwitchContextRefresh(v string)
- func (s *AgentStateManager) SetPendingSystemSupplement(v string)
- func (s *AgentStateManager) SetPreviousSummary(summary string)
- func (s *AgentStateManager) SetPromptTokens(n int)
- func (s *AgentStateManager) SetSessionID(id string)
- func (s *AgentStateManager) SetSessionIntentEmbedding(emb []float32)
- func (s *AgentStateManager) SetSessionIntentEmbeddingIfNil(emb []float32) bool
- func (s *AgentStateManager) SetSessionModel(m string)
- func (s *AgentStateManager) SetSessionProvider(ct api.ClientType)
- func (s *AgentStateManager) SetTaskActions(actions []TaskAction)
- func (s *AgentStateManager) SetToolCallGuidanceAdded(v bool)
- func (s *AgentStateManager) SetTotalCost(c float64)
- func (s *AgentStateManager) SetTotalTokens(n int)
- func (s *AgentStateManager) SetTotalToolCalls(n int)
- func (s *AgentStateManager) SetTraceSession(ts interface{})
- func (s *AgentStateManager) SetTurnCheckpoints(cps []TurnCheckpoint)
- type ChangeTracker
- func (ct *ChangeTracker) Clear()
- func (ct *ChangeTracker) CollectFileChangesForCheckpoint() ([]CheckpointFileChange, string)
- func (ct *ChangeTracker) Commit(llmResponse string, conversation []api.Message) error
- func (ct *ChangeTracker) Disable()
- func (ct *ChangeTracker) Enable()
- func (ct *ChangeTracker) GenerateAISummary() (string, error)
- func (ct *ChangeTracker) GetChangeCount() int
- func (ct *ChangeTracker) GetChanges() []TrackedFileChange
- func (ct *ChangeTracker) GetRevisionID() string
- func (ct *ChangeTracker) GetSummary() string
- func (ct *ChangeTracker) GetTrackedFiles() []string
- func (ct *ChangeTracker) IsEnabled() bool
- func (ct *ChangeTracker) PrimeShellTracking(workDir string)
- func (ct *ChangeTracker) RecordShellMutations(before, after map[string]*shellSnapshotEntry, toolCall string)
- func (ct *ChangeTracker) Reset(instructions string)
- func (ct *ChangeTracker) SyncShellCacheForPath(path string)
- func (ct *ChangeTracker) TrackFileEdit(filePath string, originalContent string, newContent string) error
- func (ct *ChangeTracker) TrackFileWrite(filePath string, newContent string) error
- func (ct *ChangeTracker) TrackShellTurn(workDir, toolCall string, destructive bool)
- type CheckpointFileChange
- type ChoiceOption
- type CircuitBreakerAction
- type CircuitBreakerState
- type ClarificationManager
- func (m *ClarificationManager) Cleanup()
- func (m *ClarificationManager) Close()
- func (m *ClarificationManager) GetPendingClarifications(delegateID string) []ClarificationRequest
- func (m *ClarificationManager) RequestClarification(ctx context.Context, delegateID, question string) (string, error)
- func (m *ClarificationManager) RespondClarification(requestID, response string) error
- type ClarificationRequest
- type ContextFileInfo
- type ConversationOptimizer
- func (co *ConversationOptimizer) CompactConversation(messages []api.Message) []api.Message
- func (co *ConversationOptimizer) GetOptimizationStats() map[string]interface{}
- func (co *ConversationOptimizer) Inner() *core.ConversationOptimizer
- func (co *ConversationOptimizer) InvalidateFile(filePath string)
- func (co *ConversationOptimizer) IsEnabled() bool
- func (co *ConversationOptimizer) OptimizeConversation(messages []api.Message) []api.Message
- func (co *ConversationOptimizer) Reset()
- func (co *ConversationOptimizer) SetEnabled(enabled bool)
- func (co *ConversationOptimizer) SetLLMClient(client api.ClientInterface, provider string, printLine func(string))
- type ConversationPruner
- type ConversationState
- func ImportStateFromJSONFile(filename string) (*ConversationState, error)
- func LoadSessionInfo(sessionID string) (*ConversationState, error)
- func LoadStateWithoutAgent(sessionID string) (*ConversationState, error)
- func LoadStateWithoutAgentScoped(sessionID, workingDir string) (*ConversationState, error)
- type ConversationTurn
- type DiffChange
- type DriftDetector
- func (d *DriftDetector) CheckDrift(sessionIntent []float32, currentEmbedding []float32) (isDrift bool, similarity float64)
- func (d *DriftDetector) DriftCount() int
- func (d *DriftDetector) IsSuppressed() bool
- func (d *DriftDetector) RecordAcceptance()
- func (d *DriftDetector) RecordDrift()
- func (d *DriftDetector) RecordRejection()
- func (d *DriftDetector) RejectionCount() int
- func (d *DriftDetector) ShouldCheck(turnNumber int) bool
- type DriftNotification
- type DropdownItem
- type DropdownOptions
- type FileChange
- type LogContext
- type LogEntry
- type MCPSubManager
- type MemoryInfo
- type MessageImportance
- type ModelItem
- type OutputBuffer
- type OutputManager
- type OutputMode
- type OutputRouter
- func (r *OutputRouter) Mode() OutputMode
- func (r *OutputRouter) RouteAgentMessage(category, message string, extra map[string]interface{})
- func (r *OutputRouter) RouteStreamChunk(chunk string, contentType string)
- func (r *OutputRouter) RouteTerminalOnly(message string)
- func (r *OutputRouter) RouteToolCompletion(ok bool, duration time.Duration, errMsg string)
- func (r *OutputRouter) RouteToolLog(action string, target string)
- func (r *OutputRouter) SetEventBus(eventBus *events.EventBus)
- func (r *OutputRouter) SetExternalWriteHook(fn func())
- func (r *OutputRouter) SetReasoningCallback(fn func(string))
- func (r *OutputRouter) SetReasoningTerminalEnabled(enabled bool)
- type ParameterConfig
- type PathTier
- type PauseState
- type ProactiveContextConfig
- type ProactiveContextResult
- type ProgressEntry
- type ProjectInfo
- type PromptTokensDetails
- type ProviderErrorInfo
- type PruningStrategy
- type QuickOption
- type RateLimitExceededError
- type ReconciliationActionResult
- type ReconciliationActionType
- type RetryAction
- type ScriptedClient
- func (c *ScriptedClient) AddResponse(response *ScriptedResponse)
- func (c *ScriptedClient) AdvanceIndex()
- func (c *ScriptedClient) Cancel()
- func (c *ScriptedClient) CheckConnection() error
- func (c *ScriptedClient) ClearHistory()
- func (c *ScriptedClient) ClearSentRequests()
- func (c *ScriptedClient) Close()
- func (c *ScriptedClient) GetAverageTPS() float64
- func (c *ScriptedClient) GetIndex() int
- func (c *ScriptedClient) GetLastTPS() float64
- func (c *ScriptedClient) GetModel() string
- func (c *ScriptedClient) GetModelContextLimit() (int, error)
- func (c *ScriptedClient) GetNextResponse() *ScriptedResponse
- func (c *ScriptedClient) GetProvider() string
- func (c *ScriptedClient) GetSentRequest(index int) []api.Message
- func (c *ScriptedClient) GetSentRequests() [][]api.Message
- func (c *ScriptedClient) GetTPSStats() map[string]float64
- func (c *ScriptedClient) GetVisionModel() string
- func (c *ScriptedClient) LastResponse() *ScriptedResponse
- func (c *ScriptedClient) Length() int
- func (c *ScriptedClient) ListModels(ctx context.Context) ([]api.ModelInfo, error)
- func (c *ScriptedClient) Reset()
- func (c *ScriptedClient) ResetTPSStats()
- func (c *ScriptedClient) ResponseHistory() []*ScriptedResponse
- func (c *ScriptedClient) SendChatRequest(ctx context.Context, messages []api.Message, tools []api.Tool, ...) (*api.ChatResponse, error)
- func (c *ScriptedClient) SendChatRequestStream(ctx context.Context, messages []api.Message, tools []api.Tool, ...) (*api.ChatResponse, error)
- func (c *ScriptedClient) SendVisionRequest(ctx context.Context, messages []api.Message, tools []api.Tool, ...) (*api.ChatResponse, error)
- func (c *ScriptedClient) SetDebug(debug bool)
- func (c *ScriptedClient) SetIndex(idx int)
- func (c *ScriptedClient) SetModel(model string) error
- func (c *ScriptedClient) SetResponses(responses []*ScriptedResponse)
- func (c *ScriptedClient) SupportsVision() bool
- type ScriptedResponse
- func NewErrorResponse(err error) *ScriptedResponse
- func NewKeepGoingResponse(content string) *ScriptedResponse
- func NewLengthResponse(content string) *ScriptedResponse
- func NewRateLimitResponse() *ScriptedResponse
- func NewStopResponse(content string) *ScriptedResponse
- func NewTimeoutResponse() *ScriptedResponse
- func NewToolCallResponse(name, args string, toolCalls ...api.ToolCall) *ScriptedResponse
- type ScriptedResponseBuilder
- func (b *ScriptedResponseBuilder) Build() *ScriptedResponse
- func (b *ScriptedResponseBuilder) Content(content string) *ScriptedResponseBuilder
- func (b *ScriptedResponseBuilder) Delay(d time.Duration) *ScriptedResponseBuilder
- func (b *ScriptedResponseBuilder) Error(err error) *ScriptedResponseBuilder
- func (b *ScriptedResponseBuilder) FinishReason(reason string) *ScriptedResponseBuilder
- func (b *ScriptedResponseBuilder) Images(images []api.ImageData) *ScriptedResponseBuilder
- func (b *ScriptedResponseBuilder) RateLimitAfter(n int) *ScriptedResponseBuilder
- func (b *ScriptedResponseBuilder) ReasoningContent(content string) *ScriptedResponseBuilder
- func (b *ScriptedResponseBuilder) StreamConfig(sc *StreamConfig) *ScriptedResponseBuilder
- func (b *ScriptedResponseBuilder) ToolCall(tc api.ToolCall) *ScriptedResponseBuilder
- func (b *ScriptedResponseBuilder) ToolCalls(tcs []api.ToolCall) *ScriptedResponseBuilder
- func (b *ScriptedResponseBuilder) Usage(promptTokens, completionTokens, totalTokens int, estimatedCost float64) *ScriptedResponseBuilder
- func (b *ScriptedResponseBuilder) VisionOnly() *ScriptedResponseBuilder
- type ScriptedTokenUsage
- type SecurityManager
- type SessionInfo
- type SessionItem
- type SharedState
- type ShellCommandResult
- type SimpleUI
- type SkillInfo
- type StateManager
- type StreamConfig
- type SubagentError
- type SubagentMetrics
- type SubagentOptions
- type SubagentProgressEntry
- type SubagentResult
- type SubagentReturn
- type SubagentRunMetrics
- type SubagentRunner
- func (r *SubagentRunner) CancelAll()
- func (r *SubagentRunner) CancelSubagent(id string) bool
- func (r *SubagentRunner) GetActiveSubagents() []*runningSubagent
- func (r *SubagentRunner) InjectInputIntoActive(input string) (string, bool)
- func (r *SubagentRunner) Metrics() SubagentMetrics
- func (r *SubagentRunner) Run(ctx context.Context, prompt string, opts SubagentOptions) *SubagentResult
- func (r *SubagentRunner) RunParallel(ctx context.Context, tasks []SubagentTask, opts SubagentOptions) []*SubagentResult
- type SubagentStatus
- type SubagentTask
- type SyncOp
- type SyncOpResult
- type TaskAction
- type Theme
- type ThemeManager
- type TokenUsage
- type ToolConfig
- type ToolExecutor
- type ToolHandler
- type ToolHandlerWithImages
- type ToolRegistry
- func (r *ToolRegistry) ExecuteTool(ctx context.Context, toolName string, args map[string]interface{}, ...) ([]api.ImageData, string, error)
- func (r *ToolRegistry) GetAllToolConfigs() map[string]ToolConfig
- func (r *ToolRegistry) GetAvailableTools() []string
- func (r *ToolRegistry) GetToolConfig(name string) (ToolConfig, bool)
- func (r *ToolRegistry) IsInteractive(name string) bool
- func (r *ToolRegistry) RegisterTool(config ToolConfig)
- type TrackedBulkItem
- type TrackedFileChange
- type TurnCheckpoint
- type TurnEvaluation
- type UI
- type WorkspaceFileMetadata
Constants ¶
const ( PruneStrategyNone = core.PruneStrategyNone PruneStrategySlidingWindow = core.PruneStrategySlidingWindow PruneStrategyImportance = core.PruneStrategyImportance PruneStrategyHybrid = core.PruneStrategyHybrid PruneStrategyAdaptive = core.PruneStrategyAdaptive )
Pruning strategy constants — re-exported from seed for backward compatibility with sprout call sites that reference them unqualified.
const ( RunTerminationCompleted = "completed" RunTerminationMaxIterations = "max_iterations" RunTerminationInterrupted = "interrupted" RunTerminationFleetBudgetExceeded = "fleet_budget_exceeded" )
const ( MAX_SUBAGENT_OUTPUT_SIZE = 10 * 1024 * 1024 // 10MB MAX_SUBAGENT_CONTEXT_SIZE = 1024 * 1024 // 1MB BATCH_SIZE = 50 // Number of lines to batch before publishing DefaultSubagentTokenBudget = 2_000_000 // Default token budget for subagents )
const DefaultClarificationTimeout = 60 * time.Second
DefaultClarificationTimeout is the default timeout for clarification requests.
const DefaultDriftCheckInterval = 5
DefaultDriftCheckInterval is the default number of turns between drift checks.
const DefaultDriftThreshold = 0.60
DefaultDriftThreshold is the default cosine similarity threshold below which a conversation is considered to have drifted from its original intent.
const MaxDriftRejections = 3
MaxDriftRejections is the number of CONSECUTIVE rejections after which drift detection is suppressed for the remainder of the session.
const RedactedContentMarker = "[REDACTED - external file]"
RedactedContentMarker is the marker used when file content is redacted because the file is outside the workspace root (to avoid leaking sensitive data).
const SkillFileName = skills.SkillFileName
SkillFileName is the conventional name of the markdown file inside each skill directory. Re-exported from pkg/skills so callers in this package don't need to learn two import paths for the same constant.
Variables ¶
var ( ErrUINotAvailable = errors.New("UI not available") ErrCancelled = errors.New("user cancelled") )
UI errors
var ( ErrWriteStale = errors.New("write refused: file may be stale") ErrWriteHasUnsyncedEdits = errors.New("write refused: user has unsynced edits to this file") )
ErrWriteStale is the sentinel returned by checkWriteStaleness for the "no recent read" / "modified after read" cases. The agent's correct response is to read_file(path) and retry.
ErrWriteHasUnsyncedEdits is the sentinel for the "browser has edits the container hasn't seen yet" case. The agent must NOT auto-retry; instead it should ask the user whether to overwrite. The platform's WS sync layer populates the WorkspaceFileMetadata that drives this.
Both are deliberately wrappable via errors.Is so callers (including the tool-result formatter) can distinguish them without string-matching.
var ErrModelNotAvailable = errors.New("configured model is not available for this provider")
ErrModelNotAvailable is returned when the configured model for the current provider is not available. In daemon mode, this allows the web UI to detect the issue and present a model selection UI rather than hard-failing.
var ErrProviderNotConfigured = errors.New("provider is not configured — configure via webui settings")
ErrProviderNotConfigured is returned when the provider cannot be initialized (unrecognized provider, missing API key, etc.) in daemon mode. This allows the web UI to start without an agent and present a provider configuration UI instead of crashing the daemon.
var FleetBudgetExceededError = errors.New("fleet token budget exceeded")
FleetBudgetExceededError is returned by the seed provider when the shared fleet token budget has been exceeded mid-conversation. It is caught by processQueryWithSeed to truncate gracefully rather than surfacing as a generic API error.
var MILESTONE_PHASES = []string{"spawn", "complete", "step"}
MILESTONE_PHASES defines phases that trigger immediate publish without batching
var PruningConfig = struct { Default struct { StandardPercent float64 MinMessages int RecentMessages int SlidingWindow int } Structural struct { RecentMessagesToKeep int MinMessagesToCompact int MinMiddleMessages int } AgenticRequiredAvailableTokens int }{ Default: struct { StandardPercent float64 MinMessages int RecentMessages int SlidingWindow int }{ StandardPercent: 0.87, MinMessages: 5, RecentMessages: 24, SlidingWindow: 30, }, Structural: struct { RecentMessagesToKeep int MinMessagesToCompact int MinMiddleMessages int }{ RecentMessagesToKeep: core.StructuralRecentToKeep, MinMessagesToCompact: core.StructuralMinMessagesToCompact, MinMiddleMessages: core.StructuralMinMiddleMessages, }, AgenticRequiredAvailableTokens: 12000, }
PruningConfig preserves the historical "single source of truth" symbol some sprout tests reference. Values come from seed's defaults so any drift between sprout and seed is impossible by construction.
New code should not read from this — query the pruner instance directly or use seed's exported constants. Retained as a thin shim only.
Functions ¶
func BuildScopedSessionPathForTesting ¶
BuildScopedSessionPathForTesting constructs the scoped session file path for test setup.
func DecrementActiveSubagents ¶
func DecrementActiveSubagents()
DecrementActiveSubagents lowers the active-subagent counter when a subagent finishes (success, error, cancel — any terminal state).
func DeleteMemory ¶
DeleteMemory deletes a memory file by name (with .md extension)
func DeleteMemoryEmbedding ¶
func DeleteMemoryEmbedding(mgr *embedding.EmbeddingManager, name string) error
DeleteMemoryEmbedding removes a memory's embedding from the ConversationStore. This is called after DeleteMemory() to keep the vector index in sync.
Graceful failure: Errors are logged but not returned as fatal. Memory files are always deleted from disk regardless of embedding cleanup.
func DeleteSession ¶
DeleteSession removes a session state file
func DeleteSessionScoped ¶
func DetectLanguages ¶
func EmbedAndStoreTurn ¶
func EmbedAndStoreTurn(ctx context.Context, mgr *embedding.EmbeddingManager, turn *ConversationTurn) error
EmbedAndStoreTurn computes embeddings for a conversation turn's prompt and actionable summary using the static embedding provider, then stores the result as a VectorRecord in the ConversationStore.
Graceful failure: Errors are logged but not returned. The caller (checkpoint recording) should always succeed regardless of embedding failures.
func EmbedMemory ¶
func EmbedMemory(ctx context.Context, mgr *embedding.EmbeddingManager, name string, content string) error
EmbedMemory embeds a memory file's content and stores it in the ConversationStore as a VectorRecord with Type "memory". This is called after SaveMemory() to keep the vector index in sync.
Graceful failure: Errors are logged but not returned as fatal. Memory files are always saved to disk regardless of embedding success.
func EstimateTokens ¶
EstimateTokens provides a token estimation based on OpenAI's tiktoken approach. Delegates to the centralized implementation in agent_api for consistency across all providers.
func ExportStateToJSON ¶
func ExportStateToJSON(state *ConversationState) ([]byte, error)
ExportStateToJSON converts a ConversationState to JSON bytes
func FormatCLIMessage ¶
FormatCLIMessage returns a human-readable drift notification for CLI display.
func FormatProactiveContext ¶
func FormatProactiveContext(results []ProactiveContextResult, config ProactiveContextConfig, now time.Time) string
FormatProactiveContext formats retrieved results as a "Previous Work" section suitable for injection into the agent's system prompt.
Output format:
## Previous Work (Contextual Memory) The following past work may be relevant. Evaluate critically and discard anything irrelevant. ### <first line of prompt> (<relative time>) User: "<user prompt>" Summary: <actionable summary>
Returns "" when results is empty. The output is capped at config.MaxContextChars characters. Pass now=time.Time{} to use the current time (same pattern as RetrieveProactiveContext).
func GetActiveSubagents ¶
func GetActiveSubagents() int
GetActiveSubagents returns the current number of running subagents.
func GetEmbeddedPlanningPrompt ¶
GetEmbeddedPlanningPrompt returns the embedded planning prompt
func GetEmbeddedSystemPrompt ¶
GetEmbeddedSystemPrompt returns the embedded system prompt
func GetEmbeddedSystemPromptWithProvider ¶
GetEmbeddedSystemPromptWithProvider returns the embedded system prompt
func GetSessionName ¶
GetSessionName returns the name of a session
func GetSessionNameScoped ¶
func GetSessionPreview ¶
GetSessionPreview returns the first 50 characters of the first user message
func GetSessionPreviewScoped ¶
func GetStateDir ¶
GetStateDir returns the directory for storing conversation state
func HasUserApproval ¶
HasUserApproval reports whether an upstream gate already obtained user approval for the current tool execution.
func IncrementActiveSubagents ¶
func IncrementActiveSubagents()
IncrementActiveSubagents bumps the active-subagent counter; paired with DecrementActiveSubagents under a defer in the spawner.
func InitializeToolRegistry ¶
func InitializeToolRegistry()
InitializeToolRegistry pre-creates the tool registry to avoid first-use overhead This should be called during agent initialization for better performance
func IsInteractiveTool ¶
IsInteractiveTool is a top-level convenience wrapping GetToolRegistry().IsInteractive(name). It exists so callers that just need a name → bool lookup don't have to take a registry handle.
func ListSessions ¶
ListSessions returns all available session IDs
func LoadContextFiles ¶
LoadContextFiles loads and formats context files for inclusion in system prompt
func LoadMemoriesForPrompt ¶
func LoadMemoriesForPrompt() string
LoadMemoriesForPrompt loads all memories and formats them for inclusion in the system prompt Returns empty string if no memories exist
func LoadMemoryContent ¶
LoadMemoryContent reads a single memory file by name The name should be without the .md extension (e.g., "git-safety" reads git-safety.md)
func MigrateMemories ¶
func MigrateMemories(ctx context.Context, mgr *embedding.EmbeddingManager)
MigrateMemories performs a one-time migration of all existing memory files to the ConversationStore. It uses sync.Once to ensure it only runs once per process lifetime, even if called multiple times.
Migration skips files that are already embedded (by checking if a record with ID "memory:<name>" exists in the store).
func NewConversationPruner ¶
func NewConversationPruner(debug bool) *core.ConversationPruner
NewConversationPruner constructs a pruner with sprout's traditional defaults: adaptive strategy with seed-default thresholds. The debug flag is retained for caller compatibility but unused — seed routes observability through the EventPublisher instead of stderr prints.
func NewSeedToolRegistry ¶
func NewSeedToolRegistry(agent *Agent) *core.ToolRegistry
NewSeedToolRegistry creates a seed core.ToolRegistry with all 30 sprout tools registered. The registry implements core.ToolExecutor directly, so it can be used as the Executor in core.Options.
Seed's ToolRegistry handles: channel suffix stripping, alias resolution, argument parsing/repair, type coercion, required parameter validation, per-tool timeouts, result truncation, circuit breakers, parallel execution for SafeForParallel tools, and event publishing.
Sprout-specific concerns are wired through:
- PreExecuteHook: security classification + subagent nesting prevention
- Handler closures: capture agent for sprout's (ctx, agent, args) signature and apply all post-processing (constraints, truncation, secret redaction, duplicate embedding check, TodoWrite events, error sanitization).
func NewSproutProvider ¶
NewSproutProvider creates a Provider that wraps a sprout ClientInterface.
func NewSproutToolExecutor ¶
func NewSproutToolExecutor(agent *Agent, exec *ToolExecutor) core.ToolExecutor
NewSproutToolExecutor creates a ToolExecutor that wraps a sprout agent ToolExecutor.
func ParseAgentsMd ¶
func PublishModel ¶
func PublishModel(model string)
PublishModel publishes a model selection (placeholder implementation)
func RenameSession ¶
RenameSession renames a session by updating the name field in the state file
func RenameSessionScoped ¶
func ResetMigrationForTesting ¶
func ResetMigrationForTesting()
ResetMigrationForTesting resets the one-time migration guard for testing purposes.
func SaveMemory ¶
SaveMemory writes a memory file Sanitizes the name: lowercase, replace spaces with hyphens, strip special chars Keeps only alphanumeric, hyphens, and underscores
func SetGetStateDirForTest ¶
SetGetStateDirForTest is a convenience helper that sets getStateDirFunc to return a fixed directory for testing.
func SetGetStateDirForTestError ¶
SetGetStateDirForTestError is a convenience helper that sets getStateDirFunc to return an error for testing error handling.
func SetGetStateDirFunc ¶
SetGetStateDirFunc sets the getStateDirFunc for testing purposes. Returns the previous function so it can be restored after the test.
func SetPackageDebugLogging ¶
func SetPackageDebugLogging(enabled bool)
SetPackageDebugLogging toggles the debug gate at runtime. Useful for tests and for the agent's --debug flag wiring.
func SetPackageLogger ¶
func SetPackageLogger(l *AgentLogger)
SetPackageLogger sets the package-level AgentLogger that package-level functions (without an *Agent receiver) use for structured logging. Called during agent initialization so embedding, proactive context, etc. all route through the same logger with session context.
func SetStateDirFuncForTesting ¶
SetStateDirFuncForTesting replaces the internal GetStateDir implementation for tests. It returns a restore function that will reset the original implementation when called. This function is safe for use in test code only.
Usage:
restore := agent.SetStateDirFuncForTesting(func() (string, error) {
return t.TempDir(), nil
})
defer restore()
func SweepExpiredEntries ¶
SweepExpiredEntries removes persistent context entries older than retentionDays from the conversation store at storePath. If retentionDays <= 0, this is a no-op. Returns the number of entries removed.
func UseSeedLoop ¶
func UseSeedLoop() bool
UseSeedLoop returns true if the agent should use seed's conversation loop instead of the native sprout ConversationHandler. DEPRECATED: Always returns true now that seed is the only path. Kept for backward compatibility with code that checks this value.
func ValidateStreamConfig ¶
func ValidateStreamConfig(sc *StreamConfig) error
ValidateStreamConfig validates a StreamConfig and returns an error if invalid
func WithUserApproved ¶
WithUserApproved marks the context as already having a user approval for the current tool call. Used by the static security gate to signal the persona cascade that re-prompting would be redundant.
func WriteTestSessionFile ¶
func WriteTestSessionFile(stateDir, sessionID, workingDir string, state *ConversationState) error
WriteTestSessionFile creates a scoped session file for testing.
Types ¶
type Agent ¶
type Agent struct {
// contains filtered or unexported fields
}
func NewAgentWithClient ¶
func NewAgentWithClient(client api.ClientInterface, clientType api.ClientType, configManager *configuration.Manager) (*Agent, error)
NewAgentWithClient builds an agent around a pre-constructed provider client. The interactive provider-resolution path in newAgentWithConfigManager (API-key prompts, connection checks, recovery loops) is skipped — useful for WASM/SDK callers where the caller already knows which provider and model to use, and where API keys live elsewhere (e.g. attached server-side by the sprout-foundry platform proxy).
The configManager must already be initialized; pass one from configuration.NewManagerSilent() or similar. The returned agent is a production agent (full lifecycle: context limits, session cleanup, tool registry, persona auto-activation).
func NewAgentWithConfigDir ¶
NewAgentWithConfigDir creates a new agent using a per-client config directory. This enables per-client config isolation for the WebUI, where each X-Sprout-Client-ID can have its own isolated config directory so settings changes by one client don't affect another.
func NewAgentWithLayers ¶
NewAgentWithLayers creates a new agent using layered configuration. globalDir contains global config (~/.config/sprout/), workspaceDir contains workspace config. This is the preferred method for WebUI usage where workspace config is supported.
func NewAgentWithModel ¶
NewAgentWithModel creates a new agent with optional model override
func NewTestAgent ¶
func NewTestAgent() *Agent
NewTestAgent creates a minimal Agent suitable for unit tests.
Tests that create bare &Agent{} structs must remember to call initSubManagers() to avoid nil-pointer panics. NewTestAgent() eliminates that two-step dance by returning an Agent whose sub-managers (state, output, security, mcpSub) and basic fields (shellCommandHistory) are already initialised.
The returned agent has NO API client, config manager, or system prompt — those are only needed in integration-style tests that should use NewAgent() instead.
Callers may freely mutate the returned Agent (e.g. setting debug, swapping in a mock state manager) after construction.
func (*Agent) AddMessage ¶
AddMessage adds a single message to the conversation history
func (*Agent) AddSessionAllowedFolder ¶
AddSessionAllowedFolder records the folder picked by the user from the filesystem approval dialog so future accesses under it are auto-approved for the rest of this session.
func (*Agent) AddTaskAction ¶
AddTaskAction records a completed task action for continuity
func (*Agent) AddToHistory ¶
AddToHistory adds a command to the history buffer
func (*Agent) ApplyPersona ¶
ApplyPersona activates a configured persona and applies provider/model/system-prompt overrides.
func (*Agent) ApplyState ¶
func (a *Agent) ApplyState(state *ConversationState)
ApplyState applies a loaded state to the current agent
func (*Agent) ApplySyncOp ¶
func (a *Agent) ApplySyncOp(op SyncOp, workspaceRoot string) SyncOpResult
ApplySyncOp applies a single SyncOp to the workspace filesystem. It validates the operation, checks for conflicts with container-side changes, applies the change, and updates the file metadata.
func (*Agent) ApplySyncOpBatch ¶
func (a *Agent) ApplySyncOpBatch(ops []SyncOp, workspaceRoot string) []SyncOpResult
ApplySyncOpBatch applies a slice of SyncOps in order, collecting results. Stops on the first conflict, returning Accepted=false for remaining ops.
func (*Agent) BuildCheckpointCompactedMessages ¶
func (*Agent) CanSpawnSubagents ¶
CanSpawnSubagents returns true if this agent is allowed to spawn subagents (i.e., current depth is less than the configured max depth).
func (*Agent) CheckFileContentSecurity ¶
CheckFileContentSecurity runs security concern detection on file content after a write. In WebUI mode, it uses the event-bus-based ApprovalManager to show a dialog. In CLI mode, it falls back to the interactive logger prompt. Ignored concerns are tracked per-file so they are not re-prompted.
func (*Agent) CheckForInterrupt ¶
CheckForInterrupt checks if an interrupt was requested
func (*Agent) CheckPatchConflict ¶
CheckPatchConflict checks whether a container patch to the given path conflicts with unsynced browser edits. Returns (conflict bool, theirsPath string). theirsPath is "<path>.theirs" when conflict is true, empty otherwise.
func (*Agent) ClearActivePersona ¶
func (a *Agent) ClearActivePersona()
ClearActivePersona removes any active persona override and restores the base system prompt.
func (*Agent) ClearConversationHistory ¶
func (a *Agent) ClearConversationHistory()
ClearConversationHistory clears the conversation history
func (*Agent) ClearInputInjectionContext ¶
func (a *Agent) ClearInputInjectionContext()
ClearInputInjectionContext clears any pending input injections
func (*Agent) ClearInterrupt ¶
func (a *Agent) ClearInterrupt()
ClearInterrupt resets the interrupt state
func (*Agent) ClearSessionOverrides ¶
func (a *Agent) ClearSessionOverrides()
ClearSessionOverrides clears any session-scoped provider/model overrides. This should be called when a webui session ends to restore config-based behavior.
func (*Agent) ClearShellCommandHistory ¶
func (a *Agent) ClearShellCommandHistory()
ClearShellCommandHistory removes all entries from shell command history
func (*Agent) ClearTrackedChanges ¶
func (a *Agent) ClearTrackedChanges()
ClearTrackedChanges clears all tracked changes (but keeps tracking enabled)
func (*Agent) CommitChanges ¶
CommitChanges commits all tracked changes to the change tracker
func (*Agent) ConsumePendingStrictSwitchNotice ¶
func (*Agent) DeferredMessageCount ¶
DeferredMessageCount returns how many messages are currently queued. Used by the UI to show "N queued" hints. Reads are racy with enqueues but counts are advisory anyway.
func (*Agent) DisableAutoPruning ¶
func (a *Agent) DisableAutoPruning()
DisableAutoPruning disables automatic conversation pruning
func (*Agent) DisableChangeTracking ¶
func (a *Agent) DisableChangeTracking()
DisableChangeTracking disables change tracking
func (*Agent) DisableEmbeddingIndex ¶
func (a *Agent) DisableEmbeddingIndex()
DisableEmbeddingIndex stops and cleans up the embedding manager. It persists the preference to the workspace config so it stays disabled on restart.
func (*Agent) DisableStreaming ¶
func (a *Agent) DisableStreaming()
DisableStreaming disables response streaming
func (*Agent) DrainDeferredMessages ¶
DrainDeferredMessages atomically removes and returns all queued messages. The CLI's REPL loop calls this after ReadLine() returns the user's next prompt and prepends them to the typed text.
func (*Agent) ElevateSessionToPermissive ¶
func (a *Agent) ElevateSessionToPermissive()
ElevateSessionToPermissive sets the agent's transient risk-profile override to "permissive" for the rest of this session. Used by the "Elevate permissions" choice on the approval dialog. Does NOT persist to disk — the user is expected to run `/risk-profile permissive` if they want this to survive restart.
Critical-tier ops (rm -rf /, fork bombs) still block; "permissive" only widens the auto-approved set, it does not disable the cascade.
func (*Agent) EnableAutoPruning ¶
func (a *Agent) EnableAutoPruning()
EnableAutoPruning enables automatic conversation pruning with default adaptive strategy
func (*Agent) EnableChangeTracking ¶
EnableChangeTracking enables change tracking for this agent session.
Side effect: primes the shell-mutation snapshot cache against the agent's workspace root. This is the one-time cost (~280 ms on a 5000-file workspace) that lets every subsequent shell_command be tracked via a cheap stat-only diff. Without this prime the first shell command's mutations would silently establish the baseline (auto-prime in TrackShellTurn) and go un-recorded — fine for read-only commands, but a real loss if the first shell does any writes.
func (*Agent) EnableEmbeddingIndex ¶
EnableEmbeddingIndex initializes the embedding manager and starts building the index in the background. Call this when the user explicitly enables indexing for the workspace (via /index command or UI toggle). It persists the preference to the workspace config so it survives restarts.
func (*Agent) EnableStreaming ¶
EnableStreaming enables response streaming with a callback
func (*Agent) EnqueueDeferredMessage ¶
func (*Agent) EvaluateOperationRisk ¶
func (a *Agent) EvaluateOperationRisk(command string) configuration.RiskLevel
EvaluateOperationRisk determines the risk level of a command for the currently active persona, using the persona's auto-approve rules. Returns RiskLevelCritical / High / Medium / Low.
Resolution order (matches the SP-058 risk profile design):
- Critical patterns (rm -rf root, fork bomb) — ALWAYS return Critical, regardless of persona, profile, or active mode.
- Active persona has its own AutoApproveRules → use them (preserves EA autonomy and any other persona-specific carve-outs).
- Otherwise → resolve the agent's active risk profile and use its baked-in rules.
- No persona at all → return Low (no cascade gating, classic non-EA behavior).
func (*Agent) ExportState ¶
ExportState exports the current agent state for persistence
func (*Agent) FleetBudgetExceeded ¶
FleetBudgetExceeded reports whether the fleet budget was exceeded during this agent's execution (mid-run truncation).
func (*Agent) GenerateActionSummary ¶
GenerateActionSummary creates a summary of completed actions for continuity
func (*Agent) GenerateCompactSummary ¶
GenerateCompactSummary creates a compact summary for session continuity (max 5K context)
func (*Agent) GenerateConversationSummary ¶
GenerateConversationSummary creates a comprehensive summary of the conversation including todos
func (*Agent) GenerateResponse ¶
GenerateResponse generates a simple response using the current model without tool calls.
TODO(SP-034-1c): accept a ctx parameter and forward it so callers can abort in-flight calls. The interruptCtx on the agent is the natural source, but changing this signature ripples into many callsites — handle in 1c.
func (*Agent) GenerateSessionSummary ¶
GenerateSessionSummary creates a summary of previous actions for continuity
func (*Agent) GetActivePersona ¶
GetActivePersona returns the currently active persona ID.
func (*Agent) GetActiveRiskProfile ¶
func (a *Agent) GetActiveRiskProfile() configuration.RiskProfile
GetActiveRiskProfile returns the profile currently in effect for this agent (override > config > default). Exposed for status commands / debug logging.
func (*Agent) GetAllShellCommandHistory ¶
func (a *Agent) GetAllShellCommandHistory() map[string]*ShellCommandResult
GetAllShellCommandHistory returns a copy of the shell command history
func (*Agent) GetAvailablePersonaIDs ¶
GetAvailablePersonaIDs returns all configured persona IDs, filtering out LocalOnly personas when running in cloud mode.
func (*Agent) GetAvailableToolNames ¶
GetAvailableToolNames returns the effective tool names available to the active session.
func (*Agent) GetAverageTPS ¶
GetAverageTPS returns the average TPS across all requests
func (*Agent) GetBackgroundProcessManager ¶
func (a *Agent) GetBackgroundProcessManager() *tools.BackgroundProcessManager
GetBackgroundProcessManager returns the background process manager.
func (*Agent) GetCachedCostSavings ¶
GetCachedCostSavings returns the cost savings from cached tokens
func (*Agent) GetCachedTokens ¶
GetCachedTokens returns the total cached/reused tokens
func (*Agent) GetChangeCount ¶
GetChangeCount returns the number of file changes tracked in this session
func (*Agent) GetChangeTracker ¶
func (a *Agent) GetChangeTracker() *ChangeTracker
GetChangeTracker returns the change tracker (can be nil)
func (*Agent) GetChangesSummary ¶
GetChangesSummary returns a summary of tracked changes
func (*Agent) GetCompletionTokens ¶
GetCompletionTokens returns the total completion tokens used
func (*Agent) GetConfig ¶
func (a *Agent) GetConfig() *configuration.Config
GetConfig returns the configuration
func (*Agent) GetConfigManager ¶
func (a *Agent) GetConfigManager() *configuration.Manager
GetConfigManager returns the configuration manager
func (*Agent) GetConfigOverrides ¶
GetConfigOverrides returns the session-scoped config overrides.
func (*Agent) GetContextTokens ¶
GetTotalCost returns the total cost of the conversation GetContextTokens returns the current and max token counts for the active model's context window. (0, 0) when state is unavailable. SP-048-3.
func (*Agent) GetContextWarningIssued ¶
GetContextWarningIssued returns whether a context warning has been issued
func (*Agent) GetCurrentContextTokens ¶
GetCurrentContextTokens returns the current context token count
func (*Agent) GetCurrentIteration ¶
GetCurrentIteration returns the current iteration number
func (*Agent) GetCurrentTPS ¶
GetCurrentTPS returns the current TPS value (alias for GetLastTPS)
func (*Agent) GetDebugLogPath ¶
GetDebugLogPath returns the path to the current debug log file (if any)
func (*Agent) GetElevationGate ¶
func (a *Agent) GetElevationGate() *security.ElevationGate
GetElevationGate returns the agent's elevation gate for external use (e.g., commit flows).
func (*Agent) GetEmbeddingManager ¶
func (a *Agent) GetEmbeddingManager() *embedding.EmbeddingManager
GetEmbeddingManager returns the embedding index manager (may be nil if embedding is not configured or enabled in the agent's config).
func (*Agent) GetEstimatedTokenResponses ¶
GetEstimatedTokenResponses returns how many responses used estimated token usage.
func (*Agent) GetEventBus ¶
GetEventBus returns the current event bus
func (*Agent) GetEventChatID ¶
GetEventChatID returns the bound chat_id from event metadata, if present.
func (*Agent) GetEventClientID ¶
GetEventClientID returns the bound client_id from event metadata, if present.
func (*Agent) GetEventUserID ¶
GetEventUserID returns the bound user_id from event metadata, if present.
func (*Agent) GetFileMetadata ¶
func (a *Agent) GetFileMetadata(path string) (WorkspaceFileMetadata, bool)
GetFileMetadata returns the cached metadata for `path` (zero-value + false if absent). Read-side companion to SetFileMetadata.
func (*Agent) GetHistory ¶
GetHistory returns a defensive copy of the command history.
func (*Agent) GetHistoryCommand ¶
GetHistoryCommand returns the command at the given index from history
func (*Agent) GetHistorySize ¶
GetHistorySize returns the number of commands in history
func (*Agent) GetInputInjectionContext ¶
GetInputInjectionContext returns the input injection channel for the new system
func (*Agent) GetLLMCallCount ¶
GetLLMCallCount returns the total number of LLM API calls made
func (*Agent) GetLastMessages ¶
GetLastMessages returns the last N messages for preview
func (*Agent) GetLastPreparedToolNames ¶
GetLastPreparedToolNames returns the tool names sent in the most recent model request.
func (*Agent) GetLastRunTerminationReason ¶
func (*Agent) GetLastTPS ¶
GetLastTPS returns the most recent TPS value from the provider
func (*Agent) GetMaxContextTokens ¶
GetMaxContextTokens returns the maximum context tokens for the current model
func (*Agent) GetMaxIterations ¶
GetMaxIterations returns the maximum iterations allowed (0 means unlimited)
func (*Agent) GetMessages ¶
GetMessages returns the current conversation messages
func (*Agent) GetOptimizationStats ¶
GetOptimizationStats returns optimization statistics
func (*Agent) GetOutputRedactor ¶
func (a *Agent) GetOutputRedactor() *security.OutputRedactor
GetOutputRedactor returns the agent's output redactor for external use.
func (*Agent) GetPersonaProviderModel ¶
GetPersonaProviderModel returns effective provider/model for display.
func (*Agent) GetPreviousSummary ¶
GetPreviousSummary returns the summary of previous actions
func (*Agent) GetPromptTokens ¶
GetPromptTokens returns the total prompt tokens used
func (*Agent) GetProvider ¶
GetProvider returns the current provider name
func (*Agent) GetProviderType ¶
func (a *Agent) GetProviderType() api.ClientType
GetProviderType returns the current provider type
func (*Agent) GetPruningStats ¶
GetPruningStats returns information about the current pruning configuration
func (*Agent) GetRevisionID ¶
GetRevisionID returns the current revision ID (if change tracking is enabled)
func (*Agent) GetSecurityApprovalMgr ¶
func (a *Agent) GetSecurityApprovalMgr() *security.ApprovalManager
GetSecurityApprovalMgr returns the security approval manager
func (*Agent) GetSessionID ¶
GetSessionID returns the session identifier
func (*Agent) GetShellCommandHistoryEntry ¶
func (a *Agent) GetShellCommandHistoryEntry(command string) (*ShellCommandResult, bool)
GetShellCommandHistoryEntry retrieves a shell command result from history
func (*Agent) GetShellCwd ¶
GetShellCwd returns the current logical shell working directory.
func (*Agent) GetSubagentRunner ¶
func (a *Agent) GetSubagentRunner() *SubagentRunner
GetSubagentRunner returns the per-agent subagent runner, creating it lazily.
func (*Agent) GetSyncStatus ¶
func (a *Agent) GetSyncStatus() map[string]WorkspaceFileMetadata
GetSyncStatus returns a map of path → WorkspaceFileMetadata for all currently tracked files in the workspace metadata store.
func (*Agent) GetSystemPrompt ¶
GetSystemPrompt returns the current system prompt
func (*Agent) GetTPSStats ¶
GetTPSStats returns comprehensive TPS statistics
func (*Agent) GetTaskActions ¶
func (a *Agent) GetTaskActions() []TaskAction
GetTaskActions returns completed task actions
func (*Agent) GetTerminalManager ¶
func (a *Agent) GetTerminalManager() tools.TerminalAccess
GetTerminalManager returns the terminal manager (may be nil in CLI mode).
func (*Agent) GetTodoManager ¶
func (a *Agent) GetTodoManager() *tools.TodoManager
GetTodoManager returns the per-agent todo manager. This ensures session isolation in daemon mode where multiple agents run concurrently.
func (*Agent) GetTotalCost ¶
func (*Agent) GetTotalTokens ¶
GetTotalTokens returns the total tokens used across all requests
func (*Agent) GetTrackedFiles ¶
GetTrackedFiles returns the list of files that have been modified in this session
func (*Agent) GetUnsafeMode ¶
GetUnsafeMode returns whether unsafe mode is enabled
func (*Agent) GetValidator ¶
func (a *Agent) GetValidator() *validation.Validator
GetValidator returns the syntax validator (nil until SetEventBus is called).
func (*Agent) GetWorkspaceRoot ¶
GetWorkspaceRoot returns the logical workspace root for this agent instance.
func (*Agent) HandleInterrupt ¶
HandleInterrupt processes an interrupt request.
func (*Agent) HasActiveWebUIClients ¶
HasActiveWebUIClients calls the registered callback (or returns false if none is set) to check whether WebUI clients are connected.
func (*Agent) HasSessionOverrides ¶
HasSessionOverrides returns true if there are session-scoped provider/model overrides
func (*Agent) HasTurnCheckpoints ¶
func (*Agent) ImportState ¶
ImportState imports agent state from JSON data
func (*Agent) InjectInputContext ¶
InjectInputContext injects a new user input using context-based interrupt system
func (*Agent) InjectProactiveContext ¶
InjectProactiveContext retrieves semantically relevant past turns and injects them into the agent's system prompt supplement. This is called once per session — on the first turn or after a cold session restore.
Graceful degradation: all errors are logged; the agent is never blocked.
func (*Agent) InjectWebUIManagers ¶
func (a *Agent) InjectWebUIManagers(approvalMgr *security.ApprovalManager, askUserMgr *tools.AskUserManager)
InjectWebUIManagers replaces the agent's internal approval and ask-user managers with the webui-owned instances. This is called after the web server is constructed so that security prompts and ask_user requests created by the agent are routed through the same manager that the webui handlers resolve responses on — eliminating the need for global singletons.
func (*Agent) InterruptCtx ¶
InterruptCtx returns the agent's interrupt context so child operations (e.g., tool execution) can derive from it and respect user cancellations.
func (*Agent) IsChangeTrackingEnabled ¶
IsChangeTrackingEnabled returns whether change tracking is enabled
func (*Agent) IsDebugMode ¶
IsDebugMode returns whether debug mode is enabled
func (*Agent) IsEmbeddingIndexEnabled ¶
IsEmbeddingIndexEnabled returns whether the embedding index is currently active.
func (*Agent) IsFolderSessionAllowed ¶
IsFolderSessionAllowed reports whether absPath sits under a folder the user has allowlisted via "Allow this folder for the rest of the session" on the filesystem approval dialog.
func (*Agent) IsInteractiveMode ¶
IsInteractiveMode returns true if running in interactive mode
func (*Agent) IsInterrupted ¶
IsInterrupted returns true if an interrupt has been requested
func (*Agent) IsLocalMode ¶
IsLocalMode returns true when the agent is running locally (CLI or local WebUI), not in a cloud environment. This controls whether LocalOnly personas (like the Executive Assistant) are available.
Cloud mode is detected via the SPROUT_CLOUD environment variable. Local mode is the default when the variable is unset or empty.
func (*Agent) IsSecurityBypassApproved ¶
IsSecurityBypassApproved returns whether the user has approved any external filesystem access this session. Coarse signal: prefer the per-path IsFolderSessionAllowed for new code.
func (*Agent) IsSessionElevated ¶
IsSessionElevated reports whether the user has elevated the session to a permissive or unrestricted risk profile. When true, all three security gates (static classifier, filesystem tier, shell risk cascade) must skip their interactive prompts and auto-approve — the user explicitly opted out of per-operation prompts for this session. Critical-tier operations (rm -rf /, fork bombs) are NOT covered by elevation and always block regardless.
func (*Agent) IsShellCommandAllowlisted ¶
IsShellCommandAllowlisted reports whether the user has previously chosen "Always approve this command" for this exact command string. The match is literal — allowlisting `rm -rf /tmp/build` does NOT cover any other path. The Critical tier still blocks regardless; this short-circuit only applies to the High-risk persona-cascade gate.
func (*Agent) IsStreamingEnabled ¶
IsStreamingEnabled returns whether streaming is enabled
func (*Agent) IsSubagent ¶
IsSubagent returns true if this agent was spawned as a subagent (depth > 0). Used to prevent nested subagent spawning and skip interactive prompts.
func (*Agent) ListChanges ¶
ListChanges returns the session manifest. args may include "since" (RFC3339), "tool", "path_pattern". Returns the raw JSON string identical to what the LLM tool produces.
func (*Agent) LoadState ¶
func (a *Agent) LoadState(sessionID string) (*ConversationState, error)
LoadState loads a conversation state by session ID
func (*Agent) LoadStateFromFile ¶
LoadStateFromFile loads agent state from a file
func (*Agent) LoadStateScoped ¶
func (a *Agent) LoadStateScoped(sessionID, workingDir string) (*ConversationState, error)
LoadStateScoped loads a conversation state by session ID within a specific working directory scope.
func (*Agent) LoadSummaryFromFile ¶
LoadSummaryFromFile loads ONLY the compact summary from a state file for minimal continuity
func (*Agent) LogToolCall ¶
LogToolCall appends a JSON line describing a tool call to a local file for quick debugging. File: ./tool_calls.log (in the current working directory)
func (*Agent) Logger ¶
func (a *Agent) Logger() *AgentLogger
Logger returns the agent logger, initializing it lazily if needed
func (*Agent) MarkEstimatedTokenUsageResponse ¶
func (a *Agent) MarkEstimatedTokenUsageResponse()
MarkEstimatedTokenUsageResponse records that token usage for one response was estimated.
func (*Agent) MaxSubagentDepth ¶
MaxSubagentDepth returns the configured maximum nesting depth. EA root gets 3 levels (max depth 2), non-EA root gets 2 levels (max depth 1).
func (*Agent) MergeEventMetadata ¶
MergeEventMetadata adds extras to the current event metadata without discarding existing keys. Unlike SetEventMetadata, which replaces the map wholesale, this is the right call when a subagent needs to layer per-spawn fields (e.g. subagent_depth, active_persona) on top of already-set chat/client routing keys inherited from its parent.
func (*Agent) MyRecentChanges ¶
MyRecentChanges returns the cross-session timeline. Thin wrapper around list_changes(include_persisted=true, since=…).
func (*Agent) NavigateHistory ¶
NavigateHistory navigates through command history direction: 1 for up (older), -1 for down (newer) currentIndex: current position in the input line
func (*Agent) OutputRouter ¶
func (a *Agent) OutputRouter() *OutputRouter
OutputRouter returns the current output router (nil if not initialized)
func (*Agent) PersistShellCommandAllowlist ¶
PersistShellCommandAllowlist appends command to the user's persistent approved-commands list (Config.ApprovedShellCommands) and saves to disk. Used by the "Always approve this command" choice on the approval dialog. Idempotent: re-adding an existing entry is a no-op but still triggers a save so the file's mtime updates (cheap).
func (*Agent) PrintCompactProgress ¶
func (a *Agent) PrintCompactProgress()
PrintCompactProgress prints a minimal progress indicator for non-interactive mode Format: [iteration:(current-context-tokens/context-limit) | total-tokens | cost]
func (*Agent) PrintConciseSummary ¶
func (a *Agent) PrintConciseSummary()
PrintConciseSummary displays a single line with essential token and cost information
func (*Agent) PrintConversationSummary ¶
PrintConversationSummary displays a comprehensive conversation summary with formatting
func (*Agent) PrintLine ¶
PrintLine prints a line of text to the console content area synchronously. It delegates to the internal renderer that handles streaming vs CLI output.
func (*Agent) PrintLineAsync ¶
PrintLineAsync enqueues a line for asynchronous output. Background goroutines (rate-limit handlers, streaming workers, etc.) should prefer this helper to avoid blocking on the UI mutex. If the queue is saturated, we fall back to bounded waiting and finally synchronous printing to avoid goroutine leaks while still preserving message ordering as much as possible.
func (*Agent) PrintTerminalOnly ¶
PrintTerminalOnly writes text to the terminal without publishing to the event bus. Use this for output already published via a more specific event type.
func (*Agent) ProcessQuery ¶
ProcessQuery handles the main conversation loop with the LLM
func (*Agent) ProcessQueryWithContinuity ¶
ProcessQueryWithContinuity processes a query with continuity from previous actions
func (*Agent) PromptChoice ¶
func (a *Agent) PromptChoice(prompt string, choices []ChoiceOption) (string, error)
PromptChoice shows a dropdown selection of simple choices and returns the selected value
func (*Agent) PublishAgentMessage ¶
func (*Agent) PublishFileChange ¶
PublishAgentMessage publishes a structured agent system message event. This is the single unified routing point for all agent output. Safe to call even when eventBus is nil (CLI-only mode) — the internal publishEvent method checks for nil before publishing. PublishFileChange emits a file_changed event so the WebUI activity feed can reflect ChangeTracker-detected mutations (including shell-driven ones, not just direct write_file/edit_file calls). Content is the captured original (for deletes/edits) — pass empty for creates, where there's no prior content. Action: "created" / "modified" / "deleted" — matches events.FileChangedEvent vocabulary.
func (*Agent) PublishQueryProgress ¶
PublishQueryProgress publishes query progress for real-time updates
func (*Agent) PublishStreamChunk ¶
PublishStreamChunk publishes a streaming chunk for real-time updates
func (*Agent) PublishTodoUpdate ¶
PublishTodoUpdate publishes a structured todo update event
func (*Agent) PublishToolEnd ¶
func (a *Agent) PublishToolEnd(toolCallID, toolName, status, result, errorMessage string, duration time.Duration)
PublishToolEnd publishes a rich tool end event
func (*Agent) PublishToolExecution ¶
PublishToolExecution publishes tool execution events for real-time updates
func (*Agent) PublishToolStart ¶
func (a *Agent) PublishToolStart(toolName, toolCallID, arguments, displayName, persona string, isSubagent bool, subagentType string, toolIndex int)
PublishToolStart publishes a rich tool start event
func (*Agent) ReadFileContent ¶
ReadFileContent reads the content of a file from the workspace. The path is resolved relative to the agent's workspace root. Returns an error if the file does not exist or cannot be read.
func (*Agent) RecordFileReadThisTurn ¶
RecordFileReadThisTurn marks `path` as read by the agent during the current turn. Called from the read_file tool handler. Safe on a nil receiver so test scaffolding doesn't have to initialize the tracker.
func (*Agent) RecordTurnCheckpoint ¶
func (*Agent) RecordTurnCheckpointAsync ¶
func (*Agent) RecoverFile ¶
RecoverFile restores one file from the tracker's session buffer. scope is forwarded as-is to handleRecoverFile so callers can request "latest" (default), "session_start", or "bulk".
func (*Agent) RefreshMCPTools ¶
RefreshMCPTools refreshes the MCP tools cache
func (*Agent) ReplaceTurnCheckpoints ¶
func (a *Agent) ReplaceTurnCheckpoints(checkpoints []TurnCheckpoint)
func (*Agent) ResetFileReadsForNewTurn ¶
func (a *Agent) ResetFileReadsForNewTurn()
ResetFileReadsForNewTurn clears the per-turn read tracker. Called at turn boundaries so the staleness rule resets between turns: a file the agent read on turn N still needs a fresh read_file on turn N+1 before writing.
func (*Agent) ResetHistoryIndex ¶
func (a *Agent) ResetHistoryIndex()
ResetHistoryIndex resets the history navigation index
func (*Agent) RestoreEmbeddingIndex ¶
func (a *Agent) RestoreEmbeddingIndex()
RestoreEmbeddingIndex checks if indexing was previously enabled for this workspace and restores it. Called once during agent startup after workspace root is known.
func (*Agent) RevertMyChanges ¶
RevertMyChanges performs a bulk revert. The historical file= scope is now served by recover_file(scope="session_start"); this method keeps the old four-arg signature for back-compat and routes file= there.
func (*Agent) SaveConversationSummary ¶
SaveConversationSummary saves the conversation summary to the state file
func (*Agent) SaveStateScoped ¶
SaveStateScoped saves conversation state under a directory-scoped session namespace.
func (*Agent) SaveStateToFile ¶
SaveStateToFile saves agent state to a file
func (*Agent) SelectProvider ¶
SelectProvider allows interactive provider selection
func (*Agent) SetBackgroundProcessManager ¶
func (a *Agent) SetBackgroundProcessManager(bpm *tools.BackgroundProcessManager)
SetBackgroundProcessManager sets the background process manager for CLI mode. When set, shell commands can run in background without PTY (os/exec).
func (*Agent) SetBaseSystemPrompt ¶
SetBaseSystemPrompt updates the baseline prompt used when persona overrides are cleared.
func (*Agent) SetConfigOverrides ¶
SetConfigOverrides stores session-scoped config overrides on the agent. These are applied in-memory and persisted with the session state.
func (*Agent) SetConversationOptimization ¶
SetConversationOptimization enables or disables conversation optimization
func (*Agent) SetElevationGatePrompter ¶
func (a *Agent) SetElevationGatePrompter()
SetElevationGatePrompter wires the agent's interactive UI into the elevation gate. Call this after agent.ui is initialized (done automatically by SetUI).
func (*Agent) SetEventBus ¶
SetEventBus sets the event bus for real-time UI updates and initializes the validator
func (*Agent) SetEventMetadata ¶
SetEventMetadata attaches metadata that should be merged into all emitted UI events.
func (*Agent) SetFileMetadata ¶
func (a *Agent) SetFileMetadata(path string, md WorkspaceFileMetadata)
SetFileMetadata replaces the cached sync metadata for `path`. Called by the platform-side sync bridge whenever it learns about a new browser sequence or last-synced acknowledgement. Safe to call before the agent is otherwise initialized.
func (*Agent) SetFleetBudget ¶
SetFleetBudget enables per-LLM-call fleet budget tracking for this agent. When tracker is non-nil and limit > 0, each LLM call will debit its token usage to the shared tracker. If the budget is exceeded, fleetBudgetTrunc is set and the conversation loop will truncate gracefully.
func (*Agent) SetFlushCallback ¶
func (a *Agent) SetFlushCallback(callback func())
SetFlushCallback sets a callback to flush buffered output
func (*Agent) SetHasActiveWebUIClients ¶
SetHasActiveWebUIClients sets a callback that returns whether any WebUI clients are currently connected. The security prompting logic uses this to decide between WebUI event-bus routing and CLI-based prompting.
func (*Agent) SetInterruptHandler ¶
func (a *Agent) SetInterruptHandler(ch chan struct{})
SetInterruptHandler sets the interrupt handler for UI mode
func (*Agent) SetLastPreparedToolNames ¶
SetLastPreparedToolNames records the exact tool names prepared for the most recent model request.
func (*Agent) SetMaxIterations ¶
SetMaxIterations sets the maximum number of iterations for the agent. A value of 0 means unlimited (no iteration cap per prompt). Negative values are clamped to 0 (unlimited).
func (*Agent) SetMessages ¶
SetMessages sets the conversation messages (for restore)
func (*Agent) SetModel ¶
SetModel changes the current model for the session. This is the session-scoped version that doesn't persist to config. For CLI use with persistence, use SetModelPersisted.
func (*Agent) SetModelPersisted ¶
SetModelPersisted changes the current model and persists the choice to config. This is intended for CLI use where the selection should be saved.
func (*Agent) SetOutputMutex ¶
SetOutputMutex sets the output mutex for synchronized output
func (*Agent) SetPreviousSummary ¶
SetPreviousSummary sets the summary of previous actions for continuity
func (*Agent) SetProvider ¶
func (a *Agent) SetProvider(provider api.ClientType) error
SetProvider switches to a specific provider with its default or current model. Session-scoped: changes are not written to config. Use SetProviderPersisted when the user explicitly chose the provider (e.g. CLI /provider command).
func (*Agent) SetProviderPersisted ¶
func (a *Agent) SetProviderPersisted(provider api.ClientType) error
SetProviderPersisted switches to a specific provider and persists the choice to config. This is intended for CLI use where the selection should be saved. The test/mock provider is rejected since it should never be the persisted default.
func (*Agent) SetPruningSlidingWindowSize ¶
SetPruningSlidingWindowSize sets the sliding window size for the sliding window strategy
func (*Agent) SetPruningStrategy ¶
func (a *Agent) SetPruningStrategy(strategy PruningStrategy)
SetPruningStrategy sets the conversation pruning strategy
func (*Agent) SetPruningThreshold ¶
SetPruningThreshold sets the context usage threshold for triggering automatic pruning threshold should be between 0 and 1 (e.g., 0.7 = 70%)
func (*Agent) SetRecentMessagesToKeep ¶
SetRecentMessagesToKeep sets how many recent messages to always preserve
func (*Agent) SetRiskProfileOverride ¶
func (a *Agent) SetRiskProfileOverride(profile configuration.RiskProfile)
SetRiskProfileOverride installs a transient risk profile that overrides the config-level setting for the lifetime of this agent. Used by the --risk-profile CLI flag and per-step workflow overrides. Pass "" to clear.
func (*Agent) SetSessionID ¶
SetSessionID sets the session identifier for continuity
func (*Agent) SetSessionName ¶
SetSessionName explicitly sets a custom name for the current session
func (*Agent) SetShellCommandHistoryEntry ¶
func (a *Agent) SetShellCommandHistoryEntry(command string, result *ShellCommandResult)
SetShellCommandHistoryEntry stores a shell command result in history
func (*Agent) SetShellCwd ¶
SetShellCwd sets the logical shell working directory and records the previous.
func (*Agent) SetStatsUpdateCallback ¶
SetStatsUpdateCallback sets a callback for token/cost updates
func (*Agent) SetStreamingCallback ¶
SetStreamingCallback sets a custom callback for streaming output
func (*Agent) SetStreamingEnabled ¶
SetStreamingEnabled enables or disables streaming responses
func (*Agent) SetSystemPrompt ¶
SetSystemPrompt sets the system prompt for the agent
func (*Agent) SetSystemPromptFromFile ¶
SetSystemPromptFromFile loads a custom system prompt from a file
func (*Agent) SetTerminalManager ¶
func (a *Agent) SetTerminalManager(tm tools.TerminalAccess)
SetTerminalManager sets the terminal manager for WebUI mode. When set (non-nil), shell commands can access hidden PTY sessions. When nil (CLI mode), shell commands use os/exec unchanged.
func (*Agent) SetTraceSession ¶
func (a *Agent) SetTraceSession(traceSession interface{})
SetTraceSession sets the trace session for dataset collection
func (*Agent) SetUnsafeMode ¶
SetUnsafeMode sets the unsafe mode flag
func (*Agent) SetWorkspaceRoot ¶
SetWorkspaceRoot records the logical workspace root for this agent instance.
func (*Agent) ShowColoredDiff ¶
ShowColoredDiff displays a colored diff between old and new content, focusing on actual changes Uses Python's difflib for better diff quality when available, falls back to Go implementation
func (*Agent) ShowDropdown ¶
func (a *Agent) ShowDropdown(items interface{}, options DropdownOptions) (interface{}, error)
ShowDropdown shows a dropdown if UI is available
func (*Agent) ShowMyChange ¶
ShowMyChange returns a unified diff JSON envelope for `path`. After the SP-061-2 consolidation this is a thin wrapper around list_changes(include_diff=true, path_pattern=path) — the standalone show_my_change tool is gone.
func (*Agent) ShowQuickPrompt ¶
func (a *Agent) ShowQuickPrompt(prompt string, options []QuickOption, horizontal bool) (QuickOption, error)
ShowQuickPrompt shows a quick prompt if UI is available
func (*Agent) Shutdown ¶
func (a *Agent) Shutdown()
Shutdown attempts to gracefully stop background work and child processes (e.g., MCP servers), and releases resources. It is safe to call multiple times.
func (*Agent) SnapshotSessionAllowedFolders ¶
SnapshotSessionAllowedFolders returns a copy of the session allowlist. Used by SubagentRunner to seed a new subagent's allowlist from the parent (so previously approved folders remain usable inside delegated work).
func (*Agent) SubagentDepth ¶
SubagentDepth returns the nesting depth of this agent. 0 = primary agent (EA), 1 = orchestrator, 2 = coder/tester, etc.
func (*Agent) SummarizeMySession ¶
SummarizeMySession returns the activity-block digest. Thin wrapper around list_changes(group_by="block").
func (*Agent) ToolLog ¶
ToolLog formats and prints a tool call message immediately for user visibility. Routes through OutputRouter for single-sourced event+terminal output. Format: [4 - 30%] read file filename.go
func (*Agent) TrackFileEdit ¶
TrackFileEdit is called by the EditFile tool to track file edits
func (*Agent) TrackFileWrite ¶
TrackFileWrite is called by the WriteFile tool to track file writes
func (*Agent) TrackMetricsFromResponse ¶
func (a *Agent) TrackMetricsFromResponse(promptTokens, completionTokens, totalTokens int, estimatedCost float64, cachedTokens int)
TrackMetricsFromResponse updates agent metrics from API response usage data
func (*Agent) TriggerInterrupt ¶
func (a *Agent) TriggerInterrupt()
TriggerInterrupt manually triggers an interrupt for testing purposes
type AgentLogger ¶
type AgentLogger struct {
// contains filtered or unexported fields
}
AgentLogger wraps the agent and provides context-aware logging
func NewAgentLogger ¶
func NewAgentLogger(agent *Agent) *AgentLogger
NewAgentLogger creates a logger, using the agent's existing debug log file if available
func (*AgentLogger) Debug ¶
func (l *AgentLogger) Debug(format string, args ...interface{})
Debug writes a debug-level log with context
func (*AgentLogger) Error ¶
func (l *AgentLogger) Error(format string, args ...interface{})
Error writes an error-level log with context
func (*AgentLogger) Info ¶
func (l *AgentLogger) Info(format string, args ...interface{})
Info writes an info-level log with context
func (*AgentLogger) SetJSONMode ¶
func (l *AgentLogger) SetJSONMode(jsonMode bool)
SetJSONMode sets whether the logger outputs JSON or human-readable text
func (*AgentLogger) Warn ¶
func (l *AgentLogger) Warn(format string, args ...interface{})
Warn writes a warn-level log with context
func (*AgentLogger) WithFields ¶
func (l *AgentLogger) WithFields(fields map[string]string) *LogContext
WithFields returns a context that adds extra fields to all subsequent logs
type AgentMCPManager ¶
type AgentMCPManager struct {
// contains filtered or unexported fields
}
AgentMCPManager implements MCPSubManager.
func NewAgentMCPManager ¶
func NewAgentMCPManager() *AgentMCPManager
NewAgentMCPManager creates a new AgentMCPManager with default values.
func (*AgentMCPManager) GetInitError ¶
func (m *AgentMCPManager) GetInitError() error
func (*AgentMCPManager) GetManager ¶
func (m *AgentMCPManager) GetManager() mcp.MCPManager
func (*AgentMCPManager) GetToolsCache ¶
func (m *AgentMCPManager) GetToolsCache() []api.Tool
func (*AgentMCPManager) IsInitialized ¶
func (m *AgentMCPManager) IsInitialized() bool
func (*AgentMCPManager) LockInit ¶
func (m *AgentMCPManager) LockInit()
func (*AgentMCPManager) SetInitError ¶
func (m *AgentMCPManager) SetInitError(err error)
func (*AgentMCPManager) SetInitialized ¶
func (m *AgentMCPManager) SetInitialized(initialized bool)
func (*AgentMCPManager) SetManager ¶
func (m *AgentMCPManager) SetManager(mgr mcp.MCPManager)
func (*AgentMCPManager) SetToolsCache ¶
func (m *AgentMCPManager) SetToolsCache(tools []api.Tool)
func (*AgentMCPManager) UnlockInit ¶
func (m *AgentMCPManager) UnlockInit()
type AgentOutputManager ¶
type AgentOutputManager struct {
// contains filtered or unexported fields
}
AgentOutputManager implements OutputManager.
func NewAgentOutputManager ¶
func NewAgentOutputManager() *AgentOutputManager
NewAgentOutputManager creates a new AgentOutputManager with default values.
func (*AgentOutputManager) EnsureAsyncOutputWorker ¶
func (m *AgentOutputManager) EnsureAsyncOutputWorker(fn func())
func (*AgentOutputManager) GetAsyncBufferSize ¶
func (m *AgentOutputManager) GetAsyncBufferSize() int
func (*AgentOutputManager) GetAsyncOutput ¶
func (m *AgentOutputManager) GetAsyncOutput() chan string
func (*AgentOutputManager) GetEventMetadata ¶
func (m *AgentOutputManager) GetEventMetadata() map[string]interface{}
func (*AgentOutputManager) GetEventMetadataMutex ¶
func (m *AgentOutputManager) GetEventMetadataMutex() *sync.RWMutex
func (*AgentOutputManager) GetFlushCallback ¶
func (m *AgentOutputManager) GetFlushCallback() func()
func (*AgentOutputManager) GetOutputMutex ¶
func (m *AgentOutputManager) GetOutputMutex() *sync.Mutex
func (*AgentOutputManager) GetOutputRouter ¶
func (m *AgentOutputManager) GetOutputRouter() *OutputRouter
func (*AgentOutputManager) GetReasoningBuffer ¶
func (m *AgentOutputManager) GetReasoningBuffer() *strings.Builder
func (*AgentOutputManager) GetReasoningCallback ¶
func (m *AgentOutputManager) GetReasoningCallback() func(string)
func (*AgentOutputManager) GetStreamingBuffer ¶
func (m *AgentOutputManager) GetStreamingBuffer() *strings.Builder
func (*AgentOutputManager) GetStreamingCallback ¶
func (m *AgentOutputManager) GetStreamingCallback() func(string)
func (*AgentOutputManager) GetTerminalWriter ¶
func (m *AgentOutputManager) GetTerminalWriter() func(string)
func (*AgentOutputManager) IsStreamingEnabled ¶
func (m *AgentOutputManager) IsStreamingEnabled() bool
func (*AgentOutputManager) SetAsyncBufferSize ¶
func (m *AgentOutputManager) SetAsyncBufferSize(size int)
func (*AgentOutputManager) SetAsyncOutput ¶
func (m *AgentOutputManager) SetAsyncOutput(ch chan string)
func (*AgentOutputManager) SetEventMetadata ¶
func (m *AgentOutputManager) SetEventMetadata(meta map[string]interface{})
func (*AgentOutputManager) SetEventMetadataUnlocked ¶
func (m *AgentOutputManager) SetEventMetadataUnlocked(meta map[string]interface{})
SetEventMetadataUnlocked sets metadata without acquiring the mutex. Caller must hold m.eventMetadataMu.
func (*AgentOutputManager) SetFlushCallback ¶
func (m *AgentOutputManager) SetFlushCallback(cb func())
func (*AgentOutputManager) SetOutputMutex ¶
func (m *AgentOutputManager) SetOutputMutex(mu *sync.Mutex)
func (*AgentOutputManager) SetOutputRouter ¶
func (m *AgentOutputManager) SetOutputRouter(router *OutputRouter)
func (*AgentOutputManager) SetReasoningCallback ¶
func (m *AgentOutputManager) SetReasoningCallback(cb func(string))
func (*AgentOutputManager) SetStreamingCallback ¶
func (m *AgentOutputManager) SetStreamingCallback(cb func(string))
func (*AgentOutputManager) SetStreamingEnabled ¶
func (m *AgentOutputManager) SetStreamingEnabled(enabled bool)
func (*AgentOutputManager) SetTerminalWriter ¶
func (m *AgentOutputManager) SetTerminalWriter(fn func(string))
type AgentSecurityManager ¶
type AgentSecurityManager struct {
// contains filtered or unexported fields
}
AgentSecurityManager implements SecurityManager, holding all security-related state previously managed directly by the Agent struct.
func NewAgentSecurityManager ¶
func NewAgentSecurityManager() *AgentSecurityManager
NewAgentSecurityManager creates a new AgentSecurityManager with all fields initialized.
func (*AgentSecurityManager) AddSessionAllowedFolder ¶
func (m *AgentSecurityManager) AddSessionAllowedFolder(folder string)
func (*AgentSecurityManager) GetAskUserMgr ¶
func (m *AgentSecurityManager) GetAskUserMgr() *agenttools.AskUserManager
func (*AgentSecurityManager) GetElevationGate ¶
func (m *AgentSecurityManager) GetElevationGate() *security.ElevationGate
func (*AgentSecurityManager) GetOutputRedactor ¶
func (m *AgentSecurityManager) GetOutputRedactor() *security.OutputRedactor
func (*AgentSecurityManager) GetSecurityApprovalMgr ¶
func (m *AgentSecurityManager) GetSecurityApprovalMgr() *security.ApprovalManager
func (*AgentSecurityManager) GetUnsafeMode ¶
func (m *AgentSecurityManager) GetUnsafeMode() bool
func (*AgentSecurityManager) HasActiveWebUIClients ¶
func (m *AgentSecurityManager) HasActiveWebUIClients() bool
func (*AgentSecurityManager) IsConcernIgnored ¶
func (m *AgentSecurityManager) IsConcernIgnored(filePath, concern string) bool
func (*AgentSecurityManager) IsFolderSessionAllowed ¶
func (m *AgentSecurityManager) IsFolderSessionAllowed(absPath string) bool
func (*AgentSecurityManager) IsSecurityBypassApproved ¶
func (m *AgentSecurityManager) IsSecurityBypassApproved() bool
func (*AgentSecurityManager) SetApprovalMgr ¶
func (m *AgentSecurityManager) SetApprovalMgr(mgr *security.ApprovalManager)
func (*AgentSecurityManager) SetAskUserMgr ¶
func (m *AgentSecurityManager) SetAskUserMgr(mgr *agenttools.AskUserManager)
func (*AgentSecurityManager) SetConcernIgnored ¶
func (m *AgentSecurityManager) SetConcernIgnored(filePath, concern string)
func (*AgentSecurityManager) SetElevationGate ¶
func (m *AgentSecurityManager) SetElevationGate(gate *security.ElevationGate)
func (*AgentSecurityManager) SetHasActiveWebUIClients ¶
func (m *AgentSecurityManager) SetHasActiveWebUIClients(fn func() bool)
func (*AgentSecurityManager) SetUnsafeMode ¶
func (m *AgentSecurityManager) SetUnsafeMode(unsafe bool)
func (*AgentSecurityManager) SnapshotSessionAllowedFolders ¶
func (m *AgentSecurityManager) SnapshotSessionAllowedFolders() []string
type AgentState ¶
type AgentState struct {
Messages []api.Message `json:"messages"`
TurnCheckpoints []TurnCheckpoint `json:"turn_checkpoints,omitempty"`
PreviousSummary string `json:"previous_summary"`
CompactSummary string `json:"compact_summary"` // New: 5K limit summary for continuity
TaskActions []TaskAction `json:"task_actions"`
SessionID string `json:"session_id"`
// Token and cost metrics
TotalTokens int `json:"total_tokens"`
TotalCost float64 `json:"total_cost"`
PromptTokens int `json:"prompt_tokens"`
CompletionTokens int `json:"completion_tokens"`
EstimatedTokenResponses int `json:"estimated_token_responses"`
CachedTokens int `json:"cached_tokens"`
CachedCostSavings float64 `json:"cached_cost_savings"`
}
AgentState represents the state of an agent that can be persisted
type AgentStateManager ¶
type AgentStateManager struct {
// contains filtered or unexported fields
}
AgentStateManager implements StateManager with simple field-backed getters/setters.
func NewAgentStateManager ¶
func NewAgentStateManager(debug bool) *AgentStateManager
NewAgentStateManager creates a new AgentStateManager with sensible defaults.
func (*AgentStateManager) AddCost ¶
func (s *AgentStateManager) AddCost(c float64)
func (*AgentStateManager) AddMessage ¶
func (s *AgentStateManager) AddMessage(msg api.Message)
func (*AgentStateManager) AddTaskAction ¶
func (s *AgentStateManager) AddTaskAction(action TaskAction)
func (*AgentStateManager) AddTurnCheckpoint ¶
func (s *AgentStateManager) AddTurnCheckpoint(cp TurnCheckpoint)
func (*AgentStateManager) GetActivePersona ¶
func (s *AgentStateManager) GetActivePersona() string
func (*AgentStateManager) GetActiveSkills ¶
func (s *AgentStateManager) GetActiveSkills() []string
func (*AgentStateManager) GetCachedCostSavings ¶
func (s *AgentStateManager) GetCachedCostSavings() float64
func (*AgentStateManager) GetCachedTokens ¶
func (s *AgentStateManager) GetCachedTokens() int
func (*AgentStateManager) GetCheckpointMutex ¶
func (s *AgentStateManager) GetCheckpointMutex() *sync.RWMutex
func (*AgentStateManager) GetCircuitBreaker ¶
func (s *AgentStateManager) GetCircuitBreaker() *CircuitBreakerState
func (*AgentStateManager) GetCommandHistory ¶
func (s *AgentStateManager) GetCommandHistory() []string
func (*AgentStateManager) GetCompletionTokens ¶
func (s *AgentStateManager) GetCompletionTokens() int
func (*AgentStateManager) GetConfigOverrides ¶
func (s *AgentStateManager) GetConfigOverrides() map[string]interface{}
func (*AgentStateManager) GetConversationPruner ¶
func (s *AgentStateManager) GetConversationPruner() *ConversationPruner
func (*AgentStateManager) GetCurrentContextTokens ¶
func (s *AgentStateManager) GetCurrentContextTokens() int
func (*AgentStateManager) GetCurrentIteration ¶
func (s *AgentStateManager) GetCurrentIteration() int
func (*AgentStateManager) GetEstimatedTokenResponses ¶
func (s *AgentStateManager) GetEstimatedTokenResponses() int
func (*AgentStateManager) GetHistoryIndex ¶
func (s *AgentStateManager) GetHistoryIndex() int
func (*AgentStateManager) GetHistoryMutex ¶
func (s *AgentStateManager) GetHistoryMutex() *sync.Mutex
func (*AgentStateManager) GetLLMCallCount ¶
func (s *AgentStateManager) GetLLMCallCount() int
func (*AgentStateManager) GetLastProviderError ¶
func (s *AgentStateManager) GetLastProviderError() *ProviderErrorInfo
GetLastProviderError returns the last provider error info
func (*AgentStateManager) GetLastRunTerminationReason ¶
func (s *AgentStateManager) GetLastRunTerminationReason() string
func (*AgentStateManager) GetMaxContextTokens ¶
func (s *AgentStateManager) GetMaxContextTokens() int
func (*AgentStateManager) GetMessages ¶
func (s *AgentStateManager) GetMessages() []api.Message
func (*AgentStateManager) GetOptimizer ¶
func (s *AgentStateManager) GetOptimizer() *ConversationOptimizer
func (*AgentStateManager) GetPauseMutex ¶
func (s *AgentStateManager) GetPauseMutex() *sync.Mutex
func (*AgentStateManager) GetPauseState ¶
func (s *AgentStateManager) GetPauseState() *PauseState
func (*AgentStateManager) GetPendingStrictSwitchNotice ¶
func (s *AgentStateManager) GetPendingStrictSwitchNotice() string
func (*AgentStateManager) GetPendingSwitchContextRefresh ¶
func (s *AgentStateManager) GetPendingSwitchContextRefresh() string
func (*AgentStateManager) GetPendingSystemSupplement ¶
func (s *AgentStateManager) GetPendingSystemSupplement() string
func (*AgentStateManager) GetPreviousSummary ¶
func (s *AgentStateManager) GetPreviousSummary() string
func (*AgentStateManager) GetPromptTokens ¶
func (s *AgentStateManager) GetPromptTokens() int
func (*AgentStateManager) GetSessionID ¶
func (s *AgentStateManager) GetSessionID() string
func (*AgentStateManager) GetSessionIntentEmbedding ¶
func (s *AgentStateManager) GetSessionIntentEmbedding() []float32
func (*AgentStateManager) GetSessionModel ¶
func (s *AgentStateManager) GetSessionModel() string
func (*AgentStateManager) GetSessionProvider ¶
func (s *AgentStateManager) GetSessionProvider() api.ClientType
func (*AgentStateManager) GetTaskActions ¶
func (s *AgentStateManager) GetTaskActions() []TaskAction
func (*AgentStateManager) GetTaskActionsMutex ¶
func (s *AgentStateManager) GetTaskActionsMutex() *sync.RWMutex
func (*AgentStateManager) GetTotalCost ¶
func (s *AgentStateManager) GetTotalCost() float64
func (*AgentStateManager) GetTotalTokens ¶
func (s *AgentStateManager) GetTotalTokens() int
func (*AgentStateManager) GetTotalToolCalls ¶
func (s *AgentStateManager) GetTotalToolCalls() int
func (*AgentStateManager) GetTraceSession ¶
func (s *AgentStateManager) GetTraceSession() interface{}
func (*AgentStateManager) GetTurnCheckpoints ¶
func (s *AgentStateManager) GetTurnCheckpoints() []TurnCheckpoint
func (*AgentStateManager) IncrementLLMCallCount ¶
func (s *AgentStateManager) IncrementLLMCallCount()
func (*AgentStateManager) IncrementTotalToolCalls ¶
func (s *AgentStateManager) IncrementTotalToolCalls()
func (*AgentStateManager) IsContextWarningIssued ¶
func (s *AgentStateManager) IsContextWarningIssued() bool
func (*AgentStateManager) IsFalseStopDetectionEnabled ¶
func (s *AgentStateManager) IsFalseStopDetectionEnabled() bool
func (*AgentStateManager) IsToolCallGuidanceAdded ¶
func (s *AgentStateManager) IsToolCallGuidanceAdded() bool
func (*AgentStateManager) SetActivePersona ¶
func (s *AgentStateManager) SetActivePersona(p string)
func (*AgentStateManager) SetActiveSkills ¶
func (s *AgentStateManager) SetActiveSkills(skills []string)
func (*AgentStateManager) SetCachedCostSavings ¶
func (s *AgentStateManager) SetCachedCostSavings(c float64)
func (*AgentStateManager) SetCachedTokens ¶
func (s *AgentStateManager) SetCachedTokens(n int)
func (*AgentStateManager) SetCircuitBreaker ¶
func (s *AgentStateManager) SetCircuitBreaker(cb *CircuitBreakerState)
func (*AgentStateManager) SetCommandHistory ¶
func (s *AgentStateManager) SetCommandHistory(h []string)
func (*AgentStateManager) SetCompletionTokens ¶
func (s *AgentStateManager) SetCompletionTokens(n int)
func (*AgentStateManager) SetConfigOverrides ¶
func (s *AgentStateManager) SetConfigOverrides(overrides map[string]interface{})
func (*AgentStateManager) SetContextWarningIssued ¶
func (s *AgentStateManager) SetContextWarningIssued(v bool)
func (*AgentStateManager) SetConversationPruner ¶
func (s *AgentStateManager) SetConversationPruner(pruner *ConversationPruner)
func (*AgentStateManager) SetCurrentContextTokens ¶
func (s *AgentStateManager) SetCurrentContextTokens(n int)
func (*AgentStateManager) SetCurrentIteration ¶
func (s *AgentStateManager) SetCurrentIteration(iter int)
func (*AgentStateManager) SetEstimatedTokenResponses ¶
func (s *AgentStateManager) SetEstimatedTokenResponses(n int)
func (*AgentStateManager) SetFalseStopDetectionEnabled ¶
func (s *AgentStateManager) SetFalseStopDetectionEnabled(v bool)
func (*AgentStateManager) SetHistoryIndex ¶
func (s *AgentStateManager) SetHistoryIndex(i int)
func (*AgentStateManager) SetLLMCallCount ¶
func (s *AgentStateManager) SetLLMCallCount(n int)
func (*AgentStateManager) SetLastProviderError ¶
func (s *AgentStateManager) SetLastProviderError(err *ProviderErrorInfo)
SetLastProviderError sets the last provider error info
func (*AgentStateManager) SetLastRunTerminationReason ¶
func (s *AgentStateManager) SetLastRunTerminationReason(reason string)
func (*AgentStateManager) SetMaxContextTokens ¶
func (s *AgentStateManager) SetMaxContextTokens(n int)
func (*AgentStateManager) SetMessages ¶
func (s *AgentStateManager) SetMessages(msgs []api.Message)
func (*AgentStateManager) SetOptimizer ¶
func (s *AgentStateManager) SetOptimizer(o *ConversationOptimizer)
func (*AgentStateManager) SetPauseState ¶
func (s *AgentStateManager) SetPauseState(ps *PauseState)
func (*AgentStateManager) SetPendingStrictSwitchNotice ¶
func (s *AgentStateManager) SetPendingStrictSwitchNotice(v string)
func (*AgentStateManager) SetPendingSwitchContextRefresh ¶
func (s *AgentStateManager) SetPendingSwitchContextRefresh(v string)
func (*AgentStateManager) SetPendingSystemSupplement ¶
func (s *AgentStateManager) SetPendingSystemSupplement(v string)
func (*AgentStateManager) SetPreviousSummary ¶
func (s *AgentStateManager) SetPreviousSummary(summary string)
func (*AgentStateManager) SetPromptTokens ¶
func (s *AgentStateManager) SetPromptTokens(n int)
func (*AgentStateManager) SetSessionID ¶
func (s *AgentStateManager) SetSessionID(id string)
func (*AgentStateManager) SetSessionIntentEmbedding ¶
func (s *AgentStateManager) SetSessionIntentEmbedding(emb []float32)
func (*AgentStateManager) SetSessionIntentEmbeddingIfNil ¶
func (s *AgentStateManager) SetSessionIntentEmbeddingIfNil(emb []float32) bool
func (*AgentStateManager) SetSessionModel ¶
func (s *AgentStateManager) SetSessionModel(m string)
func (*AgentStateManager) SetSessionProvider ¶
func (s *AgentStateManager) SetSessionProvider(ct api.ClientType)
func (*AgentStateManager) SetTaskActions ¶
func (s *AgentStateManager) SetTaskActions(actions []TaskAction)
func (*AgentStateManager) SetToolCallGuidanceAdded ¶
func (s *AgentStateManager) SetToolCallGuidanceAdded(v bool)
func (*AgentStateManager) SetTotalCost ¶
func (s *AgentStateManager) SetTotalCost(c float64)
func (*AgentStateManager) SetTotalTokens ¶
func (s *AgentStateManager) SetTotalTokens(n int)
func (*AgentStateManager) SetTotalToolCalls ¶
func (s *AgentStateManager) SetTotalToolCalls(n int)
func (*AgentStateManager) SetTraceSession ¶
func (s *AgentStateManager) SetTraceSession(ts interface{})
func (*AgentStateManager) SetTurnCheckpoints ¶
func (s *AgentStateManager) SetTurnCheckpoints(cps []TurnCheckpoint)
type ChangeTracker ¶
type ChangeTracker struct {
// contains filtered or unexported fields
}
ChangeTracker manages change tracking for the agent workflow
func NewChangeTracker ¶
func NewChangeTracker(agent *Agent, instructions string) *ChangeTracker
NewChangeTracker creates a new change tracker for an agent session
func (*ChangeTracker) Clear ¶
func (ct *ChangeTracker) Clear()
Clear clears all tracked changes (but keeps the tracker enabled). Also resets the shell-snapshot cache so a subsequent EnableChangeTracking / PrimeShellTracking call re-baselines against current disk state — otherwise a stale cache would attribute post-Clear shell mutations to "the workspace as it looked at session start", which is wrong after a Reset. The autoSkipDirs adaptive set is preserved across Clear (it's an optimization, not state about the user's changes); a Reset that wants to re-learn from scratch can null it manually.
func (*ChangeTracker) CollectFileChangesForCheckpoint ¶
func (ct *ChangeTracker) CollectFileChangesForCheckpoint() ([]CheckpointFileChange, string)
CollectFileChangesForCheckpoint returns the (path, op) manifest of changes appended since the most recent checkpoint capture, along with the current revision ID. Advances the internal watermark so a subsequent call returns only the next turn's changes. Safe to call when tracking is disabled — returns (nil, "") in that case.
Ops are git-style: "A" (added/created), "M" (modified), "D" (deleted), "R" (renamed). The ChangeTracker today only records create/write/edit — never delete or rename — so the manifest produced here will only contain A and M entries. When the tracker grows D/R support, extend the mapping table below.
Multiple writes to the same path within the same turn collapse to one entry, preferring "A" over "M" (a turn that creates then modifies the same file is recorded as A).
func (*ChangeTracker) Commit ¶
func (ct *ChangeTracker) Commit(llmResponse string, conversation []api.Message) error
Commit commits all tracked changes to the change tracker
func (*ChangeTracker) GenerateAISummary ¶
func (ct *ChangeTracker) GenerateAISummary() (string, error)
GenerateAISummary creates an AI-generated summary of the changes
func (*ChangeTracker) GetChangeCount ¶
func (ct *ChangeTracker) GetChangeCount() int
GetChangeCount returns the number of tracked changes
func (*ChangeTracker) GetChanges ¶
func (ct *ChangeTracker) GetChanges() []TrackedFileChange
GetChanges returns a copy of the tracked changes
func (*ChangeTracker) GetRevisionID ¶
func (ct *ChangeTracker) GetRevisionID() string
GetRevisionID returns the current revision ID
func (*ChangeTracker) GetSummary ¶
func (ct *ChangeTracker) GetSummary() string
GetSummary returns a summary of tracked changes
func (*ChangeTracker) GetTrackedFiles ¶
func (ct *ChangeTracker) GetTrackedFiles() []string
GetTrackedFiles returns a list of files that have been modified
func (*ChangeTracker) IsEnabled ¶
func (ct *ChangeTracker) IsEnabled() bool
IsEnabled returns whether change tracking is enabled
func (*ChangeTracker) PrimeShellTracking ¶
func (ct *ChangeTracker) PrimeShellTracking(workDir string)
PrimeShellTracking captures the workspace's current state as the baseline against which future shell_command invocations are diffed. Idempotent: a second call against the already-primed tracker is a no-op. Safe to call multiple times — only the first does work.
Lazy callers can skip this and rely on TrackShellTurn to auto-prime on first invocation; in that mode the first shell_command's own pre-state is captured but no changes are recorded for it (the initial walk IS the baseline). When the first shell command's mutations need to be tracked, PrimeShellTracking should be called from EnableChangeTracking so the baseline pre-exists.
func (*ChangeTracker) RecordShellMutations ¶
func (ct *ChangeTracker) RecordShellMutations(before, after map[string]*shellSnapshotEntry, toolCall string)
RecordShellMutations diffs a pair of snapshots (taken before/after a shell_command invocation) and appends TrackedFileChange entries for every file that materially changed. The before-snapshot supplies the OriginalCode field so a user can recover untracked-by-git files the agent accidentally deleted or mangled.
Dedup: if the path was already recorded this turn via TrackFileWrite / TrackFileEdit (the direct tool hooks), the existing entry is kept and we don't double-record from the shell diff. The direct entry is richer (original_code captured at the source) so it wins.
SP-061-1: when a single shell command churns more than shellBulkThreshold paths AND some top-level workspace directory owns at least shellBulkPerDirMin of them, that directory is rolled up into a single "bulk" entry and added to autoSkipDirs so future walks skip it entirely. The rollup carries BulkCount so the UI can render "dist/ — 1,247 files (build output)" instead of stacking thousands of individual rows.
func (*ChangeTracker) Reset ¶
func (ct *ChangeTracker) Reset(instructions string)
Reset resets the change tracker with a new revision ID and instructions
func (*ChangeTracker) SyncShellCacheForPath ¶
func (ct *ChangeTracker) SyncShellCacheForPath(path string)
SyncShellCacheForPath refreshes the shell cache entry for one path against its current on-disk state. Called by the direct file-write hooks (TrackFileWrite, TrackFileEdit) so the cache reflects writes the agent just performed via structured-file tools — without this, the next TrackShellTurn walk would see the new content as a stat mismatch against stale cache and record a duplicate "edit" entry even though no shell command touched the file.
Safe to call when the cache hasn't been primed yet (no-op) — there's no baseline to keep in sync.
func (*ChangeTracker) TrackFileEdit ¶
func (ct *ChangeTracker) TrackFileEdit(filePath string, originalContent string, newContent string) error
TrackFileEdit tracks an edit operation (EditFile tool)
func (*ChangeTracker) TrackFileWrite ¶
func (ct *ChangeTracker) TrackFileWrite(filePath string, newContent string) error
TrackFileWrite tracks a write operation (WriteFile tool)
func (*ChangeTracker) TrackShellTurn ¶
func (ct *ChangeTracker) TrackShellTurn(workDir, toolCall string, destructive bool)
TrackShellTurn diffs the workspace against the primed baseline, appends every detected mutation to the change tracker (with dedup against direct-hook entries that fired during the same window), then rebases the baseline to the new state.
If the cache hasn't been primed yet this call auto-primes — the pre-shell state is captured but no changes are recorded the first time (we have no baseline to compare against). To track the very first shell command's mutations, call PrimeShellTracking once at agent session start before the first shell_command runs.
Honors the per-tracker shellWalkEnabled knob — when disabled the call is a no-op so users with weird workspaces can keep direct-tool tracking without paying the walker's cost.
`destructive` should be set when the shell command can clobber active changes (`git checkout .`, `git reset --hard`, …). It flips the walk into the safer mode that bypasses autoSkipDirs and emits per-file rather than rolling up — see shell_destructive.go for the classifier and walkWorkspace for the behaviour switch.
Concurrency: serialized via the tracker's internal mutex. Subagents each have their own ChangeTracker so cross-subagent calls don't interfere.
type CheckpointFileChange ¶
CheckpointFileChange is a single file-change entry in a TurnCheckpoint's manifest. Op is one of "A" (added), "M" (modified), "D" (deleted), "R" (renamed) to mirror git's status codes; anything else is "?" (other).
type ChoiceOption ¶
ChoiceOption represents a simple label/value option for UI prompts
type CircuitBreakerAction ¶
type CircuitBreakerAction struct {
ActionType string // "edit_file", "shell_command", etc.
Target string // file path, command, etc.
Count int // number of times this action was performed
LastUsed int64 // unix timestamp of last use
}
CircuitBreakerAction tracks repetitive actions for circuit breaker logic
type CircuitBreakerState ¶
type CircuitBreakerState struct {
Actions map[string]*CircuitBreakerAction // key: actionType:target
// contains filtered or unexported fields
}
CircuitBreakerState tracks repetitive actions across the session.
Locking Strategy:
- The Actions map is protected by mu (sync.RWMutex)
- Use RLock/RLock for read-only access when you don't need exclusive access
- Use Lock for write operations or when you need exclusive access
- Always use defer to unlock (defer mu.Unlock() or defer mu.RUnlock())
- Helper functions ending with "Locked" must be called while holding the lock (they perform no locking themselves, allowing callers to hold lock for multiple ops)
Example patterns:
// Read-only access:
cb.mu.RLock()
defer cb.mu.RUnlock()
action := cb.Actions[key]
// Write access:
cb.mu.Lock()
defer cb.mu.Unlock()
cb.Actions[key] = &CircuitBreakerAction{...}
type ClarificationManager ¶
type ClarificationManager struct {
// contains filtered or unexported fields
}
ClarificationManager manages pending clarification requests between delegate and parent agents. It provides thread-safe tracking of clarification requests and responses via channels.
func NewClarificationManager ¶
func NewClarificationManager(eventBus *events.EventBus) *ClarificationManager
NewClarificationManager creates a manager with default 60s timeout.
func NewClarificationManagerWithTimeout ¶
func NewClarificationManagerWithTimeout(eventBus *events.EventBus, timeout time.Duration) *ClarificationManager
NewClarificationManagerWithTimeout creates a manager with a custom timeout.
func (*ClarificationManager) Cleanup ¶
func (m *ClarificationManager) Cleanup()
Cleanup removes expired entries.
func (*ClarificationManager) Close ¶
func (m *ClarificationManager) Close()
Close stops the background cleanup goroutine.
func (*ClarificationManager) GetPendingClarifications ¶
func (m *ClarificationManager) GetPendingClarifications(delegateID string) []ClarificationRequest
GetPendingClarifications returns all pending clarification requests for a delegate.
func (*ClarificationManager) RequestClarification ¶
func (m *ClarificationManager) RequestClarification(ctx context.Context, delegateID, question string) (string, error)
RequestClarification creates a clarification request, publishes an event, and blocks until a response arrives or timeout.
func (*ClarificationManager) RespondClarification ¶
func (m *ClarificationManager) RespondClarification(requestID, response string) error
RespondClarification finds a pending request and sends a response to it.
type ClarificationRequest ¶
type ClarificationRequest struct {
RequestID string `json:"request_id"`
DelegateID string `json:"delegate_id"`
Question string `json:"question"`
CreatedAt time.Time `json:"created_at"`
}
ClarificationRequest is the exported representation of a pending clarification request.
type ContextFileInfo ¶
ContextFileInfo represents information about a discovered context file
func DiscoverContextFiles ¶
func DiscoverContextFiles() (*ContextFileInfo, error)
DiscoverContextFiles looks for context files in the current directory and parent directories Returns the first matching file based on priority order
type ConversationOptimizer ¶
type ConversationOptimizer struct {
// contains filtered or unexported fields
}
ConversationOptimizer is sprout's thin wrapper around seed's core.ConversationOptimizer. The dedup + observation-masking implementation moved into seed so other consumers benefit; this wrapper preserves sprout's historical method surface (InvalidateFile, GetOptimizationStats, SetLLMClient) for callers that haven't migrated.
The LLM-based structural compaction that used to live here is now wired through seed's chat loop via Options.LLMSummarizer — see newLLMSummarizer in llm_summarizer.go and the construction site in seed_integration.go. SetLLMClient is consequently a no-op here.
func NewConversationOptimizer ¶
func NewConversationOptimizer(enabled, debug bool) *ConversationOptimizer
NewConversationOptimizer constructs the wrapper. The debug flag is kept for backward-compatible call sites but is unused now that seed's optimizer emits via the EventPublisher instead.
func (*ConversationOptimizer) CompactConversation ¶
func (co *ConversationOptimizer) CompactConversation(messages []api.Message) []api.Message
CompactConversation is retained for backward compatibility with callers that haven't migrated. Structural compaction now runs inside seed's chat loop via core.CompactWithLLMSummary, configured at seed-Agent construction. Calling this here is a no-op; the live request path no longer routes through this method.
func (*ConversationOptimizer) GetOptimizationStats ¶
func (co *ConversationOptimizer) GetOptimizationStats() map[string]interface{}
GetOptimizationStats returns a small status map. The per-file and per-command tracking counts are no longer maintained (seed scans fresh each call); the map shape stays so UI consumers continue to work.
func (*ConversationOptimizer) Inner ¶
func (co *ConversationOptimizer) Inner() *core.ConversationOptimizer
Inner exposes the wrapped seed optimizer for direct use when constructing seed-Agent options (see seed_integration.go).
func (*ConversationOptimizer) InvalidateFile ¶
func (co *ConversationOptimizer) InvalidateFile(filePath string)
InvalidateFile was used by sprout's per-file dedup cache. Seed's optimizer is stateless across calls (it scans the message list fresh each time), so there is no cache to invalidate. Kept as a no-op for caller compatibility.
func (*ConversationOptimizer) IsEnabled ¶
func (co *ConversationOptimizer) IsEnabled() bool
IsEnabled reports whether the optimizer was constructed enabled.
func (*ConversationOptimizer) OptimizeConversation ¶
func (co *ConversationOptimizer) OptimizeConversation(messages []api.Message) []api.Message
OptimizeConversation delegates to the seed optimizer. Returns the input unchanged when the optimizer is disabled.
func (*ConversationOptimizer) Reset ¶
func (co *ConversationOptimizer) Reset()
Reset clears optimizer state. Seed's optimizer is stateless across calls so this is a no-op; preserved for caller compatibility.
func (*ConversationOptimizer) SetEnabled ¶
func (co *ConversationOptimizer) SetEnabled(enabled bool)
SetEnabled toggles the optimizer at runtime. Since seed's optimizer captures Enabled at construction, this rebuilds the inner instance.
func (*ConversationOptimizer) SetLLMClient ¶
func (co *ConversationOptimizer) SetLLMClient(client api.ClientInterface, provider string, printLine func(string))
SetLLMClient is now a no-op. The LLM summary path is wired via seed Options.LLMSummarizer at seed-Agent construction (seed_integration.go).
type ConversationPruner ¶
type ConversationPruner = core.ConversationPruner
ConversationPruner is aliased to seed's core.ConversationPruner so sprout's existing callers (submanager_state.go, pruning_config.go, tests) continue to compile against the same type while the implementation lives in seed and is available to other consumers.
type ConversationState ¶
type ConversationState struct {
Messages []api.Message `json:"messages"`
TurnCheckpoints []TurnCheckpoint `json:"turn_checkpoints,omitempty"`
TaskActions []TaskAction `json:"task_actions"`
TotalCost float64 `json:"total_cost"`
TotalTokens int `json:"total_tokens"`
PromptTokens int `json:"prompt_tokens"`
CompletionTokens int `json:"completion_tokens"`
EstimatedTokenResponses int `json:"estimated_token_responses"`
CachedTokens int `json:"cached_tokens"`
CachedCostSavings float64 `json:"cached_cost_savings"`
LastUpdated time.Time `json:"last_updated"`
SessionID string `json:"session_id"`
Name string `json:"name"` // Human-readable session name
WorkingDirectory string `json:"working_directory"` // Directory where session was created
// ConfigOverrides stores session-scoped configuration overrides.
// Applied on top of global and workspace config when the session is restored.
// Only non-empty values are considered overrides.
ConfigOverrides map[string]interface{} `json:"config_overrides,omitempty"`
// SessionIntentEmbedding stores the embedding of the first user prompt in a session.
// Used for drift detection to track conversation intent over time.
SessionIntentEmbedding []float32 `json:"session_intent_embedding,omitempty"`
// LastProviderError captures details about the last API error from the LLM provider.
// Persisted in the session file so errors can be diagnosed after the fact.
LastProviderError *ProviderErrorInfo `json:"last_provider_error,omitempty"`
}
ConversationState represents the state of a conversation that can be persisted
func ImportStateFromJSONFile ¶
func ImportStateFromJSONFile(filename string) (*ConversationState, error)
ImportStateFromJSONFile loads a ConversationState from a JSON file
func LoadSessionInfo ¶
func LoadSessionInfo(sessionID string) (*ConversationState, error)
LoadSessionInfo loads session information including timestamp
func LoadStateWithoutAgent ¶
func LoadStateWithoutAgent(sessionID string) (*ConversationState, error)
LoadStateWithoutAgent loads a conversation state by session ID without an Agent instance
func LoadStateWithoutAgentScoped ¶
func LoadStateWithoutAgentScoped(sessionID, workingDir string) (*ConversationState, error)
LoadStateWithoutAgentScoped loads a state for a specific working directory scope.
type ConversationTurn ¶
type ConversationTurn struct {
ID string `json:"id"`
SessionID string `json:"session_id"`
TurnNumber int `json:"turn_number"`
Timestamp time.Time `json:"timestamp"`
UserPrompt string `json:"user_prompt"`
ActionableSummary string `json:"actionable_summary,omitempty"`
PromptEmbedding []float32 `json:"prompt_embedding,omitempty"`
FilesTouched []string `json:"files_touched,omitempty"`
WorkingDir string `json:"working_dir"`
Duration float64 `json:"duration"` // seconds from prompt to turn completion
TokenUsage int `json:"token_usage"` // total tokens in this turn
}
ConversationTurn represents a completed conversation turn stored for persistent context retrieval and semantic search across sessions.
func NewConversationTurn ¶
func NewConversationTurn(sessionID string, turnNumber int, userPrompt, workingDir string) (*ConversationTurn, error)
NewConversationTurn creates a new ConversationTurn with a generated ID and current timestamp. Returns an error if ID generation fails.
func (*ConversationTurn) String ¶
func (t *ConversationTurn) String() string
String returns a human-readable representation of the turn, omitting the embedding vector for readability.
func (*ConversationTurn) ToVectorRecord ¶
func (t *ConversationTurn) ToVectorRecord() embedding.VectorRecord
ToVectorRecord converts a ConversationTurn into a VectorRecord for storage in the conversation embedding store. The prompt text is truncated to maxSignatureLen characters for the Signature field. All turn metadata (summary, files, working dir, duration, tokens) is preserved in the Metadata map so no information is lost.
type DiffChange ¶
DiffChange represents a change region in the diff
type DriftDetector ¶
type DriftDetector struct {
// contains filtered or unexported fields
}
DriftDetector tracks conversational drift by comparing the current turn's embedding against the session's original intent embedding.
func NewDriftDetector ¶
func NewDriftDetector(threshold float64, checkInterval int) *DriftDetector
NewDriftDetector creates a new DriftDetector with the given threshold and check interval. Zero values are replaced with sensible defaults.
func (*DriftDetector) CheckDrift ¶
func (d *DriftDetector) CheckDrift(sessionIntent []float32, currentEmbedding []float32) (isDrift bool, similarity float64)
CheckDrift computes the cosine similarity between the session's original intent embedding and the current turn's embedding. Returns true if the similarity is below the threshold, indicating drift.
If sessionIntent is nil or empty, returns false, 0 as a graceful no-op.
func (*DriftDetector) DriftCount ¶
func (d *DriftDetector) DriftCount() int
DriftCount returns the number of drift detections in this session.
func (*DriftDetector) IsSuppressed ¶
func (d *DriftDetector) IsSuppressed() bool
IsSuppressed returns true if drift detection has been suppressed for this session due to too many rejections.
func (*DriftDetector) RecordAcceptance ¶
func (d *DriftDetector) RecordAcceptance()
RecordAcceptance resets the consecutive rejection counter. Called when the user chooses "Continue here" (accepts) in response to a drift notification.
func (*DriftDetector) RecordDrift ¶
func (d *DriftDetector) RecordDrift()
RecordDrift increments the drift detection counter for this session.
func (*DriftDetector) RecordRejection ¶
func (d *DriftDetector) RecordRejection()
RecordRejection increments the consecutive rejection counter and suppresses drift detection if the user has rejected MaxDriftRejections times in a row.
func (*DriftDetector) RejectionCount ¶
func (d *DriftDetector) RejectionCount() int
RejectionCount returns the number of consecutive drift rejections. This counter is reset to 0 when RecordAcceptance is called.
func (*DriftDetector) ShouldCheck ¶
func (d *DriftDetector) ShouldCheck(turnNumber int) bool
ShouldCheck returns true if drift should be checked on the given turn number. Checks occur every checkInterval turns (turn 5, 10, 15, ...). Returns false if the detector is suppressed.
type DriftNotification ¶
type DriftNotification struct {
// contains filtered or unexported fields
}
DriftNotification handles emitting drift notifications through the event bus. The notification is non-blocking — the agent continues processing after emission.
func NewDriftNotification ¶
func NewDriftNotification(detector *DriftDetector, eventBus *events.EventBus, sessionID string) *DriftNotification
NewDriftNotification creates a new drift notification handler.
func (*DriftNotification) NotifyDrift ¶
func (n *DriftNotification) NotifyDrift(similarity float64, threshold float64) map[string]interface{}
NotifyDrift emits a drift detection event via the EventBus (for WebUI). Returns the notification data so the CLI layer can use it for display. This is non-blocking — it does not wait for user response.
type DropdownItem ¶
DropdownItem represents an item in a dropdown selection
type DropdownOptions ¶
DropdownOptions provides options for dropdown display
type FileChange ¶
type FileChange struct {
Path string `json:"path"`
Op string `json:"op"` // "created" | "modified" | "deleted"
}
FileChange is a single tracked write/edit/delete from a subagent run. Sourced from ChangeTracker.GetChanges() (SP-059 Phase 2c) when change tracking is enabled; nil when it isn't.
type LogContext ¶
type LogContext struct {
// contains filtered or unexported fields
}
LogContext allows chaining fields for multiple log entries
func (*LogContext) Debug ¶
func (lc *LogContext) Debug(format string, args ...interface{})
Debug writes a debug-level log with context fields from the LogContext
func (*LogContext) Error ¶
func (lc *LogContext) Error(format string, args ...interface{})
Error writes an error-level log with context fields from the LogContext
func (*LogContext) Info ¶
func (lc *LogContext) Info(format string, args ...interface{})
Info writes an info-level log with context fields from the LogContext
func (*LogContext) Warn ¶
func (lc *LogContext) Warn(format string, args ...interface{})
Warn writes a warn-level log with context fields from the LogContext
type LogEntry ¶
type LogEntry struct {
Timestamp string `json:"timestamp"`
Level string `json:"level"` // "debug", "info", "warn", "error"
Message string `json:"message"`
SessionID string `json:"session_id,omitempty"`
Iteration int `json:"iteration,omitempty"`
Provider string `json:"provider,omitempty"`
Model string `json:"model,omitempty"`
Fields map[string]string `json:"fields,omitempty"`
}
LogEntry represents a structured log entry
type MCPSubManager ¶
type MCPSubManager interface {
GetManager() mcp.MCPManager
SetManager(mgr mcp.MCPManager)
GetToolsCache() []api.Tool
SetToolsCache(tools []api.Tool)
IsInitialized() bool
SetInitialized(initialized bool)
GetInitError() error
SetInitError(err error)
LockInit()
UnlockInit()
}
MCPSubManager manages all MCP-related state for an Agent.
type MemoryInfo ¶
type MemoryInfo struct {
Name string // Memory name, derived from filename (without .md extension)
Path string // Full file path
Content string // File content string
}
MemoryInfo represents information about a memory file
func ListMemories ¶
func ListMemories() ([]MemoryInfo, error)
ListMemories returns list of all memories with their name, path, and first line (title/heading) Sorts alphabetically by name
func LoadAllMemories ¶
func LoadAllMemories() ([]MemoryInfo, error)
LoadAllMemories reads all .md files from the memories directory Returns a slice of MemoryInfo sorted by filename Returns empty slice (not error) if no memories exist
type MessageImportance ¶
type MessageImportance = core.MessageImportance
MessageImportance is aliased from seed for tests/diagnostics that inspect the structured score output of the importance scorer.
type ModelItem ¶
type ModelItem struct {
Label string
Value string
Provider string
Model string
InputCost float64
OutputCost float64
LegacyCost float64
ContextLength int
Tags []string
}
ModelItem represents a model in dropdown selections
type OutputBuffer ¶
type OutputBuffer struct {
// contains filtered or unexported fields
}
OutputBuffer captures agent output for controlled display
func NewOutputBuffer ¶
func NewOutputBuffer() *OutputBuffer
NewOutputBuffer creates a new output buffer
func (*OutputBuffer) GetAndClear ¶
func (ob *OutputBuffer) GetAndClear() string
GetAndClear returns the output and clears the buffer
func (*OutputBuffer) GetOutput ¶
func (ob *OutputBuffer) GetOutput() string
GetOutput returns the captured output
func (*OutputBuffer) Print ¶
func (ob *OutputBuffer) Print(args ...interface{})
Print captures output
func (*OutputBuffer) Printf ¶
func (ob *OutputBuffer) Printf(format string, args ...interface{})
Printf captures formatted output
func (*OutputBuffer) Println ¶
func (ob *OutputBuffer) Println(args ...interface{})
Println captures output with newline
type OutputManager ¶
type OutputManager interface {
SetStreamingEnabled(enabled bool)
IsStreamingEnabled() bool
SetStreamingCallback(cb func(string))
GetStreamingCallback() func(string)
SetReasoningCallback(cb func(string))
GetReasoningCallback() func(string)
SetFlushCallback(cb func())
GetFlushCallback() func()
SetOutputMutex(mu *sync.Mutex)
GetOutputMutex() *sync.Mutex
GetStreamingBuffer() *strings.Builder
GetReasoningBuffer() *strings.Builder
GetOutputRouter() *OutputRouter
SetOutputRouter(router *OutputRouter)
GetAsyncOutput() chan string
SetAsyncOutput(ch chan string)
EnsureAsyncOutputWorker(fn func())
GetAsyncBufferSize() int
SetAsyncBufferSize(size int)
GetEventMetadata() map[string]interface{}
SetEventMetadata(meta map[string]interface{})
SetEventMetadataUnlocked(meta map[string]interface{})
GetEventMetadataMutex() *sync.RWMutex
SetTerminalWriter(fn func(string))
GetTerminalWriter() func(string)
}
OutputManager manages all output and streaming-related state for an Agent.
type OutputMode ¶
type OutputMode int
OutputMode determines how output is routed
const ( OutputModeTerminal OutputMode = iota // CLI-only, no event bus OutputModeEventSourced // EventBus + terminal bridge )
type OutputRouter ¶
type OutputRouter struct {
// contains filtered or unexported fields
}
OutputRouter is the single routing point for all agent output. Instead of dual-writing (publish event + print to terminal), all output flows through this router which handles both paths.
Terminal output is ALWAYS produced via the streamingCallback (when set) or via fmt.Print (fallback). The streamingCallback is the terminal display — it is NOT a WebUI path. The event bus is the WebUI path.
When the event bus is set, events are published for WebUI subscribers AND the terminal still receives its output. This is by design: the terminal always shows output; the WebUI optionally shows it via events.
func NewOutputRouter ¶
func NewOutputRouter(agent *Agent, eventBus *events.EventBus) *OutputRouter
NewOutputRouter creates an output router. If eventBus is nil, operates in terminal-only mode. agent may be nil during early initialization; set it later via the field directly.
func (*OutputRouter) Mode ¶
func (r *OutputRouter) Mode() OutputMode
Mode returns the current output mode
func (*OutputRouter) RouteAgentMessage ¶
func (r *OutputRouter) RouteAgentMessage(category, message string, extra map[string]interface{})
RouteAgentMessage routes an agent system message. category: "info", "warning", "error", "tool_log", "thought" RouteAgentMessage routes a message for display in both the WebUI and terminal.
func (*OutputRouter) RouteStreamChunk ¶
func (r *OutputRouter) RouteStreamChunk(chunk string, contentType string)
RouteStreamChunk routes a streaming chunk to the event bus and, when allowed, to terminal output.
Streaming chunks are special: they represent the character-by-character output of the assistant's response. For terminal display, they go through the streamingCallback (real-time output). For WebUI, they are published as stream_chunk events. Reasoning chunks are published but hidden from terminal output unless explicitly enabled.
func (*OutputRouter) RouteTerminalOnly ¶
func (r *OutputRouter) RouteTerminalOnly(message string)
RouteTerminalOnly writes a message directly to the terminal without publishing to the event bus. Use this for output that is already published via a separate, more specific event type (e.g., subagent output lines that are published as subagent_activity events).
func (*OutputRouter) RouteToolCompletion ¶
func (r *OutputRouter) RouteToolCompletion(ok bool, duration time.Duration, errMsg string)
RouteToolCompletion emits the inline duration / outcome chip that follows a tool-log line. Kept separate from RouteToolLog because tool_start fires before the work begins and tool_end fires after — the two are paired by toolCallID at the call site (richEventPublisher / tool_executor).
Format: ` ✓ 124ms` (indented under the prior tool-log line, dim green). On failure: ` ✗ 124ms — <short error>`.
func (*OutputRouter) RouteToolLog ¶
func (r *OutputRouter) RouteToolLog(action string, target string)
RouteToolLog routes a tool execution log message with iteration and context info.
Terminal rendering: a glyph-prefixed dim line. The iter/context info is kept on the WebUI event (for the activity feed) but elided from the terminal — that data already lives on the status footer, and pulling it into every tool-log line just adds noise. Format:
→ shell_command ls -la /path
func (*OutputRouter) SetEventBus ¶
func (r *OutputRouter) SetEventBus(eventBus *events.EventBus)
SetEventBus updates the event bus (called when webui connects/disconnects). The streamingCallback on the agent is NOT affected — it always routes to the terminal regardless of WebUI state.
func (*OutputRouter) SetExternalWriteHook ¶
func (r *OutputRouter) SetExternalWriteHook(fn func())
SetExternalWriteHook registers a callback that fires before every writeTerminalMessage emission. Pass nil to clear. Intended for the AssistantTurnRenderer in pkg/console to break its prose segment when chrome (tool logs / agent messages) interrupts the model's stream.
func (*OutputRouter) SetReasoningCallback ¶ added in v0.16.2
func (r *OutputRouter) SetReasoningCallback(fn func(string))
SetReasoningCallback registers a dedicated sink for reasoning chunks so the CLI can render thinking-stream output as a collapsed header instead of mixing it into the prose stream. When unset (the default), reasoning chunks fall through to the regular streamingCallback if SetReasoningTerminalEnabled is true; otherwise they're suppressed from the terminal entirely (the historic behaviour).
Pass nil to clear. The callback is invoked synchronously from RouteStreamChunk; the caller is responsible for any locking it needs internally.
func (*OutputRouter) SetReasoningTerminalEnabled ¶
func (r *OutputRouter) SetReasoningTerminalEnabled(enabled bool)
SetReasoningTerminalEnabled controls whether reasoning chunks are rendered in the terminal. It is disabled by default so reasoning stays available to the event bus/WebUI without polluting normal CLI output.
type ParameterConfig ¶
type ParameterConfig struct {
Name string `json:"name"`
Type string `json:"type"` // "string", "integer", "number", "boolean"
Required bool `json:"required"`
Alternatives []string `json:"alternatives"` // Alternative parameter names for backward compatibility
Description string `json:"description"`
}
ParameterConfig defines parameter validation rules for a tool
type PathTier ¶
type PathTier int
PathTier classifies a filesystem path for approval purposes. See ClassifyPathAccess for the resolution rules. The tiers are ordered from least to most restrictive.
const ( // PathTierUnknown is the zero value and shouldn't be returned; // it exists so a missing tier shows up loudly in tests rather // than silently behaving as "allow". PathTierUnknown PathTier = iota // PathTierWorkspace — the path is inside the agent's workspace // root (or the sprout config dir). No approval required. PathTierWorkspace // PathTierExternal — outside the workspace but not in a system // or off-CWD home directory. Eligible for the "Allow this folder // for the rest of the session" approval choice. Once a parent // folder is in the agent's session allowlist, future accesses // under it auto-approve. PathTierExternal // PathTierSensitive — system directories (/etc, /usr, ...) OR // home-directory paths when the agent's CWD is outside the user's // home. These ALWAYS prompt and CANNOT be added to the session // allowlist. The "Allow folder this session" choice is hidden // from the dialog for this tier. PathTierSensitive )
func ClassifyPathAccess ¶
ClassifyPathAccess decides which approval tier a path falls into. All three input paths should be absolute (or empty for unset fields). Behavior:
- Inside workspaceRoot → PathTierWorkspace.
- Under a known system directory (e.g. /etc, /usr, /var on Unix; C:\Windows, C:\Program Files on Windows) → PathTierSensitive.
- Under the user's home dir AND the agent's CWD is NOT under home → PathTierSensitive (working in /tmp, accessing ~ is unusual and shouldn't get session-wide allowlisting).
- Anything else outside the workspace → PathTierExternal.
homeDir and cwd are passed explicitly so tests can drive each branch deterministically. Production callers use os.UserHomeDir and the agent's effective CWD.
Symlinks: this classifier compares cleaned path strings; it does NOT call filepath.EvalSymlinks. The filesystem layer (pkg/filesystem) resolves symlinks before returning ErrOutsideWorkingDirectory, so the path we receive here is already the symlink-resolved target — the comparison is correct for cases where the filesystem layer hands us a real path. For non-filesystem callers (e.g. the WebUI file API consulting IsFolderSessionAllowed), the path is whatever the caller resolved. The classifier is therefore advisory: if you've crafted a clever symlink to dodge tier classification, the filesystem layer still enforces its own checks at write time.
type PauseState ¶
type PauseState struct {
IsPaused bool `json:"is_paused"`
PausedAt time.Time `json:"paused_at"`
OriginalTask string `json:"original_task"`
Clarifications []string `json:"clarifications"`
MessagesBefore []api.Message `json:"messages_before"`
}
PauseState tracks the state when a task is paused for clarification
type ProactiveContextConfig ¶
type ProactiveContextConfig struct {
// MinRelevanceScore is the minimum time-decayed similarity score required
// for a result to be included. Default: 0.50.
MinRelevanceScore float64
// MaxContextualResults caps the number of results returned. Default: 5.
MaxContextualResults int
// MaxContextChars is the character budget for FormatProactiveContext.
// The formatted string is truncated at this limit. Default: 4000.
MaxContextChars int
// WorkspaceScoped, if true, filters to turns from the same workingDir.
// Default: true.
//
// Cross-workspace bleed has been a real foot-gun (e.g. a fresh session
// in repo A pulling in semantically-similar turns from repo B and the
// model treating them as actionable). Past work from other workspaces
// is almost always noise; users who genuinely want cross-workspace
// recall can opt in by setting WorkspaceScoped: false (or via the
// PersistentContextConfig override hook in SP-027-2d).
WorkspaceScoped bool
// RetentionDays controls how many days to keep persistent context entries.
// Default: 0 (forever, never expire).
RetentionDays int
}
ProactiveContextConfig holds configuration for proactive context retrieval. These defaults will later be backed by PersistentContextConfig in pkg/configuration (SP-027-2d).
func DefaultProactiveContextConfig ¶
func DefaultProactiveContextConfig() ProactiveContextConfig
DefaultProactiveContextConfig returns a ProactiveContextConfig with the standard defaults specified in SP-027.
type ProactiveContextResult ¶
type ProactiveContextResult struct {
Record embedding.VectorRecord
Score float64 // time-decayed cosine similarity
}
ProactiveContextResult holds a retrieved conversation turn with its time-decayed similarity score.
func RetrieveProactiveContext ¶
func RetrieveProactiveContext( ctx context.Context, mgr *embedding.EmbeddingManager, config ProactiveContextConfig, query string, workingDir string, now time.Time, ) ([]ProactiveContextResult, error)
RetrieveProactiveContext retrieves relevant conversation turns from the conversation store based on semantic similarity with time-decay scoring.
The retrieval pipeline:
- Embed the query text using the static provider
- Load all conversation_turn records from the store
- Optionally filter by working directory (WorkspaceScoped)
- Score each candidate with cosine similarity + 30-day half-life decay
- Filter by MinRelevanceScore, sort descending, cap at MaxContextualResults
Graceful degradation: all errors are logged and nil/empty is returned. The agent should never be blocked by a retrieval failure.
type ProgressEntry ¶
type ProgressEntry struct {
OffsetMS int64 `json:"offset_ms"`
Phase string `json:"phase"`
Message string `json:"message"`
}
ProgressEntry is the envelope-facing form of SubagentProgressEntry, kept separately from the runner-internal type so the runner struct can change without affecting the wire shape.
type ProjectInfo ¶
type ProjectInfo struct {
Path string // Absolute path to project root
Name string // Directory name or project name from AGENTS.md
Description string // First paragraph from AGENTS.md if present
HasAgentsMd bool // Whether project has AGENTS.md
HasGitRepo bool // Whether project has .git directory
Languages []string // Detected languages (from file extensions, go.mod, package.json, etc.)
RelPath string // Relative path from home directory
}
func DiscoverProjects ¶
func DiscoverProjects(homeDir string, maxDepth int) ([]ProjectInfo, error)
type PromptTokensDetails ¶
type PromptTokensDetails struct {
CachedTokens int `json:"cached_tokens"`
CacheWriteTokens *int `json:"cache_write_tokens"`
}
PromptTokensDetails contains detailed breakdown of prompt tokens
type ProviderErrorInfo ¶
type ProviderErrorInfo struct {
Timestamp string `json:"timestamp"` // ISO 8601 when the error occurred
Provider string `json:"provider"` // e.g. "zai", "openrouter"
Model string `json:"model"` // e.g. "glm-5.1"
StatusCode int `json:"status_code,omitempty"` // HTTP status code (400, 429, 500, etc.)
ErrorType string `json:"error_type,omitempty"` // e.g. "api_error_400", "streaming_response"
Message string `json:"message"` // The error message from the provider
Retries int `json:"retries,omitempty"` // Number of retries attempted
}
ProviderErrorInfo captures details about the last API error from the LLM provider. This is persisted in the session file so errors can be diagnosed after the fact.
type PruningStrategy ¶
type PruningStrategy = core.PruningStrategy
PruningStrategy is aliased to seed's strategy type. Sprout's constants below mirror seed's so call sites need no rewrite.
type QuickOption ¶
QuickOption represents a quick choice option
type RateLimitExceededError ¶
RateLimitExceededError indicates repeated rate limit failures even after retries. This type is referenced by the scripted test client and must be available outside of the (now-deleted) APIClient file.
func (*RateLimitExceededError) Error ¶
func (e *RateLimitExceededError) Error() string
func (*RateLimitExceededError) Unwrap ¶
func (e *RateLimitExceededError) Unwrap() error
type ReconciliationActionResult ¶
type ReconciliationActionResult struct {
FilePath string `json:"file_path"`
Action ReconciliationActionType `json:"action"`
ContainerSeq int64 `json:"container_seq"`
BrowserSeq int64 `json:"browser_seq"`
}
ReconciliationActionResult is the per-file reconciliation outcome.
func ReconcileSeqNumbers ¶
func ReconcileSeqNumbers(ag *Agent, browserSeqs map[string]int64) ([]ReconciliationActionResult, error)
ReconcileSeqNumbers compares browser-supplied per-file sequence numbers against the container's stored metadata and returns a reconciliation plan. The browser sends {file_path: browser_seq}; for each file, we compare the browser's seq with the container's seq to determine the action.
Rules:
- browser_seq == container_seq → sync_ok
- browser_seq == last_synced_container AND container_seq > browser_seq → container_ahead
- browser_seq > last_synced_browser → browser_ahead (unsynced browser edits)
- both sides diverged → diverged
type ReconciliationActionType ¶
type ReconciliationActionType string
ReconciliationActionType enumerates the possible outcomes of comparing browser and container sequence numbers for a single file.
const ( // ReconcileSyncOK means browser and container are at the same seq. ReconcileSyncOK ReconciliationActionType = "sync_ok" // ReconcileContainerAhead means the container has patches the browser hasn't seen. ReconcileContainerAhead ReconciliationActionType = "container_ahead" // ReconcileBrowserAhead means the browser has edits the container hasn't applied. ReconcileBrowserAhead ReconciliationActionType = "browser_ahead" // ReconcileDiverged means both sides have diverged and conflict resolution is needed. ReconcileDiverged ReconciliationActionType = "diverged" )
type RetryAction ¶
type RetryAction int
RetryAction represents the action to take when a tool error occurs.
const ( // ActionRetry indicates the error is transient and the tool call should be retried. // Covers TransientError, RateLimitError, retryable ProviderError, and unknown/untyped errors. ActionRetry RetryAction = iota // ActionFail indicates the error is permanent and should not be retried. ActionFail // ActionEscalate indicates the error needs human/LLM review before proceeding. ActionEscalate )
func ClassifyError ¶
func ClassifyError(err error) RetryAction
ClassifyError examines an error and returns the appropriate RetryAction.
It uses typed error checks from pkg/errors (errors.As via helper functions) rather than string matching on error messages. This provides more reliable classification as the error types are structural rather than text-based.
Classification rules (checked in priority order):
- SecurityError → ActionEscalate (ask user/LLM)
- TransientError → ActionRetry (with backoff)
- RateLimitError → ActionRetry (with longer backoff)
- InvalidInputError → ActionFail (fix the input)
- ContextError (ContextOverflow) → ActionFail (need context compaction)
- ProviderError → ActionFail (auth/config) or ActionRetry (server errors) depending on Retryable
- PermanentError → ActionFail
- Retryable AgentError → ActionRetry
- Default (unknown/untyped errors) → ActionRetry once, then ActionFail
func (RetryAction) String ¶
func (a RetryAction) String() string
String returns a human-readable name for the retry action.
type ScriptedClient ¶
type ScriptedClient struct {
*factory.TestClient
// contains filtered or unexported fields
}
ScriptedClient is an enhanced mock client for comprehensive E2E testing It supports: - Sequential scripted responses with tool calls - Streaming simulation - Error injection - Vision support - Rate limit simulation
func NewScriptedClient ¶
func NewScriptedClient(responses ...*ScriptedResponse) *ScriptedClient
NewScriptedClient creates a new scripted client with optional initial responses
func NewScriptedClientWithVision ¶
func NewScriptedClientWithVision(model string, responses ...*ScriptedResponse) *ScriptedClient
NewScriptedClientWithVision creates a scripted client that supports vision models
func (*ScriptedClient) AddResponse ¶
func (c *ScriptedClient) AddResponse(response *ScriptedResponse)
AddResponse appends a response to the end of the queue
func (*ScriptedClient) AdvanceIndex ¶
func (c *ScriptedClient) AdvanceIndex()
AdvanceIndex advances to the next response
func (*ScriptedClient) Cancel ¶
func (c *ScriptedClient) Cancel()
Cancel cancels any pending operations
func (*ScriptedClient) CheckConnection ¶
func (c *ScriptedClient) CheckConnection() error
CheckConnection always returns nil for test client
func (*ScriptedClient) ClearHistory ¶
func (c *ScriptedClient) ClearHistory()
ClearHistory clears the response history
func (*ScriptedClient) ClearSentRequests ¶
func (c *ScriptedClient) ClearSentRequests()
ClearSentRequests clears all recorded sent requests
func (*ScriptedClient) Close ¶
func (c *ScriptedClient) Close()
Close closes the client and releases resources
func (*ScriptedClient) GetAverageTPS ¶
func (c *ScriptedClient) GetAverageTPS() float64
GetAverageTPS returns the average tokens per second
func (*ScriptedClient) GetIndex ¶
func (c *ScriptedClient) GetIndex() int
GetIndex returns the current response index
func (*ScriptedClient) GetLastTPS ¶
func (c *ScriptedClient) GetLastTPS() float64
GetLastTPS returns the last tokens per second
func (*ScriptedClient) GetModel ¶
func (c *ScriptedClient) GetModel() string
GetModel returns the current model
func (*ScriptedClient) GetModelContextLimit ¶
func (c *ScriptedClient) GetModelContextLimit() (int, error)
GetModelContextLimit returns the context limit
func (*ScriptedClient) GetNextResponse ¶
func (c *ScriptedClient) GetNextResponse() *ScriptedResponse
GetNextResponse returns the next response without advancing the index
func (*ScriptedClient) GetProvider ¶
func (c *ScriptedClient) GetProvider() string
GetProvider returns the provider name
func (*ScriptedClient) GetSentRequest ¶
func (c *ScriptedClient) GetSentRequest(index int) []api.Message
GetSentRequest returns a specific request's messages (nil if out of range)
func (*ScriptedClient) GetSentRequests ¶
func (c *ScriptedClient) GetSentRequests() [][]api.Message
GetSentRequests returns a defensive deep copy of all recorded request message arrays. Both the outer slice and each inner []api.Message slice are copied to prevent external mutation of the client's internal state.
func (*ScriptedClient) GetTPSStats ¶
func (c *ScriptedClient) GetTPSStats() map[string]float64
GetTPSStats returns TPS statistics
func (*ScriptedClient) GetVisionModel ¶
func (c *ScriptedClient) GetVisionModel() string
GetVisionModel returns the vision model name
func (*ScriptedClient) LastResponse ¶
func (c *ScriptedClient) LastResponse() *ScriptedResponse
LastResponse returns the last consumed response
func (*ScriptedClient) Length ¶
func (c *ScriptedClient) Length() int
Length returns the number of scripted responses
func (*ScriptedClient) ListModels ¶
ListModels returns available models
func (*ScriptedClient) Reset ¶
func (c *ScriptedClient) Reset()
Reset resets the response index to the beginning
func (*ScriptedClient) ResetTPSStats ¶
func (c *ScriptedClient) ResetTPSStats()
ResetTPSStats resets TPS statistics
func (*ScriptedClient) ResponseHistory ¶
func (c *ScriptedClient) ResponseHistory() []*ScriptedResponse
ResponseHistory returns all consumed responses
func (*ScriptedClient) SendChatRequest ¶
func (c *ScriptedClient) SendChatRequest(ctx context.Context, messages []api.Message, tools []api.Tool, reasoning string, disableThinking bool) (*api.ChatResponse, error)
SendChatRequest sends a chat request and returns a scripted response
func (*ScriptedClient) SendChatRequestStream ¶
func (c *ScriptedClient) SendChatRequestStream(ctx context.Context, messages []api.Message, tools []api.Tool, reasoning string, disableThinking bool, callback api.StreamCallback) (*api.ChatResponse, error)
SendChatRequestStream sends a streaming chat request with full simulation support
func (*ScriptedClient) SendVisionRequest ¶
func (c *ScriptedClient) SendVisionRequest(ctx context.Context, messages []api.Message, tools []api.Tool, reasoning string, disableThinking bool) (*api.ChatResponse, error)
SendVisionRequest sends a vision-enabled chat request
func (*ScriptedClient) SetDebug ¶
func (c *ScriptedClient) SetDebug(debug bool)
SetDebug enables debug mode
func (*ScriptedClient) SetIndex ¶
func (c *ScriptedClient) SetIndex(idx int)
SetIndex sets the response index (useful for replay scenarios)
func (*ScriptedClient) SetModel ¶
func (c *ScriptedClient) SetModel(model string) error
SetModel sets the model name
func (*ScriptedClient) SetResponses ¶
func (c *ScriptedClient) SetResponses(responses []*ScriptedResponse)
SetResponses replaces all responses and resets all derived state.
func (*ScriptedClient) SupportsVision ¶
func (c *ScriptedClient) SupportsVision() bool
SupportsVision returns whether vision is supported
type ScriptedResponse ¶
type ScriptedResponse struct {
// Message content to return
Content string
// Tool calls to include in the response
ToolCalls []api.ToolCall
// Finish reason for the choice
FinishReason string
// Reasoning content (for models that support it)
ReasoningContent string
// Images to include (vision support)
Images []api.ImageData
// Delay before returning the response (for rate limit simulation)
Delay time.Duration
// Error to return instead of a response
Error error
// Rate limit simulation: return rate limit error after N successful responses
RateLimitAfter int
// Stream configuration
StreamConfig *StreamConfig
// Whether this response should be used for vision requests
VisionOnly bool
// Token usage metrics for this response
Usage ScriptedTokenUsage
}
ScriptedResponse represents a single scripted response with full configuration options
func NewErrorResponse ¶
func NewErrorResponse(err error) *ScriptedResponse
NewErrorResponse creates a response that returns an error
func NewKeepGoingResponse ¶
func NewKeepGoingResponse(content string) *ScriptedResponse
NewKeepGoingResponse creates a keep-going response (empty finish_reason)
func NewLengthResponse ¶
func NewLengthResponse(content string) *ScriptedResponse
NewLengthResponse creates a length finish_reason response
func NewRateLimitResponse ¶
func NewRateLimitResponse() *ScriptedResponse
NewRateLimitResponse creates a response that simulates rate limiting
func NewStopResponse ¶
func NewStopResponse(content string) *ScriptedResponse
NewStopResponse creates a stop response
func NewTimeoutResponse ¶
func NewTimeoutResponse() *ScriptedResponse
NewTimeoutResponse creates a response with a timeout error
func NewToolCallResponse ¶
func NewToolCallResponse(name, args string, toolCalls ...api.ToolCall) *ScriptedResponse
NewToolCallResponse creates a response with tool calls
type ScriptedResponseBuilder ¶
type ScriptedResponseBuilder struct {
// contains filtered or unexported fields
}
ScriptedResponseBuilder provides a fluent interface for building ScriptedResponse
func NewScriptedResponseBuilder ¶
func NewScriptedResponseBuilder() *ScriptedResponseBuilder
NewScriptedResponseBuilder creates a new response builder
func (*ScriptedResponseBuilder) Build ¶
func (b *ScriptedResponseBuilder) Build() *ScriptedResponse
Build returns the constructed ScriptedResponse
func (*ScriptedResponseBuilder) Content ¶
func (b *ScriptedResponseBuilder) Content(content string) *ScriptedResponseBuilder
Content sets the message content
func (*ScriptedResponseBuilder) Delay ¶
func (b *ScriptedResponseBuilder) Delay(d time.Duration) *ScriptedResponseBuilder
Delay sets the delay before returning the response
func (*ScriptedResponseBuilder) Error ¶
func (b *ScriptedResponseBuilder) Error(err error) *ScriptedResponseBuilder
Error sets an error to be returned instead of a response
func (*ScriptedResponseBuilder) FinishReason ¶
func (b *ScriptedResponseBuilder) FinishReason(reason string) *ScriptedResponseBuilder
FinishReason sets the finish reason
func (*ScriptedResponseBuilder) Images ¶
func (b *ScriptedResponseBuilder) Images(images []api.ImageData) *ScriptedResponseBuilder
Images sets the images for vision support
func (*ScriptedResponseBuilder) RateLimitAfter ¶
func (b *ScriptedResponseBuilder) RateLimitAfter(n int) *ScriptedResponseBuilder
RateLimitAfter configures rate limit simulation
func (*ScriptedResponseBuilder) ReasoningContent ¶
func (b *ScriptedResponseBuilder) ReasoningContent(content string) *ScriptedResponseBuilder
ReasoningContent sets reasoning content for models that support it
func (*ScriptedResponseBuilder) StreamConfig ¶
func (b *ScriptedResponseBuilder) StreamConfig(sc *StreamConfig) *ScriptedResponseBuilder
StreamConfig sets streaming configuration
func (*ScriptedResponseBuilder) ToolCall ¶
func (b *ScriptedResponseBuilder) ToolCall(tc api.ToolCall) *ScriptedResponseBuilder
ToolCall adds a single tool call
func (*ScriptedResponseBuilder) ToolCalls ¶
func (b *ScriptedResponseBuilder) ToolCalls(tcs []api.ToolCall) *ScriptedResponseBuilder
ToolCalls sets multiple tool calls
func (*ScriptedResponseBuilder) Usage ¶
func (b *ScriptedResponseBuilder) Usage(promptTokens, completionTokens, totalTokens int, estimatedCost float64) *ScriptedResponseBuilder
Usage sets the token usage metrics for this response
func (*ScriptedResponseBuilder) VisionOnly ¶
func (b *ScriptedResponseBuilder) VisionOnly() *ScriptedResponseBuilder
VisionOnly marks this response for vision-only requests
type ScriptedTokenUsage ¶
type ScriptedTokenUsage struct {
PromptTokens int `json:"prompt_tokens"`
CompletionTokens int `json:"completion_tokens"`
TotalTokens int `json:"total_tokens"`
EstimatedCost float64 `json:"estimated_cost"`
Cost float64 `json:"cost,omitempty"`
PromptTokensDetails PromptTokensDetails `json:"prompt_tokens_details,omitempty"`
}
ScriptedTokenUsage represents token usage metrics for a scripted response
type SecurityManager ¶
type SecurityManager interface {
GetSecurityApprovalMgr() *security.ApprovalManager
SetApprovalMgr(mgr *security.ApprovalManager)
SetAskUserMgr(mgr *agenttools.AskUserManager)
GetAskUserMgr() *agenttools.AskUserManager
SetUnsafeMode(unsafe bool)
GetUnsafeMode() bool
// IsSecurityBypassApproved reports whether the user has approved
// any external filesystem access this session. After the SP-058
// follow-up this returns true iff at least one folder is on the
// session allowlist — used as a coarse "user has consented to
// external access" signal by subagent setup. Per-path decisions
// should call IsFolderSessionAllowed instead.
//
// Deprecated: use IsFolderSessionAllowed(absPath) for per-path
// checks. SetSecurityBypassApproved is gone — call
// AddSessionAllowedFolder with the specific folder instead.
IsSecurityBypassApproved() bool
// IsFolderSessionAllowed reports whether absPath sits under any
// folder the user has allowlisted for this session. Match is
// prefix-based (path-component aware) and case-sensitive on Unix.
IsFolderSessionAllowed(absPath string) bool
// AddSessionAllowedFolder records that the user picked "Allow
// this folder for the rest of the session" on the approval
// dialog. The folder is stored after Clean()-ing and dedup'd
// against the existing list.
AddSessionAllowedFolder(folder string)
// SnapshotSessionAllowedFolders returns a copy of the current
// allowlist. Used to propagate approvals into subagents (each
// subagent gets its own allowlist seeded from the parent's).
SnapshotSessionAllowedFolders() []string
IsConcernIgnored(filePath, concern string) bool
SetConcernIgnored(filePath, concern string)
GetOutputRedactor() *security.OutputRedactor
GetElevationGate() *security.ElevationGate
SetElevationGate(gate *security.ElevationGate)
SetHasActiveWebUIClients(fn func() bool)
HasActiveWebUIClients() bool
}
SecurityManager provides an interface for managing all security-related state.
type SessionInfo ¶
type SessionInfo struct {
SessionID string `json:"session_id"`
LastUpdated time.Time `json:"last_updated"`
Name string `json:"name"` // Human-readable session name
WorkingDirectory string `json:"working_directory"` // Directory where session was created
StoragePath string `json:"storage_path,omitempty"`
}
SessionInfo represents session information with timestamp
func ListAllSessionsWithTimestamps ¶
func ListAllSessionsWithTimestamps() ([]SessionInfo, error)
ListAllSessionsWithTimestamps returns all available sessions across all scopes.
func ListSessionsWithTimestamps ¶
func ListSessionsWithTimestamps() ([]SessionInfo, error)
ListSessionsWithTimestamps returns sessions for the current working directory scope.
func ListSessionsWithTimestampsScoped ¶
func ListSessionsWithTimestampsScoped(workingDir string) ([]SessionInfo, error)
ListSessionsWithTimestampsScoped returns sessions only for the given working directory scope.
type SessionItem ¶
type SessionItem struct {
Label string
Value string
SessionID string
Model string
LastUpdated time.Time
Name string // Human-readable session name
}
SessionItem represents a session in dropdown selections
type SharedState ¶
type SharedState struct {
}
SharedState holds resources shared between parent and subagents
type ShellCommandResult ¶
type ShellCommandResult struct {
Command string // The command that was run
FullOutput string // Complete output (for future reference)
TruncatedOutput string // Truncated output (what was shown)
Error error // Any error that occurred
ExecutedAt int64 // Unix timestamp
MessageIndex int // Index in messages array where this result appears
WasTruncated bool // Whether output was truncated
FullOutputPath string // Optional path to the saved full output
TruncatedTokens int // Number of tokens omitted from the middle section
TruncatedLines int // Approximate number of lines omitted from the middle
}
ShellCommandResult tracks shell command execution for deduplication
type SimpleUI ¶
type SimpleUI struct{}
SimpleUI provides a minimal fallback UI implementation
func (*SimpleUI) IsInteractive ¶
IsInteractive returns false for simple UI (non-interactive)
func (*SimpleUI) ShowDropdown ¶
func (s *SimpleUI) ShowDropdown(ctx context.Context, items interface{}, options DropdownOptions) (interface{}, error)
ShowDropdown returns an error since simple UI doesn't support dropdowns
func (*SimpleUI) ShowQuickPrompt ¶
func (s *SimpleUI) ShowQuickPrompt(ctx context.Context, prompt string, options []QuickOption, horizontal bool) (QuickOption, error)
ShowQuickPrompt returns an error since simple UI doesn't support prompts
type SkillInfo ¶
type SkillInfo struct {
ID string
Name string
Description string
Path string
Content string
Source string // "builtin", "user", or "project"
}
func ListSkills ¶
func ListSkills(config *configuration.Config) []SkillInfo
func LoadSkill ¶
func LoadSkill(skillID string, config *configuration.Config) (*SkillInfo, error)
LoadSkill resolves a skill by ID: built-ins come from the embedded pkg/skills library (the single source of truth that also seeds Config.Skills), user/project skills come from disk via skill.Path. The config registry is still the gate — a skill that isn't registered or is explicitly disabled cannot be activated, even if its content happens to be embedded.
type StateManager ¶
type StateManager interface {
// Messages
GetMessages() []api.Message
SetMessages([]api.Message)
AddMessage(api.Message)
// Session
GetSessionID() string
SetSessionID(string)
// Turn checkpoints
GetTurnCheckpoints() []TurnCheckpoint
SetTurnCheckpoints([]TurnCheckpoint)
AddTurnCheckpoint(TurnCheckpoint)
// Checkpoint mutex
GetCheckpointMutex() *sync.RWMutex
// Summary
GetPreviousSummary() string
SetPreviousSummary(string)
// Optimizer
GetOptimizer() *ConversationOptimizer
SetOptimizer(*ConversationOptimizer)
// Context tokens
GetCurrentContextTokens() int
SetCurrentContextTokens(int)
GetMaxContextTokens() int
SetMaxContextTokens(int)
// Context warning
IsContextWarningIssued() bool
SetContextWarningIssued(bool)
// Task actions
GetTaskActions() []TaskAction
SetTaskActions([]TaskAction)
AddTaskAction(TaskAction)
// Task actions mutex
GetTaskActionsMutex() *sync.RWMutex
// Cost
GetTotalCost() float64
SetTotalCost(float64)
AddCost(float64)
// Token counts
GetTotalTokens() int
SetTotalTokens(int)
GetPromptTokens() int
SetPromptTokens(int)
GetCompletionTokens() int
SetCompletionTokens(int)
// LLM call tracking
GetLLMCallCount() int
SetLLMCallCount(int)
IncrementLLMCallCount()
// Tool call tracking
GetTotalToolCalls() int
SetTotalToolCalls(int)
IncrementTotalToolCalls()
// Estimated token responses
GetEstimatedTokenResponses() int
SetEstimatedTokenResponses(int)
// Cache stats
GetCachedTokens() int
SetCachedTokens(int)
GetCachedCostSavings() float64
SetCachedCostSavings(float64)
// Skills and persona
GetActiveSkills() []string
SetActiveSkills([]string)
GetActivePersona() string
SetActivePersona(string)
// Circuit breaker
GetCircuitBreaker() *CircuitBreakerState
SetCircuitBreaker(*CircuitBreakerState)
// Tool call guidance
IsToolCallGuidanceAdded() bool
SetToolCallGuidanceAdded(bool)
// Pending state
GetPendingSwitchContextRefresh() string
SetPendingSwitchContextRefresh(string)
GetPendingStrictSwitchNotice() string
SetPendingStrictSwitchNotice(string)
GetPendingSystemSupplement() string
SetPendingSystemSupplement(string)
// False stop detection
IsFalseStopDetectionEnabled() bool
SetFalseStopDetectionEnabled(bool)
// Termination
GetLastRunTerminationReason() string
SetLastRunTerminationReason(string)
// Conversation pruner
GetConversationPruner() *ConversationPruner
SetConversationPruner(*ConversationPruner)
// Command history
GetCommandHistory() []string
SetCommandHistory([]string)
GetHistoryIndex() int
SetHistoryIndex(int)
GetHistoryMutex() *sync.Mutex
// Pause
GetPauseState() *PauseState
SetPauseState(*PauseState)
GetPauseMutex() *sync.Mutex
// Tracing
GetTraceSession() interface{}
SetTraceSession(interface{})
// Session config
GetSessionProvider() api.ClientType
SetSessionProvider(api.ClientType)
GetSessionModel() string
SetSessionModel(string)
// Config overrides
GetConfigOverrides() map[string]interface{}
SetConfigOverrides(map[string]interface{})
// Current iteration
GetCurrentIteration() int
SetCurrentIteration(int)
// Session intent embedding
GetSessionIntentEmbedding() []float32
SetSessionIntentEmbedding([]float32)
// SetSessionIntentEmbeddingIfNil atomically sets the embedding only if it is
// currently nil. Returns true if the embedding was set, false if it already
// had a value. Used to capture the first-turn intent without TOCTOU races.
SetSessionIntentEmbeddingIfNil(emb []float32) bool
// Last provider error
GetLastProviderError() *ProviderErrorInfo
SetLastProviderError(*ProviderErrorInfo)
}
StateManager defines the interface for managing conversation state previously held directly in the Agent struct.
type StreamConfig ¶
type StreamConfig struct {
// Chunks to stream (content pieces)
Chunks []string
// Delay between chunks
ChunkDelay time.Duration
// Simulated tokens per chunk
TokensPerChunk int
// Error to inject during streaming
StreamError error
// Finish reason for the final chunk
FinishReason string
// ErrorAfterChunks specifies after how many chunks to fail (0 = never fail)
ErrorAfterChunks int
// ChunkErrors allows specifying per-chunk errors (index corresponds to chunk index)
ChunkErrors []error
}
StreamConfig configures streaming behavior for a response
type SubagentError ¶
type SubagentError struct {
Status SubagentStatus
Reason string
}
SubagentError is an in-process error value carrying both the terminal Status and a free-form Reason. Returned alongside the JSON envelope when callers in Go-land want to switch on the failure mode without re-parsing the result JSON.
func (*SubagentError) Error ¶
func (e *SubagentError) Error() string
type SubagentMetrics ¶
type SubagentMetrics struct {
Active int64 // Currently executing subagents
Queued int64 // Waiting for semaphore slot
Completed int64 // Successfully completed
Failed int64 // Completed with error
Cancelled int64 // Cancelled (parent ctx or budget)
TotalQueuedWaitMS int64 // Cumulative milliseconds spent waiting in queue
}
SubagentMetrics tracks operational metrics for the subagent runner.
type SubagentOptions ¶
type SubagentOptions struct {
Persona string // "coder", "tester", "debugger", etc.
Model string // optional model override
Provider string // optional provider override
SystemPrompt string // optional system prompt override
MaxTokens int // token budget (0 = unlimited)
Timeout time.Duration // execution timeout (0 = unlimited)
WorkingDir string // optional: override workspace root (must be within $HOME)
MaxConcurrentSubagents int // max parallel subagents (0 = unlimited, default unlimited)
FleetTokenBudget int // shared token budget across all parallel subagents (0 = unlimited)
}
SubagentOptions configures an in-process subagent
type SubagentProgressEntry ¶
type SubagentProgressEntry struct {
OffsetMS int64 `json:"offset_ms"` // ms since subagent started
Phase string `json:"phase"` // "spawn" | "output" | "complete"
Message string `json:"message"`
}
SubagentProgressEntry is one timeline entry from a subagent run. Kept minimal to avoid bloating the envelope the primary's LLM sees.
type SubagentResult ¶
type SubagentResult struct {
ID string
Output string
Error error
TokensUsed int
Cost float64
ToolCalls int
// Iterations is the assistant-turn count consumed by this subagent
// run. Surfaced to the primary via SubagentRunMetrics.Iterations so
// the model has visibility into how many LLM rounds a delegated task
// burned. SP-059 Phase 5.
Iterations int
Elapsed time.Duration
Cancelled bool
BudgetExceeded bool // true if task was skipped because fleet budget was already exceeded before starting
Truncated bool // true if subagent was cut short due to fleet budget exceeded mid-run
// FileChanges is the manifest of writes/edits this subagent performed,
// captured via its own ChangeTracker. nil when tracking wasn't
// initialized for this run. SP-059 Phase 2c.
FileChanges []TrackedFileChange
// ProgressLog is a per-run timeline of notable subagent events
// (spawn, output, complete). Surfaced to the primary's LLM via the
// SubagentReturn envelope so the model can reason about *what* the
// subagent did, not just the final assistant message. Capped to
// subagentProgressLogCap entries. SP-059 Phase 3a.
ProgressLog []SubagentProgressEntry
}
SubagentResult is the structured output from a subagent
type SubagentReturn ¶
type SubagentReturn struct {
// Output is the subagent's final assistant message (was: "stdout").
Output string `json:"stdout"`
// Stderr carries the subagent's terminal error message if any.
Stderr string `json:"stderr"`
// ExitCode is "0" on success, "1" otherwise. Kept as string for
// shape-compat with the legacy resultMap.
ExitCode string `json:"exit_code"`
// Completed is "true" on natural completion, "false" if cancelled.
Completed string `json:"completed"`
// TimedOut is "true" if the run hit its timeout.
TimedOut string `json:"timed_out"`
// BudgetExceeded is "true" if the run hit its token budget.
BudgetExceeded string `json:"budget_exceeded"`
// ElapsedSeconds is the wall-clock duration, formatted "%.1f".
ElapsedSeconds string `json:"elapsed_seconds"`
// TokensUsed is the rolled-up token count (string for shape-compat).
TokensUsed string `json:"tokens_used"`
// Cost is the rolled-up dollar cost (string for shape-compat).
Cost string `json:"cost"`
// ToolCallCount is the number of tool calls the subagent made.
ToolCallCount string `json:"tool_calls"`
// Summary is JSON-stringified human-readable highlights (file ops,
// build/test status, errors). Kept for shape-compat.
Summary string `json:"summary,omitempty"`
// ContextUsed is "true" / "false" reflecting whether the subagent
// received the parent's context bundle.
ContextUsed string `json:"context_used,omitempty"`
// FilesUsed is the parent-provided files-of-interest list.
FilesUsed string `json:"files_used,omitempty"`
// WorkingDir is the directory the subagent executed under.
WorkingDir string `json:"working_dir,omitempty"`
// Status is the terminal state. Always populated, even on success.
Status SubagentStatus `json:"status"`
// ErrorReason carries free-form context when Status != completed.
ErrorReason string `json:"error_reason,omitempty"`
// FilesModified is the change-tracker-sourced manifest. nil when
// change tracking is disabled (caller treats nil as "not reported").
FilesModified []FileChange `json:"files_modified,omitempty"`
// Metrics is the structured token/cost rollup. Mirror of the
// TokensUsed/Cost/ToolCallCount string fields above for callers
// that prefer typed access.
Metrics SubagentRunMetrics `json:"metrics"`
// ProgressLog is a capped timeline of subagent activity events
// (spawn / output / complete) so the primary's LLM can reason about
// what the subagent actually did, not just its final assistant
// message. nil when no events were captured. SP-059 Phase 3a.
ProgressLog []ProgressEntry `json:"progress_log,omitempty"`
}
SubagentReturn is the typed envelope a subagent tool call returns to the primary's LLM. It marshals to JSON with backward-compatible keys for the old map[string]string shape so existing LLM behavior keeps working, plus new typed fields (status, files_modified, metrics) for callers that want them.
See SP-059 Phase 2a.
func (*SubagentReturn) MarshalJSONIndent ¶
func (r *SubagentReturn) MarshalJSONIndent() (string, error)
MarshalJSONIndent renders the envelope as a 2-space-indented JSON string for the tool result.
type SubagentRunMetrics ¶
type SubagentRunMetrics struct {
TokensUsed int `json:"tokens_used"`
Cost float64 `json:"cost"`
ToolCalls int `json:"tool_calls"`
Iterations int `json:"iterations"`
}
SubagentRunMetrics is the structured token/cost accounting for a subagent run. Sourced directly from SubagentResult (subagent_runner.go), not by regex-scraping stdout. Iterations is the assistant-turn count, exposed so the primary's LLM can reason about how much budget a delegated task burned.
type SubagentRunner ¶
type SubagentRunner struct {
// contains filtered or unexported fields
}
SubagentRunner manages in-process subagent execution
func NewSubagentRunner ¶
func NewSubagentRunner(parent *Agent, shared *SharedState) *SubagentRunner
NewSubagentRunner creates a new SubagentRunner
func (*SubagentRunner) CancelAll ¶
func (r *SubagentRunner) CancelAll()
CancelAll cancels all running subagents. Called when the user clicks Stop on the primary — without this, the primary's TriggerInterrupt returns but subagent work continues until self-completion.
func (*SubagentRunner) CancelSubagent ¶
func (r *SubagentRunner) CancelSubagent(id string) bool
CancelSubagent cancels a specific running subagent by ID. Cancels both the run context (truncates pending work) and the subagent agent's interrupt signal (preempts the in-flight ProcessQuery loop, which doesn't observe runCtx — see SP-059 Phase 1a).
func (*SubagentRunner) GetActiveSubagents ¶
func (r *SubagentRunner) GetActiveSubagents() []*runningSubagent
GetActiveSubagents returns information about currently running subagents
func (*SubagentRunner) InjectInputIntoActive ¶
func (r *SubagentRunner) InjectInputIntoActive(input string) (string, bool)
InjectInputIntoActive delivers a steering message to the deepest (most-recently-started) running subagent. Returns the target ID when delivery succeeds, or empty string when no subagent is currently active — the caller falls back to the primary's input channel in that case.
"Deepest" wins so that nested-subagent setups route to the one the user is most likely watching activity from in the Subagents tab. Selection ties broken by start time (latest wins).
func (*SubagentRunner) Metrics ¶
func (r *SubagentRunner) Metrics() SubagentMetrics
Metrics returns a snapshot of the subagent runner's operational metrics.
func (*SubagentRunner) Run ¶
func (r *SubagentRunner) Run(ctx context.Context, prompt string, opts SubagentOptions) *SubagentResult
Run spawns an in-process subagent and waits for completion
func (*SubagentRunner) RunParallel ¶
func (r *SubagentRunner) RunParallel(ctx context.Context, tasks []SubagentTask, opts SubagentOptions) []*SubagentResult
RunParallel spawns multiple subagents concurrently. If the parent context is cancelled, remaining subagents are cancelled and their results are set to cancellation errors.
type SubagentStatus ¶
type SubagentStatus string
SubagentStatus enumerates terminal states of a subagent run. Replaces the legacy SUBAGENT_SECURITY_ERROR / SUBAGENT_TOKEN_BUDGET_EXCEEDED / SUBAGENT_FAILED sentinel string prefixes — those literals are retained in the human-readable Output so any LLM behavior keyed on the legacy shape still works, but in-process callers should switch to Status.
See SP-059 Phase 2d.
const ( SubagentStatusCompleted SubagentStatus = "completed" SubagentStatusCancelled SubagentStatus = "cancelled" SubagentStatusTimedOut SubagentStatus = "timed_out" SubagentStatusBudgetExceeded SubagentStatus = "budget_exceeded" SubagentStatusSecurityBlocked SubagentStatus = "security_blocked" SubagentStatusFailed SubagentStatus = "failed" )
type SubagentTask ¶
type SubagentTask struct {
ID string
Prompt string
Model string
Provider string
Persona string
WorkingDir string // optional: override workspace root
}
SubagentTask represents a single parallel subagent task
type SyncOp ¶
type SyncOp struct {
OpType string `json:"op_type"` // "write", "delete", or "rename"
Path string `json:"path"` // Target file path (relative to workspace root)
Content string `json:"content"` // For write ops: the file content
NewPath string `json:"new_path"` // For rename ops: the destination path
BrowserSeq int64 `json:"browser_seq"` // Monotonically increasing browser-side seq number
Timestamp int64 `json:"timestamp"` // Unix milliseconds when the op was created
}
SyncOp represents a single file operation sent from the browser to the container as part of the workspace sync protocol (SP-046 §2). The browser queues these in OPFS and flushes them via HTTP POST when the WebSocket is up.
type SyncOpResult ¶
type SyncOpResult struct {
Accepted bool `json:"accepted"` // Whether the op was applied
ConflictPath string `json:"conflict_path"` // Set if there's a container-side conflict (path to .theirs file)
ContainerSeq int64 `json:"container_seq"` // Current container sequence after applying
Error string `json:"error,omitempty"` // Error message if not accepted
}
SyncOpResult is the server response to a SyncOp application.
type TaskAction ¶
type TaskAction struct {
Type string // "file_created", "file_modified", "command_executed", "file_read"
Description string // Human-readable description
Details string // Additional details like file path, command, etc.
}
TaskAction represents a completed action during task execution
type Theme ¶
type Theme struct {
Name string `json:"name"`
Description string `json:"description"`
Colors struct {
Success string `json:"success"`
Warning string `json:"warning"`
Error string `json:"error"`
Info string `json:"info"`
Primary string `json:"primary"`
Secondary string `json:"secondary"`
Accent string `json:"accent"`
} `json:"colors"`
}
Theme represents a color theme configuration
type ThemeManager ¶
type ThemeManager struct {
// contains filtered or unexported fields
}
ThemeManager manages color themes
func NewThemeManager ¶
func NewThemeManager() *ThemeManager
NewThemeManager creates a new theme manager with default theme
func (*ThemeManager) GetColor ¶
func (tm *ThemeManager) GetColor(name string) string
GetColor returns a color by name
func (*ThemeManager) GetTheme ¶
func (tm *ThemeManager) GetTheme() Theme
GetTheme returns the current theme
func (*ThemeManager) LoadDefaultTheme ¶
func (tm *ThemeManager) LoadDefaultTheme()
LoadDefaultTheme loads the default theme
func (*ThemeManager) LoadThemeFromFile ¶
func (tm *ThemeManager) LoadThemeFromFile(themePath string) error
LoadThemeFromFile loads a theme from a JSON file
type TokenUsage ¶
type TokenUsage struct {
PromptTokens int
CompletionTokens int
TotalTokens int
EstimatedCost float64
}
TokenUsage captures key token metrics for each turn
type ToolConfig ¶
type ToolConfig struct {
Name string `json:"name"`
Description string `json:"description"`
Parameters []ParameterConfig `json:"parameters"`
Handler ToolHandler `json:"-"` // Function reference, not serialized
HandlerImages ToolHandlerWithImages `json:"-"` // Optional image-returning handler (takes precedence over Handler when set)
// Interactive declares that the tool owns the terminal during
// execution — either by reading from stdin (e.g. ask_user prompting
// for a response) OR by streaming output to stdout/stderr live (e.g.
// shell_command tee'ing subprocess output via io.MultiWriter). Either
// case is incompatible with the CLI activity-indicator spinner: the
// spinner's \r\033[K updates would clobber the tool's prompt or
// interleave with its output. When true, ToolStart subscribers must
// stop any active spinner and emit no result chrome on ToolEnd — the
// tool's natural output IS the feedback the user expects.
Interactive bool `json:"interactive,omitempty"`
// Per-tool execution config consumed by the seed core.ToolRegistry
// transformer in pkg/agent/seed_tool_registry.go. Zero values fall
// through to the seed registry's defaults (5min timeout, 50KB result
// cap, no aliases, not safe for parallel execution).
Aliases []string `json:"aliases,omitempty"`
Timeout time.Duration `json:"timeout,omitempty"`
MaxResultSize int `json:"max_result_size,omitempty"`
SafeForParallel bool `json:"safe_for_parallel,omitempty"`
}
ToolConfig holds configuration for a tool
type ToolExecutor ¶
type ToolExecutor struct {
// contains filtered or unexported fields
}
ToolExecutor handles tool execution logic
func NewToolExecutor ¶
func NewToolExecutor(agent *Agent) *ToolExecutor
NewToolExecutor creates a new tool executor
func (*ToolExecutor) ExecuteTools ¶
func (te *ToolExecutor) ExecuteTools(toolCalls []api.ToolCall) []api.Message
ExecuteTools executes a list of tool calls and returns the results
func (*ToolExecutor) GenerateToolCallID ¶
func (te *ToolExecutor) GenerateToolCallID(toolName string) string
GenerateToolCallID creates a unique tool call ID if one is missing
func (*ToolExecutor) SetHandlerRegistry ¶
func (te *ToolExecutor) SetHandlerRegistry(r *tools.ToolRegistry)
SetHandlerRegistry sets the new tool handler registry for dual dispatch. When set, the executor checks this registry first before falling back to the legacy dispatch path. This enables gradual migration of tools. Thread-safe: may be called concurrently with tool execution.
type ToolHandler ¶
ToolHandler represents a function that can handle a tool execution
type ToolHandlerWithImages ¶
type ToolHandlerWithImages func(ctx context.Context, a *Agent, args map[string]interface{}) ([]api.ImageData, string, error)
ToolHandlerWithImages is like ToolHandler but can also return image data for multimodal (vision-capable) models. The []api.ImageData slice should be nil when no images are produced; the string is always the text result.
type ToolRegistry ¶
type ToolRegistry struct {
// contains filtered or unexported fields
}
ToolRegistry manages tool configurations in a data-driven way
func GetToolRegistry ¶
func GetToolRegistry() *ToolRegistry
GetToolRegistry returns the default tool registry, initializing it lazily if needed (thread-safe)
func (*ToolRegistry) ExecuteTool ¶
func (r *ToolRegistry) ExecuteTool(ctx context.Context, toolName string, args map[string]interface{}, agent *Agent) ([]api.ImageData, string, error)
ExecuteTool executes a tool with standardized parameter validation and error handling
func (*ToolRegistry) GetAllToolConfigs ¶
func (r *ToolRegistry) GetAllToolConfigs() map[string]ToolConfig
GetAllToolConfigs returns a copy of all registered tool configs keyed by name.
func (*ToolRegistry) GetAvailableTools ¶
func (r *ToolRegistry) GetAvailableTools() []string
GetAvailableTools returns a list of all registered tool names
func (*ToolRegistry) GetToolConfig ¶
func (r *ToolRegistry) GetToolConfig(name string) (ToolConfig, bool)
GetToolConfig returns the ToolConfig for the given tool name. Returns the config and true if found, or zero-value and false if not.
func (*ToolRegistry) IsInteractive ¶
func (r *ToolRegistry) IsInteractive(name string) bool
IsInteractive reports whether the named tool is registered with Interactive=true. Unknown tools return false. Use this from CLI subscribers (e.g. the activity-indicator goroutine) to decide whether to suppress transient chrome that would clobber the tool's own prompt.
func (*ToolRegistry) RegisterTool ¶
func (r *ToolRegistry) RegisterTool(config ToolConfig)
RegisterTool adds a tool to the registry
type TrackedBulkItem ¶ added in v0.16.2
type TrackedBulkItem struct {
FilePath string `json:"file_path"`
OriginalCode string `json:"original_code"`
NewCode string `json:"new_code"`
Operation string `json:"operation"` // "create" | "edit" | "delete"
}
TrackedBulkItem is the per-file payload packed inside a bulk TrackedFileChange. Shape mirrors TrackedFileChange's recoverable fields so the recovery helpers (`isRecoverableOriginal`, `restoreFile`) can be reused without translation.
type TrackedFileChange ¶
type TrackedFileChange struct {
FilePath string `json:"file_path"`
OriginalCode string `json:"original_code"`
NewCode string `json:"new_code"`
Operation string `json:"operation"` // "write", "edit", "create", "delete", "bulk"
Timestamp time.Time `json:"timestamp"`
ToolCall string `json:"tool_call"` // Which tool was used
// BulkCount is set on a rollup entry produced when a single shell
// command churns more than the bulk threshold — typical of
// `make build`, `npm ci`, `cargo build`, or `git checkout .`.
// FilePath then names the directory or command label (workspace-
// relative, trailing "/") and Operation is "bulk". When zero, the
// entry represents a normal single-file change. SP-061-1.
BulkCount int `json:"bulk_count,omitempty"`
// BulkItems carries the per-file recovery payload for bulk entries.
// Populated when the bulk fits inside the walk's content budget
// (~32 MiB). When present, recover_file can match a specific path
// inside the bulk and recover_bulk can restore the whole set.
// Empty when the bulk row is count-only (build-output rollup that
// the user said is cheap to regenerate, or destructive bulk that
// blew through the memory cap).
BulkItems []TrackedBulkItem `json:"bulk_items,omitempty"`
}
TrackedFileChange represents a file change made during agent execution
type TurnCheckpoint ¶
type TurnCheckpoint struct {
StartIndex int `json:"start_index"`
EndIndex int `json:"end_index"`
Summary string `json:"summary"`
ActionableSummary string `json:"actionable_summary,omitempty"`
// FileChanges is the git-style manifest (M/A/D/R) of files touched
// during this turn. Populated from the agent's ChangeTracker at
// checkpoint-record time. Empty when tracking is disabled or the turn
// didn't write any files.
FileChanges []CheckpointFileChange `json:"file_changes,omitempty"`
// RevisionID is the ChangeTracker revision that was active when this
// turn ran. When set, the summary text references it so the model can
// call the view_history tool to recover the exact diff. Empty when
// tracking is disabled.
RevisionID string `json:"revision_id,omitempty"`
}
TurnCheckpoint stores a compact summary for a completed user turn while preserving the original full messages for cache-efficient reuse until needed.
type TurnEvaluation ¶
type TurnEvaluation struct {
Iteration int
Timestamp time.Time
UserInput string
AssistantContent string
ToolCalls []api.ToolCall
ToolResults []api.Message
TokenUsage TokenUsage
CompletionReached bool
FinishReason string
ReasoningSnippet string
GuardrailTrigger string
}
TurnEvaluation captures the inputs, outputs, and tool activity for each iteration
type UI ¶
type UI interface {
// ShowDropdown displays a dropdown selection UI
ShowDropdown(ctx context.Context, items interface{}, options DropdownOptions) (interface{}, error)
// ShowQuickPrompt shows a small prompt with quick choices
ShowQuickPrompt(ctx context.Context, prompt string, options []QuickOption, horizontal bool) (QuickOption, error)
// IsInteractive returns true if UI is available
IsInteractive() bool
}
UI provides UI capabilities to the agent
type WorkspaceFileMetadata ¶
type WorkspaceFileMetadata struct {
// BrowserSeq counts user-driven edits to the file from the browser side.
// Bumped each time the user types and the change flushes to OPFS.
BrowserSeq int64 `json:"browser_seq"`
// ContainerSeq counts agent-driven writes to the file via the agent's
// tool handlers. Bumped each time writeFileContent succeeds.
ContainerSeq int64 `json:"container_seq"`
// LastSyncedBrowser is the BrowserSeq value the container has
// acknowledged. BrowserSeq > LastSyncedBrowser means the browser has
// unsynced edits — see the conflict rule.
LastSyncedBrowser int64 `json:"last_synced_browser"`
// LastSyncedContainer is the ContainerSeq value the browser has
// acknowledged.
LastSyncedContainer int64 `json:"last_synced_container"`
// ModifiedAt is the wall-clock time of the most recent write to the
// file from any source. Used by the staleness rule's "recent
// modification" check.
ModifiedAt time.Time `json:"modified_at"`
}
WorkspaceFileMetadata describes the per-file sync state that the browser-primary workspace model in SP-046 needs to enforce consistency between the browser-side OPFS replica and the container-side filesystem.
On native sprout (single-replica), only ModifiedAt and the agent's turn-scoped read tracking actually matter. The sequence fields are placeholders for the eventual WS-based sync layer to populate from the browser side; until then they're zero. Storing the struct now (rather than retrofitting later) keeps the persistence shape stable.
Spec: roadmap/SP-046-workspace-sync-model.md §3.
func (WorkspaceFileMetadata) HasUnsyncedBrowserEdits ¶
func (m WorkspaceFileMetadata) HasUnsyncedBrowserEdits() bool
HasUnsyncedBrowserEdits reports whether the browser side has writes the container hasn't applied yet. The agent's write_file tool wrapper refuses to overwrite such files without explicit user confirmation.
Source Files
¶
- agent.go
- agent_change_methods.go
- agent_creation.go
- agent_debug.go
- agent_embedding.go
- agent_events.go
- agent_getters.go
- agent_helpers.go
- agent_helpers_ansi.go
- agent_history.go
- agent_lifecycle.go
- agent_logger.go
- agent_prompt.go
- agent_provider.go
- agent_test_factory.go
- api_client_types.go
- approval_allowlist.go
- change_tracking.go
- change_tracking_shell.go
- change_tracking_shell_persist.go
- clarification_manager.go
- context_discovery.go
- conversation.go
- conversation_optimizer.go
- conversation_pruner.go
- conversation_turn.go
- conversation_types.go
- conversation_utils.go
- debug_log.go
- diff.go
- drift_detection.go
- drift_notification.go
- embedded_prompts.go
- errors.go
- github_url_router.go
- helpers_test_util.go
- input.go
- llm_summarizer.go
- mcp.go
- memory.go
- memory_embedding.go
- memory_handlers.go
- memory_manage.go
- memory_search_handler.go
- metrics.go
- models.go
- output_buffer.go
- output_router.go
- path_tier.go
- pause.go
- persistence.go
- persona.go
- proactive_context.go
- project_discovery.go
- provider_syntax.go
- pruning_config.go
- resource_capture.go
- retry.go
- risk_prompt.go
- scripted_dsl.go
- scripted_playback.go
- scripted_response_builder.go
- secret_prompter.go
- seed_integration.go
- seed_tool_registry.go
- self_review_tool.go
- session_info.go
- settings_handler.go
- shell.go
- shell_destructive.go
- shell_readonly.go
- simple_ui.go
- skills.go
- state.go
- state_test_helpers.go
- streaming.go
- subagent_runner.go
- subagent_types.go
- submanager_mcp.go
- submanager_output.go
- submanager_security.go
- submanager_state.go
- summary.go
- task_queue_manage.go
- theme.go
- token_utils.go
- tool_call_format.go
- tool_definitions.go
- tool_duplicates.go
- tool_execution_context.go
- tool_executor.go
- tool_executor_circuit_breaker.go
- tool_executor_config.go
- tool_executor_helpers.go
- tool_executor_parallel.go
- tool_executor_sequential.go
- tool_executor_todo_events.go
- tool_executor_trace.go
- tool_handlers.go
- tool_handlers_analysis.go
- tool_handlers_automate.go
- tool_handlers_browse.go
- tool_handlers_changes.go
- tool_handlers_file.go
- tool_handlers_history.go
- tool_handlers_interaction.go
- tool_handlers_recover.go
- tool_handlers_repo_map.go
- tool_handlers_request_clarification.go
- tool_handlers_respond_clarification.go
- tool_handlers_search.go
- tool_handlers_shell.go
- tool_handlers_structured.go
- tool_handlers_subagent.go
- tool_handlers_task_queue.go
- tool_handlers_todo.go
- tool_json_repair.go
- tool_registrations.go
- tool_registry.go
- tool_result_constraint.go
- tool_security.go
- tool_validation.go
- tool_visibility.go
- tools.go
- turn_checkpoint_summary.go
- turn_checkpoints.go
- turn_embedding.go
- types.go
- ui.go
- ui_choice.go
- ui_types.go
- utils.go
- workspace_sync.go