ruby_llm-agents 3.1.0 → 3.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (89) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -0
  3. data/app/controllers/ruby_llm/agents/agents_controller.rb +16 -14
  4. data/app/controllers/ruby_llm/agents/dashboard_controller.rb +20 -20
  5. data/app/controllers/ruby_llm/agents/executions_controller.rb +5 -7
  6. data/app/helpers/ruby_llm/agents/application_helper.rb +57 -58
  7. data/app/models/ruby_llm/agents/execution/analytics.rb +27 -27
  8. data/app/models/ruby_llm/agents/execution/scopes.rb +4 -6
  9. data/app/models/ruby_llm/agents/execution.rb +25 -25
  10. data/app/models/ruby_llm/agents/tenant/budgetable.rb +16 -10
  11. data/app/models/ruby_llm/agents/tenant/resettable.rb +12 -12
  12. data/app/models/ruby_llm/agents/tenant/trackable.rb +7 -7
  13. data/app/services/ruby_llm/agents/agent_registry.rb +6 -6
  14. data/app/views/ruby_llm/agents/executions/_audio_player.html.erb +57 -0
  15. data/app/views/ruby_llm/agents/executions/show.html.erb +8 -0
  16. data/lib/generators/ruby_llm_agents/agent_generator.rb +4 -4
  17. data/lib/generators/ruby_llm_agents/background_remover_generator.rb +6 -6
  18. data/lib/generators/ruby_llm_agents/embedder_generator.rb +4 -4
  19. data/lib/generators/ruby_llm_agents/image_analyzer_generator.rb +7 -7
  20. data/lib/generators/ruby_llm_agents/image_editor_generator.rb +4 -4
  21. data/lib/generators/ruby_llm_agents/image_generator_generator.rb +6 -6
  22. data/lib/generators/ruby_llm_agents/image_pipeline_generator.rb +9 -9
  23. data/lib/generators/ruby_llm_agents/image_transformer_generator.rb +6 -6
  24. data/lib/generators/ruby_llm_agents/image_upscaler_generator.rb +4 -4
  25. data/lib/generators/ruby_llm_agents/image_variator_generator.rb +4 -4
  26. data/lib/generators/ruby_llm_agents/install_generator.rb +3 -3
  27. data/lib/generators/ruby_llm_agents/migrate_structure_generator.rb +4 -4
  28. data/lib/generators/ruby_llm_agents/multi_tenancy_generator.rb +2 -2
  29. data/lib/generators/ruby_llm_agents/restructure_generator.rb +13 -13
  30. data/lib/generators/ruby_llm_agents/speaker_generator.rb +6 -6
  31. data/lib/generators/ruby_llm_agents/transcriber_generator.rb +4 -4
  32. data/lib/generators/ruby_llm_agents/upgrade_generator.rb +2 -2
  33. data/lib/ruby_llm/agents/audio/speaker/active_storage_support.rb +87 -0
  34. data/lib/ruby_llm/agents/audio/speaker.rb +50 -31
  35. data/lib/ruby_llm/agents/audio/speech_client.rb +328 -0
  36. data/lib/ruby_llm/agents/audio/speech_pricing.rb +273 -0
  37. data/lib/ruby_llm/agents/audio/transcriber.rb +43 -33
  38. data/lib/ruby_llm/agents/base_agent.rb +14 -14
  39. data/lib/ruby_llm/agents/core/base/callbacks.rb +3 -3
  40. data/lib/ruby_llm/agents/core/configuration.rb +90 -73
  41. data/lib/ruby_llm/agents/core/errors.rb +27 -2
  42. data/lib/ruby_llm/agents/core/instrumentation.rb +64 -66
  43. data/lib/ruby_llm/agents/core/llm_tenant.rb +7 -7
  44. data/lib/ruby_llm/agents/core/version.rb +1 -1
  45. data/lib/ruby_llm/agents/dsl/base.rb +3 -3
  46. data/lib/ruby_llm/agents/dsl/reliability.rb +9 -9
  47. data/lib/ruby_llm/agents/image/analyzer/dsl.rb +1 -1
  48. data/lib/ruby_llm/agents/image/analyzer/execution.rb +4 -4
  49. data/lib/ruby_llm/agents/image/background_remover/dsl.rb +1 -1
  50. data/lib/ruby_llm/agents/image/background_remover/execution.rb +3 -3
  51. data/lib/ruby_llm/agents/image/concerns/image_operation_execution.rb +8 -8
  52. data/lib/ruby_llm/agents/image/editor/execution.rb +1 -1
  53. data/lib/ruby_llm/agents/image/generator/pricing.rb +9 -10
  54. data/lib/ruby_llm/agents/image/generator.rb +6 -6
  55. data/lib/ruby_llm/agents/image/pipeline/dsl.rb +6 -6
  56. data/lib/ruby_llm/agents/image/pipeline/execution.rb +9 -9
  57. data/lib/ruby_llm/agents/image/pipeline.rb +1 -1
  58. data/lib/ruby_llm/agents/image/transformer/execution.rb +1 -1
  59. data/lib/ruby_llm/agents/image/upscaler/dsl.rb +1 -1
  60. data/lib/ruby_llm/agents/image/upscaler/execution.rb +3 -5
  61. data/lib/ruby_llm/agents/image/variator/execution.rb +1 -1
  62. data/lib/ruby_llm/agents/infrastructure/alert_manager.rb +4 -4
  63. data/lib/ruby_llm/agents/infrastructure/attempt_tracker.rb +4 -4
  64. data/lib/ruby_llm/agents/infrastructure/budget/budget_query.rb +9 -9
  65. data/lib/ruby_llm/agents/infrastructure/budget/config_resolver.rb +3 -3
  66. data/lib/ruby_llm/agents/infrastructure/budget/forecaster.rb +1 -1
  67. data/lib/ruby_llm/agents/infrastructure/budget/spend_recorder.rb +17 -17
  68. data/lib/ruby_llm/agents/infrastructure/circuit_breaker.rb +1 -0
  69. data/lib/ruby_llm/agents/infrastructure/execution_logger_job.rb +1 -1
  70. data/lib/ruby_llm/agents/infrastructure/reliability.rb +6 -6
  71. data/lib/ruby_llm/agents/pipeline/builder.rb +11 -11
  72. data/lib/ruby_llm/agents/pipeline/middleware/budget.rb +3 -3
  73. data/lib/ruby_llm/agents/pipeline/middleware/cache.rb +4 -4
  74. data/lib/ruby_llm/agents/pipeline/middleware/instrumentation.rb +83 -22
  75. data/lib/ruby_llm/agents/pipeline/middleware/reliability.rb +2 -3
  76. data/lib/ruby_llm/agents/pipeline/middleware/tenant.rb +7 -7
  77. data/lib/ruby_llm/agents/results/background_removal_result.rb +6 -6
  78. data/lib/ruby_llm/agents/results/embedding_result.rb +15 -15
  79. data/lib/ruby_llm/agents/results/image_analysis_result.rb +7 -7
  80. data/lib/ruby_llm/agents/results/image_edit_result.rb +4 -4
  81. data/lib/ruby_llm/agents/results/image_generation_result.rb +5 -5
  82. data/lib/ruby_llm/agents/results/image_pipeline_result.rb +4 -4
  83. data/lib/ruby_llm/agents/results/image_transform_result.rb +4 -4
  84. data/lib/ruby_llm/agents/results/image_upscale_result.rb +5 -5
  85. data/lib/ruby_llm/agents/results/image_variation_result.rb +4 -4
  86. data/lib/ruby_llm/agents/results/speech_result.rb +12 -7
  87. data/lib/ruby_llm/agents/results/transcription_result.rb +1 -1
  88. data/lib/ruby_llm/agents/text/embedder.rb +13 -13
  89. metadata +5 -1
