ruby_llm-agents 1.3.4 → 2.1.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 (191) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +112 -336
  3. data/app/controllers/concerns/ruby_llm/agents/sortable.rb +0 -1
  4. data/app/controllers/ruby_llm/agents/agents_controller.rb +5 -56
  5. data/app/controllers/ruby_llm/agents/dashboard_controller.rb +22 -106
  6. data/app/controllers/ruby_llm/agents/executions_controller.rb +4 -114
  7. data/app/controllers/ruby_llm/agents/tenants_controller.rb +30 -2
  8. data/app/helpers/ruby_llm/agents/application_helper.rb +19 -53
  9. data/app/models/ruby_llm/agents/execution/analytics.rb +13 -54
  10. data/app/models/ruby_llm/agents/execution/scopes.rb +61 -14
  11. data/app/models/ruby_llm/agents/execution.rb +52 -12
  12. data/app/models/ruby_llm/agents/execution_detail.rb +18 -0
  13. data/app/models/ruby_llm/agents/tenant/budgetable.rb +132 -24
  14. data/app/models/ruby_llm/agents/tenant/incrementable.rb +117 -0
  15. data/app/models/ruby_llm/agents/tenant/resettable.rb +128 -0
  16. data/app/models/ruby_llm/agents/tenant/trackable.rb +46 -12
  17. data/app/models/ruby_llm/agents/tenant.rb +2 -3
  18. data/app/models/ruby_llm/agents/tenant_budget.rb +6 -3
  19. data/app/services/ruby_llm/agents/agent_registry.rb +6 -112
  20. data/app/views/layouts/ruby_llm/agents/application.html.erb +89 -252
  21. data/app/views/ruby_llm/agents/agents/_config_agent.html.erb +71 -218
  22. data/app/views/ruby_llm/agents/agents/_config_embedder.html.erb +20 -63
  23. data/app/views/ruby_llm/agents/agents/_config_image_generator.html.erb +44 -131
  24. data/app/views/ruby_llm/agents/agents/_config_moderator.html.erb +16 -57
  25. data/app/views/ruby_llm/agents/agents/_config_speaker.html.erb +39 -104
  26. data/app/views/ruby_llm/agents/agents/_config_transcriber.html.erb +29 -82
  27. data/app/views/ruby_llm/agents/agents/_empty_state.html.erb +4 -14
  28. data/app/views/ruby_llm/agents/agents/index.html.erb +105 -274
  29. data/app/views/ruby_llm/agents/agents/show.html.erb +248 -378
  30. data/app/views/ruby_llm/agents/dashboard/_action_center.html.erb +29 -52
  31. data/app/views/ruby_llm/agents/dashboard/_tenant_budget.html.erb +73 -99
  32. data/app/views/ruby_llm/agents/dashboard/index.html.erb +228 -433
  33. data/app/views/ruby_llm/agents/executions/_execution.html.erb +1 -1
  34. data/app/views/ruby_llm/agents/executions/_filters.html.erb +4 -25
  35. data/app/views/ruby_llm/agents/executions/_list.html.erb +111 -152
  36. data/app/views/ruby_llm/agents/executions/index.html.erb +5 -7
  37. data/app/views/ruby_llm/agents/executions/show.html.erb +526 -1037
  38. data/app/views/ruby_llm/agents/shared/_agent_type_badge.html.erb +5 -21
  39. data/app/views/ruby_llm/agents/shared/_executions_table.html.erb +70 -191
  40. data/app/views/ruby_llm/agents/shared/_filter_dropdown.html.erb +16 -44
  41. data/app/views/ruby_llm/agents/shared/_select_dropdown.html.erb +12 -41
  42. data/app/views/ruby_llm/agents/shared/_status_badge.html.erb +11 -65
  43. data/app/views/ruby_llm/agents/shared/_tenant_filter.html.erb +6 -5
  44. data/app/views/ruby_llm/agents/system_config/show.html.erb +240 -351
  45. data/app/views/ruby_llm/agents/tenants/_form.html.erb +67 -77
  46. data/app/views/ruby_llm/agents/tenants/edit.html.erb +7 -9
  47. data/app/views/ruby_llm/agents/tenants/index.html.erb +100 -122
  48. data/app/views/ruby_llm/agents/tenants/show.html.erb +146 -336
  49. data/config/routes.rb +0 -13
  50. data/lib/generators/ruby_llm_agents/install_generator.rb +13 -17
  51. data/lib/generators/ruby_llm_agents/migrate_structure_generator.rb +2 -12
  52. data/lib/generators/ruby_llm_agents/restructure_generator.rb +0 -2
  53. data/lib/generators/ruby_llm_agents/templates/add_usage_counters_to_tenants_migration.rb.tt +37 -0
  54. data/lib/generators/ruby_llm_agents/templates/agent.rb.tt +1 -2
  55. data/lib/generators/ruby_llm_agents/templates/application_agent.rb.tt +1 -1
  56. data/lib/generators/ruby_llm_agents/templates/application_image_pipeline.rb.tt +0 -1
  57. data/lib/generators/ruby_llm_agents/templates/create_execution_details_migration.rb.tt +27 -0
  58. data/lib/generators/ruby_llm_agents/templates/create_tenants_migration.rb.tt +25 -0
  59. data/lib/generators/ruby_llm_agents/templates/image_pipeline.rb.tt +0 -1
  60. data/lib/generators/ruby_llm_agents/templates/initializer.rb.tt +33 -12
  61. data/lib/generators/ruby_llm_agents/templates/migration.rb.tt +40 -71
  62. data/lib/generators/ruby_llm_agents/templates/remove_agent_version_migration.rb.tt +13 -0
  63. data/lib/generators/ruby_llm_agents/templates/remove_workflow_columns_migration.rb.tt +19 -0
  64. data/lib/generators/ruby_llm_agents/templates/skills/AGENTS.md.tt +2 -4
  65. data/lib/generators/ruby_llm_agents/templates/skills/IMAGE_PIPELINES.md.tt +0 -1
  66. data/lib/generators/ruby_llm_agents/templates/split_execution_details_migration.rb.tt +232 -0
  67. data/lib/generators/ruby_llm_agents/upgrade_generator.rb +77 -259
  68. data/lib/ruby_llm/agents/audio/speaker.rb +0 -1
  69. data/lib/ruby_llm/agents/audio/transcriber.rb +0 -1
  70. data/lib/ruby_llm/agents/base_agent.rb +54 -23
  71. data/lib/ruby_llm/agents/core/base/callbacks.rb +142 -0
  72. data/lib/ruby_llm/agents/core/base.rb +23 -55
  73. data/lib/ruby_llm/agents/core/configuration.rb +97 -117
  74. data/lib/ruby_llm/agents/core/errors.rb +0 -58
  75. data/lib/ruby_llm/agents/core/instrumentation.rb +157 -110
  76. data/lib/ruby_llm/agents/core/llm_tenant.rb +8 -7
  77. data/lib/ruby_llm/agents/core/version.rb +1 -1
  78. data/lib/ruby_llm/agents/dsl/base.rb +157 -17
  79. data/lib/ruby_llm/agents/dsl/caching.rb +33 -2
  80. data/lib/ruby_llm/agents/dsl/reliability.rb +148 -0
  81. data/lib/ruby_llm/agents/dsl.rb +1 -2
  82. data/lib/ruby_llm/agents/image/analyzer/execution.rb +1 -2
  83. data/lib/ruby_llm/agents/image/background_remover/execution.rb +1 -2
  84. data/lib/ruby_llm/agents/image/concerns/image_operation_dsl.rb +1 -13
  85. data/lib/ruby_llm/agents/image/concerns/image_operation_execution.rb +2 -2
  86. data/lib/ruby_llm/agents/image/editor/dsl.rb +0 -14
  87. data/lib/ruby_llm/agents/image/editor/execution.rb +1 -10
  88. data/lib/ruby_llm/agents/image/editor.rb +0 -1
  89. data/lib/ruby_llm/agents/image/generator.rb +0 -21
  90. data/lib/ruby_llm/agents/image/pipeline/dsl.rb +0 -13
  91. data/lib/ruby_llm/agents/image/pipeline/execution.rb +0 -1
  92. data/lib/ruby_llm/agents/image/transformer/dsl.rb +0 -13
  93. data/lib/ruby_llm/agents/image/transformer/execution.rb +1 -10
  94. data/lib/ruby_llm/agents/image/transformer.rb +0 -1
  95. data/lib/ruby_llm/agents/image/upscaler/execution.rb +1 -2
  96. data/lib/ruby_llm/agents/image/variator/execution.rb +1 -2
  97. data/lib/ruby_llm/agents/infrastructure/alert_manager.rb +78 -173
  98. data/lib/ruby_llm/agents/infrastructure/budget/budget_query.rb +66 -2
  99. data/lib/ruby_llm/agents/infrastructure/budget/spend_recorder.rb +0 -12
  100. data/lib/ruby_llm/agents/infrastructure/circuit_breaker.rb +10 -13
  101. data/lib/ruby_llm/agents/infrastructure/execution_logger_job.rb +8 -0
  102. data/lib/ruby_llm/agents/pipeline/context.rb +0 -1
  103. data/lib/ruby_llm/agents/pipeline/middleware/budget.rb +28 -4
  104. data/lib/ruby_llm/agents/pipeline/middleware/cache.rb +3 -10
  105. data/lib/ruby_llm/agents/pipeline/middleware/instrumentation.rb +88 -55
  106. data/lib/ruby_llm/agents/pipeline/middleware/tenant.rb +5 -41
  107. data/lib/ruby_llm/agents/rails/engine.rb +6 -6
  108. data/lib/ruby_llm/agents/results/base.rb +1 -49
  109. data/lib/ruby_llm/agents/text/embedder.rb +0 -1
  110. data/lib/ruby_llm/agents.rb +1 -9
  111. data/lib/tasks/ruby_llm_agents.rake +34 -0
  112. metadata +14 -83
  113. data/app/controllers/ruby_llm/agents/api_configurations_controller.rb +0 -214
  114. data/app/controllers/ruby_llm/agents/workflows_controller.rb +0 -544
  115. data/app/mailers/ruby_llm/agents/alert_mailer.rb +0 -84
  116. data/app/mailers/ruby_llm/agents/application_mailer.rb +0 -28
  117. data/app/models/ruby_llm/agents/api_configuration.rb +0 -386
  118. data/app/models/ruby_llm/agents/execution/workflow.rb +0 -170
  119. data/app/models/ruby_llm/agents/tenant/configurable.rb +0 -135
  120. data/app/views/ruby_llm/agents/agents/_agent.html.erb +0 -98
  121. data/app/views/ruby_llm/agents/agents/_version_comparison.html.erb +0 -186
  122. data/app/views/ruby_llm/agents/agents/_workflow.html.erb +0 -126
  123. data/app/views/ruby_llm/agents/alert_mailer/alert_notification.html.erb +0 -107
  124. data/app/views/ruby_llm/agents/alert_mailer/alert_notification.text.erb +0 -18
  125. data/app/views/ruby_llm/agents/api_configurations/_api_key_field.html.erb +0 -34
  126. data/app/views/ruby_llm/agents/api_configurations/_form.html.erb +0 -288
  127. data/app/views/ruby_llm/agents/api_configurations/edit.html.erb +0 -95
  128. data/app/views/ruby_llm/agents/api_configurations/edit_tenant.html.erb +0 -97
  129. data/app/views/ruby_llm/agents/api_configurations/show.html.erb +0 -214
  130. data/app/views/ruby_llm/agents/api_configurations/tenant.html.erb +0 -179
  131. data/app/views/ruby_llm/agents/dashboard/_agent_comparison.html.erb +0 -73
  132. data/app/views/ruby_llm/agents/dashboard/_alerts_feed.html.erb +0 -62
  133. data/app/views/ruby_llm/agents/dashboard/_breaker_strip.html.erb +0 -47
  134. data/app/views/ruby_llm/agents/dashboard/_budgets_bar.html.erb +0 -75
  135. data/app/views/ruby_llm/agents/dashboard/_model_comparison.html.erb +0 -56
  136. data/app/views/ruby_llm/agents/dashboard/_model_cost_breakdown.html.erb +0 -115
  137. data/app/views/ruby_llm/agents/dashboard/_now_strip.html.erb +0 -59
  138. data/app/views/ruby_llm/agents/dashboard/_top_errors.html.erb +0 -60
  139. data/app/views/ruby_llm/agents/executions/_workflow_summary.html.erb +0 -86
  140. data/app/views/ruby_llm/agents/executions/dry_run.html.erb +0 -149
  141. data/app/views/ruby_llm/agents/shared/_breadcrumbs.html.erb +0 -48
  142. data/app/views/ruby_llm/agents/shared/_nav_link.html.erb +0 -27
  143. data/app/views/ruby_llm/agents/shared/_stat_card.html.erb +0 -14
  144. data/app/views/ruby_llm/agents/shared/_workflow_type_badge.html.erb +0 -35
  145. data/app/views/ruby_llm/agents/workflows/_empty_state.html.erb +0 -22
  146. data/app/views/ruby_llm/agents/workflows/_step_performance.html.erb +0 -228
  147. data/app/views/ruby_llm/agents/workflows/_structure_dsl.html.erb +0 -539
  148. data/app/views/ruby_llm/agents/workflows/_structure_parallel.html.erb +0 -76
  149. data/app/views/ruby_llm/agents/workflows/_structure_pipeline.html.erb +0 -74
  150. data/app/views/ruby_llm/agents/workflows/_structure_router.html.erb +0 -108
  151. data/app/views/ruby_llm/agents/workflows/_workflow_diagram.html.erb +0 -920
  152. data/app/views/ruby_llm/agents/workflows/index.html.erb +0 -179
  153. data/app/views/ruby_llm/agents/workflows/show.html.erb +0 -467
  154. data/lib/generators/ruby_llm_agents/api_configuration_generator.rb +0 -100
  155. data/lib/generators/ruby_llm_agents/templates/add_workflow_migration.rb.tt +0 -38
  156. data/lib/generators/ruby_llm_agents/templates/application_workflow.rb.tt +0 -48
  157. data/lib/generators/ruby_llm_agents/templates/create_api_configurations_migration.rb.tt +0 -90
  158. data/lib/generators/ruby_llm_agents/templates/skills/WORKFLOWS.md.tt +0 -551
  159. data/lib/ruby_llm/agents/core/base/moderation_dsl.rb +0 -181
  160. data/lib/ruby_llm/agents/core/base/moderation_execution.rb +0 -274
  161. data/lib/ruby_llm/agents/core/resolved_config.rb +0 -348
  162. data/lib/ruby_llm/agents/image/generator/content_policy.rb +0 -95
  163. data/lib/ruby_llm/agents/infrastructure/redactor.rb +0 -130
  164. data/lib/ruby_llm/agents/results/moderation_result.rb +0 -158
  165. data/lib/ruby_llm/agents/text/moderator.rb +0 -237
  166. data/lib/ruby_llm/agents/workflow/approval.rb +0 -205
  167. data/lib/ruby_llm/agents/workflow/approval_store.rb +0 -179
  168. data/lib/ruby_llm/agents/workflow/async.rb +0 -220
  169. data/lib/ruby_llm/agents/workflow/async_executor.rb +0 -156
  170. data/lib/ruby_llm/agents/workflow/dsl/executor.rb +0 -467
  171. data/lib/ruby_llm/agents/workflow/dsl/input_schema.rb +0 -244
  172. data/lib/ruby_llm/agents/workflow/dsl/iteration_executor.rb +0 -289
  173. data/lib/ruby_llm/agents/workflow/dsl/parallel_group.rb +0 -107
  174. data/lib/ruby_llm/agents/workflow/dsl/route_builder.rb +0 -150
  175. data/lib/ruby_llm/agents/workflow/dsl/schedule_helpers.rb +0 -187
  176. data/lib/ruby_llm/agents/workflow/dsl/step_config.rb +0 -352
  177. data/lib/ruby_llm/agents/workflow/dsl/step_executor.rb +0 -415
  178. data/lib/ruby_llm/agents/workflow/dsl/wait_config.rb +0 -257
  179. data/lib/ruby_llm/agents/workflow/dsl/wait_executor.rb +0 -317
  180. data/lib/ruby_llm/agents/workflow/dsl.rb +0 -576
  181. data/lib/ruby_llm/agents/workflow/instrumentation.rb +0 -249
  182. data/lib/ruby_llm/agents/workflow/notifiers/base.rb +0 -117
  183. data/lib/ruby_llm/agents/workflow/notifiers/email.rb +0 -117
  184. data/lib/ruby_llm/agents/workflow/notifiers/slack.rb +0 -180
  185. data/lib/ruby_llm/agents/workflow/notifiers/webhook.rb +0 -121
  186. data/lib/ruby_llm/agents/workflow/notifiers.rb +0 -70
  187. data/lib/ruby_llm/agents/workflow/orchestrator.rb +0 -416
  188. data/lib/ruby_llm/agents/workflow/result.rb +0 -592
  189. data/lib/ruby_llm/agents/workflow/thread_pool.rb +0 -185
  190. data/lib/ruby_llm/agents/workflow/throttle_manager.rb +0 -206
  191. data/lib/ruby_llm/agents/workflow/wait_result.rb +0 -213
