Class: RobotLab::RunConfig

Inherits:
Object
  • Object
show all
Defined in:
lib/robot_lab/run_config.rb

Overview

Shared configuration object for LLM, tools, callbacks, and infrastructure.

RunConfig provides a unified way to express operational defaults that flow through the configuration hierarchy:

RobotLab.config -> Network -> Robot -> Template front matter -> Task -> Runtime

Only explicitly set values are stored. Merge semantics: the more-specific config’s non-nil values win over the less-specific config.

Examples:

Keyword construction

config = RunConfig.new(model: "claude-sonnet-4", temperature: 0.7)

Block DSL

config = RunConfig.new do |c|
  c.model "claude-sonnet-4"
  c.temperature 0.7
end

Merge (more-specific wins)

network_config = RunConfig.new(model: "claude-sonnet-4", temperature: 0.5)
robot_config   = RunConfig.new(temperature: 0.9)
effective       = network_config.merge(robot_config)
effective.temperature  #=> 0.9
effective.model        #=> "claude-sonnet-4"

Constant Summary collapse

LLM_FIELDS =

LLM configuration fields (applied to chat via with_* methods)

%i[
  model temperature top_p top_k max_tokens
  presence_penalty frequency_penalty stop
].freeze
TOOL_FIELDS =

Tool-related fields

%i[mcp tools].freeze
CALLBACK_FIELDS =

Callback fields (Procs)

%i[on_tool_call on_tool_result on_content].freeze
INFRA_FIELDS =

Infrastructure fields

%i[bus enable_cache max_tool_rounds token_budget ractor_pool_size max_concurrent_robots
doom_loop_threshold auto_compact compact_threshold].freeze
FIELDS =

All recognized fields

(LLM_FIELDS + TOOL_FIELDS + CALLBACK_FIELDS + INFRA_FIELDS).freeze
NON_SERIALIZABLE_FIELDS =

Fields that cannot be serialized to JSON (Procs, IO objects, etc.) auto_compact is excluded because it may be a Proc.

(CALLBACK_FIELDS + %i[bus auto_compact]).freeze

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(**kwargs) {|self| ... } ⇒ RunConfig

Creates a new RunConfig.

Parameters:

  • kwargs (Hash)

    field values to set

Yields:

  • (self)

    optional block for DSL-style configuration



58
59
60
61
62
63
64
65
66
# File 'lib/robot_lab/run_config.rb', line 58

def initialize(**kwargs)
  @fields = {}

  kwargs.each do |key, value|
    set(key, value)
  end

  yield self if block_given?
end

Class Method Details

.from_front_matter(metadata) ⇒ RunConfig

Build a RunConfig from prompt_manager front matter metadata.

Parameters:

  • metadata (Object)

    a PM::Metadata object (responds to field names)

Returns:



125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
# File 'lib/robot_lab/run_config.rb', line 125

def self.from_front_matter()
  fields = {}

  LLM_FIELDS.each do |key|
    value = .respond_to?(key) ? .send(key) : nil
    fields[key] = value if value
  end

  # Extract tool-related fields
  %i[mcp tools].each do |key|
    value = .respond_to?(key) ? .send(key) : nil
    fields[key] = value if value
  end

  new(**fields)
end

Instance Method Details

#==(other) ⇒ Boolean

Parameters:

  • other (RunConfig)

    the other RunConfig to compare

Returns:

  • (Boolean)


155
156
157
# File 'lib/robot_lab/run_config.rb', line 155

def ==(other)
  other.is_a?(RunConfig) && to_h == other.to_h
end

#apply_to(chat) ⇒ Object

Applies LLM fields to a chat object via its with_* methods.

Parameters:

  • chat (Object)

    a RubyLLM::Chat (or similar) that responds to with_model, with_temperature, etc.



111
112
113
114
115
116
117
118
119
# File 'lib/robot_lab/run_config.rb', line 111

def apply_to(chat)
  LLM_FIELDS.each do |field|
    value = @fields[field]
    next unless value

    method = :"with_#{field}"
    chat.public_send(method, value) if chat.respond_to?(method)
  end
end

#empty?Boolean

Returns true if no fields have been set.

Returns:

  • (Boolean)

    true if no fields have been set



143
144
145
# File 'lib/robot_lab/run_config.rb', line 143

def empty?
  @fields.empty?
end

#inspectString

Returns:

  • (String)


160
161
162
# File 'lib/robot_lab/run_config.rb', line 160

def inspect
  "#<#{self.class} #{@fields.inspect}>"
end

#key?(field) ⇒ Boolean

Returns true if the field has been explicitly set.

Parameters:

  • field (Symbol)

    the field name

Returns:

  • (Boolean)

    true if the field has been explicitly set



149
150
151
# File 'lib/robot_lab/run_config.rb', line 149

def key?(field)
  @fields.key?(field)
end

#merge(other) ⇒ RunConfig

Merges another RunConfig (or Hash) on top of this one. The other’s non-nil values win. Returns a new RunConfig.

Parameters:

  • other (RunConfig, Hash)

    the more-specific configuration

Returns:



102
103
104
105
106
# File 'lib/robot_lab/run_config.rb', line 102

def merge(other)
  other_hash = other.is_a?(RunConfig) ? other.to_h : other
  merged = @fields.merge(other_hash) { |_k, old_v, new_v| new_v.nil? ? old_v : new_v }
  self.class.new(**merged)
end

#to_hHash

Returns a duplicate of the internal fields hash.

Returns:

  • (Hash)

    only the fields that have been explicitly set



86
87
88
# File 'lib/robot_lab/run_config.rb', line 86

def to_h
  @fields.dup
end

#to_json_hashHash

Returns a JSON-safe hash (skips Procs, IO, and other non-serializable values).

Returns:

  • (Hash)


93
94
95
# File 'lib/robot_lab/run_config.rb', line 93

def to_json_hash
  @fields.except(*NON_SERIALIZABLE_FIELDS)
end