legionio 1.7.8 → 1.7.13

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.
@@ -41,7 +41,7 @@ module Legion
41
41
  record_learning(domain: domain, success: success)
42
42
  publish_lesson(runner: runner_class, function: function, success: success)
43
43
  rescue StandardError => e
44
- Legion::Logging.debug "[TaskOutcomeObserver] handle_outcome error: #{e.message}" if defined?(Legion::Logging)
44
+ Legion::Logging.warn "[TaskOutcomeObserver] handle_outcome error: #{e.class}: #{e.message}" if defined?(Legion::Logging)
45
45
  end
46
46
 
47
47
  def derive_domain(runner_class)
@@ -53,13 +53,15 @@ module Legion
53
53
  end
54
54
 
55
55
  def record_learning(domain:, success:)
56
- return unless defined?(Legion::Extensions::Agentic::Learning::MetaLearning)
56
+ client = meta_learning_client
57
+ return unless client
57
58
 
58
- Legion::Extensions::Agentic::Learning::MetaLearning.record_learning_episode(
59
- domain_id: domain, success: success
60
- )
59
+ domain_id = resolve_learning_domain_id(client, domain)
60
+ return unless domain_id
61
+
62
+ client.record_learning_episode(domain_id: domain_id, success: success)
61
63
  rescue StandardError => e
62
- Legion::Logging.debug "[TaskOutcomeObserver] record_learning failed: #{e.message}" if defined?(Legion::Logging)
64
+ Legion::Logging.warn "[TaskOutcomeObserver] record_learning failed: #{e.class}: #{e.message}" if defined?(Legion::Logging)
63
65
  end
64
66
 
65
67
  def publish_lesson(runner:, function:, success:, **_opts)
@@ -76,7 +78,7 @@ module Legion
76
78
  is_inference: false
77
79
  )
78
80
  rescue StandardError => e
79
- Legion::Logging.debug "[TaskOutcomeObserver] publish_lesson failed: #{e.message}" if defined?(Legion::Logging)
81
+ Legion::Logging.warn "[TaskOutcomeObserver] publish_lesson failed: #{e.class}: #{e.message}" if defined?(Legion::Logging)
80
82
  end
81
83
 
82
84
  def setup_llm_reflection_hook
@@ -94,7 +96,29 @@ module Legion
94
96
  Legion::LLM::Hooks::Reflection.install
95
97
  Legion::Logging.info '[TaskOutcomeObserver] LLM reflection hook auto-installed'
96
98
  rescue StandardError => e
97
- Legion::Logging.debug "[TaskOutcomeObserver] LLM reflection hook install failed: #{e.message}" if defined?(Legion::Logging)
99
+ Legion::Logging.warn "[TaskOutcomeObserver] LLM reflection hook install failed: #{e.class}: #{e.message}" if defined?(Legion::Logging)
100
+ end
101
+
102
+ def meta_learning_client
103
+ return unless defined?(Legion::Extensions::Agentic::Learning::MetaLearning::Client)
104
+
105
+ @meta_learning_client ||= Legion::Extensions::Agentic::Learning::MetaLearning::Client.new
106
+ end
107
+
108
+ def resolve_learning_domain_id(client, domain)
109
+ domain_map = learning_domain_map
110
+ return domain_map[domain] if domain_map.key?(domain)
111
+
112
+ result = client.create_learning_domain(name: domain)
113
+ return if result.is_a?(Hash) && result[:error]
114
+
115
+ domain_id = result[:id]
116
+ domain_map[domain] = domain_id if domain_id
117
+ domain_id
118
+ end
119
+
120
+ def learning_domain_map
121
+ @learning_domain_map ||= {}
98
122
  end
99
123
  end
100
124
  end
@@ -1,7 +1,11 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'legion/logging/helper'
4
+
3
5
  module Legion
4
6
  module Telemetry
7
+ extend Legion::Logging::Helper
8
+
5
9
  autoload :OpenInference, 'legion/telemetry/open_inference'