@@ -167,15 +167,18 @@ module RubyLLM
167
167
  # enforcement: :soft
168
168
  # }
169
169
 
170
- # @!attribute [rw] alerts
171
- # Alert configuration for notifications.
172
- # @return [Hash, nil] Alert config with :slack_webhook_url, :webhook_url, :on_events, :custom keys
170
+ # @!attribute [rw] on_alert
171
+ # Alert handler proc called when governance events occur.
172
+ # Receives event name and payload hash. Filter events in your proc as needed.
173
+ # @return [Proc, nil] Alert handler or nil to disable (default: nil)
173
174
  # @example
174
- # config.alerts = {
175
- # slack_webhook_url: ENV["SLACK_WEBHOOK"],
176
- # webhook_url: ENV["AGENTS_WEBHOOK"],
177
- # on_events: [:budget_soft_cap, :budget_hard_cap, :breaker_open],
178
- # custom: ->(event, payload) { Rails.logger.info("Alert: #{event}") }
175
+ # config.on_alert = ->(event, payload) {
176
+ # case event
177
+ # when :budget_hard_cap
178
+ # Slack::Notifier.new(ENV["SLACK_WEBHOOK"]).ping("Budget exceeded")
179
+ # when :breaker_open
180
+ # PagerDuty.trigger(payload)
181
+ # end
179
182
  # }
