Class: Pikuri::Agent::Configurator

Inherits:
Object
  • Object
show all
Defined in:
lib/pikuri/agent/configurator.rb

Overview

Build-time collector yielded into the Pikuri::Agent.new block. Hosts and Extensions call its methods to declare tools, listeners, +on_close+ handlers, and extension instances; #initialize drains the collected state into the agent's wiring before returning, then discards the Configurator (it carries no runtime state). System-prompt contributions are not collected here — the Agent pulls them from each extension's Extension#system_prompt_snippets at assembly time.

Pikuri::Agent.new(transport: ..., system_prompt: ...) do |c|
c.add_listener Pikuri::Agent::Listener::Terminal.new
c.add_tool     Pikuri::Tool::WebSearch.build
c.add_extension Pikuri::Skill::Extension.new(catalog: catalog, root: project_root)
end

Extensions implement configure(c) against this same type, so block-users and extensions share one API.

Two tool pools: regular vs. sub-agent-only

#add_tool registers a tool the parent agent can call (lands in #tools, handed to ruby_llm). #add_sub_agent_tool registers one the parent cannot call (lands in #sub_agent_tools, never sent to ruby_llm for the parent) but which SubAgent::Extension's persona-tool-name resolution can reach. The use case is the lethal-trifecta defense: keep network tools (+web_search+ / web_scrape / fetch) off the parent so a prompt-injected file read can't egress through it, while the researcher persona still reaches them via the agent tool. See SECURITY.md.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(transport:, system_prompt_base:, id:, streaming:, step_limit:, cancellable:, interloper:, on_close_sink: nil) ⇒ Configurator

Returns a new instance of Configurator.

Parameters:



98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
# File 'lib/pikuri/agent/configurator.rb', line 98

def initialize(transport:, system_prompt_base:, id:, streaming:,
               step_limit:, cancellable:, interloper:,
               on_close_sink: nil)
  @transport = transport
  @system_prompt_base = system_prompt_base
  @id = id
  @streaming = streaming
  @step_limit = step_limit
  @cancellable = cancellable
  @interloper = interloper

  @tools = []
  @sub_agent_tools = []
  @listeners = []
  @on_close_handlers = on_close_sink || []
  @extensions = []
end

Instance Attribute Details

#cancellableControl::Cancellable? (readonly)

Returns cancellation control, or nil. Extensions running sub-LLM calls in configure share it so a user cancel during boot propagates.

Returns:

  • (Control::Cancellable, nil)

    cancellation control, or nil. Extensions running sub-LLM calls in configure share it so a user cancel during boot propagates.



56
57
58
# File 'lib/pikuri/agent/configurator.rb', line 56

def cancellable
  @cancellable
end

#extensionsArray<#configure> (readonly)

Returns extension instances added via #add_extension, in declaration order. The Agent calls bind on each after wiring is complete.

