events

package
v1.0.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Mar 11, 2026 License: AGPL-3.0 Imports: 5 Imported by: 0

Documentation

Overview

Package events provides event types and handling for the agent loop.

Events allow external systems to observe agent behavior, collect metrics, and implement logging without coupling to the agent implementation.

Thread Safety:

All types in this package are designed for concurrent use.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type ContextUpdateData

type ContextUpdateData struct {
	// Action is what happened (e.g., "add", "evict", "update").
	Action string `json:"action"`

	// EntriesAffected is the number of entries affected.
	EntriesAffected int `json:"entries_affected"`

	// TokensBefore is the token count before the update.
	TokensBefore int `json:"tokens_before"`

	// TokensAfter is the token count after the update.
	TokensAfter int `json:"tokens_after"`
}

ContextUpdateData is the data for context update events.

type Emitter

type Emitter struct {
	// contains filtered or unexported fields
}

Emitter broadcasts events to subscribers.

Thread Safety: Emitter is safe for concurrent use.

func NewEmitter

func NewEmitter(opts ...EmitterOption) *Emitter

NewEmitter creates a new event emitter.

func (*Emitter) ClearBuffer

func (e *Emitter) ClearBuffer()

ClearBuffer removes all buffered events.

func (*Emitter) CurrentStep

func (e *Emitter) CurrentStep() int

CurrentStep returns the current step number without incrementing.

func (*Emitter) Emit

func (e *Emitter) Emit(eventType Type, data any)

Emit broadcasts an event to all matching subscribers.

Inputs:

eventType - The type of event.
data - Event-specific data.

func (*Emitter) EmitWithMetadata

func (e *Emitter) EmitWithMetadata(eventType Type, data any, metadata *EventMetadata)

EmitWithMetadata broadcasts an event with additional metadata.

Description:

Creates an event with the specified type, data, and metadata, then
broadcasts it to all matching subscribers. The event is also buffered
for later retrieval. Handler panics are recovered to prevent one
failing handler from crashing the emitter.

Inputs:

eventType - The type of event.
data - Event-specific data (use typed data structs from types.go).
metadata - Additional context (nil is allowed).

Thread Safety: This method is safe for concurrent use.

func (*Emitter) GetBuffer

func (e *Emitter) GetBuffer() []Event

GetBuffer returns a copy of buffered events.

func (*Emitter) GetBufferByType

func (e *Emitter) GetBufferByType(eventType Type) []Event

GetBufferByType returns buffered events of a specific type.

func (*Emitter) GetBufferSince

func (e *Emitter) GetBufferSince(since time.Time) []Event

GetBufferSince returns events since a timestamp.

func (*Emitter) IncrementStep

func (e *Emitter) IncrementStep() int

IncrementStep increments and returns the new step number.

func (*Emitter) Reset

func (e *Emitter) Reset()

Reset clears all state including subscriptions and buffer.

func (*Emitter) SetSessionID

func (e *Emitter) SetSessionID(id string)

SetSessionID updates the session ID for future events.

func (*Emitter) SetStep

func (e *Emitter) SetStep(step int)

SetStep updates the current step number.

func (*Emitter) Subscribe

func (e *Emitter) Subscribe(handler Handler, types ...Type) string

Subscribe registers a handler for events.

Inputs:

handler - Function to call for each event.
types - Event types to subscribe to (nil = all types).

Outputs:

string - Subscription ID for unsubscribing.

func (*Emitter) SubscribeWithFilter

func (e *Emitter) SubscribeWithFilter(handler Handler, filter Filter, types ...Type) string

SubscribeWithFilter registers a handler with a custom filter.

Inputs:

handler - Function to call for matching events.
filter - Custom filter function (nil = no filter).
types - Event types to subscribe to (nil = all types).

Outputs:

string - Subscription ID for unsubscribing.

func (*Emitter) SubscriptionCount

func (e *Emitter) SubscriptionCount() int

SubscriptionCount returns the number of active subscriptions.

func (*Emitter) Unsubscribe

func (e *Emitter) Unsubscribe(id string) bool

Unsubscribe removes a subscription.

Inputs:

id - The subscription ID to remove.

Outputs:

bool - True if the subscription was found and removed.

type EmitterOption

type EmitterOption func(*Emitter)

