legion-gaia 0.9.26 → 0.9.27

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 0bd458b6bb7a1f5f9625afb623eda2e0d343707d7e1b0c7223112807a01c6156
4
- data.tar.gz: 23efe96dd88bf05ed4cba417b956dbcd1245f543c914baa18451ab52bc31fa6f
3
+ metadata.gz: 6cb8b5e651481a25407e6431621202c5b29e421eb13f7281c02347373169e576
4
+ data.tar.gz: 781ac8b692dff9d7e1d7e258415b93d99b700967d033b0cde67ed2d930d28f32
5
5
  SHA512:
6
- metadata.gz: 3d93060f86928ce533879622b08c81944140eae71b9590ee6ba04dd4904e513379fc77d3f6388b023b94ce7ddcbf69554d2bcffb3cc78d27d13fd5599e844290
7
- data.tar.gz: cfc4492c4027b02d0ef765808d61e44ebf9a18fa8133750d5910236304cb8d2bdb65f5faf92622f5835855776843bb0e4bab3b6575bc458678c08495dfa07ba4
6
+ metadata.gz: 915bc653dc93ed27a1fcf2ddc6ecfee1a350465914d6f6600fe4c152c8aa0c309a63845dcb6065b12fc4b9fd8262f688f939c9a8e4b99df57e327d66c73ddca1
7
+ data.tar.gz: bb37d7e68883d1446176cfab34e49287df418736a82b91bc1cab6e998f19d73dc49f3c6023861eb24c92d82503d792a0b388e15d49f1cff98bccc8ef26d20749
data/CHANGELOG.md CHANGED
@@ -1,5 +1,10 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.9.27] - 2026-03-28
4
+
5
+ ### Added
6
+ - `Legion::Gaia::Routes` self-registering Sinatra route module (`lib/legion/gaia/routes.rb`): extracts all `/api/gaia/*` route handlers from LegionIO. Self-registers with `Legion::API.register_library_routes('gaia', Routes)` during boot. Includes fallback helpers for standalone mounting.
7
+
3
8
  ## [0.9.26] - 2026-03-25
4
9
 
5
10
  ### Added
@@ -0,0 +1,154 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Self-registering route module for legion-gaia.
4
+ # All routes previously defined in LegionIO/lib/legion/api/gaia.rb now live here
5
+ # and are mounted via Legion::API.register_library_routes when legion-gaia boots.
6
+ #
7
+ # LegionIO/lib/legion/api/gaia.rb is preserved for backward compatibility but guards
8
+ # its registration with defined?(Legion::Gaia::Routes) so double-registration is avoided.
9
+
10
+ module Legion
11
+ module Gaia
12
+ module Routes
13
+ def self.registered(app) # rubocop:disable Metrics/AbcSize,Metrics/CyclomaticComplexity,Metrics/MethodLength,Metrics/PerceivedComplexity
14
+ app.helpers do # rubocop:disable Metrics/BlockLength
15
+ unless method_defined?(:gaia_available?)
16
+ define_method(:gaia_available?) do
17
+ defined?(Legion::Gaia) && Legion::Gaia.respond_to?(:started?) && Legion::Gaia.started?
18
+ end
19
+ end
20
+
21
+ unless method_defined?(:gaia_buffer_max_size)
22
+ define_method(:gaia_buffer_max_size) do
23
+ return nil unless defined?(Legion::Gaia::SensoryBuffer)
24
+
25
+ Legion::Gaia::SensoryBuffer::MAX_BUFFER_SIZE
26
+ rescue NameError
27
+ nil
28
+ end
29
+ end
30
+
31
+ unless method_defined?(:build_channel_info)
32
+ define_method(:build_channel_info) do |channel_id, adapter|
33
+ info = { id: channel_id, started: adapter&.started? || false }
34
+ info[:capabilities] = adapter.capabilities if adapter.respond_to?(:capabilities)
35
+ info[:type] = adapter.class.name.split('::').last if adapter
36
+ info
37
+ end
38
+ end
39
+
40
+ unless method_defined?(:json_response)
41
+ define_method(:json_response) do |data, status_code: 200|
42
+ content_type :json
43
+ status status_code
44
+ Legion::JSON.dump({ data: data })
45
+ end
46
+ end
47
+
48
+ unless method_defined?(:json_error)
49
+ define_method(:json_error) do |code, message, status_code: 400|
50
+ content_type :json
51
+ status status_code
52
+ Legion::JSON.dump({ error: { code: code, message: message } })
53
+ end
54
+ end
55
+ end
56
+
57
+ register_status_route(app)
58
+ register_channels_route(app)
59
+ register_buffer_route(app)
60
+ register_sessions_route(app)
61
+ register_teams_webhook_route(app)
62
+ end
63
+
64
+ def self.register_status_route(app)
65
+ app.get '/api/gaia/status' do
66
+ if gaia_available?
67
+ json_response(Legion::Gaia.status)
68
+ else
69
+ json_response({ started: false }, status_code: 503)
70
+ end
71
+ end
72
+ end
73
+
74
+ def self.register_channels_route(app)
75
+ app.get '/api/gaia/channels' do
76
+ halt 503, json_error('gaia_unavailable', 'gaia is not started', status_code: 503) unless gaia_available?
77
+
78
+ registry = Legion::Gaia.channel_registry
79
+ return json_response({ channels: [] }) unless registry
80
+
81
+ channels = registry.active_channels.map do |ch_id|
82
+ adapter = registry.adapter_for(ch_id)
83
+ build_channel_info(ch_id, adapter)
84
+ end
85
+
86
+ json_response({ channels: channels, count: channels.size })
87
+ end
88
+ end
89
+
90
+ def self.register_buffer_route(app)
91
+ app.get '/api/gaia/buffer' do
92
+ halt 503, json_error('gaia_unavailable', 'gaia is not started', status_code: 503) unless gaia_available?
93
+
94
+ buffer = Legion::Gaia.sensory_buffer
95
+ json_response({
96
+ depth: buffer&.size || 0,
97
+ empty: buffer.nil? || buffer.empty?,
98
+ max_size: gaia_buffer_max_size
99
+ })
100
+ end
101
+ end
102
+
103
+ def self.register_sessions_route(app)
104
+ app.get '/api/gaia/sessions' do
105
+ halt 503, json_error('gaia_unavailable', 'gaia is not started', status_code: 503) unless gaia_available?
106
+
107
+ store = Legion::Gaia.session_store
108
+ json_response({
109
+ count: store&.size || 0,
110
+ active: gaia_available?
111
+ })
112
+ end
113
+ end
114
+
115
+ def self.register_teams_webhook_route(app)
116
+ app.post '/api/channels/teams/webhook' do
117
+ if defined?(Legion::Logging)
118
+ Legion::Logging.debug "API: POST /api/channels/teams/webhook params=#{params.keys}"
119
+ end
120
+ body = request.body.read
121
+ activity = Legion::JSON.load(body)
122
+
123
+ adapter = Routes.teams_adapter
124
+ unless adapter
125
+ if defined?(Legion::Logging)
126
+ Legion::Logging.warn 'API POST /api/channels/teams/webhook returned 503: teams adapter not available'
127
+ end
128
+ halt 503, json_response({ error: 'teams adapter not available' }, status_code: 503)
129
+ end
130
+
131
+ input_frame = adapter.translate_inbound(activity)
132
+ Legion::Gaia.sensory_buffer&.push(input_frame) if defined?(Legion::Gaia)
133
+ Legion::Logging.info "API: accepted Teams webhook frame_id=#{input_frame&.id}" if defined?(Legion::Logging)
134
+ json_response({ status: 'accepted', frame_id: input_frame&.id })
135
+ end
136
+ end
137
+
138
+ def self.teams_adapter
139
+ return nil unless defined?(Legion::Gaia) && Legion::Gaia.respond_to?(:channel_registry)
140
+ return nil unless Legion::Gaia.channel_registry
141
+
142
+ Legion::Gaia.channel_registry.adapter_for(:teams)
143
+ rescue StandardError => e
144
+ Legion::Logging.warn "Gaia#teams_adapter failed: #{e.message}" if defined?(Legion::Logging)
145
+ nil
146
+ end
147
+
148
+ class << self
149
+ private :register_status_route, :register_channels_route, :register_buffer_route,
150
+ :register_sessions_route, :register_teams_webhook_route
151
+ end
152
+ end
153
+ end
154
+ end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Legion
4
4
  module Gaia
