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.
- checksums.yaml +4 -4
- data/README.md +112 -336
- data/app/controllers/concerns/ruby_llm/agents/sortable.rb +0 -1
- data/app/controllers/ruby_llm/agents/agents_controller.rb +5 -56
- data/app/controllers/ruby_llm/agents/dashboard_controller.rb +22 -106
- data/app/controllers/ruby_llm/agents/executions_controller.rb +4 -114
- data/app/controllers/ruby_llm/agents/tenants_controller.rb +30 -2
- data/app/helpers/ruby_llm/agents/application_helper.rb +19 -53
- data/app/models/ruby_llm/agents/execution/analytics.rb +13 -54
- data/app/models/ruby_llm/agents/execution/scopes.rb +61 -14
- data/app/models/ruby_llm/agents/execution.rb +52 -12
- data/app/models/ruby_llm/agents/execution_detail.rb +18 -0
- data/app/models/ruby_llm/agents/tenant/budgetable.rb +132 -24
- data/app/models/ruby_llm/agents/tenant/incrementable.rb +117 -0
- data/app/models/ruby_llm/agents/tenant/resettable.rb +128 -0
- data/app/models/ruby_llm/agents/tenant/trackable.rb +46 -12
- data/app/models/ruby_llm/agents/tenant.rb +2 -3
- data/app/models/ruby_llm/agents/tenant_budget.rb +6 -3
- data/app/services/ruby_llm/agents/agent_registry.rb +6 -112
- data/app/views/layouts/ruby_llm/agents/application.html.erb +89 -252
- data/app/views/ruby_llm/agents/agents/_config_agent.html.erb +71 -218
- data/app/views/ruby_llm/agents/agents/_config_embedder.html.erb +20 -63
- data/app/views/ruby_llm/agents/agents/_config_image_generator.html.erb +44 -131
- data/app/views/ruby_llm/agents/agents/_config_moderator.html.erb +16 -57
- data/app/views/ruby_llm/agents/agents/_config_speaker.html.erb +39 -104
- data/app/views/ruby_llm/agents/agents/_config_transcriber.html.erb +29 -82
- data/app/views/ruby_llm/agents/agents/_empty_state.html.erb +4 -14
- data/app/views/ruby_llm/agents/agents/index.html.erb +105 -274
- data/app/views/ruby_llm/agents/agents/show.html.erb +248 -378
- data/app/views/ruby_llm/agents/dashboard/_action_center.html.erb +29 -52
- data/app/views/ruby_llm/agents/dashboard/_tenant_budget.html.erb +73 -99
- data/app/views/ruby_llm/agents/dashboard/index.html.erb +228 -433
- data/app/views/ruby_llm/agents/executions/_execution.html.erb +1 -1
- data/app/views/ruby_llm/agents/executions/_filters.html.erb +4 -25
- data/app/views/ruby_llm/agents/executions/_list.html.erb +111 -152
- data/app/views/ruby_llm/agents/executions/index.html.erb +5 -7
- data/app/views/ruby_llm/agents/executions/show.html.erb +526 -1037
- data/app/views/ruby_llm/agents/shared/_agent_type_badge.html.erb +5 -21
- data/app/views/ruby_llm/agents/shared/_executions_table.html.erb +70 -191
- data/app/views/ruby_llm/agents/shared/_filter_dropdown.html.erb +16 -44
- data/app/views/ruby_llm/agents/shared/_select_dropdown.html.erb +12 -41
- data/app/views/ruby_llm/agents/shared/_status_badge.html.erb +11 -65
- data/app/views/ruby_llm/agents/shared/_tenant_filter.html.erb +6 -5
- data/app/views/ruby_llm/agents/system_config/show.html.erb +240 -351
- data/app/views/ruby_llm/agents/tenants/_form.html.erb +67 -77
- data/app/views/ruby_llm/agents/tenants/edit.html.erb +7 -9
- data/app/views/ruby_llm/agents/tenants/index.html.erb +100 -122
- data/app/views/ruby_llm/agents/tenants/show.html.erb +146 -336
- data/config/routes.rb +0 -13
- data/lib/generators/ruby_llm_agents/install_generator.rb +13 -17
- data/lib/generators/ruby_llm_agents/migrate_structure_generator.rb +2 -12
- data/lib/generators/ruby_llm_agents/restructure_generator.rb +0 -2
- data/lib/generators/ruby_llm_agents/templates/add_usage_counters_to_tenants_migration.rb.tt +37 -0
- data/lib/generators/ruby_llm_agents/templates/agent.rb.tt +1 -2
- data/lib/generators/ruby_llm_agents/templates/application_agent.rb.tt +1 -1
- data/lib/generators/ruby_llm_agents/templates/application_image_pipeline.rb.tt +0 -1
- data/lib/generators/ruby_llm_agents/templates/create_execution_details_migration.rb.tt +27 -0
- data/lib/generators/ruby_llm_agents/templates/create_tenants_migration.rb.tt +25 -0
- data/lib/generators/ruby_llm_agents/templates/image_pipeline.rb.tt +0 -1
- data/lib/generators/ruby_llm_agents/templates/initializer.rb.tt +33 -12
- data/lib/generators/ruby_llm_agents/templates/migration.rb.tt +40 -71
- data/lib/generators/ruby_llm_agents/templates/remove_agent_version_migration.rb.tt +13 -0
- data/lib/generators/ruby_llm_agents/templates/remove_workflow_columns_migration.rb.tt +19 -0
- data/lib/generators/ruby_llm_agents/templates/skills/AGENTS.md.tt +2 -4
- data/lib/generators/ruby_llm_agents/templates/skills/IMAGE_PIPELINES.md.tt +0 -1
- data/lib/generators/ruby_llm_agents/templates/split_execution_details_migration.rb.tt +232 -0
- data/lib/generators/ruby_llm_agents/upgrade_generator.rb +77 -259
- data/lib/ruby_llm/agents/audio/speaker.rb +0 -1
- data/lib/ruby_llm/agents/audio/transcriber.rb +0 -1
- data/lib/ruby_llm/agents/base_agent.rb +54 -23
- data/lib/ruby_llm/agents/core/base/callbacks.rb +142 -0
- data/lib/ruby_llm/agents/core/base.rb +23 -55
- data/lib/ruby_llm/agents/core/configuration.rb +97 -117
- data/lib/ruby_llm/agents/core/errors.rb +0 -58
- data/lib/ruby_llm/agents/core/instrumentation.rb +157 -110
- data/lib/ruby_llm/agents/core/llm_tenant.rb +8 -7
- data/lib/ruby_llm/agents/core/version.rb +1 -1
- data/lib/ruby_llm/agents/dsl/base.rb +157 -17
- data/lib/ruby_llm/agents/dsl/caching.rb +33 -2
- data/lib/ruby_llm/agents/dsl/reliability.rb +148 -0
- data/lib/ruby_llm/agents/dsl.rb +1 -2
- data/lib/ruby_llm/agents/image/analyzer/execution.rb +1 -2
- data/lib/ruby_llm/agents/image/background_remover/execution.rb +1 -2
- data/lib/ruby_llm/agents/image/concerns/image_operation_dsl.rb +1 -13
- data/lib/ruby_llm/agents/image/concerns/image_operation_execution.rb +2 -2
- data/lib/ruby_llm/agents/image/editor/dsl.rb +0 -14
- data/lib/ruby_llm/agents/image/editor/execution.rb +1 -10
- data/lib/ruby_llm/agents/image/editor.rb +0 -1
- data/lib/ruby_llm/agents/image/generator.rb +0 -21
- data/lib/ruby_llm/agents/image/pipeline/dsl.rb +0 -13
- data/lib/ruby_llm/agents/image/pipeline/execution.rb +0 -1
- data/lib/ruby_llm/agents/image/transformer/dsl.rb +0 -13
- data/lib/ruby_llm/agents/image/transformer/execution.rb +1 -10
- data/lib/ruby_llm/agents/image/transformer.rb +0 -1
- data/lib/ruby_llm/agents/image/upscaler/execution.rb +1 -2
- data/lib/ruby_llm/agents/image/variator/execution.rb +1 -2
- data/lib/ruby_llm/agents/infrastructure/alert_manager.rb +78 -173
- data/lib/ruby_llm/agents/infrastructure/budget/budget_query.rb +66 -2
- data/lib/ruby_llm/agents/infrastructure/budget/spend_recorder.rb +0 -12
- data/lib/ruby_llm/agents/infrastructure/circuit_breaker.rb +10 -13
- data/lib/ruby_llm/agents/infrastructure/execution_logger_job.rb +8 -0
- data/lib/ruby_llm/agents/pipeline/context.rb +0 -1
- data/lib/ruby_llm/agents/pipeline/middleware/budget.rb +28 -4
- data/lib/ruby_llm/agents/pipeline/middleware/cache.rb +3 -10
- data/lib/ruby_llm/agents/pipeline/middleware/instrumentation.rb +88 -55
- data/lib/ruby_llm/agents/pipeline/middleware/tenant.rb +5 -41
- data/lib/ruby_llm/agents/rails/engine.rb +6 -6
- data/lib/ruby_llm/agents/results/base.rb +1 -49
- data/lib/ruby_llm/agents/text/embedder.rb +0 -1
- data/lib/ruby_llm/agents.rb +1 -9
- data/lib/tasks/ruby_llm_agents.rake +34 -0
- metadata +14 -83
- data/app/controllers/ruby_llm/agents/api_configurations_controller.rb +0 -214
- data/app/controllers/ruby_llm/agents/workflows_controller.rb +0 -544
- data/app/mailers/ruby_llm/agents/alert_mailer.rb +0 -84
- data/app/mailers/ruby_llm/agents/application_mailer.rb +0 -28
- data/app/models/ruby_llm/agents/api_configuration.rb +0 -386
- data/app/models/ruby_llm/agents/execution/workflow.rb +0 -170
- data/app/models/ruby_llm/agents/tenant/configurable.rb +0 -135
- data/app/views/ruby_llm/agents/agents/_agent.html.erb +0 -98
- data/app/views/ruby_llm/agents/agents/_version_comparison.html.erb +0 -186
- data/app/views/ruby_llm/agents/agents/_workflow.html.erb +0 -126
- data/app/views/ruby_llm/agents/alert_mailer/alert_notification.html.erb +0 -107
- data/app/views/ruby_llm/agents/alert_mailer/alert_notification.text.erb +0 -18
- data/app/views/ruby_llm/agents/api_configurations/_api_key_field.html.erb +0 -34
- data/app/views/ruby_llm/agents/api_configurations/_form.html.erb +0 -288
- data/app/views/ruby_llm/agents/api_configurations/edit.html.erb +0 -95
- data/app/views/ruby_llm/agents/api_configurations/edit_tenant.html.erb +0 -97
- data/app/views/ruby_llm/agents/api_configurations/show.html.erb +0 -214
- data/app/views/ruby_llm/agents/api_configurations/tenant.html.erb +0 -179
- data/app/views/ruby_llm/agents/dashboard/_agent_comparison.html.erb +0 -73
- data/app/views/ruby_llm/agents/dashboard/_alerts_feed.html.erb +0 -62
- data/app/views/ruby_llm/agents/dashboard/_breaker_strip.html.erb +0 -47
- data/app/views/ruby_llm/agents/dashboard/_budgets_bar.html.erb +0 -75
- data/app/views/ruby_llm/agents/dashboard/_model_comparison.html.erb +0 -56
- data/app/views/ruby_llm/agents/dashboard/_model_cost_breakdown.html.erb +0 -115
- data/app/views/ruby_llm/agents/dashboard/_now_strip.html.erb +0 -59
- data/app/views/ruby_llm/agents/dashboard/_top_errors.html.erb +0 -60
- data/app/views/ruby_llm/agents/executions/_workflow_summary.html.erb +0 -86
- data/app/views/ruby_llm/agents/executions/dry_run.html.erb +0 -149
- data/app/views/ruby_llm/agents/shared/_breadcrumbs.html.erb +0 -48
- data/app/views/ruby_llm/agents/shared/_nav_link.html.erb +0 -27
- data/app/views/ruby_llm/agents/shared/_stat_card.html.erb +0 -14
- data/app/views/ruby_llm/agents/shared/_workflow_type_badge.html.erb +0 -35
- data/app/views/ruby_llm/agents/workflows/_empty_state.html.erb +0 -22
- data/app/views/ruby_llm/agents/workflows/_step_performance.html.erb +0 -228
- data/app/views/ruby_llm/agents/workflows/_structure_dsl.html.erb +0 -539
- data/app/views/ruby_llm/agents/workflows/_structure_parallel.html.erb +0 -76
- data/app/views/ruby_llm/agents/workflows/_structure_pipeline.html.erb +0 -74
- data/app/views/ruby_llm/agents/workflows/_structure_router.html.erb +0 -108
- data/app/views/ruby_llm/agents/workflows/_workflow_diagram.html.erb +0 -920
- data/app/views/ruby_llm/agents/workflows/index.html.erb +0 -179
- data/app/views/ruby_llm/agents/workflows/show.html.erb +0 -467
- data/lib/generators/ruby_llm_agents/api_configuration_generator.rb +0 -100
- data/lib/generators/ruby_llm_agents/templates/add_workflow_migration.rb.tt +0 -38
- data/lib/generators/ruby_llm_agents/templates/application_workflow.rb.tt +0 -48
- data/lib/generators/ruby_llm_agents/templates/create_api_configurations_migration.rb.tt +0 -90
- data/lib/generators/ruby_llm_agents/templates/skills/WORKFLOWS.md.tt +0 -551
- data/lib/ruby_llm/agents/core/base/moderation_dsl.rb +0 -181
- data/lib/ruby_llm/agents/core/base/moderation_execution.rb +0 -274
- data/lib/ruby_llm/agents/core/resolved_config.rb +0 -348
- data/lib/ruby_llm/agents/image/generator/content_policy.rb +0 -95
- data/lib/ruby_llm/agents/infrastructure/redactor.rb +0 -130
- data/lib/ruby_llm/agents/results/moderation_result.rb +0 -158
- data/lib/ruby_llm/agents/text/moderator.rb +0 -237
- data/lib/ruby_llm/agents/workflow/approval.rb +0 -205
- data/lib/ruby_llm/agents/workflow/approval_store.rb +0 -179
- data/lib/ruby_llm/agents/workflow/async.rb +0 -220
- data/lib/ruby_llm/agents/workflow/async_executor.rb +0 -156
- data/lib/ruby_llm/agents/workflow/dsl/executor.rb +0 -467
- data/lib/ruby_llm/agents/workflow/dsl/input_schema.rb +0 -244
- data/lib/ruby_llm/agents/workflow/dsl/iteration_executor.rb +0 -289
- data/lib/ruby_llm/agents/workflow/dsl/parallel_group.rb +0 -107
- data/lib/ruby_llm/agents/workflow/dsl/route_builder.rb +0 -150
- data/lib/ruby_llm/agents/workflow/dsl/schedule_helpers.rb +0 -187
- data/lib/ruby_llm/agents/workflow/dsl/step_config.rb +0 -352
- data/lib/ruby_llm/agents/workflow/dsl/step_executor.rb +0 -415
- data/lib/ruby_llm/agents/workflow/dsl/wait_config.rb +0 -257
- data/lib/ruby_llm/agents/workflow/dsl/wait_executor.rb +0 -317
- data/lib/ruby_llm/agents/workflow/dsl.rb +0 -576
- data/lib/ruby_llm/agents/workflow/instrumentation.rb +0 -249
- data/lib/ruby_llm/agents/workflow/notifiers/base.rb +0 -117
- data/lib/ruby_llm/agents/workflow/notifiers/email.rb +0 -117
- data/lib/ruby_llm/agents/workflow/notifiers/slack.rb +0 -180
- data/lib/ruby_llm/agents/workflow/notifiers/webhook.rb +0 -121
- data/lib/ruby_llm/agents/workflow/notifiers.rb +0 -70
- data/lib/ruby_llm/agents/workflow/orchestrator.rb +0 -416
- data/lib/ruby_llm/agents/workflow/result.rb +0 -592
- data/lib/ruby_llm/agents/workflow/thread_pool.rb +0 -185
- data/lib/ruby_llm/agents/workflow/throttle_manager.rb +0 -206
- 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]
|
|
171
|
-
# Alert
|
|
172
|
-
#
|
|
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.
|
|
175
|
-
#
|
|
176
|
-
#
|
|
177
|
-
#
|
|
178
|
-
#
|
|
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
|
-
:
|
|
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
|
-
@
|
|
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
|