6
10
  autoload :SafetyMetrics, 'legion/telemetry/safety_metrics'
7
11
 
@@ -11,14 +15,14 @@ module Legion
11
15
  defined?(OpenTelemetry::Trace) &&
12
16
  OpenTelemetry::Trace.current_span != OpenTelemetry::Trace::Span::INVALID
13
17
  rescue StandardError => e
14
- Legion::Logging.debug "Telemetry#otel_available? failed: #{e.message}" if defined?(Legion::Logging)
18
+ handle_exception(e, level: :debug, operation: 'telemetry.otel_available')
15
19
  false
16
20
  end
17
21
 
18
22
  def enabled?
19
23
  defined?(OpenTelemetry::SDK) ? true : false
20
24
  rescue StandardError => e
21
- Legion::Logging.debug "Telemetry#enabled? failed: #{e.message}" if defined?(Legion::Logging)
25
+ handle_exception(e, level: :debug, operation: 'telemetry.enabled')
22
26
  false
23
27
  end
24
28
 
@@ -29,13 +33,13 @@ module Legion
29
33
  return
30
34
  end
31
35
 
32
- Legion::Logging.debug "[Telemetry] span: #{name}" if defined?(Legion::Logging)
36
+ log.debug { "[Telemetry] starting span=#{name} kind=#{kind}" }
33
37
  tracer = OpenTelemetry.tracer_provider.tracer('legion', Legion::VERSION)
34
38
  tracer.in_span(name, kind: kind, attributes: sanitize_attributes(attributes), &)
35
39
  rescue StandardError => e
36
40
  raise if block_given? && !otel_init_error?(e)
37
41
 
38
- Legion::Logging.debug "[Telemetry] span error for #{name}: #{e.message}" if defined?(Legion::Logging)
42
+ handle_exception(e, level: :debug, operation: 'telemetry.with_span', span_name: name, kind: kind)
39
43
  yield(nil) if block_given?
40
44
  end
41
45
 
@@ -45,7 +49,7 @@ module Legion
45
49
  span.record_exception(exception)
46
50
  span.status = OpenTelemetry::Trace::Status.error(exception.message)
47
51
  rescue StandardError => e
48
- Legion::Logging.debug "Telemetry#record_exception failed: #{e.message}" if defined?(Legion::Logging)
52
+ handle_exception(e, level: :debug, operation: 'telemetry.record_exception')
49
53
  nil
50
54
  end
51
55
 
@@ -60,7 +64,7 @@ module Legion
60
64
  [k.to_s, val]
61
65
  end
62
66
  rescue StandardError => e
63
- Legion::Logging.debug "Telemetry#sanitize_attributes failed: #{e.message}" if defined?(Legion::Logging)
67
+ handle_exception(e, level: :debug, operation: 'telemetry.sanitize_attributes')
64
68
  {}
65
69
  end
66
70
 
@@ -82,14 +86,14 @@ module Legion
82
86
  tracing = telemetry[:tracing]
83
87
  tracing.is_a?(Hash) ? tracing : {}
84
88
  rescue StandardError => e
85
- Legion::Logging.debug "Telemetry#tracing_settings failed: #{e.message}" if defined?(Legion::Logging)
89
+ handle_exception(e, level: :debug, operation: 'telemetry.tracing_settings')
86
90
  {}
87
91
  end
88
92
 
89
93
  def otel_init_error?(error)
90
94
  error.message.include?('OpenTelemetry') || error.message.include?('tracer')
91
95
  rescue StandardError => e
92
- Legion::Logging.debug "Telemetry#otel_init_error? check failed: #{e.message}" if defined?(Legion::Logging)
96
+ handle_exception(e, level: :debug, operation: 'telemetry.otel_init_error?')
93
97
  false
94
98
  end
95
99
 
@@ -111,10 +115,13 @@ module Legion
111
115
  )
112
116
 
