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 +4 -4
- data/CHANGELOG.md +5 -0
- data/lib/legion/gaia/routes.rb +154 -0
- data/lib/legion/gaia/version.rb +1 -1
- data/lib/legion/gaia.rb +11 -0
- metadata +2 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 6cb8b5e651481a25407e6431621202c5b29e421eb13f7281c02347373169e576
|
|
4
|
+
data.tar.gz: 781ac8b692dff9d7e1d7e258415b93d99b700967d033b0cde67ed2d930d28f32
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
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
|
data/lib/legion/gaia/version.rb
CHANGED
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.
|
|
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
|