Class: SwarmSDK::V3::Hooks::Runner

Inherits:
Object
  • Object
show all
Defined in:
lib/swarm_sdk/v3/hooks/runner.rb

Overview

Executes hooks for a given event in registration order

Hooks are grouped by event type and executed sequentially. For tool events, hooks are filtered by their matcher before execution. The first hook that returns a non-continue Result short-circuits the chain.

## Match Parameter (tool hooks only)

| Input | Behavior | |————-|———————————–| | ‘nil` | Matches all tools | | `:Bash` | Exact match on tool name | | `“Bash”` | Exact match (same as Symbol) | | `/pattern/` | Regex match (user controls anchor)| | `[:W, :E]` | Exact match on any in the array |

Examples:

hooks = [
  { event: :before_ask, block: ->(ctx) { puts ctx.prompt } },
  { event: :before_tool, match: :Bash, block: ->(ctx) { ctx.halt("no bash") } },
]
runner = Runner.new(hooks)
result = runner.run(:before_ask, context)

Constant Summary collapse

EVENTS =

Supported hook events

[:before_ask, :after_ask, :before_tool, :after_tool, :on_stop].freeze
TOOL_EVENTS =

Tool-specific event types (these support match filtering)

[:before_tool, :after_tool].freeze

Instance Method Summary collapse

Constructor Details

#initialize(hooks = []) ⇒ Runner

Create a new runner from a list of hook configurations

Examples:

Runner.new([
  { event: :before_ask, block: my_proc },
  { event: :before_tool, match: :Bash, block: guard_proc },
])

Parameters:

  • hooks (Array<Hash>) (defaults to: [])

    Hook config hashes with :event, :block, and optional :match

Raises:

  • (KeyError)

    If a hook references an unknown event



46
47
48
49
# File 'lib/swarm_sdk/v3/hooks/runner.rb', line 46

def initialize(hooks = [])
  @hooks = EVENTS.each_with_object({}) { |e, h| h[e] = [] }
  hooks.each { |hook| @hooks.fetch(hook[:event]) << hook }
end

Instance Method Details

#any_tool_hooks?Boolean

Whether any tool hooks are registered

Used by Agent to skip around_tool_execution registration when no tool hooks exist, avoiding unnecessary overhead.

Returns:

  • (Boolean)


87
88
89
# File 'lib/swarm_sdk/v3/hooks/runner.rb', line 87

def any_tool_hooks?
  @hooks[:before_tool].any? || @hooks[:after_tool].any?
end

#run(event, context) ⇒ Result

Execute hooks for an event and return the controlling result

Hooks run in registration order. The first hook that returns a non-continue SwarmSDK::V3::Hooks::Result wins and short-circuits the chain. If no hook returns a controlling result, SwarmSDK::V3::Hooks::Result.continue is returned.

For tool events (:before_tool, :after_tool), hooks are filtered by their matcher against the context’s tool_name.

Examples:

result = runner.run(:before_ask, context)
if result.halt?
  # stop processing
end

Parameters:

  • event (Symbol)

    Event type (one of EVENTS)

  • context (Context)

    Hook context with event data

Returns:

  • (Result)

    The controlling result



69
70
71
72
73
74
75
76
77
78
79
# File 'lib/swarm_sdk/v3/hooks/runner.rb', line 69

def run(event, context)
  hooks_for_event = @hooks.fetch(event)
  hooks_for_event = filter_by_matcher(hooks_for_event, context.tool_name) if tool_event?(event)

  hooks_for_event.each do |hook|
    result = hook[:block].call(context)
    return result if result.is_a?(Result) && !result.continue?
  end

  Result.continue
end