ruby_llm-agents 3.7.2 → 3.9.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 (68) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +30 -10
  3. data/app/controllers/ruby_llm/agents/agents_controller.rb +14 -141
  4. data/app/controllers/ruby_llm/agents/dashboard_controller.rb +12 -166
  5. data/app/controllers/ruby_llm/agents/executions_controller.rb +1 -1
  6. data/app/controllers/ruby_llm/agents/requests_controller.rb +117 -0
  7. data/app/helpers/ruby_llm/agents/application_helper.rb +38 -0
  8. data/app/models/ruby_llm/agents/execution/analytics.rb +302 -103
  9. data/app/models/ruby_llm/agents/execution.rb +76 -54
  10. data/app/models/ruby_llm/agents/execution_detail.rb +2 -0
  11. data/app/models/ruby_llm/agents/tenant.rb +39 -0
  12. data/app/services/ruby_llm/agents/agent_registry.rb +98 -0
  13. data/app/views/layouts/ruby_llm/agents/application.html.erb +4 -2
  14. data/app/views/ruby_llm/agents/executions/_list.html.erb +3 -17
  15. data/app/views/ruby_llm/agents/requests/index.html.erb +153 -0
  16. data/app/views/ruby_llm/agents/requests/show.html.erb +136 -0
  17. data/config/routes.rb +2 -0
  18. data/lib/generators/ruby_llm_agents/agent_generator.rb +2 -2
  19. data/lib/generators/ruby_llm_agents/demo_generator.rb +102 -0
  20. data/lib/generators/ruby_llm_agents/doctor_generator.rb +196 -0
  21. data/lib/generators/ruby_llm_agents/install_generator.rb +7 -19
  22. data/lib/generators/ruby_llm_agents/templates/add_dashboard_performance_indexes_migration.rb.tt +23 -0
  23. data/lib/generators/ruby_llm_agents/templates/agent.rb.tt +27 -80
  24. data/lib/generators/ruby_llm_agents/templates/application_agent.rb.tt +18 -51
  25. data/lib/generators/ruby_llm_agents/templates/initializer.rb.tt +19 -17
  26. data/lib/generators/ruby_llm_agents/templates/migration.rb.tt +3 -0
  27. data/lib/generators/ruby_llm_agents/upgrade_generator.rb +25 -0
  28. data/lib/ruby_llm/agents/base_agent.rb +71 -4
  29. data/lib/ruby_llm/agents/core/base.rb +4 -0
  30. data/lib/ruby_llm/agents/core/configuration.rb +11 -0
  31. data/lib/ruby_llm/agents/core/instrumentation.rb +15 -19
  32. data/lib/ruby_llm/agents/core/version.rb +1 -1
  33. data/lib/ruby_llm/agents/infrastructure/alert_manager.rb +4 -4
  34. data/lib/ruby_llm/agents/infrastructure/budget_tracker.rb +19 -11
  35. data/lib/ruby_llm/agents/pipeline/builder.rb +8 -4
  36. data/lib/ruby_llm/agents/pipeline/context.rb +69 -1
  37. data/lib/ruby_llm/agents/pipeline/middleware/base.rb +58 -4
  38. data/lib/ruby_llm/agents/pipeline/middleware/budget.rb +21 -17
  39. data/lib/ruby_llm/agents/pipeline/middleware/cache.rb +40 -26
  40. data/lib/ruby_llm/agents/pipeline/middleware/instrumentation.rb +126 -120
  41. data/lib/ruby_llm/agents/pipeline/middleware/reliability.rb +13 -11
  42. data/lib/ruby_llm/agents/pipeline/middleware/tenant.rb +29 -31
  43. data/lib/ruby_llm/agents/providers/inception/capabilities.rb +107 -0
  44. data/lib/ruby_llm/agents/providers/inception/chat.rb +17 -0
  45. data/lib/ruby_llm/agents/providers/inception/configuration.rb +9 -0
  46. data/lib/ruby_llm/agents/providers/inception/models.rb +38 -0
  47. data/lib/ruby_llm/agents/providers/inception/registry.rb +45 -0
  48. data/lib/ruby_llm/agents/providers/inception.rb +50 -0
  49. data/lib/ruby_llm/agents/rails/engine.rb +11 -0
  50. data/lib/ruby_llm/agents/results/background_removal_result.rb +7 -1
  51. data/lib/ruby_llm/agents/results/base.rb +28 -4
  52. data/lib/ruby_llm/agents/results/embedding_result.rb +4 -0
  53. data/lib/ruby_llm/agents/results/image_analysis_result.rb +11 -3
  54. data/lib/ruby_llm/agents/results/image_edit_result.rb +7 -1
  55. data/lib/ruby_llm/agents/results/image_generation_result.rb +7 -1
  56. data/lib/ruby_llm/agents/results/image_pipeline_result.rb +7 -1
  57. data/lib/ruby_llm/agents/results/image_transform_result.rb +7 -1
  58. data/lib/ruby_llm/agents/results/image_upscale_result.rb +7 -1
  59. data/lib/ruby_llm/agents/results/image_variation_result.rb +7 -1
  60. data/lib/ruby_llm/agents/results/speech_result.rb +6 -0
  61. data/lib/ruby_llm/agents/results/trackable.rb +25 -0
  62. data/lib/ruby_llm/agents/results/transcription_result.rb +6 -0
  63. data/lib/ruby_llm/agents/text/embedder.rb +8 -1
  64. data/lib/ruby_llm/agents/track_report.rb +127 -0
  65. data/lib/ruby_llm/agents/tracker.rb +32 -0
  66. data/lib/ruby_llm/agents.rb +212 -0
  67. data/lib/tasks/ruby_llm_agents.rake +6 -0
  68. metadata +17 -2