180
183
 
181
184
  # @!attribute [rw] persist_prompts
@@ -188,17 +191,6 @@ module RubyLLM
188
191
  # Set to false to reduce storage or for privacy compliance.
189
192
  # @return [Boolean] Enable response persistence (default: true)
190
193
 
191
- # @!attribute [rw] redaction
192
- # Redaction configuration for PII and sensitive data.
193
- # @return [Hash, nil] Redaction config with :fields, :patterns, :placeholder, :max_value_length keys
194
- # @example
195
- # config.redaction = {
196
- # fields: %w[password api_key email ssn],
197
- # patterns: [/\b\d{3}-\d{2}-\d{4}\b/],
198
- # placeholder: "[REDACTED]",
199
- # max_value_length: 5000
200
- # }
201
-
202
194
  # @!attribute [rw] multi_tenancy_enabled
203
195
  # Whether multi-tenancy features are enabled.
204
196
  # When false, the gem behaves exactly as before (backward compatible).
@@ -274,35 +266,6 @@ module RubyLLM
274
266
  # @example
275
267
  # config.track_embeddings = false
276
268
 
277
- # @!attribute [rw] default_moderation_model
278
- # The default moderation model identifier for all agents.
279
- # Can be overridden per-agent using the `moderation` DSL method.
280
- # @return [String] Model identifier (default: "omni-moderation-latest")
281
- # @example
282
- # config.default_moderation_model = "text-moderation-007"
283
-
284
- # @!attribute [rw] default_moderation_threshold
285
- # The default threshold for moderation scores.
286
- # Content with scores at or above this threshold will be flagged.
287
- # Set to nil to use the provider's default flagging.
288
- # @return [Float, nil] Threshold (0.0-1.0) or nil for provider default (default: nil)
289
- # @example
290
- # config.default_moderation_threshold = 0.8
291
-
292
- # @!attribute [rw] default_moderation_action
293
- # The default action when content is flagged.
294
- # Can be overridden per-agent using the `moderation` DSL method.
295
- # @return [Symbol] Action (:block, :raise, :warn, :log) (default: :block)
296
- # @example
297
- # config.default_moderation_action = :raise
298
-
299
- # @!attribute [rw] track_moderation
300
- # Whether to track moderation executions in the database.
301
- # When enabled, moderation operations are logged as executions.
302
- # @return [Boolean] Enable moderation tracking (default: true)
303
- # @example
304
- # config.track_moderation = false
305
-
306
269
  # @!attribute [rw] default_transcription_model