EmitterOption configures an Emitter.

func WithBufferSize

func WithBufferSize(size int) EmitterOption

WithBufferSize sets the event buffer size.

func WithSessionID

func WithSessionID(id string) EmitterOption

WithSessionID sets the session ID for all events.

type ErrorContext

type ErrorContext struct {
	// ToolName is the tool that caused the error, if applicable.
	ToolName string `json:"tool_name,omitempty"`

	// InvocationID links to the tool invocation that failed.
	InvocationID string `json:"invocation_id,omitempty"`

	// FilePath is the file involved in the error, if applicable.
	FilePath string `json:"file_path,omitempty"`

	// SymbolID is the symbol involved in the error, if applicable.
	SymbolID string `json:"symbol_id,omitempty"`

	// Phase is the agent phase where the error occurred.
	Phase string `json:"phase,omitempty"`

	// StepNumber is the step where the error occurred.
	StepNumber int `json:"step_number,omitempty"`

	// StackTrace is the stack trace, if available.
	StackTrace string `json:"stack_trace,omitempty"`
}

ErrorContext contains typed context for error events.

type ErrorData

type ErrorData struct {
	// Error is the error message.
	Error string `json:"error"`

	// Code is a machine-readable error code.
	Code string `json:"code,omitempty"`

	// Recoverable indicates if the error can be recovered from.
	Recoverable bool `json:"recoverable"`

	// Context provides typed additional error context.
	Context *ErrorContext `json:"context,omitempty"`
}

ErrorData is the data for error events.

type Event

type Event struct {
	// ID is a unique identifier for this event.
	ID string `json:"id"`

	// Type identifies the kind of event.
	Type Type `json:"type"`

	// SessionID links the event to a session.
	SessionID string `json:"session_id"`

	// Timestamp is when the event occurred (Unix milliseconds UTC).
	Timestamp int64 `json:"timestamp"`

	// Step is the agent step number when this event occurred.
	Step int `json:"step"`

	// Data contains event-specific data. Should be one of the typed
	// data structs: StateTransitionData, ToolInvocationData, ToolResultData,
	// ContextUpdateData, LLMRequestData, LLMResponseData, SafetyCheckData,
	// ReflectionData, ErrorData, SessionStartData, SessionEndData, or StepCompleteData.
	Data any `json:"data,omitempty"`

	// Metadata contains typed additional context for the event.
	Metadata *EventMetadata `json:"metadata,omitempty"`
}

Event represents an agent event.

Description:

Events are the primary mechanism for observing agent behavior.
Each event has a type that determines the structure of its Data field.
Use the appropriate typed data struct (StateTransitionData, ToolResultData, etc.)
when setting the Data field.

Thread Safety:

Event structs should be treated as immutable after creation.

type EventMetadata

type EventMetadata struct {
	// TraceID links the event to a distributed trace.
	TraceID string `json:"trace_id,omitempty"`

	// SpanID links the event to a specific span.
	SpanID string `json:"span_id,omitempty"`

	// Source identifies where the event originated.
	Source string `json:"source,omitempty"`

	// Tags are key-value pairs for categorization.
	Tags map[string]string `json:"tags,omitempty"`

	// Priority indicates event importance (higher = more important).
	Priority int `json:"priority,omitempty"`
}

EventMetadata contains typed additional context for events.

type Filter

type Filter func(event *Event) bool

Filter is a function that determines if an event should be handled.

func ErrorFilter

func ErrorFilter() Filter

ErrorFilter creates a filter that only passes error events.

func PerformanceFilter

func PerformanceFilter() Filter

PerformanceFilter creates a filter for performance-related events.

func SessionFilter

func SessionFilter(sessionID string) Filter

SessionFilter creates a filter that matches a specific session.

func TypeFilter

func TypeFilter(types ...Type) Filter

TypeFilter creates a filter that matches specific event types.

type Handler

type Handler func(event *Event)

Handler is a function that processes events.

func ChannelHandler

func ChannelHandler(ch chan<- Event, dropOnFull bool) Handler

ChannelHandler creates a handler that sends events to a channel.

Inputs:

ch - The channel to send events to.
dropOnFull - If true, drops events when channel is full; if false, blocks.

Outputs:

Handler - A handler function that sends events to the channel.

func FilteredHandler