113
117
  OpenTelemetry.tracer_provider.add_span_processor(processor)
114
- Legion::Logging.info "OTLP exporter configured: #{endpoint}"
118
+ log.info "OTLP exporter configured: #{endpoint}"
115
119
  true
116
120
  rescue LoadError
117
- Legion::Logging.warn 'opentelemetry-exporter-otlp gem not available'
121
+ log.warn 'opentelemetry-exporter-otlp gem not available'
122
+ false
123
+ rescue StandardError => e
124
+ handle_exception(e, level: :warn, operation: 'telemetry.configure_otlp', endpoint: endpoint)
118
125
  false
119
126
  end
120
127
 
@@ -124,9 +131,10 @@ module Legion
124
131
  exporter = OpenTelemetry::SDK::Trace::Export::ConsoleSpanExporter.new
125
132
  processor = OpenTelemetry::SDK::Trace::Export::SimpleSpanProcessor.new(exporter)
126
133
  OpenTelemetry.tracer_provider.add_span_processor(processor)
134
+ log.info 'Console telemetry exporter configured'
127
135
  true
128
136
  rescue StandardError => e
129
- Legion::Logging.debug "Telemetry#configure_console failed: #{e.message}" if defined?(Legion::Logging)
137
+ handle_exception(e, level: :debug, operation: 'telemetry.configure_console')
130
138
  false
131
139
  end
132
140
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Legion
4
- VERSION = '1.7.8'
4
+ VERSION = '1.7.13'
5
5
  end
@@ -3,10 +3,15 @@
3
3
  require 'openssl'
4
4
  require 'net/http'
5
5
  require 'uri'
6
+ require 'legion/logging/helper'
6
7
 
7
8
  module Legion
8
9
  module Webhooks
10
+ DISPATCH_CACHE_TTL = 5
11
+
9
12
  class << self
13
+ include Legion::Logging::Helper
14
+
10
15
  def register(url:, secret:, event_types: ['*'], max_retries: 5, **)
11
16
  return { error: 'data_unavailable' } unless db_available?
12
17
 
@@ -19,6 +24,7 @@ module Legion
19
24
  created_at: Time.now.utc,
20
25
  updated_at: Time.now.utc
21
26
  )
27
+ invalidate_dispatch_cache!
22
28
  { registered: true, id: id }
23
29
  end
24
30
 
@@ -26,6 +32,7 @@ module Legion
26
32
  return { error: 'data_unavailable' } unless db_available?
27
33
 
28
34
  Legion::Data.connection[:webhooks].where(id: id).delete
35
+ invalidate_dispatch_cache!
29
36
  { unregistered: true }
30
37
  end
31
38
 
@@ -38,26 +45,111 @@ module Legion
38
45
  def dispatch(event_name, payload)
39
46
  return unless db_available?
40
47
 
41
- webhooks = Legion::Data.connection[:webhooks].where(status: 'active').all
48
+ webhooks = active_dispatch_webhooks
42
49
  webhooks.each do |wh|
43
- patterns = begin
44
- Legion::JSON.load(wh[:event_types])
45
- rescue StandardError => e
46
- Legion::Logging.debug("Webhooks#dispatch event_types parse failed: #{e.message}") if defined?(Legion::Logging)
47
- ['*']
48
- end
50
+ patterns = event_patterns_for(wh, event_name: event_name)
49
51
  next unless patterns.any? { |p| File.fnmatch?(p, event_name) }
50
52
 
53
+ log.debug { "[Webhooks] dispatching event=#{event_name} webhook_id=#{wh[:id]} patterns=#{patterns.size}" }
51
54
  deliver(wh, event_name, payload)
52
55
  end
53
56
  end
54
57
 
55
58
  def deliver(webhook, event_name, payload, attempt: 1)
