ruby_llm-agents 0.4.0 → 1.0.0.beta.1

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 (208) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +225 -34
  3. data/app/controllers/ruby_llm/agents/agents_controller.rb +136 -16
  4. data/app/controllers/ruby_llm/agents/api_configurations_controller.rb +214 -0
  5. data/app/controllers/ruby_llm/agents/dashboard_controller.rb +29 -9
  6. data/app/controllers/ruby_llm/agents/{settings_controller.rb → system_config_controller.rb} +3 -3
  7. data/app/controllers/ruby_llm/agents/tenants_controller.rb +109 -0
  8. data/app/controllers/ruby_llm/agents/workflows_controller.rb +355 -0
  9. data/app/helpers/ruby_llm/agents/application_helper.rb +25 -0
  10. data/app/models/ruby_llm/agents/api_configuration.rb +386 -0
  11. data/app/models/ruby_llm/agents/execution.rb +3 -0
  12. data/app/models/ruby_llm/agents/tenant_budget.rb +112 -14
  13. data/app/services/ruby_llm/agents/agent_registry.rb +51 -12
  14. data/app/views/layouts/ruby_llm/agents/application.html.erb +5 -30
  15. data/app/views/ruby_llm/agents/agents/_agent.html.erb +13 -1
  16. data/app/views/ruby_llm/agents/agents/_config_agent.html.erb +235 -0
  17. data/app/views/ruby_llm/agents/agents/_config_embedder.html.erb +70 -0
  18. data/app/views/ruby_llm/agents/agents/_config_image_generator.html.erb +152 -0
  19. data/app/views/ruby_llm/agents/agents/_config_moderator.html.erb +63 -0
  20. data/app/views/ruby_llm/agents/agents/_config_speaker.html.erb +108 -0
  21. data/app/views/ruby_llm/agents/agents/_config_transcriber.html.erb +91 -0
  22. data/app/views/ruby_llm/agents/agents/_workflow.html.erb +1 -1
  23. data/app/views/ruby_llm/agents/agents/index.html.erb +74 -9
  24. data/app/views/ruby_llm/agents/agents/show.html.erb +18 -378
  25. data/app/views/ruby_llm/agents/api_configurations/_api_key_field.html.erb +34 -0
  26. data/app/views/ruby_llm/agents/api_configurations/_form.html.erb +288 -0
  27. data/app/views/ruby_llm/agents/api_configurations/edit.html.erb +95 -0
  28. data/app/views/ruby_llm/agents/api_configurations/edit_tenant.html.erb +97 -0
  29. data/app/views/ruby_llm/agents/api_configurations/show.html.erb +211 -0
  30. data/app/views/ruby_llm/agents/api_configurations/tenant.html.erb +179 -0
  31. data/app/views/ruby_llm/agents/dashboard/_action_center.html.erb +1 -1
  32. data/app/views/ruby_llm/agents/dashboard/_agent_comparison.html.erb +269 -15
  33. data/app/views/ruby_llm/agents/executions/show.html.erb +98 -0
  34. data/app/views/ruby_llm/agents/shared/_agent_type_badge.html.erb +93 -0
  35. data/app/views/ruby_llm/agents/{settings → system_config}/show.html.erb +1 -1
  36. data/app/views/ruby_llm/agents/tenants/_form.html.erb +150 -0
  37. data/app/views/ruby_llm/agents/tenants/edit.html.erb +13 -0
  38. data/app/views/ruby_llm/agents/tenants/index.html.erb +129 -0
  39. data/app/views/ruby_llm/agents/tenants/show.html.erb +374 -0
  40. data/app/views/ruby_llm/agents/workflows/_step_performance.html.erb +236 -0
  41. data/app/views/ruby_llm/agents/workflows/_structure_parallel.html.erb +76 -0
  42. data/app/views/ruby_llm/agents/workflows/_structure_pipeline.html.erb +74 -0
  43. data/app/views/ruby_llm/agents/workflows/_structure_router.html.erb +108 -0
  44. data/app/views/ruby_llm/agents/workflows/show.html.erb +442 -0
  45. data/config/routes.rb +13 -1
  46. data/lib/generators/ruby_llm_agents/agent_generator.rb +56 -7
  47. data/lib/generators/ruby_llm_agents/api_configuration_generator.rb +100 -0
  48. data/lib/generators/ruby_llm_agents/background_remover_generator.rb +110 -0
  49. data/lib/generators/ruby_llm_agents/embedder_generator.rb +107 -0
  50. data/lib/generators/ruby_llm_agents/image_analyzer_generator.rb +115 -0
  51. data/lib/generators/ruby_llm_agents/image_editor_generator.rb +108 -0
  52. data/lib/generators/ruby_llm_agents/image_generator_generator.rb +116 -0
  53. data/lib/generators/ruby_llm_agents/image_pipeline_generator.rb +178 -0
  54. data/lib/generators/ruby_llm_agents/image_transformer_generator.rb +109 -0
  55. data/lib/generators/ruby_llm_agents/image_upscaler_generator.rb +103 -0
  56. data/lib/generators/ruby_llm_agents/image_variator_generator.rb +102 -0
  57. data/lib/generators/ruby_llm_agents/install_generator.rb +76 -4
  58. data/lib/generators/ruby_llm_agents/restructure_generator.rb +292 -0
  59. data/lib/generators/ruby_llm_agents/speaker_generator.rb +121 -0
  60. data/lib/generators/ruby_llm_agents/templates/add_execution_type_migration.rb.tt +8 -0
  61. data/lib/generators/ruby_llm_agents/templates/agent.rb.tt +99 -84
  62. data/lib/generators/ruby_llm_agents/templates/application_agent.rb.tt +42 -40
  63. data/lib/generators/ruby_llm_agents/templates/application_background_remover.rb.tt +26 -0
  64. data/lib/generators/ruby_llm_agents/templates/application_embedder.rb.tt +50 -0
  65. data/lib/generators/ruby_llm_agents/templates/application_image_analyzer.rb.tt +26 -0
  66. data/lib/generators/ruby_llm_agents/templates/application_image_editor.rb.tt +20 -0
  67. data/lib/generators/ruby_llm_agents/templates/application_image_generator.rb.tt +38 -0
  68. data/lib/generators/ruby_llm_agents/templates/application_image_pipeline.rb.tt +139 -0
  69. data/lib/generators/ruby_llm_agents/templates/application_image_transformer.rb.tt +21 -0
  70. data/lib/generators/ruby_llm_agents/templates/application_image_upscaler.rb.tt +20 -0
  71. data/lib/generators/ruby_llm_agents/templates/application_image_variator.rb.tt +20 -0
  72. data/lib/generators/ruby_llm_agents/templates/application_speaker.rb.tt +49 -0
  73. data/lib/generators/ruby_llm_agents/templates/application_transcriber.rb.tt +53 -0
  74. data/lib/generators/ruby_llm_agents/templates/background_remover.rb.tt +44 -0
  75. data/lib/generators/ruby_llm_agents/templates/create_api_configurations_migration.rb.tt +90 -0
  76. data/lib/generators/ruby_llm_agents/templates/embedder.rb.tt +41 -0
  77. data/lib/generators/ruby_llm_agents/templates/image_analyzer.rb.tt +45 -0
  78. data/lib/generators/ruby_llm_agents/templates/image_editor.rb.tt +35 -0
  79. data/lib/generators/ruby_llm_agents/templates/image_generator.rb.tt +47 -0
  80. data/lib/generators/ruby_llm_agents/templates/image_pipeline.rb.tt +50 -0
  81. data/lib/generators/ruby_llm_agents/templates/image_transformer.rb.tt +44 -0
  82. data/lib/generators/ruby_llm_agents/templates/image_upscaler.rb.tt +38 -0
  83. data/lib/generators/ruby_llm_agents/templates/image_variator.rb.tt +33 -0
  84. data/lib/generators/ruby_llm_agents/templates/skills/AGENTS.md.tt +228 -0
  85. data/lib/generators/ruby_llm_agents/templates/skills/BACKGROUND_REMOVERS.md.tt +131 -0
  86. data/lib/generators/ruby_llm_agents/templates/skills/EMBEDDERS.md.tt +255 -0
  87. data/lib/generators/ruby_llm_agents/templates/skills/IMAGE_ANALYZERS.md.tt +120 -0
  88. data/lib/generators/ruby_llm_agents/templates/skills/IMAGE_EDITORS.md.tt +102 -0
  89. data/lib/generators/ruby_llm_agents/templates/skills/IMAGE_GENERATORS.md.tt +282 -0
  90. data/lib/generators/ruby_llm_agents/templates/skills/IMAGE_PIPELINES.md.tt +228 -0
  91. data/lib/generators/ruby_llm_agents/templates/skills/IMAGE_TRANSFORMERS.md.tt +120 -0
  92. data/lib/generators/ruby_llm_agents/templates/skills/IMAGE_UPSCALERS.md.tt +110 -0
  93. data/lib/generators/ruby_llm_agents/templates/skills/IMAGE_VARIATORS.md.tt +120 -0
  94. data/lib/generators/ruby_llm_agents/templates/skills/SPEAKERS.md.tt +212 -0
  95. data/lib/generators/ruby_llm_agents/templates/skills/TOOLS.md.tt +227 -0
  96. data/lib/generators/ruby_llm_agents/templates/skills/TRANSCRIBERS.md.tt +251 -0
  97. data/lib/generators/ruby_llm_agents/templates/skills/WORKFLOWS.md.tt +300 -0
  98. data/lib/generators/ruby_llm_agents/templates/speaker.rb.tt +56 -0
  99. data/lib/generators/ruby_llm_agents/templates/transcriber.rb.tt +51 -0
  100. data/lib/generators/ruby_llm_agents/transcriber_generator.rb +107 -0
  101. data/lib/generators/ruby_llm_agents/upgrade_generator.rb +152 -1
  102. data/lib/ruby_llm/agents/audio/speaker.rb +553 -0
  103. data/lib/ruby_llm/agents/audio/transcriber.rb +669 -0
  104. data/lib/ruby_llm/agents/base_agent.rb +675 -0
  105. data/lib/ruby_llm/agents/core/base/moderation_dsl.rb +181 -0
  106. data/lib/ruby_llm/agents/core/base/moderation_execution.rb +274 -0
  107. data/lib/ruby_llm/agents/core/base.rb +135 -0
  108. data/lib/ruby_llm/agents/core/configuration.rb +981 -0
  109. data/lib/ruby_llm/agents/core/errors.rb +150 -0
  110. data/lib/ruby_llm/agents/{instrumentation.rb → core/instrumentation.rb} +93 -4
  111. data/lib/ruby_llm/agents/core/llm_tenant.rb +358 -0
  112. data/lib/ruby_llm/agents/core/resolved_config.rb +348 -0
  113. data/lib/ruby_llm/agents/{version.rb → core/version.rb} +1 -1
  114. data/lib/ruby_llm/agents/dsl/base.rb +110 -0
  115. data/lib/ruby_llm/agents/dsl/caching.rb +142 -0
  116. data/lib/ruby_llm/agents/dsl/reliability.rb +307 -0
  117. data/lib/ruby_llm/agents/dsl.rb +41 -0
  118. data/lib/ruby_llm/agents/image/analyzer/dsl.rb +130 -0
  119. data/lib/ruby_llm/agents/image/analyzer/execution.rb +402 -0
  120. data/lib/ruby_llm/agents/image/analyzer.rb +90 -0
  121. data/lib/ruby_llm/agents/image/background_remover/dsl.rb +154 -0
  122. data/lib/ruby_llm/agents/image/background_remover/execution.rb +240 -0
  123. data/lib/ruby_llm/agents/image/background_remover.rb +89 -0
  124. data/lib/ruby_llm/agents/image/concerns/image_operation_dsl.rb +91 -0
  125. data/lib/ruby_llm/agents/image/concerns/image_operation_execution.rb +165 -0
  126. data/lib/ruby_llm/agents/image/editor/dsl.rb +56 -0
  127. data/lib/ruby_llm/agents/image/editor/execution.rb +207 -0
  128. data/lib/ruby_llm/agents/image/editor.rb +92 -0
  129. data/lib/ruby_llm/agents/image/generator/active_storage_support.rb +127 -0
  130. data/lib/ruby_llm/agents/image/generator/content_policy.rb +95 -0
  131. data/lib/ruby_llm/agents/image/generator/pricing.rb +353 -0
  132. data/lib/ruby_llm/agents/image/generator/templates.rb +124 -0
  133. data/lib/ruby_llm/agents/image/generator.rb +455 -0
  134. data/lib/ruby_llm/agents/image/pipeline/dsl.rb +213 -0
  135. data/lib/ruby_llm/agents/image/pipeline/execution.rb +382 -0
  136. data/lib/ruby_llm/agents/image/pipeline.rb +97 -0
  137. data/lib/ruby_llm/agents/image/transformer/dsl.rb +148 -0
  138. data/lib/ruby_llm/agents/image/transformer/execution.rb +223 -0
  139. data/lib/ruby_llm/agents/image/transformer.rb +95 -0
  140. data/lib/ruby_llm/agents/image/upscaler/dsl.rb +83 -0
  141. data/lib/ruby_llm/agents/image/upscaler/execution.rb +219 -0
  142. data/lib/ruby_llm/agents/image/upscaler.rb +81 -0
  143. data/lib/ruby_llm/agents/image/variator/dsl.rb +62 -0
  144. data/lib/ruby_llm/agents/image/variator/execution.rb +189 -0
  145. data/lib/ruby_llm/agents/image/variator.rb +80 -0
  146. data/lib/ruby_llm/agents/{alert_manager.rb → infrastructure/alert_manager.rb} +17 -22
  147. data/lib/ruby_llm/agents/infrastructure/budget/budget_query.rb +145 -0
  148. data/lib/ruby_llm/agents/infrastructure/budget/config_resolver.rb +149 -0
  149. data/lib/ruby_llm/agents/infrastructure/budget/forecaster.rb +68 -0
  150. data/lib/ruby_llm/agents/infrastructure/budget/spend_recorder.rb +279 -0
  151. data/lib/ruby_llm/agents/infrastructure/budget_tracker.rb +275 -0
  152. data/lib/ruby_llm/agents/{execution_logger_job.rb → infrastructure/execution_logger_job.rb} +17 -1
  153. data/lib/ruby_llm/agents/{reliability → infrastructure/reliability}/executor.rb +2 -1
  154. data/lib/ruby_llm/agents/{reliability → infrastructure/reliability}/retry_strategy.rb +9 -3
  155. data/lib/ruby_llm/agents/{reliability.rb → infrastructure/reliability.rb} +11 -21
  156. data/lib/ruby_llm/agents/pipeline/builder.rb +215 -0
  157. data/lib/ruby_llm/agents/pipeline/context.rb +255 -0
  158. data/lib/ruby_llm/agents/pipeline/executor.rb +86 -0
  159. data/lib/ruby_llm/agents/pipeline/middleware/base.rb +124 -0
  160. data/lib/ruby_llm/agents/pipeline/middleware/budget.rb +95 -0
  161. data/lib/ruby_llm/agents/pipeline/middleware/cache.rb +171 -0
  162. data/lib/ruby_llm/agents/pipeline/middleware/instrumentation.rb +415 -0
  163. data/lib/ruby_llm/agents/pipeline/middleware/reliability.rb +276 -0
  164. data/lib/ruby_llm/agents/pipeline/middleware/tenant.rb +196 -0
  165. data/lib/ruby_llm/agents/pipeline.rb +68 -0
  166. data/lib/ruby_llm/agents/{engine.rb → rails/engine.rb} +79 -10
  167. data/lib/ruby_llm/agents/results/background_removal_result.rb +286 -0
  168. data/lib/ruby_llm/agents/{result.rb → results/base.rb} +73 -1
  169. data/lib/ruby_llm/agents/results/embedding_result.rb +243 -0
  170. data/lib/ruby_llm/agents/results/image_analysis_result.rb +314 -0
  171. data/lib/ruby_llm/agents/results/image_edit_result.rb +250 -0
  172. data/lib/ruby_llm/agents/results/image_generation_result.rb +346 -0
  173. data/lib/ruby_llm/agents/results/image_pipeline_result.rb +399 -0
  174. data/lib/ruby_llm/agents/results/image_transform_result.rb +251 -0
  175. data/lib/ruby_llm/agents/results/image_upscale_result.rb +255 -0
  176. data/lib/ruby_llm/agents/results/image_variation_result.rb +237 -0
  177. data/lib/ruby_llm/agents/results/moderation_result.rb +158 -0
  178. data/lib/ruby_llm/agents/results/speech_result.rb +338 -0
  179. data/lib/ruby_llm/agents/results/transcription_result.rb +408 -0
  180. data/lib/ruby_llm/agents/text/embedder.rb +444 -0
  181. data/lib/ruby_llm/agents/text/moderator.rb +237 -0
  182. data/lib/ruby_llm/agents/workflow/async.rb +220 -0
  183. data/lib/ruby_llm/agents/workflow/async_executor.rb +156 -0
  184. data/lib/ruby_llm/agents/{workflow.rb → workflow/orchestrator.rb} +6 -5
  185. data/lib/ruby_llm/agents/workflow/parallel.rb +34 -17
  186. data/lib/ruby_llm/agents/workflow/thread_pool.rb +185 -0
  187. data/lib/ruby_llm/agents.rb +86 -20
  188. metadata +189 -35
  189. data/lib/ruby_llm/agents/base/caching.rb +0 -40
  190. data/lib/ruby_llm/agents/base/cost_calculation.rb +0 -105
  191. data/lib/ruby_llm/agents/base/dsl.rb +0 -324
  192. data/lib/ruby_llm/agents/base/execution.rb +0 -283
  193. data/lib/ruby_llm/agents/base/reliability_dsl.rb +0 -82
  194. data/lib/ruby_llm/agents/base/reliability_execution.rb +0 -136
  195. data/lib/ruby_llm/agents/base/response_building.rb +0 -86
  196. data/lib/ruby_llm/agents/base/tool_tracking.rb +0 -57
  197. data/lib/ruby_llm/agents/base.rb +0 -209
  198. data/lib/ruby_llm/agents/budget_tracker.rb +0 -471
  199. data/lib/ruby_llm/agents/configuration.rb +0 -357
  200. /data/lib/ruby_llm/agents/{deprecations.rb → core/deprecations.rb} +0 -0
  201. /data/lib/ruby_llm/agents/{inflections.rb → core/inflections.rb} +0 -0
  202. /data/lib/ruby_llm/agents/{attempt_tracker.rb → infrastructure/attempt_tracker.rb} +0 -0
  203. /data/lib/ruby_llm/agents/{cache_helper.rb → infrastructure/cache_helper.rb} +0 -0
  204. /data/lib/ruby_llm/agents/{circuit_breaker.rb → infrastructure/circuit_breaker.rb} +0 -0
  205. /data/lib/ruby_llm/agents/{redactor.rb → infrastructure/redactor.rb} +0 -0
  206. /data/lib/ruby_llm/agents/{reliability → infrastructure/reliability}/breaker_manager.rb +0 -0
  207. /data/lib/ruby_llm/agents/{reliability → infrastructure/reliability}/execution_constraints.rb +0 -0
  208. /data/lib/ruby_llm/agents/{reliability → infrastructure/reliability}/fallback_routing.rb +0 -0