@@ -0,0 +1,107 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RubyLLM
4
+ module Agents
5
+ module Providers
6
+ class Inception
7
+ # Determines capabilities and pricing for Inception Mercury models.
8
+ #
9
+ # Mercury models are diffusion LLMs with text-only I/O.
10
+ # Pricing is per million tokens.
11
+ #
12
+ # Models:
13
+ # - mercury-2: Reasoning dLLM, function calling, structured output
14
+ # - mercury: Base chat dLLM, function calling, structured output
15
+ # - mercury-coder-small: Fast coding model
16
+ # - mercury-edit: Code editing/FIM model
17
+ module Capabilities
18
+ module_function
19
+
20
+ REASONING_MODELS = %w[mercury-2].freeze
21
+ CODER_MODELS = %w[mercury-coder-small mercury-edit].freeze
22
+ FUNCTION_CALLING_MODELS = %w[mercury-2 mercury].freeze
23
+
24
+ def context_window_for(_model_id)
25
+ 128_000
26
+ end
27
+
28
+ def max_tokens_for(_model_id)
29
+ 32_000
30
+ end
31
+
32
+ def input_price_for(_model_id)
33
+ 0.25
34
+ end
35
+
36
+ def output_price_for(model_id)
37
+ if CODER_MODELS.include?(model_id)
38
+ 1.00
39
+ else
40
+ 0.75
41
+ end
42
+ end
43
+
44
+ def supports_vision?(_model_id)
45
+ false
46
+ end
47
+
48
+ def supports_functions?(model_id)
49
+ FUNCTION_CALLING_MODELS.include?(model_id)
50
+ end
51
+
52
+ def supports_json_mode?(model_id)
53
+ FUNCTION_CALLING_MODELS.include?(model_id)
54
+ end
55
+
56
+ def format_display_name(model_id)
57
+ case model_id
58
+ when "mercury-2" then "Mercury 2"
59
+ when "mercury" then "Mercury"
60
+ when "mercury-coder-small" then "Mercury Coder Small"
61
+ when "mercury-edit" then "Mercury Edit"
62
+ else
63
+ model_id.split("-").map(&:capitalize).join(" ")
64
+ end
65
+ end
66
+
67
+ def model_type(model_id)
68
+ if CODER_MODELS.include?(model_id)
69
+ "code"
70
+ else
71
+ "chat"
72
+ end
73
+ end
74
+
75
+ def model_family(_model_id)
76
+ :mercury
77
+ end
78
+
79
+ def modalities_for(_model_id)
80
+ {input: ["text"], output: ["text"]}
81
+ end
82
+
83
+ def capabilities_for(model_id)
84
+ caps = ["streaming"]
85
+ if FUNCTION_CALLING_MODELS.include?(model_id)
86
+ caps << "function_calling"
87
+ caps << "structured_output"
88
+ end
89
+ caps << "reasoning" if REASONING_MODELS.include?(model_id)
90
+ caps
91
+ end
92
+
93
+ def pricing_for(model_id)
94
+ {
95
+ text_tokens: {
96
+ standard: {
97
+ input_per_million: input_price_for(model_id),
98
+ output_per_million: output_price_for(model_id)
99
+ }
100
+ }
101
+ }
102
+ end
103
+ end
104
+ end
105
+ end
106
+ end
107
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RubyLLM
4
+ module Agents
5
+ module Providers
6
+ class Inception
7
+ # Chat methods for Inception Mercury API.
8
+ # Mercury uses standard OpenAI chat format.
9
+ module Chat
10
+ def format_role(role)
11
+ role.to_s
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Extends RubyLLM::Configuration with Inception API key support.
4
+ # This allows users to configure: config.inception_api_key = ENV['INCEPTION_API_KEY']
5
+ module RubyLLM
6
+ class Configuration
7
+ attr_accessor :inception_api_key unless method_defined?(:inception_api_key)
8
+ end
9
+ end
@@ -0,0 +1,38 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RubyLLM
4
+ module Agents
5
+ module Providers
6
+ class Inception
7
+ # Parses model metadata from the Inception /models API endpoint.
8
+ # Response format is OpenAI-compatible.
9
+ module Models
10
+ module_function
11
+
12
+ def parse_list_models_response(response, slug, capabilities)
13
+ Array(response.body["data"]).map do |model_data|
14
+ model_id = model_data["id"]
15
+
16
+ ::RubyLLM::Model::Info.new(
17
+ id: model_id,
18
+ name: capabilities.format_display_name(model_id),
19
+ provider: slug,
20
+ family: "mercury",
21
+ created_at: model_data["created"] ? Time.at(model_data["created"]) : nil,
22
+ context_window: capabilities.context_window_for(model_id),
23
+ max_output_tokens: capabilities.max_tokens_for(model_id),
24
+ modalities: capabilities.modalities_for(model_id),
25
+ capabilities: capabilities.capabilities_for(model_id),
26
+ pricing: capabilities.pricing_for(model_id),
27
+ metadata: {
28
+ object: model_data["object"],
29
+ owned_by: model_data["owned_by"]
30
+ }.compact
31
+ )
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,45 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RubyLLM
4
+ module Agents
5
+ module Providers
6
+ class Inception
7
+ # Registers Mercury models in the RubyLLM model registry so they
8
+ # can be resolved by model ID without calling the Inception /models API.
9
+ module Registry
10
+ MODELS = [
11
+ {id: "mercury-2", name: "Mercury 2"},
12
+ {id: "mercury", name: "Mercury"},
13
+ {id: "mercury-coder-small", name: "Mercury Coder Small"},
14
+ {id: "mercury-edit", name: "Mercury Edit"}
15
+ ].freeze
16
+
17
+ module_function
18
+
19
+ def register_models!
20
+ models_instance = ::RubyLLM::Models.instance
21
+ capabilities = Inception::Capabilities
22
+
23
+ MODELS.each do |model_def|
24
+ model_id = model_def[:id]
25
+
26
+ model_info = ::RubyLLM::Model::Info.new(
27
+ id: model_id,
28
+ name: model_def[:name],
29
+ provider: "inception",
30
+ family: "mercury",
31
+ context_window: capabilities.context_window_for(model_id),
32
+ max_output_tokens: capabilities.max_tokens_for(model_id),
33
+ modalities: capabilities.modalities_for(model_id),
34
+ capabilities: capabilities.capabilities_for(model_id),
35
+ pricing: capabilities.pricing_for(model_id)
36
+ )
37
+
38
+ models_instance.all << model_info
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,50 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Configuration extension must be loaded first (adds inception_api_key to RubyLLM::Configuration)
4
+ require_relative "inception/configuration"
5
+
6
+ module RubyLLM
7
+ module Agents
8
+ module Providers
9
+ # Inception Labs Mercury API integration (OpenAI-compatible).
10
+ # Mercury models are diffusion LLMs (dLLMs) that generate tokens
11
+ # in parallel for dramatically faster inference.
12
+ #
13
+ # @see https://docs.inceptionlabs.ai/
14
+ class Inception < ::RubyLLM::Providers::OpenAI
15
+ def api_base
16
+ "https://api.inceptionlabs.ai/v1"
17
+ end
18
+
19
+ def headers
20
+ {
21
+ "Authorization" => "Bearer #{@config.inception_api_key}"
22
+ }
23
+ end
24
+
25
+ class << self
26
+ def capabilities
27
+ Inception::Capabilities
28
+ end
29
+
30
+ def configuration_requirements
31
+ %i[inception_api_key]
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
38
+
39
+ # Load sub-modules after the class is defined
40
+ require_relative "inception/capabilities"
41
+ require_relative "inception/chat"
42
+ require_relative "inception/models"
43
+ require_relative "inception/registry"
44
+
45
+ # Include modules after they're loaded
46
+ RubyLLM::Agents::Providers::Inception.include RubyLLM::Agents::Providers::Inception::Chat
47
+ RubyLLM::Agents::Providers::Inception.include RubyLLM::Agents::Providers::Inception::Models
48
+
49
+ # Register Mercury models in the RubyLLM model registry
50
+ RubyLLM::Agents::Providers::Inception::Registry.register_models!
@@ -53,6 +53,17 @@ module RubyLLM
53
53
  helper RubyLLM::Agents::ApplicationHelper
