Module: RubyLLM::Agents::Tenant::Budgetable
- Extended by:
- ActiveSupport::Concern
- Included in:
- RubyLLM::Agents::Tenant
- Defined in:
- app/models/ruby_llm/agents/tenant/budgetable.rb
Overview
Handles budget limits and enforcement for tenants.
Supports three types of limits:
-
Cost limits (USD): daily_limit, monthly_limit
-
Token limits: daily_token_limit, monthly_token_limit
-
Execution limits: daily_execution_limit, monthly_execution_limit
Enforcement modes:
-
:none - No enforcement, tracking only
-
:soft - Log warnings when limits exceeded
-
:hard - Block execution when limits exceeded
Constant Summary collapse
- ENFORCEMENT_MODES =
Valid enforcement modes
%w[none soft hard].freeze
Instance Method Summary collapse
-
#budget_status ⇒ Hash
Get full budget status using counter columns.
-
#budgets_enabled? ⇒ Boolean
Checks if budget enforcement is enabled.
-
#check_budget!(agent_type = nil) ⇒ Object
Check budget and raise if exceeded (for hard enforcement).
-
#effective_daily_execution_limit ⇒ Integer?
Returns the effective daily execution limit.
-
#effective_daily_limit ⇒ Float?
Returns the effective daily cost limit.
-
#effective_daily_token_limit ⇒ Integer?
Returns the effective daily token limit.
-
#effective_enforcement ⇒ Symbol
Returns the effective enforcement mode.
-
#effective_monthly_execution_limit ⇒ Integer?
Returns the effective monthly execution limit.
-
#effective_monthly_limit ⇒ Float?
Returns the effective monthly cost limit.
-
#effective_monthly_token_limit ⇒ Integer?
Returns the effective monthly token limit.
-
#effective_per_agent_daily(agent_type) ⇒ Float?
Returns the effective per-agent daily limit.
-
#effective_per_agent_monthly(agent_type) ⇒ Float?
Returns the effective per-agent monthly limit.
-
#hard_enforcement? ⇒ Boolean
Checks if hard enforcement is enabled.
-
#remaining_budget(type: :daily_cost) ⇒ Numeric?
Get remaining budget for a specific type.
-
#soft_enforcement? ⇒ Boolean
Checks if soft enforcement is enabled.
-
#to_budget_config ⇒ Hash
Convert to config hash for BudgetTracker.
-
#within_budget?(type: :daily_cost) ⇒ Boolean
Check if within budget for a specific type using counter columns.
-
#within_daily_cost_budget? ⇒ Boolean
Individual budget check methods.
- #within_daily_execution_budget? ⇒ Boolean
- #within_daily_token_budget? ⇒ Boolean
- #within_monthly_cost_budget? ⇒ Boolean
- #within_monthly_execution_budget? ⇒ Boolean
- #within_monthly_token_budget? ⇒ Boolean
Instance Method Details
#budget_status ⇒ Hash
Get full budget status using counter columns
283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 |
# File 'app/models/ruby_llm/agents/tenant/budgetable.rb', line 283 def budget_status ensure_daily_reset! ensure_monthly_reset! { enabled: budgets_enabled?, enforcement: effective_enforcement, global_daily: budget_status_for(effective_daily_limit, daily_cost_spent), global_monthly: budget_status_for(effective_monthly_limit, monthly_cost_spent), global_daily_tokens: budget_status_for(effective_daily_token_limit, daily_tokens_used), global_monthly_tokens: budget_status_for(effective_monthly_token_limit, monthly_tokens_used), global_daily_executions: budget_status_for(effective_daily_execution_limit, daily_executions_count), global_monthly_executions: budget_status_for(effective_monthly_execution_limit, monthly_executions_count) } end |
#budgets_enabled? ⇒ Boolean
Checks if budget enforcement is enabled
161 162 163 |
# File 'app/models/ruby_llm/agents/tenant/budgetable.rb', line 161 def budgets_enabled? effective_enforcement != :none end |
#check_budget!(agent_type = nil) ⇒ Object
Check budget and raise if exceeded (for hard enforcement)
236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 |
# File 'app/models/ruby_llm/agents/tenant/budgetable.rb', line 236 def check_budget!(agent_type = nil) return unless budgets_enabled? return unless hard_enforcement? ensure_daily_reset! ensure_monthly_reset! if effective_daily_limit && daily_cost_spent >= effective_daily_limit raise Reliability::BudgetExceededError.new( :global_daily, effective_daily_limit, daily_cost_spent, tenant_id: tenant_id ) end if effective_monthly_limit && monthly_cost_spent >= effective_monthly_limit raise Reliability::BudgetExceededError.new( :global_monthly, effective_monthly_limit, monthly_cost_spent, tenant_id: tenant_id ) end if effective_daily_token_limit && daily_tokens_used >= effective_daily_token_limit raise Reliability::BudgetExceededError.new( :global_daily_tokens, effective_daily_token_limit, daily_tokens_used, tenant_id: tenant_id ) end if effective_monthly_token_limit && monthly_tokens_used >= effective_monthly_token_limit raise Reliability::BudgetExceededError.new( :global_monthly_tokens, effective_monthly_token_limit, monthly_tokens_used, tenant_id: tenant_id ) end if effective_daily_execution_limit && daily_executions_count >= effective_daily_execution_limit raise Reliability::BudgetExceededError.new( :global_daily_executions, effective_daily_execution_limit, daily_executions_count, tenant_id: tenant_id ) end if effective_monthly_execution_limit && monthly_executions_count >= effective_monthly_execution_limit raise Reliability::BudgetExceededError.new( :global_monthly_executions, effective_monthly_execution_limit, monthly_executions_count, tenant_id: tenant_id ) end end |
#effective_daily_execution_limit ⇒ Integer?
Returns the effective daily execution limit
99 100 101 102 103 104 |
# File 'app/models/ruby_llm/agents/tenant/budgetable.rb', line 99 def effective_daily_execution_limit return daily_execution_limit if daily_execution_limit.present? return nil unless inherit_global_defaults global_config&.dig(:global_daily_executions) end |
#effective_daily_limit ⇒ Float?
Returns the effective daily cost limit
59 60 61 62 63 64 |
# File 'app/models/ruby_llm/agents/tenant/budgetable.rb', line 59 def effective_daily_limit return daily_limit if daily_limit.present? return nil unless inherit_global_defaults global_config&.dig(:global_daily) end |
#effective_daily_token_limit ⇒ Integer?
Returns the effective daily token limit
79 80 81 82 83 84 |
# File 'app/models/ruby_llm/agents/tenant/budgetable.rb', line 79 def effective_daily_token_limit return daily_token_limit if daily_token_limit.present? return nil unless inherit_global_defaults global_config&.dig(:global_daily_tokens) end |
#effective_enforcement ⇒ Symbol
Returns the effective enforcement mode
119 120 121 122 123 124 |
# File 'app/models/ruby_llm/agents/tenant/budgetable.rb', line 119 def effective_enforcement return enforcement.to_sym if enforcement.present? return :soft unless inherit_global_defaults RubyLLM::Agents.configuration.budget_enforcement end |
#effective_monthly_execution_limit ⇒ Integer?
Returns the effective monthly execution limit
109 110 111 112 113 114 |
# File 'app/models/ruby_llm/agents/tenant/budgetable.rb', line 109 def effective_monthly_execution_limit return monthly_execution_limit if monthly_execution_limit.present? return nil unless inherit_global_defaults global_config&.dig(:global_monthly_executions) end |
#effective_monthly_limit ⇒ Float?
Returns the effective monthly cost limit
69 70 71 72 73 74 |
# File 'app/models/ruby_llm/agents/tenant/budgetable.rb', line 69 def effective_monthly_limit return monthly_limit if monthly_limit.present? return nil unless inherit_global_defaults global_config&.dig(:global_monthly) end |
#effective_monthly_token_limit ⇒ Integer?
Returns the effective monthly token limit
89 90 91 92 93 94 |
# File 'app/models/ruby_llm/agents/tenant/budgetable.rb', line 89 def effective_monthly_token_limit return monthly_token_limit if monthly_token_limit.present? return nil unless inherit_global_defaults global_config&.dig(:global_monthly_tokens) end |
#effective_per_agent_daily(agent_type) ⇒ Float?
Returns the effective per-agent daily limit
Checks the current name and all aliases for matching limits.
132 133 134 135 136 137 138 139 |
# File 'app/models/ruby_llm/agents/tenant/budgetable.rb', line 132 def effective_per_agent_daily(agent_type) names = resolve_agent_names(agent_type) limit = names.lazy.filter_map { |n| per_agent_daily&.dig(n) }.first return limit if limit.present? return nil unless inherit_global_defaults names.lazy.filter_map { |n| global_config&.dig(:per_agent_daily, n) }.first end |
#effective_per_agent_monthly(agent_type) ⇒ Float?
Returns the effective per-agent monthly limit
Checks the current name and all aliases for matching limits.
147 148 149 150 151 152 153 154 |
# File 'app/models/ruby_llm/agents/tenant/budgetable.rb', line 147 def effective_per_agent_monthly(agent_type) names = resolve_agent_names(agent_type) limit = names.lazy.filter_map { |n| per_agent_monthly&.dig(n) }.first return limit if limit.present? return nil unless inherit_global_defaults names.lazy.filter_map { |n| global_config&.dig(:per_agent_monthly, n) }.first end |
#hard_enforcement? ⇒ Boolean
Checks if hard enforcement is enabled
168 169 170 |
# File 'app/models/ruby_llm/agents/tenant/budgetable.rb', line 168 def hard_enforcement? effective_enforcement == :hard end |
#remaining_budget(type: :daily_cost) ⇒ Numeric?
Get remaining budget for a specific type
209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 |
# File 'app/models/ruby_llm/agents/tenant/budgetable.rb', line 209 def remaining_budget(type: :daily_cost) case type when :daily_cost effective_daily_limit && (ensure_daily_reset! effective_daily_limit - daily_cost_spent) when :monthly_cost effective_monthly_limit && (ensure_monthly_reset! effective_monthly_limit - monthly_cost_spent) when :daily_tokens effective_daily_token_limit && (ensure_daily_reset! effective_daily_token_limit - daily_tokens_used) when :monthly_tokens effective_monthly_token_limit && (ensure_monthly_reset! effective_monthly_token_limit - monthly_tokens_used) when :daily_executions effective_daily_execution_limit && (ensure_daily_reset! effective_daily_execution_limit - daily_executions_count) when :monthly_executions effective_monthly_execution_limit && (ensure_monthly_reset! effective_monthly_execution_limit - monthly_executions_count) end end |
#soft_enforcement? ⇒ Boolean
Checks if soft enforcement is enabled
175 176 177 |
# File 'app/models/ruby_llm/agents/tenant/budgetable.rb', line 175 def soft_enforcement? effective_enforcement == :soft end |
#to_budget_config ⇒ Hash
Convert to config hash for BudgetTracker
334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 |
# File 'app/models/ruby_llm/agents/tenant/budgetable.rb', line 334 def to_budget_config { enabled: budgets_enabled?, enforcement: effective_enforcement, # Cost limits global_daily: effective_daily_limit, global_monthly: effective_monthly_limit, per_agent_daily: merged_per_agent_daily, per_agent_monthly: merged_per_agent_monthly, # Token limits global_daily_tokens: effective_daily_token_limit, global_monthly_tokens: effective_monthly_token_limit, # Execution limits global_daily_executions: effective_daily_execution_limit, global_monthly_executions: effective_monthly_execution_limit } end |
#within_budget?(type: :daily_cost) ⇒ Boolean
Check if within budget for a specific type using counter columns
184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 |
# File 'app/models/ruby_llm/agents/tenant/budgetable.rb', line 184 def within_budget?(type: :daily_cost) return true unless budgets_enabled? case type when :daily_cost within_daily_cost_budget? when :monthly_cost within_monthly_cost_budget? when :daily_tokens within_daily_token_budget? when :monthly_tokens within_monthly_token_budget? when :daily_executions within_daily_execution_budget? when :monthly_executions within_monthly_execution_budget? else true end end |
#within_daily_cost_budget? ⇒ Boolean
Individual budget check methods
301 302 303 304 |
# File 'app/models/ruby_llm/agents/tenant/budgetable.rb', line 301 def within_daily_cost_budget? ensure_daily_reset! effective_daily_limit.nil? || daily_cost_spent < effective_daily_limit end |
#within_daily_execution_budget? ⇒ Boolean
321 322 323 324 |
# File 'app/models/ruby_llm/agents/tenant/budgetable.rb', line 321 def within_daily_execution_budget? ensure_daily_reset! effective_daily_execution_limit.nil? || daily_executions_count < effective_daily_execution_limit end |
#within_daily_token_budget? ⇒ Boolean
311 312 313 314 |
# File 'app/models/ruby_llm/agents/tenant/budgetable.rb', line 311 def within_daily_token_budget? ensure_daily_reset! effective_daily_token_limit.nil? || daily_tokens_used < effective_daily_token_limit end |
#within_monthly_cost_budget? ⇒ Boolean
306 307 308 309 |
# File 'app/models/ruby_llm/agents/tenant/budgetable.rb', line 306 def within_monthly_cost_budget? ensure_monthly_reset! effective_monthly_limit.nil? || monthly_cost_spent < effective_monthly_limit end |
#within_monthly_execution_budget? ⇒ Boolean
326 327 328 329 |
# File 'app/models/ruby_llm/agents/tenant/budgetable.rb', line 326 def within_monthly_execution_budget? ensure_monthly_reset! effective_monthly_execution_limit.nil? || monthly_executions_count < effective_monthly_execution_limit end |
#within_monthly_token_budget? ⇒ Boolean
316 317 318 319 |
# File 'app/models/ruby_llm/agents/tenant/budgetable.rb', line 316 def within_monthly_token_budget? ensure_monthly_reset! effective_monthly_token_limit.nil? || monthly_tokens_used < effective_monthly_token_limit end |