Class: Legion::Extensions::Agentic::Homeostasis::Hourglass::Helpers::HourglassEngine

Inherits:
Object
  • Object
show all
Defined in:
lib/legion/extensions/agentic/homeostasis/hourglass/helpers/hourglass_engine.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeHourglassEngine

Returns a new instance of HourglassEngine.



12
13
14
15
# File 'lib/legion/extensions/agentic/homeostasis/hourglass/helpers/hourglass_engine.rb', line 12

def initialize
  @hourglasses = {}
  @grains      = {}
end

Instance Attribute Details

#grainsObject (readonly)

Returns the value of attribute grains.



10
11
12
# File 'lib/legion/extensions/agentic/homeostasis/hourglass/helpers/hourglass_engine.rb', line 10

def grains
  @grains
end

#hourglassesObject (readonly)

Returns the value of attribute hourglasses.



10
11
12
# File 'lib/legion/extensions/agentic/homeostasis/hourglass/helpers/hourglass_engine.rb', line 10

def hourglasses
  @hourglasses
end

Instance Method Details

#create_grain(grain_type:, domain: nil, content: nil, weight: 1.0) ⇒ Object

Create a grain and register it; raises ArgumentError if MAX_GRAINS reached

Raises:

  • (ArgumentError)


18
19
20
21
22
23
24
25
26
27
28
29
# File 'lib/legion/extensions/agentic/homeostasis/hourglass/helpers/hourglass_engine.rb', line 18

def create_grain(grain_type:, domain: nil, content: nil, weight: 1.0)
  raise ArgumentError, "MAX_GRAINS (#{Constants::MAX_GRAINS}) reached" if @grains.size >= Constants::MAX_GRAINS

  grain = Grain.new(
    grain_type: grain_type,
    domain:     domain,
    content:    content,
    weight:     weight
  )
  @grains[grain.id] = grain
  grain
end

#create_hourglass(domain: nil, grain_type: :attention, top_level: 1.0, neck_width: 0.5, bottom_level: 0.0) ⇒ Object

Create an hourglass and register it; raises ArgumentError if MAX_HOURGLASSES reached

Raises:

  • (ArgumentError)


32
33
34
35
36
37
38
39
40
41
42
43
44
45
# File 'lib/legion/extensions/agentic/homeostasis/hourglass/helpers/hourglass_engine.rb', line 32

def create_hourglass(domain: nil, grain_type: :attention, top_level: 1.0,
                     neck_width: 0.5, bottom_level: 0.0)
  raise ArgumentError, "MAX_HOURGLASSES (#{Constants::MAX_HOURGLASSES}) reached" if @hourglasses.size >= Constants::MAX_HOURGLASSES

  hourglass = Hourglass.new(
    domain:       domain,
    grain_type:   grain_type,
    top_level:    top_level,
    neck_width:   neck_width,
    bottom_level: bottom_level
  )
  @hourglasses[hourglass.id] = hourglass
  hourglass
end

#flip(hourglass_id) ⇒ Object

Flip a specific hourglass by id; raises ArgumentError if not found



77
78
79
80
81
82
83
# File 'lib/legion/extensions/agentic/homeostasis/hourglass/helpers/hourglass_engine.rb', line 77

def flip(hourglass_id)
  h = @hourglasses.fetch(hourglass_id) do
    raise ArgumentError, "hourglass not found: #{hourglass_id}"
  end
  h.flip!
  h
end

#flow_reportObject

Return a summary report of all hourglasses grouped by state



97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
# File 'lib/legion/extensions/agentic/homeostasis/hourglass/helpers/hourglass_engine.rb', line 97

def flow_report
  grouped = @hourglasses.values.group_by(&:state)

  {
    total:         @hourglasses.size,
    grain_count:   @grains.size,
    flowing:       grouped.fetch(:flowing,  []).size,
    blocked:       grouped.fetch(:blocked,  []).size,
    empty:         grouped.fetch(:empty,    []).size,
    full:          grouped.fetch(:full,     []).size,
    paused:        grouped.fetch(:paused,   []).size,
    most_urgent:   most_urgent&.to_h,
    most_depleted: most_depleted&.to_h,
    hourglasses:   @hourglasses.values.map(&:to_h)
  }
end

#flow_tick(rate = Constants::FLOW_RATE) ⇒ Object

Advance all non-expired hourglasses by one flow tick



48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
# File 'lib/legion/extensions/agentic/homeostasis/hourglass/helpers/hourglass_engine.rb', line 48

def flow_tick(rate = Constants::FLOW_RATE)
  ticked    = 0
  expired   = 0
  blocked   = 0

  @hourglasses.each_value do |h|
    if h.state == :paused
      blocked += 1
      next
    end

    if h.expired?
      expired += 1
      next
    end

    if rand < Constants::BLOCKAGE_CHANCE
      h.pause!
      blocked += 1
    else
      h.flow!(rate)
      ticked += 1
    end
  end

  { ticked: ticked, expired: expired, blocked: blocked, total: @hourglasses.size }
end

#most_depletedObject

Return the hourglass with the most sand in the bottom (most depleted from top)



92
93
94
# File 'lib/legion/extensions/agentic/homeostasis/hourglass/helpers/hourglass_engine.rb', line 92

def most_depleted
  @hourglasses.values.max_by(&:bottom_level)
end

#most_urgentObject

Return the hourglass closest to expired (lowest top_level, not already expired)



86
87
88
89
# File 'lib/legion/extensions/agentic/homeostasis/hourglass/helpers/hourglass_engine.rb', line 86

def most_urgent
  candidates = @hourglasses.values.reject(&:expired?).reject { |h| h.state == :paused }
  candidates.min_by(&:top_level)
end