lex-llm-bedrock 0.1.0 → 0.1.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/CHANGELOG.md +8 -0
- data/README.md +1 -1
- data/lex-llm-bedrock.gemspec +1 -1
- data/lib/legion/extensions/llm/bedrock/provider.rb +13 -2
- data/lib/legion/extensions/llm/bedrock/registry_event_builder.rb +93 -0
- data/lib/legion/extensions/llm/bedrock/registry_publisher.rb +100 -0
- data/lib/legion/extensions/llm/bedrock/transport/exchanges/llm_registry.rb +24 -0
- data/lib/legion/extensions/llm/bedrock/transport/messages/registry_event.rb +42 -0
- data/lib/legion/extensions/llm/bedrock/version.rb +1 -1
- data/lib/legion/extensions/llm/bedrock.rb +2 -0
- metadata +7 -3
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 5ec33f1d698328146833876f1b61387ad6523c88cd10c582c98202bb4f8dc72e
|
|
4
|
+
data.tar.gz: 0a4d8b1318967238535525779f4f37d623ae9c34db3f420a9f38869b4caddcf1
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 5ec0f51f96ded0783c297eec606e003a9f09c94dd83f351877fdeee5652eb0778d60842b7d43cebf505391fdd734d7bea071080e2c9d15268a746ecdeb984715
|
|
7
|
+
data.tar.gz: 55ac1281aabe5f8592ea643aebf457e79de527fdad49e47c8c7d685d30dfd0a04a86b09f3aaca27f0a3b8f4ae8211bf8c07d7fe27f8bae79b1167bba736a06e7
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.1.2 - 2026-04-28
|
|
4
|
+
|
|
5
|
+
- Publish best-effort `llm.registry` live readiness and live foundation-model availability events using `lex-llm` registry envelopes when transport is already available.
|
|
6
|
+
|
|
7
|
+
## 0.1.1 - 2026-04-28
|
|
8
|
+
|
|
9
|
+
- Require `lex-llm >= 0.1.5` for the shared model offering, alias, readiness, and fleet lane contract used by Bedrock routing metadata.
|
|
10
|
+
|
|
3
11
|
## 0.1.0 - 2026-04-28
|
|
4
12
|
|
|
5
13
|
- Initial Legion::Extensions::Llm Bedrock provider extension scaffold.
|
data/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
Amazon Bedrock provider extension for `Legion::Extensions::Llm`.
|
|
4
4
|
|
|
5
|
-
This gem adds a hosted Bedrock provider surface for Legion LLM routing without depending on the old `legion-llm` gem. It uses the official AWS SDK for Ruby and keeps discovery offline by default, so loading the extension or running tests does not require live AWS credentials.
|
|
5
|
+
This gem adds a hosted Bedrock provider surface for Legion LLM routing without depending on the old `legion-llm` gem. It uses the official AWS SDK for Ruby and keeps discovery offline by default, so loading the extension or running tests does not require live AWS credentials. It requires `lex-llm >= 0.1.5` for the shared model offering, alias, readiness, and fleet lane contract.
|
|
6
6
|
|
|
7
7
|
## Install
|
|
8
8
|
|
data/lex-llm-bedrock.gemspec
CHANGED
|
@@ -28,5 +28,5 @@ Gem::Specification.new do |spec|
|
|
|
28
28
|
spec.add_dependency 'legion-json', '>= 1.2.1'
|
|
29
29
|
spec.add_dependency 'legion-logging', '>= 1.3.2'
|
|
30
30
|
spec.add_dependency 'legion-settings', '>= 1.3.14'
|
|
31
|
-
spec.add_dependency 'lex-llm', '>= 0.1.
|
|
31
|
+
spec.add_dependency 'lex-llm', '>= 0.1.5'
|
|
32
32
|
end
|
|
@@ -26,6 +26,8 @@ module Legion
|
|
|
26
26
|
ALIASES = STATIC_MODELS.to_h { |entry| [entry.fetch(:alias), entry.fetch(:model)] }.freeze
|
|
27
27
|
|
|
28
28
|
class << self
|
|
29
|
+
attr_writer :registry_publisher
|
|
30
|
+
|
|
29
31
|
def slug = 'bedrock'
|
|
30
32
|
|
|
31
33
|
def configuration_options
|
|
@@ -43,6 +45,10 @@ module Legion
|
|
|
43
45
|
def configuration_requirements = []
|
|
44
46
|
def capabilities = Capabilities
|
|
45
47
|
|
|
48
|
+
def registry_publisher
|
|
49
|
+
@registry_publisher ||= RegistryPublisher.new
|
|
50
|
+
end
|
|
51
|
+
|
|
46
52
|
def resolve_model_id(model_id, config: nil) # rubocop:disable Lint/UnusedMethodArgument
|
|
47
53
|
ALIASES.fetch(model_id.to_s, model_id.to_s)
|
|
48
54
|
end
|
|
@@ -83,7 +89,9 @@ module Legion
|
|
|
83
89
|
return static_offerings(**filters) unless live
|
|
84
90
|
|
|
85
91
|
response = bedrock_client.list_foundation_models(**filters)
|
|
86
|
-
Array(value(response, :model_summaries)).map { |summary| offering_from_summary(summary) }
|
|
92
|
+
Array(value(response, :model_summaries)).map { |summary| offering_from_summary(summary) }.tap do |offerings|
|
|
93
|
+
self.class.registry_publisher.publish_offerings_async(offerings, readiness: readiness(live: false))
|
|
94
|
+
end
|
|
87
95
|
end
|
|
88
96
|
|
|
89
97
|
def offering_for(model:, model_family: nil, instance_id: :default, **metadata)
|
|
@@ -116,7 +124,10 @@ module Legion
|
|
|
116
124
|
end
|
|
117
125
|
|
|
118
126
|
def readiness(live: false)
|
|
119
|
-
health(live: live).merge(local: false, remote: true, api_base: api_base,
|
|
127
|
+
health(live: live).merge(local: false, remote: true, api_base: api_base,
|
|
128
|
+
endpoints: endpoint_manifest).tap do |metadata|
|
|
129
|
+
self.class.registry_publisher.publish_readiness_async(metadata) if live
|
|
130
|
+
end
|
|
120
131
|
end
|
|
121
132
|
|
|
122
133
|
def list_models
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Legion
|
|
4
|
+
module Extensions
|
|
5
|
+
module Llm
|
|
6
|
+
module Bedrock
|
|
7
|
+
# Builds sanitized lex-llm registry envelopes for Bedrock provider state.
|
|
8
|
+
class RegistryEventBuilder
|
|
9
|
+
def readiness(readiness)
|
|
10
|
+
registry_event_class.public_send(
|
|
11
|
+
readiness[:ready] ? :available : :unavailable,
|
|
12
|
+
provider_offering(readiness),
|
|
13
|
+
runtime: runtime_metadata,
|
|
14
|
+
health: readiness_health(readiness),
|
|
15
|
+
metadata: readiness_metadata(readiness)
|
|
16
|
+
)
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def offering_available(offering, readiness:)
|
|
20
|
+
registry_event_class.available(
|
|
21
|
+
offering,
|
|
22
|
+
runtime: runtime_metadata,
|
|
23
|
+
health: offering_health(readiness),
|
|
24
|
+
metadata: offering_metadata
|
|
25
|
+
)
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
private
|
|
29
|
+
|
|
30
|
+
def provider_offering(readiness)
|
|
31
|
+
{
|
|
32
|
+
provider_family: :bedrock,
|
|
33
|
+
provider_instance: provider_instance,
|
|
34
|
+
transport: :aws_sdk,
|
|
35
|
+
model: 'provider-readiness',
|
|
36
|
+
usage_type: :inference,
|
|
37
|
+
capabilities: [],
|
|
38
|
+
health: readiness_health(readiness),
|
|
39
|
+
metadata: { lex: :llm_bedrock, provider_readiness: true }
|
|
40
|
+
}
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def readiness_health(readiness)
|
|
44
|
+
health = {
|
|
45
|
+
ready: readiness[:ready] == true,
|
|
46
|
+
status: readiness[:ready] ? :available : :unavailable,
|
|
47
|
+
checked: readiness[:checked] != false
|
|
48
|
+
}
|
|
49
|
+
add_readiness_error(health, readiness)
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def add_readiness_error(health, source)
|
|
53
|
+
error_class = source[:error] || source['error']
|
|
54
|
+
error_message = source[:message] || source['message']
|
|
55
|
+
health[:error_class] = error_class if error_class
|
|
56
|
+
health[:error] = error_message if error_message
|
|
57
|
+
health
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def offering_health(readiness)
|
|
61
|
+
ready = readiness.fetch(:ready, true) == true
|
|
62
|
+
{ ready:, status: ready ? :available : :degraded, checked: readiness[:checked] != false }
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def readiness_metadata(readiness)
|
|
66
|
+
{
|
|
67
|
+
extension: :lex_llm_bedrock,
|
|
68
|
+
provider: :bedrock,
|
|
69
|
+
configured: readiness[:configured] == true,
|
|
70
|
+
live: readiness[:live] == true
|
|
71
|
+
}
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def offering_metadata
|
|
75
|
+
{ extension: :lex_llm_bedrock, provider: :bedrock }
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def runtime_metadata
|
|
79
|
+
{ node: provider_instance }
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
def provider_instance
|
|
83
|
+
:bedrock
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
def registry_event_class
|
|
87
|
+
::Legion::Extensions::Llm::Routing::RegistryEvent
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
end
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Legion
|
|
4
|
+
module Extensions
|
|
5
|
+
module Llm
|
|
6
|
+
module Bedrock
|
|
7
|
+
# Best-effort publisher for Bedrock provider availability events.
|
|
8
|
+
class RegistryPublisher
|
|
9
|
+
APP_ID = 'lex-llm-bedrock'
|
|
10
|
+
|
|
11
|
+
def initialize(builder: RegistryEventBuilder.new)
|
|
12
|
+
@builder = builder
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def publish_readiness_async(readiness)
|
|
16
|
+
schedule { publish_event(@builder.readiness(readiness)) }
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def publish_offerings_async(offerings, readiness:)
|
|
20
|
+
schedule do
|
|
21
|
+
Array(offerings).each do |offering|
|
|
22
|
+
publish_event(@builder.offering_available(offering, readiness:))
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
private
|
|
28
|
+
|
|
29
|
+
def schedule(&)
|
|
30
|
+
return false unless publishing_available?
|
|
31
|
+
|
|
32
|
+
Thread.new do
|
|
33
|
+
Thread.current.abort_on_exception = false
|
|
34
|
+
yield
|
|
35
|
+
rescue StandardError => e
|
|
36
|
+
log_publish_failure(e, level: :debug)
|
|
37
|
+
end
|
|
38
|
+
rescue StandardError => e
|
|
39
|
+
log_publish_failure(e, level: :debug)
|
|
40
|
+
false
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def publish_event(event)
|
|
44
|
+
return false unless publishing_available?
|
|
45
|
+
|
|
46
|
+
message_class.new(event:, app_id: APP_ID).publish(spool: false)
|
|
47
|
+
rescue StandardError => e
|
|
48
|
+
log_publish_failure(e)
|
|
49
|
+
false
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def publishing_available?
|
|
53
|
+
return false unless registry_event_available?
|
|
54
|
+
return false unless transport_message_available?
|
|
55
|
+
return true unless defined?(::Legion::Transport::Connection)
|
|
56
|
+
return true unless ::Legion::Transport::Connection.respond_to?(:session_open?)
|
|
57
|
+
|
|
58
|
+
::Legion::Transport::Connection.session_open?
|
|
59
|
+
rescue StandardError
|
|
60
|
+
false
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def registry_event_available?
|
|
64
|
+
defined?(::Legion::Extensions::Llm::Routing::RegistryEvent)
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def transport_message_available?
|
|
68
|
+
return true if message_class_defined?
|
|
69
|
+
return false unless defined?(::Legion::Transport::Message) && defined?(::Legion::Transport::Exchange)
|
|
70
|
+
|
|
71
|
+
require 'legion/extensions/llm/bedrock/transport/messages/registry_event'
|
|
72
|
+
message_class_defined?
|
|
73
|
+
rescue LoadError
|
|
74
|
+
false
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def message_class_defined?
|
|
78
|
+
defined?(::Legion::Extensions::Llm::Bedrock::Transport::Messages::RegistryEvent)
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
def message_class
|
|
82
|
+
::Legion::Extensions::Llm::Bedrock::Transport::Messages::RegistryEvent
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
def log_publish_failure(error, level: :warn)
|
|
86
|
+
message = "[lex-llm-bedrock] llm.registry publish failed: #{error.class}: #{error.message}"
|
|
87
|
+
logger = ::Legion::Extensions::Llm.logger if defined?(::Legion::Extensions::Llm)
|
|
88
|
+
if logger.respond_to?(level)
|
|
89
|
+
logger.public_send(level, message)
|
|
90
|
+
elsif logger.respond_to?(:debug)
|
|
91
|
+
logger.debug(message)
|
|
92
|
+
end
|
|
93
|
+
rescue StandardError
|
|
94
|
+
nil
|
|
95
|
+
end
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
end
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Legion
|
|
4
|
+
module Extensions
|
|
5
|
+
module Llm
|
|
6
|
+
module Bedrock
|
|
7
|
+
module Transport
|
|
8
|
+
module Exchanges
|
|
9
|
+
# Topic exchange for Bedrock provider availability events.
|
|
10
|
+
class LlmRegistry < ::Legion::Transport::Exchange
|
|
11
|
+
def exchange_name
|
|
12
|
+
'llm.registry'
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def default_type
|
|
16
|
+
'topic'
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'legion/extensions/llm/bedrock/transport/exchanges/llm_registry'
|
|
4
|
+
|
|
5
|
+
module Legion
|
|
6
|
+
module Extensions
|
|
7
|
+
module Llm
|
|
8
|
+
module Bedrock
|
|
9
|
+
module Transport
|
|
10
|
+
module Messages
|
|
11
|
+
# Publishes lex-llm RegistryEvent envelopes to the llm.registry exchange.
|
|
12
|
+
class RegistryEvent < ::Legion::Transport::Message
|
|
13
|
+
def initialize(event:, **options)
|
|
14
|
+
super(**event.to_h.merge(options))
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def exchange
|
|
18
|
+
Transport::Exchanges::LlmRegistry
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def routing_key
|
|
22
|
+
@options[:routing_key] || "llm.registry.#{@options.fetch(:event_type)}"
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def type
|
|
26
|
+
'llm.registry.event'
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def app_id
|
|
30
|
+
@options[:app_id] || RegistryPublisher::APP_ID
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def persistent # rubocop:disable Naming/PredicateMethod
|
|
34
|
+
false
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
require 'legion/extensions/llm'
|
|
4
4
|
require 'legion/extensions/llm/bedrock/provider'
|
|
5
|
+
require 'legion/extensions/llm/bedrock/registry_event_builder'
|
|
6
|
+
require 'legion/extensions/llm/bedrock/registry_publisher'
|
|
5
7
|
require 'legion/extensions/llm/bedrock/version'
|
|
6
8
|
|
|
7
9
|
module Legion
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: lex-llm-bedrock
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.1.
|
|
4
|
+
version: 0.1.2
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- LegionIO
|
|
@@ -85,14 +85,14 @@ dependencies:
|
|
|
85
85
|
requirements:
|
|
86
86
|
- - ">="
|
|
87
87
|
- !ruby/object:Gem::Version
|
|
88
|
-
version: 0.1.
|
|
88
|
+
version: 0.1.5
|
|
89
89
|
type: :runtime
|
|
90
90
|
prerelease: false
|
|
91
91
|
version_requirements: !ruby/object:Gem::Requirement
|
|
92
92
|
requirements:
|
|
93
93
|
- - ">="
|
|
94
94
|
- !ruby/object:Gem::Version
|
|
95
|
-
version: 0.1.
|
|
95
|
+
version: 0.1.5
|
|
96
96
|
description: Amazon Bedrock provider integration for the LegionIO LLM routing framework.
|
|
97
97
|
email:
|
|
98
98
|
- matthewdiverson@gmail.com
|
|
@@ -112,6 +112,10 @@ files:
|
|
|
112
112
|
- lex-llm-bedrock.gemspec
|
|
113
113
|
- lib/legion/extensions/llm/bedrock.rb
|
|
114
114
|
- lib/legion/extensions/llm/bedrock/provider.rb
|
|
115
|
+
- lib/legion/extensions/llm/bedrock/registry_event_builder.rb
|
|
116
|
+
- lib/legion/extensions/llm/bedrock/registry_publisher.rb
|
|
117
|
+
- lib/legion/extensions/llm/bedrock/transport/exchanges/llm_registry.rb
|
|
118
|
+
- lib/legion/extensions/llm/bedrock/transport/messages/registry_event.rb
|
|
115
119
|
- lib/legion/extensions/llm/bedrock/version.rb
|
|
116
120
|
homepage: https://github.com/LegionIO/lex-llm-bedrock
|
|
117
121
|
licenses:
|