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
|
@@ -14,7 +14,6 @@ module RubyLlmAgents
|
|
|
14
14
|
# - Create the initializer at config/initializers/ruby_llm_agents.rb
|
|
15
15
|
# - Create app/agents/application_agent.rb base class
|
|
16
16
|
# - Create app/agents/concerns/ directory
|
|
17
|
-
# - Create app/workflows/application_workflow.rb base class
|
|
18
17
|
# - Optionally mount the dashboard engine in routes
|
|
19
18
|
#
|
|
20
19
|
class InstallGenerator < ::Rails::Generators::Base
|
|
@@ -38,6 +37,15 @@ module RubyLlmAgents
|
|
|
38
37
|
)
|
|
39
38
|
end
|
|
40
39
|
|
|
40
|
+
def create_execution_details_migration
|
|
41
|
+
return if options[:skip_migration]
|
|
42
|
+
|
|
43
|
+
migration_template(
|
|
44
|
+
"create_execution_details_migration.rb.tt",
|
|
45
|
+
File.join(db_migrate_path, "create_ruby_llm_agents_execution_details.rb")
|
|
46
|
+
)
|
|
47
|
+
end
|
|
48
|
+
|
|
41
49
|
def create_initializer
|
|
42
50
|
return if options[:skip_initializer]
|
|
43
51
|
|
|
@@ -51,9 +59,6 @@ module RubyLlmAgents
|
|
|
51
59
|
empty_directory "app/agents"
|
|
52
60
|
empty_directory "app/agents/concerns"
|
|
53
61
|
|
|
54
|
-
# Create workflows directory
|
|
55
|
-
empty_directory "app/workflows"
|
|
56
|
-
|
|
57
62
|
# Create tools directory
|
|
58
63
|
empty_directory "app/tools"
|
|
59
64
|
end
|
|
@@ -62,19 +67,12 @@ module RubyLlmAgents
|
|
|
62
67
|
template "application_agent.rb.tt", "app/agents/application_agent.rb"
|
|
63
68
|
end
|
|
64
69
|
|
|
65
|
-
def create_application_workflow
|
|
66
|
-
template "application_workflow.rb.tt", "app/workflows/application_workflow.rb"
|
|
67
|
-
end
|
|
68
|
-
|
|
69
70
|
def create_skill_files
|
|
70
71
|
say_status :create, "skill documentation files", :green
|
|
71
72
|
|
|
72
73
|
# Create agents skill file
|
|
73
74
|
template "skills/AGENTS.md.tt", "app/agents/AGENTS.md"
|
|
74
75
|
|
|
75
|
-
# Create workflows skill file
|
|
76
|
-
template "skills/WORKFLOWS.md.tt", "app/workflows/WORKFLOWS.md"
|
|
77
|
-
|
|
78
76
|
# Create tools skill file
|
|
79
77
|
template "skills/TOOLS.md.tt", "app/tools/TOOLS.md"
|
|
80
78
|
end
|
|
@@ -104,18 +102,16 @@ module RubyLlmAgents
|
|
|
104
102
|
say " │ ├── application_agent.rb"
|
|
105
103
|
say " │ ├── concerns/"
|
|
106
104
|
say " │ └── AGENTS.md"
|
|
107
|
-
say " ├── workflows/"
|
|
108
|
-
say " │ ├── application_workflow.rb"
|
|
109
|
-
say " │ └── WORKFLOWS.md"
|
|
110
105
|
say " └── tools/"
|
|
111
106
|
say " └── TOOLS.md"
|
|
112
107
|
say ""
|
|
113
108
|
say "Skill files (*.md) help AI coding assistants understand how to use this gem."
|
|
114
109
|
say ""
|
|
115
110
|
say "Next steps:"
|
|
116
|
-
say " 1.
|
|
117
|
-
say " 2.
|
|
118
|
-
say " 3.
|
|
111
|
+
say " 1. Set your API keys in config/initializers/ruby_llm_agents.rb"
|
|
112
|
+
say " 2. Run migrations: rails db:migrate"
|
|
113
|
+
say " 3. Generate an agent: rails generate ruby_llm_agents:agent MyAgent query:required"
|
|
114
|
+
say " 4. Access the dashboard at: /agents"
|
|
119
115
|
say ""
|
|
120
116
|
say "Generator commands:"
|
|
121
117
|
say " rails generate ruby_llm_agents:agent CustomerSupport query:required"
|
|
@@ -11,14 +11,12 @@ module RubyLlmAgents
|
|
|
11
11
|
# app/{root}/image/generators/
|
|
12
12
|
# app/{root}/audio/speakers/
|
|
13
13
|
# app/{root}/text/embedders/
|
|
14
|
-
# app/{root}/workflows/
|
|
15
14
|
#
|
|
16
15
|
# To:
|
|
17
16
|
# app/agents/
|
|
18
17
|
# app/agents/images/
|
|
19
18
|
# app/agents/audio/
|
|
20
19
|
# app/agents/embedders/
|
|
21
|
-
# app/workflows/
|
|
22
20
|
#
|
|
23
21
|
# Usage:
|
|
24
22
|
# rails generate ruby_llm_agents:migrate_structure
|
|
@@ -72,9 +70,6 @@ module RubyLlmAgents
|
|
|
72
70
|
"text/embedders" => "agents/embedders",
|
|
73
71
|
"text/moderators" => "agents/moderators",
|
|
74
72
|
|
|
75
|
-
# Workflows
|
|
76
|
-
"workflows" => "workflows",
|
|
77
|
-
|
|
78
73
|
# Tools
|
|
79
74
|
"tools" => "tools"
|
|
80
75
|
}.freeze
|
|
@@ -93,10 +88,7 @@ module RubyLlmAgents
|
|
|
93
88
|
|
|
94
89
|
# Text namespaces -> Embedders/Moderators
|
|
95
90
|
/\A(\w+)::Text::(\w+Embedder)\z/ => 'Embedders::\2',
|
|
96
|
-
/\A(\w+)::Text::(\w+Moderator)\z/ => 'Moderators::\2'
|
|
97
|
-
|
|
98
|
-
# Workflows (remove root namespace)
|
|
99
|
-
/\A(\w+)::(\w+Workflow)\z/ => '\2'
|
|
91
|
+
/\A(\w+)::Text::(\w+Moderator)\z/ => 'Moderators::\2'
|
|
100
92
|
}.freeze
|
|
101
93
|
|
|
102
94
|
def check_prerequisites
|
|
@@ -120,7 +112,7 @@ module RubyLlmAgents
|
|
|
120
112
|
say "=" * 60
|
|
121
113
|
say ""
|
|
122
114
|
say "Source: app/#{@source_root_dir}/"
|
|
123
|
-
say "Target: app/agents/
|
|
115
|
+
say "Target: app/agents/"
|
|
124
116
|
say ""
|
|
125
117
|
|
|
126
118
|
@files_to_migrate = []
|
|
@@ -274,7 +266,6 @@ module RubyLlmAgents
|
|
|
274
266
|
say " │ ├── audio/"
|
|
275
267
|
say " │ ├── embedders/"
|
|
276
268
|
say " │ └── moderators/"
|
|
277
|
-
say " └── workflows/"
|
|
278
269
|
say ""
|
|
279
270
|
say "Next steps:"
|
|
280
271
|
say " 1. Update class references in your code:"
|
|
@@ -327,7 +318,6 @@ module RubyLlmAgents
|
|
|
327
318
|
image/generators
|
|
328
319
|
audio/speakers
|
|
329
320
|
text/embedders
|
|
330
|
-
workflows
|
|
331
321
|
]
|
|
332
322
|
|
|
333
323
|
old_indicators.any? do |indicator|
|
|
@@ -38,7 +38,6 @@ module RubyLlmAgents
|
|
|
38
38
|
DIRECTORY_MAPPING = {
|
|
39
39
|
# Top-level under llm/
|
|
40
40
|
"agents" => { category: nil, type: "agents" },
|
|
41
|
-
"workflows" => { category: nil, type: "workflows" },
|
|
42
41
|
"tools" => { category: nil, type: "tools" },
|
|
43
42
|
|
|
44
43
|
# Audio group
|
|
@@ -173,7 +172,6 @@ module RubyLlmAgents
|
|
|
173
172
|
say " ├── text/"
|
|
174
173
|
say " │ ├── embedders/"
|
|
175
174
|
say " │ └── moderators/"
|
|
176
|
-
say " ├── workflows/"
|
|
177
175
|
say " └── tools/"
|
|
178
176
|
say ""
|
|
179
177
|
say "Namespaces have been updated to use #{root_namespace}::"
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Migration to add usage counter columns to tenants table
|
|
4
|
+
#
|
|
5
|
+
# These columns enable DB-based budget tracking with atomic SQL increments,
|
|
6
|
+
# replacing the previous cache-based counter approach.
|
|
7
|
+
#
|
|
8
|
+
# Run with: rails db:migrate
|
|
9
|
+
class AddUsageCountersToRubyLLMAgentsTenants < ActiveRecord::Migration<%= migration_version %>
|
|
10
|
+
def change
|
|
11
|
+
change_table :ruby_llm_agents_tenants, bulk: true do |t|
|
|
12
|
+
# Cost counters
|
|
13
|
+
t.decimal :daily_cost_spent, precision: 12, scale: 6, default: 0, null: false
|
|
14
|
+
t.decimal :monthly_cost_spent, precision: 12, scale: 6, default: 0, null: false
|
|
15
|
+
|
|
16
|
+
# Token counters
|
|
17
|
+
t.bigint :daily_tokens_used, default: 0, null: false
|
|
18
|
+
t.bigint :monthly_tokens_used, default: 0, null: false
|
|
19
|
+
|
|
20
|
+
# Execution counters
|
|
21
|
+
t.bigint :daily_executions_count, default: 0, null: false
|
|
22
|
+
t.bigint :monthly_executions_count, default: 0, null: false
|
|
23
|
+
|
|
24
|
+
# Error counters
|
|
25
|
+
t.bigint :daily_error_count, default: 0, null: false
|
|
26
|
+
t.bigint :monthly_error_count, default: 0, null: false
|
|
27
|
+
|
|
28
|
+
# Last execution metadata
|
|
29
|
+
t.datetime :last_execution_at
|
|
30
|
+
t.string :last_execution_status
|
|
31
|
+
|
|
32
|
+
# Period tracking (for lazy reset)
|
|
33
|
+
t.date :daily_reset_date
|
|
34
|
+
t.date :monthly_reset_date
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
@@ -14,7 +14,6 @@ class <%= class_name %>Agent < ApplicationAgent
|
|
|
14
14
|
|
|
15
15
|
model "<%= options[:model] %>"
|
|
16
16
|
temperature <%= options[:temperature] %>
|
|
17
|
-
version "1.0"
|
|
18
17
|
# timeout 30 # Per-request timeout in seconds (default: 60)
|
|
19
18
|
|
|
20
19
|
# ============================================
|
|
@@ -104,7 +103,7 @@ class <%= class_name %>Agent < ApplicationAgent
|
|
|
104
103
|
# end
|
|
105
104
|
|
|
106
105
|
# Custom metadata to include in execution logs
|
|
107
|
-
# def
|
|
106
|
+
# def metadata
|
|
108
107
|
# { custom_field: "value", request_id: params[:request_id] }
|
|
109
108
|
# end
|
|
110
109
|
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
class CreateRubyLLMAgentsExecutionDetails < ActiveRecord::Migration<%= migration_version %>
|
|
4
|
+
def change
|
|
5
|
+
create_table :ruby_llm_agents_execution_details do |t|
|
|
6
|
+
t.references :execution, null: false,
|
|
7
|
+
foreign_key: { to_table: :ruby_llm_agents_executions, on_delete: :cascade },
|
|
8
|
+
index: { unique: true }
|
|
9
|
+
|
|
10
|
+
t.text :error_message
|
|
11
|
+
t.text :system_prompt
|
|
12
|
+
t.text :user_prompt
|
|
13
|
+
t.json :response, default: {}
|
|
14
|
+
t.json :messages_summary, default: {}, null: false
|
|
15
|
+
t.json :tool_calls, default: [], null: false
|
|
16
|
+
t.json :attempts, default: [], null: false
|
|
17
|
+
t.json :fallback_chain
|
|
18
|
+
t.json :parameters, default: {}, null: false
|
|
19
|
+
t.string :routed_to
|
|
20
|
+
t.json :classification_result
|
|
21
|
+
t.datetime :cached_at
|
|
22
|
+
t.integer :cache_creation_tokens, default: 0
|
|
23
|
+
|
|
24
|
+
t.timestamps
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
@@ -49,6 +49,31 @@ class CreateRubyLLMAgentsTenants < ActiveRecord::Migration<%= migration_version
|
|
|
49
49
|
# Status (for soft-delete/disable)
|
|
50
50
|
t.boolean :active, default: true
|
|
51
51
|
|
|
52
|
+
# Usage counter columns (DB-based budget tracking)
|
|
53
|
+
# Cost counters
|
|
54
|
+
t.decimal :daily_cost_spent, precision: 12, scale: 6, default: 0, null: false
|
|
55
|
+
t.decimal :monthly_cost_spent, precision: 12, scale: 6, default: 0, null: false
|
|
56
|
+
|
|
57
|
+
# Token counters
|
|
58
|
+
t.bigint :daily_tokens_used, default: 0, null: false
|
|
59
|
+
t.bigint :monthly_tokens_used, default: 0, null: false
|
|
60
|
+
|
|
61
|
+
# Execution counters
|
|
62
|
+
t.bigint :daily_executions_count, default: 0, null: false
|
|
63
|
+
t.bigint :monthly_executions_count, default: 0, null: false
|
|
64
|
+
|
|
65
|
+
# Error counters
|
|
66
|
+
t.bigint :daily_error_count, default: 0, null: false
|
|
67
|
+
t.bigint :monthly_error_count, default: 0, null: false
|
|
68
|
+
|
|
69
|
+
# Last execution metadata
|
|
70
|
+
t.datetime :last_execution_at
|
|
71
|
+
t.string :last_execution_status
|
|
72
|
+
|
|
73
|
+
# Period tracking (for lazy reset)
|
|
74
|
+
t.date :daily_reset_date
|
|
75
|
+
t.date :monthly_reset_date
|
|
76
|
+
|
|
52
77
|
# Extensible metadata (JSON)
|
|
53
78
|
t.json :metadata, null: false, default: {}
|
|
54
79
|
|
|
@@ -5,6 +5,30 @@
|
|
|
5
5
|
# For more information, see: https://github.com/adham90/ruby_llm-agents
|
|
6
6
|
|
|
7
7
|
RubyLLM::Agents.configure do |config|
|
|
8
|
+
# ============================================
|
|
9
|
+
# LLM Provider API Keys
|
|
10
|
+
# ============================================
|
|
11
|
+
# Configure at least one provider. Set these in your environment
|
|
12
|
+
# or replace ENV[] calls with your keys directly.
|
|
13
|
+
|
|
14
|
+
# config.openai_api_key = ENV["OPENAI_API_KEY"]
|
|
15
|
+
# config.anthropic_api_key = ENV["ANTHROPIC_API_KEY"]
|
|
16
|
+
# config.gemini_api_key = ENV["GOOGLE_API_KEY"]
|
|
17
|
+
|
|
18
|
+
# Additional providers:
|
|
19
|
+
# config.deepseek_api_key = ENV["DEEPSEEK_API_KEY"]
|
|
20
|
+
# config.openrouter_api_key = ENV["OPENROUTER_API_KEY"]
|
|
21
|
+
# config.mistral_api_key = ENV["MISTRAL_API_KEY"]
|
|
22
|
+
# config.xai_api_key = ENV["XAI_API_KEY"]
|
|
23
|
+
|
|
24
|
+
# Custom endpoints (e.g., Azure OpenAI, local Ollama):
|
|
25
|
+
# config.openai_api_base = "https://your-resource.openai.azure.com"
|
|
26
|
+
# config.ollama_api_base = "http://localhost:11434"
|
|
27
|
+
|
|
28
|
+
# Connection settings:
|
|
29
|
+
# config.request_timeout = 120
|
|
30
|
+
# config.max_retries = 3
|
|
31
|
+
|
|
8
32
|
# ============================================
|
|
9
33
|
# Model Defaults
|
|
10
34
|
# ============================================
|
|
@@ -130,22 +154,19 @@ RubyLLM::Agents.configure do |config|
|
|
|
130
154
|
# Governance - Alerts
|
|
131
155
|
# ============================================
|
|
132
156
|
|
|
133
|
-
# Alert
|
|
134
|
-
#
|
|
135
|
-
# - webhook_url: Generic webhook URL (receives JSON POST)
|
|
136
|
-
# - on_events: Events to trigger alerts
|
|
157
|
+
# Alert handler for governance events
|
|
158
|
+
# Receives (event, payload) when important events occur:
|
|
137
159
|
# - :budget_soft_cap - Soft budget limit reached
|
|
138
160
|
# - :budget_hard_cap - Hard budget limit exceeded
|
|
139
161
|
# - :breaker_open - Circuit breaker opened
|
|
140
162
|
# - :agent_anomaly - Cost/duration anomaly detected
|
|
141
|
-
#
|
|
142
|
-
#
|
|
143
|
-
#
|
|
144
|
-
#
|
|
145
|
-
#
|
|
146
|
-
#
|
|
147
|
-
#
|
|
148
|
-
# }
|
|
163
|
+
# config.on_alert = ->(event, payload) {
|
|
164
|
+
# case event
|
|
165
|
+
# when :budget_hard_cap
|
|
166
|
+
# Slack::Notifier.new(ENV["SLACK_WEBHOOK"]).ping("Budget exceeded: #{payload[:total_cost]}")
|
|
167
|
+
# when :breaker_open
|
|
168
|
+
# Rails.logger.error("[Alert] Circuit breaker opened for #{payload[:agent_type]}")
|
|
169
|
+
# end
|
|
149
170
|
# }
|
|
150
171
|
|
|
151
172
|
# ============================================
|
|
@@ -5,109 +5,79 @@ class CreateRubyLLMAgentsExecutions < ActiveRecord::Migration<%= migration_versi
|
|
|
5
5
|
create_table :ruby_llm_agents_executions do |t|
|
|
6
6
|
# Agent identification
|
|
7
7
|
t.string :agent_type, null: false
|
|
8
|
-
t.string :
|
|
8
|
+
t.string :execution_type, null: false, default: "chat"
|
|
9
9
|
|
|
10
10
|
# Model configuration
|
|
11
11
|
t.string :model_id, null: false
|
|
12
12
|
t.string :model_provider
|
|
13
13
|
t.decimal :temperature, precision: 3, scale: 2
|
|
14
|
+
t.string :chosen_model_id
|
|
15
|
+
|
|
16
|
+
# Status
|
|
17
|
+
t.string :status, null: false, default: "running"
|
|
18
|
+
t.string :finish_reason
|
|
19
|
+
t.string :error_class
|
|
14
20
|
|
|
15
21
|
# Timing
|
|
16
22
|
t.datetime :started_at, null: false
|
|
17
23
|
t.datetime :completed_at
|
|
18
24
|
t.integer :duration_ms
|
|
19
25
|
|
|
20
|
-
# Streaming and finish
|
|
21
|
-
t.boolean :streaming, default: false
|
|
22
|
-
t.integer :time_to_first_token_ms
|
|
23
|
-
t.string :finish_reason
|
|
24
|
-
|
|
25
|
-
# Distributed tracing
|
|
26
|
-
t.string :request_id
|
|
27
|
-
t.string :trace_id
|
|
28
|
-
t.string :span_id
|
|
29
|
-
t.bigint :parent_execution_id
|
|
30
|
-
t.bigint :root_execution_id
|
|
31
|
-
|
|
32
|
-
# Routing and retries
|
|
33
|
-
t.string :fallback_reason
|
|
34
|
-
t.boolean :retryable
|
|
35
|
-
t.boolean :rate_limited
|
|
36
|
-
|
|
37
|
-
# Caching
|
|
38
|
-
t.boolean :cache_hit, default: false
|
|
39
|
-
t.string :response_cache_key
|
|
40
|
-
t.datetime :cached_at
|
|
41
|
-
|
|
42
|
-
# Status
|
|
43
|
-
t.string :status, default: "success", null: false
|
|
44
|
-
|
|
45
26
|
# Token usage
|
|
46
|
-
t.integer :input_tokens
|
|
47
|
-
t.integer :output_tokens
|
|
48
|
-
t.integer :total_tokens
|
|
27
|
+
t.integer :input_tokens, default: 0
|
|
28
|
+
t.integer :output_tokens, default: 0
|
|
29
|
+
t.integer :total_tokens, default: 0
|
|
49
30
|
t.integer :cached_tokens, default: 0
|
|
50
|
-
t.integer :cache_creation_tokens, default: 0
|
|
51
31
|
|
|
52
32
|
# Costs (in dollars, 6 decimal precision)
|
|
53
33
|
t.decimal :input_cost, precision: 12, scale: 6
|
|
54
34
|
t.decimal :output_cost, precision: 12, scale: 6
|
|
55
35
|
t.decimal :total_cost, precision: 12, scale: 6
|
|
56
36
|
|
|
57
|
-
#
|
|
58
|
-
t.
|
|
59
|
-
t.json :response, default: {}
|
|
60
|
-
t.json :metadata, null: false, default: {}
|
|
37
|
+
# Caching
|
|
38
|
+
t.boolean :cache_hit, default: false
|
|
61
39
|
|
|
62
|
-
#
|
|
63
|
-
t.
|
|
64
|
-
|
|
40
|
+
# Streaming
|
|
41
|
+
t.boolean :streaming, default: false
|
|
42
|
+
|
|
43
|
+
# Retry / Fallback
|
|
44
|
+
t.integer :attempts_count, default: 1, null: false
|
|
45
|
+
|
|
46
|
+
# Tool calls
|
|
47
|
+
t.integer :tool_calls_count, default: 0, null: false
|
|
48
|
+
|
|
49
|
+
# Distributed tracing
|
|
50
|
+
t.string :trace_id
|
|
51
|
+
t.string :request_id
|
|
52
|
+
|
|
53
|
+
# Execution hierarchy (self-join)
|
|
54
|
+
t.bigint :parent_execution_id
|
|
55
|
+
t.bigint :root_execution_id
|
|
65
56
|
|
|
66
|
-
#
|
|
67
|
-
t.
|
|
68
|
-
t.text :user_prompt
|
|
57
|
+
# Multi-tenancy
|
|
58
|
+
t.string :tenant_id
|
|
69
59
|
|
|
70
|
-
#
|
|
71
|
-
t.
|
|
72
|
-
t.integer :tool_calls_count, null: false, default: 0
|
|
60
|
+
# Conversation context
|
|
61
|
+
t.integer :messages_count, default: 0, null: false
|
|
73
62
|
|
|
74
|
-
#
|
|
75
|
-
t.
|
|
76
|
-
t.string :workflow_type
|
|
77
|
-
t.string :workflow_step
|
|
78
|
-
t.string :routed_to
|
|
79
|
-
t.json :classification_result
|
|
63
|
+
# Flexible storage (niche fields, trace context, custom tags)
|
|
64
|
+
t.json :metadata, null: false, default: {}
|
|
80
65
|
|
|
81
66
|
t.timestamps
|
|
82
67
|
end
|
|
83
68
|
|
|
84
|
-
# Indexes
|
|
85
|
-
add_index :ruby_llm_agents_executions, :agent_type
|
|
86
|
-
add_index :ruby_llm_agents_executions, :status
|
|
87
|
-
add_index :ruby_llm_agents_executions, :created_at
|
|
69
|
+
# Indexes: only what's actually queried
|
|
88
70
|
add_index :ruby_llm_agents_executions, [:agent_type, :created_at]
|
|
89
71
|
add_index :ruby_llm_agents_executions, [:agent_type, :status]
|
|
90
|
-
add_index :ruby_llm_agents_executions,
|
|
91
|
-
add_index :ruby_llm_agents_executions, :
|
|
92
|
-
add_index :ruby_llm_agents_executions, :
|
|
93
|
-
|
|
94
|
-
# Tracing indexes
|
|
95
|
-
add_index :ruby_llm_agents_executions, :request_id
|
|
72
|
+
add_index :ruby_llm_agents_executions, :status
|
|
73
|
+
add_index :ruby_llm_agents_executions, :created_at
|
|
74
|
+
add_index :ruby_llm_agents_executions, [:tenant_id, :created_at]
|
|
75
|
+
add_index :ruby_llm_agents_executions, [:tenant_id, :status]
|
|
96
76
|
add_index :ruby_llm_agents_executions, :trace_id
|
|
77
|
+
add_index :ruby_llm_agents_executions, :request_id
|
|
97
78
|
add_index :ruby_llm_agents_executions, :parent_execution_id
|
|
98
79
|
add_index :ruby_llm_agents_executions, :root_execution_id
|
|
99
80
|
|
|
100
|
-
# Caching index
|
|
101
|
-
add_index :ruby_llm_agents_executions, :response_cache_key
|
|
102
|
-
|
|
103
|
-
# Tool calls index
|
|
104
|
-
add_index :ruby_llm_agents_executions, :tool_calls_count
|
|
105
|
-
|
|
106
|
-
# Workflow indexes
|
|
107
|
-
add_index :ruby_llm_agents_executions, :workflow_id
|
|
108
|
-
add_index :ruby_llm_agents_executions, :workflow_type
|
|
109
|
-
add_index :ruby_llm_agents_executions, [:workflow_id, :workflow_step]
|
|
110
|
-
|
|
111
81
|
# Foreign keys for execution hierarchy
|
|
112
82
|
add_foreign_key :ruby_llm_agents_executions, :ruby_llm_agents_executions,
|
|
113
83
|
column: :parent_execution_id, on_delete: :nullify
|
|
@@ -116,7 +86,6 @@ class CreateRubyLLMAgentsExecutions < ActiveRecord::Migration<%= migration_versi
|
|
|
116
86
|
|
|
117
87
|
# GIN indexes for JSONB columns (PostgreSQL only)
|
|
118
88
|
# Uncomment if using PostgreSQL:
|
|
119
|
-
# add_index :ruby_llm_agents_executions, :parameters, using: :gin
|
|
120
89
|
# add_index :ruby_llm_agents_executions, :metadata, using: :gin
|
|
121
90
|
end
|
|
122
91
|
end
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Migration to remove agent_version column (deprecated in favor of content-based cache keys)
|
|
4
|
+
class RemoveAgentVersionFromRubyLLMAgentsExecutions < ActiveRecord::Migration<%= migration_version %>
|
|
5
|
+
def change
|
|
6
|
+
# Remove the composite index first (if it exists)
|
|
7
|
+
remove_index :ruby_llm_agents_executions, [:agent_type, :agent_version],
|
|
8
|
+
if_exists: true
|
|
9
|
+
|
|
10
|
+
# Remove the deprecated column
|
|
11
|
+
remove_column :ruby_llm_agents_executions, :agent_version, :string, default: "1.0"
|
|
12
|
+
end
|
|
13
|
+
end
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Migration to remove workflow columns (workflows feature removed)
|
|
4
|
+
class RemoveWorkflowColumnsFromRubyLLMAgentsExecutions < ActiveRecord::Migration<%= migration_version %>
|
|
5
|
+
def change
|
|
6
|
+
# Remove indexes first
|
|
7
|
+
remove_index :ruby_llm_agents_executions, [:workflow_id, :workflow_step],
|
|
8
|
+
if_exists: true
|
|
9
|
+
remove_index :ruby_llm_agents_executions, :workflow_id,
|
|
10
|
+
if_exists: true
|
|
11
|
+
remove_index :ruby_llm_agents_executions, :workflow_type,
|
|
12
|
+
if_exists: true
|
|
13
|
+
|
|
14
|
+
# Remove the columns
|
|
15
|
+
remove_column :ruby_llm_agents_executions, :workflow_id, :string
|
|
16
|
+
remove_column :ruby_llm_agents_executions, :workflow_type, :string
|
|
17
|
+
remove_column :ruby_llm_agents_executions, :workflow_step, :string
|
|
18
|
+
end
|
|
19
|
+
end
|
|
@@ -15,7 +15,6 @@ class MyAgent < ApplicationAgent
|
|
|
15
15
|
# Configuration
|
|
16
16
|
model "gpt-4o"
|
|
17
17
|
temperature 0.0
|
|
18
|
-
version "1.0"
|
|
19
18
|
|
|
20
19
|
# Parameters
|
|
21
20
|
param :query, required: true
|
|
@@ -60,7 +59,6 @@ app/agents/
|
|
|
60
59
|
|--------|-------------|---------|
|
|
61
60
|
| `model` | LLM model to use | `model "gpt-4o"` |
|
|
62
61
|
| `temperature` | Response randomness (0.0-2.0) | `temperature 0.7` |
|
|
63
|
-
| `version` | Cache invalidation version | `version "2.0"` |
|
|
64
62
|
| `timeout` | Request timeout in seconds | `timeout 30` |
|
|
65
63
|
| `description` | Human-readable description | `description "Searches documents"` |
|
|
66
64
|
|
|
@@ -183,10 +181,10 @@ def cache_key_data
|
|
|
183
181
|
end
|
|
184
182
|
```
|
|
185
183
|
|
|
186
|
-
### `
|
|
184
|
+
### `metadata`
|
|
187
185
|
Add custom data to execution logs:
|
|
188
186
|
```ruby
|
|
189
|
-
def
|
|
187
|
+
def metadata
|
|
190
188
|
{ request_id: params[:request_id] }
|
|
191
189
|
end
|
|
192
190
|
```
|
|
@@ -129,7 +129,6 @@ result = Images::SmartPipeline.call(
|
|
|
129
129
|
module Images
|
|
130
130
|
class EcommercePipeline < ApplicationImagePipeline
|
|
131
131
|
description "Generate and process product images"
|
|
132
|
-
version "1.0"
|
|
133
132
|
|
|
134
133
|
step :generate, generator: ProductGenerator
|
|
135
134
|
step :upscale, upscaler: PhotoUpscaler, scale: 2
|