ruby_llm-agents 0.2.4 → 0.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 (62) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +273 -0
  3. data/app/channels/ruby_llm/agents/executions_channel.rb +24 -1
  4. data/app/controllers/concerns/ruby_llm/agents/filterable.rb +81 -0
  5. data/app/controllers/concerns/ruby_llm/agents/paginatable.rb +51 -0
  6. data/app/controllers/ruby_llm/agents/agents_controller.rb +228 -59
  7. data/app/controllers/ruby_llm/agents/dashboard_controller.rb +167 -12
  8. data/app/controllers/ruby_llm/agents/executions_controller.rb +189 -31
  9. data/app/controllers/ruby_llm/agents/settings_controller.rb +20 -0
  10. data/app/helpers/ruby_llm/agents/application_helper.rb +307 -7
  11. data/app/models/ruby_llm/agents/execution/analytics.rb +224 -20
  12. data/app/models/ruby_llm/agents/execution/metrics.rb +41 -25
  13. data/app/models/ruby_llm/agents/execution/scopes.rb +234 -14
  14. data/app/models/ruby_llm/agents/execution.rb +259 -16
  15. data/app/services/ruby_llm/agents/agent_registry.rb +49 -12
  16. data/app/views/layouts/rubyllm/agents/application.html.erb +351 -85
  17. data/app/views/rubyllm/agents/agents/_version_comparison.html.erb +186 -0
  18. data/app/views/rubyllm/agents/agents/show.html.erb +233 -10
  19. data/app/views/rubyllm/agents/dashboard/_action_center.html.erb +62 -0
  20. data/app/views/rubyllm/agents/dashboard/_alerts_feed.html.erb +62 -0
  21. data/app/views/rubyllm/agents/dashboard/_breaker_strip.html.erb +47 -0
  22. data/app/views/rubyllm/agents/dashboard/_budgets_bar.html.erb +165 -0
  23. data/app/views/rubyllm/agents/dashboard/_now_strip.html.erb +10 -0
  24. data/app/views/rubyllm/agents/dashboard/_now_strip_values.html.erb +71 -0
  25. data/app/views/rubyllm/agents/dashboard/index.html.erb +215 -109
  26. data/app/views/rubyllm/agents/executions/_filters.html.erb +152 -155
  27. data/app/views/rubyllm/agents/executions/_list.html.erb +103 -12
  28. data/app/views/rubyllm/agents/executions/dry_run.html.erb +149 -0
  29. data/app/views/rubyllm/agents/executions/index.html.erb +17 -72
  30. data/app/views/rubyllm/agents/executions/index.turbo_stream.erb +16 -2
  31. data/app/views/rubyllm/agents/executions/show.html.erb +693 -14
  32. data/app/views/rubyllm/agents/settings/show.html.erb +369 -0
  33. data/app/views/rubyllm/agents/shared/_filter_dropdown.html.erb +121 -0
  34. data/app/views/rubyllm/agents/shared/_select_dropdown.html.erb +85 -0
  35. data/config/routes.rb +7 -0
  36. data/lib/generators/ruby_llm_agents/templates/add_attempts_migration.rb.tt +27 -0
  37. data/lib/generators/ruby_llm_agents/templates/add_caching_migration.rb.tt +23 -0
  38. data/lib/generators/ruby_llm_agents/templates/add_finish_reason_migration.rb.tt +19 -0
  39. data/lib/generators/ruby_llm_agents/templates/add_routing_migration.rb.tt +19 -0
  40. data/lib/generators/ruby_llm_agents/templates/add_streaming_migration.rb.tt +8 -0
  41. data/lib/generators/ruby_llm_agents/templates/add_tracing_migration.rb.tt +34 -0
  42. data/lib/generators/ruby_llm_agents/templates/agent.rb.tt +66 -4
  43. data/lib/generators/ruby_llm_agents/templates/application_agent.rb.tt +53 -6
  44. data/lib/generators/ruby_llm_agents/templates/initializer.rb.tt +139 -8
  45. data/lib/generators/ruby_llm_agents/templates/migration.rb.tt +38 -1
  46. data/lib/generators/ruby_llm_agents/upgrade_generator.rb +78 -0
  47. data/lib/ruby_llm/agents/alert_manager.rb +207 -0
  48. data/lib/ruby_llm/agents/attempt_tracker.rb +295 -0
  49. data/lib/ruby_llm/agents/base.rb +580 -112
  50. data/lib/ruby_llm/agents/budget_tracker.rb +360 -0
  51. data/lib/ruby_llm/agents/circuit_breaker.rb +197 -0
  52. data/lib/ruby_llm/agents/configuration.rb +279 -1
  53. data/lib/ruby_llm/agents/engine.rb +58 -6
  54. data/lib/ruby_llm/agents/execution_logger_job.rb +17 -6
  55. data/lib/ruby_llm/agents/inflections.rb +13 -2
  56. data/lib/ruby_llm/agents/instrumentation.rb +538 -87
  57. data/lib/ruby_llm/agents/redactor.rb +130 -0
  58. data/lib/ruby_llm/agents/reliability.rb +185 -0
  59. data/lib/ruby_llm/agents/version.rb +3 -1
  60. data/lib/ruby_llm/agents.rb +52 -0
  61. metadata +41 -2
  62. data/app/controllers/ruby_llm/agents/application_controller.rb +0 -37