@@ -1,357 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module RubyLLM
4
- module Agents
5
- # Global configuration for RubyLLM::Agents
6
- #
7
- # Provides centralized settings for agent behavior, dashboard authentication,
8
- # caching, and observability thresholds.
9
- #
10
- # @example Basic configuration
11
- # RubyLLM::Agents.configure do |config|
12
- # config.default_model = "gpt-4o"
13
- # config.default_temperature = 0.7
14
- # config.async_logging = true
15
- # end
16
- #
17
- # @example Dashboard with HTTP Basic Auth
18
- # RubyLLM::Agents.configure do |config|
19
- # config.basic_auth_username = ENV["AGENTS_USER"]
20
- # config.basic_auth_password = ENV["AGENTS_PASS"]
21
- # end
22
- #
23
- # @example Dashboard with custom authentication
24
- # RubyLLM::Agents.configure do |config|
25
- # config.dashboard_parent_controller = "AdminController"
26
- # config.dashboard_auth = ->(controller) { controller.current_user&.admin? }
27
- # end
28
- #
29
- # @see RubyLLM::Agents.configure
30
- # @api public
31
- class Configuration
32
- # @!attribute [rw] default_model
33
- # The default LLM model identifier for all agents.
34
- # Can be overridden per-agent using the `model` DSL method.
35
- # @return [String] Model identifier (default: "gemini-2.0-flash")
36
- # @example
37
- # config.default_model = "gpt-4o"
38
-
39
- # @!attribute [rw] default_temperature
40
- # The default temperature for LLM responses (0.0 to 2.0).
41
- # Lower values produce more deterministic outputs.
42
- # @return [Float] Temperature value (default: 0.0)
43
-
44
- # @!attribute [rw] default_timeout
45
- # Maximum seconds to wait for an LLM response before timing out.
46
- # @return [Integer] Timeout in seconds (default: 60)
47
-
48
- # @!attribute [rw] async_logging
49
- # Whether to log executions via background job (recommended for production).
50
- # When false, executions are logged synchronously.
51
- # @return [Boolean] Enable async logging (default: true)
52
-
53
- # @!attribute [rw] retention_period
54
- # How long to retain execution records before cleanup.
55
- # @return [ActiveSupport::Duration] Retention period (default: 30.days)
56
-
57
- # @!attribute [rw] anomaly_cost_threshold
58
- # Cost threshold in dollars that triggers anomaly logging.
59
- # Executions exceeding this cost are logged as warnings.
60
- # @return [Float] Cost threshold in USD (default: 5.00)
61
-
62
- # @!attribute [rw] anomaly_duration_threshold
63
- # Duration threshold in milliseconds that triggers anomaly logging.
64
- # @return [Integer] Duration threshold in ms (default: 10_000)
65
-
66
- # @!attribute [rw] dashboard_auth
67
- # Lambda for custom dashboard authentication.
68
- # Receives the controller instance, should return truthy to allow access.
69
- # @return [Proc] Authentication lambda (default: allows all)
70
- # @example
71
- # config.dashboard_auth = ->(c) { c.current_user&.admin? }
72
-
73
- # @!attribute [rw] dashboard_parent_controller
74
- # Parent controller class name for the dashboard.
75
- # Use this to inherit authentication from your app's admin controller.
76
- # @return [String] Controller class name (default: "ActionController::Base")
77
-
78
- # @!attribute [rw] basic_auth_username
79
- # Username for HTTP Basic Auth on the dashboard.
80
- # Both username and password must be set to enable Basic Auth.
81
- # @return [String, nil] Username or nil to disable (default: nil)
82
-
83
- # @!attribute [rw] basic_auth_password
84
- # Password for HTTP Basic Auth on the dashboard.
85
- # @return [String, nil] Password or nil to disable (default: nil)
86
-
87
- # @!attribute [rw] per_page
88
- # Number of records per page in dashboard listings.
89
- # @return [Integer] Records per page (default: 25)
90
-
91
- # @!attribute [rw] recent_executions_limit
92
- # Number of recent executions shown on the dashboard home.
93
- # @return [Integer] Limit for recent executions (default: 10)
94
-
95
- # @!attribute [rw] job_retry_attempts
96
- # Number of retry attempts for the async logging job on failure.
97
- # @return [Integer] Retry attempts (default: 3)
98
-
99
- # @!attribute [w] cache_store
100
- # Custom cache store for agent response caching.
101
- # Falls back to Rails.cache if not set.
102
- # @return [ActiveSupport::Cache::Store, nil]
103
-
104
- # @!attribute [rw] default_retries
105
- # Default retry configuration for all agents.
106
- # Can be overridden per-agent using the `retries` DSL method.
107
- # @return [Hash] Retry config with :max, :backoff, :base, :max_delay, :on keys
108
- # @example
109
- # config.default_retries = { max: 2, backoff: :exponential, base: 0.4, max_delay: 3.0, on: [] }
110
-
111
- # @!attribute [rw] default_fallback_models
112
- # Default fallback models for all agents.
113
- # Can be overridden per-agent using the `fallback_models` DSL method.
114
- # @return [Array<String>] List of model identifiers to try on failure
115
-
116
- # @!attribute [rw] default_total_timeout
117
- # Default total timeout across all retry attempts.
118
- # Can be overridden per-agent using the `total_timeout` DSL method.
119
- # @return [Integer, nil] Total timeout in seconds, or nil for no limit
120
-
121
- # @!attribute [rw] default_streaming
122
- # Whether streaming mode is enabled by default for all agents.
123
- # When enabled and a block is passed to call, chunks are yielded as they arrive.
124
- # Can be overridden per-agent using the `streaming` DSL method.
125
- # @return [Boolean] Enable streaming (default: false)
126
- # @example
127
- # config.default_streaming = true
128
-
129
- # @!attribute [rw] default_tools
130
- # Default tools available to all agents.
131
- # Should be an array of RubyLLM::Tool classes.
132
- # Can be overridden or extended per-agent using the `tools` DSL method.
133
- # @return [Array<Class>] Tool classes (default: [])
134
- # @example
135
- # config.default_tools = [WeatherTool, SearchTool]
136
-
137
- # @!attribute [rw] budgets
138
- # Budget configuration for cost governance.
139
- # @return [Hash, nil] Budget config with :global_daily, :global_monthly, :per_agent_daily, :per_agent_monthly, :enforcement keys
140
- # @example
141
- # config.budgets = {
142
- # global_daily: 25.0,
143
- # global_monthly: 300.0,
144
- # per_agent_daily: { "ContentAgent" => 5.0 },
145
- # per_agent_monthly: { "ContentAgent" => 120.0 },
146
- # enforcement: :soft
147
- # }
148
-
149
- # @!attribute [rw] alerts
150
- # Alert configuration for notifications.
151
- # @return [Hash, nil] Alert config with :slack_webhook_url, :webhook_url, :on_events, :custom keys
152
- # @example
153
- # config.alerts = {
154
- # slack_webhook_url: ENV["SLACK_WEBHOOK"],
155
- # webhook_url: ENV["AGENTS_WEBHOOK"],
156
- # on_events: [:budget_soft_cap, :budget_hard_cap, :breaker_open],
157
- # custom: ->(event, payload) { Rails.logger.info("Alert: #{event}") }
158
- # }
159
-
160
- # @!attribute [rw] persist_prompts
161
- # Whether to persist system and user prompts in execution records.
162
- # Set to false to reduce storage or for privacy compliance.
163
- # @return [Boolean] Enable prompt persistence (default: true)
164
-
165
- # @!attribute [rw] persist_responses
166
- # Whether to persist LLM responses in execution records.
167
- # Set to false to reduce storage or for privacy compliance.
168
- # @return [Boolean] Enable response persistence (default: true)
169
-
170
- # @!attribute [rw] redaction
171
- # Redaction configuration for PII and sensitive data.
172
- # @return [Hash, nil] Redaction config with :fields, :patterns, :placeholder, :max_value_length keys
173
- # @example
174
- # config.redaction = {
175
- # fields: %w[password api_key email ssn],
176
- # patterns: [/\b\d{3}-\d{2}-\d{4}\b/],
177
- # placeholder: "[REDACTED]",
178
- # max_value_length: 5000
179
- # }
180
-
181
- # @!attribute [rw] multi_tenancy_enabled
182
- # Whether multi-tenancy features are enabled.
183
- # When false, the gem behaves exactly as before (backward compatible).
184
- # @return [Boolean] Enable multi-tenancy (default: false)
185
- # @example
186
- # config.multi_tenancy_enabled = true
187
-
188
- # @!attribute [rw] tenant_resolver
189
- # Lambda that returns the current tenant identifier.
190
- # Called whenever tenant context is needed for budget tracking,
191
- # circuit breakers, and execution recording.
192
- # @return [Proc] Tenant resolution lambda (default: -> { nil })
193
- # @example Using Rails CurrentAttributes
194
- # config.tenant_resolver = -> { Current.tenant&.id }
195
- # @example Using request store
196
- # config.tenant_resolver = -> { RequestStore[:tenant_id] }
197
-
198
- attr_accessor :default_model,
199
- :default_temperature,
200
- :default_timeout,
201
- :async_logging,
202
- :retention_period,
203
- :anomaly_cost_threshold,
204
- :anomaly_duration_threshold,
205
- :dashboard_auth,
206
- :dashboard_parent_controller,
207
- :basic_auth_username,
208
- :basic_auth_password,
209
- :per_page,
210
- :recent_executions_limit,
211
- :job_retry_attempts,
212
- :default_retries,
213
- :default_fallback_models,
214
- :default_total_timeout,
215
- :default_streaming,
216
- :default_tools,
217
- :budgets,
218
- :alerts,
219
- :persist_prompts,
220
- :persist_responses,
221
- :redaction,
222
- :multi_tenancy_enabled,
223
- :tenant_resolver
224
-
225
- attr_writer :cache_store
226
-
227
- # Initializes configuration with default values
228
- #
229
- # @return [Configuration] A new configuration instance with defaults
230
- # @api private
231
- def initialize
232
- @default_model = "gemini-2.0-flash"
233
- @default_temperature = 0.0
234
- @default_timeout = 60
235
- @cache_store = nil
236
- @async_logging = true
237
- @retention_period = 30.days
238
- @anomaly_cost_threshold = 5.00
239
- @anomaly_duration_threshold = 10_000
240
- @dashboard_auth = ->(_controller) { true }
241
- @dashboard_parent_controller = "ActionController::Base"
242
- @basic_auth_username = nil
243
- @basic_auth_password = nil
244
- @per_page = 25
245
- @recent_executions_limit = 10
246
- @job_retry_attempts = 3
247
-
248
- # Reliability defaults (all disabled by default for backward compatibility)
249
- @default_retries = { max: 0, backoff: :exponential, base: 0.4, max_delay: 3.0, on: [] }
250
- @default_fallback_models = []
251
- @default_total_timeout = nil
252
-
253
- # Streaming and tools defaults
254
- @default_streaming = false
255
- @default_tools = []
256
-
257
- # Governance defaults
258
- @budgets = nil
259
- @alerts = nil
260
- @persist_prompts = true
261
- @persist_responses = true
262
- @redaction = nil
263
-
264
- # Multi-tenancy defaults (disabled for backward compatibility)
265
- @multi_tenancy_enabled = false
266
- @tenant_resolver = -> { nil }
267
- end
268
-
269
- # Returns the configured cache store, falling back to Rails.cache
270
- #
271
- # @return [ActiveSupport::Cache::Store] The cache store instance
272
- # @example Using a custom cache store
273
- # config.cache_store = ActiveSupport::Cache::MemoryStore.new
274
- def cache_store
275
- @cache_store || Rails.cache
276
- end
277
-
278
- # Returns whether budgets are configured and enforcement is enabled
279
- #
280
- # @return [Boolean] true if budgets are configured with enforcement
281
- def budgets_enabled?
282
- budgets.is_a?(Hash) && budgets[:enforcement] && budgets[:enforcement] != :none
283
- end
284
-
285
- # Returns the budget enforcement mode
286
- #
287
- # @return [Symbol] :none, :soft, or :hard
288
- def budget_enforcement
289
- budgets&.dig(:enforcement) || :none
290
- end
291
-
292
- # Returns whether alerts are configured
293
- #
294
- # @return [Boolean] true if any alert destination is configured
295
- def alerts_enabled?
296
- return false unless alerts.is_a?(Hash)
297
-
298
- alerts[:slack_webhook_url].present? ||
299
- alerts[:webhook_url].present? ||
300
- alerts[:custom].present?
301
- end
302
-
303
- # Returns the list of events to alert on
304
- #
305
- # @return [Array<Symbol>] Event names to trigger alerts
306
- def alert_events
307
- alerts&.dig(:on_events) || []
308
- end
309
-
310
- # Returns merged redaction fields (default sensitive keys + configured)
311
- #
312
- # @return [Array<String>] Field names to redact
313
- def redaction_fields
314
- default_fields = %w[password token api_key secret credential auth key access_token]
315
- configured_fields = redaction&.dig(:fields) || []
316
- (default_fields + configured_fields).map(&:downcase).uniq
317
- end
318
-
319
- # Returns redaction patterns
320
- #
321
- # @return [Array<Regexp>] Patterns to match and redact
322
- def redaction_patterns
323
- redaction&.dig(:patterns) || []
324
- end
325
-
326
- # Returns the redaction placeholder string
327
- #
328
- # @return [String] Placeholder to replace redacted values
329
- def redaction_placeholder
330
- redaction&.dig(:placeholder) || "[REDACTED]"
331
- end
332
-
333
- # Returns the maximum value length before truncation
334
- #
335
- # @return [Integer, nil] Max length, or nil for no limit
336
- def redaction_max_value_length
337
- redaction&.dig(:max_value_length)
338
- end
339
-
340
- # Returns whether multi-tenancy is enabled
341
- #
342
- # @return [Boolean] true if multi-tenancy is enabled
343
- def multi_tenancy_enabled?
344
- @multi_tenancy_enabled == true
345
- end
346
-
347
- # Returns the current tenant ID from the resolver
348
- #
349
- # @return [String, nil] Current tenant identifier or nil
350
- def current_tenant_id
351
- return nil unless multi_tenancy_enabled?
352
-
353
- tenant_resolver&.call
354
- end
355
- end
356
- end
357
- end