54
54
  before_action :authenticate_dashboard!
55
55
 
56
+ rescue_from ::ActiveRecord::StatementInvalid do |e|
57
+ if e.message.include?("ruby_llm_agents_")
58
+ render plain: "RubyLLM::Agents migrations are pending.\n\n" \
59
+ "Run: rails db:migrate\n" \
60
+ "Or: rails ruby_llm_agents:doctor",
61
+ status: :service_unavailable
62
+ else
63
+ raise
64
+ end
65
+ end
66
+
56
67
  private
57
68
 
58
69
  # Authenticates dashboard access using configured method
@@ -15,6 +15,8 @@ module RubyLLM
15
15
  # result.success? # => true
16
16
  #
17
17
  class BackgroundRemovalResult
18
+ include Trackable
19
+
18
20
  attr_reader :foreground, :mask, :source_image, :model_id, :output_format,
19
21
  :alpha_matting, :refine_edges,
20
22
  :started_at, :completed_at, :tenant_id, :remover_class,
@@ -38,7 +40,7 @@ module RubyLLM
38
40
  # @param error_message [String, nil] Error message if failed
39
41
  def initialize(foreground:, mask:, source_image:, model_id:, output_format:,
40
42
  alpha_matting:, refine_edges:, started_at:, completed_at:,
41
- tenant_id:, remover_class:, error_class: nil, error_message: nil)
43
+ tenant_id:, remover_class:, error_class: nil, error_message: nil, agent_class_name: nil)
42
44
  @foreground = foreground