@@ -0,0 +1,130 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RubyLLM
4
+ module Agents
5
+ # Unified redaction utility for PII and sensitive data
6
+ #
7
+ # Provides methods to redact sensitive information from hashes, arrays, and strings
8
+ # based on configurable field names and regex patterns.
9
+ #
10
+ # @example Redacting a hash
11
+ # Redactor.redact({ password: "secret", name: "John" })
12
+ # # => { password: "[REDACTED]", name: "John" }
13
+ #
14
+ # @example Redacting a string with patterns
15
+ # Redactor.redact_string("SSN: 123-45-6789")
16
+ # # => "SSN: [REDACTED]"
17
+ #
18
+ # @see RubyLLM::Agents::Configuration
19
+ # @api public
20
+ module Redactor
21
+ class << self
22
+ # Redacts sensitive data from an object (hash, array, or primitive)
23
+ #
24
+ # @param obj [Object] The object to redact
25
+ # @param config [Configuration, nil] Optional configuration override
26
+ # @return [Object] The redacted object (new object, original not modified)
27
+ def redact(obj, config = nil)
28
+ config ||= RubyLLM::Agents.configuration
29
+
30
+ case obj
31
+ when Hash
32
+ redact_hash(obj, config)
33
+ when Array
34
+ redact_array(obj, config)
35
+ when String
36
+ redact_string(obj, config)
37
+ else
38
+ obj
39
+ end
40
+ end
41
+
42
+ # Redacts sensitive data from a string using configured patterns
43
+ #
44
+ # @param str [String, nil] The string to redact
45
+ # @param config [Configuration, nil] Optional configuration override
46
+ # @return [String, nil] The redacted string
47
+ def redact_string(str, config = nil)
48
+ return nil if str.nil?
49
+ return str unless str.is_a?(String)
50
+
51
+ config ||= RubyLLM::Agents.configuration
52
+ result = str.dup
53
+
54
+ # Apply pattern-based redaction
55
+ config.redaction_patterns.each do |pattern|
56
+ result = result.gsub(pattern, config.redaction_placeholder)
57
+ end
58
+
59
+ # Truncate if max length is configured
60
+ max_length = config.redaction_max_value_length
61
+ if max_length && result.length > max_length
62
+ result = result[0, max_length] + "..."
63
+ end
64
+
65
+ result
66
+ end
67
+
68
+ private
69
+
70
+ # Redacts sensitive fields from a hash
71
+ #
72
+ # @param hash [Hash] The hash to redact
73
+ # @param config [Configuration] The configuration
74
+ # @return [Hash] The redacted hash
75
+ def redact_hash(hash, config)
76
+ hash.each_with_object({}) do |(key, value), result|
77
+ key_str = key.to_s.downcase
78
+
79
+ if sensitive_field?(key_str, config)
80
+ result[key] = config.redaction_placeholder
81
+ else
82
+ result[key] = redact_value(value, config)
83
+ end
84
+ end
85
+ end
86
+
87
+ # Redacts sensitive values from an array
88
+ #
89
+ # @param array [Array] The array to redact
90
+ # @param config [Configuration] The configuration
91
+ # @return [Array] The redacted array
92
+ def redact_array(array, config)
93
+ array.map { |item| redact(item, config) }
94
+ end
95
+
96
+ # Redacts a single value based on its type
97
+ #
98
+ # @param value [Object] The value to redact
99
+ # @param config [Configuration] The configuration
100
+ # @return [Object] The redacted value
101
+ def redact_value(value, config)
102
+ case value
103
+ when Hash
104
+ redact_hash(value, config)
105
+ when Array
106
+ redact_array(value, config)
107
+ when String
108
+ redact_string(value, config)
109
+ when defined?(ActiveRecord::Base) && ActiveRecord::Base
110
+ # Convert ActiveRecord objects to safe references
111
+ { id: value.id, type: value.class.name }
112
+ else
113
+ value
114
+ end
115
+ end
116
+
117
+ # Checks if a field name is sensitive
118
+ #
119
+ # @param field_name [String] The field name to check (lowercase)
120
+ # @param config [Configuration] The configuration
121
+ # @return [Boolean] true if the field should be redacted
122
+ def sensitive_field?(field_name, config)
123
+ config.redaction_fields.any? do |sensitive|
124
+ field_name.include?(sensitive.downcase)
125
+ end
126
+ end
127
+ end
128
+ end
129
+ end
130
+ end
@@ -0,0 +1,185 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RubyLLM
4
+ module Agents
5
+ # Reliability module providing error classes and utilities for retry/fallback logic
6
+ #
7
+ # This module defines custom error types for reliability features and provides
8
+ # utilities for determining which errors are retryable.
9
+ #
10
+ # @example Checking if an error is retryable
11
+ # Reliability.retryable_error?(Timeout::Error.new) # => true
12
+ # Reliability.retryable_error?(ArgumentError.new) # => false
13
+ #
14
+ # @see RubyLLM::Agents::Base
15
+ # @api public
16
+ module Reliability
17
+ # Base error class for all reliability-related errors
18
+ #
19
+ # @api public
20
+ class Error < StandardError; end
21
+
22
+ # Raised when the circuit breaker is open and requests are being blocked
23
+ #
24
+ # @example
25
+ # raise CircuitBreakerOpenError.new("MyAgent", "gpt-4o")
26
+ #
27
+ # @api public
28
+ class CircuitBreakerOpenError < Error
29
+ attr_reader :agent_type, :model_id
30
+
31
+ # @param agent_type [String] The agent class name
32
+ # @param model_id [String] The model identifier
33
+ def initialize(agent_type, model_id)
34
+ @agent_type = agent_type
35
+ @model_id = model_id
36
+ super("Circuit breaker is open for #{agent_type} with model #{model_id}")
37
+ end
38
+ end
39
+
40
+ # Raised when budget limits have been exceeded
41
+ #
42
+ # @example
43
+ # raise BudgetExceededError.new(:global_daily, 25.0, 27.5)
44
+ #
45
+ # @api public
46
+ class BudgetExceededError < Error
47
+ attr_reader :scope, :limit, :current
48
+
49
+ # @param scope [Symbol] The budget scope (:global_daily, :global_monthly, :per_agent_daily, etc.)
50
+ # @param limit [Float] The budget limit in USD
51
+ # @param current [Float] The current spend in USD
52
+ # @param agent_type [String, nil] The agent type for per-agent budgets
53
+ def initialize(scope, limit, current, agent_type: nil)
54
+ @scope = scope
55
+ @limit = limit
56
+ @current = current
57
+ @agent_type = agent_type
58
+
59
+ message = "Budget exceeded for #{scope}"
60
+ message += " (#{agent_type})" if agent_type
61
+ message += ": limit $#{limit}, current $#{current}"
62
+ super(message)
63
+ end
64
+ end
65
+
66
+ # Raised when the total timeout for all retry/fallback attempts is exceeded
67
+ #
68
+ # @api public
69
+ class TotalTimeoutError < Error
70
+ attr_reader :timeout_seconds, :elapsed_seconds
71
+
72
+ # @param timeout_seconds [Integer] The configured total timeout
73
+ # @param elapsed_seconds [Float] The elapsed time when timeout occurred
74
+ def initialize(timeout_seconds, elapsed_seconds)
75
+ @timeout_seconds = timeout_seconds
76
+ @elapsed_seconds = elapsed_seconds
77
+ super("Total timeout of #{timeout_seconds}s exceeded (elapsed: #{elapsed_seconds.round(2)}s)")
78
+ end
79
+ end
80
+
81
+ # Raised when all models in the fallback chain have been exhausted
82
+ #
83
+ # @api public
84
+ class AllModelsExhaustedError < Error
85
+ attr_reader :models_tried, :last_error
86
+
87
+ # @param models_tried [Array<String>] List of models that were attempted
88
+ # @param last_error [Exception] The last error that occurred
89
+ def initialize(models_tried, last_error)
90
+ @models_tried = models_tried
91
+ @last_error = last_error
92
+ super("All models exhausted: #{models_tried.join(', ')}. Last error: #{last_error.message}")
93
+ end
94
+ end
95
+
96
+ class << self
97
+ # Default list of error classes that are considered retryable
98
+ #
99
+ # These errors typically indicate transient issues that may resolve on retry.
100
+ #
101
+ # @return [Array<Class>] Error classes that are retryable by default
102
+ def default_retryable_errors
103
+ @default_retryable_errors ||= [
104
+ Timeout::Error,
105
+ defined?(Net::OpenTimeout) ? Net::OpenTimeout : nil,
106
+ defined?(Net::ReadTimeout) ? Net::ReadTimeout : nil,
107
+ defined?(Faraday::TimeoutError) ? Faraday::TimeoutError : nil,
108
+ defined?(Faraday::ConnectionFailed) ? Faraday::ConnectionFailed : nil,
109
+ defined?(Errno::ECONNREFUSED) ? Errno::ECONNREFUSED : nil,
110
+ defined?(Errno::ECONNRESET) ? Errno::ECONNRESET : nil,
111
+ defined?(Errno::ETIMEDOUT) ? Errno::ETIMEDOUT : nil,
112
+ defined?(SocketError) ? SocketError : nil,
113
+ defined?(OpenSSL::SSL::SSLError) ? OpenSSL::SSL::SSLError : nil
114
+ ].compact
115
+ end
116
+
117
+ # Determines if an error is retryable based on default and custom error classes
118
+ #
119
+ # @param error [Exception] The error to check
120
+ # @param custom_errors [Array<Class>] Additional error classes to consider retryable
121
+ # @return [Boolean] true if the error is retryable
122
+ def retryable_error?(error, custom_errors: [])
123
+ all_retryable = default_retryable_errors + Array(custom_errors)
124
+ all_retryable.any? { |klass| error.is_a?(klass) } || retryable_by_message?(error)
125
+ end
126
+
127
+ # Determines if an error is retryable based on its message content
128
+ #
129
+ # Some errors (like HTTP 5xx responses) may not have specific error classes
130
+ # but can be identified by their message.
131
+ #
132
+ # @param error [Exception] The error to check
133
+ # @return [Boolean] true if the error message indicates a retryable condition
134
+ def retryable_by_message?(error)
135
+ message = error.message.to_s.downcase
136
+ retryable_patterns.any? { |pattern| message.include?(pattern) }
137
+ end
138
+
139
+ # Patterns in error messages that indicate retryable errors
140
+ #
141
+ # @return [Array<String>] Patterns to match against error messages
142
+ def retryable_patterns
143
+ @retryable_patterns ||= [
144
+ "rate limit",
145
+ "rate_limit",
146
+ "too many requests",
147
+ "429",
148
+ "500",
149
+ "502",
150
+ "503",
151
+ "504",
152
+ "service unavailable",
153
+ "internal server error",
154
+ "bad gateway",
155
+ "gateway timeout",
156
+ "overloaded",
157
+ "capacity"
158
+ ].freeze
159
+ end
160
+
161
+ # Calculates the backoff delay for a retry attempt
162
+ #
163
+ # @param strategy [Symbol] The backoff strategy (:constant or :exponential)
164
+ # @param base [Float] The base delay in seconds
165
+ # @param max_delay [Float] The maximum delay in seconds
166
+ # @param attempt [Integer] The current attempt number (0-indexed)
167
+ # @return [Float] The delay in seconds (including jitter)
168
+ def calculate_backoff(strategy:, base:, max_delay:, attempt:)
169
+ delay = case strategy
170
+ when :constant
171
+ base
172
+ when :exponential
173
+ [base * (2**attempt), max_delay].min
174
+ else
175
+ base
176
+ end
177
+
178
+ # Add jitter (0 to 50% of delay)
179
+ jitter = rand * delay * 0.5
180
+ delay + jitter
181
+ end
182
+ end
183
+ end
184
+ end
185
+ end
@@ -2,6 +2,8 @@
2
2
 
