Documentation
¶
Overview ¶
Package executor provides the core autonomous agent execution loop.
Index ¶
- func EstimateTokens(messages []provider.Message) int
- type ApprovalRecord
- type ApprovalStatus
- type Approver
- type Config
- type ContextManager
- func (cm *ContextManager) Compact(ctx context.Context, messages []provider.Message, aiProvider provider.Provider) []provider.Message
- func (cm *ContextManager) Compactions() int
- func (cm *ContextManager) ContextLimitTokens() int
- func (cm *ContextManager) NeedsCompaction(messages []provider.Message) bool
- func (cm *ContextManager) SetModelLimit(model string, limit int)
- func (cm *ContextManager) TokenUsage(messages []provider.Message) (estimated, limit int)
- type HumanRequest
- type HumanRequester
- type LoopDetector
- type LoopDetectorConfig
- type LoopStatus
- type MemoryEntry
- type MemoryStore
- type NullApprover
- type NullHumanRequester
- type NullMemoryStore
- type NullSecretRedactor
- type NullTranscript
- type RequestStatus
- type RequestType
- type Result
- type SecretRedactor
- type TranscriptEntry
- type TranscriptRecorder
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func EstimateTokens ¶
EstimateTokens estimates the number of tokens in a message slice. Uses a rough heuristic of 4 characters per token (standard for English text).
Types ¶
type ApprovalRecord ¶
type ApprovalRecord struct {
ID string
Status ApprovalStatus
ReviewerComment string
}
ApprovalRecord is a resolved approval request.
type ApprovalStatus ¶
type ApprovalStatus string
ApprovalStatus represents the resolution state of an approval.
const ( ApprovalPending ApprovalStatus = "pending" ApprovalApproved ApprovalStatus = "approved" ApprovalRejected ApprovalStatus = "rejected" ApprovalTimeout ApprovalStatus = "timeout" )
type Approver ¶
type Approver interface {
// WaitForResolution blocks until the approval with the given ID is resolved
// or the timeout elapses.
WaitForResolution(ctx context.Context, approvalID string, timeout time.Duration) (*ApprovalRecord, error)
}
Approver manages approval gate blocking.
type Config ¶
type Config struct {
// Provider is the AI backend. Required.
Provider provider.Provider
// ToolRegistry provides tool definitions and execution. Optional.
ToolRegistry *tools.Registry
// Approver handles approval gates. Defaults to NullApprover.
Approver Approver
// HumanRequester handles blocking human-request gates. Defaults to NullHumanRequester.
HumanRequester HumanRequester
// SecretRedactor redacts secrets from messages. Defaults to NullSecretRedactor.
SecretRedactor SecretRedactor
// Transcript records conversation entries. Defaults to NullTranscript.
Transcript TranscriptRecorder
// Memory provides persistent agent memory. Defaults to NullMemoryStore.
Memory MemoryStore
// MaxIterations caps the agent loop. Default: 10.
MaxIterations int
// ApprovalTimeout is how long to wait for human approval. Default: 30m.
ApprovalTimeout time.Duration
// RequestTimeout is how long to wait for human request response. Default: 60m.
RequestTimeout time.Duration
// LoopDetector config. Zero values use defaults.
LoopDetection LoopDetectorConfig
// CompactionThreshold is the fraction of context limit at which compaction triggers. Default: 0.80.
CompactionThreshold float64
// TaskID and ProjectID are used for transcript recording.
TaskID string
ProjectID string
}
Config holds all dependencies for the executor. Nil interface fields are replaced with their Null* implementations.
type ContextManager ¶
type ContextManager struct {
// contains filtered or unexported fields
}
ContextManager tracks token usage across a message array and compacts the conversation when it approaches the model's context limit.
func NewContextManager ¶
func NewContextManager(providerName string, compactionThreshold float64) *ContextManager
NewContextManager creates a ContextManager for the given provider. The model name is used to look up the context window size. compactionThreshold sets the fraction of the context limit that triggers compaction; pass 0 to use the default (0.80).
func (*ContextManager) Compact ¶
func (cm *ContextManager) Compact( ctx context.Context, messages []provider.Message, aiProvider provider.Provider, ) []provider.Message
Compact compresses the conversation history by:
- Keeping the system message (index 0) and the most recent 2 exchanges.
- Summarising the middle portion using the LLM provider.
- Injecting the summary as a system-level context note.
If summarisation fails, the middle messages are replaced with a placeholder rather than aborting. Returns the compacted message slice.
func (*ContextManager) Compactions ¶
func (cm *ContextManager) Compactions() int
Compactions returns how many times compaction has been applied.
func (*ContextManager) ContextLimitTokens ¶
func (cm *ContextManager) ContextLimitTokens() int
ContextLimitTokens returns the model's context window size in tokens.
func (*ContextManager) NeedsCompaction ¶
func (cm *ContextManager) NeedsCompaction(messages []provider.Message) bool
NeedsCompaction returns true if the estimated token count exceeds the threshold.
func (*ContextManager) SetModelLimit ¶
func (cm *ContextManager) SetModelLimit(model string, limit int)
SetModelLimit overrides the context token limit for a specific model name pattern. This allows module config to adjust limits without modifying the built-in defaults.
func (*ContextManager) TokenUsage ¶
func (cm *ContextManager) TokenUsage(messages []provider.Message) (estimated, limit int)
TokenUsage returns the current estimated tokens and the context limit.
type HumanRequest ¶
type HumanRequest struct {
ID string
RequestType RequestType
Status RequestStatus
ResponseData string
ResponseComment string
Metadata string // JSON
}
HumanRequest is a resolved human request record.
type HumanRequester ¶
type HumanRequester interface {
// WaitForResolution blocks until the request with the given ID is resolved
// or the timeout elapses.
WaitForResolution(ctx context.Context, requestID string, timeout time.Duration) (*HumanRequest, error)
}
HumanRequester manages blocking human-request gates.
type LoopDetector ¶
type LoopDetector struct {
// contains filtered or unexported fields
}
LoopDetector detects agent execution loops using multiple heuristics.
func NewLoopDetector ¶
func NewLoopDetector(cfg LoopDetectorConfig) *LoopDetector
NewLoopDetector creates a LoopDetector with the given config. Zero values in cfg are replaced with defaults (MaxConsecutive=3, MaxErrors=2, MaxAlternating=3, MaxNoProgress=3).
func (*LoopDetector) Check ¶
func (ld *LoopDetector) Check() (LoopStatus, string)
Check evaluates the recorded history for loop patterns and returns the current status along with a human-readable explanation. Checks are evaluated in priority order: hard breaks take precedence over warnings.
type LoopDetectorConfig ¶
type LoopDetectorConfig struct {
// MaxConsecutive is the number of identical consecutive tool calls before a loop is detected.
// Default: 3.
MaxConsecutive int
// MaxErrors is the number of times the same tool call can return the same error before a loop is detected.
// Default: 2.
MaxErrors int
// MaxAlternating is the number of A/B alternating cycles before a loop is detected.
// Default: 3.
MaxAlternating int
// MaxNoProgress is the number of identical (same args + same result) non-error calls before a loop is detected.
// Default: 3.
MaxNoProgress int
}
LoopDetectorConfig holds configurable thresholds for loop detection.
type LoopStatus ¶
type LoopStatus int
LoopStatus represents the result of a loop check.
const ( // LoopStatusOK means no loop detected. LoopStatusOK LoopStatus = iota // LoopStatusWarning means a potential loop pattern is forming. LoopStatusWarning // LoopStatusBreak means a definitive loop is detected; execution should stop. LoopStatusBreak )
type MemoryEntry ¶
MemoryEntry is a single piece of persistent agent memory.
type MemoryStore ¶
type MemoryStore interface {
// Search finds relevant memories for agentID using query text.
Search(ctx context.Context, agentID, query string, limit int) ([]MemoryEntry, error)
// Save persists a memory entry.
Save(ctx context.Context, entry MemoryEntry) error
// ExtractAndSave extracts facts from a transcript and saves them.
ExtractAndSave(ctx context.Context, agentID, transcript string, embedder provider.Embedder) error
}
MemoryStore provides persistent memory storage and retrieval.
type NullApprover ¶
type NullApprover struct{}
NullApprover is a no-op Approver — always returns "approved".
func (*NullApprover) WaitForResolution ¶
func (n *NullApprover) WaitForResolution(_ context.Context, _ string, _ time.Duration) (*ApprovalRecord, error)
type NullHumanRequester ¶
type NullHumanRequester struct{}
NullHumanRequester is a no-op HumanRequester — always returns expired.
func (*NullHumanRequester) WaitForResolution ¶
func (n *NullHumanRequester) WaitForResolution(_ context.Context, _ string, _ time.Duration) (*HumanRequest, error)
type NullMemoryStore ¶
type NullMemoryStore struct{}
NullMemoryStore is a no-op MemoryStore.
func (*NullMemoryStore) ExtractAndSave ¶
func (*NullMemoryStore) Save ¶
func (n *NullMemoryStore) Save(_ context.Context, _ MemoryEntry) error
func (*NullMemoryStore) Search ¶
func (n *NullMemoryStore) Search(_ context.Context, _, _ string, _ int) ([]MemoryEntry, error)
type NullSecretRedactor ¶
type NullSecretRedactor struct{}
NullSecretRedactor is a no-op SecretRedactor.
func (*NullSecretRedactor) CheckAndRedact ¶
func (n *NullSecretRedactor) CheckAndRedact(_ *provider.Message)
func (*NullSecretRedactor) Redact ¶
func (n *NullSecretRedactor) Redact(text string) string
type NullTranscript ¶
type NullTranscript struct{}
NullTranscript is a no-op TranscriptRecorder.
func (*NullTranscript) Record ¶
func (n *NullTranscript) Record(_ context.Context, _ TranscriptEntry) error
type RequestStatus ¶
type RequestStatus string
RequestStatus represents the resolution state of a human request.
const ( RequestPending RequestStatus = "pending" RequestResolved RequestStatus = "resolved" RequestCancelled RequestStatus = "cancelled" RequestExpired RequestStatus = "expired" )
type RequestType ¶
type RequestType string
RequestType categorizes what the agent needs from the human.
const ( RequestTypeToken RequestType = "token" RequestTypeBinary RequestType = "binary" RequestTypeAccess RequestType = "access" RequestTypeInfo RequestType = "info" RequestTypeCustom RequestType = "custom" )
type Result ¶
type Result struct {
Content string
Thinking string
Iterations int
Status string // "completed", "failed", "loop_detected", "approval_timeout", "request_expired"
Error string
}
Result is the outcome of an Execute call.
func Execute ¶
func Execute(ctx context.Context, cfg Config, systemPrompt, userTask, agentID string) (*Result, error)
Execute runs the autonomous agent loop with the given config. systemPrompt is the agent's system instructions; userTask is the task to complete; agentID is the agent's identifier used for memory and transcript recording.
type SecretRedactor ¶
type SecretRedactor interface {
// Redact returns the text with known secrets replaced.
Redact(text string) string
// CheckAndRedact redacts secrets from a message in place.
CheckAndRedact(msg *provider.Message)
}
SecretRedactor redacts secrets from text.
type TranscriptEntry ¶
type TranscriptEntry struct {
ID string
AgentID string
TaskID string
ProjectID string
Iteration int
Role provider.Role
Content string
Thinking string
ToolCalls []provider.ToolCall
ToolCallID string
}
TranscriptEntry is a single recorded message in the agent conversation.
type TranscriptRecorder ¶
type TranscriptRecorder interface {
Record(ctx context.Context, entry TranscriptEntry) error
}
TranscriptRecorder records agent interactions.