43
45
  @mask = mask
44
46
  @source_image = source_image
@@ -53,6 +55,10 @@ module RubyLLM
53
55
  @error_class = error_class
54
56
  @error_message = error_message
55
57
  @execution_id = nil
58
+
59
+ # Tracking
60
+ @agent_class_name = agent_class_name
61
+ register_with_tracker
56
62
  end
57
63
 
58
64
  # Loads the associated Execution record from the database
@@ -107,6 +107,16 @@ module RubyLLM
107
107
  # @return [Integer, nil] Database ID of the associated Execution record
108
108
  attr_reader :execution_id
109
109
 
110
+ # @!group Tracking
111
+ # @!attribute [r] agent_class_name
112
+ # @return [String, nil] The agent class that produced this result
113
+ attr_reader :agent_class_name
114
+
115
+ # @!group Debug
116
+ # @!attribute [r] trace
117
+ # @return [Array<Hash>, nil] Pipeline trace entries (when debug: true)
118
+ attr_reader :trace
119
+
110
120
  # Creates a new Result instance
111
121
  #
112
122
  # @param content [Hash, String] The processed response content
@@ -159,6 +169,16 @@ module RubyLLM
159
169
 
160
170
  # Execution record
161
171
  @execution_id = options[:execution_id]
172
+
173
+ # Tracking
174
+ @agent_class_name = options[:agent_class_name]
175
+
176
+ # Debug trace
177
+ @trace = options[:trace]
178
+
179
+ # Register with active tracker
180
+ tracker = Thread.current[:ruby_llm_agents_tracker]
181
+ tracker << self if tracker
162
182
  end
163
183
 
164
184
  # Loads the associated Execution record from the database
@@ -219,16 +239,18 @@ module RubyLLM
219
239
  # Returns whether tool calls were made during execution
220
240
  #
221
241
  # @return [Boolean] true if tool_calls_count > 0