3
3
  module RubyLLM
4
4
  module Agents
5
- VERSION = "0.2.4"
5
+ # Current version of the RubyLLM::Agents gem
6
+ # @return [String] Semantic version string
7
+ VERSION = "0.3.0"
6
8
  end
7
9
  end
@@ -1,23 +1,75 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "csv"
4
+
3
5
  require_relative "agents/version"
4
6
  require_relative "agents/configuration"
7
+ require_relative "agents/reliability"
8
+ require_relative "agents/redactor"
9
+ require_relative "agents/circuit_breaker"
10
+ require_relative "agents/budget_tracker"
11
+ require_relative "agents/alert_manager"
12
+ require_relative "agents/attempt_tracker"
5
13
  require_relative "agents/inflections" if defined?(Rails)
6
14
  require_relative "agents/engine" if defined?(Rails::Engine)
7
15
 
8
16
  module RubyLLM
17
+ # Agent framework for building LLM-powered agents with observability
18
+ #
19
+ # RubyLLM::Agents provides a DSL for creating agents that interact with
20
+ # large language models, with built-in execution tracking, cost monitoring,
21
+ # and a dashboard for observability.
22
+ #
23
+ # @example Basic configuration
24
+ # RubyLLM::Agents.configure do |config|
25
+ # config.default_model = "gpt-4o"
26
+ # config.async_logging = true
27
+ # end
28
+ #
29
+ # @example Creating an agent
30
+ # class SearchAgent < ApplicationAgent
31
+ # model "gpt-4o"
32
+ # param :query, required: true
33
+ #
34
+ # def user_prompt
35
+ # "Search for: #{query}"
36
+ # end
37
+ # end
38
+ #
39
+ # SearchAgent.call(query: "ruby gems")
40
+ #
41
+ # @see RubyLLM::Agents::Base
42
+ # @see RubyLLM::Agents::Configuration
9
43
  module Agents
