Documentation
¶
Index ¶
- Constants
- func Execute(ctx context.Context, event EventType, data map[string]interface{}) error
- func ExecuteAsync(ctx context.Context, event EventType, data map[string]interface{})
- func ExecuteAsyncEnvelope(ctx context.Context, env EventEnvelope)
- func ExecuteEnvelope(ctx context.Context, env EventEnvelope) error
- func FormatEvent(event Event) string
- func LoadConventionPolicies(cwd string) int
- func LoadHooksDir(dir string) error
- func Register(h Hook)
- func RegisterDecisionHook(fn DecisionHookFn)
- func RegisterDecisionHookWithConfig(config DecisionHookConfig, fn DecisionHookFn)
- func ResetDecisionHooks()
- type DecisionHookConfig
- type DecisionHookFn
- type DecisionMatcher
- type Diagnostic
- type EnvelopeFn
- type Event
- type EventBus
- func (eb *EventBus) Emit(event Event)
- func (eb *EventBus) GetHistory(eventType string, limit int) []Event
- func (eb *EventBus) OnError(fn func(err error))
- func (eb *EventBus) OnFileWrite(fn func(path string))
- func (eb *EventBus) OnSessionEnd(fn func(duration time.Duration, tokens int))
- func (eb *EventBus) OnToolCall(fn func(tool string, duration time.Duration))
- func (eb *EventBus) Register(hook *LifecycleHook)
- func (eb *EventBus) Stats() EventStats
- func (eb *EventBus) Subscribe(eventType string) <-chan Event
- func (eb *EventBus) Unregister(hookID string)
- func (eb *EventBus) Unsubscribe(eventType string, ch <-chan Event)
- type EventEnvelope
- type EventStats
- type EventType
- type Hook
- type HookDecision
- func Allow() *HookDecision
- func Deny(reason string) *HookDecision
- func ExecuteDecisionHooks(event string, data map[string]interface{}) *HookDecision
- func ExecuteDecisionHooksSafe(event string, data map[string]interface{}) *HookDecision
- func Instruct(message string) *HookDecision
- func Modify(reason string, modifiedInput json.RawMessage) *HookDecision
- type LSPFeedbackProvider
- type LifecycleHook
- type Registry
- func (r *Registry) Execute(ctx context.Context, event EventType, data map[string]interface{}) error
- func (r *Registry) ExecuteAsync(_ context.Context, event EventType, data map[string]interface{})
- func (r *Registry) ExecuteAsyncEnvelope(_ context.Context, env EventEnvelope)
- func (r *Registry) ExecuteEnvelope(ctx context.Context, env EventEnvelope) error
- func (r *Registry) Register(h Hook)
- type WrappedDecisionHook
Constants ¶
const ( ActionAllow = "allow" ActionDeny = "deny" ActionModify = "modify" ActionInstruct = "instruct" )
DecisionAction constants for HookDecision.Action.
const ( SessionStart = "session.start" SessionEnd = "session.end" TurnStart = "turn.start" TurnEnd = "turn.end" ToolCallStart = "tool_call.start" ToolCallEnd = "tool_call.end" ToolCallError = "tool_call.error" FileRead = "file.read" FileWrite = "file.write" FileEdit = "file.edit" FileDelete = "file.delete" CompactionStart = "compaction.start" CompactionEnd = "compaction.end" BudgetWarning = "budget.warning" BudgetExceeded = "budget.exceeded" ErrorOccurred = "error.occurred" ErrorRecovered = "error.recovered" ModelSwitch = "model.switch" ProviderSwitch = "provider.switch" UserInput = "user.input" AgentResponse = "agent.response" // Review lifecycle events ReviewQueued = "review.queued" ReviewStarted = "review.started" ReviewCompleted = "review.completed" ReviewFailed = "review.failed" ReviewFixed = "review.fixed" )
LifecycleEventType constants representing agent lifecycle events.
Variables ¶
This section is empty.
Functions ¶
func ExecuteAsync ¶
ExecuteAsync runs hooks asynchronously on the global registry.
func ExecuteAsyncEnvelope ¶
func ExecuteAsyncEnvelope(ctx context.Context, env EventEnvelope)
ExecuteAsyncEnvelope runs hooks asynchronously on the global registry using a typed envelope.
func ExecuteEnvelope ¶
func ExecuteEnvelope(ctx context.Context, env EventEnvelope) error
ExecuteEnvelope runs all hooks for an event on the global registry using a typed envelope.
func FormatEvent ¶
FormatEvent returns a human-readable log line for the event.
func LoadConventionPolicies ¶
LoadConventionPolicies discovers and loads convention policy files. Convention: auto-discovered *policy*.{md,go} files from:
- {cwd}/.agents/policies/ (project scope)
- Hawk user state policies directory
Returns the number of policies loaded.
func RegisterDecisionHook ¶
func RegisterDecisionHook(fn DecisionHookFn)
RegisterDecisionHook adds a decision hook to the global list.
func RegisterDecisionHookWithConfig ¶
func RegisterDecisionHookWithConfig(config DecisionHookConfig, fn DecisionHookFn)
RegisterDecisionHookWithConfig adds a decision hook with matching and priority.
func ResetDecisionHooks ¶
func ResetDecisionHooks()
ResetDecisionHooks clears all registered decision hooks. Intended for testing.
Types ¶
type DecisionHookConfig ¶
type DecisionHookConfig struct {
Name string
Matcher DecisionMatcher
Priority int // Lower = earlier evaluation
}
DecisionHookConfig configures a decision hook with matching and priority.
type DecisionHookFn ¶
type DecisionHookFn func(event string, data map[string]interface{}) *HookDecision
DecisionHookFn is a function that inspects an event and optionally returns a decision. Returning nil means "no opinion" (proceed normally).
type DecisionMatcher ¶
type DecisionMatcher struct {
Events []string // Event types to match (e.g., "pre_tool", "post_tool")
ToolNames []string // Tool names to match (e.g., "Bash", "Write", "Edit")
}
DecisionMatcher specifies which events and tools a decision hook applies to. Empty arrays mean "match all".
type Diagnostic ¶
type Diagnostic struct {
Line int
Column int
Severity int // 1=error, 2=warning, 3=info, 4=hint
Code string
Message string
}
Diagnostic mirrors lsp.Diagnostic to avoid import cycle.
type EnvelopeFn ¶
type EnvelopeFn func(ctx context.Context, envelope EventEnvelope) error
EnvelopeFn is the typed hook function signature using EventEnvelope.
func AdaptLegacyFn ¶
func AdaptLegacyFn(fn func(ctx context.Context, data map[string]interface{}) error) EnvelopeFn
AdaptLegacyFn wraps a legacy hook function into an EnvelopeFn. The legacy function receives only the payload from the envelope.
type EventBus ¶
type EventBus struct {
Hooks map[string][]*LifecycleHook
Listeners map[string][]chan Event
History []Event
MaxHistory int
// contains filtered or unexported fields
}
EventBus is the central publish/subscribe mechanism for lifecycle events.
func NewEventBus ¶
func NewEventBus() *EventBus
NewEventBus creates a new EventBus with sensible defaults.
func (*EventBus) Emit ¶
Emit fires all hooks for the event type and sends to listeners. Synchronous hooks run in priority order; async hooks run in goroutines.
func (*EventBus) GetHistory ¶
GetHistory returns the most recent events of the given type, limited to `limit`. If eventType is empty, all events are considered.
func (*EventBus) OnFileWrite ¶
OnFileWrite registers a convenience hook that fires on FileWrite events.
func (*EventBus) OnSessionEnd ¶
OnSessionEnd registers a convenience hook that fires when a session ends.
func (*EventBus) OnToolCall ¶
OnToolCall registers a convenience hook that fires when a tool call completes.
func (*EventBus) Register ¶
func (eb *EventBus) Register(hook *LifecycleHook)
Register adds a hook to the bus for its configured event type.
func (*EventBus) Stats ¶
func (eb *EventBus) Stats() EventStats
Stats returns aggregate statistics about the event bus.
func (*EventBus) Unregister ¶
Unregister removes a hook by its ID from all event types.
func (*EventBus) Unsubscribe ¶
Unsubscribe removes a previously subscribed channel.
type EventEnvelope ¶
type EventEnvelope struct {
Timestamp time.Time `json:"timestamp"`
Source string `json:"source"` // e.g. "hooks", "mission", "plugin"
SessionID string `json:"session_id"` // session that triggered the event
AgentID string `json:"agent_id"` // agent that triggered the event
CorrelationID string `json:"correlation_id"` // traces across hook chains
EventType EventType `json:"event_type"`
Payload map[string]interface{} `json:"payload"` // event-specific data
}
EventEnvelope provides structured, typed metadata for hook events. It wraps the raw payload with tracing and context fields.
type EventStats ¶
type EventStats struct {
TotalEvents int
ByType map[string]int
HookCount int
AsyncHooks int
AvgHookTime time.Duration
}
EventStats provides aggregate statistics about the event bus.
type EventType ¶
type EventType string
EventType represents a hook event.
const ( EventPreQuery EventType = "pre_query" EventPostQuery EventType = "post_query" EventPreTool EventType = "pre_tool" EventPostTool EventType = "post_tool" EventPreCompact EventType = "pre_compact" EventPostCompact EventType = "post_compact" EventFileChanged EventType = "file_changed" EventSessionStart EventType = "session_start" EventSessionEnd EventType = "session_end" EventPermissionAsk EventType = "permission_ask" EventError EventType = "error" )
type Hook ¶
type Hook struct {
Name string
Event EventType
Priority int // lower = earlier
Fn func(ctx context.Context, data map[string]interface{}) error // legacy
FnV2 EnvelopeFn // typed envelope (preferred)
}
Hook is a registered hook function.
func BuiltinHooks ¶
func BuiltinHooks() []Hook
BuiltinHooks returns the default set of built-in hooks.
func LSPFeedbackHook ¶
func LSPFeedbackHook(provider LSPFeedbackProvider) Hook
LSPFeedbackHook creates a hook that runs LSP diagnostics after file edits and provides blocking feedback when errors are found.
type HookDecision ¶
type HookDecision struct {
Action string `json:"action"` // "allow", "deny", "modify", "instruct"
Reason string `json:"reason,omitempty"`
Message string `json:"message,omitempty"` // User-facing message (for deny/instruct)
ModifiedInput json.RawMessage `json:"modified_input,omitempty"`
}
HookDecision represents the outcome of a decision hook.
func ExecuteDecisionHooks ¶
func ExecuteDecisionHooks(event string, data map[string]interface{}) *HookDecision
ExecuteDecisionHooks runs all registered decision hooks for the given event. It respects matchers (event type + tool name) and returns the first non-nil decision. If all hooks return nil, the result is nil (meaning no opinion, proceed normally). Fail-open: hook errors are logged but do not block the operation.
func ExecuteDecisionHooksSafe ¶
func ExecuteDecisionHooksSafe(event string, data map[string]interface{}) *HookDecision
ExecuteDecisionHooksSafe runs all registered decision hooks with full fail-open semantics. Returns the first non-nil decision, or nil if all hooks return nil or panic.
func Instruct ¶
func Instruct(message string) *HookDecision
Instruct creates an instruct decision that injects context without blocking. The agent receives the message as guidance for its next action.
func Modify ¶
func Modify(reason string, modifiedInput json.RawMessage) *HookDecision
Modify creates a modify decision with modified input.
type LSPFeedbackProvider ¶
type LSPFeedbackProvider interface {
// DiagnosticsForFile returns diagnostics for a file path.
// Returns nil if no LSP server is available for the file type.
DiagnosticsForFile(ctx context.Context, filePath string) ([]Diagnostic, error)
}
LSPFeedbackProvider abstracts LSP diagnostics for the feedback hook. This interface allows the hook to call into the LSP manager without creating an import cycle.
type LifecycleHook ¶
type LifecycleHook struct {
ID string
Name string
Event string
Handler func(Event) error
Priority int
Async bool
Enabled bool
}
LifecycleHook is a registered handler for lifecycle events on the EventBus.
type Registry ¶
type Registry struct {
// contains filtered or unexported fields
}
Registry stores and executes hooks.
func (*Registry) Execute ¶
Execute runs all hooks for an event. Fail-open: hook errors are logged but do not stop execution of subsequent hooks.
func (*Registry) ExecuteAsync ¶
ExecuteAsync runs hooks asynchronously (fire and forget). Uses a fresh context to avoid passing a cancelled caller context.
func (*Registry) ExecuteAsyncEnvelope ¶
func (r *Registry) ExecuteAsyncEnvelope(_ context.Context, env EventEnvelope)
ExecuteAsyncEnvelope runs hooks asynchronously using a typed EventEnvelope.
func (*Registry) ExecuteEnvelope ¶
func (r *Registry) ExecuteEnvelope(ctx context.Context, env EventEnvelope) error
ExecuteEnvelope runs all hooks for an event using a typed EventEnvelope. Hooks with FnV2 set receive the envelope directly; legacy Fn hooks receive the payload. Fail-open: hook errors are logged but do not stop execution of subsequent hooks.
type WrappedDecisionHook ¶
type WrappedDecisionHook struct {
Config DecisionHookConfig
Fn DecisionHookFn
}
WrappedDecisionHook pairs a config with its evaluation function.