Documentation
¶
Overview ¶
Package ctxmgr is the namespace for context budget, decay, packing, providers, visualisation, and read-only context. See ../REFACTOR_PLAN.md.
Named "ctxmgr" (not "context") to avoid shadowing the stdlib context package.
Index ¶
- func CollapseRepeatedMessages(msgs []types.EyrieMessage) []types.EyrieMessage
- func EstimateTokensFromContent(content string) int
- func FormatContextItems(items []ContextItem) string
- func PackingReport(result *PackingResult, strategy PackingStrategy, totalMessages int, ...) string
- func SuggestFiles(projectDir string) []string
- func SummarizeDropped(dropped []ScoredMessage) string
- func TokenEstimate(content string) int
- type ContextAllocation
- type ContextBudget
- type ContextDecay
- func (cd *ContextDecay) Access(id string)
- func (cd *ContextDecay) Add(content, category string, tokens int) string
- func (cd *ContextDecay) ApplyDecay()
- func (cd *ContextDecay) BuildContext(maxTokens int) string
- func (cd *ContextDecay) FormatEntries(entries []DecayEntry) string
- func (cd *ContextDecay) Get(id string) (*DecayEntry, float64)
- func (cd *ContextDecay) GetByBudget(maxTokens int) []DecayEntry
- func (cd *ContextDecay) GetTopN(n int) []DecayEntry
- func (cd *ContextDecay) Pin(id string)
- func (cd *ContextDecay) Prune(minWeight float64) int
- func (cd *ContextDecay) Stats() DecayStats
- func (cd *ContextDecay) Unpin(id string)
- type ContextFile
- type ContextFileOption
- type ContextItem
- type ContextManager
- type ContextPacker
- type ContextProvider
- type ContextSection
- type ContextSnapshot
- type ContextStats
- type ContextVisualizer
- func (cv *ContextVisualizer) HistoryChart(snapshots []ContextSnapshot, width int) string
- func (cv *ContextVisualizer) Recommend() []string
- func (cv *ContextVisualizer) RenderBar(width int) string
- func (cv *ContextVisualizer) RenderCompact() string
- func (cv *ContextVisualizer) RenderDetailed() string
- func (cv *ContextVisualizer) TakeSnapshot(turn int) ContextSnapshot
- func (cv *ContextVisualizer) Update(sections []ContextSection)
- func (cv *ContextVisualizer) WarnIfCritical() string
- type DecayEntry
- type DecayStats
- type DependencyContextProvider
- type EnvironmentContextProvider
- type ErrorContextProvider
- type FileContextProvider
- type GitContextProvider
- type PackingResult
- type PackingStrategy
- type ReadOnlyContext
- func (rc *ReadOnlyContext) AddFile(path string, opts ...ContextFileOption) error
- func (rc *ReadOnlyContext) AddPattern(pattern string) error
- func (rc *ReadOnlyContext) BuildContextBlock() string
- func (rc *ReadOnlyContext) Evict() []string
- func (rc *ReadOnlyContext) IsReadOnly(path string) bool
- func (rc *ReadOnlyContext) RefreshStale() error
- func (rc *ReadOnlyContext) RemoveFile(path string)
- func (rc *ReadOnlyContext) Stats() ContextStats
- type ScoredMessage
- type VizContextItem
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func CollapseRepeatedMessages ¶
func CollapseRepeatedMessages(msgs []types.EyrieMessage) []types.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 EstimateTokensFromContent ¶
EstimateTokensFromContent provides a quick token estimate for content. Uses len/4 for English text, len/3 for code-heavy content.
func FormatContextItems ¶
func FormatContextItems(items []ContextItem) string
FormatContextItems formats context items into a system prompt section.
func PackingReport ¶
func PackingReport(result *PackingResult, strategy PackingStrategy, totalMessages int, mustKeepCount int) string
PackingReport generates a human-readable report of the packing result.
func SuggestFiles ¶
SuggestFiles returns a list of commonly useful context files that exist in the given directory.
func SummarizeDropped ¶
func SummarizeDropped(dropped []ScoredMessage) string
SummarizeDropped creates a brief summary of what was dropped.
func TokenEstimate ¶
TokenEstimate provides a quick token count approximation: len(content) / 4.
Types ¶
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 ContextDecay ¶
type ContextDecay struct {
HalfLife time.Duration
MinWeight float64
Entries []DecayEntry
// contains filtered or unexported fields
}
ContextDecay manages context entries with time-based importance decay. Older context gradually loses weight unless pinned or accessed, keeping the most relevant information prioritized for the model's context window.
The decay follows exponential half-life: weight = initial * 0.5^(elapsed/halfLife) This mirrors human memory curves and ensures stale context doesn't crowd out fresh, relevant information.
func NewContextDecay ¶
func NewContextDecay(halfLife time.Duration) *ContextDecay
NewContextDecay creates a new ContextDecay manager with the given half-life. If halfLife is zero or negative, a default of 30 minutes is used.
func (*ContextDecay) Access ¶
func (cd *ContextDecay) Access(id string)
Access marks an entry as accessed, boosting its weight as a relevance signal. Each access resets the decay timer and increases the base weight.
func (*ContextDecay) Add ¶
func (cd *ContextDecay) Add(content, category string, tokens int) string
Add inserts a new context entry with initial weight 1.0. Returns the generated ID for the entry.
func (*ContextDecay) ApplyDecay ¶
func (cd *ContextDecay) ApplyDecay()
ApplyDecay recalculates all entry weights based on time elapsed since last access. Pinned entries are not affected by decay.
func (*ContextDecay) BuildContext ¶
func (cd *ContextDecay) BuildContext(maxTokens int) string
BuildContext formats the top entries fitting within the token budget as a context string.
func (*ContextDecay) FormatEntries ¶
func (cd *ContextDecay) FormatEntries(entries []DecayEntry) string
FormatEntries renders a slice of entries as a human-readable context block showing weight, pin status, and content.
func (*ContextDecay) Get ¶
func (cd *ContextDecay) Get(id string) (*DecayEntry, float64)
Get retrieves an entry by ID and returns it with its current decayed weight. Returns nil if the entry is not found.
func (*ContextDecay) GetByBudget ¶
func (cd *ContextDecay) GetByBudget(maxTokens int) []DecayEntry
GetByBudget returns entries fitting within the given token budget, sorted by weight descending. Entries are selected greedily by weight until the budget is exhausted.
func (*ContextDecay) GetTopN ¶
func (cd *ContextDecay) GetTopN(n int) []DecayEntry
GetTopN returns the N entries with the highest current weight, sorted descending.
func (*ContextDecay) Pin ¶
func (cd *ContextDecay) Pin(id string)
Pin marks an entry as pinned, preventing decay. Pinned entries always have weight 1.0.
func (*ContextDecay) Prune ¶
func (cd *ContextDecay) Prune(minWeight float64) int
Prune removes all entries whose current decayed weight is below the given threshold. Returns the number of entries removed.
func (*ContextDecay) Stats ¶
func (cd *ContextDecay) Stats() DecayStats
Stats returns aggregate statistics about the current context decay state.
func (*ContextDecay) Unpin ¶
func (cd *ContextDecay) Unpin(id string)
Unpin removes the pin from an entry, allowing normal decay to resume.
type ContextFile ¶
type ContextFile struct {
Path string
Content string
TokenCount int
AddedAt time.Time
LastRefreshed time.Time
AutoRefresh bool
Pinned bool
}
ContextFile represents a single read-only context file loaded into the agent's context.
type ContextFileOption ¶
type ContextFileOption func(*ContextFile)
ContextFileOption configures how a file is added to the read-only context.
func WithAutoRefresh ¶
func WithAutoRefresh() ContextFileOption
WithAutoRefresh marks the file to be re-read on each turn if it changes on disk.
func WithPinned ¶
func WithPinned() ContextFileOption
WithPinned marks the file as pinned so it is never evicted.
type ContextItem ¶
type ContextItem struct {
Source string
Title string
Content string
Relevance float64
TokenCount int
}
ContextItem represents a single piece of context gathered from a provider.
func PrioritizeItems ¶
func PrioritizeItems(items []ContextItem, budget int) []ContextItem
PrioritizeItems performs greedy selection sorted by relevance, picking items until budget is exhausted while ensuring source diversity.
type ContextManager ¶
type ContextManager struct {
Providers []ContextProvider
TotalBudget int
// contains filtered or unexported fields
}
ContextManager manages multiple context providers and orchestrates context gathering.
func NewContextManager ¶
func NewContextManager(totalBudget int) *ContextManager
NewContextManager creates a new ContextManager with the given total token budget.
func (*ContextManager) GatherAll ¶
func (cm *ContextManager) GatherAll(ctx context.Context, query string) ([]ContextItem, error)
GatherAll calls all providers in parallel, collects items, sorts by relevance, and truncates to fit within TotalBudget.
func (*ContextManager) Register ¶
func (cm *ContextManager) Register(provider ContextProvider)
Register adds a context provider to the manager.
type ContextPacker ¶
type ContextPacker struct {
MaxTokens int // model's context window
ReservedForOutput int // tokens reserved for response
SystemPromptTokens int // tokens consumed by system prompt
Strategy PackingStrategy // packing strategy to use
}
ContextPacker optimally selects which messages to keep when approaching context window limits, maximizing information density per token spent.
func NewContextPacker ¶
func NewContextPacker(maxTokens int) *ContextPacker
NewContextPacker creates a new context packer for the given model context size.
func (*ContextPacker) OptimalSelection ¶
func (cp *ContextPacker) OptimalSelection(messages []ScoredMessage, budget int) []int
OptimalSelection performs greedy selection by score/token ratio, respecting constraints (tool pairs, pinned messages).
func (*ContextPacker) Pack ¶
func (cp *ContextPacker) Pack(messages []ScoredMessage, currentTask string) *PackingResult
Pack scores each message and selects the optimal subset within budget. It ensures tool_use/tool_result pairs stay together, always keeps the system prompt context, first user message, and the last 4 messages.
func (*ContextPacker) ScoreMessage ¶
func (cp *ContextPacker) ScoreMessage(msg ScoredMessage, currentTask string, position int, total int) float64
ScoreMessage computes a composite score for a message based on multiple factors.
type ContextProvider ¶
type ContextProvider interface {
Name() string
Description() string
Gather(ctx context.Context, query string) ([]ContextItem, error)
TokenBudget() int
}
ContextProvider is a pluggable source of context that can be injected into the agent's system prompt.
type ContextSection ¶
type ContextSection struct {
Name string // "system_prompt", "memory", "conversation", "tool_results", "reserved"
Tokens int
Percentage float64
Color string // ANSI color code for the bar
Items []VizContextItem
Compressible bool
}
ContextSection represents a named region of the context window.
type ContextSnapshot ¶
ContextSnapshot captures context state at a particular turn for history tracking.
type ContextStats ¶
ContextStats provides statistics about the read-only context state.
type ContextVisualizer ¶
type ContextVisualizer struct {
MaxTokens int
Sections []ContextSection
// contains filtered or unexported fields
}
ContextVisualizer provides a real-time view of context window usage, showing users exactly what occupies their context and how space is allocated.
func NewContextVisualizer ¶
func NewContextVisualizer(maxTokens int) *ContextVisualizer
NewContextVisualizer creates a visualizer for the given maximum token budget.
func (*ContextVisualizer) HistoryChart ¶
func (cv *ContextVisualizer) HistoryChart(snapshots []ContextSnapshot, width int) string
HistoryChart renders context usage across turns as a sparkline-style chart.
Example:
Turn 1: [██░░░░░░░░░░░░░░░░░░] 8% Turn 5: [████████░░░░░░░░░░░░] 35% Turn 10: [████████████████░░░░] 78% ← compacted Turn 11: [██████░░░░░░░░░░░░░░] 28%
func (*ContextVisualizer) Recommend ¶
func (cv *ContextVisualizer) Recommend() []string
Recommend returns actionable suggestions based on current context state.
func (*ContextVisualizer) RenderBar ¶
func (cv *ContextVisualizer) RenderBar(width int) string
RenderBar renders a horizontal stacked bar showing each section's proportion.
Example output:
Context: [████████░░░░░░░░░░░░] 42% used (84,000/200,000)
[sys|mem|████conv████|tool|░░░reserved░░░]
func (*ContextVisualizer) RenderCompact ¶
func (cv *ContextVisualizer) RenderCompact() string
RenderCompact renders a single-line summary of context usage.
Example: [42% | sys:2% mem:1% conv:26% repo:4% ctx:6% | 116K free]
func (*ContextVisualizer) RenderDetailed ¶
func (cv *ContextVisualizer) RenderDetailed() string
RenderDetailed renders a full breakdown table of context usage by section.
func (*ContextVisualizer) TakeSnapshot ¶
func (cv *ContextVisualizer) TakeSnapshot(turn int) ContextSnapshot
TakeSnapshot captures the current context state for a given turn number.
func (*ContextVisualizer) Update ¶
func (cv *ContextVisualizer) Update(sections []ContextSection)
Update replaces the current sections and recalculates percentages.
func (*ContextVisualizer) WarnIfCritical ¶
func (cv *ContextVisualizer) WarnIfCritical() string
WarnIfCritical returns a warning string if context usage is dangerously high. Returns empty string if usage is within safe limits.
type DecayEntry ¶
type DecayEntry struct {
ID string
Content string
Weight float64
CreatedAt time.Time
LastAccessed time.Time
AccessCount int
Category string
Tokens int
Pinned bool
}
DecayEntry represents a single piece of context with decay metadata.
type DecayStats ¶
type DecayStats struct {
TotalEntries int
AvgWeight float64
Oldest time.Time
Newest time.Time
PinnedCount int
TotalTokens int
}
DecayStats provides aggregate statistics about the context decay state.
type DependencyContextProvider ¶
type DependencyContextProvider struct {
ProjectDir string
}
DependencyContextProvider provides dependency information from project files.
func (*DependencyContextProvider) Description ¶
func (d *DependencyContextProvider) Description() string
func (*DependencyContextProvider) Gather ¶
func (d *DependencyContextProvider) Gather(ctx context.Context, query string) ([]ContextItem, error)
func (*DependencyContextProvider) Name ¶
func (d *DependencyContextProvider) Name() string
func (*DependencyContextProvider) TokenBudget ¶
func (d *DependencyContextProvider) TokenBudget() int
type EnvironmentContextProvider ¶
type EnvironmentContextProvider struct{}
EnvironmentContextProvider provides system and environment information.
func (*EnvironmentContextProvider) Description ¶
func (e *EnvironmentContextProvider) Description() string
func (*EnvironmentContextProvider) Gather ¶
func (e *EnvironmentContextProvider) Gather(ctx context.Context, query string) ([]ContextItem, error)
func (*EnvironmentContextProvider) Name ¶
func (e *EnvironmentContextProvider) Name() string
func (*EnvironmentContextProvider) TokenBudget ¶
func (e *EnvironmentContextProvider) TokenBudget() int
type ErrorContextProvider ¶
type ErrorContextProvider struct {
LogDir string
}
ErrorContextProvider provides recent build/test errors as context.
func (*ErrorContextProvider) Description ¶
func (e *ErrorContextProvider) Description() string
func (*ErrorContextProvider) Gather ¶
func (e *ErrorContextProvider) Gather(ctx context.Context, query string) ([]ContextItem, error)
func (*ErrorContextProvider) Name ¶
func (e *ErrorContextProvider) Name() string
func (*ErrorContextProvider) TokenBudget ¶
func (e *ErrorContextProvider) TokenBudget() int
type FileContextProvider ¶
FileContextProvider provides recently modified files as context.
func (*FileContextProvider) Description ¶
func (f *FileContextProvider) Description() string
func (*FileContextProvider) Gather ¶
func (f *FileContextProvider) Gather(ctx context.Context, query string) ([]ContextItem, error)
func (*FileContextProvider) Name ¶
func (f *FileContextProvider) Name() string
func (*FileContextProvider) TokenBudget ¶
func (f *FileContextProvider) TokenBudget() int
type GitContextProvider ¶
GitContextProvider provides recent git history as context.
func (*GitContextProvider) Description ¶
func (g *GitContextProvider) Description() string
func (*GitContextProvider) Gather ¶
func (g *GitContextProvider) Gather(ctx context.Context, query string) ([]ContextItem, error)
func (*GitContextProvider) Name ¶
func (g *GitContextProvider) Name() string
func (*GitContextProvider) TokenBudget ¶
func (g *GitContextProvider) TokenBudget() int
type PackingResult ¶
type PackingResult struct {
KeptMessages []int // indices of kept messages
DroppedMessages []int // indices of dropped messages
TotalTokens int // total tokens of kept messages
Utilization float64 // percentage of context used (0.0 - 1.0)
Summary string // summary of dropped content
}
PackingResult contains the outcome of a context packing operation.
type PackingStrategy ¶
type PackingStrategy string
PackingStrategy determines how the context packer selects messages to keep.
const ( // StrategyRecent keeps the most recent messages (simple truncation). StrategyRecent PackingStrategy = "recent" // StrategyRelevance scores messages by relevance to the current task. StrategyRelevance PackingStrategy = "relevance" // StrategyHybrid combines recency and relevance scoring (default). StrategyHybrid PackingStrategy = "hybrid" // StrategyCompression summarizes old messages, keeps recent verbatim. StrategyCompression PackingStrategy = "compression" )
type ReadOnlyContext ¶
type ReadOnlyContext struct {
Files map[string]*ContextFile
Patterns []string
MaxTokenBudget int
// contains filtered or unexported fields
}
ReadOnlyContext manages a set of files loaded for agent reference that cannot be edited. Files are tracked with token budgets and can be auto-refreshed when they change on disk.
func NewReadOnlyContext ¶
func NewReadOnlyContext(maxBudget int) *ReadOnlyContext
NewReadOnlyContext creates a new ReadOnlyContext with the given token budget.
func (*ReadOnlyContext) AddFile ¶
func (rc *ReadOnlyContext) AddFile(path string, opts ...ContextFileOption) error
AddFile reads a file from disk and adds it to the read-only context. Returns an error if the file cannot be read or would exceed the token budget.
func (*ReadOnlyContext) AddPattern ¶
func (rc *ReadOnlyContext) AddPattern(pattern string) error
AddPattern adds a glob pattern and immediately resolves matching files. Files that match the pattern are added to the read-only context.
func (*ReadOnlyContext) BuildContextBlock ¶
func (rc *ReadOnlyContext) BuildContextBlock() string
BuildContextBlock formats all context files for system prompt injection.
func (*ReadOnlyContext) Evict ¶
func (rc *ReadOnlyContext) Evict() []string
Evict removes unpinned files by LRU (oldest AddedAt first) until within budget. Returns the list of evicted file paths.
func (*ReadOnlyContext) IsReadOnly ¶
func (rc *ReadOnlyContext) IsReadOnly(path string) bool
IsReadOnly checks if a path is in the read-only context. Used by Edit/Write tools to block modifications to context files.
func (*ReadOnlyContext) RefreshStale ¶
func (rc *ReadOnlyContext) RefreshStale() error
RefreshStale re-reads files that have been modified on disk since last refresh. Only refreshes files with AutoRefresh=true.
func (*ReadOnlyContext) RemoveFile ¶
func (rc *ReadOnlyContext) RemoveFile(path string)
RemoveFile removes a file from the read-only context.
func (*ReadOnlyContext) Stats ¶
func (rc *ReadOnlyContext) Stats() ContextStats
Stats returns statistics about the current read-only context state.