Documentation
¶
Index ¶
- Constants
- Variables
- func AutoFixPrompt(path, content string, errors []ValidationError) string
- func BuildCompactPrompt(variant CompactVariant) string
- func CollapseRepeatedMessages(msgs []client.EyrieMessage) []client.EyrieMessage
- func CompressForContext(text string, budget int) (string, int)
- func CountTokens(text string) int
- func CountTokensFast(text string) int
- func DecomposePrompt() string
- func DefaultCouncilModels() []string
- func DynamicMaxTokens(messages []client.EyrieMessage, contextSize int, taskType string) int
- func EstimateTokens(msgs []client.EyrieMessage) int
- func FormatCompactSummary(raw string) string
- func FormatCostDisplay(totalUSD float64) string
- func FormatResults(results []BackgroundResult) string
- func FormatTeachingMoment(action, reasoning string) string
- func LoadCostHistory() ([]analytics.CostEntry, error)
- func ModelPricing(modelName string) (inputPricePerM, outputPricePerM float64)
- func RemainingTime(ctx context.Context) string
- func SummarizeTrajectory(messages []client.EyrieMessage) string
- func TeachPromptAugment(depth int) string
- func TimeoutMessage(elapsed time.Duration) string
- func WithTimeout(ctx context.Context, cfg TimeoutConfig) (context.Context, context.CancelFunc)
- type APICompactConfig
- type APICompactStrategy
- type AdaptivePrompt
- type AutoCompactor
- func (ac *AutoCompactor) AutoCompactIfNeeded(ctx context.Context, sess *Session) (string, bool)
- func (ac *AutoCompactor) GetAutoCompactThreshold() int
- func (ac *AutoCompactor) LastStrategy() string
- func (ac *AutoCompactor) ResetFailures()
- func (ac *AutoCompactor) RunCompaction(ctx context.Context, sess *Session) (string, error)
- func (ac *AutoCompactor) ShouldAutoCompact(sess *Session) bool
- type AutonomyConfig
- type AutonomyLevel
- type BackgroundAgentPool
- func (p *BackgroundAgentPool) AllResults() []BackgroundResult
- func (p *BackgroundAgentPool) Collect() []BackgroundResult
- func (p *BackgroundAgentPool) HasPending() bool
- func (p *BackgroundAgentPool) PendingCount() int
- func (p *BackgroundAgentPool) Submit(id, prompt string, ...)
- func (p *BackgroundAgentPool) WaitAll() []BackgroundResult
- type BackgroundResult
- type BacktrackEngine
- func (be *BacktrackEngine) FindBacktrackPoint() *DecisionPoint
- func (be *BacktrackEngine) GenerateRetryPrompt(dp *DecisionPoint) string
- func (be *BacktrackEngine) MarkOutcome(turnIdx int, outcome string)
- func (be *BacktrackEngine) RecordDecision(turnIdx int, desc string, alternatives []string, msgs []client.EyrieMessage)
- func (be *BacktrackEngine) RestoreState(dp *DecisionPoint) []client.EyrieMessage
- func (be *BacktrackEngine) Size() int
- type Belief
- type BeliefState
- func (bs *BeliefState) FormatForPrompt() string
- func (bs *BeliefState) Get(subject string) []*Belief
- func (bs *BeliefState) Invalidate(subject string)
- func (bs *BeliefState) Prune(currentTurn int)
- func (bs *BeliefState) Record(category, subject, content string, turn int)
- func (bs *BeliefState) Size() int
- type CascadeRouter
- type CompactConfig
- type CompactResult
- type CompactStrategy
- type CompactVariant
- type ContextAllocation
- type ContextBudget
- type Cost
- type CostEntry
- type CostTracker
- type CostTrackerInterface
- type CouncilConfig
- type CouncilRanking
- type CouncilResponse
- type CouncilResult
- type Critic
- func (c *Critic) BuildPrompt(original, patched, intent string) string
- func (c *Critic) Model() string
- func (c *Critic) ParseVerdict(response string) *PatchVerdict
- func (c *Critic) PreScreenPatch(originalContent, patchedContent, intent string) *PatchVerdict
- func (c *Critic) ShouldBlock(verdict *PatchVerdict) bool
- type DecisionPoint
- type DiffSandbox
- func (ds *DiffSandbox) Apply(path string) error
- func (ds *DiffSandbox) ApplyAll() (int, error)
- func (ds *DiffSandbox) DiffAll() string
- func (ds *DiffSandbox) DiffFor(path string) string
- func (ds *DiffSandbox) Disable()
- func (ds *DiffSandbox) Enable()
- func (ds *DiffSandbox) Format() string
- func (ds *DiffSandbox) Get(path string) *PendingChange
- func (ds *DiffSandbox) IsEnabled() bool
- func (ds *DiffSandbox) List() []*PendingChange
- func (ds *DiffSandbox) Reject(path string)
- func (ds *DiffSandbox) RejectAll()
- func (ds *DiffSandbox) Stage(path, action, oldContent, newContent string)
- type ErrorPattern
- type ErrorPatternDB
- type EvolvingMemoryAdapter
- type EvolvingMemoryInterface
- type FewShotExample
- type FewShotStore
- type LLMClient
- type LimitTracker
- type LoopDetector
- func (ld *LoopDetector) DoomLoopWarning() string
- func (ld *LoopDetector) Escalated() bool
- func (ld *LoopDetector) IsDoomLoop() bool
- func (ld *LoopDetector) IsLooping() bool
- func (ld *LoopDetector) LoopWarning() string
- func (ld *LoopDetector) MarkEscalated()
- func (ld *LoopDetector) RecordStep(toolNames []string, inputs []string, outputs []string)
- func (ld *LoopDetector) Reset()
- type MemoryRecaller
- type MicroCompactConfig
- type MicroCompactStrategy
- type ModelTier
- type PatchVerdict
- type PendingChange
- type PermissionEngine
- type PermissionMemory
- func (pm *PermissionMemory) AllowSpec(spec string)
- func (pm *PermissionMemory) AlwaysAllow(toolName string)
- func (pm *PermissionMemory) AlwaysAllowPattern(pattern string)
- func (pm *PermissionMemory) AlwaysDeny(toolName string)
- func (pm *PermissionMemory) AlwaysDenyPattern(pattern string)
- func (pm *PermissionMemory) Check(toolName string, summary string) *bool
- func (pm *PermissionMemory) DenySpec(spec string)
- type PermissionMode
- type PermissionRequest
- type PlanState
- type PromptAdjustment
- type PromptTuner
- type PromptVariant
- type ProtectedPaths
- type Reflection
- type Reflector
- type RoutingDecision
- type SafetyLimits
- type SelfReviewResult
- type Session
- func (s *Session) AddAssistant(content string)
- func (s *Session) AddUser(content string)
- func (s *Session) AppendSystemContext(content string)
- func (s *Session) AutoCompactIfNeeded() bool
- func (s *Session) Compact()
- func (s *Session) ConvoHead() string
- func (s *Session) ForkConversation(nodeID string) (string, error)
- func (s *Session) ListBranches(nodeID string) ([]*convodag.Node, error)
- func (s *Session) LoadMessages(msgs []client.EyrieMessage)
- func (s *Session) MessageCount() int
- func (s *Session) Metrics() *metrics.Registry
- func (s *Session) Model() string
- func (s *Session) Provider() string
- func (s *Session) RawMessages() []client.EyrieMessage
- func (s *Session) RemoveLastExchange()
- func (s *Session) SetAPIKey(provider, apiKey string)
- func (s *Session) SetAPIKeys(apiKeys map[string]string)
- func (s *Session) SetAllowedDirs(dirs []string)
- func (s *Session) SetLogger(l *logger.Logger)
- func (s *Session) SetMaxBudgetUSD(amount float64) error
- func (s *Session) SetMaxTurns(turns int) error
- func (s *Session) SetModel(model string)
- func (s *Session) SetPermissionMode(mode string) error
- func (s *Session) SetProvider(provider string)
- func (s *Session) ShouldAutoCompact() bool
- func (s *Session) SmartCompact()
- func (s *Session) Stream(ctx context.Context) (<-chan StreamEvent, error)
- func (s *Session) SwitchBranch(nodeID string) error
- func (s *Session) WireAgentTool()
- type SessionLifecycle
- type SessionMemoryConfig
- type SessionMemoryStrategy
- type SessionOutcome
- type ShadowWorkspace
- type SkillDistillerAdapter
- type SkillStoreInterface
- type SmartCompactStrategy
- type SnapshotCache
- type SnapshotTracker
- type SnowballDetector
- type StrategyRegistry
- type StreamEvent
- type StreamUsage
- type SubAgentMode
- type Subtask
- type TeachConfig
- type TimeoutConfig
- type TrajectoryDistiller
- type TrajectoryRun
- type TransferLearning
- type TransferPattern
- type TruncateStrategy
- type ValidationError
- type ValidationResult
Constants ¶
const ( DefaultExploreTurns = 15 DefaultGeneralTurns = 20 MaxAgentDepth = 2 )
Sub-agent budget defaults per mode.
const ConfidenceThreshold = 0.7
ConfidenceThreshold is the minimum confidence score for auto-approval. Below this, the review will not approve even if no issues are found.
const DefaultSnapshotTTL = 10 * time.Second
DefaultSnapshotTTL is the default time-to-live for snapshot cache entries.
const DoomLoopThreshold = 3
DoomLoopThreshold is the number of repeated patterns before escalation (matches OpenCode).
const MaxAutoFixRetries = 3
MaxAutoFixRetries is the maximum number of times to retry auto-fixing a file.
Variables ¶
var ExploreTools = []string{
"Glob", "Grep", "Read", "Bash", "LS",
}
ExploreTools are the read-only tools available to explore-mode sub-agents.
Functions ¶
func AutoFixPrompt ¶
func AutoFixPrompt(path, content string, errors []ValidationError) string
AutoFixPrompt returns a prompt instructing the LLM to fix syntax errors in a file.
func BuildCompactPrompt ¶
func BuildCompactPrompt(variant CompactVariant) string
BuildCompactPrompt constructs the full compaction prompt for LLM-based summarization.
func CollapseRepeatedMessages ¶
func CollapseRepeatedMessages(msgs []client.EyrieMessage) []client.EyrieMessage
CollapseRepeatedMessages finds and collapses similar consecutive messages to save context tokens. It collapses:
- 3+ consecutive tool_results with similar content into a summary
- Repeated error messages into a count
func CompressForContext ¶
CompressForContext compresses text to fit within a token budget, returning the compressed text and the final token count.
func CountTokens ¶
CountTokens returns a precise BPE-based token count for the given text.
func CountTokensFast ¶
CountTokensFast returns a fast heuristic token estimate for the given text.
func DecomposePrompt ¶
func DecomposePrompt() string
DecomposePrompt returns a system prompt that instructs the LLM to break a task into numbered subtasks with titles, descriptions, and file lists.
func DefaultCouncilModels ¶
func DefaultCouncilModels() []string
DefaultCouncilModels returns diverse models from different providers.
func DynamicMaxTokens ¶
func DynamicMaxTokens(messages []client.EyrieMessage, contextSize int, taskType string) int
DynamicMaxTokens calculates the optimal max_tokens for a request based on: - Whether the last few turns were tool-call-heavy (reduce to 4096) - Whether the user asked a question expecting text (8192) - Whether this is a code generation task (16384) - The remaining context budget (don't exceed model's limit)
Research basis: Output tokens are 3-5x more expensive than input tokens. Most tool-call turns only need 200-2000 tokens of output.
func EstimateTokens ¶
func EstimateTokens(msgs []client.EyrieMessage) int
EstimateTokens provides a rough token estimate for messages.
func FormatCompactSummary ¶
FormatCompactSummary strips the <analysis> drafting block and extracts the <summary> content.
func FormatCostDisplay ¶
FormatCostDisplay returns a compact cost string for the status bar.
func FormatResults ¶
func FormatResults(results []BackgroundResult) string
FormatResults formats background results for injection into the agent context.
func FormatTeachingMoment ¶
FormatTeachingMoment wraps agent output with teaching context.
func LoadCostHistory ¶
LoadHistory reads all historical cost entries from the JSONL file.
func ModelPricing ¶
ModelPricing returns input/output price per million tokens for a model.
func RemainingTime ¶
RemainingTime returns a formatted remaining-time string derived from the context deadline set by WithTimeout. If no deadline is set it returns an empty string.
func SummarizeTrajectory ¶
func SummarizeTrajectory(messages []client.EyrieMessage) string
SummarizeTrajectory extracts a concise summary from a sequence of messages: what was attempted, what failed, key decisions made, and files touched.
func TeachPromptAugment ¶
TeachPromptAugment returns a system prompt addition that instructs the agent to explain its reasoning at the given depth level.
func TimeoutMessage ¶
TimeoutMessage returns a user-friendly message when the time budget is exhausted.
func WithTimeout ¶
func WithTimeout(ctx context.Context, cfg TimeoutConfig) (context.Context, context.CancelFunc)
WithTimeout wraps a context with the total timeout and stores the deadline so that RemainingTime can report it.
Types ¶
type APICompactConfig ¶
type APICompactConfig struct {
TriggerTokens int
KeepTargetTokens int
ClearToolInputs bool
ClearThinking bool
PreserveMutating bool
}
APICompactConfig controls API-level compaction.
func DefaultAPICompactConfig ¶
func DefaultAPICompactConfig() APICompactConfig
DefaultAPICompactConfig returns defaults matching the archive.
type APICompactStrategy ¶
type APICompactStrategy struct{}
APICompactStrategy uses API-level context edits to clear thinking blocks and old tool inputs without mutating local message content.
func (*APICompactStrategy) Compact ¶
func (s *APICompactStrategy) Compact(ctx context.Context, sess *Session) (*CompactResult, error)
func (*APICompactStrategy) Name ¶
func (s *APICompactStrategy) Name() string
func (*APICompactStrategy) ShouldTrigger ¶
func (s *APICompactStrategy) ShouldTrigger(msgs []client.EyrieMessage, tokenCount, threshold int) bool
type AdaptivePrompt ¶
type AdaptivePrompt struct {
// contains filtered or unexported fields
}
AdaptivePrompt adjusts system prompt sections based on user corrections. When the user says "don't do X" or "always do Y", the adaptive prompt system records it and injects it into future sessions.
func NewAdaptivePrompt ¶
func NewAdaptivePrompt() *AdaptivePrompt
NewAdaptivePrompt creates an adaptive prompt backed by ~/.hawk/adaptive_prompt.json.
func (*AdaptivePrompt) Count ¶
func (ap *AdaptivePrompt) Count() int
Count returns the number of active adjustments.
func (*AdaptivePrompt) FormatForPrompt ¶
func (ap *AdaptivePrompt) FormatForPrompt() string
FormatForPrompt returns active adjustments as system prompt rules.
func (*AdaptivePrompt) LearnFromFeedback ¶
func (ap *AdaptivePrompt) LearnFromFeedback(userMessage string)
LearnFromFeedback extracts prompt adjustments from user corrections.
type AutoCompactor ¶
type AutoCompactor struct {
// contains filtered or unexported fields
}
AutoCompactor orchestrates compaction with circuit breaker protection.
func NewAutoCompactor ¶
func NewAutoCompactor(config CompactConfig) *AutoCompactor
NewAutoCompactor creates an auto-compactor with the given config.
func (*AutoCompactor) AutoCompactIfNeeded ¶
AutoCompactIfNeeded runs compaction if threshold is met. Returns the strategy name used and whether compaction occurred.
func (*AutoCompactor) GetAutoCompactThreshold ¶
func (ac *AutoCompactor) GetAutoCompactThreshold() int
GetAutoCompactThreshold returns the token count at which auto-compaction triggers.
func (*AutoCompactor) LastStrategy ¶
func (ac *AutoCompactor) LastStrategy() string
LastStrategy returns the name of the last strategy used.
func (*AutoCompactor) ResetFailures ¶
func (ac *AutoCompactor) ResetFailures()
ResetFailures resets the circuit breaker failure count.
func (*AutoCompactor) RunCompaction ¶
RunCompaction selects and executes the best compaction strategy.
func (*AutoCompactor) ShouldAutoCompact ¶
func (ac *AutoCompactor) ShouldAutoCompact(sess *Session) bool
ShouldAutoCompact determines if compaction is needed based on current state.
type AutonomyConfig ¶
type AutonomyConfig struct {
Level AutonomyLevel
AutoContinue bool
AutoApplyEdits bool
AutoExecuteBash bool
AutoCommit bool
}
AutonomyConfig holds the derived permission flags for an autonomy level.
func PresetConfig ¶
func PresetConfig(level AutonomyLevel) AutonomyConfig
PresetConfig returns the AutonomyConfig for a given level.
func (AutonomyConfig) NeedsPermission ¶
func (c AutonomyConfig) NeedsPermission(toolName string, isSafe bool) bool
NeedsPermission returns true when the tool call should prompt the user. isSafe indicates whether the specific invocation has been classified as safe (e.g. a non-destructive bash command).
type AutonomyLevel ¶
type AutonomyLevel int
AutonomyLevel controls how much the agent can do without asking the user.
const ( // AutonomySupervised asks for permission on every tool call. AutonomySupervised AutonomyLevel = 0 // AutonomyBasic auto-allows read-only tools. AutonomyBasic AutonomyLevel = 1 // AutonomySemi auto-allows reads and writes, asks for Bash. AutonomySemi AutonomyLevel = 2 // AutonomyFull auto-allows everything except destructive commands. AutonomyFull AutonomyLevel = 3 // AutonomyYOLO never asks for permission. AutonomyYOLO AutonomyLevel = 4 )
func ParseAutonomyLevel ¶
func ParseAutonomyLevel(s string) AutonomyLevel
ParseAutonomyLevel converts a string name or number to an AutonomyLevel.
func (AutonomyLevel) String ¶
func (l AutonomyLevel) String() string
String returns the human-readable name of an autonomy level.
type BackgroundAgentPool ¶
type BackgroundAgentPool struct {
// contains filtered or unexported fields
}
BackgroundAgentPool manages async sub-agents that run in the background. When background agents finish, their results are collected for re-injection into the main agent loop (inspired by herm's completion cycles).
func NewBackgroundAgentPool ¶
func NewBackgroundAgentPool() *BackgroundAgentPool
NewBackgroundAgentPool creates a pool with configurable wait limits.
func (*BackgroundAgentPool) AllResults ¶
func (p *BackgroundAgentPool) AllResults() []BackgroundResult
AllResults returns all results collected so far (completed background tasks).
func (*BackgroundAgentPool) Collect ¶
func (p *BackgroundAgentPool) Collect() []BackgroundResult
Collect gathers all completed background results without blocking. Returns immediately with whatever results are available.
func (*BackgroundAgentPool) HasPending ¶
func (p *BackgroundAgentPool) HasPending() bool
HasPending returns true if background agents are still running.
func (*BackgroundAgentPool) PendingCount ¶
func (p *BackgroundAgentPool) PendingCount() int
PendingCount returns the number of in-flight background agents.
func (*BackgroundAgentPool) Submit ¶
func (p *BackgroundAgentPool) Submit(id, prompt string, spawn func(ctx context.Context, prompt string) (string, error))
Submit launches a background sub-agent. The spawn function runs asynchronously.
func (*BackgroundAgentPool) WaitAll ¶
func (p *BackgroundAgentPool) WaitAll() []BackgroundResult
WaitAll blocks until all pending tasks complete or timeout.
type BackgroundResult ¶
type BackgroundResult struct {
ID string
Prompt string
Output string
Error error
Elapsed time.Duration
}
BackgroundResult holds the output of a completed background agent.
type BacktrackEngine ¶
type BacktrackEngine struct {
// contains filtered or unexported fields
}
BacktrackEngine records decision points during agent execution and provides the ability to identify the most recent failure and generate a retry prompt with alternative approaches.
func NewBacktrackEngine ¶
func NewBacktrackEngine() *BacktrackEngine
NewBacktrackEngine creates a new backtrack engine that retains at most 50 decision points.
func (*BacktrackEngine) FindBacktrackPoint ¶
func (be *BacktrackEngine) FindBacktrackPoint() *DecisionPoint
FindBacktrackPoint returns the most recent failed decision point that has alternative approaches available, or nil if none exists.
func (*BacktrackEngine) GenerateRetryPrompt ¶
func (be *BacktrackEngine) GenerateRetryPrompt(dp *DecisionPoint) string
GenerateRetryPrompt builds a prompt that tells the agent what failed and suggests alternative approaches.
func (*BacktrackEngine) MarkOutcome ¶
func (be *BacktrackEngine) MarkOutcome(turnIdx int, outcome string)
MarkOutcome sets the outcome ("success" or "failure") for the decision at the given turn index. If multiple decisions exist at the same turn index, the most recent one is updated.
func (*BacktrackEngine) RecordDecision ¶
func (be *BacktrackEngine) RecordDecision(turnIdx int, desc string, alternatives []string, msgs []client.EyrieMessage)
RecordDecision saves a decision point with the current conversation state. If the number of recorded points exceeds the maximum, the oldest point is removed.
func (*BacktrackEngine) RestoreState ¶
func (be *BacktrackEngine) RestoreState(dp *DecisionPoint) []client.EyrieMessage
RestoreState returns the conversation messages captured at the given decision point, representing the state just before (not including) the failed decision. This allows the agent to retry from that point.
func (*BacktrackEngine) Size ¶
func (be *BacktrackEngine) Size() int
Size returns the number of recorded decision points.
type Belief ¶
type Belief struct {
ID string
Category string // "file_purpose", "function_behavior", "dependency", "architecture"
Subject string // file or symbol name
Content string // what we believe about it
Confidence float64 // 0-1
DiscoveredAt int // turn index when discovered
LastVerified int // turn index when last confirmed
}
Belief represents a single piece of discovered knowledge about the codebase.
type BeliefState ¶
type BeliefState struct {
// contains filtered or unexported fields
}
BeliefState tracks what the agent has discovered about the codebase to prevent forgetting across long conversations. Beliefs are keyed by a generated ID.
func NewBeliefState ¶
func NewBeliefState() *BeliefState
NewBeliefState creates an empty belief state.
func (*BeliefState) FormatForPrompt ¶
func (bs *BeliefState) FormatForPrompt() string
FormatForPrompt returns a formatted string summarizing all current beliefs, suitable for injection into the system prompt.
func (*BeliefState) Get ¶
func (bs *BeliefState) Get(subject string) []*Belief
Get returns all beliefs about a given subject.
func (*BeliefState) Invalidate ¶
func (bs *BeliefState) Invalidate(subject string)
Invalidate marks all beliefs about a subject as stale by halving their confidence. This should be called when a file is modified, since our beliefs about it may no longer hold.
func (*BeliefState) Prune ¶
func (bs *BeliefState) Prune(currentTurn int)
Prune removes beliefs that have not been verified in the last 20 turns, keeping the belief state manageable in long conversations.
func (*BeliefState) Record ¶
func (bs *BeliefState) Record(category, subject, content string, turn int)
Record adds or updates a belief. If a belief with the same category and subject already exists, it is updated with the new content and turn index.
func (*BeliefState) Size ¶
func (bs *BeliefState) Size() int
Size returns the number of active beliefs.
type CascadeRouter ¶
type CascadeRouter struct {
Enabled bool
FrugalMode bool // more aggressive downgrading
DefaultModel string // fallback when classification is inconclusive
Roles routing.ModelRoles
// contains filtered or unexported fields
}
CascadeRouter selects the optimal model for each request based on task complexity. It uses pre-request classification (before we have a response) to route:
- simple/chat tasks -> cheap model (haiku)
- debug/review/refactor -> mid model (sonnet)
- generation -> expensive model (opus)
The router also tracks routing decisions for analytics.
func NewCascadeRouter ¶
func NewCascadeRouter(defaultModel string, roles routing.ModelRoles) *CascadeRouter
NewCascadeRouter creates a router with sensible defaults. The defaultModel is used as the fallback when classification yields no strong signal and no role-specific model is configured.
func (*CascadeRouter) DecisionCount ¶
func (cr *CascadeRouter) DecisionCount() int
DecisionCount returns how many routing decisions have been recorded.
func (*CascadeRouter) Decisions ¶
func (cr *CascadeRouter) Decisions() []RoutingDecision
Decisions returns a snapshot of all routing decisions made so far.
func (*CascadeRouter) Savings ¶
func (cr *CascadeRouter) Savings() float64
Savings estimates the USD saved by routing decisions compared to always using the most expensive model. This is a rough heuristic: it sums the per-million-token price difference for each decision where the selected model is cheaper than the original.
func (*CascadeRouter) SelectModel ¶
func (cr *CascadeRouter) SelectModel(prompt string, currentModel string, userOverride string) string
SelectModel picks the best model for a given prompt. If userOverride is non-empty the user's explicit choice always wins (override is never downgraded). The returned string is the model name to use for the API call.
func (*CascadeRouter) Summary ¶
func (cr *CascadeRouter) Summary() string
Summary returns a human-readable summary of routing activity.
type CompactConfig ¶
type CompactConfig struct {
AutoEnabled bool
ContextWindowSize int
AutoCompactBuffer int
MaxOutputTokens int
MaxFailures int
}
CompactConfig controls auto-compaction behavior.
func DefaultCompactConfig ¶
func DefaultCompactConfig() CompactConfig
DefaultCompactConfig returns sensible defaults matching the archive behavior.
type CompactResult ¶
type CompactResult struct {
Messages []client.EyrieMessage
Summary string
TokensBefore int
TokensAfter int
Strategy string
}
CompactResult holds the outcome of a compaction operation.
type CompactStrategy ¶
type CompactStrategy interface {
Name() string
ShouldTrigger(msgs []client.EyrieMessage, tokenCount, threshold int) bool
Compact(ctx context.Context, s *Session) (*CompactResult, error)
}
CompactStrategy defines a conversation compaction approach.
type CompactVariant ¶
type CompactVariant int
CompactVariant determines which compaction prompt style to use.
const ( CompactBase CompactVariant = iota // Full conversation CompactPartial // Recent messages only CompactUpTo // Prefix summarization )
type ContextAllocation ¶
type ContextAllocation struct {
SystemPrompt int
ToolDefs int
RepoMap int
Memory int
Workspace int
PreloadedFiles int
Conversation int
OutputReserve int
SafetyMargin int
Remaining int // should be ~0 if properly allocated
}
ContextAllocation shows where tokens are going for the current conversation state.
type ContextBudget ¶
type ContextBudget struct {
Total int // model's full context window
// Fixed allocations
SystemPrompt int // 3000-5000 tokens (rules, identity)
ToolDefs int // 2000-3000 tokens (tool descriptions)
RepoMap int // 2000-4000 tokens (ranked symbol map)
Memory int // 1000-2000 tokens (yaad/zenbrain context)
Workspace int // 500 tokens (git status, branch, recent commits)
// Adaptive allocations
PreloadedFiles int // 10000-30000 tokens (relevant code context)
Conversation int // remaining (managed by compaction)
// Reserved
OutputReserve int // 16000-20000 tokens (model response space)
SafetyMargin int // 10000-15000 tokens (estimation errors, API overhead)
}
ContextBudget allocates the model's context window across different content categories. Based on research: proper allocation prevents context overflow and optimizes information density per token spent.
The allocator ensures:
- Fixed allocations for system prompt, repo map, memory, workspace context
- Adaptive allocation for pre-loaded files (expands when conversation is short)
- Managed conversation history (triggers compaction when exceeded)
- Reserved budget for model output and safety margin
Research basis: All top coding agents (Claude Code, Cursor, Aider) manage context, but none formalize it as an explicit budget with categories. This is the missing architectural glue.
func NewContextBudget ¶
func NewContextBudget(contextSize int) *ContextBudget
NewContextBudget creates a budget for the given model context size. Allocations scale proportionally with the context window while respecting sensible floors and ceilings per category.
func (*ContextBudget) Allocate ¶
func (b *ContextBudget) Allocate(conversationTokens int) *ContextAllocation
Allocate distributes the budget based on current conversation length. As conversation grows, PreloadedFiles shrinks to make room.
func (*ContextBudget) FilesBudget ¶
func (b *ContextBudget) FilesBudget(conversationTokens int) int
FilesBudget returns the current budget available for pre-loaded file context.
func (*ContextBudget) ShouldCompact ¶
func (b *ContextBudget) ShouldCompact(conversationTokens int) bool
ShouldCompact returns true if conversation exceeds its allocation.
func (*ContextBudget) UsageReport ¶
func (b *ContextBudget) UsageReport(conversationTokens int) string
UsageReport returns a human-readable breakdown of current allocation.
type Cost ¶
type Cost struct {
Model string
PromptTokens int
CompletionTokens int
CacheReadTokens int
CacheWriteTokens int
TotalCostUSD float64
// contains filtered or unexported fields
}
Cost tracks token usage and estimated cost.
func (*Cost) AddCacheTokens ¶
AddCacheTokens records cache token usage (priced at ~10% of input).
type CostEntry ¶
type CostEntry struct {
SessionID string
TaskGoal string
TotalCost float64
Duration time.Duration
Success bool
Timestamp time.Time
}
CostEntry represents a single cost data point recorded at session end.
type CostTracker ¶
type CostTracker struct {
// contains filtered or unexported fields
}
CostTracker records per-request cost entries for analytics and optimization. Data is appended to ~/.hawk/cost.jsonl for cross-session analysis.
func NewCostTracker ¶
func NewCostTracker(sessionID string) *CostTracker
NewCostTracker creates a tracker that persists to ~/.hawk/cost.jsonl.
func (*CostTracker) Entries ¶
func (ct *CostTracker) Entries() []analytics.CostEntry
Entries returns all recorded entries for this session.
func (*CostTracker) Record ¶
func (ct *CostTracker) Record(entry analytics.CostEntry) error
Record adds a cost entry and persists it.
func (*CostTracker) SessionTotal ¶
func (ct *CostTracker) SessionTotal() float64
SessionTotal returns total USD spent in the current session.
type CostTrackerInterface ¶
CostTrackerInterface abstracts cost recording and querying.
type CouncilConfig ¶
type CouncilConfig struct {
Models []string // council member model names
Chairman string // chairman model (synthesizer)
}
CouncilConfig controls the Karpathy LLM Council pattern.
type CouncilRanking ¶
CouncilRanking holds one model's ranking of responses.
type CouncilResponse ¶
CouncilResponse holds one model's contribution.
type CouncilResult ¶
type CouncilResult struct {
Responses []CouncilResponse
Rankings []CouncilRanking
Synthesis string
}
CouncilResult holds the full council output.
func RunCouncil ¶
func RunCouncil(ctx context.Context, query string, cfg CouncilConfig, sess *Session) (*CouncilResult, error)
RunCouncil implements Karpathy's 3-stage LLM Council pattern:
- Send query to all models in parallel, collect responses
- Anonymize responses, send ranking prompt to all models in parallel
- Send all responses + rankings to chairman for synthesis
type Critic ¶
type Critic struct {
// contains filtered or unexported fields
}
Critic provides fast pre-validation of patches using a cheap model before expensive execution. It generates a prompt for the cheap model and parses the response into a structured verdict.
func (*Critic) BuildPrompt ¶
BuildPrompt constructs a prompt for the cheap model to evaluate a patch.
func (*Critic) ParseVerdict ¶
func (c *Critic) ParseVerdict(response string) *PatchVerdict
ParseVerdict parses a model response into a structured PatchVerdict.
func (*Critic) PreScreenPatch ¶
func (c *Critic) PreScreenPatch(originalContent, patchedContent, intent string) *PatchVerdict
PreScreenPatch asks the cheap model whether a patch looks correct given the stated intent. It builds a prompt, and returns a verdict. In this implementation, the caller is expected to send the prompt to the model and pass the response to ParseVerdict. This method constructs a PatchVerdict based on a simple heuristic comparison when no model call is available.
func (*Critic) ShouldBlock ¶
func (c *Critic) ShouldBlock(verdict *PatchVerdict) bool
ShouldBlock returns true if the verdict indicates the patch should be blocked (verdict is "incorrect" with confidence > 0.8).
type DecisionPoint ¶
type DecisionPoint struct {
TurnIndex int
Description string // what was decided
Alternatives []string // other options available
Outcome string // "success", "failure", or "" (pending)
Messages []client.EyrieMessage // conversation state at this point
}
DecisionPoint captures a point in the conversation where the agent made a choice that can potentially be rolled back if it leads to failure.
type DiffSandbox ¶
type DiffSandbox struct {
// contains filtered or unexported fields
}
DiffSandbox holds pending file changes so the user can review diffs before applying.
func NewDiffSandbox ¶
func NewDiffSandbox() *DiffSandbox
NewDiffSandbox creates a new, enabled DiffSandbox.
func (*DiffSandbox) Apply ¶
func (ds *DiffSandbox) Apply(path string) error
Apply writes one pending change to disk and removes it from the sandbox.
func (*DiffSandbox) ApplyAll ¶
func (ds *DiffSandbox) ApplyAll() (int, error)
ApplyAll writes all pending changes to disk and clears the sandbox.
func (*DiffSandbox) DiffAll ¶
func (ds *DiffSandbox) DiffAll() string
DiffAll returns all diffs combined.
func (*DiffSandbox) DiffFor ¶
func (ds *DiffSandbox) DiffFor(path string) string
DiffFor returns the unified diff for a single pending file.
func (*DiffSandbox) Format ¶
func (ds *DiffSandbox) Format() string
Format returns a human-readable summary of all pending changes.
func (*DiffSandbox) Get ¶
func (ds *DiffSandbox) Get(path string) *PendingChange
Get returns the pending change for a specific path, or nil.
func (*DiffSandbox) IsEnabled ¶
func (ds *DiffSandbox) IsEnabled() bool
IsEnabled returns whether the sandbox is active.
func (*DiffSandbox) List ¶
func (ds *DiffSandbox) List() []*PendingChange
List returns all pending changes sorted by path.
func (*DiffSandbox) Reject ¶
func (ds *DiffSandbox) Reject(path string)
Reject discards the pending change for one file.
func (*DiffSandbox) RejectAll ¶
func (ds *DiffSandbox) RejectAll()
RejectAll discards all pending changes.
func (*DiffSandbox) Stage ¶
func (ds *DiffSandbox) Stage(path, action, oldContent, newContent string)
Stage records a pending file change and computes a unified diff.
type ErrorPattern ¶
type ErrorPattern struct {
Trigger string `json:"trigger"` // error message pattern
RootCause string `json:"root_cause"` // why it happens
Resolution string `json:"resolution"` // how to fix it
HitCount int `json:"hit_count"` // times encountered
LastSeen time.Time `json:"last_seen"`
}
ErrorPattern records a known error trigger, root cause, and resolution.
type ErrorPatternDB ¶
type ErrorPatternDB struct {
// contains filtered or unexported fields
}
ErrorPatternDB learns from tool failures and prevents repeating mistakes.
func NewErrorPatternDB ¶
func NewErrorPatternDB() *ErrorPatternDB
NewErrorPatternDB creates a database backed by ~/.hawk/error_patterns.json.
func (*ErrorPatternDB) FormatHints ¶
func (db *ErrorPatternDB) FormatHints(errorMsg string) string
FormatHints returns actionable hints for an error from known patterns.
func (*ErrorPatternDB) Match ¶
func (db *ErrorPatternDB) Match(errorMsg string) []ErrorPattern
Match finds patterns that match the given error message.
func (*ErrorPatternDB) Record ¶
func (db *ErrorPatternDB) Record(trigger, rootCause, resolution string)
Record adds or updates an error pattern.
type EvolvingMemoryAdapter ¶
type EvolvingMemoryAdapter struct {
EM *memory.EvolvingMemory
}
EvolvingMemoryAdapter bridges memory.EvolvingMemory to the EvolvingMemoryInterface.
func (*EvolvingMemoryAdapter) Format ¶
func (a *EvolvingMemoryAdapter) Format() string
func (*EvolvingMemoryAdapter) Learn ¶
func (a *EvolvingMemoryAdapter) Learn(pattern, lesson string) error
func (*EvolvingMemoryAdapter) Retrieve ¶
func (a *EvolvingMemoryAdapter) Retrieve(query string) []string
type EvolvingMemoryInterface ¶
type EvolvingMemoryInterface interface {
Learn(pattern, lesson string) error
Retrieve(query string) []string
Format() string
}
EvolvingMemoryInterface abstracts guideline retrieval and learning so the lifecycle can be tested without real storage.
type FewShotExample ¶
type FewShotExample struct {
Prompt string `json:"prompt"`
Response string `json:"response"`
TaskType string `json:"task_type"`
Quality float64 `json:"quality"` // 0-1, based on whether output was kept
CreatedAt time.Time `json:"created_at"`
UsedCount int `json:"used_count"`
}
FewShotExample is a recorded successful interaction.
type FewShotStore ¶
type FewShotStore struct {
// contains filtered or unexported fields
}
FewShotStore collects successful (prompt, response) pairs and injects the most relevant as few-shot examples into the system prompt.
func NewFewShotStore ¶
func NewFewShotStore() *FewShotStore
NewFewShotStore creates a store backed by ~/.hawk/fewshot.json.
func (*FewShotStore) FormatForPrompt ¶
func (fs *FewShotStore) FormatForPrompt(prompt string) string
FormatForPrompt returns few-shot examples formatted for system prompt injection.
func (*FewShotStore) Record ¶
func (fs *FewShotStore) Record(prompt, response, taskType string)
Record saves a successful interaction as a potential few-shot example.
func (*FewShotStore) Retrieve ¶
func (fs *FewShotStore) Retrieve(prompt string, topK int) []FewShotExample
Retrieve finds the most relevant few-shot examples for a given prompt.
type LLMClient ¶
type LLMClient interface {
Chat(ctx context.Context, msgs []client.EyrieMessage, opts client.ChatOptions) (*client.EyrieResponse, error)
}
LLMClient is the interface for sending chat requests to an LLM provider. It is satisfied by *client.EyrieClient.
type LimitTracker ¶
type LimitTracker struct {
// contains filtered or unexported fields
}
LimitTracker tracks usage against limits.
func NewLimitTracker ¶
func NewLimitTracker(limits SafetyLimits) *LimitTracker
NewLimitTracker creates a LimitTracker with the given limits.
func (*LimitTracker) IsExceeded ¶
func (lt *LimitTracker) IsExceeded() (bool, string)
IsExceeded returns true and a human-readable reason when any limit is breached.
func (*LimitTracker) RecordCost ¶
func (lt *LimitTracker) RecordCost(usd float64)
RecordCost adds to the running cost total.
func (*LimitTracker) RecordTokens ¶
func (lt *LimitTracker) RecordTokens(n int)
RecordTokens adds output tokens to the running total.
func (*LimitTracker) RecordToolCall ¶
func (lt *LimitTracker) RecordToolCall(toolName string)
RecordToolCall records a tool invocation. Tools named "Bash" or "bash" also increment the bash command counter; "Write" or "Edit" increment file writes.
func (*LimitTracker) RecordTurn ¶
func (lt *LimitTracker) RecordTurn()
RecordTurn increments the turn counter.
func (*LimitTracker) Summary ¶
func (lt *LimitTracker) Summary() string
Summary returns a one-line summary of usage vs limits.
type LoopDetector ¶
type LoopDetector struct {
// contains filtered or unexported fields
}
LoopDetector detects repeated identical tool call patterns using SHA-256 signatures. Supports two severity levels: warning (soft) and doom loop (hard escalation).
func NewLoopDetector ¶
func NewLoopDetector(windowSize, maxRepeats int) *LoopDetector
NewLoopDetector creates a detector with a sliding window.
func (*LoopDetector) DoomLoopWarning ¶
func (ld *LoopDetector) DoomLoopWarning() string
DoomLoopWarning returns the hard escalation message (repeated loops).
func (*LoopDetector) Escalated ¶
func (ld *LoopDetector) Escalated() bool
Escalated returns whether the detector has already fired a warning.
func (*LoopDetector) IsDoomLoop ¶
func (ld *LoopDetector) IsDoomLoop() bool
IsDoomLoop returns true when the agent has been stuck for DoomLoopThreshold consecutive escalation attempts — it should hard-stop and ask the user.
func (*LoopDetector) IsLooping ¶
func (ld *LoopDetector) IsLooping() bool
IsLooping returns true if any signature appears more than maxRepeats times in the window.
func (*LoopDetector) LoopWarning ¶
func (ld *LoopDetector) LoopWarning() string
LoopWarning returns the soft warning message (first detection).
func (*LoopDetector) MarkEscalated ¶
func (ld *LoopDetector) MarkEscalated()
MarkEscalated records that a warning was shown.
func (*LoopDetector) RecordStep ¶
func (ld *LoopDetector) RecordStep(toolNames []string, inputs []string, outputs []string)
RecordStep hashes the tool calls and results from a single agent step.
func (*LoopDetector) Reset ¶
func (ld *LoopDetector) Reset()
Reset clears the escalation state (e.g., after user provides new direction).
type MemoryRecaller ¶
type MemoryRecaller interface {
Recall(query string, tokenBudget int) (string, error)
Remember(content, category string) error
}
MemoryRecaller abstracts memory recall/remember so engine avoids importing memory directly.
type MicroCompactConfig ¶
type MicroCompactConfig struct {
CompactableTools map[string]bool
TimeGapMins float64
KeepRecent int
}
MicroCompactConfig controls micro-compaction behavior.
func DefaultMicroCompactConfig ¶
func DefaultMicroCompactConfig() MicroCompactConfig
DefaultMicroCompactConfig returns the default micro-compaction settings.
type MicroCompactStrategy ¶
type MicroCompactStrategy struct{}
MicroCompactStrategy clears old tool result content while preserving message structure.
func (*MicroCompactStrategy) Compact ¶
func (s *MicroCompactStrategy) Compact(ctx context.Context, sess *Session) (*CompactResult, error)
func (*MicroCompactStrategy) Name ¶
func (s *MicroCompactStrategy) Name() string
func (*MicroCompactStrategy) ShouldTrigger ¶
func (s *MicroCompactStrategy) ShouldTrigger(msgs []client.EyrieMessage, tokenCount, threshold int) bool
ShouldTrigger fires when there are enough messages with compactable tool results and sufficient time has passed since the last assistant message (cache is cold).
type PatchVerdict ¶
type PatchVerdict struct {
Likely string // "correct", "incorrect", "uncertain"
Issues []string // specific issues found
Confidence float64 // 0-1
}
PatchVerdict is the result of a critic's pre-screening of a patch.
type PendingChange ¶
type PendingChange struct {
Path string
Action string // "create", "edit", "overwrite"
OldContent string
NewContent string
Diff string
CreatedAt time.Time
}
PendingChange represents a staged file modification that has not yet been applied to disk.
type PermissionEngine ¶
type PermissionEngine struct {
Memory *PermissionMemory
AutoMode *permissions.AutoModeState
Classifier *permissions.Classifier
BypassKill *permissions.BypassKillswitch
Mode PermissionMode
Autonomy AutonomyLevel
PromptFn func(PermissionRequest) // callback to ask user
}
PermissionEngine encapsulates all permission-checking logic. Extracted from Session to keep the god object lean.
func NewPermissionEngine ¶
func NewPermissionEngine() *PermissionEngine
NewPermissionEngine creates a PermissionEngine with sensible defaults.
func (*PermissionEngine) ApplyToolState ¶
func (pe *PermissionEngine) ApplyToolState(name string)
ApplyToolState updates permission mode based on plan mode tools.
func (*PermissionEngine) CheckTool ¶
func (pe *PermissionEngine) CheckTool(ctx context.Context, tc toolCallInfo) (bool, string)
CheckTool determines if a tool call is allowed, denied, or needs user prompt. Returns (granted bool, denyReason string). If the user must be asked, it blocks on PromptFn with a 5-minute timeout.
func (*PermissionEngine) SetMode ¶
func (pe *PermissionEngine) SetMode(mode string) error
SetMode applies a permission mode string.
type PermissionMemory ¶
type PermissionMemory struct {
// contains filtered or unexported fields
}
PermissionMemory stores always-allow and always-deny rules.
func NewPermissionMemory ¶
func NewPermissionMemory() *PermissionMemory
func (*PermissionMemory) AllowSpec ¶
func (pm *PermissionMemory) AllowSpec(spec string)
AllowSpec applies an archive-style permission rule, e.g. "Bash(git:*)".
func (*PermissionMemory) AlwaysAllow ¶
func (pm *PermissionMemory) AlwaysAllow(toolName string)
AlwaysAllow marks a tool as always allowed.
func (*PermissionMemory) AlwaysAllowPattern ¶
func (pm *PermissionMemory) AlwaysAllowPattern(pattern string)
AlwaysAllowPattern adds a pattern rule (e.g. "bash:go *").
func (*PermissionMemory) AlwaysDeny ¶
func (pm *PermissionMemory) AlwaysDeny(toolName string)
AlwaysDeny marks a tool as always denied.
func (*PermissionMemory) AlwaysDenyPattern ¶
func (pm *PermissionMemory) AlwaysDenyPattern(pattern string)
AlwaysDenyPattern adds a deny pattern rule.
func (*PermissionMemory) Check ¶
func (pm *PermissionMemory) Check(toolName string, summary string) *bool
Check returns: true=allowed, false=denied, nil=ask user.
func (*PermissionMemory) DenySpec ¶
func (pm *PermissionMemory) DenySpec(spec string)
DenySpec applies an archive-style deny rule, e.g. "Write(*.env)".
type PermissionMode ¶
type PermissionMode string
PermissionMode controls how permission prompts are handled.
const ( PermissionModeDefault PermissionMode = "default" PermissionModeAcceptEdits PermissionMode = "acceptEdits" PermissionModeBypassPermissions PermissionMode = "bypassPermissions" PermissionModeDontAsk PermissionMode = "dontAsk" PermissionModePlan PermissionMode = "plan" )
type PermissionRequest ¶
PermissionRequest is sent from engine to TUI when a tool needs approval.
type PlanState ¶
PlanState tracks progress through a set of subtasks.
func NewPlanState ¶
NewPlanState creates a new plan with the given name and no subtasks.
func (*PlanState) Next ¶
Next returns the next pending subtask and marks it as in_progress, or nil if none remain.
type PromptAdjustment ¶
type PromptAdjustment struct {
Rule string `json:"rule"` // "always use tabs" or "never add comments"
Source string `json:"source"` // user message that triggered this
Polarity string `json:"polarity"` // "do" or "dont"
Confidence float64 `json:"confidence"` // increases with reinforcement
Active bool `json:"active"`
CreatedAt time.Time `json:"created_at"`
LastUsed time.Time `json:"last_used"`
}
PromptAdjustment is a user-derived prompt modification.
type PromptTuner ¶
type PromptTuner struct {
// contains filtered or unexported fields
}
PromptTuner optimizes system prompt sections based on session outcomes. Tracks which prompt configurations lead to successful sessions and adjusts over time (OPRO/EvoPrompt pattern without LLM calls).
func NewPromptTuner ¶
func NewPromptTuner() *PromptTuner
NewPromptTuner creates a tuner backed by ~/.hawk/prompt_tuning.json.
func (*PromptTuner) BestVariant ¶
func (pt *PromptTuner) BestVariant(section string) (string, float64)
BestVariant returns the highest-scoring variant for a section.
func (*PromptTuner) RecordOutcome ¶
func (pt *PromptTuner) RecordOutcome(section, content string, success bool)
RecordOutcome updates the variant score based on a session outcome.
func (*PromptTuner) Report ¶
func (pt *PromptTuner) Report() string
Report returns a summary of all tracked variants sorted by score.
type PromptVariant ¶
type PromptVariant struct {
Section string `json:"section"` // which section was varied
Content string `json:"content"` // the variant content
Score float64 `json:"score"` // success rate (0-1)
Uses int `json:"uses"` // times used
Successes int `json:"successes"` // successful sessions with this variant
LastUsed time.Time `json:"last_used"`
}
PromptVariant is a tracked prompt configuration with its performance score.
type ProtectedPaths ¶
type ProtectedPaths struct {
// contains filtered or unexported fields
}
ProtectedPaths tracks file paths that are read-only within the session. Tools that write or edit files should check IsProtected before proceeding.
func NewProtectedPaths ¶
func NewProtectedPaths() *ProtectedPaths
NewProtectedPaths creates an empty ProtectedPaths set.
func (*ProtectedPaths) Add ¶
func (p *ProtectedPaths) Add(path string)
Add marks a path as protected (read-only). The path is cleaned before storage for consistent lookups.
func (*ProtectedPaths) Format ¶
func (p *ProtectedPaths) Format() string
Format returns a human-readable block suitable for system prompt injection.
func (*ProtectedPaths) IsProtected ¶
func (p *ProtectedPaths) IsProtected(path string) bool
IsProtected returns true when path (or any ancestor directory) is protected.
func (*ProtectedPaths) List ¶
func (p *ProtectedPaths) List() []string
List returns a sorted slice of all protected paths.
func (*ProtectedPaths) Remove ¶
func (p *ProtectedPaths) Remove(path string)
Remove unmarks a path so it is no longer protected.
type Reflection ¶
type Reflection struct {
Attempt int // which attempt number this reflects on
TaskGoal string // what the task was trying to accomplish
WhatFailed string // what specifically went wrong
WhyFailed string // root cause analysis
WhatToDo string // what should be done differently next time
Timestamp time.Time // when the reflection was generated
}
Reflection captures a structured verbal self-reflection on a failed attempt.
type Reflector ¶
type Reflector struct {
// contains filtered or unexported fields
}
Reflector generates verbal self-reflections after task attempts. Based on Reflexion (Shinn et al., NeurIPS 2023): verbal reinforcement learning achieves 91% on HumanEval by storing natural-language reflections in an episodic memory buffer for subsequent attempts.
Instead of mechanical extraction ("tools used: X, files touched: Y"), we ask the LLM: "Analyze what went wrong and what should be done differently." This produces richer, actionable feedback that subsequent attempts can use.
func NewReflector ¶
NewReflector creates a Reflector that uses the given LLM client and model to generate verbal reflections on failed task attempts.
func (*Reflector) History ¶
func (r *Reflector) History() []Reflection
History returns a copy of all reflections generated so far.
func (*Reflector) InjectReflections ¶
InjectReflections formats all accumulated reflections into a block of text suitable for prepending to the next attempt's prompt. If there are no reflections yet, it returns an empty string.
func (*Reflector) Reflect ¶
func (r *Reflector) Reflect(ctx context.Context, goal string, messages []client.EyrieMessage, errorMsg string) (*Reflection, error)
Reflect generates a verbal self-reflection on a failed attempt by asking the LLM to analyze the conversation history and error. The resulting Reflection is appended to the internal history for later injection.
type RoutingDecision ¶
type RoutingDecision struct {
OriginalModel string `json:"original_model"`
SelectedModel string `json:"selected_model"`
TaskType string `json:"task_type"`
Reason string `json:"reason"`
Timestamp time.Time `json:"timestamp"`
}
RoutingDecision records a single model selection event.
type SafetyLimits ¶
type SafetyLimits struct {
MaxToolCalls int // max total tool invocations (default: 200)
MaxFileWrites int // max files created/modified (default: 50)
MaxBashCommands int // max bash executions (default: 100)
MaxCostUSD float64 // max spend (default: from MaxBudgetUSD)
MaxTurns int // max LLM turns (default: from MaxTurns)
MaxOutputTokens int // max total output tokens (default: 500K)
}
SafetyLimits caps what the agent can do in a single session.
func DefaultLimits ¶
func DefaultLimits() SafetyLimits
DefaultLimits returns conservative safety limits for normal interactive use.
func ResearchLimits ¶
func ResearchLimits() SafetyLimits
ResearchLimits returns strict per-iteration limits suitable for research tasks.
func VibeLimits ¶
func VibeLimits() SafetyLimits
VibeLimits returns more permissive limits for autonomous/vibe mode.
type SelfReviewResult ¶
type SelfReviewResult struct {
Approved bool // whether the change should be applied
Issues []string // problems found during review
Suggestions []string // improvements that could be made
Confidence float64 // 0.0-1.0: how confident the reviewer is in its assessment
}
SelfReviewResult holds the outcome of an LLM self-review of a proposed change.
func ReviewBeforeWrite ¶
func ReviewBeforeWrite(ctx context.Context, llm LLMClient, model string, intent string, filePath string, oldContent string, newContent string) (*SelfReviewResult, error)
ReviewBeforeWrite asks the model to review its own proposed changes before they are applied to a file. It compares old and new content in the context of the user's original intent and returns approval or a list of issues.
If confidence is below ConfidenceThreshold (0.7), the review will suggest fixes rather than approving, regardless of whether explicit issues were found.
type Session ¶
type Session struct {
Cost Cost
Router *modelPkg.Router
Perm *PermissionEngine // extracted permission subsystem
// Backward-compatible accessors below (will be removed after full migration)
Permissions *PermissionMemory // use Perm.Memory
AutoMode *permissions.AutoModeState // use Perm.AutoMode
Classifier *permissions.Classifier // use Perm.Classifier
BypassKill *permissions.BypassKillswitch // use Perm.BypassKill
Mode PermissionMode // use Perm.Mode
MaxTurns int
MaxBudgetUSD float64
AllowedDirs []string
PermissionFn func(PermissionRequest) // use Perm.PromptFn
AgentSpawnFn func(ctx context.Context, prompt string) (string, error)
AskUserFn func(question string) (string, error)
Memory MemoryRecaller
YaadBridge *memory.YaadBridge
EnhancedMemory *memory.EnhancedMemoryManager
PinnedMessages int // messages to protect from compaction (from /pin)
AutoCompactThresholdPct int // token % to trigger auto-compact (default 85)
// Cost optimization
Cascade *CascadeRouter // cascade.go — model tier routing
Lifecycle *SessionLifecycle // lifecycle.go — self-improvement loop
Reflector *Reflector // reflect.go — verbal self-reflection
CostTracker *CostTracker // cost_tracker.go — per-request cost persistence
// Advanced features
Autonomy AutonomyLevel // autonomy.go — permission level
Sandbox *DiffSandbox // diffsandbox.go — staged file changes
Plan *PlanState // subtask.go — user-activated plan
Beliefs *BeliefState // belief.go — discovered knowledge
Critic *Critic // critic.go — patch pre-screening
Backtrack *BacktrackEngine // backtrack.go — decision recording
Limits *LimitTracker // limits.go — safety limits
Teach TeachConfig // teach.go — explanation depth
Trajectory *TrajectoryDistiller // trajectory.go — multi-run distillation
Shadow *ShadowWorkspace // shadow.go — edit pre-validation
Snapshots SnapshotTracker // snapshot integration for auto-tracking
ConvoDAG *convodag.DAG // conversation DAG for branching/forking
Sleeptime *memory.SleeptimeAgent // sleeptime.go — background memory consolidation
Activity *memory.ActivityTracker // activity.go — memory save nudging (Engram pattern)
SkillDistiller *memory.SkillDistiller // skill_distill.go — auto-skill extraction
Tracer *trace.Tracer // trace.go — distributed tracing spans
// contains filtered or unexported fields
}
Session manages a conversation with an LLM via eyrie.
func NewSession ¶
NewSession creates a new conversation session.
func (*Session) AddAssistant ¶
func (*Session) AppendSystemContext ¶
AppendSystemContext adds runtime context, such as /add-dir, to future model calls.
func (*Session) AutoCompactIfNeeded ¶
AutoCompactIfNeeded runs compaction when the conversation exceeds the threshold.
func (*Session) Compact ¶
func (s *Session) Compact()
Compact reduces conversation history (boundary-aware truncation).
func (*Session) ForkConversation ¶
ForkConversation creates a new branch from a specific point in history. Returns the fork node ID and the messages up to that point.
func (*Session) ListBranches ¶
ListBranches returns child nodes (alternative branches) from a given node.
func (*Session) LoadMessages ¶
func (s *Session) LoadMessages(msgs []client.EyrieMessage)
func (*Session) MessageCount ¶
func (*Session) RawMessages ¶
func (s *Session) RawMessages() []client.EyrieMessage
RawMessages returns the conversation messages for persistence.
func (*Session) RemoveLastExchange ¶
func (s *Session) RemoveLastExchange()
RemoveLastExchange removes the last user+assistant message pair.
func (*Session) SetAPIKeys ¶
SetAPIKeys updates all known provider API keys for subsequent requests.
func (*Session) SetAllowedDirs ¶
SetAllowedDirs sets directories that file tools are allowed to access.
func (*Session) SetMaxBudgetUSD ¶
SetMaxBudgetUSD caps estimated API spend for this session.
func (*Session) SetMaxTurns ¶
SetMaxTurns caps the number of model turns in the agent loop.
func (*Session) SetPermissionMode ¶
SetPermissionMode applies an archive-compatible permission mode.
func (*Session) SetProvider ¶
SetProvider updates the active provider for subsequent requests.
func (*Session) ShouldAutoCompact ¶
ShouldAutoCompact returns true if the conversation is approaching context limits.
func (*Session) SmartCompact ¶
func (s *Session) SmartCompact()
SmartCompact reduces conversation history using LLM-generated summaries.
func (*Session) Stream ¶
func (s *Session) Stream(ctx context.Context) (<-chan StreamEvent, error)
Stream runs the agentic loop: LLM → tool_use → execute → loop.
func (*Session) SwitchBranch ¶
SwitchBranch navigates to a different branch point and rebuilds messages.
func (*Session) WireAgentTool ¶
func (s *Session) WireAgentTool()
WireAgentTool sets up sub-agent spawning with two modes:
- explore: fast/cheap model, read-only tools, higher turn budget
- general: full model, all tools, standard budget
type SessionLifecycle ¶
type SessionLifecycle struct {
Memory EvolvingMemoryInterface
SkillStore SkillStoreInterface
CostTracker CostTrackerInterface
}
SessionLifecycle manages the start and end of agent sessions, implementing the self-improvement loop that makes hawk better over time.
Research basis: - Reflexion (NeurIPS 2023): 91% HumanEval via episodic memory of reflections - ExpeL (AAAI 2024): extract insights from task experiences - Voyager: 15.3x faster with accumulated skill library - DSPy (Stanford): 25-65% improvement via curated few-shot examples
The closed loop: SESSION START:
- Retrieve relevant EvolvingMemory guidelines
- Inject few-shot examples from prior successes
- Load yaad context (conventions, active tasks, stale warnings)
SESSION END:
- Generate LLM reflection ("what worked, what failed, why")
- Extract guidelines via EvolvingMemory.Learn()
- Distill successful approaches into skills
- Record cost/performance metrics
- Trigger yaad consolidation
func (*SessionLifecycle) OnSessionEnd ¶
func (l *SessionLifecycle) OnSessionEnd(_ context.Context, session *Session, outcome SessionOutcome) error
OnSessionEnd performs post-session learning.
func (*SessionLifecycle) OnSessionStart ¶
func (l *SessionLifecycle) OnSessionStart(_ context.Context, initialPrompt string) string
OnSessionStart prepares context for a new session. Returns context to inject into the system prompt.
type SessionMemoryConfig ¶
SessionMemoryConfig controls session memory compaction thresholds.
func DefaultSessionMemoryConfig ¶
func DefaultSessionMemoryConfig() SessionMemoryConfig
DefaultSessionMemoryConfig returns defaults matching the archive.
type SessionMemoryStrategy ¶
type SessionMemoryStrategy struct{}
SessionMemoryStrategy uses the session memory file as a compaction summary instead of making an LLM call.
func (*SessionMemoryStrategy) Compact ¶
func (s *SessionMemoryStrategy) Compact(ctx context.Context, sess *Session) (*CompactResult, error)
func (*SessionMemoryStrategy) Name ¶
func (s *SessionMemoryStrategy) Name() string
func (*SessionMemoryStrategy) ShouldTrigger ¶
func (s *SessionMemoryStrategy) ShouldTrigger(msgs []client.EyrieMessage, tokenCount, threshold int) bool
type SessionOutcome ¶
type SessionOutcome struct {
Success bool
TaskGoal string
FilesChanged []string
ToolsUsed []string
TotalCost float64
Duration time.Duration
UserFeedback string // empty if none
}
SessionOutcome captures the results of a completed session.
type ShadowWorkspace ¶
type ShadowWorkspace struct {
// contains filtered or unexported fields
}
ShadowWorkspace provides a temporary directory where file edits can be validated (e.g. via `go vet`, `tsc`, `pylint`) without touching the original source tree.
func NewShadowWorkspace ¶
func NewShadowWorkspace() (*ShadowWorkspace, error)
NewShadowWorkspace creates a new temporary directory for shadow validation.
func (*ShadowWorkspace) Close ¶
func (sw *ShadowWorkspace) Close()
Close removes the shadow workspace temp directory and all its contents.
func (*ShadowWorkspace) TempDir ¶
func (sw *ShadowWorkspace) TempDir() string
TempDir returns the path to the shadow workspace temp directory.
func (*ShadowWorkspace) ValidateEdit ¶
func (sw *ShadowWorkspace) ValidateEdit(originalPath, newContent string) []ValidationError
ValidateEdit copies a file into the shadow workspace, writes newContent to the copy, runs the language-appropriate validation tool, and returns any errors found. The temp copy is cleaned up before returning.
func (*ShadowWorkspace) ValidateMultipleEdits ¶
func (sw *ShadowWorkspace) ValidateMultipleEdits(edits map[string]string) map[string][]ValidationError
ValidateMultipleEdits validates several files at once and returns a map of file path to validation errors.
type SkillDistillerAdapter ¶
type SkillDistillerAdapter struct {
SD *memory.SkillDistiller
}
SkillDistillerAdapter bridges memory.SkillDistiller to SkillStoreInterface. Skill distillation builds a prompt for LLM extraction — the actual distilled skills are stored as files in hawk-skills/.
func (*SkillDistillerAdapter) Distill ¶
func (a *SkillDistillerAdapter) Distill(goal string, steps []string, outcome string) error
func (*SkillDistillerAdapter) Retrieve ¶
func (a *SkillDistillerAdapter) Retrieve(_ string) []string
type SkillStoreInterface ¶
type SkillStoreInterface interface {
Distill(goal string, steps []string, outcome string) error
Retrieve(query string) []string
}
SkillStoreInterface abstracts skill distillation and retrieval.
type SmartCompactStrategy ¶
type SmartCompactStrategy struct{}
SmartCompactStrategy uses LLM to generate a conversation summary.
func (*SmartCompactStrategy) Compact ¶
func (s *SmartCompactStrategy) Compact(ctx context.Context, sess *Session) (*CompactResult, error)
func (*SmartCompactStrategy) Name ¶
func (s *SmartCompactStrategy) Name() string
func (*SmartCompactStrategy) ShouldTrigger ¶
func (s *SmartCompactStrategy) ShouldTrigger(msgs []client.EyrieMessage, tokenCount, threshold int) bool
type SnapshotCache ¶
type SnapshotCache struct {
// contains filtered or unexported fields
}
SnapshotCache is a TTL-based cache for project snapshots.
func NewSnapshotCache ¶
func NewSnapshotCache(ttl time.Duration) *SnapshotCache
NewSnapshotCache creates a new SnapshotCache with the given TTL. If ttl is zero, DefaultSnapshotTTL is used.
func (*SnapshotCache) Get ¶
func (sc *SnapshotCache) Get(key string) (string, bool)
Get returns the cached value for the key if it exists and has not expired.
func (*SnapshotCache) GetOrCompute ¶
GetOrCompute returns the cached value for the key, or computes and caches it using the provided function if the value is missing or expired.
func (*SnapshotCache) Set ¶
func (sc *SnapshotCache) Set(key, value string)
Set stores a value in the cache with the configured TTL.
type SnapshotTracker ¶
SnapshotTracker abstracts the snapshot system so engine doesn't import snapshot directly.
type SnowballDetector ¶
type SnowballDetector struct {
// contains filtered or unexported fields
}
SnowballDetector detects when token consumption is growing faster than progress, signalling that the agent is stuck in a snowball pattern where each turn consumes more tokens without proportional progress.
func NewSnowballDetector ¶
func NewSnowballDetector(maxTokens int) *SnowballDetector
NewSnowballDetector creates a detector with the given absolute token ceiling. The default growth threshold is 2.0x (last 3 turns vs first 3 turns).
func (*SnowballDetector) IsSnowballing ¶
func (sd *SnowballDetector) IsSnowballing() bool
IsSnowballing returns true if the last 3 turns consumed 2x+ tokens compared to the first 3 turns AND progress per token is declining.
func (*SnowballDetector) RecordTurn ¶
func (sd *SnowballDetector) RecordTurn(tokens int, progress float64)
RecordTurn records token usage and estimated progress for a single turn. Progress should be in the range [0, 1].
func (*SnowballDetector) Reset ¶
func (sd *SnowballDetector) Reset()
Reset clears all recorded data.
func (*SnowballDetector) ShouldAbort ¶
func (sd *SnowballDetector) ShouldAbort() bool
ShouldAbort returns true if total tokens exceed maxTokens or the growth rate exceeds 3x between the first and last 3-turn windows.
func (*SnowballDetector) String ¶
func (sd *SnowballDetector) String() string
String implements the Stringer interface for SnowballDetector.
func (*SnowballDetector) Summary ¶
func (sd *SnowballDetector) Summary() string
Summary returns a human-readable summary of the snowball state.
type StrategyRegistry ¶
type StrategyRegistry struct {
// contains filtered or unexported fields
}
StrategyRegistry manages compaction strategies in priority order.
func NewStrategyRegistry ¶
func NewStrategyRegistry(config CompactConfig) *StrategyRegistry
NewStrategyRegistry creates a registry with default strategies.
func (*StrategyRegistry) SelectStrategy ¶
func (r *StrategyRegistry) SelectStrategy(msgs []client.EyrieMessage, tokenCount int) CompactStrategy
SelectStrategy picks the highest-priority strategy whose trigger fires.
type StreamEvent ¶
type StreamEvent struct {
Type string // content, thinking, tool_use, tool_result, usage, done, error
Content string
ToolName string
ToolID string
Usage *StreamUsage // usage data for this event
}
StreamEvent is sent from the engine to the TUI.
type StreamUsage ¶
type StreamUsage struct {
PromptTokens int `json:"prompt_tokens"`
CompletionTokens int `json:"completion_tokens"`
CacheReadTokens int `json:"cache_read_tokens,omitempty"`
CacheWriteTokens int `json:"cache_write_tokens,omitempty"`
}
StreamUsage tracks token usage for a single stream event.
type SubAgentMode ¶
type SubAgentMode string
SubAgentMode determines the capabilities and cost profile of a sub-agent.
const ( SubAgentExplore SubAgentMode = "explore" SubAgentGeneral SubAgentMode = "general" )
type Subtask ¶
type Subtask struct {
ID int
Title string
Description string
Files []string
Status string // "pending", "in_progress", "done", "skipped"
}
Subtask represents a single unit of work within a plan.
func ParseSubtasks ¶
ParseSubtasks parses LLM output formatted as numbered subtasks. Expected format:
- Title here Description of what to do Files: path/to/file.go, another/file.go
type TeachConfig ¶
TeachConfig controls explanation depth.
type TimeoutConfig ¶
type TimeoutConfig struct {
Total time.Duration // total time for the entire operation
PerTurn time.Duration // max time per LLM turn (default: 60s)
PerTool time.Duration // max time per tool execution (default: 120s)
Countdown bool // show remaining time in output
}
TimeoutConfig controls operation time budgets.
func DefaultTimeoutConfig ¶
func DefaultTimeoutConfig() TimeoutConfig
DefaultTimeoutConfig returns a TimeoutConfig with sensible per-turn and per-tool defaults. Total is left at zero (no overall deadline) so the caller can set it.
type TrajectoryDistiller ¶
type TrajectoryDistiller struct {
// contains filtered or unexported fields
}
TrajectoryDistiller runs a task multiple times, summarizing what worked, and retrying with distilled knowledge from previous attempts.
func NewTrajectoryDistiller ¶
func NewTrajectoryDistiller(session *Session, maxRuns int) *TrajectoryDistiller
NewTrajectoryDistiller creates a new distiller wrapping the given session.
func (*TrajectoryDistiller) BestRun ¶
func (td *TrajectoryDistiller) BestRun(runs []TrajectoryRun) *TrajectoryRun
BestRun returns the run with Success=true (preferring earlier), or the highest-quality failure (most messages, fewest errors).
func (*TrajectoryDistiller) RunWithDistillation ¶
func (td *TrajectoryDistiller) RunWithDistillation(ctx context.Context, prompt string) (string, error)
RunWithDistillation executes the prompt, and if it fails, retries with accumulated trajectory summaries from prior attempts. Returns the best result.
type TrajectoryRun ¶
type TrajectoryRun struct {
ID int
Messages []client.EyrieMessage
Success bool
Summary string // distilled lessons from this run
Tokens int
}
TrajectoryRun records a single attempt at completing a task.
type TransferLearning ¶
type TransferLearning struct {
// contains filtered or unexported fields
}
TransferLearning enables cross-session knowledge transfer. Extracts generalizable patterns from completed sessions and applies them to new sessions on similar codebases.
func NewTransferLearning ¶
func NewTransferLearning() *TransferLearning
NewTransferLearning creates a store backed by ~/.hawk/transfer.json.
func (*TransferLearning) Apply ¶
func (tl *TransferLearning) Apply(language, taskDescription string) []TransferPattern
Apply finds patterns relevant to the current task.
func (*TransferLearning) FormatForPrompt ¶
func (tl *TransferLearning) FormatForPrompt(language, task string) string
FormatForPrompt returns transfer patterns as system prompt context.
func (*TransferLearning) Learn ¶
func (tl *TransferLearning) Learn(language, category, pattern, approach string)
Learn extracts a transferable pattern from a successful session.
type TransferPattern ¶
type TransferPattern struct {
Language string `json:"language"` // go, python, typescript, etc.
Category string `json:"category"` // "fix", "refactor", "feature", "test"
Pattern string `json:"pattern"` // generalized description
Approach string `json:"approach"` // what worked
Confidence float64 `json:"confidence"` // based on success rate
UsedCount int `json:"used_count"`
SuccessRate float64 `json:"success_rate"`
CreatedAt time.Time `json:"created_at"`
}
TransferPattern is a reusable pattern extracted from a successful session.
type TruncateStrategy ¶
type TruncateStrategy struct{}
TruncateStrategy is the fallback that does boundary-aware truncation.
func (*TruncateStrategy) Compact ¶
func (s *TruncateStrategy) Compact(ctx context.Context, sess *Session) (*CompactResult, error)
func (*TruncateStrategy) Name ¶
func (s *TruncateStrategy) Name() string
func (*TruncateStrategy) ShouldTrigger ¶
func (s *TruncateStrategy) ShouldTrigger(_ []client.EyrieMessage, tokenCount, threshold int) bool
type ValidationError ¶
ValidationError represents a single validation issue.
type ValidationResult ¶
type ValidationResult struct {
Valid bool
Errors []ValidationError
}
ValidationResult holds the outcome of validating a file.
func ValidateFile ¶
func ValidateFile(path string) *ValidationResult
ValidateFile determines the language from the file extension and runs the appropriate syntax checker.
Source Files
¶
- adaptive_prompt.go
- agent.go
- autonomy.go
- background_agent.go
- backtrack.go
- belief.go
- cascade.go
- compact.go
- compact_api.go
- compact_auto.go
- compact_micro.go
- compact_prompt.go
- compact_session_memory.go
- compact_strategy.go
- context_budget.go
- context_collapse.go
- cost.go
- cost_display.go
- cost_table.go
- cost_tracker.go
- council.go
- critic.go
- diffsandbox.go
- engine.go
- error_patterns.go
- fewshot.go
- lifecycle.go
- lifecycle_adapters.go
- limits.go
- loop_detect.go
- permission.go
- permission_engine.go
- prompt_tuner.go
- protected.go
- reflect.go
- self_review.go
- session.go
- shadow.go
- sleeptime_ops.go
- snapshot_cache.go
- snowball.go
- stream.go
- subtask.go
- teach.go
- timeout.go
- token_budget.go
- tokenizer.go
- trajectory.go
- transfer.go
- validate.go