307
270
  # The default transcription model identifier for all transcribers.
308
271
  # Can be overridden per-transcriber using the `model` DSL method.
@@ -376,6 +339,57 @@ module RubyLLM
376
339
  # @example
377
340
  # config.tool_result_max_length = 5000
378
341
 
342
+ # @!attribute [rw] redaction
343
+ # Configuration for PII and sensitive data redaction.
344
+ # When set, sensitive data is redacted before storing in execution records.
345
+ # @return [Hash, nil] Redaction config with :fields, :patterns, :placeholder, :max_value_length keys
346
+ # @example
347
+ # config.redaction = {
348
+ # fields: %w[ssn credit_card phone_number email],
349
+ # patterns: [/\b\d{3}-\d{2}-\d{4}\b/],
350
+ # placeholder: "[REDACTED]",
351
+ # max_value_length: 5000
352
+ # }
353
+
354
+ # API key and provider attributes forwarded to RubyLLM.
355
+ # These let users configure everything in one place through
356
+ # RubyLLM::Agents.configure instead of a separate RubyLLM.configure block.
357
+ FORWARDED_RUBY_LLM_ATTRIBUTES = %i[
358
+ openai_api_key
359
+ anthropic_api_key
360
+ gemini_api_key
361
+ deepseek_api_key
362
+ openrouter_api_key
363
+ bedrock_api_key
364
+ bedrock_secret_key
365
+ bedrock_session_token
366
+ bedrock_region
367
+ mistral_api_key
368
+ perplexity_api_key
369
+ xai_api_key
370
+ gpustack_api_key
371
+ openai_api_base
372
+ openai_organization_id
373
+ openai_project_id
374
+ gemini_api_base
375
+ gpustack_api_base
376
+ ollama_api_base
377
+ vertexai_project_id
378
+ vertexai_location
379
+ request_timeout
380
+ max_retries
381
+ ].freeze
382
+
383
+ FORWARDED_RUBY_LLM_ATTRIBUTES.each do |attr|
384
+ define_method(:"#{attr}=") do |value|
385
+ RubyLLM.config.public_send(:"#{attr}=", value)
386
+ end
387
+
388
+ define_method(attr) do
389
+ RubyLLM.config.public_send(attr)
390
+ end
391
+ end
392
+
379
393
  # Attributes without validation (simple accessors)