44
+ # Base error class for agent-related exceptions
10
45
  class Error < StandardError; end
11
46
 
12
47
  class << self
48
+ # Returns the global configuration instance
49
+ #
50
+ # @return [Configuration] The configuration object
13
51
  def configuration
14
52
  @configuration ||= Configuration.new
15
53
  end
16
54
 
55
+ # Yields the configuration for modification
56
+ #
57
+ # @yield [Configuration] The configuration object
58
+ # @return [void]
59
+ # @example
60
+ # RubyLLM::Agents.configure do |config|
61
+ # config.default_model = "claude-3-sonnet"
62
+ # end
17
63
  def configure
18
64
  yield(configuration)
19
65
  end
20
66
 
67
+ # Resets configuration to defaults
68
+ #
69
+ # Primarily used for testing to ensure clean state.
70
+ #
71
+ # @return [Configuration] A new configuration instance
72
+ # @api private
21
73
  def reset_configuration!
22
74
  @configuration = Configuration.new
23
75
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ruby_llm-agents
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.4
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - adham90
@@ -79,6 +79,20 @@ dependencies:
79
79
  - - ">="
80
80
  - !ruby/object:Gem::Version
81
81
  version: '5.0'
82
+ - !ruby/object:Gem::Dependency
83
+ name: csv
84
+ requirement: !ruby/object:Gem::Requirement
85
+ requirements:
86
+ - - ">="
87
+ - !ruby/object:Gem::Version
88
+ version: '0'
89
+ type: :runtime
90
+ prerelease: false
91
+ version_requirements: !ruby/object:Gem::Requirement
92
+ requirements:
93
+ - - ">="
94
+ - !ruby/object:Gem::Version
95
+ version: '0'
82
96
  description: A Rails engine for creating, managing, and monitoring LLM-powered agents.