@@ -168,7 +168,7 @@ module RubyLLM
168
168
  def fallback_provider(provider = nil, **options)
169
169
  if provider
170
170
  @fallback_providers ||= []
171
- @fallback_providers << { provider: provider, **options }
171
+ @fallback_providers << {provider: provider, **options}
172
172
  end
173
173
  @fallback_providers || inherited_fallback_providers || []
174
174
  end
@@ -201,7 +201,7 @@ module RubyLLM
201
201
  # circuit_breaker errors: 10, within: 60, cooldown: 300
202
202
  def circuit_breaker(errors: nil, within: nil, cooldown: nil)
203
203
  if errors || within || cooldown
204
- @circuit_breaker_config ||= { errors: 10, within: 60, cooldown: 300 }
204
+ @circuit_breaker_config ||= {errors: 10, within: 60, cooldown: 300}
205
205
  @circuit_breaker_config[:errors] = errors if errors
206
206
  @circuit_breaker_config[:within] = within if within
207
207
  @circuit_breaker_config[:cooldown] = cooldown if cooldown
@@ -297,8 +297,8 @@ module RubyLLM
297
297
  # Inner builder class for block-style configuration
298
298
  class ReliabilityBuilder
299
299
  attr_reader :retries_config, :fallback_models_list, :total_timeout_value,
