Class: RubyPi::Agent::State
- Inherits:
-
Object
- Object
- RubyPi::Agent::State
- Defined in:
- lib/ruby_pi/agent/state.rb
Overview
Mutable state object threaded through the agent loop. Encapsulates the full conversation history, configuration, and hook callables so that the loop, compaction, and transforms all operate on a single shared object.
Instance Attribute Summary collapse
-
#after_tool_call ⇒ Proc?
Callable invoked after each tool call; receives the ToolCall and the RubyPi::Tools::Result.
-
#before_tool_call ⇒ Proc?
Callable invoked before each tool call; receives the RubyPi::LLM::ToolCall.
-
#max_iterations ⇒ Integer
readonly
Maximum think-act-observe iterations before halting.
-
#model ⇒ RubyPi::LLM::BaseProvider
readonly
The LLM provider instance.
-
#system_prompt ⇒ String
The system prompt prepended to every LLM call.
-
#tools ⇒ RubyPi::Tools::Registry
readonly
The registry of available tools.
-
#transform_context ⇒ Proc?
Callable invoked with state before each LLM call to transform context (system prompt, messages).
-
#user_data ⇒ Hash
Arbitrary user-provided data accessible by transforms and extensions.
Instance Method Summary collapse
-
#add_message(role:, content: nil, **options) ⇒ Array<Hash>
Appends a message to the conversation history.
-
#increment_iteration! ⇒ Integer
Increments the iteration counter by one.
-
#initialize(system_prompt:, model:, tools: nil, messages: [], max_iterations: 10, transform_context: nil, before_tool_call: nil, after_tool_call: nil, user_data: {}) ⇒ State
constructor
Creates a new State instance with the given configuration.
-
#inspect ⇒ String
Provides a human-readable summary of the current state for debugging.
-
#iteration ⇒ Integer
Returns the current iteration count (number of completed think-act-observe cycles).
-
#max_iterations_reached? ⇒ Boolean
Returns true if the iteration count has reached or exceeded max_iterations.
-
#messages ⇒ Array<Hash>
Returns a frozen copy of the conversation history.
-
#messages=(new_messages) ⇒ Array<Hash>
Replaces the entire conversation history.
-
#reset_iteration! ⇒ Integer
Resets the iteration counter to zero.
Constructor Details
#initialize(system_prompt:, model:, tools: nil, messages: [], max_iterations: 10, transform_context: nil, before_tool_call: nil, after_tool_call: nil, user_data: {}) ⇒ State
Creates a new State instance with the given configuration.
69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 |
# File 'lib/ruby_pi/agent/state.rb', line 69 def initialize( system_prompt:, model:, tools: nil, messages: [], max_iterations: 10, transform_context: nil, before_tool_call: nil, after_tool_call: nil, user_data: {} ) unless max_iterations.is_a?(Integer) && max_iterations.positive? raise ArgumentError, "max_iterations must be a positive integer, got #{max_iterations.inspect}" end @system_prompt = system_prompt @model = model @tools = tools @messages = deep_dup(Array()) @max_iterations = max_iterations @transform_context = transform_context @before_tool_call = before_tool_call @after_tool_call = after_tool_call @user_data = user_data @iteration = 0 end |
Instance Attribute Details
#after_tool_call ⇒ Proc?
Returns callable invoked after each tool call; receives the ToolCall and the RubyPi::Tools::Result.
52 53 54 |
# File 'lib/ruby_pi/agent/state.rb', line 52 def after_tool_call @after_tool_call end |
#before_tool_call ⇒ Proc?
Returns callable invoked before each tool call; receives the RubyPi::LLM::ToolCall.
48 49 50 |
# File 'lib/ruby_pi/agent/state.rb', line 48 def before_tool_call @before_tool_call end |
#max_iterations ⇒ Integer (readonly)
Returns maximum think-act-observe iterations before halting.
40 41 42 |
# File 'lib/ruby_pi/agent/state.rb', line 40 def max_iterations @max_iterations end |
#model ⇒ RubyPi::LLM::BaseProvider (readonly)
Returns the LLM provider instance.
34 35 36 |
# File 'lib/ruby_pi/agent/state.rb', line 34 def model @model end |
#system_prompt ⇒ String
Returns the system prompt prepended to every LLM call.
31 32 33 |
# File 'lib/ruby_pi/agent/state.rb', line 31 def system_prompt @system_prompt end |
#tools ⇒ RubyPi::Tools::Registry (readonly)
Returns the registry of available tools.
37 38 39 |
# File 'lib/ruby_pi/agent/state.rb', line 37 def tools @tools end |
#transform_context ⇒ Proc?
Returns callable invoked with state before each LLM call to transform context (system prompt, messages).
44 45 46 |
# File 'lib/ruby_pi/agent/state.rb', line 44 def transform_context @transform_context end |
#user_data ⇒ Hash
Returns arbitrary user-provided data accessible by transforms and extensions.
56 57 58 |
# File 'lib/ruby_pi/agent/state.rb', line 56 def user_data @user_data end |
Instance Method Details
#add_message(role:, content: nil, **options) ⇒ Array<Hash>
Appends a message to the conversation history.
NOTE: history grows without bound — there is no built-in cap. Growth per run is limited by max_iterations, but long-lived agents that call continue() repeatedly (or use a high max_iterations with large tool outputs) accumulate messages linearly. Configure Agent.new(compaction: ...) to keep the context bounded.
108 109 110 111 112 |
# File 'lib/ruby_pi/agent/state.rb', line 108 def (role:, content: nil, **) = { role: role.to_sym, content: content }.merge() @messages << deep_dup() end |
#increment_iteration! ⇒ Integer
Increments the iteration counter by one. Called by the agent loop at the end of each think-act-observe cycle.
143 144 145 |
# File 'lib/ruby_pi/agent/state.rb', line 143 def increment_iteration! @iteration += 1 end |
#inspect ⇒ String
Provides a human-readable summary of the current state for debugging.
169 170 171 172 173 174 |
# File 'lib/ruby_pi/agent/state.rb', line 169 def inspect "#<RubyPi::Agent::State " \ "iteration=#{@iteration}/#{@max_iterations} " \ "messages=#{@messages.size} " \ "tools=#{@tools&.size || 0}>" end |
#iteration ⇒ Integer
Returns the current iteration count (number of completed think-act-observe cycles).
135 136 137 |
# File 'lib/ruby_pi/agent/state.rb', line 135 def iteration @iteration end |
#max_iterations_reached? ⇒ Boolean
Returns true if the iteration count has reached or exceeded max_iterations.
162 163 164 |
# File 'lib/ruby_pi/agent/state.rb', line 162 def max_iterations_reached? @iteration >= @max_iterations end |
#messages ⇒ Array<Hash>
Returns a frozen copy of the conversation history. Callers cannot accidentally mutate the internal array through this reference.
118 119 120 |
# File 'lib/ruby_pi/agent/state.rb', line 118 def deep_dup(@messages).freeze end |
#messages=(new_messages) ⇒ Array<Hash>
Replaces the entire conversation history. Used by compaction to swap in a shortened message array.
127 128 129 |
# File 'lib/ruby_pi/agent/state.rb', line 127 def () @messages = deep_dup(Array()) end |
#reset_iteration! ⇒ Integer
Resets the iteration counter to zero.
Issue #16: Provides an encapsulated way to reset the iteration counter instead of using instance_variable_set(:@iteration, 0) which bypasses encapsulation. Called at the start of both run() and continue() to ensure each invocation gets a fresh iteration budget.
155 156 157 |
# File 'lib/ruby_pi/agent/state.rb', line 155 def reset_iteration! @iteration = 0 end |