Returns:

  • (Array<#configure>)

    extension instances added via #add_extension, in declaration order. The Agent calls bind on each after wiring is complete.



84
85
86
# File 'lib/pikuri/agent/configurator.rb', line 84

def extensions
  @extensions
end

#idString (readonly)

Returns this agent's unique identifier; empty for the main agent, persona-rooted (e.g. "researcher 0") for sub-agents.

Returns:

  • (String)

    this agent's unique identifier; empty for the main agent, persona-rooted (e.g. "researcher 0") for sub-agents.



43
44
45
# File 'lib/pikuri/agent/configurator.rb', line 43

def id
  @id
end

#interloperControl::Interloper? (readonly)

Returns mid-loop user-input queue passed to the Agent ctor, or nil.

Returns:



60
61
62
# File 'lib/pikuri/agent/configurator.rb', line 60

def interloper
  @interloper
end

#listenersArray<Listener::Base> (readonly)

Returns listeners added via #add_listener, in declaration order. Drained by Pikuri::Agent#initialize.

Returns:



74
75
76
# File 'lib/pikuri/agent/configurator.rb', line 74

def listeners
  @listeners
end

#on_close_handlersArray<Proc> (readonly)

Returns on_close handlers added via #on_close, in declaration order. Fired by Pikuri::Agent#close in LIFO order with per-handler rescue.

Returns:

  • (Array<Proc>)

    on_close handlers added via #on_close, in declaration order. Fired by Pikuri::Agent#close in LIFO order with per-handler rescue.



79
80
81
# File 'lib/pikuri/agent/configurator.rb', line 79

def on_close_handlers
  @on_close_handlers
end

#step_limitControl::StepLimit? (readonly)

Returns step-budget control passed to the Agent ctor, or nil.

Returns:



51
52
53
# File 'lib/pikuri/agent/configurator.rb', line 51

def step_limit
  @step_limit
end

#streamingBoolean (readonly)

Returns true when the agent opted into chunk-level streaming.

Returns:

  • (Boolean)

    true when the agent opted into chunk-level streaming.



47
48
49
# File 'lib/pikuri/agent/configurator.rb', line 47

def streaming
  @streaming
end

#sub_agent_toolsArray<Tool> (readonly)

Returns tools added via #add_sub_agent_tool, in declaration order; drained but not registered with ruby_llm — available only to sub-agents (see the class header).

Returns:

  • (Array<Tool>)

    tools added via #add_sub_agent_tool, in declaration order; drained but not registered with ruby_llm — available only to sub-agents (see the class header).



69
70
71
# File 'lib/pikuri/agent/configurator.rb', line 69

def sub_agent_tools
  @sub_agent_tools
end

#system_prompt_baseString (readonly)

Returns the system_prompt: kwarg, untouched — the base the Agent prepends to the pulled Extension#system_prompt_snippets.

Returns:



39
40
41
# File 'lib/pikuri/agent/configurator.rb', line 39

def system_prompt_base
  @system_prompt_base
end

#toolsArray<Tool> (readonly)

Returns tools added via #add_tool, in declaration order; drained by Pikuri::Agent#initialize and registered with ruby_llm.

Returns:



64
65
66
# File 'lib/pikuri/agent/configurator.rb', line 64

def tools
  @tools
end

#transportAgent::ChatTransport (readonly)

Returns same transport the Agent will use, so an extension can wire helpers against the same model.

Returns:

  • (Agent::ChatTransport)

    same transport the Agent will use, so an extension can wire helpers against the same model.



35
36
37
# File 'lib/pikuri/agent/configurator.rb', line 35

def transport
  @transport
end

Instance Method Details

#add_extension(extension) ⇒ void

This method returns an undefined value.

Register an extension: its configure(self) runs immediately (so source order matches execution order), and the instance is retained for the bind(ctx) sweep at the end of Pikuri::Agent#initialize. Both hooks are required — include Pikuri::Agent::Extension for no-op defaults.

Parameters:

  • extension (Extension, #configure, #bind)

    extension instance



173
174
175
176
177
# File 'lib/pikuri/agent/configurator.rb', line 173

def add_extension(extension)
  @extensions << extension
  extension.configure(self)
  nil
end

#add_listener(listener) ⇒ void

This method returns an undefined value.

Append a listener to the agent's listener list.

Parameters:



151
152
153
154
# File 'lib/pikuri/agent/configurator.rb', line 151

def add_listener(listener)
  @listeners << listener
  nil
end

#add_listeners(listeners) ⇒ void

This method returns an undefined value.

Append several listeners at once. Accepts any enumerable (Array, ListenerList, …); declaration order is preserved.

Parameters:



161
162
163
164
# File 'lib/pikuri/agent/configurator.rb', line 161

def add_listeners(listeners)
  listeners.each { |l| @listeners << l }
  nil
end

#add_sub_agent_tool(tool) ⇒ void

This method returns an undefined value.

Append a tool to the sub-agent-only pool. The parent LLM never sees it; only sub-agents whose persona tool_names include the tool's name get it in their toolset. See the class header for the trifecta-defense rationale.

Parameters:



142
143
144
145
# File 'lib/pikuri/agent/configurator.rb', line 142

def add_sub_agent_tool(tool)
  @sub_agent_tools << tool
  nil
end

#add_tool(tool) ⇒ void

This method returns an undefined value.

Append a tool to the agent's static tool list.

Parameters:



120
121
122
123
# File 'lib/pikuri/agent/configurator.rb', line 120

def add_tool(tool)
  @tools << tool
  nil
end

#add_tools(tools) ⇒ void

This method returns an undefined value.

Append several tools at once. Equivalent to calling #add_tool for each element of tools; declaration order is preserved.

Parameters:

  • tools (Enumerable<Tool>)


130
131
132
133
# File 'lib/pikuri/agent/configurator.rb', line 130

def add_tools(tools)
  tools.each { |t| @tools << t }
  nil
end

#on_close { ... } ⇒ void

This method returns an undefined value.

Register a handler called by Pikuri::Agent#close (LIFO, each inside its own rescue).

Yields:

  • called with no arguments at close time

Raises:

  • (ArgumentError)


184
185
186
187
188
189
# File 'lib/pikuri/agent/configurator.rb', line 184

def on_close(&blk)
  raise ArgumentError, 'on_close requires a block' unless block_given?

  @on_close_handlers << blk
  nil
end