5
- VERSION = '0.9.26'
5
+ VERSION = '0.9.27'
6
6
  end
7
7
  end
data/lib/legion/gaia.rb CHANGED
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'legion/gaia/version'
4
+ require 'legion/gaia/routes'
4
5
  require 'legion/gaia/advisory'
5
6
  require 'legion/gaia/audit_observer'
6
7
  require 'legion/gaia/settings'
@@ -53,6 +54,7 @@ module Legion
53
54
  settings_hash = settings
54
55
  settings_hash[:connected] = true if settings_hash
55
56
 
57
+ register_routes
56
58
  check_teams_auth
57
59
 
58
60
  log_info "Legion::Gaia booted (#{@mode}): #{boot_summary}"
@@ -158,6 +160,15 @@ module Legion
158
160
 
159
161
  private
160
162
 
163
+ def register_routes
164
+ return unless defined?(Legion::API) && Legion::API.respond_to?(:register_library_routes)
165
+
166
+ Legion::API.register_library_routes('gaia', Legion::Gaia::Routes)
167
+ Legion::Logging.debug 'Legion::Gaia routes registered with API' if defined?(Legion::Logging)
168
+ rescue StandardError => e
169
+ Legion::Logging.warn "Legion::Gaia route registration failed: #{e.message}" if defined?(Legion::Logging)
170
+ end
171
+
161
172
  def boot_agent
162
173
  @sensory_buffer = SensoryBuffer.new
163
174
  @registry = Registry.instance
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: legion-gaia
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.9.26
4
+ version: 0.9.27
5
5
  platform: ruby
6
6
  authors:
7
7
  - Esity
@@ -435,6 +435,7 @@ files:
435
435
  - lib/legion/gaia/router/transport/queues/inbound.rb
436
436
  - lib/legion/gaia/router/transport/queues/outbound.rb
437
437
  - lib/legion/gaia/router/worker_routing.rb
438
+ - lib/legion/gaia/routes.rb
438
439
  - lib/legion/gaia/runner_host.rb
439
440
  - lib/legion/gaia/sensory_buffer.rb
440
441
  - lib/legion/gaia/session_store.rb