func FilteredHandler(handler Handler, filter Filter) Handler

FilteredHandler creates a handler that only processes events matching a filter.

Inputs:

handler - The underlying handler.
filter - The filter function.

Outputs:

Handler - A handler that filters events before processing.

func LoggingHandler

func LoggingHandler(logger *slog.Logger, level slog.Level) Handler

LoggingHandler creates a handler that logs events.

Inputs:

logger - The slog logger to use.
level - The log level for events.

Outputs:

Handler - A handler function that logs events.

func MultiHandler

func MultiHandler(handlers ...Handler) Handler

MultiHandler creates a handler that calls multiple handlers.

Inputs:

handlers - The handlers to call.

Outputs:

Handler - A handler that calls all provided handlers.

type LLMRequestData

type LLMRequestData struct {
	// Model is the model being used.
	Model string `json:"model"`

	// TokensIn is the input token count.
	TokensIn int `json:"tokens_in"`

	// HasTools indicates if tools were included.
	HasTools bool `json:"has_tools"`

	// ToolCount is the number of tools available.
	ToolCount int `json:"tool_count,omitempty"`

	// SystemPromptLen is the length of the system prompt in characters.
	// Full system prompt is not included to avoid bloating logs.
	SystemPromptLen int `json:"system_prompt_len,omitempty"`

	// MessageCount is the number of messages in the conversation history.
	MessageCount int `json:"message_count,omitempty"`

	// MessageSummary shows role distribution: "user:3,assistant:2,tool:5"
	MessageSummary string `json:"message_summary,omitempty"`

	// LastUserMessage is the last user message (truncated to 500 chars).
	// This is the query being answered - critical for debugging.
	LastUserMessage string `json:"last_user_message,omitempty"`

	// ToolNames lists the available tools (for understanding what agent can do).
	ToolNames []string `json:"tool_names,omitempty"`
}

LLMRequestData is the data for LLM request events.

type LLMResponseData

type LLMResponseData struct {
	// Model is the model that responded.
	Model string `json:"model"`

	// TokensOut is the output token count.
	TokensOut int `json:"tokens_out"`

	// Duration is how long the request took.
	Duration time.Duration `json:"duration"`

	// StopReason is why generation stopped.
	StopReason string `json:"stop_reason"`

	// HasToolCalls indicates if the response includes tool calls.
	HasToolCalls bool `json:"has_tool_calls"`

	// ToolCallCount is the number of tool calls.
	ToolCallCount int `json:"tool_call_count,omitempty"`

	// ContentLen is the length of the text content in characters.
	ContentLen int `json:"content_len,omitempty"`

	// ContentPreview is the first 500 chars of the text content.
	// Critical for debugging empty response issues like CB-31/Test 30.
	ContentPreview string `json:"content_preview,omitempty"`

	// ToolCallsPreview summarizes tool calls: "Grep(query=main),ReadFile(path=main.go)"
	ToolCallsPreview string `json:"tool_calls_preview,omitempty"`
}

LLMResponseData is the data for LLM response events.

type Metrics

type Metrics struct {
	SessionCount         int64         `json:"session_count"`
	StepCount            int64         `json:"step_count"`
	ToolInvocations      int64         `json:"tool_invocations"`
	LLMRequests          int64         `json:"llm_requests"`
	SafetyChecks         int64         `json:"safety_checks"`
	ErrorCount           int64         `json:"error_count"`
	BlockedBySefetyCount int64         `json:"blocked_by_safety_count"`
	TotalInputTokens     int64         `json:"total_input_tokens"`
	TotalOutputTokens    int64         `json:"total_output_tokens"`
	AvgToolDuration      time.Duration `json:"avg_tool_duration"`
	AvgLLMDuration       time.Duration `json:"avg_llm_duration"`
	AvgStepDuration      time.Duration `json:"avg_step_duration"`
	AvgSessionDuration   time.Duration `json:"avg_session_duration"`
	ActiveSession        string        `json:"active_session,omitempty"`
}

Metrics returns a snapshot of collected metrics.

type MetricsCollector

type MetricsCollector struct {
	// contains filtered or unexported fields
}

MetricsCollector collects metrics from events.

Thread Safety: MetricsCollector is safe for concurrent use.

func NewMetricsCollector

func NewMetricsCollector() *MetricsCollector

