Module: RubyLLM::Contract::Step::Dsl
- Included in:
- Base
- Defined in:
- lib/ruby_llm/contract/step/dsl.rb
Overview
Extracted from Base to reduce class length. DSL accessor methods for step definition (input_type, output_type, prompt, etc.).
Constant Summary collapse
- UNSET =
Sentinel signalling “explicitly reset” (‘some_attr(:default)`). Distinguishes reset (lookup stops at this class, returns nil) from “never set” (lookup falls through to superclass).
Object.new
Instance Method Summary collapse
- #around_call(&block) ⇒ Object
- #attachment_token_estimate(n = nil) ⇒ Object
- #class_observers ⇒ Object
- #class_validates ⇒ Object
- #contract(&block) ⇒ Object
-
#inherited_value(name) ⇒ Object
Walks the inheritance chain for a class-level DSL attribute.
-
#inherited_value_with_reset(name) ⇒ Object
Like ‘inherited_value`, but honours the `UNSET` sentinel — when this class has been reset via `some_attr(:default)`, returns nil without falling through to the superclass.
- #input_type(type = nil) ⇒ Object
- #max_cost(amount = nil, on_unknown_pricing: nil) ⇒ Object
- #max_input(tokens = nil) ⇒ Object
- #max_output(tokens = nil) ⇒ Object
- #model(name = nil) ⇒ Object
- #observe(description, &block) ⇒ Object
- #on_unknown_attachment_size(mode = nil) ⇒ Object
- #on_unknown_pricing ⇒ Object
- #output_schema(&block) ⇒ Object
- #output_type(type = nil) ⇒ Object
- #prompt(text = nil, &block) ⇒ Object
- #reasoning_effort(value = nil) ⇒ Object
- #retry_policy(models: nil, attempts: nil, retry_on: nil, &block) ⇒ Object
- #temperature(value = nil) ⇒ Object
- #thinking(effort: nil, budget: nil) ⇒ Object
- #validate(description, &block) ⇒ Object
Instance Method Details
#around_call(&block) ⇒ Object
259 260 261 262 263 264 265 266 267 268 269 |
# File 'lib/ruby_llm/contract/step/dsl.rb', line 259 def around_call(&block) if block return @around_call = block end if defined?(@around_call) && @around_call @around_call elsif superclass.respond_to?(:around_call) superclass.around_call end end |
#attachment_token_estimate(n = nil) ⇒ Object
172 173 174 175 176 177 178 179 180 181 182 183 184 |
# File 'lib/ruby_llm/contract/step/dsl.rb', line 172 def (n = nil) if n == :default @attachment_token_estimate = UNSET return nil end if n validate_positive!("attachment_token_estimate", n) return @attachment_token_estimate = n end inherited_value_with_reset(:attachment_token_estimate) end |
#class_observers ⇒ Object
122 123 124 125 126 |
# File 'lib/ruby_llm/contract/step/dsl.rb', line 122 def class_observers own = defined?(@class_observers) ? @class_observers : [] inherited = superclass.respond_to?(:class_observers) ? superclass.class_observers : [] inherited + own end |
#class_validates ⇒ Object
112 113 114 115 116 |
# File 'lib/ruby_llm/contract/step/dsl.rb', line 112 def class_validates own = defined?(@class_validates) ? @class_validates : [] inherited = superclass.respond_to?(:class_validates) ? superclass.class_validates : [] inherited + own end |
#contract(&block) ⇒ Object
91 92 93 94 95 96 97 98 99 100 101 |
# File 'lib/ruby_llm/contract/step/dsl.rb', line 91 def contract(&block) return @contract_definition = Definition.new(&block) if block if defined?(@contract_definition) && @contract_definition @contract_definition elsif superclass.respond_to?(:contract) superclass.contract else Definition.new end end |
#inherited_value(name) ⇒ Object
Walks the inheritance chain for a class-level DSL attribute. Returns the first explicitly-set value found, or nil.
18 19 20 21 22 23 |
# File 'lib/ruby_llm/contract/step/dsl.rb', line 18 def inherited_value(name) ivar = :"@#{name}" return instance_variable_get(ivar) if instance_variable_defined?(ivar) superclass.public_send(name) if superclass.respond_to?(name) end |
#inherited_value_with_reset(name) ⇒ Object
Like ‘inherited_value`, but honours the `UNSET` sentinel — when this class has been reset via `some_attr(:default)`, returns nil without falling through to the superclass.
28 29 30 31 32 33 34 35 36 37 38 |
# File 'lib/ruby_llm/contract/step/dsl.rb', line 28 def inherited_value_with_reset(name) ivar = :"@#{name}" if instance_variable_defined?(ivar) value = instance_variable_get(ivar) return value unless value.equal?(UNSET) return nil end superclass.public_send(name) if superclass.respond_to?(name) end |
#input_type(type = nil) ⇒ Object
40 41 42 43 44 45 46 47 48 49 50 |
# File 'lib/ruby_llm/contract/step/dsl.rb', line 40 def input_type(type = nil) return @input_type = type if type if defined?(@input_type) @input_type elsif superclass.respond_to?(:input_type) superclass.input_type else String end end |
#max_cost(amount = nil, on_unknown_pricing: nil) ⇒ Object
146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 |
# File 'lib/ruby_llm/contract/step/dsl.rb', line 146 def max_cost(amount = nil, on_unknown_pricing: nil) if amount == :default @max_cost = UNSET @on_unknown_pricing = nil return nil end if amount validate_positive!("max_cost", amount) if on_unknown_pricing && !%i[refuse warn].include?(on_unknown_pricing) raise ArgumentError, "on_unknown_pricing must be :refuse or :warn, got #{on_unknown_pricing.inspect}" end @max_cost = amount @on_unknown_pricing = on_unknown_pricing || :refuse return @max_cost end inherited_value_with_reset(:max_cost) end |
#max_input(tokens = nil) ⇒ Object
137 138 139 140 141 142 143 144 |
# File 'lib/ruby_llm/contract/step/dsl.rb', line 137 def max_input(tokens = nil) if tokens validate_positive!("max_input", tokens) return @max_input = tokens end inherited_value(:max_input) end |
#max_output(tokens = nil) ⇒ Object
128 129 130 131 132 133 134 135 |
# File 'lib/ruby_llm/contract/step/dsl.rb', line 128 def max_output(tokens = nil) if tokens validate_positive!("max_output", tokens) return @max_output = tokens end inherited_value(:max_output) end |
#model(name = nil) ⇒ Object
199 200 201 202 203 204 205 206 207 208 |
# File 'lib/ruby_llm/contract/step/dsl.rb', line 199 def model(name = nil) if name == :default @model = UNSET return nil end return @model = name if name inherited_value_with_reset(:model) end |
#observe(description, &block) ⇒ Object
118 119 120 |
# File 'lib/ruby_llm/contract/step/dsl.rb', line 118 def observe(description, &block) (@class_observers ||= []) << Invariant.new(description, block) end |
#on_unknown_attachment_size(mode = nil) ⇒ Object
186 187 188 189 190 191 192 193 194 195 196 197 |
# File 'lib/ruby_llm/contract/step/dsl.rb', line 186 def (mode = nil) if mode unless %i[refuse warn].include?(mode) raise ArgumentError, "on_unknown_attachment_size must be :refuse or :warn, got #{mode.inspect}" end return @on_unknown_attachment_size = mode end inherited_value(:on_unknown_attachment_size) || :refuse end |
#on_unknown_pricing ⇒ Object
168 169 170 |
# File 'lib/ruby_llm/contract/step/dsl.rb', line 168 def on_unknown_pricing inherited_value(:on_unknown_pricing) || :refuse end |
#output_schema(&block) ⇒ Object
66 67 68 69 70 71 72 73 74 75 |
# File 'lib/ruby_llm/contract/step/dsl.rb', line 66 def output_schema(&block) if block require "ruby_llm/schema" @output_schema = ::RubyLLM::Schema.create(&block) elsif defined?(@output_schema) @output_schema elsif superclass.respond_to?(:output_schema) superclass.output_schema end end |
#output_type(type = nil) ⇒ Object
52 53 54 55 56 57 58 59 60 61 62 63 64 |
# File 'lib/ruby_llm/contract/step/dsl.rb', line 52 def output_type(type = nil) return @output_type = type if type if defined?(@output_type) @output_type elsif defined?(@output_schema) && @output_schema RubyLLM::Contract::Types::Hash elsif superclass.respond_to?(:output_type) superclass.output_type else Hash end end |
#prompt(text = nil, &block) ⇒ Object
77 78 79 80 81 82 83 84 85 86 87 88 89 |
# File 'lib/ruby_llm/contract/step/dsl.rb', line 77 def prompt(text = nil, &block) if text @prompt_block = proc { user text } elsif block @prompt_block = block elsif defined?(@prompt_block) && @prompt_block @prompt_block elsif superclass.respond_to?(:prompt) superclass.prompt else raise(ArgumentError, "prompt has not been set") end end |
#reasoning_effort(value = nil) ⇒ Object
240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 |
# File 'lib/ruby_llm/contract/step/dsl.rb', line 240 def reasoning_effort(value = nil) return (thinking && thinking[:effort]) if value.nil? # Alias is scoped to the effort dimension only. `:default` on the # alias clears effort but PRESERVES any previously-set budget — the # name does not suggest "wipe the whole thinking config." Use the # full `thinking(effort: :default)` to clear everything. if value == :default current_budget = thinking && thinking[:budget] if current_budget @thinking = { budget: current_budget } return nil end return thinking(effort: :default) end thinking(effort: value) end |
#retry_policy(models: nil, attempts: nil, retry_on: nil, &block) ⇒ Object
271 272 273 274 275 276 277 278 279 280 281 |
# File 'lib/ruby_llm/contract/step/dsl.rb', line 271 def retry_policy(models: nil, attempts: nil, retry_on: nil, &block) if block || models || attempts || retry_on return @retry_policy = RetryPolicy.new(models: models, attempts: attempts, retry_on: retry_on, &block) end if defined?(@retry_policy) && @retry_policy @retry_policy elsif superclass.respond_to?(:retry_policy) superclass.retry_policy end end |
#temperature(value = nil) ⇒ Object
210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 |
# File 'lib/ruby_llm/contract/step/dsl.rb', line 210 def temperature(value = nil) if value == :default @temperature = UNSET return nil end # NOTE: `value` may be 0 (a legitimate setting); use `nil?` rather # than truthiness to distinguish "no arg passed" from "explicit 0". unless value.nil? unless value.is_a?(Numeric) && value >= 0 && value <= 2 raise ArgumentError, "temperature must be 0.0-2.0, got #{value}" end return @temperature = value end inherited_value_with_reset(:temperature) end |
#thinking(effort: nil, budget: nil) ⇒ Object
229 230 231 232 233 234 235 236 237 238 |
# File 'lib/ruby_llm/contract/step/dsl.rb', line 229 def thinking(effort: nil, budget: nil) if effort == :default @thinking = UNSET return nil end return @thinking = { effort: effort, budget: budget }.compact if effort || budget inherited_value_with_reset(:thinking) end |
#validate(description, &block) ⇒ Object
103 104 105 106 107 108 109 110 |
# File 'lib/ruby_llm/contract/step/dsl.rb', line 103 def validate(description, &block) # `nil.to_s.empty?` is already true - the explicit nil branch was # redundant. `caller` pushes the backtrace to user code instead # of DSL internals (per Codex review of 0.10.0). raise ArgumentError, "validate description must be a non-empty string", caller if description.to_s.empty? (@class_validates ||= []) << Invariant.new(description, block) end |