Documentation
¶
Overview ¶
Package hooks provides shell-command-based pre-tool hooks, adapted from Charm's crush project (MIT). Hooks fire before each tool execution and can:
- Allow (exit 0, no JSON output or {"decision":"allow"})
- Deny (exit 2, or {"decision":"deny","reason":"..."})
- Halt turn (exit 49, or {"halt":true,"reason":"..."})
- Rewrite input (exit 0, {"updatedInput":"...","decision":"allow"})
- Inject context (exit 0, {"context":"..."})
Index ¶
- Constants
- type ActiveHookInfo
- type AggregateResult
- type Decision
- type Executor
- func (e *Executor) Execute(ctx context.Context, event types.HookEvent, data map[string]any) ([]types.HookResult, error)
- func (e *Executor) ExecuteAsync(ctx context.Context, event types.HookEvent, data map[string]any)
- func (e *Executor) ExecuteFirst(ctx context.Context, event types.HookEvent, data map[string]any) *types.HookResult
- func (e *Executor) IsEnabled() bool
- func (e *Executor) SetEnabled(enabled bool)
- func (e *Executor) SetTimeout(timeout time.Duration)
- type HookConfig
- type HookHandler
- type HookInfo
- type HookLifecycleConfig
- type HookLifecycleEvent
- type HookLifecycleManager
- func (m *HookLifecycleManager) ExecuteHook(ctx context.Context, hook HookRegistration, progress types.HookProgress) error
- func (m *HookLifecycleManager) GetActiveHooks() map[string]*ActiveHookInfo
- func (m *HookLifecycleManager) GetConfig() *HookLifecycleConfig
- func (m *HookLifecycleManager) GetHookState(hookID string) (HookState, error)
- func (m *HookLifecycleManager) GetLifecycleEvents() <-chan HookLifecycleEvent
- func (m *HookLifecycleManager) GetMetrics() HookMetrics
- func (m *HookLifecycleManager) PauseHook(hookID string) error
- func (m *HookLifecycleManager) RegisterHook(hook HookRegistration) error
- func (m *HookLifecycleManager) RemoveHook(hookID string) error
- func (m *HookLifecycleManager) ResumeHook(hookID string) error
- func (m *HookLifecycleManager) Shutdown()
- func (m *HookLifecycleManager) UpdateConfig(config *HookLifecycleConfig)
- func (m *HookLifecycleManager) WaitShutdown()
- type HookMetadata
- type HookMetrics
- type HookRegistration
- type HookResult
- type HookState
- type HookTimeoutEvent
- type HookTimeoutInfo
- type HookTimeoutManager
- func (m *HookTimeoutManager) CheckTimeout(hookID string) bool
- func (m *HookTimeoutManager) ClearAllTimeouts()
- func (m *HookTimeoutManager) ClearExpiredTimeouts() int
- func (m *HookTimeoutManager) GetActiveCount() int
- func (m *HookTimeoutManager) GetActiveTimeouts() map[string]*HookTimeoutInfo
- func (m *HookTimeoutManager) GetDefaultTimeout() time.Duration
- func (m *HookTimeoutManager) GetExpiredCount() int
- func (m *HookTimeoutManager) GetExpiredTimeouts() map[string]*HookTimeoutInfo
- func (m *HookTimeoutManager) GetTimeoutEvents() <-chan HookTimeoutEvent
- func (m *HookTimeoutManager) GetTimeoutInfo(hookID string) (*HookTimeoutInfo, error)
- func (m *HookTimeoutManager) SetDefaultTimeout(timeout time.Duration)
- func (m *HookTimeoutManager) Shutdown()
- func (m *HookTimeoutManager) StartTimeout(parentCtx context.Context, hookID string, timeout time.Duration) (context.Context, context.CancelFunc)
- func (m *HookTimeoutManager) StopTimeout(hookID string)
- type Registry
- func (r *Registry) Add(hook HookRegistration)
- func (r *Registry) CleanupDeadHooks() int
- func (r *Registry) CleanupExpiredHooks() int
- func (r *Registry) Clear(event types.HookEvent)
- func (r *Registry) Count(event types.HookEvent) int
- func (r *Registry) Get(event types.HookEvent) []HookRegistration
- func (r *Registry) GetActiveHooks(event types.HookEvent) []HookRegistration
- func (r *Registry) GetHook(id string) (*HookRegistration, error)
- func (r *Registry) GetHookStats() map[string]interface{}
- func (r *Registry) GetHooksByState(state HookState) []HookRegistration
- func (r *Registry) HasHooks(event types.HookEvent) bool
- func (r *Registry) List() map[types.HookEvent][]HookRegistration
- func (r *Registry) PauseHook(id string) error
- func (r *Registry) RecordHookExecution(id string, err error) error
- func (r *Registry) Remove(id string)
- func (r *Registry) ResumeHook(id string) error
- func (r *Registry) SetHookState(id string, state HookState) error
- type Runner
Constants ¶
const HaltExitCode = 49
HaltExitCode is the exit code that halts the entire turn (crush convention).
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type ActiveHookInfo ¶
type ActiveHookInfo struct {
HookID string
Event types.HookEvent
StartTime time.Time
Context context.Context
CancelFunc context.CancelFunc
}
ActiveHookInfo tracks information about actively running hooks
type AggregateResult ¶
type AggregateResult struct {
Decision Decision
Halt bool
Reason string
UpdatedInput string
Context string
HookCount int
Hooks []HookInfo
}
AggregateResult is the merged outcome of all matching hooks.
type Executor ¶
type Executor struct {
// contains filtered or unexported fields
}
Executor handles hook execution with timeout and error handling.
func NewExecutor ¶
NewExecutor creates a new hook executor.
func (*Executor) Execute ¶
func (e *Executor) Execute(ctx context.Context, event types.HookEvent, data map[string]any) ([]types.HookResult, error)
Execute executes all hooks registered for a specific event. Hooks are executed in priority order (highest first). Returns aggregated results from all hooks.
func (*Executor) ExecuteAsync ¶
ExecuteAsync executes hooks asynchronously and returns immediately. Useful for non-blocking hooks (e.g., logging, analytics).
func (*Executor) ExecuteFirst ¶
func (e *Executor) ExecuteFirst(ctx context.Context, event types.HookEvent, data map[string]any) *types.HookResult
ExecuteFirst executes hooks until one returns a non-continue action. Returns the first hook result that is not "continue".
func (*Executor) SetEnabled ¶
SetEnabled enables or disables hook execution.
func (*Executor) SetTimeout ¶
SetTimeout sets the default timeout for hook execution.
type HookConfig ¶
type HookConfig struct {
// Matcher is a regex against the tool name. Empty = match all.
Matcher string `yaml:"matcher" json:"matcher,omitempty"`
// Command is the shell command to execute.
Command string `yaml:"command" json:"command"`
// Timeout in seconds (default 30).
Timeout int `yaml:"timeout" json:"timeout,omitempty"`
}
HookConfig declares a shell hook. Stored in .seshat.yaml under hooks.pre_tool_use.
type HookHandler ¶
type HookHandler = types.HookHandler
HookHandler is an alias for types.HookHandler. Returning (nil, nil) is equivalent to HookActionContinue.
type HookInfo ¶
type HookInfo struct {
Name string `json:"name"`
Matcher string `json:"matcher,omitempty"`
Decision string `json:"decision"`
Halt bool `json:"halt,omitempty"`
Reason string `json:"reason,omitempty"`
InputRewrite bool `json:"input_rewrite,omitempty"`
}
HookInfo identifies a single hook that ran and its individual result.
type HookLifecycleConfig ¶
type HookLifecycleConfig struct {
// CleanupInterval is how often to check for expired hooks
CleanupInterval time.Duration
// DefaultHookLifetime is the default lifetime for hooks
DefaultHookLifetime time.Duration
// MaxExecutionRetries is the maximum number of retries before marking a hook as dead
MaxExecutionRetries int
// ExecutionTimeout is the maximum time a hook can run before being cancelled
ExecutionTimeout time.Duration
// EnableAutoCleanup enables automatic cleanup of expired/dead hooks
EnableAutoCleanup bool
// EnablePerformanceTracking enables tracking of hook performance metrics
EnablePerformanceTracking bool
// HookTimeoutManager is the manager for hook timeouts
HookTimeoutManager *HookTimeoutManager
}
HookLifecycleConfig configures the hook lifecycle manager behavior
func DefaultHookLifecycleConfig ¶
func DefaultHookLifecycleConfig() *HookLifecycleConfig
DefaultHookLifecycleConfig returns default lifecycle configuration
type HookLifecycleEvent ¶
type HookLifecycleEvent struct {
EventType string
HookID string
Timestamp time.Time
Error error
Metadata map[string]interface{}
}
HookLifecycleEvent represents a lifecycle event that occurred
type HookLifecycleManager ¶
type HookLifecycleManager struct {
// contains filtered or unexported fields
}
HookLifecycleManager manages the lifecycle of hooks including registration, execution tracking, cleanup, and state management.
func NewHookLifecycleManager ¶
func NewHookLifecycleManager(registry *Registry) *HookLifecycleManager
NewHookLifecycleManager creates a new hook lifecycle manager
func NewHookLifecycleManagerWithConfig ¶
func NewHookLifecycleManagerWithConfig(registry *Registry, config *HookLifecycleConfig) *HookLifecycleManager
NewHookLifecycleManagerWithConfig creates a new hook lifecycle manager with custom config
func (*HookLifecycleManager) ExecuteHook ¶
func (m *HookLifecycleManager) ExecuteHook( ctx context.Context, hook HookRegistration, progress types.HookProgress, ) error
ExecuteHook executes a hook with lifecycle management
func (*HookLifecycleManager) GetActiveHooks ¶
func (m *HookLifecycleManager) GetActiveHooks() map[string]*ActiveHookInfo
GetActiveHooks returns all currently active hooks
func (*HookLifecycleManager) GetConfig ¶
func (m *HookLifecycleManager) GetConfig() *HookLifecycleConfig
GetConfig returns the current configuration
func (*HookLifecycleManager) GetHookState ¶
func (m *HookLifecycleManager) GetHookState(hookID string) (HookState, error)
GetHookState returns the current state of a hook
func (*HookLifecycleManager) GetLifecycleEvents ¶
func (m *HookLifecycleManager) GetLifecycleEvents() <-chan HookLifecycleEvent
GetLifecycleEvents returns the channel for lifecycle events
func (*HookLifecycleManager) GetMetrics ¶
func (m *HookLifecycleManager) GetMetrics() HookMetrics
GetMetrics returns current hook metrics
func (*HookLifecycleManager) PauseHook ¶
func (m *HookLifecycleManager) PauseHook(hookID string) error
PauseHook pauses a hook temporarily
func (*HookLifecycleManager) RegisterHook ¶
func (m *HookLifecycleManager) RegisterHook(hook HookRegistration) error
RegisterHook registers a new hook with lifecycle management
func (*HookLifecycleManager) RemoveHook ¶
func (m *HookLifecycleManager) RemoveHook(hookID string) error
RemoveHook removes a hook from the registry
func (*HookLifecycleManager) ResumeHook ¶
func (m *HookLifecycleManager) ResumeHook(hookID string) error
ResumeHook resumes a paused hook
func (*HookLifecycleManager) Shutdown ¶
func (m *HookLifecycleManager) Shutdown()
Shutdown gracefully shuts down the lifecycle manager
func (*HookLifecycleManager) UpdateConfig ¶
func (m *HookLifecycleManager) UpdateConfig(config *HookLifecycleConfig)
UpdateConfig updates the lifecycle configuration
func (*HookLifecycleManager) WaitShutdown ¶
func (m *HookLifecycleManager) WaitShutdown()
WaitShutdown waits for the shutdown to complete
type HookMetadata ¶
type HookMetadata struct {
HookCount int `json:"hook_count"`
Decision string `json:"decision"`
Halt bool `json:"halt,omitempty"`
Reason string `json:"reason,omitempty"`
InputRewrite bool `json:"input_rewrite,omitempty"`
Hooks []HookInfo `json:"hooks,omitempty"`
}
HookMetadata is embedded in tool response metadata so the UI can display a hook indicator.
type HookMetrics ¶
type HookMetrics struct {
TotalExecutions int64
SuccessfulExecutions int64
FailedExecutions int64
AverageExecutionTime time.Duration
TotalExecutionTime time.Duration
MaxExecutionTime time.Duration
MinExecutionTime time.Duration
}
HookMetrics tracks performance metrics for hooks
type HookRegistration ¶
type HookRegistration struct {
// ID uniquely identifies this hook registration
ID string
// Event is the event this hook is registered for
Event types.HookEvent
// Handler is the function to call when the hook is triggered
Handler HookHandler
// Priority determines execution order (higher = earlier)
Priority int
// Optional metadata for debugging and tracking
Metadata map[string]any
// Lifecycle management fields
State HookState // Current state of the hook
CreatedAt time.Time // When the hook was registered
LastExecuted time.Time // When the hook was last executed
ExecCount int // Number of times the hook has been executed
ErrorCount int // Number of times the hook has errored
LastError error // Last error encountered by the hook
IsPermanent bool // If true, hook cannot be auto-cleaned
MaxLifetime time.Duration // Maximum lifetime before auto-cleanup (0 = infinite)
}
HookRegistration represents a registered hook with lifecycle support.
type HookResult ¶
type HookResult struct {
Decision Decision
Halt bool
Reason string
UpdatedInput string // non-empty = rewrite tool input JSON
Context string // non-empty = append to tool result
}
HookResult is the outcome of one hook run.
type HookState ¶
type HookState string
HookState represents the current state of a hook
const ( // HookStateActive means the hook is active and will be executed HookStateActive HookState = "active" // HookStatePaused means the hook is temporarily paused HookStatePaused HookState = "paused" // HookStateInactive means the hook is inactive and won't be executed HookStateInactive HookState = "inactive" // HookStateDead means the hook has encountered an error and is dead HookStateDead HookState = "dead" )
type HookTimeoutEvent ¶
HookTimeoutEvent represents a timeout event that occurred
type HookTimeoutInfo ¶
type HookTimeoutInfo struct {
HookID string
StartTime time.Time
Timeout time.Duration
Context context.Context
CancelFunc context.CancelFunc
Expired bool
ExpiredTime time.Time
}
HookTimeoutInfo tracks timeout information for a hook
type HookTimeoutManager ¶
type HookTimeoutManager struct {
// contains filtered or unexported fields
}
HookTimeoutManager manages timeouts for hook executions
func NewHookTimeoutManager ¶
func NewHookTimeoutManager() *HookTimeoutManager
NewHookTimeoutManager creates a new hook timeout manager
func NewHookTimeoutManagerWithTimeout ¶
func NewHookTimeoutManagerWithTimeout(defaultTimeout time.Duration) *HookTimeoutManager
NewHookTimeoutManagerWithTimeout creates a new hook timeout manager with default timeout
func (*HookTimeoutManager) CheckTimeout ¶
func (m *HookTimeoutManager) CheckTimeout(hookID string) bool
CheckTimeout checks if a hook has timed out
func (*HookTimeoutManager) ClearAllTimeouts ¶
func (m *HookTimeoutManager) ClearAllTimeouts()
ClearAllTimeouts removes all timeout information
func (*HookTimeoutManager) ClearExpiredTimeouts ¶
func (m *HookTimeoutManager) ClearExpiredTimeouts() int
ClearExpiredTimeouts removes all expired timeout information
func (*HookTimeoutManager) GetActiveCount ¶
func (m *HookTimeoutManager) GetActiveCount() int
GetActiveCount returns the number of active timeout trackers
func (*HookTimeoutManager) GetActiveTimeouts ¶
func (m *HookTimeoutManager) GetActiveTimeouts() map[string]*HookTimeoutInfo
GetActiveTimeouts returns all active timeout information
func (*HookTimeoutManager) GetDefaultTimeout ¶
func (m *HookTimeoutManager) GetDefaultTimeout() time.Duration
GetDefaultTimeout returns the default timeout duration
func (*HookTimeoutManager) GetExpiredCount ¶
func (m *HookTimeoutManager) GetExpiredCount() int
GetExpiredCount returns the number of expired timeout trackers
func (*HookTimeoutManager) GetExpiredTimeouts ¶
func (m *HookTimeoutManager) GetExpiredTimeouts() map[string]*HookTimeoutInfo
GetExpiredTimeouts returns all expired timeout information
func (*HookTimeoutManager) GetTimeoutEvents ¶
func (m *HookTimeoutManager) GetTimeoutEvents() <-chan HookTimeoutEvent
GetTimeoutEvents returns the channel for timeout events
func (*HookTimeoutManager) GetTimeoutInfo ¶
func (m *HookTimeoutManager) GetTimeoutInfo(hookID string) (*HookTimeoutInfo, error)
GetTimeoutInfo returns timeout information for a hook
func (*HookTimeoutManager) SetDefaultTimeout ¶
func (m *HookTimeoutManager) SetDefaultTimeout(timeout time.Duration)
SetDefaultTimeout sets the default timeout duration
func (*HookTimeoutManager) Shutdown ¶
func (m *HookTimeoutManager) Shutdown()
Shutdown gracefully shuts down the timeout manager
func (*HookTimeoutManager) StartTimeout ¶
func (m *HookTimeoutManager) StartTimeout(parentCtx context.Context, hookID string, timeout time.Duration) (context.Context, context.CancelFunc)
StartTimeout starts tracking a timeout for a hook. parentCtx is used as the parent context so the hook is cancelled when the calling request is cancelled in addition to its own deadline.
func (*HookTimeoutManager) StopTimeout ¶
func (m *HookTimeoutManager) StopTimeout(hookID string)
StopTimeout stops tracking a timeout for a hook
type Registry ¶
type Registry struct {
// contains filtered or unexported fields
}
Registry is a unified hook registry for all lifecycle hooks. It supports registration, retrieval, and execution of hooks by event type.
func (*Registry) Add ¶
func (r *Registry) Add(hook HookRegistration)
Add registers a new hook for the specified event.
func (*Registry) CleanupDeadHooks ¶
CleanupDeadHooks removes hooks that are in dead state
func (*Registry) CleanupExpiredHooks ¶
CleanupExpiredHooks removes hooks that have exceeded their lifetime
func (*Registry) Clear ¶
Clear removes all hooks for a specific event, or all events if event is empty.
func (*Registry) Get ¶
func (r *Registry) Get(event types.HookEvent) []HookRegistration
Get retrieves all hooks registered for a specific event.
func (*Registry) GetActiveHooks ¶
func (r *Registry) GetActiveHooks(event types.HookEvent) []HookRegistration
GetActiveHooks returns only active hooks for a specific event
func (*Registry) GetHook ¶
func (r *Registry) GetHook(id string) (*HookRegistration, error)
GetHook retrieves a specific hook by ID
func (*Registry) GetHookStats ¶
GetHookStats returns statistics for all hooks
func (*Registry) GetHooksByState ¶
func (r *Registry) GetHooksByState(state HookState) []HookRegistration
GetHooksByState returns all hooks in a specific state
func (*Registry) List ¶
func (r *Registry) List() map[types.HookEvent][]HookRegistration
List returns all registered hooks across all events.
func (*Registry) RecordHookExecution ¶
RecordHookExecution records that a hook was executed
func (*Registry) ResumeHook ¶
ResumeHook resumes a paused hook by ID