lex-mesh 0.4.1 → 0.4.2
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/Gemfile +1 -0
- data/lib/legion/extensions/mesh/actors/gossip.rb +1 -1
- data/lib/legion/extensions/mesh/actors/heartbeat.rb +1 -1
- data/lib/legion/extensions/mesh/actors/pending_expiry.rb +1 -1
- data/lib/legion/extensions/mesh/actors/preference_listener.rb +3 -3
- data/lib/legion/extensions/mesh/actors/silence_watchdog.rb +1 -1
- data/lib/legion/extensions/mesh/client.rb +1 -1
- data/lib/legion/extensions/mesh/helpers/peer_verify.rb +6 -6
- data/lib/legion/extensions/mesh/helpers/pending_requests.rb +1 -1
- data/lib/legion/extensions/mesh/helpers/preference_profile.rb +12 -12
- data/lib/legion/extensions/mesh/helpers/registry.rb +1 -1
- data/lib/legion/extensions/mesh/runners/mesh.rb +5 -5
- data/lib/legion/extensions/mesh/runners/preferences.rb +7 -7
- data/lib/legion/extensions/mesh/runners/task_request.rb +3 -3
- data/lib/legion/extensions/mesh/version.rb +1 -1
- data/lib/legion/extensions/mesh.rb +2 -2
- data/spec/legion/extensions/mesh/runners/mesh_gossip_spec.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: edbe1f87a3c1b6cad5d87f2ee8c1b04551b9bbd36804c7d4f71ed18f9833f58e
|
|
4
|
+
data.tar.gz: 50f43be7cffacaa7b23e316d2f69a1763a2b82a7437f7d1e854e4f5cd088bc3e
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: d14a5e8b04963df9a79bdc216c27c669330801c2d0677299908a15cbf2abd125b2e841a245a678823c6c9efab9b83c13e7b0d35b230ae0ba13ddbc42c0e152fc
|
|
7
|
+
data.tar.gz: fe99ad0868788b91826c3bfa25dbbaa131e63b471b409e9ae110c4296bb2af8f44a366939331fff63f9358b6d49e1f513bc268aaf3f2c6c00ac530791c4a4060
|
data/Gemfile
CHANGED
|
@@ -6,7 +6,7 @@ module Legion
|
|
|
6
6
|
module Extensions
|
|
7
7
|
module Mesh
|
|
8
8
|
module Actor
|
|
9
|
-
class Gossip < Legion::Extensions::Actors::Every
|
|
9
|
+
class Gossip < Legion::Extensions::Actors::Every # rubocop:disable Legion/Extension/EveryActorRequiresTime
|
|
10
10
|
def runner_class
|
|
11
11
|
Legion::Extensions::Mesh::Runners::Mesh
|
|
12
12
|
end
|
|
@@ -6,7 +6,7 @@ module Legion
|
|
|
6
6
|
module Extensions
|
|
7
7
|
module Mesh
|
|
8
8
|
module Actor
|
|
9
|
-
class Heartbeat < Legion::Extensions::Actors::Every
|
|
9
|
+
class Heartbeat < Legion::Extensions::Actors::Every # rubocop:disable Legion/Extension/EveryActorRequiresTime
|
|
10
10
|
def runner_class
|
|
11
11
|
Legion::Extensions::Mesh::Runners::Mesh
|
|
12
12
|
end
|
|
@@ -6,7 +6,7 @@ module Legion
|
|
|
6
6
|
module Extensions
|
|
7
7
|
module Mesh
|
|
8
8
|
module Actor
|
|
9
|
-
class PendingExpiry < Legion::Extensions::Actors::Every
|
|
9
|
+
class PendingExpiry < Legion::Extensions::Actors::Every # rubocop:disable Legion/Extension/EveryActorRequiresTime
|
|
10
10
|
def runner_class
|
|
11
11
|
Legion::Extensions::Mesh::Runners::Preferences
|
|
12
12
|
end
|
|
@@ -31,10 +31,10 @@ module Legion
|
|
|
31
31
|
Legion::Extensions::Mesh::Transport::Queues::Preference
|
|
32
32
|
end
|
|
33
33
|
|
|
34
|
-
def enabled?
|
|
34
|
+
def enabled? # rubocop:disable Legion/Extension/ActorEnabledSideEffects
|
|
35
35
|
defined?(Legion::Extensions::Mesh::Runners::Preferences) &&
|
|
36
|
-
|
|
37
|
-
rescue StandardError
|
|
36
|
+
Legion.const_defined?(:Transport, false)
|
|
37
|
+
rescue StandardError => _e
|
|
38
38
|
false
|
|
39
39
|
end
|
|
40
40
|
end
|
|
@@ -6,7 +6,7 @@ module Legion
|
|
|
6
6
|
module Extensions
|
|
7
7
|
module Mesh
|
|
8
8
|
module Actor
|
|
9
|
-
class SilenceWatchdog < Legion::Extensions::Actors::Every
|
|
9
|
+
class SilenceWatchdog < Legion::Extensions::Actors::Every # rubocop:disable Legion/Extension/EveryActorRequiresTime
|
|
10
10
|
def runner_class
|
|
11
11
|
Legion::Extensions::Mesh::Runners::Mesh
|
|
12
12
|
end
|
|
@@ -21,21 +21,21 @@ module Legion
|
|
|
21
21
|
return { valid: false, org_id: org_id, reason: :unknown_peer } unless peer
|
|
22
22
|
|
|
23
23
|
require 'ed25519'
|
|
24
|
-
pub_key_b64 = peer[:public_key].
|
|
24
|
+
pub_key_b64 = peer[:public_key].delete_prefix('ed25519:')
|
|
25
25
|
verify_key = Ed25519::VerifyKey.new(Base64.strict_decode64(pub_key_b64))
|
|
26
26
|
signature = Base64.strict_decode64(signed_message[:signature])
|
|
27
27
|
message_bytes = signed_message[:signed_bytes] || json_dump(signed_message[:payload])
|
|
28
28
|
verify_key.verify(signature, message_bytes)
|
|
29
29
|
{ valid: true, org_id: org_id }
|
|
30
|
-
rescue Ed25519::VerifyError
|
|
30
|
+
rescue Ed25519::VerifyError => _e
|
|
31
31
|
{ valid: false, org_id: org_id, reason: :invalid_signature }
|
|
32
32
|
rescue StandardError => e
|
|
33
33
|
{ valid: false, org_id: org_id, reason: :error, message: e.message }
|
|
34
34
|
end
|
|
35
35
|
|
|
36
36
|
def check_rate_limit(org_id)
|
|
37
|
-
@counters ||= Hash.new { |h, k| h[k] = { count: 0, window_start: Time.now.utc } }
|
|
38
|
-
counter = @counters[org_id]
|
|
37
|
+
@counters ||= Hash.new { |h, k| h[k] = { count: 0, window_start: Time.now.utc } } # rubocop:disable ThreadSafety/ClassInstanceVariable
|
|
38
|
+
counter = @counters[org_id] # rubocop:disable ThreadSafety/ClassInstanceVariable
|
|
39
39
|
peer = find_peer(org_id)
|
|
40
40
|
limit = peer&.dig(:rate_limit) || 100
|
|
41
41
|
|
|
@@ -51,7 +51,7 @@ module Legion
|
|
|
51
51
|
end
|
|
52
52
|
|
|
53
53
|
def reset_counters!
|
|
54
|
-
@counters = nil
|
|
54
|
+
@counters = nil # rubocop:disable ThreadSafety/ClassInstanceVariable
|
|
55
55
|
end
|
|
56
56
|
|
|
57
57
|
private
|
|
@@ -65,7 +65,7 @@ module Legion
|
|
|
65
65
|
|
|
66
66
|
def json_dump(data)
|
|
67
67
|
if defined?(Legion::JSON)
|
|
68
|
-
Legion::JSON.dump({ data: data })
|
|
68
|
+
Legion::JSON.dump({ data: data }) # rubocop:disable Legion/HelperMigration/DirectJson
|
|
69
69
|
else
|
|
70
70
|
require 'json'
|
|
71
71
|
::JSON.dump({ data: data })
|
|
@@ -124,8 +124,8 @@ module Legion
|
|
|
124
124
|
MESH_CACHE_TTL = 3600 # 1 hour default
|
|
125
125
|
|
|
126
126
|
def store_mesh_profile(agent_id:, profile:, source_agent_id:)
|
|
127
|
-
@mesh_cache ||= {}
|
|
128
|
-
@mesh_cache[agent_id.to_s] = {
|
|
127
|
+
@mesh_cache ||= {} # rubocop:disable ThreadSafety/ClassInstanceVariable
|
|
128
|
+
@mesh_cache[agent_id.to_s] = { # rubocop:disable ThreadSafety/ClassInstanceVariable
|
|
129
129
|
profile: profile,
|
|
130
130
|
source_agent_id: source_agent_id,
|
|
131
131
|
origin: :mesh_transfer,
|
|
@@ -147,26 +147,26 @@ module Legion
|
|
|
147
147
|
end
|
|
148
148
|
|
|
149
149
|
def cached_mesh_profile(agent_id:, ttl: MESH_CACHE_TTL)
|
|
150
|
-
@mesh_cache ||= {}
|
|
151
|
-
entry = @mesh_cache[agent_id.to_s]
|
|
150
|
+
@mesh_cache ||= {} # rubocop:disable ThreadSafety/ClassInstanceVariable
|
|
151
|
+
entry = @mesh_cache[agent_id.to_s] # rubocop:disable ThreadSafety/ClassInstanceVariable
|
|
152
152
|
return nil unless entry
|
|
153
153
|
|
|
154
154
|
if Time.now - entry[:cached_at] > ttl
|
|
155
|
-
@mesh_cache.delete(agent_id.to_s)
|
|
155
|
+
@mesh_cache.delete(agent_id.to_s) # rubocop:disable ThreadSafety/ClassInstanceVariable
|
|
156
156
|
return nil
|
|
157
157
|
end
|
|
158
158
|
|
|
159
159
|
entry[:profile]
|
|
160
|
-
rescue StandardError
|
|
160
|
+
rescue StandardError => _e
|
|
161
161
|
nil
|
|
162
162
|
end
|
|
163
163
|
|
|
164
164
|
def clear_mesh_cache(agent_id: nil)
|
|
165
|
-
@mesh_cache ||= {}
|
|
165
|
+
@mesh_cache ||= {} # rubocop:disable ThreadSafety/ClassInstanceVariable
|
|
166
166
|
if agent_id
|
|
167
|
-
@mesh_cache.delete(agent_id.to_s)
|
|
167
|
+
@mesh_cache.delete(agent_id.to_s) # rubocop:disable ThreadSafety/ClassInstanceVariable
|
|
168
168
|
else
|
|
169
|
-
@mesh_cache.clear
|
|
169
|
+
@mesh_cache.clear # rubocop:disable ThreadSafety/ClassInstanceVariable
|
|
170
170
|
end
|
|
171
171
|
end
|
|
172
172
|
|
|
@@ -214,7 +214,7 @@ module Legion
|
|
|
214
214
|
traces.select { |t| t[:domain_tags]&.include?('preference') }.filter_map do |trace|
|
|
215
215
|
parse_preference_trace(trace)
|
|
216
216
|
end
|
|
217
|
-
rescue StandardError
|
|
217
|
+
rescue StandardError => _e
|
|
218
218
|
[]
|
|
219
219
|
end
|
|
220
220
|
|
|
@@ -226,7 +226,7 @@ module Legion
|
|
|
226
226
|
return nil unless match
|
|
227
227
|
|
|
228
228
|
{ domain: match[1], value: match[2], source: match[3], confidence: trace[:confidence] }
|
|
229
|
-
rescue StandardError
|
|
229
|
+
rescue StandardError => _e
|
|
230
230
|
nil
|
|
231
231
|
end
|
|
232
232
|
|
|
@@ -239,7 +239,7 @@ module Legion
|
|
|
239
239
|
)
|
|
240
240
|
result = personality_runner.personality_compatibility(other_profile: profile[:personality])
|
|
241
241
|
{ score: result[:compatibility], interpretation: result[:interpretation] }
|
|
242
|
-
rescue StandardError
|
|
242
|
+
rescue StandardError => _e
|
|
243
243
|
nil
|
|
244
244
|
end
|
|
245
245
|
|
|
@@ -5,8 +5,8 @@ module Legion
|
|
|
5
5
|
module Mesh
|
|
6
6
|
module Runners
|
|
7
7
|
module Mesh
|
|
8
|
-
include Legion::Extensions::Helpers::Lex if Legion::Extensions.const_defined?(:Helpers) &&
|
|
9
|
-
Legion::Extensions::Helpers.const_defined?(:Lex)
|
|
8
|
+
include Legion::Extensions::Helpers::Lex if Legion::Extensions.const_defined?(:Helpers, false) &&
|
|
9
|
+
Legion::Extensions::Helpers.const_defined?(:Lex, false)
|
|
10
10
|
|
|
11
11
|
def register(agent_id:, capabilities: [], endpoint: nil, **)
|
|
12
12
|
mesh_registry.register_agent(agent_id, capabilities: capabilities, endpoint: endpoint)
|
|
@@ -134,18 +134,18 @@ module Legion
|
|
|
134
134
|
def gossip_max_peers
|
|
135
135
|
settings = Legion::Settings.dig(:mesh, :gossip)
|
|
136
136
|
(settings.is_a?(Hash) ? settings[:max_peers_per_message] : nil) || 100
|
|
137
|
-
rescue StandardError
|
|
137
|
+
rescue StandardError => _e
|
|
138
138
|
100
|
|
139
139
|
end
|
|
140
140
|
|
|
141
141
|
def local_node_name
|
|
142
142
|
Legion::Settings[:client][:name]
|
|
143
|
-
rescue StandardError
|
|
143
|
+
rescue StandardError => _e
|
|
144
144
|
'unknown'
|
|
145
145
|
end
|
|
146
146
|
|
|
147
147
|
def mesh_registry
|
|
148
|
-
@mesh_registry ||= Helpers::Registry.new
|
|
148
|
+
@mesh_registry ||= Helpers::Registry.new # rubocop:disable Legion/Singleton/UseInstance
|
|
149
149
|
end
|
|
150
150
|
end
|
|
151
151
|
end
|
|
@@ -7,8 +7,8 @@ module Legion
|
|
|
7
7
|
module Mesh
|
|
8
8
|
module Runners
|
|
9
9
|
module Preferences
|
|
10
|
-
include Legion::Extensions::Helpers::Lex if Legion::Extensions.const_defined?(:Helpers) &&
|
|
11
|
-
Legion::Extensions::Helpers.const_defined?(:Lex)
|
|
10
|
+
include Legion::Extensions::Helpers::Lex if Legion::Extensions.const_defined?(:Helpers, false) &&
|
|
11
|
+
Legion::Extensions::Helpers.const_defined?(:Lex, false)
|
|
12
12
|
|
|
13
13
|
def query_preferences(target_agent_id:, domains: nil, callback: nil, ttl: 5, **)
|
|
14
14
|
default_profile = Helpers::PreferenceProfile.resolve(owner_id: target_agent_id)
|
|
@@ -96,7 +96,7 @@ module Legion
|
|
|
96
96
|
else
|
|
97
97
|
'unknown'
|
|
98
98
|
end
|
|
99
|
-
rescue StandardError
|
|
99
|
+
rescue StandardError => _e
|
|
100
100
|
'unknown'
|
|
101
101
|
end
|
|
102
102
|
|
|
@@ -110,7 +110,7 @@ module Legion
|
|
|
110
110
|
correlation_id: msg[:correlation_id]
|
|
111
111
|
).publish
|
|
112
112
|
rescue StandardError => e
|
|
113
|
-
|
|
113
|
+
log.debug("[mesh] failed to publish preference response: #{e.message}")
|
|
114
114
|
end
|
|
115
115
|
|
|
116
116
|
def publish_preference_query(target_agent_id:, correlation_id:, domains:)
|
|
@@ -125,7 +125,7 @@ module Legion
|
|
|
125
125
|
|
|
126
126
|
def default_preference_callback(target_agent_id:)
|
|
127
127
|
lambda do |_profile|
|
|
128
|
-
|
|
128
|
+
log.debug("[mesh] received and cached preferences for #{target_agent_id}")
|
|
129
129
|
end
|
|
130
130
|
end
|
|
131
131
|
|
|
@@ -138,11 +138,11 @@ module Legion
|
|
|
138
138
|
evaluator = Object.new.extend(trust_mod)
|
|
139
139
|
result = evaluator.get_trust(agent_id: agent_id, domain: :general)
|
|
140
140
|
|
|
141
|
-
return :allowed unless result[:found]
|
|
141
|
+
return :allowed unless result[:found] # rubocop:disable Legion/Extension/RunnerReturnHash
|
|
142
142
|
|
|
143
143
|
composite = result.dig(:trust, :composite) || 0.0
|
|
144
144
|
composite >= Helpers::Topology::TRUST_CONSIDER_THRESHOLD ? :allowed : :denied
|
|
145
|
-
rescue StandardError
|
|
145
|
+
rescue StandardError => _e
|
|
146
146
|
:allowed
|
|
147
147
|
end
|
|
148
148
|
|
|
@@ -10,7 +10,7 @@ module Legion
|
|
|
10
10
|
module Extensions
|
|
11
11
|
module Mesh
|
|
12
12
|
module Runners
|
|
13
|
-
module TaskRequest
|
|
13
|
+
module TaskRequest # rubocop:disable Legion/Extension/RunnerIncludeHelpers
|
|
14
14
|
include Runners::Mesh
|
|
15
15
|
|
|
16
16
|
DEFAULT_TIMEOUT = 30
|
|
@@ -65,10 +65,10 @@ module Legion
|
|
|
65
65
|
private
|
|
66
66
|
|
|
67
67
|
def resolve_target(to)
|
|
68
|
-
return to if mesh_registry.agents.key?(to)
|
|
68
|
+
return to if mesh_registry.agents.key?(to) # rubocop:disable Legion/Extension/RunnerReturnHash
|
|
69
69
|
|
|
70
70
|
agents = mesh_registry.find_by_capability(to.to_sym)
|
|
71
|
-
return nil if agents.empty?
|
|
71
|
+
return nil if agents.empty? # rubocop:disable Legion/Extension/RunnerReturnHash
|
|
72
72
|
|
|
73
73
|
online = agents.select { |a| a[:status] == :online }
|
|
74
74
|
(online.empty? ? agents : online).sample[:agent_id]
|
|
@@ -12,7 +12,7 @@ require 'legion/extensions/mesh/runners/preferences'
|
|
|
12
12
|
require 'legion/extensions/mesh/runners/delegation'
|
|
13
13
|
require 'legion/extensions/mesh/runners/task_request'
|
|
14
14
|
|
|
15
|
-
if
|
|
15
|
+
if Legion.const_defined?(:Transport, false)
|
|
16
16
|
require 'legion/extensions/mesh/transport/messages/preference_query'
|
|
17
17
|
require 'legion/extensions/mesh/transport/messages/preference_response'
|
|
18
18
|
require 'legion/extensions/mesh/transport/messages/mesh_departure'
|
|
@@ -22,7 +22,7 @@ end
|
|
|
22
22
|
module Legion
|
|
23
23
|
module Extensions
|
|
24
24
|
module Mesh
|
|
25
|
-
extend Legion::Extensions::Core if Legion::Extensions.const_defined? :Core
|
|
25
|
+
extend Legion::Extensions::Core if Legion::Extensions.const_defined? :Core, false
|
|
26
26
|
end
|
|
27
27
|
end
|
|
28
28
|
end
|
|
@@ -7,7 +7,7 @@ RSpec.describe 'Gossip runner methods' do
|
|
|
7
7
|
|
|
8
8
|
before do
|
|
9
9
|
allow(subject).to receive(:mesh_registry).and_return(
|
|
10
|
-
Legion::Extensions::Mesh::Helpers::Registry.new
|
|
10
|
+
Legion::Extensions::Mesh::Helpers::Registry.new # rubocop:disable Legion/Singleton/UseInstance
|
|
11
11
|
)
|
|
12
12
|
end
|
|
13
13
|
|