Documentation
¶
Overview ¶
Package utils provides error handling utilities and conventions for the codebase. This file documents the project's error handling conventions.
Package utils provides error handling utilities and conventions for the codebase.
This package implements a comprehensive error handling system with: - StructuredError: Rich error type with code, severity, category, and context - Helper functions for creating typed errors (system, network, validation, etc.) - Error utilities for checking, formatting, and wrapping errors
For detailed error handling conventions, see:
- pkg/utils/error_handling_convention.go - Full documentation of patterns
Quick Reference:
- Wrap errors with context: fmt.Errorf("context: %w", err)
- Standalone errors: errors.New("message")
- Secondary error context: fmt.Errorf("primary: %w (debug: %v)", primary, secondary)
See StructuredError for the main error type and its methods.
Index ¶
- Constants
- Variables
- func CapitalizeWords(s string) string
- func ClearLine()
- func ClearScreen()
- func CreateBackup(filePath string) error
- func DefaultChoiceHint(defaultYes bool) string
- func EstimateTokens(text string) int
- func ExtractJSON(input string) (string, error)
- func FormatError(err error) string
- func FormatFileSize(size int64) string
- func GenerateFileRevisionHash(filename, code string) string
- func GenerateRequestHash(instructions string) string
- func GetAllProviderLimiters() map[string]TokenBucketInfo
- func GetCurrentTimestamp() int64
- func GetTimestamp() string
- func HideCursor()
- func IsCriticalError(err error) bool
- func IsEmptyString(s string) bool
- func IsNetworkError(err error) bool
- func IsValidFileExtension(filename string, allowedExtensions []string) bool
- func IsValidationError(err error) bool
- func LogLLMResponse(filename, response string)
- func LogUserPrompt(prompt string)
- func MoveCursor(row, col int)
- func ReadLineWithTimeout(reader *bufio.Reader, d time.Duration) (string, error)
- func RemoveProviderRateLimiter(providerName string)
- func RestoreCursorPosition()
- func SaveCursorPosition()
- func SetProviderRate(providerName string, rate float64, burst int)
- func ShowCursor()
- func SplitTopLevelJSONObjects(s string) []string
- func StringSliceEqual(a, b []string) bool
- func TruncateString(s string, maxLength int) string
- func ValidateJSONFields(jsonStr string, requiredFields []string) error
- func WrapError(err error, message string) error
- type ApprovalChoice
- type DiffOptimizer
- type ErrorCategory
- type ErrorContext
- type ErrorSeverity
- type FileChangeSummary
- type FilesystemPromptTier
- type Logger
- func (w *Logger) AskForApprovalWithOptions(prompt, command string, analysis *SecurityAnalysisView) ApprovalChoice
- func (w *Logger) AskForConfirmation(prompt string, default_response bool, required bool) bool
- func (w *Logger) AskForFilesystemApproval(prompt, path, folder string, tier FilesystemPromptTier) ApprovalChoice
- func (w *Logger) Close() error
- func (w *Logger) IsInteractive() bool
- func (w *Logger) Log(message string)
- func (w *Logger) LogAnalysisResult(filePath, success, summary, err string)
- func (w *Logger) LogError(err error)
- func (w *Logger) LogProcessStep(step string)
- func (w *Logger) LogUserInteraction(message string)
- func (w *Logger) LogWorkspaceOperation(operation, details string)
- func (w *Logger) Logf(format string, v ...interface{})
- type OptimizedDiffResult
- type ProviderRateLimiter
- type RateLimitBackoff
- func (rlb *RateLimitBackoff) CalculateBackoffDelay(resp *http.Response, attempt int) time.Duration
- func (rlb *RateLimitBackoff) IsRateLimitError(err error, resp *http.Response) bool
- func (rlb *RateLimitBackoff) LogRateLimit(provider, model string, totalTokens int, err error, resp *http.Response)
- func (rlb *RateLimitBackoff) SetOutputFunc(fn func(string))
- func (rlb *RateLimitBackoff) ShouldRetry(attempt int) bool
- func (rlb *RateLimitBackoff) WaitWithProgress(duration time.Duration, provider string)
- type ReviewFileClass
- type RunLogger
- type SecurityAnalysisView
- type StructuredError
- func NewConfigError(key string, rootCause error) *StructuredError
- func NewExecutionError(component, operation string, rootCause error) *StructuredError
- func NewFileSystemError(operation, path string, rootCause error) *StructuredError
- func NewNetworkError(operation string, rootCause error) *StructuredError
- func NewStructuredError(code, message string, severity ErrorSeverity, category ErrorCategory, ...) *StructuredError
- func NewSystemError(operation string, rootCause error) *StructuredError
- func NewUserError(message string, rootCause error) *StructuredError
- func NewValidationError(field, reason string) *StructuredError
- func (e *StructuredError) Error() string
- func (e *StructuredError) GetCategory() ErrorCategory
- func (e *StructuredError) GetCode() string
- func (e *StructuredError) GetContext() *ErrorContext
- func (e *StructuredError) GetSeverity() ErrorSeverity
- func (e *StructuredError) GetStackTrace() string
- func (e *StructuredError) IsRecoverable() bool
- func (e *StructuredError) MakeUnrecoverable() *StructuredError
- func (e *StructuredError) Unwrap() error
- func (e *StructuredError) WithComponent(component string) *StructuredError
- func (e *StructuredError) WithContext(ctx *ErrorContext) *StructuredError
- func (e *StructuredError) WithMetadata(key string, value interface{}) *StructuredError
- func (e *StructuredError) WithOperation(operation string) *StructuredError
- func (e *StructuredError) WithResource(resource string) *StructuredError
- type TerminalSize
- type TokenBucket
- func (tb *TokenBucket) GetAvailableTokens() float64
- func (tb *TokenBucket) GetBurst() int
- func (tb *TokenBucket) GetRate() float64
- func (tb *TokenBucket) Refund()
- func (tb *TokenBucket) TryWait() bool
- func (tb *TokenBucket) UpdateRate(rate float64, burst int)
- func (tb *TokenBucket) Wait(ctx context.Context) error
- type TokenBucketInfo
Constants ¶
const ApprovalPromptTimeout = 30 * time.Minute
ApprovalPromptTimeout bounds how long an interactive security prompt — the CLI yes/no confirmation, the 4-option approval menu, the filesystem approval menu, and the pkg/console arrow-key picker — blocks waiting for the user before it gives up and denies for safety.
It mirrors security.DefaultTimeout (the WebUI event-bus wait, also 30 min) so a user gets the same grace window whether the prompt renders in the terminal or the browser. We keep the value here rather than importing pkg/security so pkg/utils stays leaf-level.
A finite bound is the fix for the "agent wedged forever / terminal stuck in raw mode" failure: when stdin is open but idle (the user walked away, or the harness isn't forwarding keystrokes), the old readers blocked indefinitely and the raw-mode picker never restored the terminal. Now every surface releases stdin, restores cooked mode, and surfaces a clear timeout deny.
The previous 5-minute value was too short for a human reviewing a complex command (terraform plan, a long migration script). 30 minutes matches the webui default and was deliberately chosen there because "a false-deny after 5 minutes was a recurring UX complaint" — the same applies to the CLI surface.
Variables ¶
var ErrPromptTimeout = errors.New("prompt timed out waiting for input")
ErrPromptTimeout is returned by ReadLineWithTimeout when no line arrives within the deadline. Callers treat it as a deny-for-safety signal, distinct from a genuine read error (closed stdin).
var FilesystemSecurityPromptHook func(prompt, path, folder string, tier FilesystemPromptTier) ApprovalChoice
FilesystemSecurityPromptHook is the matching hook for AskForFilesystemApproval. Same registration pattern as SecurityPromptHook. Filesystem approvals do not currently produce LLM analyses (only shell_command does), so the hook signature stays unchanged.
var SecurityPromptHook func(prompt, command string, analysis *SecurityAnalysisView) ApprovalChoice
SecurityPromptHook, when non-nil, replaces the line-based key entry in AskForApprovalWithOptions with an interactive picker (arrow-key SelectList in pkg/console). Registered at pkg/console init() time. Leaving the hook nil keeps the legacy "y/n/a/e" path so this package stays leaf-level — no upward dependency on pkg/console.
SP-124 Phase 3: the hook now receives an optional LLM-derived analysis (nil when the analyzer timed out, errored, or wasn't produced). The arrow-key picker renders this above the option list so the user sees the LLM's plain-language summary before deciding. The legacy line-based prompt ignores the analysis when it falls back (no styling available).
Functions ¶
func CapitalizeWords ¶
CapitalizeWords capitalizes the first letter of each word in a string.
func CreateBackup ¶
CreateBackup creates a timestamped backup of a file. It reads the content of the file at filePath, and saves it to a backup directory (.sprout/backups) with a timestamped filename.
func DefaultChoiceHint ¶
DefaultChoiceHint builds the "Y/n" or "y/N" tail for a confirmation prompt, with the default letter rendered in bold ANSI when color output is allowed (honors NO_COLOR / FORCE_COLOR via console.ResolveColorPreference). Hitting Enter on an empty response is currently rejected by the loop, so the visual hint also communicates to the user that the capitalized letter is the safe choice to type explicitly.
func EstimateTokens ¶
EstimateTokens provides a rough estimate of the number of tokens in a given text. This is a simple character-based estimation (e.g., 4 chars per token) and may not be accurate for all models or languages, but provides a general idea for prompt length management.
func ExtractJSON ¶
ExtractJSON extracts JSON from any source (LLM responses, plain text, markdown, etc.) This is the primary JSON extraction function that handles all common scenarios: - Plain JSON objects/arrays - Markdown code blocks (```json, ```) - Multiple extraction strategies with fallbacks - Robust error handling and validation
func FormatFileSize ¶
FormatFileSize converts a file size in bytes to a human-readable string (e.g., "1.2 MB", "345 KB").
func GenerateFileRevisionHash ¶
GenerateFileRevisionHash generates a SHA256 hash for a file based on its name and code content.
func GenerateRequestHash ¶
GenerateRequestHash generates a SHA256 hash for a given set of instructions.
func GetAllProviderLimiters ¶
func GetAllProviderLimiters() map[string]TokenBucketInfo
GetAllProviderLimiters returns a snapshot of all provider limiters and their settings. This is useful for debugging and monitoring.
func GetCurrentTimestamp ¶
func GetCurrentTimestamp() int64
GetCurrentTimestamp returns the current timestamp
func GetTimestamp ¶
func GetTimestamp() string
GetTimestamp returns a formatted timestamp string suitable for filenames.
func IsCriticalError ¶
IsCriticalError checks if an error is critical
func IsNetworkError ¶
IsNetworkError checks if an error is network-related
func IsValidFileExtension ¶
IsValidFileExtension checks if the given filename has one of the allowed extensions. Extensions should be provided with a leading dot, e.g., ".go", ".txt".
func IsValidationError ¶
IsValidationError checks if an error is validation-related
func LogLLMResponse ¶
func LogLLMResponse(filename, response string)
LogLLMResponse logs the LLM's response to a file in the .sprout/llm_responses directory.
func LogUserPrompt ¶
func LogUserPrompt(prompt string)
LogUserPrompt logs the user's original prompt to a file in the .sprout/prompts directory.
func MoveCursor ¶
func MoveCursor(row, col int)
MoveCursor moves the cursor to the specified position (1-based)
func ReadLineWithTimeout ¶ added in v0.16.7
ReadLineWithTimeout reads a single newline-terminated line from reader, returning ErrPromptTimeout if nothing arrives within d.
The blocking ReadString runs in a goroutine. On timeout the goroutine is left to resolve on its own (it completes when a line eventually arrives or stdin closes). Callers MUST return after a timeout rather than loop with the same reader, so at most one read goroutine is ever outstanding per reader — overlapping ReadString calls on one bufio.Reader would race.
func RemoveProviderRateLimiter ¶
func RemoveProviderRateLimiter(providerName string)
RemoveProviderRateLimiter removes the rate limiter for a specific provider. This is primarily useful for testing.
func RestoreCursorPosition ¶
func RestoreCursorPosition()
RestoreCursorPosition restores the saved cursor position
func SaveCursorPosition ¶
func SaveCursorPosition()
SaveCursorPosition saves the current cursor position
func SetProviderRate ¶
SetProviderRate sets or updates the rate and burst for a specific provider. Provider names are case-insensitive. This can be used to override default rates based on configuration.
func SplitTopLevelJSONObjects ¶
SplitTopLevelJSONObjects splits a string containing multiple concatenated top-level JSON objects It properly handles string escaping and nested braces/brackets
func StringSliceEqual ¶
StringSliceEqual checks if two string slices are equal, ignoring order.
func TruncateString ¶
TruncateString truncates a string to a specified maximum length, appending "..." if truncation occurs.
func ValidateJSONFields ¶
ValidateJSONFields validates that a JSON string contains the required fields This is useful for ensuring API responses have expected structure
Types ¶
type ApprovalChoice ¶
type ApprovalChoice int
ApprovalChoice is the typed result of AskForApprovalWithOptions — the 4-option CLI prompt that lets the user respond to a security gate with Deny / Approve once / Always approve / Elevate.
Defined here (not in pkg/security) so pkg/utils can stay leaf-level — the agent layer maps this to security.ApprovalDecision at the callsite.
const ( // ApprovalChoiceDeny rejects the operation. ApprovalChoiceDeny ApprovalChoice = iota // ApprovalChoiceApproveOnce allows this single invocation. ApprovalChoiceApproveOnce // ApprovalChoiceApproveAlways allows this invocation and persists // the command to the user's allowlist (Config.ApprovedShellCommands). ApprovalChoiceApproveAlways // ApprovalChoiceElevate allows this invocation and sets the session // risk-profile override to permissive. ApprovalChoiceElevate // ApprovalChoiceAllowFolderSession allows this invocation and adds // the prompt's target folder to the agent's session-allowed list, // auto-approving future accesses under that folder. Only offered // for the External filesystem tier. ApprovalChoiceAllowFolderSession // ApprovalChoiceAlwaysAsk approves this invocation and persists // the command as an "ask" rule in Config.CommandPolicies so future // matching commands always force an interactive prompt. SP-123-2b. ApprovalChoiceAlwaysAsk )
type DiffOptimizer ¶
type DiffOptimizer struct {
// Configuration for optimization thresholds
MaxDiffLines int // Maximum lines to include in full diff
MaxFileSize int // Maximum file size in bytes for full content
LargeFileExtensions []string // File extensions considered as large files
LockFilePatterns []string // Patterns for lock files
GeneratedFilePatterns []string // Patterns for generated files
WorkingDir string // Working directory for git commands (optional)
}
DiffOptimizer provides utilities for optimizing diff content for API endpoints
func NewDiffOptimizer ¶
func NewDiffOptimizer() *DiffOptimizer
NewDiffOptimizer creates a new diff optimizer with default settings
func NewDiffOptimizerForReview ¶
func NewDiffOptimizerForReview() *DiffOptimizer
NewDiffOptimizerForReview creates a diff optimizer optimized for code review This uses much higher thresholds to ensure reviewers get full context
func (*DiffOptimizer) OptimizeDiff ¶
func (do *DiffOptimizer) OptimizeDiff(diff string) *OptimizedDiffResult
OptimizeDiff optimizes a git diff by replacing large files with summaries
type ErrorCategory ¶
type ErrorCategory int
ErrorCategory represents the category of an error
const ( CategorySystem ErrorCategory = iota CategoryNetwork CategoryFileSystem CategoryConfiguration CategoryValidation CategoryExecution CategoryUser )
type ErrorContext ¶
type ErrorContext struct {
Component string
Operation string
UserID string
RequestID string
Resource string
Metadata map[string]interface{}
}
ErrorContext provides additional context for errors
type ErrorSeverity ¶
type ErrorSeverity int
ErrorSeverity represents the severity level of an error
const ( SeverityLow ErrorSeverity = iota SeverityMedium SeverityHigh SeverityCritical )
type FileChangeSummary ¶
FileChangeSummary tracks changes in a file
type FilesystemPromptTier ¶
type FilesystemPromptTier int
FilesystemPromptTier picks the option set for the filesystem approval prompt. PathTierExternal gets 3 options (Allow once / Allow folder this session / Deny); PathTierSensitive gets 2 (Allow once / Deny) — sensitive paths can never be session- allowlisted because they're system or off-CWD home files.
const ( // FilesystemPromptExternal — Tier B, 3 options including // "Allow this folder for the rest of the session". FilesystemPromptExternal FilesystemPromptTier = iota // FilesystemPromptSensitive — Tier C, 2 options. The "Allow // folder this session" choice is suppressed. FilesystemPromptSensitive )
type Logger ¶
type Logger struct {
// contains filtered or unexported fields
}
Logger represents a workspace logger.
func GetLogger ¶
GetLogger returns the singleton instance of Logger. It initializes the logger with a file handler that rotates logs. The skipPrompts parameter determines if user interaction is enabled. This value can be overridden on subsequent calls to GetLogger.
func (*Logger) AskForApprovalWithOptions ¶
func (w *Logger) AskForApprovalWithOptions(prompt, command string, analysis *SecurityAnalysisView) ApprovalChoice
AskForApprovalWithOptions prompts the user with a 4-option menu for a high-risk shell command. Returns the chosen ApprovalChoice. On stdin unavailable / non-interactive, returns ApprovalChoiceDeny for safety.
The prompt renders the command on its own line so the user can see what they're approving, then lists the four options with single-letter keys. The Elevate option carries an inline disclaimer so users understand they're loosening the gate for the rest of the session, not forever.
SP-124 Phase 3: when an LLM-derived analysis is supplied (analyzer succeeded within its timeout), the hook renders the summary, modifies, and color-coded recommendation above the picker. The legacy line-based fallback (no arrow-key picker registered) ignores the analysis — its styling surface is too limited to do it justice and a brief "y/n/a/s/e" prompt already conveys the risk.
func (*Logger) AskForConfirmation ¶
AskForConfirmation prompts the user with a message and waits for a 'yes' or 'no' response. It returns true for 'yes' and false for 'no'.
func (*Logger) AskForFilesystemApproval ¶
func (w *Logger) AskForFilesystemApproval(prompt, path, folder string, tier FilesystemPromptTier) ApprovalChoice
AskForFilesystemApproval prompts the user about an out-of-workspace filesystem access. The option set depends on tier:
FilesystemPromptExternal: 3 options — Allow once / Allow this folder for the rest of the session / Deny. Picking the folder option causes the agent to persist `folder` to its session allowlist so future paths under it auto-approve.
FilesystemPromptSensitive: 2 options — Allow once / Deny. System paths and off-CWD home paths cannot be session-allow- listed; the dialog calls this out so the user understands why they'll keep seeing the prompt.
On stdin unavailable / non-interactive, returns ApprovalChoiceDeny. `path` is the file being accessed; `folder` is the directory the agent would add to the allowlist if the user picks the folder option (typically the parent dir of `path`).
func (*Logger) IsInteractive ¶
IsInteractive returns true if user interaction is enabled
func (*Logger) LogAnalysisResult ¶
LogAnalysisResult logs analysis results. These messages go only to the log file.
func (*Logger) LogProcessStep ¶
LogProcessStep logs the current step in a process.
func (*Logger) LogUserInteraction ¶
LogUserInteraction logs user interactions that require a response, and prints to stdout.
func (*Logger) LogWorkspaceOperation ¶
LogWorkspaceOperation logs workspace operations. These messages go only to the log file.
type OptimizedDiffResult ¶
type OptimizedDiffResult struct {
OptimizedContent string // The optimized diff content
FileSummaries map[string]string // Summary for each optimized file
Warnings []string // Warnings about suspicious optimized files
OriginalLines int // Original number of lines
OptimizedLines int // Optimized number of lines
BytesSaved int // Estimated bytes saved
}
OptimizedDiffResult represents the result of diff optimization
type ProviderRateLimiter ¶
type ProviderRateLimiter struct {
// contains filtered or unexported fields
}
ProviderRateLimiter manages a global registry of token buckets per provider. This ensures that all requests to the same provider are rate limited together, preventing cascading 429 errors when multiple subagents are running concurrently.
type RateLimitBackoff ¶
type RateLimitBackoff struct {
MaxRetries int
BaseDelay time.Duration
MaxDelay time.Duration
BufferTime time.Duration
// contains filtered or unexported fields
}
RateLimitBackoff handles rate limit detection and backoff calculations
func NewRateLimitBackoff ¶
func NewRateLimitBackoff() *RateLimitBackoff
NewRateLimitBackoff creates a new rate limit backoff handler with sensible defaults
func (*RateLimitBackoff) CalculateBackoffDelay ¶
CalculateBackoffDelay calculates how long to wait before retrying
func (*RateLimitBackoff) IsRateLimitError ¶
func (rlb *RateLimitBackoff) IsRateLimitError(err error, resp *http.Response) bool
IsRateLimitError checks if an error or HTTP response indicates a rate limit
func (*RateLimitBackoff) LogRateLimit ¶
func (rlb *RateLimitBackoff) LogRateLimit(provider, model string, totalTokens int, err error, resp *http.Response)
LogRateLimit logs rate limit information for analysis
func (*RateLimitBackoff) SetOutputFunc ¶
func (rlb *RateLimitBackoff) SetOutputFunc(fn func(string))
SetOutputFunc overrides the default output function for user-facing messages
func (*RateLimitBackoff) ShouldRetry ¶
func (rlb *RateLimitBackoff) ShouldRetry(attempt int) bool
ShouldRetry determines if we should retry based on attempt count
func (*RateLimitBackoff) WaitWithProgress ¶
func (rlb *RateLimitBackoff) WaitWithProgress(duration time.Duration, provider string)
WaitWithProgress waits for the specified duration while showing progress
type ReviewFileClass ¶
type ReviewFileClass struct {
IsLockFile bool
IsGenerated bool
IsVendored bool
IsBinary bool
SkipForReview bool
}
func ClassifyReviewFile ¶
func ClassifyReviewFile(path string) ReviewFileClass
type RunLogger ¶
type RunLogger struct {
// contains filtered or unexported fields
}
RunLogger writes structured JSONL events for a single agent run.
func GetRunLogger ¶
func GetRunLogger() *RunLogger
GetRunLogger creates (once) and returns the run logger. Log file: .sprout/runlogs/run-YYYYmmdd_HHMMSS.jsonl
type SecurityAnalysisView ¶ added in v0.17.7
type SecurityAnalysisView struct {
// Summary is the LLM's one-sentence plain-language description
// of what the command does. Always populated when the analyzer
// succeeded; the worst case is a short sentence.
Summary string
// Modifies is a short description of what the command would
// modify (filesystem paths, network endpoints, system state).
// May be empty if the LLM did not flag anything specific.
Modifies string
// RiskAssessment is the LLM's own rating: "low", "moderate", or
// "high". Independent of the static classifier's risk level
// (SAFE/CAUTION/DANGEROUS) shown elsewhere in the prompt — the
// two often agree but can diverge on context-sensitive commands.
RiskAssessment string
// Recommendation is the LLM's suggested action: "approve",
// "review", or "reject". Drives the color-coded tone badge in
// the CLI panel ("✓ Looks safe" / "⚠ Review needed" /
// "✗ Recommend reject").
Recommendation string
// ChainLength is the number of subcommands in the analyzed chain.
// 0 for single-command analyses (regression-guard: legacy CLI/WebUI
// callers pass nil/zero and see no chain UI). SP-124b Phase 2.
ChainLength int
// ChainSubcommands are the per-subcommand strings (in order). Rendered
// as a stepper in CLI/WebUI when ChainLength > 1. SP-124b Phase 2.
ChainSubcommands []string
// ChainClassifications is the per-subcommand risk ("low"/"moderate"/
// "high"), parallel to ChainSubcommands. Drives the colored dots on
// the stepper. SP-124b Phase 2.
ChainClassifications []string
}
SecurityAnalysisView is the leaf-level mirror of pkg/agent.SecurityAnalysis.
pkg/utils is intentionally below pkg/agent in the dependency graph (pkg/agent imports pkg/utils, not the reverse), so the picker hook signature cannot take *pkg/agent.SecurityAnalysis directly without breaking the leaf-level contract. This struct duplicates just the four fields the CLI prompt needs to render the analysis panel above the 4-option picker.
pkg/agent converts its own SecurityAnalysis to this view at the call site (see pkg/agent/approval_broker.go and pkg/agent/seed_tool_security.go). Adding fields here is safe — old callers pass nil, new callers populate what they have.
type StructuredError ¶
type StructuredError struct {
Code string
Message string
Severity ErrorSeverity
Category ErrorCategory
Context *ErrorContext
RootCause error
StackTrace string
Timestamp int64
Recoverable bool
}
StructuredError represents a standardized error with rich context
func NewConfigError ¶
func NewConfigError(key string, rootCause error) *StructuredError
NewConfigError creates a configuration-related error
func NewExecutionError ¶
func NewExecutionError(component, operation string, rootCause error) *StructuredError
NewExecutionError creates an execution error
func NewFileSystemError ¶
func NewFileSystemError(operation, path string, rootCause error) *StructuredError
NewFileSystemError creates a filesystem-related error
func NewNetworkError ¶
func NewNetworkError(operation string, rootCause error) *StructuredError
NewNetworkError creates a network-related error
func NewStructuredError ¶
func NewStructuredError(code, message string, severity ErrorSeverity, category ErrorCategory, rootCause error) *StructuredError
NewStructuredError creates a new structured error
func NewSystemError ¶
func NewSystemError(operation string, rootCause error) *StructuredError
NewSystemError creates a system-level error
func NewUserError ¶
func NewUserError(message string, rootCause error) *StructuredError
NewUserError creates a user-facing error
func NewValidationError ¶
func NewValidationError(field, reason string) *StructuredError
NewValidationError creates a validation error
func (*StructuredError) Error ¶
func (e *StructuredError) Error() string
Error implements the error interface
func (*StructuredError) GetCategory ¶
func (e *StructuredError) GetCategory() ErrorCategory
GetCategory returns the error category
func (*StructuredError) GetCode ¶
func (e *StructuredError) GetCode() string
GetCode returns the error code
func (*StructuredError) GetContext ¶
func (e *StructuredError) GetContext() *ErrorContext
GetContext returns the error context
func (*StructuredError) GetSeverity ¶
func (e *StructuredError) GetSeverity() ErrorSeverity
GetSeverity returns the error severity
func (*StructuredError) GetStackTrace ¶
func (e *StructuredError) GetStackTrace() string
GetStackTrace returns the stack trace if available
func (*StructuredError) IsRecoverable ¶
func (e *StructuredError) IsRecoverable() bool
IsRecoverable checks if the error can be recovered from
func (*StructuredError) MakeUnrecoverable ¶
func (e *StructuredError) MakeUnrecoverable() *StructuredError
MakeUnrecoverable marks the error as unrecoverable
func (*StructuredError) Unwrap ¶
func (e *StructuredError) Unwrap() error
Unwrap returns the underlying error for compatibility with errors.Is and errors.As
func (*StructuredError) WithComponent ¶
func (e *StructuredError) WithComponent(component string) *StructuredError
WithComponent adds component context
func (*StructuredError) WithContext ¶
func (e *StructuredError) WithContext(ctx *ErrorContext) *StructuredError
WithContext adds context to the error
func (*StructuredError) WithMetadata ¶
func (e *StructuredError) WithMetadata(key string, value interface{}) *StructuredError
WithMetadata adds metadata to the error
func (*StructuredError) WithOperation ¶
func (e *StructuredError) WithOperation(operation string) *StructuredError
WithOperation adds operation context
func (*StructuredError) WithResource ¶
func (e *StructuredError) WithResource(resource string) *StructuredError
WithResource adds resource context
type TerminalSize ¶
TerminalSize represents the dimensions of the terminal
func GetTerminalSize ¶
func GetTerminalSize() (*TerminalSize, error)
GetTerminalSize returns the terminal size using multiple detection methods
type TokenBucket ¶
type TokenBucket struct {
// contains filtered or unexported fields
}
TokenBucket implements a thread-safe token bucket rate limiter. Tokens are added to the bucket at a constant rate, up to a maximum burst capacity. Requests must acquire a token from the bucket before proceeding.
The algorithm: - The bucket starts with 'burst' tokens. - Tokens are added at 'rate' tokens per second. - The bucket never exceeds 'burst' tokens. - A request waits until at least one token is available, then consumes one.
This implementation uses time.After for efficient waiting, avoiding busy-waiting. The nextReservation field is used to track when the next reserved token becomes available, preventing TOCTOU races when multiple goroutines wait concurrently.
func GetProviderRateLimiter ¶
func GetProviderRateLimiter(providerName string) *TokenBucket
GetProviderRateLimiter returns the rate limiter for the specified provider. If no limiter exists for the provider, one is created with default rates. Provider names are case-insensitive.
Default rates (tokens per second, burst): - openai: 1.0 tps (60 RPM), burst 5 - openrouter: 2.0 tps (120 RPM), burst 10 - deepinfra: 1.0 tps (60 RPM), burst 5 - deepseek: 0.5 tps (30 RPM), burst 3 - ollama/ollama-local/ollama-cloud: 10.0 tps (600 RPM), burst 20 - zai: 2.0 tps (120 RPM), burst 10 - chutes: 2.0 tps (120 RPM), burst 10 - lmstudio: 10.0 tps (600 RPM), burst 20 - mistral: 1.0 tps (60 RPM), burst 5 - cerebras: 2.0 tps (120 RPM), burst 10 - Default: 0.5 tps (30 RPM), burst 3
func NewTokenBucket ¶
func NewTokenBucket(rate float64, burst int) *TokenBucket
NewTokenBucket creates a new token bucket with the specified rate and burst capacity. rate: tokens per second (e.g., 1.0 = 1 token per second) burst: maximum number of tokens the bucket can hold
If rate <= 0 or burst <= 0, the bucket allows unlimited access.
func (*TokenBucket) GetAvailableTokens ¶
func (tb *TokenBucket) GetAvailableTokens() float64
GetAvailableTokens returns the approximate number of tokens currently available. This is useful for debugging and monitoring.
func (*TokenBucket) GetBurst ¶
func (tb *TokenBucket) GetBurst() int
GetBurst returns the current burst capacity.
func (*TokenBucket) GetRate ¶
func (tb *TokenBucket) GetRate() float64
GetRate returns the current rate (tokens per second).
func (*TokenBucket) Refund ¶
func (tb *TokenBucket) Refund()
Refund returns a previously consumed token to the bucket. This is useful when a rate-limited operation fails before using the capacity.
func (*TokenBucket) TryWait ¶
func (tb *TokenBucket) TryWait() bool
TryWait attempts to acquire a token without blocking. Returns true if a token was acquired, false if no token is available. If the bucket was configured with rate <= 0 or burst <= 0, TryWait returns true immediately.
func (*TokenBucket) UpdateRate ¶
func (tb *TokenBucket) UpdateRate(rate float64, burst int)
UpdateRate dynamically updates the rate and burst capacity. This is safe to call while other goroutines are using Wait/TryWait. Note: If there are pending reservations, they will be honored at the old rate. To immediately apply the new rate, you may want to reset the limiter.
func (*TokenBucket) Wait ¶
func (tb *TokenBucket) Wait(ctx context.Context) error
Wait blocks until a token is available, then consumes one. Returns an error if the context is canceled before a token becomes available. If the bucket was configured with rate <= 0 or burst <= 0, Wait returns immediately.
type TokenBucketInfo ¶
type TokenBucketInfo struct {
Rate float64 // tokens per second
Burst int // maximum tokens
AvailableTokens float64 // approximate tokens currently available
}
TokenBucketInfo contains information about a token bucket's state.
Source Files
¶
Directories
¶
| Path | Synopsis |
|---|---|
|
Package console provides Windows console utilities shared between pkg/automate (StopProcess escalation) and pkg/agent_tools (interruptProcessGroup).
|
Package console provides Windows console utilities shared between pkg/automate (StopProcess escalation) and pkg/agent_tools (interruptProcessGroup). |
|
Package pidalive provides a single canonical answer to "is this PID alive?" for all of sprout.
|
Package pidalive provides a single canonical answer to "is this PID alive?" for all of sprout. |