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
@@ -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. Run migrations: rails db:migrate"
117
- say " 2. Generate an agent: rails generate ruby_llm_agents:agent MyAgent query:required"
118
- say " 3. Access the dashboard at: /agents"
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/ and app/workflows/"
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 execution_metadata
106
+ # def metadata
108
107
  # { custom_field: "value", request_id: params[:request_id] }
109
108
  # end
110
109
 
@@ -63,7 +63,7 @@ class ApplicationAgent < RubyLLM::Agents::Base
63
63
  # end
64
64
 
65
65
  # Example: Common metadata
66
- # def execution_metadata
66
+ # def metadata
67
67
  # { app_version: Rails.application.config.version }
68
68
  # end
69
69
  end
@@ -47,7 +47,6 @@ module Images
47
47
  #
48
48
  # METADATA:
49
49
  # ---------
50
- # version "1.0" # Version identifier (affects cache key)
51
50
  # description "My pipeline" # Human-readable description
52
51
  #
53
52
  # ============================================================================
@@ -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
 
@@ -37,7 +37,6 @@ module Images
37
37
  <% end -%>
38
38
 
39
39
  description "<%= class_name %> image processing pipeline"
40
- version "1.0"
41
40
  <%- if class_name.include?("::") -%>
42
41
  <%- class_name.split("::").length.times do |i| -%>
43
42
  <%= " " * (class_name.split("::").length - i) %>end
@@ -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 notifications for important events
134
- # - slack_webhook_url: Slack incoming webhook URL
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
- # - custom: Lambda for custom handling
142
- # config.alerts = {
143
- # slack_webhook_url: ENV["SLACK_AGENTS_WEBHOOK"],
144
- # webhook_url: ENV["AGENTS_ALERT_WEBHOOK"],
145
- # on_events: [:budget_soft_cap, :budget_hard_cap, :breaker_open],
146
- # custom: ->(event, payload) {
147
- # Rails.logger.info("[AgentAlert] #{event}: #{payload}")
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 :agent_version, default: "1.0"
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
- # Data (JSON - works with PostgreSQL, MySQL, SQLite3)
58
- t.json :parameters, null: false, default: {}
59
- t.json :response, default: {}
60
- t.json :metadata, null: false, default: {}
37
+ # Caching
38
+ t.boolean :cache_hit, default: false
61
39
 
62
- # Error tracking
63
- t.string :error_class
64
- t.text :error_message
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
- # Prompts (for history/changelog)
67
- t.text :system_prompt
68
- t.text :user_prompt
57
+ # Multi-tenancy
58
+ t.string :tenant_id
69
59
 
70
- # Tool calls tracking
71
- t.json :tool_calls, null: false, default: []
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
- # Workflow orchestration
75
- t.string :workflow_id
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 for common queries
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, [:agent_type, :agent_version]
91
- add_index :ruby_llm_agents_executions, :duration_ms
92
- add_index :ruby_llm_agents_executions, :total_cost
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
- ### `execution_metadata`
184
+ ### `metadata`
187
185
  Add custom data to execution logs:
188
186
  ```ruby
189
- def execution_metadata
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