300
- :circuit_breaker_config, :retryable_patterns_list, :fallback_providers_list,
301
- :non_fallback_errors_list
300
+ :circuit_breaker_config, :retryable_patterns_list, :fallback_providers_list,
301
+ :non_fallback_errors_list
302
302
 
303
303
  def initialize
304
304
  @retries_config = nil
@@ -332,7 +332,7 @@ module RubyLLM
332
332
  # fallback_provider :openai, voice: "nova"
333
333
  # fallback_provider :elevenlabs, voice: "Rachel", model: "eleven_multilingual_v2"
334
334
  def fallback_provider(provider, **options)
335
- @fallback_providers_list << { provider: provider, **options }
335
+ @fallback_providers_list << {provider: provider, **options}
336
336
  end
337
337
 
338
338
  def total_timeout(seconds)
@@ -366,8 +366,8 @@ module RubyLLM
366
366
  #
367
367
  class OnFailureBuilder
368
368
  attr_reader :retries_config, :fallback_models_list, :total_timeout_value,
369
- :circuit_breaker_config, :retryable_patterns_list, :fallback_providers_list,
370
- :non_fallback_errors_list
369
+ :circuit_breaker_config, :retryable_patterns_list, :fallback_providers_list,
370
+ :non_fallback_errors_list
371
371
 
372
372
  def initialize
373
373
  @retries_config = nil
@@ -423,7 +423,7 @@ module RubyLLM
423
423
  # @param options [Hash] Provider-specific options
424
424
  #
425
425
  def fallback_provider(provider, **options)
426
- @fallback_providers_list << { provider: provider, **options }
426
+ @fallback_providers_list << {provider: provider, **options}
427
427
  end
428
428
 
429
429
  # Configure timeout for all retry/fallback attempts
@@ -440,7 +440,7 @@ module RubyLLM
440
440
  end
441
441
 
442
442
  # Also support total_timeout for compatibility
443
- alias total_timeout timeout
443
+ alias_method :total_timeout, :timeout
444
444
 
445
445
  # Configure circuit breaker
446
446
  #
@@ -31,7 +31,7 @@ module RubyLLM
31
31
  def analysis_type(value = nil)
32
32
  if value
33
33
  unless VALID_ANALYSIS_TYPES.include?(value)
34
- raise ArgumentError, "Analysis type must be one of: #{VALID_ANALYSIS_TYPES.join(', ')}"
34
+ raise ArgumentError, "Analysis type must be one of: #{VALID_ANALYSIS_TYPES.join(", ")}"
35
35
  end
36
36
  @analysis_type = value
37
37
  else
@@ -46,7 +46,7 @@ module RubyLLM
46
46
  record_execution(result) if execution_tracking_enabled?
47
47
 
48
48
  result
49
- rescue StandardError => e
49
+ rescue => e
50
50
  record_failed_execution(e, started_at) if execution_tracking_enabled?
51
51
  build_error_result(e, started_at)
52
52
  end
@@ -138,8 +138,8 @@ module RubyLLM
138
138
  caption: "Brief caption string",
139
139
  description: "Detailed description string (if applicable)",
140
140
  tags: ["array", "of", "tag", "strings"],
141
- objects: [{ name: "object name", location: "position", confidence: "high/medium/low" }],
142
- colors: [{ hex: "#RRGGBB", name: "color name", percentage: 25 }],
141
+ objects: [{name: "object name", location: "position", confidence: "high/medium/low"}],
142
+ colors: [{hex: "#RRGGBB", name: "color name", percentage: 25}],
143
143
  text: "Extracted text if any"
144
144
  }
145
145
 
@@ -154,7 +154,7 @@ module RubyLLM
154
154
 
155
155
  # Use RubyLLM chat with vision
156
156
  chat = RubyLLM.chat(model: model)
157
- chat.ask(prompt, with: { image: image_content })
157
+ chat.ask(prompt, with: {image: image_content})
158
158
  end