380
394
  attr_accessor :default_model,
381
395
  :async_logging,
@@ -389,10 +403,9 @@ module RubyLLM
389
403
  :default_streaming,
390
404
  :default_tools,
391
405
  :default_thinking,
392
- :alerts,
406
+ :on_alert,
393
407
  :persist_prompts,
394
408
  :persist_responses,
395
- :redaction,
396
409
  :multi_tenancy_enabled,
397
410
  :persist_messages_summary,
398
411
  :default_retryable_patterns,
@@ -400,10 +413,6 @@ module RubyLLM
400
413
  :default_embedding_dimensions,
401
414
  :default_embedding_batch_size,
402
415
  :track_embeddings,
403
- :default_moderation_model,
404
- :default_moderation_threshold,
405
- :default_moderation_action,
406
- :track_moderation,
407
416
  :default_transcription_model,
408
417
  :track_transcriptions,
409
418
  :default_tts_provider,
@@ -437,7 +446,8 @@ module RubyLLM
437
446
  :default_background_output_format,
438
447
  :root_directory,
439
448
  :root_namespace,
440
- :tool_result_max_length
449
+ :tool_result_max_length,
450
+ :redaction
441
451
 
442
452
  # Attributes with validation (readers only, custom setters below)
443
453
  attr_reader :default_temperature,