56
- Legion::Logging.info "[Webhooks] delivery attempt #{attempt} for event=#{event_name} url=#{webhook[:url]}" if defined?(Legion::Logging)
57
- body = Legion::JSON.dump({ event: event_name, payload: payload, timestamp: Time.now.utc.iso8601 })
59
+ log.info "[Webhooks] delivery attempt #{attempt} for event=#{event_name} url=#{webhook[:url]}"
60
+ body = delivery_body(event_name, payload)
58
61
  signature = compute_signature(webhook[:secret], body)
59
62
 
60
- uri = URI.parse(webhook[:url])
63
+ response = perform_delivery_request(webhook[:url], event_name, body, signature)
64
+ success = response.code.to_i < 400
65
+
66
+ if success
67
+ log.info "[Webhooks] delivered event=#{event_name} status=#{response.code}"
68
+ else
69
+ log.warn "[Webhooks] delivery failed event=#{event_name} status=#{response.code} url=#{webhook[:url]}"
70
+ end
71
+
72
+ handle_delivery_response(
73
+ webhook: webhook,
74
+ event_name: event_name,
75
+ payload: payload,
76
+ response: response,
77
+ success: success,
78
+ attempt: attempt
79
+ )
80
+ rescue StandardError => e
81
+ handle_exception(
82
+ e,
83
+ level: :error,
84
+ operation: 'webhooks.deliver',
85
+ event_name: event_name,
86
+ webhook_id: webhook[:id],
87
+ attempt: attempt,
88
+ url: webhook[:url]
89
+ )
90
+ handle_delivery_exception(webhook, event_name, payload, attempt, e)
91
+ end
92
+
93
+ def compute_signature(secret, body)
94
+ OpenSSL::HMAC.hexdigest('SHA256', secret, body)
95
+ end
96
+
97
+ private
98
+
99
+ def invalidate_dispatch_cache!
100
+ @active_webhooks_cache = nil
101
+ @active_webhooks_cached_at = nil
102
+ @pattern_cache = {}
103
+ end
104
+
105
+ def active_dispatch_webhooks
106
+ cache_valid = @active_webhooks_cache && @active_webhooks_cached_at &&
107
+ (monotonic_now - @active_webhooks_cached_at) < DISPATCH_CACHE_TTL
108
+ return @active_webhooks_cache if cache_valid
109
+
110
+ @active_webhooks_cache = Legion::Data.connection[:webhooks].where(status: 'active').all
111
+ @active_webhooks_cached_at = monotonic_now
112
+ @active_webhooks_cache
113
+ end
114
+
115
+ def monotonic_now
116
+ ::Process.clock_gettime(::Process::CLOCK_MONOTONIC)
117
+ end
118
+
119
+ def event_patterns_for(webhook, event_name:)
120
+ @pattern_cache ||= {}
121
+ cached_entry = @pattern_cache[webhook[:id]]
122
+
123
+ if cached_entry &&
124
+ cached_entry[:updated_at] == webhook[:updated_at] &&
125
+ cached_entry[:event_types] == webhook[:event_types]
126
+ return cached_entry[:patterns]
127
+ end
128
+
129
+ patterns = parse_event_patterns(webhook[:event_types], webhook_id: webhook[:id], event_name: event_name)
130
+ @pattern_cache[webhook[:id]] = {
131
+ updated_at: webhook[:updated_at],
132
+ event_types: webhook[:event_types],
133
+ patterns: patterns
134
+ }
135
+ patterns
136
+ end
137
+
138
+ def parse_event_patterns(raw_event_types, webhook_id:, event_name:)
139
+ parsed = Legion::JSON.load(raw_event_types)
140
+ Array(parsed).map(&:to_s).reject(&:empty?).then { |patterns| patterns.empty? ? ['*'] : patterns }
141
+ rescue StandardError => e
142
+ handle_exception(e, level: :debug, operation: 'webhooks.dispatch.parse_event_types',
143
+ event_name: event_name, webhook_id: webhook_id)
144
+ ['*']
145
+ end
146
+
147
+ def delivery_body(event_name, payload)
148
+ Legion::JSON.dump({ event: event_name, payload: payload, timestamp: Time.now.utc.iso8601 })
149
+ end
150
+
151
+ def perform_delivery_request(url, event_name, body, signature)
152
+ uri = URI.parse(url)
61
153
  http = Net::HTTP.new(uri.host, uri.port)
