Class: Legion::Extensions::Agentic::Attention::Economy::Helpers::AttentionBudget

Inherits:
Object
  • Object
show all
Includes:
Constants
Defined in:
lib/legion/extensions/agentic/attention/economy/helpers/attention_budget.rb

Constant Summary

Constants included from Constants

Constants::BUDGET_RECOVERY_RATE, Constants::DEFAULT_BUDGET, Constants::DEMAND_TYPES, Constants::EFFICIENCY_LABELS, Constants::MAX_DEMANDS, Constants::MIN_ALLOCATION, Constants::PRIORITY_LABELS

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(total_budget: Constants::DEFAULT_BUDGET) ⇒ AttentionBudget

Returns a new instance of AttentionBudget.



17
18
19
20
21
22
# File 'lib/legion/extensions/agentic/attention/economy/helpers/attention_budget.rb', line 17

def initialize(total_budget: Constants::DEFAULT_BUDGET)
  @demands       = {}
  @total_budget  = total_budget
  @spent         = 0.0
  @recovered     = 0.0
end

Instance Attribute Details

#recoveredObject (readonly)

Returns the value of attribute recovered.



15
16
17
# File 'lib/legion/extensions/agentic/attention/economy/helpers/attention_budget.rb', line 15

def recovered
  @recovered
end

#spentObject (readonly)

Returns the value of attribute spent.



15
16
17
# File 'lib/legion/extensions/agentic/attention/economy/helpers/attention_budget.rb', line 15

def spent
  @spent
end

#total_budgetObject (readonly)

Returns the value of attribute total_budget.



15
16
17
# File 'lib/legion/extensions/agentic/attention/economy/helpers/attention_budget.rb', line 15

def total_budget
  @total_budget
end

Instance Method Details

#allocate(demand_id:, amount: nil) ⇒ Object



33
34
35
36
37
38
39
40
41
42
43
44
# File 'lib/legion/extensions/agentic/attention/economy/helpers/attention_budget.rb', line 33

def allocate(demand_id:, amount: nil)
  demand = @demands.fetch(demand_id, nil)
  return { allocated: false, reason: :not_found } unless demand

  alloc_amount = (amount || demand.cost).clamp(Constants::MIN_ALLOCATION, 1.0)

  return { allocated: false, reason: :insufficient_budget, available: available_budget.round(10) } if alloc_amount > available_budget

  demand.allocate!(amount: alloc_amount)
  @spent = (@spent + alloc_amount).round(10)
  { allocated: true, demand_id: demand_id, amount: alloc_amount, remaining: available_budget.round(10) }
end

#available_budgetObject



64
65
66
# File 'lib/legion/extensions/agentic/attention/economy/helpers/attention_budget.rb', line 64

def available_budget
  (@total_budget - @spent).clamp(0.0, @total_budget).round(10)
end

#best_roi(limit: 5) ⇒ Object



78
79
80
81
82
# File 'lib/legion/extensions/agentic/attention/economy/helpers/attention_budget.rb', line 78

def best_roi(limit: 5)
  @demands.values
          .sort_by { |d| -d.efficiency }
          .first(limit)
end

#budget_pressureObject



88
89
90
# File 'lib/legion/extensions/agentic/attention/economy/helpers/attention_budget.rb', line 88

def budget_pressure
  utilization
end

#budget_reportObject



110
111
112
113
114
115
116
117
118
119
120
121
122
# File 'lib/legion/extensions/agentic/attention/economy/helpers/attention_budget.rb', line 110

def budget_report
  {
    total_budget:    @total_budget,
    spent:           @spent.round(10),
    available:       available_budget,
    utilization:     utilization,
    recovered:       @recovered.round(10),
    over_budget:     over_budget?,
    budget_pressure: budget_pressure,
    demand_count:    @demands.size,
    allocated_count: @demands.values.count { |d| d.allocated.positive? }
  }
end

#create_demand(label:, demand_type:, priority:, cost:, roi: 0.5) ⇒ Object