222
- def has_tool_calls?
242
+ def tool_calls?
223
243
  tool_calls_count.to_i > 0
224
244
  end
245
+ alias_method :has_tool_calls?, :tool_calls?
225
246
 
226
247
  # Returns whether thinking data is present in the result
227
248
  #
228
249
  # @return [Boolean] true if thinking_text is present
229
- def has_thinking?
250
+ def thinking?
230
251
  thinking_text.present?
231
252
  end
253
+ alias_method :has_thinking?, :thinking?
232
254
 
233
255
  # Converts the result to a hash
234
256
  #
@@ -262,8 +284,10 @@ module RubyLLM
262
284
  thinking_text: thinking_text,
263
285
  thinking_signature: thinking_signature,
264
286
  thinking_tokens: thinking_tokens,
265
- execution_id: execution_id
266
- }
287
+ execution_id: execution_id,
288
+ agent_class_name: agent_class_name,
289
+ trace: trace
290
+ }.compact
267
291
  end
268
292
 
269
293
  # @!group Deprecated Hash Delegation
@@ -25,6 +25,8 @@ module RubyLLM
25
25
  #
26
26
  # @api public
27
27
  class EmbeddingResult
28
+ include Trackable
29
+
28
30
  # @!attribute [r] vectors
29
31
  # @return [Array<Array<Float>>] The embedding vectors
30
32
  attr_reader :vectors
@@ -106,6 +108,8 @@ module RubyLLM
106
108
  @error_class = attributes[:error_class]
107
109
  @error_message = attributes[:error_message]
108
110
  @execution_id = attributes[:execution_id]
111
+ @agent_class_name = attributes[:agent_class_name]
112
+ register_with_tracker
109
113
  end
110
114
 
111
115
  # Loads the associated Execution record from the database
@@ -17,6 +17,8 @@ module RubyLLM
17
17
  # result.success? # => true
18
18
  #
19
19
  class ImageAnalysisResult
20
+ include Trackable
21
+
20
22
  attr_reader :image, :model_id, :analysis_type,
21
23
  :caption, :description, :tags, :objects, :colors, :text,
22
24
  :raw_response, :started_at, :completed_at, :tenant_id, :analyzer_class,
@@ -43,7 +45,7 @@ module RubyLLM
43
45
  # @param error_message [String, nil] Error message if failed
44
46
  def initialize(image:, model_id:, analysis_type:, caption:, description:, tags:,
45
47
  objects:, colors:, text:, raw_response:, started_at:, completed_at:,
46
- tenant_id:, analyzer_class:, error_class: nil, error_message: nil)
48
+ tenant_id:, analyzer_class:, error_class: nil, error_message: nil, agent_class_name: nil)
47
49
  @image = image
48
50
  @model_id = model_id
49
51
  @analysis_type = analysis_type
@@ -61,6 +63,10 @@ module RubyLLM
61
63
  @error_class = error_class
62
64
  @error_message = error_message
63
65
  @execution_id = nil
66
+
67
+ # Tracking
68
+ @agent_class_name = agent_class_name
69
+ register_with_tracker
64
70
  end
65
71
 
66
72
  # Loads the associated Execution record from the database
@@ -161,17 +167,19 @@ module RubyLLM
161
167
  #
162
168
  # @param name [String] Object name to search for
163
169
  # @return [Boolean] Whether the object was detected
164
- def has_object?(name)
170
+ def includes_object?(name)
165
171
  objects.any? { |obj| obj[:name]&.downcase&.include?(name.to_s.downcase) }
166
172
  end
173
+ alias_method :has_object?, :includes_object?
167
174
 
168
175
  # Check if a specific tag is present
169
176
  #
170
177
  # @param tag [String] Tag to search for
171
178
  # @return [Boolean] Whether the tag is present
172
- def has_tag?(tag)
179
+ def includes_tag?(tag)
173
180
  tags.any? { |t| t.downcase == tag.to_s.downcase }
174
181
  end
182
+ alias_method :has_tag?, :includes_tag?
175
183
 
176
184
  # Timing
177
185
 
@@ -17,6 +17,8 @@ module RubyLLM
17
17
  # result.success? # => true
18
18
  #
19
19
  class ImageEditResult
20
+ include Trackable
21
+
20
22
  attr_reader :images, :source_image, :mask, :prompt, :model_id, :size,
21
23
  :started_at, :completed_at, :tenant_id, :editor_class,
22
24
  :error_class, :error_message
@@ -38,7 +40,7 @@ module RubyLLM
38
40
  # @param error_message [String, nil] Error message if failed
39
41
  def initialize(images:, source_image:, mask:, prompt:, model_id:, size:,
40
42
  started_at:, completed_at:, tenant_id:, editor_class:,
41
- error_class: nil, error_message: nil)
43
+ error_class: nil, error_message: nil, agent_class_name: nil)
42
44
  @images = images
43
45
  @source_image = source_image
44
46
  @mask = mask
@@ -52,6 +54,10 @@ module RubyLLM
52
54
  @error_class = error_class
53
55
  @error_message = error_message
54
56
  @execution_id = nil
57
+
58
+ # Tracking
59
+ @agent_class_name = agent_class_name
60
+ register_with_tracker
55
61
  end
56
62
 
57
63
  # Loads the associated Execution record from the database
@@ -20,6 +20,8 @@ module RubyLLM
20
20
  # result.save_all("./logos")
21
21
  #
22
22
  class ImageGenerationResult
23
+ include Trackable
24
+
23
25
  attr_reader :images, :prompt, :model_id, :size, :quality, :style,
24
26
  :started_at, :completed_at, :tenant_id, :generator_class,
25
27
  :error_class, :error_message, :execution_id
@@ -40,7 +42,7 @@ module RubyLLM
40
42
  # @param error_message [String, nil] Error message if failed
41
43
  def initialize(images:, prompt:, model_id:, size:, quality:, style:,
42
44
  started_at:, completed_at:, tenant_id:, generator_class:,
43
- error_class: nil, error_message: nil, execution_id: nil)
45
+ error_class: nil, error_message: nil, execution_id: nil, agent_class_name: nil)
44
46
  @images = images
45
47
  @prompt = prompt
46
48
  @model_id = model_id
@@ -54,6 +56,10 @@ module RubyLLM
54
56
  @error_class = error_class
55
57
  @error_message = error_message
56
58
  @execution_id = execution_id
59
+
60
+ # Tracking
61
+ @agent_class_name = agent_class_name
62
+ register_with_tracker
57
63
  end
58
64
 
59
65
  # Loads the associated Execution record from the database
@@ -21,6 +21,8 @@ module RubyLLM
21
21
  # result.analysis # => Shortcut to analyzer step result
22
22
  #
23
23
  class ImagePipelineResult
24
+ include Trackable
25
+
24
26
  attr_reader :step_results, :started_at, :completed_at, :tenant_id,
25
27
  :pipeline_class, :context, :error_class, :error_message
26
28
  attr_accessor :execution_id
@@ -36,7 +38,7 @@ module RubyLLM
36
38
  # @param error_class [String, nil] Error class name if failed
37
39
  # @param error_message [String, nil] Error message if failed
38
40
  def initialize(step_results:, started_at:, completed_at:, tenant_id:,
39
- pipeline_class:, context:, error_class: nil, error_message: nil)
41
+ pipeline_class:, context:, error_class: nil, error_message: nil, agent_class_name: nil)
40
42
  @step_results = step_results
41
43
  @started_at = started_at
42
44
  @completed_at = completed_at
@@ -46,6 +48,10 @@ module RubyLLM
46
48
  @error_class = error_class
47
49
  @error_message = error_message
48
50
  @execution_id = nil
51
+
52
+ # Tracking
53
+ @agent_class_name = agent_class_name
54
+ register_with_tracker
49
55
  end
50
56
 
51
57
  # Loads the associated Execution record from the database
@@ -17,6 +17,8 @@ module RubyLLM
17
17
  # result.success? # => true
18
18
  #
19
19
  class ImageTransformResult
20
+ include Trackable
21
+
20
22
  attr_reader :images, :source_image, :prompt, :model_id, :size, :strength,
21
23
  :started_at, :completed_at, :tenant_id, :transformer_class,
22
24
  :error_class, :error_message
@@ -38,7 +40,7 @@ module RubyLLM
38
40
  # @param error_message [String, nil] Error message if failed
39
41
  def initialize(images:, source_image:, prompt:, model_id:, size:, strength:,
40
42
  started_at:, completed_at:, tenant_id:, transformer_class:,
41
- error_class: nil, error_message: nil)
43
+ error_class: nil, error_message: nil, agent_class_name: nil)
42
44
  @images = images