62
154
  http.use_ssl = uri.scheme == 'https'
63
155
  http.open_timeout = 5
@@ -68,54 +160,90 @@ module Legion
68
160
  request['X-Legion-Signature'] = "sha256=#{signature}"
69
161
  request['X-Legion-Event'] = event_name
70
162
  request.body = body
163
+ http.request(request)
164
+ end
71
165
 
72
- response = http.request(request)
73
- success = response.code.to_i < 400
166
+ def handle_delivery_response(delivery)
167
+ error_message = "http_status=#{delivery[:response].code}" unless delivery[:success]
168
+ record_delivery(
169
+ webhook_id: delivery[:webhook][:id],
170
+ event_name: delivery[:event_name],
171
+ status: delivery[:response].code.to_i,
172
+ success: delivery[:success],
173
+ error: error_message,
174
+ attempt: delivery[:attempt]
175
+ )
176
+ return { delivered: true, status: delivery[:response].code.to_i } if delivery[:success]
74
177
 
75
- if success
76
- Legion::Logging.info "[Webhooks] delivered event=#{event_name} status=#{response.code}" if defined?(Legion::Logging)
77
- elsif defined?(Legion::Logging)
78
- Legion::Logging.error "[Webhooks] delivery failed event=#{event_name} status=#{response.code} url=#{webhook[:url]}"
79
- end
178
+ finalize_failure(
179
+ webhook: delivery[:webhook],
180
+ event_name: delivery[:event_name],
181
+ payload: delivery[:payload],
182
+ attempt: delivery[:attempt],
183
+ error: error_message,
184
+ response_status: delivery[:response].code.to_i
185
+ )
186
+ end
80
187
 
81
- record_delivery(webhook[:id], event_name, response.code.to_i, success)
82
- { delivered: success, status: response.code.to_i }
83
- rescue StandardError => e
84
- Legion::Logging.error "[Webhooks] delivery error event=#{event_name}: #{e.message}" if defined?(Legion::Logging)
85
- record_delivery(webhook[:id], event_name, nil, false, error: e.message)
86
- if attempt < (webhook[:max_retries] || 5)
87
- Legion::Logging.warn "[Webhooks] will retry event=#{event_name} attempt=#{attempt}" if defined?(Legion::Logging)
88
- { delivered: false, error: e.message, will_retry: true }
89
- else
90
- dead_letter(webhook[:id], event_name, payload, attempt, e.message)
91
- { delivered: false, error: e.message, dead_lettered: true }
188
+ def handle_delivery_exception(webhook, event_name, payload, attempt, error)
189
+ record_delivery(
190
+ webhook_id: webhook[:id],
191
+ event_name: event_name,
192
+ status: nil,
193
+ success: false,
194
+ error: error.message,
195
+ attempt: attempt
196
+ )
197
+ finalize_failure(
198
+ webhook: webhook,
199
+ event_name: event_name,
200
+ payload: payload,
201
+ attempt: attempt,
202
+ error: error.message
203
+ )
204
+ end
205
+
206
+ def finalize_failure(failure)
207
+ if retry_pending?(failure[:webhook], failure[:attempt])
208
+ next_attempt = failure[:attempt] + 1
209
+ log.warn "[Webhooks] retrying event=#{failure[:event_name]} next_attempt=#{next_attempt}"
210
+ return deliver(failure[:webhook], failure[:event_name], failure[:payload], attempt: next_attempt)
92
211
  end
212
+
213
+ dead_letter(failure[:webhook][:id], failure[:event_name], failure[:payload], failure[:attempt], failure[:error])
214
+ { delivered: false, error: failure[:error], dead_lettered: true, status: failure[:response_status] }
93
215
  end
94
216
 
95
- def compute_signature(secret, body)
96
- OpenSSL::HMAC.hexdigest('SHA256', secret, body)
217
+ def retry_pending?(webhook, attempt)
218
+ attempt <= retry_limit(webhook)
97
219
  end
98
220
 
99
- private
221
+ def retry_limit(webhook)
222
+ retries = webhook[:max_retries].to_i
223
+ retries.negative? ? 0 : retries
224
+ end
100
225
 
101
226
  def db_available?
102
227
  defined?(Legion::Data) && Legion::Data.respond_to?(:connection) && Legion::Data.connection
103
228
  rescue StandardError => e
104
- Legion::Logging.debug("Webhooks#db_available? failed: #{e.message}") if defined?(Legion::Logging)
229
+ handle_exception(e, level: :debug, operation: 'webhooks.db_available?')
105
230
  false
106
231
  end
107
232
 
108
- def record_delivery(webhook_id, event_name, status, success, error: nil)
233
+ def record_delivery(delivery)
109
234
  Legion::Data.connection[:webhook_deliveries].insert(
110
- webhook_id: webhook_id,
111
- event_name: event_name,
112
- response_status: status,
113
- success: success,
114
- error: error,
235
+ webhook_id: delivery[:webhook_id],
236
+ event_name: delivery[:event_name],
237
+ response_status: delivery[:status],
238
+ success: delivery[:success],
239
+ attempt: delivery.fetch(:attempt, 1),
240
+ error: delivery[:error],
115
241
  delivered_at: Time.now.utc
116
242
  )
117
243
  rescue StandardError => e
118
- Legion::Logging.debug("Webhooks#record_delivery failed: #{e.message}") if defined?(Legion::Logging)
244
+ handle_exception(e, level: :debug, operation: 'webhooks.record_delivery',
245
+ webhook_id: delivery[:webhook_id], event_name: delivery[:event_name],
246
+ status: delivery[:status], success: delivery[:success], attempt: delivery.fetch(:attempt, 1))
119
247
  nil
120
248
  end
121
249
 
@@ -129,7 +257,8 @@ module Legion
129
257
  created_at: Time.now.utc
130
258
  )
131
259
  rescue StandardError => e
132
- Legion::Logging.debug("Webhooks#dead_letter failed: #{e.message}") if defined?(Legion::Logging)
260
+ handle_exception(e, level: :debug, operation: 'webhooks.dead_letter',
261
+ webhook_id: webhook_id, event_name: event_name, attempts: attempts)
133
262
  nil
134
263
  end
135
264
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: legionio
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.7.8
4
+ version: 1.7.13
5
5
  platform: ruby
6
6
  authors:
7
7
  - Esity
@@ -15,14 +15,14 @@ dependencies:
15
15
  requirements:
16
16
  - - ">="
17
17
  - !ruby/object:Gem::Version
18
- version: 0.5.1
18
+ version: 0.7.1
19
19
  type: :runtime
20
20
  prerelease: false
21
21
  version_requirements: !ruby/object:Gem::Requirement
22
22
  requirements:
23
23
  - - ">="
24
24
  - !ruby/object:Gem::Version
25
- version: 0.5.1
25
+ version: 0.7.1
26
26
  - !ruby/object:Gem::Dependency
27
27
  name: kramdown
28
28
  requirement: !ruby/object:Gem::Requirement
@@ -225,42 +225,42 @@ dependencies:
225
225
  requirements:
226
226
  - - ">="
227
227
  - !ruby/object:Gem::Version
228
- version: 1.3.16
228
+ version: 1.3.22
229
229
  type: :runtime
230
230
  prerelease: false
231
231
  version_requirements: !ruby/object:Gem::Requirement
232
232
  requirements:
233
233
  - - ">="
234
234
  - !ruby/object:Gem::Version
235
- version: 1.3.16
235
+ version: 1.3.22
236
236
  - !ruby/object:Gem::Dependency
237
237
  name: legion-crypt
238
238
  requirement: !ruby/object:Gem::Requirement
239
239
  requirements:
240
240
  - - ">="
241
241
  - !ruby/object:Gem::Version
242
- version: 1.4.17
242
+ version: 1.5.1
243
243
  type: :runtime
244
244
  prerelease: false
245
245
  version_requirements: !ruby/object:Gem::Requirement
246
246
  requirements:
247
247
  - - ">="
248
248
  - !ruby/object:Gem::Version
249
- version: 1.4.17
249
+ version: 1.5.1
250
250
  - !ruby/object:Gem::Dependency
251
251
  name: legion-data
252
252
  requirement: !ruby/object:Gem::Requirement
253
253
  requirements:
254
254
  - - ">="
255
255
  - !ruby/object:Gem::Version
256
- version: 1.6.7
256
+ version: 1.6.19
257
257
  type: :runtime
258
258
  prerelease: false
259
259
  version_requirements: !ruby/object:Gem::Requirement
260
260
  requirements:
261
261
  - - ">="
262
262
  - !ruby/object:Gem::Version
263
- version: 1.6.7
263
+ version: 1.6.19
264
264
  - !ruby/object:Gem::Dependency
265
265
  name: legion-json
266
266
  requirement: !ruby/object:Gem::Requirement
@@ -281,56 +281,56 @@ dependencies:
281
281
  requirements:
282
282
  - - ">="
283
283
  - !ruby/object:Gem::Version
284
- version: 1.4.0
284
+ version: 1.5.0
285
285
  type: :runtime
286
286
  prerelease: false
287
287
  version_requirements: !ruby/object:Gem::Requirement
288
288
  requirements:
289
289
  - - ">="
290
290
  - !ruby/object:Gem::Version
291
- version: 1.4.0
291
+ version: 1.5.0
292
292
  - !ruby/object:Gem::Dependency
293
293
  name: legion-settings
294
294
  requirement: !ruby/object:Gem::Requirement
295
295
  requirements:
296
296
  - - ">="
297
297
  - !ruby/object:Gem::Version
298
- version: 1.3.19
298
+ version: 1.3.25
299
299
  type: :runtime
300
300
  prerelease: false
301
301
  version_requirements: !ruby/object:Gem::Requirement
302
302
  requirements:
303
303
  - - ">="
304
304
  - !ruby/object:Gem::Version
305
- version: 1.3.19
305
+ version: 1.3.25
306
306
  - !ruby/object:Gem::Dependency
307
307
  name: legion-transport
308
308
  requirement: !ruby/object:Gem::Requirement
309
309
  requirements:
310
310
  - - ">="
311
311
  - !ruby/object:Gem::Version
312
- version: 1.4.4
312
+ version: 1.4.14
313
313
  type: :runtime
314
314
  prerelease: false
315
315
  version_requirements: !ruby/object:Gem::Requirement
316
316
  requirements:
317
317
  - - ">="
318
318
  - !ruby/object:Gem::Version
319
- version: 1.4.4
319
+ version: 1.4.14
320
320
  - !ruby/object:Gem::Dependency
321
321
  name: legion-apollo
322
322
  requirement: !ruby/object:Gem::Requirement
323
323
  requirements:
324
324
  - - ">="
325
325
  - !ruby/object:Gem::Version
326
- version: 0.3.1
326
+ version: 0.4.0
327
327
  type: :runtime
328
328
  prerelease: false
329
329
  version_requirements: !ruby/object:Gem::Requirement
330
330
  requirements:
331
331
  - - ">="
332
332
  - !ruby/object:Gem::Version
333
- version: 0.3.1
333
+ version: 0.4.0
334
334
  - !ruby/object:Gem::Dependency
335
335
  name: legion-gaia
336
336
  requirement: !ruby/object:Gem::Requirement