@@ -634,10 +644,9 @@ module RubyLLM
634
644
 
635
645
  # Governance defaults
636
646
  @budgets = nil
637
- @alerts = nil
647
+ @on_alert = nil
638
648
  @persist_prompts = true
639
649
  @persist_responses = true
640
- @redaction = nil
641
650
 
642
651
  # Multi-tenancy defaults (disabled for backward compatibility)
643
652
  @multi_tenancy_enabled = false
@@ -654,12 +663,6 @@ module RubyLLM
654
663
  @default_embedding_batch_size = 100
655
664
  @track_embeddings = true
656
665
 
657
- # Moderation defaults
658
- @default_moderation_model = "omni-moderation-latest"
659
- @default_moderation_threshold = nil
660
- @default_moderation_action = :block
661
- @track_moderation = true
662
-
663
666
  # Transcription defaults
664
667
  @default_transcription_model = "whisper-1"
665
668
  @track_transcriptions = true
@@ -715,6 +718,9 @@ module RubyLLM
715
718
 
716
719
  # Tool tracking defaults
717
720
  @tool_result_max_length = 10_000
721
+
722
+ # Redaction defaults (disabled by default)
723
+ @redaction = nil
718
724
  end
719
725
 
720
726
  # Returns the configured cache store, falling back to Rails.cache