Raises:

  • (ArgumentError)


24
25
26
27
28
29
30
31
# File 'lib/legion/extensions/agentic/attention/economy/helpers/attention_budget.rb', line 24

def create_demand(label:, demand_type:, priority:, cost:, roi: 0.5)
  raise ArgumentError, "demand_type must be one of #{Constants::DEMAND_TYPES.inspect}" unless Constants::DEMAND_TYPES.include?(demand_type)
  raise ArgumentError, "max demands (#{Constants::MAX_DEMANDS}) reached" if @demands.size >= Constants::MAX_DEMANDS

  demand = Demand.new(label: label, demand_type: demand_type, priority: priority, cost: cost, roi: roi)
  @demands[demand.id] = demand
  demand
end

#deallocate(demand_id:) ⇒ Object



46
47
48
49
50
51
52
53
54
# File 'lib/legion/extensions/agentic/attention/economy/helpers/attention_budget.rb', line 46

def deallocate(demand_id:)
  demand = @demands.fetch(demand_id, nil)
  return { deallocated: false, reason: :not_found } unless demand

  freed = demand.allocated
  demand.deallocate!
  @spent = [(@spent - freed).round(10), 0.0].max
  { deallocated: true, demand_id: demand_id, freed: freed.round(10), remaining: available_budget.round(10) }
end

#demandsObject



130
131
132
# File 'lib/legion/extensions/agentic/attention/economy/helpers/attention_budget.rb', line 130

def demands
  @demands.values
end

#find_demand(demand_id) ⇒ Object



134
135
136
# File 'lib/legion/extensions/agentic/attention/economy/helpers/attention_budget.rb', line 134

def find_demand(demand_id)
  @demands[demand_id]
end

#over_budget?Boolean

Returns:

  • (Boolean)


84
85
86
# File 'lib/legion/extensions/agentic/attention/economy/helpers/attention_budget.rb', line 84

def over_budget?
  @spent > @total_budget
end

#prioritized_demandsObject



74
75
76
# File 'lib/legion/extensions/agentic/attention/economy/helpers/attention_budget.rb', line 74

def prioritized_demands
  @demands.values.sort_by { |d| -d.priority }
end

#rebalanceObject



92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
# File 'lib/legion/extensions/agentic/attention/economy/helpers/attention_budget.rb', line 92

def rebalance
  return { rebalanced: 0 } unless over_budget?

  sorted = @demands.values.select { |d| d.allocated.positive? }.sort_by(&:priority)
  freed_count = 0

  sorted.each do |demand|
    break unless over_budget?

    freed = demand.allocated
    demand.deallocate!
    @spent = [(@spent - freed).round(10), 0.0].max
    freed_count += 1
  end

  { rebalanced: freed_count, spent: @spent, available: available_budget.round(10) }
end

#recover!(amount: Constants::BUDGET_RECOVERY_RATE) ⇒ Object



56
57
58
59
60
61
62
# File 'lib/legion/extensions/agentic/attention/economy/helpers/attention_budget.rb', line 56

def recover!(amount: Constants::BUDGET_RECOVERY_RATE)
  previous = @spent
  @spent   = [(@spent - amount).round(10), 0.0].max
  delta    = (previous - @spent).round(10)
  @recovered = (@recovered + delta).round(10)
  { recovered: delta, spent: @spent, available: available_budget.round(10) }
end

#to_hObject



124
125
126
127
128
# File 'lib/legion/extensions/agentic/attention/economy/helpers/attention_budget.rb', line 124

def to_h
  budget_report.merge(
    demands: @demands.values.map(&:to_h)
  )
end

#utilizationObject



68
69
70
71
72
# File 'lib/legion/extensions/agentic/attention/economy/helpers/attention_budget.rb', line 68

def utilization
  return 0.0 if @total_budget.zero?

  (@spent / @total_budget).clamp(0.0, 1.0).round(10)
end