83
97
  Includes a DSL for agent configuration, execution tracking, cost analytics, and
84
98
  a mountable dashboard UI.
@@ -91,10 +105,12 @@ files:
91
105
  - LICENSE.txt
92
106
  - README.md
93
107
  - app/channels/ruby_llm/agents/executions_channel.rb
108
+ - app/controllers/concerns/ruby_llm/agents/filterable.rb
109
+ - app/controllers/concerns/ruby_llm/agents/paginatable.rb
94
110
  - app/controllers/ruby_llm/agents/agents_controller.rb
95
- - app/controllers/ruby_llm/agents/application_controller.rb
96
111
  - app/controllers/ruby_llm/agents/dashboard_controller.rb
97
112
  - app/controllers/ruby_llm/agents/executions_controller.rb
113
+ - app/controllers/ruby_llm/agents/settings_controller.rb
98
114
  - app/helpers/ruby_llm/agents/application_helper.rb
99
115
  - app/javascript/ruby_llm/agents/controllers/filter_controller.js
100
116
  - app/javascript/ruby_llm/agents/controllers/index.js
@@ -105,24 +121,41 @@ files:
105
121
  - app/models/ruby_llm/agents/execution/scopes.rb
106
122
  - app/services/ruby_llm/agents/agent_registry.rb