@@ -747,55 +753,6 @@ module RubyLLM
747
753
  default_retryable_patterns.values.flatten.uniq
748
754
  end
749
755
 
750
- # Returns whether alerts are configured
751
- #
752
- # @return [Boolean] true if any alert destination is configured
753
- def alerts_enabled?
754
- return false unless alerts.is_a?(Hash)
755
-
756
- alerts[:slack_webhook_url].present? ||
757
- alerts[:webhook_url].present? ||
758
- alerts[:custom].present? ||
759
- alerts[:email_recipients].present?
760
- end
761
-
762
- # Returns the list of events to alert on
763
- #
764
- # @return [Array<Symbol>] Event names to trigger alerts
765
- def alert_events
766
- alerts&.dig(:on_events) || []
767
- end
768
-
769
- # Returns merged redaction fields (default sensitive keys + configured)
770
- #
771
- # @return [Array<String>] Field names to redact
772
- def redaction_fields
773
- default_fields = %w[password token api_key secret credential auth key access_token]
774
- configured_fields = redaction&.dig(:fields) || []
775
- (default_fields + configured_fields).map(&:downcase).uniq
776
- end
777
-
778
- # Returns redaction patterns
779
- #
780
- # @return [Array<Regexp>] Patterns to match and redact
781
- def redaction_patterns
782
- redaction&.dig(:patterns) || []
783
- end
784
-
785
- # Returns the redaction placeholder string
786
- #
787
- # @return [String] Placeholder to replace redacted values
788
- def redaction_placeholder
789
- redaction&.dig(:placeholder) || "[REDACTED]"
790
- end
791
-
792
- # Returns the maximum value length before truncation
793
- #
794
- # @return [Integer, nil] Max length, or nil for no limit
795
- def redaction_max_value_length
796
- redaction&.dig(:max_value_length)
797
- end
798
-
799
756
  # Returns whether multi-tenancy is enabled
800
757
  #