159
159
 
160
160
  def prepare_image_content
@@ -30,7 +30,7 @@ module RubyLLM
30
30
  def output_format(value = nil)
31
31
  if value
32
32
  unless VALID_OUTPUT_FORMATS.include?(value)
33
- raise ArgumentError, "Output format must be one of: #{VALID_OUTPUT_FORMATS.join(', ')}"
33
+ raise ArgumentError, "Output format must be one of: #{VALID_OUTPUT_FORMATS.join(", ")}"
34
34
  end
35
35
  @output_format = value
36
36
  else
@@ -46,7 +46,7 @@ module RubyLLM
46
46
  record_execution(result) if execution_tracking_enabled?
47
47
 
48
48
  result
49
- rescue StandardError => e
49
+ rescue => e
50
50
  record_failed_execution(e, started_at) if execution_tracking_enabled?
51
51
  build_error_result(e, started_at)
52
52
  end
@@ -112,13 +112,13 @@ module RubyLLM
112
112
  mode: "segmentation_mask",
113
113
  **build_removal_options
114
114
  )
115
- rescue StandardError
115
+ rescue
116
116
  # Mask generation failed, continue without it
117
117
  mask = nil
118
118
  end
119
119
  end
120
120
 
121
- { foreground: foreground, mask: mask }
121
+ {foreground: foreground, mask: mask}
122
122
  end
123
123
 
124
124
  def build_removal_options
@@ -20,11 +20,11 @@ module RubyLLM
20
20
  return unless tenant
21
21
 
22
22
  @tenant_id = case tenant
23
- when Hash then tenant[:id]
24
- when Integer, String then tenant
25
- else
26
- tenant.try(:llm_tenant_id) || tenant.try(:id)
27
- end
23
+ when Hash then tenant[:id]
24
+ when Integer, String then tenant
25
+ else
26
+ tenant.try(:llm_tenant_id) || tenant.try(:id)
27
+ end
28
28
  end
29
29
 
30
30
  # Check budget before execution
@@ -87,7 +87,7 @@ module RubyLLM
87
87
  else
88
88
  RubyLLM::Agents::Execution.create!(execution_data)
89
89
  end
90
- rescue StandardError => e
90
+ rescue => e
91
91
  Rails.logger.error("[RubyLLM::Agents] Failed to record #{execution_type} execution: #{e.message}") if defined?(Rails)
92
92
  end
93
93
 
@@ -101,7 +101,7 @@ module RubyLLM
101
101
  else
102
102
  RubyLLM::Agents::Execution.create!(execution_data)
103
103
  end
104
- rescue StandardError => e
104
+ rescue => e
105
105
  Rails.logger.error("[RubyLLM::Agents] Failed to record failed #{execution_type} execution: #{e.message}") if defined?(Rails)
106
106
  end
107
107
 
@@ -142,7 +142,7 @@ module RubyLLM
142
142
  end
143
143
 
144
144
  def build_metadata(result)
145
- { count: result.count }
145
+ {count: result.count}
146
146
  end
147
147
 
148
148
  def budget_tracking_enabled?
@@ -45,7 +45,7 @@ module RubyLLM
45
45
  record_execution(result) if execution_tracking_enabled?
46
46
 
47
47
  result
48
- rescue StandardError => e
48
+ rescue => e
49
49
  record_failed_execution(e, started_at) if execution_tracking_enabled?
50
50
  build_error_result(e, started_at)
51
51
  end
@@ -158,7 +158,7 @@ module RubyLLM
158
158
  else
159
159
  fetch_from_url
160
160
  end
161
- rescue StandardError => e
161
+ rescue => e
162
162
  warn "[RubyLLM::Agents] Failed to fetch LiteLLM pricing: #{e.message}"
163
163
  {}
164
164
  end
@@ -178,7 +178,7 @@ module RubyLLM
178
178
  else
179
179
  {}
180
180
  end
181
- rescue StandardError => e
181
+ rescue => e
182
182
  warn "[RubyLLM::Agents] HTTP error fetching LiteLLM pricing: #{e.message}"
183
183
  {}
184
184
  end
@@ -314,9 +314,9 @@ module RubyLLM
314
314
 
315
315
  def fallback_pricing_table
