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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 59c2c3fda768fc58435dbe327fd8314e4b9dbfdbdf978e9220e3ad4999e42bc1
4
- data.tar.gz: 8b448d4dbb18e1c8d2d3dde0c817cc49591142d5bc88c6057cf8f8f28d3cab8d
3
+ metadata.gz: 5ec33f1d698328146833876f1b61387ad6523c88cd10c582c98202bb4f8dc72e
4
+ data.tar.gz: 0a4d8b1318967238535525779f4f37d623ae9c34db3f420a9f38869b4caddcf1
5
5
  SHA512:
6
- metadata.gz: 47d5d1f35bd64d93db2e068b988a4ff9bb3d8622726f23cfe897b282f8cd1c4f454a44b82c170c04831c108226f373869121ac9a61f574bf023a13a8d9c92c8b
7
- data.tar.gz: 2c9679fabbce22abde6a5f7e58da92c34e113afe5b6f166e3956ee6c91034f7178737e95897a93ba348750c85358822b3dc464841dfcbbf37d74ceb66469ef03
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
 
@@ -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.3'
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, endpoints: endpoint_manifest)
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
@@ -4,7 +4,7 @@ module Legion
4
4
  module Extensions
5
5
  module Llm
6
6
  module Bedrock
7
- VERSION = '0.1.0'
7
+ VERSION = '0.1.2'
8
8
  end
9
9
  end
10
10
  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.0
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.3
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.3
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: