Class: Pikuri::Agent::ListenerList
- Inherits:
-
Object
- Object
- Pikuri::Agent::ListenerList
- Defined in:
- lib/pikuri/agent/listener_list.rb
Overview
Listener-list value object that an Pikuri::Agent owns. Implements the same attach(chat) / on_message(msg) protocol as an individual listener — every call is fanned out to the underlying list — so the Agent never sees a raw Array and never has to express “for each listener, do X” inline.
Why a class, not an Array
Two operations want one home rather than scattered helpers:
-
#for_sub_agent produces a derived list for a sub-agent run by forwarding to each listener’s own for_sub_agent(**params) hook (default identity for listeners that don’t define one). The dispatch lives on the listener —
Terminalswaps in a padded fresh instance,TokenLogresets its snapshot,StepLimitpicksmax_stepsout of the params hash — so this class doesn’t grow a method per new listener type. The synthesizer rescue uses the same hook with max_steps: 1, since a step-exhausted synth is just another fresh-context run. -
#attach / #on_message replace each { |l| l.attach(chat) } and each { |l| l.on_message(msg) } at the call sites, which makes the seam (“a listener list is a thing the agent owns”) more visible.
Instance Method Summary collapse
-
#attach(chat) ⇒ void
Wire every listener into
chat‘s callback API. -
#context_window_cap=(cap) ⇒ void
Set the context-window cap on every Pikuri::Agent::Listener::TokenLog in the list.
-
#for_sub_agent(**params) ⇒ ListenerList
Return a new ListenerList in which every listener has been asked for its sub-agent variant.
-
#initialize(listeners) ⇒ ListenerList
constructor
A new instance of ListenerList.
-
#on_message(message) ⇒ void
Dispatch one message to every listener.
- #to_s ⇒ String
Constructor Details
#initialize(listeners) ⇒ ListenerList
Returns a new instance of ListenerList.
32 33 34 |
# File 'lib/pikuri/agent/listener_list.rb', line 32 def initialize(listeners) @listeners = listeners.dup end |
Instance Method Details
#attach(chat) ⇒ void
This method returns an undefined value.
Wire every listener into chat‘s callback API. Forwarded verbatim to each listener’s #attach — see Pikuri::Agent::Listener::MessageListener#attach and Pikuri::Agent::Listener::StepLimit#attach for what each one registers.
42 43 44 |
# File 'lib/pikuri/agent/listener_list.rb', line 42 def attach(chat) @listeners.each { |l| l.attach(chat) } end |
#context_window_cap=(cap) ⇒ void
This method returns an undefined value.
Set the context-window cap on every Pikuri::Agent::Listener::TokenLog in the list. Called by Pikuri::Agent#initialize once ContextWindowDetector has resolved a value, so the ctx=<used>/<cap> form lights up across all token loggers without the caller having to know which listeners they registered.
Non-TokenLog listeners are left alone — they have no cap to carry.
98 99 100 101 102 |
# File 'lib/pikuri/agent/listener_list.rb', line 98 def context_window_cap=(cap) @listeners.each do |l| l.context_window_cap = cap if l.is_a?(Listener::TokenLog) end end |
#for_sub_agent(**params) ⇒ ListenerList
Return a new Pikuri::Agent::ListenerList in which every listener has been asked for its sub-agent variant. Each listener that defines for_sub_agent(**params) receives the forwarded params and returns either self or a replacement; listeners that don’t define the method are kept by reference (output, structured capture, and anything else stateful flow continuously into the parent’s instances).
The dispatch lives on the listener so adding a new listener type with sub-agent-specific behavior doesn’t change this class — see Pikuri::Agent::Listener::Terminal#for_sub_agent (fresh padded instance), Pikuri::Agent::Listener::TokenLog#for_sub_agent (fresh, zeroed snapshot), and Pikuri::Agent::Listener::StepLimit#for_sub_agent (fresh cap from max_steps:).
params is a flat hash forwarded as kwargs to every listener’s hook; each listener picks the keys it cares about and ignores the rest (the ** catch-all in their signatures). Calling with no params is always valid — every listener’s for_sub_agent treats its consumed keys as optional (e.g. StepLimit falls back to its own cap when max_steps: is absent).
79 80 81 82 83 84 |
# File 'lib/pikuri/agent/listener_list.rb', line 79 def for_sub_agent(**params) swapped = @listeners.map do |l| l.respond_to?(:for_sub_agent) ? l.for_sub_agent(**params) : l end self.class.new(swapped) end |
#on_message(message) ⇒ void
This method returns an undefined value.
Dispatch one message to every listener.
50 51 52 |
# File 'lib/pikuri/agent/listener_list.rb', line 50 def () @listeners.each { |l| l.() } end |
#to_s ⇒ String
108 109 110 |
# File 'lib/pikuri/agent/listener_list.rb', line 108 def to_s "[#{@listeners.map(&:to_s).join(', ')}]" end |