107
123
  - app/views/layouts/rubyllm/agents/application.html.erb
124
+ - app/views/rubyllm/agents/agents/_version_comparison.html.erb
108
125
  - app/views/rubyllm/agents/agents/index.html.erb
109
126
  - app/views/rubyllm/agents/agents/show.html.erb
127
+ - app/views/rubyllm/agents/dashboard/_action_center.html.erb
128
+ - app/views/rubyllm/agents/dashboard/_alerts_feed.html.erb
129
+ - app/views/rubyllm/agents/dashboard/_breaker_strip.html.erb
130
+ - app/views/rubyllm/agents/dashboard/_budgets_bar.html.erb
110
131
  - app/views/rubyllm/agents/dashboard/_execution_item.html.erb
132
+ - app/views/rubyllm/agents/dashboard/_now_strip.html.erb
133
+ - app/views/rubyllm/agents/dashboard/_now_strip_values.html.erb
111
134
  - app/views/rubyllm/agents/dashboard/index.html.erb
112
135
  - app/views/rubyllm/agents/executions/_execution.html.erb
113
136
  - app/views/rubyllm/agents/executions/_filters.html.erb
114
137
  - app/views/rubyllm/agents/executions/_list.html.erb
138
+ - app/views/rubyllm/agents/executions/dry_run.html.erb
115
139
  - app/views/rubyllm/agents/executions/index.html.erb
116
140
  - app/views/rubyllm/agents/executions/index.turbo_stream.erb
117
141
  - app/views/rubyllm/agents/executions/show.html.erb
142
+ - app/views/rubyllm/agents/settings/show.html.erb
118
143
  - app/views/rubyllm/agents/shared/_executions_table.html.erb
