ruby_llm-agents 1.1.0 → 1.2.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.
@@ -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::TenantBudget
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
- # Budget association (optional)
73
- has_one :llm_budget,
74
- class_name: "RubyLLM::Agents::TenantBudget",
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 TenantBudget on model creation (default: false)
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 budget callback
105
- after_create :create_default_llm_budget if llm_tenant_options[:budget]
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 = apply_period_scope(scope, period) if period
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 = apply_period_scope(scope, period) if period
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 = apply_period_scope(scope, period) if period
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
- # Returns or builds the associated TenantBudget
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
- BudgetTracker.status(tenant_id: llm_tenant_id)
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
- status = llm_budget_status
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
- status = llm_budget_status
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
- BudgetTracker.check_budget!(self.class.name, tenant_id: llm_tenant_id)
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 apply_period_scope(scope, period)
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
- # Maps user-friendly type to budget status key
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 create_default_llm_budget
332
+ def create_default_llm_tenant
333
333
  return if self.class.llm_tenant_options.blank?
334
- return if llm_budget&.persisted?
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
- budget = build_llm_budget(
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
- budget.tenant_record = self
354
- budget.save!
353
+ tenant.tenant_record = self
354
+ tenant.save!
355
355
  end
356
356
  end
357
357
  end
@@ -4,6 +4,6 @@ module RubyLLM
4
4
  module Agents
5
5
  # Current version of the RubyLLM::Agents gem
6
6
  # @return [String] Semantic version string
7
- VERSION = "1.1.0"
7
+ VERSION = "1.2.0"
8
8
  end
9
9
  end
@@ -125,13 +125,15 @@ module RubyLLM
125
125
  nil
126
126
  end
127
127
 
128
- # Checks if the tenant_budgets table exists
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
- @tenant_budget_table_exists = ::ActiveRecord::Base.connection.table_exists?(:ruby_llm_agents_tenant_budgets)
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
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.0
4
+ version: 1.2.0
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
@@ -208,6 +212,7 @@ files:
208
212
  - lib/generators/ruby_llm_agents/templates/background_remover.rb.tt
209
213
  - lib/generators/ruby_llm_agents/templates/create_api_configurations_migration.rb.tt
210
214
  - lib/generators/ruby_llm_agents/templates/create_tenant_budgets_migration.rb.tt
215
+ - lib/generators/ruby_llm_agents/templates/create_tenants_migration.rb.tt
211
216
  - lib/generators/ruby_llm_agents/templates/embedder.rb.tt
212
217
  - lib/generators/ruby_llm_agents/templates/image_analyzer.rb.tt
213
218
  - lib/generators/ruby_llm_agents/templates/image_editor.rb.tt
@@ -218,6 +223,7 @@ files:
218
223
  - lib/generators/ruby_llm_agents/templates/image_variator.rb.tt
219
224
  - lib/generators/ruby_llm_agents/templates/initializer.rb.tt
220
225
  - lib/generators/ruby_llm_agents/templates/migration.rb.tt
226
+ - lib/generators/ruby_llm_agents/templates/rename_tenant_budgets_to_tenants_migration.rb.tt
221
227
  - lib/generators/ruby_llm_agents/templates/skills/AGENTS.md.tt
222
228
  - lib/generators/ruby_llm_agents/templates/skills/BACKGROUND_REMOVERS.md.tt
223
229
  - lib/generators/ruby_llm_agents/templates/skills/EMBEDDERS.md.tt