Class: Pikuri::Agent::Control::StepLimit

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

Overview

Caps the number of tool calls per Pikuri::Agent#run_loop invocation. ruby_llm has no built-in step budget; the Agent pokes #tick! on every before_tool_call callback and #reset! at the start of each turn. Once the counter exceeds the configured cap, #tick! raises Exceeded, the Agent catches it, and the step- exhaustion synthesizer rescues to salvage a partial answer.

Defined Under Namespace

Classes: Exceeded

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(max:) ⇒ StepLimit

Returns a new instance of StepLimit.

Parameters:

  • max (Integer)

    hard cap on tool-call rounds; must be positive

Raises:

  • (ArgumentError)

    if max is zero or negative



35
36
37
38
39
40
# File 'lib/pikuri/agent/control/step_limit.rb', line 35

def initialize(max:)
  raise ArgumentError, "max must be positive, got #{max}" if max <= 0

  @max = max
  @step = 0
end

Instance Attribute Details

#maxInteger (readonly)

Returns the configured cap.

Returns:

  • (Integer)

    the configured cap



30
31
32
# File 'lib/pikuri/agent/control/step_limit.rb', line 30

def max
  @max
end

#stepInteger (readonly)

Returns current step count; exposed so callers can introspect it (and so tests can assert it).

Returns:

  • (Integer)

    current step count; exposed so callers can introspect it (and so tests can assert it)



70
71
72
# File 'lib/pikuri/agent/control/step_limit.rb', line 70

def step
  @step
end

Instance Method Details

#for_sub_agent(max_steps: @max) ⇒ StepLimit

Sub-agent variant: a fresh StepLimit at the caller-supplied max_steps:, or — when the key is absent — at the receiver’s own cap. The mutable counter is per-chat, so the parent’s instance cannot govern a sub-agent’s chat; every sub-agent needs its own.

Parameters:

  • max_steps (Integer) (defaults to: @max)

    positive step cap for the sub-agent; defaults to the receiver’s current cap

Returns:

Raises:

  • (ArgumentError)

    if max_steps is non-positive



82
83
84
# File 'lib/pikuri/agent/control/step_limit.rb', line 82

def for_sub_agent(max_steps: @max)
  self.class.new(max: max_steps)
end

#reset!void

This method returns an undefined value.

Reset the counter back to zero. Called by Pikuri::Agent at the start of each turn (in Pikuri::Agent#run_loop before forwarding the user message to the chat) so the same instance can govern many turns across a long-running REPL. Mid-loop Interloper injections deliberately do not trigger a reset — those are additional context for the same turn, not a fresh one, and a chatty user could otherwise refresh the budget forever by injecting.



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

def reset!
  @step = 0
end

#tick!void

This method returns an undefined value.

Increment the tool-call counter; raise Exceeded once it crosses #max. Called by Pikuri::Agent from its before_tool_call wiring.

Raises:



49
50
51
52
# File 'lib/pikuri/agent/control/step_limit.rb', line 49

def tick!
  @step += 1
  raise Exceeded, @max if @step > @max
end

#to_sString

Returns short config dump for Pikuri::Agent#to_s.

Returns:



87
88
89
# File 'lib/pikuri/agent/control/step_limit.rb', line 87

def to_s
  "StepLimit(max=#{@max})"
end