144
+ - app/views/rubyllm/agents/shared/_filter_dropdown.html.erb
145
+ - app/views/rubyllm/agents/shared/_select_dropdown.html.erb
119
146
  - app/views/rubyllm/agents/shared/_stat_card.html.erb
120
147
  - app/views/rubyllm/agents/shared/_status_badge.html.erb
121
148
  - app/views/rubyllm/agents/shared/_status_dot.html.erb
122
149
  - config/routes.rb
123
150
  - lib/generators/ruby_llm_agents/agent_generator.rb
124
151
  - lib/generators/ruby_llm_agents/install_generator.rb
152
+ - lib/generators/ruby_llm_agents/templates/add_attempts_migration.rb.tt
153
+ - lib/generators/ruby_llm_agents/templates/add_caching_migration.rb.tt
154
+ - lib/generators/ruby_llm_agents/templates/add_finish_reason_migration.rb.tt
125
155
  - lib/generators/ruby_llm_agents/templates/add_prompts_migration.rb.tt
156
+ - lib/generators/ruby_llm_agents/templates/add_routing_migration.rb.tt
157
+ - lib/generators/ruby_llm_agents/templates/add_streaming_migration.rb.tt
158
+ - lib/generators/ruby_llm_agents/templates/add_tracing_migration.rb.tt
126
159
  - lib/generators/ruby_llm_agents/templates/agent.rb.tt
127
160
  - lib/generators/ruby_llm_agents/templates/application_agent.rb.tt
128
161
  - lib/generators/ruby_llm_agents/templates/initializer.rb.tt
@@ -130,12 +163,18 @@ files:
130
163
  - lib/generators/ruby_llm_agents/upgrade_generator.rb
131
164
  - lib/ruby_llm-agents.rb
132
165
  - lib/ruby_llm/agents.rb
166
+ - lib/ruby_llm/agents/alert_manager.rb
167
+ - lib/ruby_llm/agents/attempt_tracker.rb
133
168
  - lib/ruby_llm/agents/base.rb
169
+ - lib/ruby_llm/agents/budget_tracker.rb
170
+ - lib/ruby_llm/agents/circuit_breaker.rb
134
171
  - lib/ruby_llm/agents/configuration.rb
135
172
  - lib/ruby_llm/agents/engine.rb
136
173
  - lib/ruby_llm/agents/execution_logger_job.rb
137
174
  - lib/ruby_llm/agents/inflections.rb
138
175
  - lib/ruby_llm/agents/instrumentation.rb
176
+ - lib/ruby_llm/agents/redactor.rb
177
+ - lib/ruby_llm/agents/reliability.rb
139
178
  - lib/ruby_llm/agents/version.rb
140
179
  homepage: https://github.com/adham90/ruby_llm-agents
141
180
  licenses:
@@ -1,37 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module RubyLLM
4
- module Agents
5
- class ApplicationController < ActionController::Base
6
- layout "rubyllm/agents/application"
7
-
8
- before_action :authenticate_dashboard!
9
-
10
- private
11
-
12
- def authenticate_dashboard!
13
- if basic_auth_configured?
14
- authenticate_with_http_basic_auth
15
- else
16
- auth_proc = RubyLLM::Agents.configuration.dashboard_auth
17
- return if auth_proc.call(self)
18
-
19
- render plain: "Unauthorized", status: :unauthorized
20
- end
21
- end
22
-
23
- def basic_auth_configured?
24
- config = RubyLLM::Agents.configuration
25
- config.basic_auth_username.present? && config.basic_auth_password.present?
26
- end
27
-
28
- def authenticate_with_http_basic_auth
29
- config = RubyLLM::Agents.configuration
30
- authenticate_or_request_with_http_basic("RubyLLM Agents") do |username, password|
31
- ActiveSupport::SecurityUtils.secure_compare(username, config.basic_auth_username) &&
32
- ActiveSupport::SecurityUtils.secure_compare(password, config.basic_auth_password)
33
- end
34
- end
35
- end
36
- end
37
- end