801
758
  # @return [Boolean] true if multi-tenancy is enabled
@@ -869,8 +826,6 @@ module RubyLLM
869
826
  when :images then "images"
870
827
  when :audio then "audio"
871
828
  when :embedders then "embedders"
872
- when :moderators then "moderators"
873
- when :workflows then "workflows"
874
829
  when :text then "text"
875
830
  when :image then "image"
876
831
  end
@@ -895,16 +850,41 @@ module RubyLLM
895
850
 
896
851
  [
897
852
  base,
898
- "app/workflows", # Top-level workflows directory
899
853
  "#{base}/images",
900
854
  "#{base}/audio",
901
855
  "#{base}/embedders",
902
- "#{base}/moderators",
903
- "#{base}/workflows",
904
856
  "#{base}/tools"
905
857
  ]
906
858
  end
907
859
 
860
+ # Returns the redaction fields (parameter names to redact)
861
+ #
862
+ # @return [Array<String>] Fields to redact
863
+ def redaction_fields
864
+ redaction&.dig(:fields) || []
865
+ end
866
+
867
+ # Returns the redaction regex patterns
868
+ #
869
+ # @return [Array<Regexp>] Patterns to match and redact
870
+ def redaction_patterns
871
+ redaction&.dig(:patterns) || []
872
+ end
873
+
874
+ # Returns the redaction placeholder string
875
+ #
876
+ # @return [String] Placeholder for redacted values (default: "[REDACTED]")
877
+ def redaction_placeholder
878
+ redaction&.dig(:placeholder) || "[REDACTED]"
879
+ end
880
+
881
+ # Returns the max value length for redaction
882
+ #
883
+ # @return [Integer, nil] Max length before truncation, or nil for no limit
884
+ def redaction_max_value_length
885
+ redaction&.dig(:max_value_length)
886
+ end
887
+
908
888
  private
909
889
 
910
890
  # Validates that a value is within a range
@@ -88,63 +88,5 @@ module RubyLLM
88
88
 
89
89
  # Raised for configuration issues
90
90
  class ConfigurationError < Error; end
91
-
92
- # Raised when content is flagged during moderation
93
- #
94
- # Contains the full moderation result and the phase where
95
- # the content was flagged.
96
- #
97
- # @example Handling moderation errors
98
- # begin
99
- # result = MyAgent.call(message: user_input)
100
- # rescue RubyLLM::Agents::ModerationError => e
101
- # puts "Content blocked: #{e.flagged_categories.join(', ')}"
102
- # puts "Phase: #{e.phase}"
103
- # puts "Scores: #{e.category_scores}"
104
- # end
105
- #
106
- # @api public
107
- class ModerationError < Error
108
- # @return [Object] The raw moderation result from RubyLLM
109
- attr_reader :moderation_result
110
-
111
- # @return [Symbol] The phase where content was flagged (:input or :output)
112
- attr_reader :phase
113
-
114
- # Creates a new ModerationError
115
- #
116
- # @param moderation_result [Object] The moderation result from RubyLLM
117
- # @param phase [Symbol] The phase where content was flagged
118
- def initialize(moderation_result, phase)
119
- @moderation_result = moderation_result
120
- @phase = phase
121
-
122
- categories = moderation_result.flagged_categories
123
- category_list = categories.respond_to?(:join) ? categories.join(", ") : categories.to_s
124
-
125
- super("Content flagged during #{phase} moderation: #{category_list}")
126
- end
127
-
128
- # Returns the flagged categories from the moderation result
129
- #
130
- # @return [Array<String, Symbol>] List of flagged categories
131
- def flagged_categories
132
- moderation_result.flagged_categories
133
- end
134
-
135
- # Returns the category scores from the moderation result
136
- #
137
- # @return [Hash{String, Symbol => Float}] Category to score mapping
138
- def category_scores
139
- moderation_result.category_scores
140
- end
141
-
142
- # Returns whether the moderation result was flagged
143
- #
144
- # @return [Boolean] Always true for ModerationError
145
- def flagged?
146
- true
147
- end
148
- end
149
91
  end
150
92
  end