NewMetricsCollector creates a new metrics collector.

func (*MetricsCollector) GetMetrics

func (c *MetricsCollector) GetMetrics() Metrics

GetMetrics returns a snapshot of collected metrics.

func (*MetricsCollector) Handler

func (c *MetricsCollector) Handler() Handler

Handler returns an event handler for the collector.

func (*MetricsCollector) Reset

func (c *MetricsCollector) Reset()

Reset clears all collected metrics.

type MockEmitter

type MockEmitter struct {
	Events []Event
	// contains filtered or unexported fields
}

MockEmitter is a mock emitter for testing.

func NewMockEmitter

func NewMockEmitter() *MockEmitter

NewMockEmitter creates a new mock emitter.

func (*MockEmitter) Clear

func (m *MockEmitter) Clear()

Clear removes all recorded events.

func (*MockEmitter) Emit

func (m *MockEmitter) Emit(eventType Type, data any)

Emit records an event.

func (*MockEmitter) EmitWithMetadata

func (m *MockEmitter) EmitWithMetadata(eventType Type, data any, metadata *EventMetadata)

EmitWithMetadata records an event with metadata.

func (*MockEmitter) EventCount

func (m *MockEmitter) EventCount() int

EventCount returns the number of recorded events.

func (*MockEmitter) GetEvents

func (m *MockEmitter) GetEvents() []Event

GetEvents returns all recorded events.

func (*MockEmitter) GetEventsByType

func (m *MockEmitter) GetEventsByType(eventType Type) []Event

GetEventsByType returns events of a specific type.

type ReflectionData

type ReflectionData struct {
	// StepsCompleted is the number of steps completed so far.
	StepsCompleted int `json:"steps_completed"`

	// TokensUsed is the total tokens used so far.
	TokensUsed int `json:"tokens_used"`

	// Decision is the reflection outcome.
	Decision string `json:"decision"`

	// Reason explains the decision.
	Reason string `json:"reason,omitempty"`
}

ReflectionData is the data for reflection events.

type SafetyCheckData

type SafetyCheckData struct {
	// ChangesChecked is the number of changes checked.
	ChangesChecked int `json:"changes_checked"`

	// Passed indicates if the check passed.
	Passed bool `json:"passed"`

	// CriticalCount is the number of critical issues.
	CriticalCount int `json:"critical_count"`

	// WarningCount is the number of warnings.
	WarningCount int `json:"warning_count"`

	// Blocked indicates if execution was blocked.
	Blocked bool `json:"blocked"`
}

SafetyCheckData is the data for safety check events.

type SessionEndData

type SessionEndData struct {
	// FinalState is the state when the session ended.
	FinalState agent.AgentState `json:"final_state"`

	// TotalSteps is the number of steps executed.
	TotalSteps int `json:"total_steps"`

	// TotalDuration is how long the session lasted.
	TotalDuration time.Duration `json:"total_duration"`

	// TotalTokens is the total tokens used.
	TotalTokens int `json:"total_tokens"`

	// Success indicates if the session completed successfully.
	Success bool `json:"success"`

	// Error is set if the session ended with an error.
	Error string `json:"error,omitempty"`
}

SessionEndData is the data for session end events.

type SessionStartData

type SessionStartData struct {
	// Query is the initial user query.
	Query string `json:"query"`

	// ProjectRoot is the project directory.
	ProjectRoot string `json:"project_root"`

	// GraphID is the code graph being used.
	GraphID string `json:"graph_id,omitempty"`
}

SessionStartData is the data for session start events.

type StateTransitionData

type StateTransitionData struct {
	// FromState is the previous state.
	FromState agent.AgentState `json:"from_state"`

	// ToState is the new state.
	ToState agent.AgentState `json:"to_state"`

	// Reason explains why the transition occurred.
	Reason string `json:"reason,omitempty"`
}

StateTransitionData is the data for state transition events.

type StepCompleteData

type StepCompleteData struct {
	// StepNumber is the step that completed.
	StepNumber int `json:"step_number"`

	// Duration is how long the step took.
	Duration time.Duration `json:"duration"`

	// ToolsInvoked is the number of tools invoked in this step.
	ToolsInvoked int `json:"tools_invoked"`

	// TokensUsed is the tokens used in this step.
	TokensUsed int `json:"tokens_used"`
}