316
316
  {
317
- "gpt-image-1" => { standard: 0.04, hd: 0.08, large_hd: 0.12 },
318
- "dall-e-3" => { standard: 0.04, hd: 0.08, large_hd: 0.12 },
319
- "dall-e-2" => { "1024x1024" => 0.02, "512x512" => 0.018, "256x256" => 0.016 },
317
+ "gpt-image-1" => {standard: 0.04, hd: 0.08, large_hd: 0.12},
318
+ "dall-e-3" => {standard: 0.04, hd: 0.08, large_hd: 0.12},
319
+ "dall-e-2" => {"1024x1024" => 0.02, "512x512" => 0.018, "256x256" => 0.016},
320
320
  "flux-pro" => 0.05,
321
321
  "flux-dev" => 0.025,
322
322
  "flux-schnell" => 0.003,
@@ -332,16 +332,15 @@ module RubyLLM
332
332
  width, height = size.to_s.split("x").map(&:to_i)
333
333
  return nil if width.zero? || height.zero?
334
334
  width * height
335
- rescue StandardError
335
+ rescue
336
336
  nil
337
337
  end
338
338
 
339
339
  def normalize_model_id(model_id)
340
340
  model_id.to_s
341
- .downcase
342
- .gsub(/[^a-z0-9.-]/, "-")
343
- .gsub(/-+/, "-")
344
- .gsub(/^-|-$/, "")
341
+ .downcase
342
+ .gsub(/[^a-z0-9.-]/, "-").squeeze("-")
343
+ .gsub(/^-|-$/, "")
345
344
  end
346
345
 
347
346
  def config
@@ -168,25 +168,25 @@ module RubyLLM
168
168
 
169
169
  def default_image_model
170
170
  RubyLLM::Agents.configuration.default_image_model
171
- rescue StandardError
171
+ rescue
172
172
  "dall-e-3"
173
173
  end
174
174
 
175
175
  def default_image_size
176
176
  RubyLLM::Agents.configuration.default_image_size
177
- rescue StandardError
177
+ rescue
178
178
  "1024x1024"
179
179
  end
180
180
 
181
181
  def default_image_quality
182
182
  RubyLLM::Agents.configuration.default_image_quality
183
- rescue StandardError
183
+ rescue
184
184
  "standard"
185
185
  end
186
186
 
187
187
  def default_image_style
188
188
  RubyLLM::Agents.configuration.default_image_style
189
- rescue StandardError
189
+ rescue
190
190
  "vivid"
191
191
  end
192
192
  end
@@ -241,7 +241,7 @@ module RubyLLM
241
241
  images = generate_images
242
242
 
243
243
  execution_completed_at = Time.current
244
- duration_ms = ((execution_completed_at - execution_started_at) * 1000).to_i
244
+ ((execution_completed_at - execution_started_at) * 1000).to_i
245
245
 
246
246
  # Build result
247
247
  result = build_result(
@@ -257,7 +257,7 @@ module RubyLLM
257
257
  context.total_cost = result.total_cost
258
258
 
259
259
  context.output = result
260
- rescue StandardError => e
260
+ rescue => e
261
261
  execution_completed_at = Time.current
262
262
  context.output = build_error_result(
263
263
  e,
@@ -76,7 +76,7 @@ module RubyLLM
76
76
  # before_pipeline { |ctx| ctx[:started_at] = Time.current }
77
77
  #
78
78
  def before_pipeline(method_name = nil, &block)
79
- @callbacks ||= { before: [], after: [] }
79
+ @callbacks ||= {before: [], after: []}
80
80
  @callbacks[:before] << (block || method_name)
81
81
  end
82
82
 
@@ -91,7 +91,7 @@ module RubyLLM
91
91
  # after_pipeline { |result| notify_completion(result) }
92
92
  #
93
93
  def after_pipeline(method_name = nil, &block)
94
- @callbacks ||= { before: [], after: [] }
94
+ @callbacks ||= {before: [], after: []}
95
95
  @callbacks[:after] << (block || method_name)
96
96
  end
97
97
 
@@ -99,7 +99,7 @@ module RubyLLM
99
99
  #
100
100
  # @return [Hash] Hash with :before and :after arrays
101
101
  def callbacks
102
- @callbacks ||= { before: [], after: [] }
102
+ @callbacks ||= {before: [], after: []}
103
103
  end
104
104
 
105
105
  # Set or get the description
@@ -148,7 +148,7 @@ module RubyLLM
148
148
  end
149
149
  end
150
150
 
151
- alias stop_on_error? stop_on_error
151
+ alias_method :stop_on_error?, :stop_on_error
152
152
 
153
153
  private
154
154
 
@@ -163,11 +163,11 @@ module RubyLLM
163
163
  step_keys = config.keys & valid_keys
164
164
 
165
165
  if step_keys.empty?
166
- raise ArgumentError, "Step :#{name} must specify one of: #{valid_keys.join(', ')}"
166
+ raise ArgumentError, "Step :#{name} must specify one of: #{valid_keys.join(", ")}"
167
167
  end
168
168
 
169
169
  if step_keys.size > 1
170
- raise ArgumentError, "Step :#{name} can only specify one step type, got: #{step_keys.join(', ')}"
170
+ raise ArgumentError, "Step :#{name} can only specify one step type, got: #{step_keys.join(", ")}"
171
171
  end
172
172
 
173
173
  # Validate the class responds to call
@@ -37,7 +37,7 @@ module RubyLLM
37
37
  next unless should_run_step?(step_def)
38
38
 
39
39
  result = execute_step(step_def, current_image)
40
- @step_results << { name: step_def[:name], type: step_def[:type], result: result }
40
+ @step_results << {name: step_def[:name], type: step_def[:type], result: result}
41
41
 
42
42
  # Update context with result
43
43
  @context[step_def[:name]] = result
@@ -63,7 +63,7 @@ module RubyLLM
63
63
  record_execution(result) if execution_tracking_enabled?
64
64
 
65
65
  result
66
- rescue StandardError => e
66
+ rescue => e
67
67
  record_failed_execution(e) if execution_tracking_enabled?
68
68
  build_error_result(e)
69
69
  end
@@ -218,11 +218,11 @@ module RubyLLM
218
218
  return unless tenant
219
219
 
220
220
  @tenant_id = case tenant
221
- when Hash then tenant[:id]
222
- when Integer, String then tenant
223
- else
224
- tenant.try(:llm_tenant_id) || tenant.try(:id)
225
- end
221
+ when Hash then tenant[:id]
222
+ when Integer, String then tenant
223
+ else
224
+ tenant.try(:llm_tenant_id) || tenant.try(:id)
225
+ end
226
226
  end
227
227
 
228
228
  # Budget tracking
@@ -327,7 +327,7 @@ module RubyLLM
327
327
  else
328
328
  RubyLLM::Agents::Execution.create!(execution_data)
329
329
  end
330
- rescue StandardError => e
330
+ rescue => e
331
331
  Rails.logger.error("[RubyLLM::Agents] Failed to record pipeline execution: #{e.message}") if defined?(Rails)
332
332
  end
333
333
 
@@ -359,7 +359,7 @@ module RubyLLM
359
359
  else
360
360
  RubyLLM::Agents::Execution.create!(execution_data)
361
361
  end
362
- rescue StandardError => e
362
+ rescue => e
363
363
  Rails.logger.error("[RubyLLM::Agents] Failed to record failed pipeline execution: #{e.message}") if defined?(Rails)
364
364
  end
365
365
 
@@ -63,7 +63,7 @@ module RubyLLM
63
63
  super
64
64
  # Copy steps to subclass
65
65
  subclass.instance_variable_set(:@steps, @steps&.dup || [])
66
- subclass.instance_variable_set(:@callbacks, @callbacks&.dup || { before: [], after: [] })
66
+ subclass.instance_variable_set(:@callbacks, @callbacks&.dup || {before: [], after: []})
67
67
  subclass.instance_variable_set(:@version, @version)
68
68
  subclass.instance_variable_set(:@description, @description)
69
69
  subclass.instance_variable_set(:@cache_ttl, @cache_ttl)
@@ -45,7 +45,7 @@ module RubyLLM
45
45
  record_execution(result) if execution_tracking_enabled?
46
46
 
47
47
  result
48
- rescue StandardError => e
48
+ rescue => e
49
49
  record_failed_execution(e, started_at) if execution_tracking_enabled?
50
50
  build_error_result(e, started_at)
51
51
  end
@@ -29,7 +29,7 @@ module RubyLLM
29
29
  def scale(value = nil)
30
30
  if value
31
31
  unless VALID_SCALES.include?(value)
32
- raise ArgumentError, "Scale must be one of: #{VALID_SCALES.join(', ')}"
32
+ raise ArgumentError, "Scale must be one of: #{VALID_SCALES.join(", ")}"
33
33
  end
34
34
  @scale = value
35
35
  else
@@ -45,7 +45,7 @@ module RubyLLM
45
45
  record_execution(result) if execution_tracking_enabled?
46
46
 
47
47
  result
48
- rescue StandardError => e
48
+ rescue => e
49
49
  record_failed_execution(e, started_at) if execution_tracking_enabled?
50
50
  build_error_result(e, started_at)
51
51
  end
@@ -126,7 +126,7 @@ module RubyLLM
126
126
  def build_error_result(error, started_at)
127
127
  ImageUpscaleResult.new(
128
128
  image: nil,
129
- source_image: self.image,
129
+ source_image: image,
130
130
  model_id: resolve_model,
131
131
  scale: resolve_scale,
132
132
  output_size: nil,
@@ -160,10 +160,8 @@ module RubyLLM
160
160
  elsif defined?(Vips)
161
161
  img = Vips::Image.new_from_file(image)
162
162
  [img.width, img.height]
163
- else
164
- nil
165
163
  end
166
- rescue StandardError
164
+ rescue
167
165
  nil
168
166
  end
169
167
 
@@ -45,7 +45,7 @@ module RubyLLM
45
45
  record_execution(result) if execution_tracking_enabled?
46
46
 
47
47
  result
48
- rescue StandardError => e
48
+ rescue => e
49
49
  record_failed_execution(e, started_at) if execution_tracking_enabled?
50
50
  build_error_result(e, started_at)
51
51
  end
@@ -43,7 +43,7 @@ module RubyLLM
43
43
 
44
44
  # Store in cache for dashboard display
45
45
  store_for_dashboard(event, full_payload)
46
- rescue StandardError => e
46
+ rescue => e
47
47
  Rails.logger.error("[RubyLLM::Agents::AlertManager] Failed: #{e.message}")
48
48
  end
49
49
 
@@ -72,7 +72,7 @@ module RubyLLM
72
72
  return unless handler.respond_to?(:call)
73
73
 
74
74
  handler.call(event, payload)
75
- rescue StandardError => e
75
+ rescue => e
76
76
  Rails.logger.warn("[RubyLLM::Agents::AlertManager] Handler failed: #{e.message}")
77
77
  end
78
78
 
@@ -83,7 +83,7 @@ module RubyLLM
83
83
  # @return [void]
84
84
  def emit_notification(event, payload)
85
85
  ActiveSupport::Notifications.instrument("ruby_llm_agents.alert.#{event}", payload)
86
- rescue StandardError
86
+ rescue
87
87
  # Ignore notification failures
88
88
  end
89
89
 
@@ -106,7 +106,7 @@ module RubyLLM
106
106
  alerts = alerts.first(50)
107
107
 
108
108
  cache.write(key, alerts, expires_in: 24.hours)
109
- rescue StandardError
109
+ rescue
110
110
  # Ignore cache failures
111
111
  end
112
112
 
@@ -235,7 +235,7 @@ module RubyLLM
235
235
  def safe_value(response, method, default = nil)
236
236
  return default unless response.respond_to?(method)
237
237
  response.public_send(method)
238
- rescue StandardError
238
+ rescue
239
239
  default
240
240
  end
241
241
 
@@ -249,7 +249,7 @@ module RubyLLM
249
249
  model_id: attempt[:model_id],
250
250
  attempt_index: @attempts.length
251
251
  )
252
- rescue StandardError
252
+ rescue
253
253
  # Ignore notification failures
254
254
  end
255
255
 
@@ -275,7 +275,7 @@ module RubyLLM
275
275
  end
276
276
 
277
277
  ActiveSupport::Notifications.instrument(event, payload)
278
- rescue StandardError
278
+ rescue
279
279
  # Ignore notification failures
280
280
  end
281
281
 
@@ -288,7 +288,7 @@ module RubyLLM
288
288
  "ruby_llm_agents.attempt.short_circuit",
289
289
  model_id: attempt[:model_id]
290
290
  )
291
- rescue StandardError
291
+ rescue
292
292
  # Ignore notification failures
293
293
  end
294
294
  end
@@ -58,9 +58,9 @@ module RubyLLM
58
58
  # @return [Float] Total spend in USD
59
59
  def current_global_spend(period)
60
60
  total = RubyLLM::Agents::Execution
61
- .where("created_at >= ?", period_start(period))
62
- .where(tenant_id: nil)
63
- .sum(:total_cost)
61
+ .where("created_at >= ?", period_start(period))
62
+ .where(tenant_id: nil)
63
+ .sum(:total_cost)
64
64
  key = SpendRecorder.budget_cache_key(:global, period)
65
65
  BudgetQuery.cache_write(key, total, expires_in: period_ttl(period))
66
66
  total
@@ -72,9 +72,9 @@ module RubyLLM
72
72
  # @return [Integer] Total tokens used
73
73
  def current_global_tokens(period)
74
74
  total = RubyLLM::Agents::Execution
75
- .where("created_at >= ?", period_start(period))
76
- .where(tenant_id: nil)
77
- .sum(:total_tokens)
75
+ .where("created_at >= ?", period_start(period))
76
+ .where(tenant_id: nil)
77
+ .sum(:total_tokens)
78
78
  key = SpendRecorder.token_cache_key(period)
79
79
  BudgetQuery.cache_write(key, total, expires_in: period_ttl(period))
80
80
  total
@@ -106,7 +106,7 @@ module RubyLLM
106
106
  # @param tenant_id [String, nil] The tenant identifier
107
107
  # @param budget_config [Hash] Budget configuration
108
108
  # @return [Float, nil] Remaining budget in USD, or nil if no limit configured
109
- def remaining_budget(scope, period, agent_type: nil, tenant_id: nil, budget_config:)
109
+ def remaining_budget(scope, period, budget_config:, agent_type: nil, tenant_id: nil)
110
110
  limit = case [scope, period]
111
111
  when [:global, :daily]
112
112
  budget_config[:global_daily]
@@ -129,7 +129,7 @@ module RubyLLM
129
129
  # @param tenant_id [String, nil] The tenant identifier
130
130
  # @param budget_config [Hash] Budget configuration
131
131
  # @return [Integer, nil] Remaining token budget, or nil if no limit configured
132
- def remaining_token_budget(period, tenant_id: nil, budget_config:)
132
+ def remaining_token_budget(period, budget_config:, tenant_id: nil)
133
133
  limit = case period
134
134
  when :daily
135
135
  budget_config[:global_daily_tokens]
@@ -148,7 +148,7 @@ module RubyLLM
148
148
  # @param tenant_id [String, nil] The tenant identifier
149
149
  # @param budget_config [Hash] Budget configuration
150
150
  # @return [Hash] Budget status information
151
- def status(agent_type: nil, tenant_id: nil, budget_config:)
151
+ def status(budget_config:, agent_type: nil, tenant_id: nil)
152
152
  {
153
153
  tenant_id: tenant_id,
154
154
  enabled: budget_config[:enabled],
@@ -120,7 +120,7 @@ module RubyLLM
120
120
  return nil unless tenant_budget_table_exists?
121
121
 
122
122
  TenantBudget.for_tenant(tenant_id)
123
- rescue StandardError => e
123
+ rescue => e
124
124
  Rails.logger.warn("[RubyLLM::Agents] Failed to lookup tenant budget: #{e.message}")
125
125
  nil
126
126
  end
@@ -133,8 +133,8 @@ module RubyLLM
133
133
 
134
134
  # Check for new table name (tenants) or old table name (tenant_budgets) for backward compatibility
135
135
  @tenant_budget_table_exists = ::ActiveRecord::Base.connection.table_exists?(:ruby_llm_agents_tenants) ||
136
- ::ActiveRecord::Base.connection.table_exists?(:ruby_llm_agents_tenant_budgets)
137
- rescue StandardError
136
+ ::ActiveRecord::Base.connection.table_exists?(:ruby_llm_agents_tenant_budgets)
137
+ rescue
138
138
  @tenant_budget_table_exists = false
139
139
  end
140
140
 
@@ -13,7 +13,7 @@ module RubyLLM
13
13
  # @param tenant_id [String, nil] The tenant identifier
14
14
  # @param budget_config [Hash] Budget configuration
15
15
  # @return [Hash, nil] Forecast information
16
- def calculate_forecast(tenant_id: nil, budget_config:)
16
+ def calculate_forecast(budget_config:, tenant_id: nil)
17
17
  return nil unless budget_config[:enabled]
18
18
  return nil unless budget_config[:global_daily] || budget_config[:global_monthly]
19
19