ruby_llm-agents 1.1.0 → 1.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/app/models/ruby_llm/agents/tenant/budgetable.rb +277 -0
- data/app/models/ruby_llm/agents/tenant/configurable.rb +135 -0
- data/app/models/ruby_llm/agents/tenant/trackable.rb +310 -0
- data/app/models/ruby_llm/agents/tenant.rb +146 -0
- data/app/models/ruby_llm/agents/tenant_budget.rb +12 -253
- data/app/views/layouts/ruby_llm/agents/application.html.erb +1 -1
- data/app/views/ruby_llm/agents/agents/_empty_state.html.erb +22 -19
- data/app/views/ruby_llm/agents/workflows/_empty_state.html.erb +22 -0
- data/app/views/ruby_llm/agents/workflows/index.html.erb +1 -1
- data/lib/generators/ruby_llm_agents/multi_tenancy_generator.rb +42 -22
- data/lib/generators/ruby_llm_agents/templates/add_tenant_to_executions_migration.rb.tt +13 -2
- data/lib/generators/ruby_llm_agents/templates/create_tenant_budgets_migration.rb.tt +11 -0
- data/lib/generators/ruby_llm_agents/templates/create_tenants_migration.rb.tt +72 -0
- data/lib/generators/ruby_llm_agents/templates/rename_tenant_budgets_to_tenants_migration.rb.tt +34 -0
- data/lib/generators/ruby_llm_agents/upgrade_generator.rb +26 -0
- data/lib/ruby_llm/agents/core/configuration.rb +18 -26
- data/lib/ruby_llm/agents/core/llm_tenant.rb +60 -60
- data/lib/ruby_llm/agents/core/version.rb +1 -1
- data/lib/ruby_llm/agents/infrastructure/budget/config_resolver.rb +4 -2
- data/lib/ruby_llm/agents/rails/engine.rb +22 -28
- metadata +8 -1
|
@@ -147,6 +147,26 @@ module RubyLlmAgents
|
|
|
147
147
|
)
|
|
148
148
|
end
|
|
149
149
|
|
|
150
|
+
def create_rename_tenant_budgets_migration
|
|
151
|
+
# Skip if already using new table name
|
|
152
|
+
if table_exists?(:ruby_llm_agents_tenants)
|
|
153
|
+
say_status :skip, "ruby_llm_agents_tenants table already exists", :yellow
|
|
154
|
+
return
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
# Only run if old table exists (needs upgrade)
|
|
158
|
+
unless table_exists?(:ruby_llm_agents_tenant_budgets)
|
|
159
|
+
say_status :skip, "No tenant_budgets table to upgrade", :yellow
|
|
160
|
+
return
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
say_status :upgrade, "Renaming tenant_budgets to tenants", :blue
|
|
164
|
+
migration_template(
|
|
165
|
+
"rename_tenant_budgets_to_tenants_migration.rb.tt",
|
|
166
|
+
File.join(db_migrate_path, "rename_tenant_budgets_to_tenants.rb")
|
|
167
|
+
)
|
|
168
|
+
end
|
|
169
|
+
|
|
150
170
|
def migrate_agents_directory
|
|
151
171
|
root_dir = RubyLLM::Agents.configuration.root_directory
|
|
152
172
|
namespace = RubyLLM::Agents.configuration.root_namespace
|
|
@@ -211,6 +231,12 @@ module RubyLlmAgents
|
|
|
211
231
|
false
|
|
212
232
|
end
|
|
213
233
|
|
|
234
|
+
def table_exists?(table)
|
|
235
|
+
ActiveRecord::Base.connection.table_exists?(table)
|
|
236
|
+
rescue StandardError
|
|
237
|
+
false
|
|
238
|
+
end
|
|
239
|
+
|
|
214
240
|
def migrate_directory(old_dir, new_dir, namespace)
|
|
215
241
|
source = Rails.root.join("app", old_dir)
|
|
216
242
|
destination = Rails.root.join("app", new_dir)
|
|
@@ -353,21 +353,21 @@ module RubyLLM
|
|
|
353
353
|
# config.async_max_concurrency = 20
|
|
354
354
|
|
|
355
355
|
# @!attribute [rw] root_directory
|
|
356
|
-
# The root directory name under app/ for all
|
|
356
|
+
# The root directory name under app/ for all agent components.
|
|
357
357
|
# This allows customization of the directory structure.
|
|
358
|
-
# @return [String] Directory name (default: "
|
|
358
|
+
# @return [String] Directory name (default: "agents")
|
|
359
359
|
# @example
|
|
360
|
-
# config.root_directory = "ai" # Creates app/ai/ instead of app/
|
|
360
|
+
# config.root_directory = "ai" # Creates app/ai/ instead of app/agents/
|
|
361
361
|
|
|
362
362
|
# @!attribute [rw] root_namespace
|
|
363
|
-
# The root namespace for all
|
|
364
|
-
#
|
|
365
|
-
# Set to nil or "" to use no namespace
|
|
366
|
-
# @return [String, nil] Namespace (default:
|
|
363
|
+
# The root namespace for all agent component classes.
|
|
364
|
+
# When set, subdirectory namespaces are prefixed with this.
|
|
365
|
+
# Set to nil or "" to use no root namespace.
|
|
366
|
+
# @return [String, nil] Namespace (default: nil)
|
|
367
367
|
# @example Custom namespace
|
|
368
|
-
# config.root_namespace = "AI" #
|
|
369
|
-
# @example No namespace (
|
|
370
|
-
# config.root_namespace = nil #
|
|
368
|
+
# config.root_namespace = "AI" # app/agents/embedders -> AI::Embedders
|
|
369
|
+
# @example No namespace (default)
|
|
370
|
+
# config.root_namespace = nil # app/agents/embedders -> Embedders
|
|
371
371
|
|
|
372
372
|
# Attributes without validation (simple accessors)
|
|
373
373
|
attr_accessor :default_model,
|
|
@@ -821,26 +821,18 @@ module RubyLLM
|
|
|
821
821
|
|
|
822
822
|
# Returns the full namespace for a given category
|
|
823
823
|
#
|
|
824
|
-
# @param category [Symbol, nil] Category (
|
|
824
|
+
# @param category [Symbol, String, nil] Category (e.g., :embedders, :images, or nil for root)
|
|
825
825
|
# @return [String, nil] Full namespace string, or nil if no namespace configured
|
|
826
|
-
# @example With root_namespace = "
|
|
827
|
-
# namespace_for(:
|
|
828
|
-
# namespace_for(nil)
|
|
826
|
+
# @example With root_namespace = "AI"
|
|
827
|
+
# namespace_for(:embedders) #=> "AI::Embedders"
|
|
828
|
+
# namespace_for(nil) #=> "AI"
|
|
829
829
|
# @example With no namespace (root_namespace = nil)
|
|
830
|
-
# namespace_for(:
|
|
831
|
-
# namespace_for(nil)
|
|
830
|
+
# namespace_for(:embedders) #=> "Embedders"
|
|
831
|
+
# namespace_for(nil) #=> nil
|
|
832
832
|
def namespace_for(category = nil)
|
|
833
|
-
category_namespace =
|
|
834
|
-
when :images then "Images"
|
|
835
|
-
when :audio then "Audio"
|
|
836
|
-
when :embedders then "Embedders"
|
|
837
|
-
when :moderators then "Moderators"
|
|
838
|
-
when :workflows then "Workflows"
|
|
839
|
-
when :text then "Text"
|
|
840
|
-
when :image then "Image"
|
|
841
|
-
end
|
|
833
|
+
category_namespace = category&.to_s&.camelize
|
|
842
834
|
|
|
843
|
-
if root_namespace
|
|
835
|
+
if root_namespace.present?
|
|
844
836
|
category_namespace ? "#{root_namespace}::#{category_namespace}" : root_namespace
|
|
845
837
|
else
|
|
846
838
|
category_namespace
|
|
@@ -12,21 +12,25 @@ module RubyLLM
|
|
|
12
12
|
#
|
|
13
13
|
# @example Basic usage
|
|
14
14
|
# class Organization < ApplicationRecord
|
|
15
|
+
# include RubyLLM::Agents::LLMTenant
|
|
15
16
|
# llm_tenant
|
|
16
17
|
# end
|
|
17
18
|
#
|
|
18
19
|
# @example With custom ID method
|
|
19
20
|
# class Organization < ApplicationRecord
|
|
21
|
+
# include RubyLLM::Agents::LLMTenant
|
|
20
22
|
# llm_tenant id: :slug
|
|
21
23
|
# end
|
|
22
24
|
#
|
|
23
25
|
# @example With auto-created budget
|
|
24
26
|
# class Organization < ApplicationRecord
|
|
27
|
+
# include RubyLLM::Agents::LLMTenant
|
|
25
28
|
# llm_tenant id: :slug, budget: true
|
|
26
29
|
# end
|
|
27
30
|
#
|
|
28
31
|
# @example With limits (auto-creates budget)
|
|
29
32
|
# class Organization < ApplicationRecord
|
|
33
|
+
# include RubyLLM::Agents::LLMTenant
|
|
30
34
|
# llm_tenant(
|
|
31
35
|
# id: :slug,
|
|
32
36
|
# name: :company_name,
|
|
@@ -41,6 +45,7 @@ module RubyLLM
|
|
|
41
45
|
#
|
|
42
46
|
# @example With API keys from model columns/methods
|
|
43
47
|
# class Organization < ApplicationRecord
|
|
48
|
+
# include RubyLLM::Agents::LLMTenant
|
|
44
49
|
# encrypts :openai_api_key, :anthropic_api_key # Rails 7+ encryption
|
|
45
50
|
#
|
|
46
51
|
# llm_tenant(
|
|
@@ -57,7 +62,7 @@ module RubyLLM
|
|
|
57
62
|
# end
|
|
58
63
|
# end
|
|
59
64
|
#
|
|
60
|
-
# @see RubyLLM::Agents::
|
|
65
|
+
# @see RubyLLM::Agents::Tenant
|
|
61
66
|
# @api public
|
|
62
67
|
module LLMTenant
|
|
63
68
|
extend ActiveSupport::Concern
|
|
@@ -69,12 +74,16 @@ module RubyLLM
|
|
|
69
74
|
as: :tenant_record,
|
|
70
75
|
dependent: :nullify
|
|
71
76
|
|
|
72
|
-
#
|
|
73
|
-
has_one :
|
|
74
|
-
class_name: "RubyLLM::Agents::
|
|
77
|
+
# Link to gem's Tenant model (new name)
|
|
78
|
+
has_one :llm_tenant_record,
|
|
79
|
+
class_name: "RubyLLM::Agents::Tenant",
|
|
75
80
|
as: :tenant_record,
|
|
76
81
|
dependent: :destroy
|
|
77
82
|
|
|
83
|
+
# Backward compatible alias (llm_budget points to same Tenant record)
|
|
84
|
+
# @deprecated Use llm_tenant_record instead
|
|
85
|
+
alias_method :llm_budget_association, :llm_tenant_record
|
|
86
|
+
|
|
78
87
|
# Store options at class level
|
|
79
88
|
class_attribute :llm_tenant_options, default: {}
|
|
80
89
|
end
|
|
@@ -84,7 +93,7 @@ module RubyLLM
|
|
|
84
93
|
#
|
|
85
94
|
# @param id [Symbol] Method to call for tenant_id string (default: :id)
|
|
86
95
|
# @param name [Symbol] Method for budget display name (default: :to_s)
|
|
87
|
-
# @param budget [Boolean] Auto-create
|
|
96
|
+
# @param budget [Boolean] Auto-create Tenant record on model creation (default: false)
|
|
88
97
|
# @param limits [Hash] Default budget limits (implies budget: true)
|
|
89
98
|
# @param enforcement [Symbol] Budget enforcement mode (:none, :soft, :hard)
|
|
90
99
|
# @param inherit_global [Boolean] Inherit from global config (default: true)
|
|
@@ -101,8 +110,8 @@ module RubyLLM
|
|
|
101
110
|
api_keys: api_keys
|
|
102
111
|
}
|
|
103
112
|
|
|
104
|
-
# Auto-create
|
|
105
|
-
after_create :
|
|
113
|
+
# Auto-create tenant record callback
|
|
114
|
+
after_create :create_default_llm_tenant if llm_tenant_options[:budget]
|
|
106
115
|
end
|
|
107
116
|
|
|
108
117
|
private
|
|
@@ -152,13 +161,42 @@ module RubyLLM
|
|
|
152
161
|
end.compact
|
|
153
162
|
end
|
|
154
163
|
|
|
164
|
+
# Returns or builds the associated Tenant record
|
|
165
|
+
#
|
|
166
|
+
# @return [Tenant] The tenant record
|
|
167
|
+
def llm_tenant
|
|
168
|
+
llm_tenant_record || build_llm_tenant_record(tenant_id: llm_tenant_id)
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
# Backward compatible alias for llm_tenant
|
|
172
|
+
# @deprecated Use llm_tenant instead
|
|
173
|
+
alias_method :llm_budget, :llm_tenant
|
|
174
|
+
|
|
175
|
+
# Configure tenant with a block
|
|
176
|
+
#
|
|
177
|
+
# @yield [tenant] The tenant to configure
|
|
178
|
+
# @return [Tenant] The saved tenant
|
|
179
|
+
def llm_configure(&block)
|
|
180
|
+
tenant = llm_tenant
|
|
181
|
+
yield(tenant) if block_given?
|
|
182
|
+
tenant.save!
|
|
183
|
+
tenant
|
|
184
|
+
end
|
|
185
|
+
|
|
186
|
+
# Backward compatible alias
|
|
187
|
+
# @deprecated Use llm_configure instead
|
|
188
|
+
alias_method :llm_configure_budget, :llm_configure
|
|
189
|
+
|
|
190
|
+
# Tracking methods using llm_executions association
|
|
191
|
+
# These query executions via the polymorphic tenant_record association
|
|
192
|
+
|
|
155
193
|
# Returns cost for a given period
|
|
156
194
|
#
|
|
157
195
|
# @param period [Symbol, Range, nil] Time period (:today, :this_month, etc.)
|
|
158
196
|
# @return [BigDecimal] Total cost
|
|
159
197
|
def llm_cost(period: nil)
|
|
160
198
|
scope = llm_executions
|
|
161
|
-
scope =
|
|
199
|
+
scope = apply_llm_period_scope(scope, period) if period
|
|
162
200
|
scope.sum(:total_cost) || 0
|
|
163
201
|
end
|
|
164
202
|
|
|
@@ -182,7 +220,7 @@ module RubyLLM
|
|
|
182
220
|
# @return [Integer] Total tokens
|
|
183
221
|
def llm_tokens(period: nil)
|
|
184
222
|
scope = llm_executions
|
|
185
|
-
scope =
|
|
223
|
+
scope = apply_llm_period_scope(scope, period) if period
|
|
186
224
|
scope.sum(:total_tokens) || 0
|
|
187
225
|
end
|
|
188
226
|
|
|
@@ -206,7 +244,7 @@ module RubyLLM
|
|
|
206
244
|
# @return [Integer] Execution count
|
|
207
245
|
def llm_execution_count(period: nil)
|
|
208
246
|
scope = llm_executions
|
|
209
|
-
scope =
|
|
247
|
+
scope = apply_llm_period_scope(scope, period) if period
|
|
210
248
|
scope.count
|
|
211
249
|
end
|
|
212
250
|
|
|
@@ -237,29 +275,13 @@ module RubyLLM
|
|
|
237
275
|
}
|
|
238
276
|
end
|
|
239
277
|
|
|
240
|
-
#
|
|
241
|
-
#
|
|
242
|
-
# @return [TenantBudget] The budget record
|
|
243
|
-
def llm_budget
|
|
244
|
-
super || build_llm_budget(tenant_id: llm_tenant_id)
|
|
245
|
-
end
|
|
246
|
-
|
|
247
|
-
# Configure budget with a block
|
|
248
|
-
#
|
|
249
|
-
# @yield [budget] The budget to configure
|
|
250
|
-
# @return [TenantBudget] The saved budget
|
|
251
|
-
def llm_configure_budget
|
|
252
|
-
budget = llm_budget
|
|
253
|
-
yield(budget) if block_given?
|
|
254
|
-
budget.save!
|
|
255
|
-
budget
|
|
256
|
-
end
|
|
278
|
+
# Delegate budget methods to the Tenant record
|
|
257
279
|
|
|
258
280
|
# Returns the budget status from BudgetTracker
|
|
259
281
|
#
|
|
260
282
|
# @return [Hash] Budget status
|
|
261
283
|
def llm_budget_status
|
|
262
|
-
|
|
284
|
+
llm_tenant.budget_status
|
|
263
285
|
end
|
|
264
286
|
|
|
265
287
|
# Checks if within budget for a given limit type
|
|
@@ -267,11 +289,7 @@ module RubyLLM
|
|
|
267
289
|
# @param type [Symbol] Limit type (:daily_cost, :monthly_cost, :daily_tokens, etc.)
|
|
268
290
|
# @return [Boolean] true if within budget
|
|
269
291
|
def llm_within_budget?(type: :daily_cost)
|
|
270
|
-
|
|
271
|
-
return true unless status[:enabled]
|
|
272
|
-
|
|
273
|
-
key = budget_status_key(type)
|
|
274
|
-
status.dig(key, :percentage_used).to_f < 100
|
|
292
|
+
llm_tenant.within_budget?(type: type)
|
|
275
293
|
end
|
|
276
294
|
|
|
277
295
|
# Returns remaining budget for a given limit type
|
|
@@ -279,9 +297,7 @@ module RubyLLM
|
|
|
279
297
|
# @param type [Symbol] Limit type
|
|
280
298
|
# @return [Numeric, nil] Remaining amount
|
|
281
299
|
def llm_remaining_budget(type: :daily_cost)
|
|
282
|
-
|
|
283
|
-
key = budget_status_key(type)
|
|
284
|
-
status.dig(key, :remaining)
|
|
300
|
+
llm_tenant.remaining_budget(type: type)
|
|
285
301
|
end
|
|
286
302
|
|
|
287
303
|
# Raises an error if over budget
|
|
@@ -289,7 +305,7 @@ module RubyLLM
|
|
|
289
305
|
# @raise [BudgetExceededError] if budget is exceeded
|
|
290
306
|
# @return [void]
|
|
291
307
|
def llm_check_budget!
|
|
292
|
-
|
|
308
|
+
llm_tenant.check_budget!(self.class.name)
|
|
293
309
|
end
|
|
294
310
|
|
|
295
311
|
private
|
|
@@ -299,7 +315,7 @@ module RubyLLM
|
|
|
299
315
|
# @param scope [ActiveRecord::Relation] The query scope
|
|
300
316
|
# @param period [Symbol, Range] The period to filter by
|
|
301
317
|
# @return [ActiveRecord::Relation] Filtered scope
|
|
302
|
-
def
|
|
318
|
+
def apply_llm_period_scope(scope, period)
|
|
303
319
|
case period
|
|
304
320
|
when :today then scope.where(created_at: Time.current.all_day)
|
|
305
321
|
when :yesterday then scope.where(created_at: 1.day.ago.all_day)
|
|
@@ -310,34 +326,18 @@ module RubyLLM
|
|
|
310
326
|
end
|
|
311
327
|
end
|
|
312
328
|
|
|
313
|
-
#
|
|
314
|
-
#
|
|
315
|
-
# @param type [Symbol] User-friendly type
|
|
316
|
-
# @return [Symbol] Status key
|
|
317
|
-
def budget_status_key(type)
|
|
318
|
-
case type
|
|
319
|
-
when :daily_cost then :global_daily
|
|
320
|
-
when :monthly_cost then :global_monthly
|
|
321
|
-
when :daily_tokens then :global_daily_tokens
|
|
322
|
-
when :monthly_tokens then :global_monthly_tokens
|
|
323
|
-
when :daily_executions then :global_daily_executions
|
|
324
|
-
when :monthly_executions then :global_monthly_executions
|
|
325
|
-
else :global_daily
|
|
326
|
-
end
|
|
327
|
-
end
|
|
328
|
-
|
|
329
|
-
# Creates the default budget on model creation
|
|
329
|
+
# Creates the default tenant record on model creation
|
|
330
330
|
#
|
|
331
331
|
# @return [void]
|
|
332
|
-
def
|
|
332
|
+
def create_default_llm_tenant
|
|
333
333
|
return if self.class.llm_tenant_options.blank?
|
|
334
|
-
return if
|
|
334
|
+
return if llm_tenant_record&.persisted?
|
|
335
335
|
|
|
336
336
|
options = self.class.llm_tenant_options
|
|
337
337
|
limits = options[:limits] || {}
|
|
338
338
|
name_method = options[:name] || :to_s
|
|
339
339
|
|
|
340
|
-
|
|
340
|
+
tenant = build_llm_tenant_record(
|
|
341
341
|
tenant_id: llm_tenant_id,
|
|
342
342
|
name: send(name_method).to_s,
|
|
343
343
|
daily_limit: limits[:daily_cost],
|
|
@@ -350,8 +350,8 @@ module RubyLLM
|
|
|
350
350
|
inherit_global_defaults: options.fetch(:inherit_global, true)
|
|
351
351
|
)
|
|
352
352
|
|
|
353
|
-
|
|
354
|
-
|
|
353
|
+
tenant.tenant_record = self
|
|
354
|
+
tenant.save!
|
|
355
355
|
end
|
|
356
356
|
end
|
|
357
357
|
end
|
|
@@ -125,13 +125,15 @@ module RubyLLM
|
|
|
125
125
|
nil
|
|
126
126
|
end
|
|
127
127
|
|
|
128
|
-
# Checks if the
|
|
128
|
+
# Checks if the tenants table exists (supports old and new table names)
|
|
129
129
|
#
|
|
130
130
|
# @return [Boolean] true if table exists
|
|
131
131
|
def tenant_budget_table_exists?
|
|
132
132
|
return @tenant_budget_table_exists if defined?(@tenant_budget_table_exists)
|
|
133
133
|
|
|
134
|
-
|
|
134
|
+
# Check for new table name (tenants) or old table name (tenant_budgets) for backward compatibility
|
|
135
|
+
@tenant_budget_table_exists = ::ActiveRecord::Base.connection.table_exists?(:ruby_llm_agents_tenants) ||
|
|
136
|
+
::ActiveRecord::Base.connection.table_exists?(:ruby_llm_agents_tenant_budgets)
|
|
135
137
|
rescue StandardError
|
|
136
138
|
@tenant_budget_table_exists = false
|
|
137
139
|
end
|
|
@@ -170,14 +170,16 @@ module RubyLLM
|
|
|
170
170
|
g.factory_bot dir: "spec/factories"
|
|
171
171
|
end
|
|
172
172
|
|
|
173
|
-
# Adds the host app's
|
|
173
|
+
# Adds the host app's agent directories to Rails autoload paths
|
|
174
174
|
#
|
|
175
|
-
# This allows agent classes and other
|
|
175
|
+
# This allows agent classes and other components defined in app/agents/
|
|
176
176
|
# to be automatically loaded without explicit requires.
|
|
177
177
|
#
|
|
178
|
-
# Supports
|
|
179
|
-
#
|
|
180
|
-
#
|
|
178
|
+
# Supports subdirectory namespacing:
|
|
179
|
+
# - app/agents/ (top-level, no namespace)
|
|
180
|
+
# - app/agents/embedders/ -> Embedders namespace
|
|
181
|
+
# - app/agents/images/ -> Images namespace
|
|
182
|
+
# - app/workflows/ (top-level, no namespace)
|
|
181
183
|
#
|
|
182
184
|
# @api private
|
|
183
185
|
initializer "ruby_llm_agents.autoload_agents", before: :set_autoload_paths do |app|
|
|
@@ -210,42 +212,34 @@ module RubyLLM
|
|
|
210
212
|
|
|
211
213
|
# Determines the namespace constant for a given path
|
|
212
214
|
#
|
|
213
|
-
# @param path [String] Relative path like "app/
|
|
215
|
+
# @param path [String] Relative path like "app/agents/embedders"
|
|
214
216
|
# @param config [Configuration] Current configuration
|
|
215
217
|
# @return [Module, nil] Namespace module or nil for top-level
|
|
216
218
|
# @api private
|
|
217
219
|
def self.namespace_for_path(path, config)
|
|
218
|
-
# Parse the path to determine namespace
|
|
219
220
|
parts = path.split("/")
|
|
220
|
-
return nil unless parts.length >= 3
|
|
221
221
|
|
|
222
|
-
|
|
222
|
+
# app/workflows -> no namespace (top-level workflows)
|
|
223
|
+
return nil if parts == ["app", "workflows"]
|
|
223
224
|
|
|
224
|
-
#
|
|
225
|
+
# Need at least app/{root_directory}
|
|
226
|
+
return nil unless parts.length >= 2 && parts[0] == "app"
|
|
227
|
+
return nil unless parts[1] == config.root_directory
|
|
228
|
+
|
|
229
|
+
# app/agents -> no namespace (root level)
|
|
230
|
+
return nil if parts.length == 2
|
|
231
|
+
|
|
232
|
+
# app/agents/embedders -> Embedders namespace
|
|
233
|
+
subdirectory = parts[2]
|
|
225
234
|
namespace_name = if config.root_namespace.blank?
|
|
226
|
-
|
|
227
|
-
case category
|
|
228
|
-
when "audio", "image", "text"
|
|
229
|
-
category.camelize # "Audio", "Image", "Text"
|
|
230
|
-
else
|
|
231
|
-
nil # Top-level for agents, workflows, tools
|
|
232
|
-
end
|
|
235
|
+
subdirectory.camelize
|
|
233
236
|
else
|
|
234
|
-
#
|
|
235
|
-
case category
|
|
236
|
-
when "audio", "image", "text"
|
|
237
|
-
"#{config.root_namespace}::#{category.camelize}"
|
|
238
|
-
else
|
|
239
|
-
config.root_namespace
|
|
240
|
-
end
|
|
237
|
+
"#{config.root_namespace}::#{subdirectory.camelize}"
|
|
241
238
|
end
|
|
242
239
|
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
# Return the constant, creating intermediate modules if needed
|
|
240
|
+
# Create the namespace module if needed
|
|
246
241
|
namespace_name.constantize
|
|
247
242
|
rescue NameError
|
|
248
|
-
# Create the namespace module if it doesn't exist
|
|
249
243
|
namespace_name.split("::").inject(Object) do |mod, name|
|
|
250
244
|
mod.const_defined?(name, false) ? mod.const_get(name) : mod.const_set(name, Module.new)
|
|
251
245
|
end
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: ruby_llm-agents
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.1
|
|
4
|
+
version: 1.2.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- adham90
|
|
@@ -95,6 +95,10 @@ files:
|
|
|
95
95
|
- app/models/ruby_llm/agents/execution/metrics.rb
|
|
96
96
|
- app/models/ruby_llm/agents/execution/scopes.rb
|
|
97
97
|
- app/models/ruby_llm/agents/execution/workflow.rb
|
|
98
|
+
- app/models/ruby_llm/agents/tenant.rb
|
|
99
|
+
- app/models/ruby_llm/agents/tenant/budgetable.rb
|
|
100
|
+
- app/models/ruby_llm/agents/tenant/configurable.rb
|
|
101
|
+
- app/models/ruby_llm/agents/tenant/trackable.rb
|
|
98
102
|
- app/models/ruby_llm/agents/tenant_budget.rb
|
|
99
103
|
- app/services/ruby_llm/agents/agent_registry.rb
|
|
100
104
|
- app/views/layouts/ruby_llm/agents/application.html.erb
|
|
@@ -155,6 +159,7 @@ files:
|
|
|
155
159
|
- app/views/ruby_llm/agents/tenants/edit.html.erb
|
|
156
160
|
- app/views/ruby_llm/agents/tenants/index.html.erb
|
|
157
161
|
- app/views/ruby_llm/agents/tenants/show.html.erb
|
|
162
|
+
- app/views/ruby_llm/agents/workflows/_empty_state.html.erb
|
|
158
163
|
- app/views/ruby_llm/agents/workflows/_step_performance.html.erb
|
|
159
164
|
- app/views/ruby_llm/agents/workflows/_structure_dsl.html.erb
|
|
160
165
|
- app/views/ruby_llm/agents/workflows/_structure_parallel.html.erb
|
|
@@ -208,6 +213,7 @@ files:
|
|
|
208
213
|
- lib/generators/ruby_llm_agents/templates/background_remover.rb.tt
|
|
209
214
|
- lib/generators/ruby_llm_agents/templates/create_api_configurations_migration.rb.tt
|
|
210
215
|
- lib/generators/ruby_llm_agents/templates/create_tenant_budgets_migration.rb.tt
|
|
216
|
+
- lib/generators/ruby_llm_agents/templates/create_tenants_migration.rb.tt
|
|
211
217
|
- lib/generators/ruby_llm_agents/templates/embedder.rb.tt
|
|
212
218
|
- lib/generators/ruby_llm_agents/templates/image_analyzer.rb.tt
|
|
213
219
|
- lib/generators/ruby_llm_agents/templates/image_editor.rb.tt
|
|
@@ -218,6 +224,7 @@ files:
|
|
|
218
224
|
- lib/generators/ruby_llm_agents/templates/image_variator.rb.tt
|
|
219
225
|
- lib/generators/ruby_llm_agents/templates/initializer.rb.tt
|
|
220
226
|
- lib/generators/ruby_llm_agents/templates/migration.rb.tt
|
|
227
|
+
- lib/generators/ruby_llm_agents/templates/rename_tenant_budgets_to_tenants_migration.rb.tt
|
|
221
228
|
- lib/generators/ruby_llm_agents/templates/skills/AGENTS.md.tt
|
|
222
229
|
- lib/generators/ruby_llm_agents/templates/skills/BACKGROUND_REMOVERS.md.tt
|
|
223
230
|
- lib/generators/ruby_llm_agents/templates/skills/EMBEDDERS.md.tt
|