43
45
  @source_image = source_image
44
46
  @prompt = prompt
@@ -52,6 +54,10 @@ module RubyLLM
52
54
  @error_class = error_class
53
55
  @error_message = error_message
54
56
  @execution_id = nil
57
+
58
+ # Tracking
59
+ @agent_class_name = agent_class_name
60
+ register_with_tracker
55
61
  end
56
62
 
57
63
  # Loads the associated Execution record from the database
@@ -15,6 +15,8 @@ module RubyLLM
15
15
  # result.success? # => true
16
16
  #
17
17
  class ImageUpscaleResult
18
+ include Trackable
19
+
18
20
  attr_reader :image, :source_image, :model_id, :scale, :output_size, :face_enhance,
19
21
  :started_at, :completed_at, :tenant_id, :upscaler_class,
20
22
  :error_class, :error_message
@@ -36,7 +38,7 @@ module RubyLLM
36
38
  # @param error_message [String, nil] Error message if failed
37
39
  def initialize(image:, source_image:, model_id:, scale:, output_size:, face_enhance:,
38
40
  started_at:, completed_at:, tenant_id:, upscaler_class:,
39
- error_class: nil, error_message: nil)
41
+ error_class: nil, error_message: nil, agent_class_name: nil)
40
42
  @image = image
41
43
  @source_image = source_image
42
44
  @model_id = model_id
@@ -50,6 +52,10 @@ module RubyLLM
50
52
  @error_class = error_class
51
53
  @error_message = error_message
52
54
  @execution_id = nil
55
+
56
+ # Tracking
57
+ @agent_class_name = agent_class_name
58
+ register_with_tracker
53
59
  end
54
60
 
55
61
  # Loads the associated Execution record from the database
@@ -14,6 +14,8 @@ module RubyLLM
14
14
  # result.success? # => true
15
15
  #
16
16
  class ImageVariationResult
17
+ include Trackable
18
+
17
19
  attr_reader :images, :source_image, :model_id, :size, :variation_strength,
18
20
  :started_at, :completed_at, :tenant_id, :variator_class,
19
21
  :error_class, :error_message
@@ -34,7 +36,7 @@ module RubyLLM
34
36
  # @param error_message [String, nil] Error message if failed
35
37
  def initialize(images:, source_image:, model_id:, size:, variation_strength:,
36
38
  started_at:, completed_at:, tenant_id:, variator_class:,
37
- error_class: nil, error_message: nil)
39
+ error_class: nil, error_message: nil, agent_class_name: nil)
38
40
  @images = images
39
41
  @source_image = source_image
40
42
  @model_id = model_id
@@ -47,6 +49,10 @@ module RubyLLM
47
49
  @error_class = error_class
48
50
  @error_message = error_message
49
51
  @execution_id = nil
52
+
53
+ # Tracking
54
+ @agent_class_name = agent_class_name
55
+ register_with_tracker
50
56
  end
51
57
 
52
58
  # Loads the associated Execution record from the database
@@ -23,6 +23,8 @@ module RubyLLM
23
23
  #
24
24
  # @api public
25
25
  class SpeechResult
26
+ include Trackable
27
+
26
28
  # @!group Audio Content
27
29
 
28
30
  # @!attribute [r] audio
@@ -229,6 +231,10 @@ module RubyLLM
229
231
 
230
232
  # Execution record
231
233
  @execution_id = attributes[:execution_id]
234
+
235
+ # Tracking
236
+ @agent_class_name = attributes[:agent_class_name]
237
+ register_with_tracker
232
238
  end
233
239
 
234
240
  # Loads the associated Execution record from the database
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RubyLLM
4
+ module Agents
5
+ # Mixin that registers a result object with the active Tracker.
6
+ #
7
+ # Included in every result class so that RubyLLM::Agents.track
8
+ # can collect results automatically.
9
+ #
10
+ # @api private
11
+ module Trackable
12
+ def self.included(base)
13
+ base.attr_reader :agent_class_name unless base.method_defined?(:agent_class_name)
14
+ end
15
+
16
+ private
17
+
18
+ # Call from the end of initialize to register with the active tracker
19
+ def register_with_tracker
20
+ tracker = Thread.current[:ruby_llm_agents_tracker]
21
+ tracker << self if tracker
22
+ end
23
+ end
24
+ end
25
+ end