StepCompleteData is the data for step complete events.

type Subscription

type Subscription struct {
	// ID uniquely identifies this subscription.
	ID string

	// Handler processes matching events.
	Handler Handler

	// Filter determines which events to handle (nil = all events).
	Filter Filter

	// Types limits which event types to handle (nil = all types).
	Types []Type
}

Subscription represents a subscription to events.

type ToolForcingData

type ToolForcingData struct {
	// Query is the user's analytical query.
	Query string `json:"query"`

	// SuggestedTool is the tool being suggested in the forcing hint.
	SuggestedTool string `json:"suggested_tool,omitempty"`

	// RetryCount is the current tool forcing retry attempt.
	RetryCount int `json:"retry_count"`

	// MaxRetries is the maximum number of retries allowed.
	MaxRetries int `json:"max_retries"`

	// StepNumber is the step where forcing occurred.
	StepNumber int `json:"step_number"`

	// Reason explains why tool forcing was triggered.
	Reason string `json:"reason,omitempty"`
}

ToolForcingData is the data for tool forcing events.

type ToolInvocationData

type ToolInvocationData struct {
	// ToolName is the name of the tool being invoked.
	ToolName string `json:"tool_name"`

	// InvocationID uniquely identifies this invocation.
	InvocationID string `json:"invocation_id"`

	// Parameters are the typed tool parameters.
	Parameters *ToolInvocationParameters `json:"parameters,omitempty"`
}

ToolInvocationData is the data for tool invocation events.

type ToolInvocationParameters

type ToolInvocationParameters struct {
	// StringParams contains string parameter values.
	StringParams map[string]string `json:"string_params,omitempty"`

	// IntParams contains integer parameter values.
	IntParams map[string]int `json:"int_params,omitempty"`

	// BoolParams contains boolean parameter values.
	BoolParams map[string]bool `json:"bool_params,omitempty"`

	// RawJSON contains the original JSON if parsing into typed maps failed.
	RawJSON []byte `json:"raw_json,omitempty"`
}

ToolInvocationParameters contains typed parameters for tool invocation events.

type ToolResultData

type ToolResultData struct {
	// ToolName is the name of the tool.
	ToolName string `json:"tool_name"`

	// InvocationID links to the invocation.
	InvocationID string `json:"invocation_id"`

	// Success indicates if the tool succeeded.
	Success bool `json:"success"`

	// Duration is how long the tool took.
	Duration time.Duration `json:"duration"`

	// TokensUsed is the output token count.
	TokensUsed int `json:"tokens_used,omitempty"`

	// Cached indicates if the result was cached.
	Cached bool `json:"cached,omitempty"`

	// Error is set if the tool failed.
	Error string `json:"error,omitempty"`
}

ToolResultData is the data for tool result events.

type Type

type Type string

Type identifies the kind of event.

const (
	// TypeStateTransition is emitted when the agent changes state.
	TypeStateTransition Type = "state_transition"

	// TypeToolInvocation is emitted when a tool is about to be invoked.
	TypeToolInvocation Type = "tool_invocation"

	// TypeToolResult is emitted when a tool returns a result.
	TypeToolResult Type = "tool_result"

	// TypeContextUpdate is emitted when context is modified.
	TypeContextUpdate Type = "context_update"

	// TypeLLMRequest is emitted when sending a request to the LLM.
	TypeLLMRequest Type = "llm_request"

	// TypeLLMResponse is emitted when receiving a response from the LLM.
	TypeLLMResponse Type = "llm_response"

	// TypeSafetyCheck is emitted when a safety check is performed.
	TypeSafetyCheck Type = "safety_check"

	// TypeReflection is emitted during reflection phase.
	TypeReflection Type = "reflection"

	// TypeError is emitted when an error occurs.
	TypeError Type = "error"

	// TypeSessionStart is emitted when a session begins.
	TypeSessionStart Type = "session_start"

	// TypeSessionEnd is emitted when a session ends.
	TypeSessionEnd Type = "session_end"

	// TypeStepComplete is emitted when a step is completed.
	TypeStepComplete Type = "step_complete"

	// TypeToolForcing is emitted when tool usage is being forced for an analytical query.
	TypeToolForcing Type = "tool_forcing"
)

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL