lex-llm-bedrock 0.1.5 → 0.2.0

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: 61bd89194ee181746dc54c6b898bf31b4b8d599a01121bcec9a0dbd8b80d3b5c
4
- data.tar.gz: 97ab9f39bec79114152b42d8fdf8f996a50b4b1ac94dcb1a230049ccd8d08398
3
+ metadata.gz: eafb04fa29d1bf032323c4040c7cdbe0ea2d3cf1c72328864ec54b5e2f7ce117
4
+ data.tar.gz: 6da27c531876ff32af29b783548b86bed7a4146f45f0b94da679320dd594310b
5
5
  SHA512:
6
- metadata.gz: 441194151664025152b62567db2f84d9b406779502f560c9f8b0a41c891ec8f487624a8fd5bf3d6a7c86172b15a5f218bfa38c9f847d7a7bdec5db49e678ccca
7
- data.tar.gz: 7676dff0e80cc6a3a0589a01acc723b7920c3d59193936c2f5a8bc89444957f1f43e9cf8b003ab19badd21720a74a26d8b3046d7e673c1333a1fca458b12af43
6
+ metadata.gz: 7b7a1bc938f269380f0310cfd0e4a2f3561e986ed09db904dbe6a31663451658bac03e56b54c57f3c32efd85c7d83eb64e8d50fdbeac20efe2314f6a9e5d0a38
7
+ data.tar.gz: db293ebc885b48aa2902ecccfd5cf8e47bf58fd775ec211d31cb9a491dcecb60c5146989175affd2e1c59bd3f2429492eea94f36d202f41955708d72a3ec5780
data/CHANGELOG.md CHANGED
@@ -1,5 +1,16 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.2.0 - 2026-04-30
4
+
5
+ - Adopt lex-llm 0.1.9 base contract: flat `default_settings`, base `RegistryPublisher`, base `RegistryEventBuilder`.
6
+ - Replace `provider_settings` call with flat default_settings hash (default_model, region, credentials, whitelist/blacklist, TLS, instances).
7
+ - Remove `Provider.register` call; register configuration options directly via `Configuration.register_provider_options`.
8
+ - Delete local `RegistryPublisher`, `RegistryEventBuilder`, and `transport/` directory; use parameterized base classes from lex-llm.
9
+ - Move `registry_publisher` from `Provider` class method to `Bedrock` module method using `Legion::Extensions::Llm::RegistryPublisher.new(provider_family: :bedrock)`.
10
+ - Rewrite `list_models` to return `Model::Info` with `capabilities`, `modalities_input`, and `modalities_output` derived from Bedrock `inputModalities`/`outputModalities`.
11
+ - Publish discovered models via `publish_models_async` (base contract) instead of `publish_offerings_async`.
12
+ - Bump gemspec dependency to `lex-llm >= 0.1.9`.
13
+
3
14
  ## 0.1.5 - 2026-04-30
4
15
 
5
16
  - Audit logging, rescue blocks, and README for full observability.
@@ -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.5'
31
+ spec.add_dependency 'lex-llm', '>= 0.2.0'
32
32
  end
@@ -27,8 +27,6 @@ module Legion
27
27
  ALIASES = STATIC_MODELS.to_h { |entry| [entry.fetch(:alias), entry.fetch(:model)] }.freeze
28
28
 
29
29
  class << self
30
- attr_writer :registry_publisher
31
-
32
30
  def slug = 'bedrock'
33
31
 
34
32
  def configuration_options
@@ -47,7 +45,7 @@ module Legion
47
45
  def capabilities = Capabilities
48
46
 
49
47
  def registry_publisher
50
- @registry_publisher ||= RegistryPublisher.new
48
+ Bedrock.registry_publisher
51
49
  end
52
50
 
53
51
  def resolve_model_id(model_id, config: nil) # rubocop:disable Lint/UnusedMethodArgument
@@ -96,7 +94,6 @@ module Legion
96
94
  response = bedrock_client.list_foundation_models(**filters)
97
95
  Array(value(response, :model_summaries)).map { |summary| offering_from_summary(summary) }.tap do |offerings|
98
96
  log.info { "bedrock.provider.discover_offerings: found #{offerings.size} models" }
99
- self.class.registry_publisher.publish_offerings_async(offerings, readiness: readiness(live: false))
100
97
  end
101
98
  end
102
99
 
@@ -145,16 +142,11 @@ module Legion
145
142
 
146
143
  def list_models
147
144
  log.info { 'bedrock.provider.list_models: fetching live model list' }
148
- discover_offerings(live: true).map do |offering|
149
- Legion::Extensions::Llm::Model::Info.new(
150
- id: offering.model,
151
- name: offering.metadata[:alias] || offering.model,
152
- provider: :bedrock,
153
- family: offering.metadata[:model_family],
154
- capabilities: offering.capabilities.map(&:to_s),
155
- metadata: offering.to_h
156
- )
157
- end
145
+ response = bedrock_client.list_foundation_models
146
+ models = Array(value(response, :model_summaries)).filter_map { |summary| model_info_from_summary(summary) }
147
+ log.info { "bedrock.provider.list_models: found #{models.size} models" }
148
+ self.class.registry_publisher.publish_models_async(models, readiness: readiness(live: false))
149
+ models
158
150
  end
159
151
 
160
152
  def chat(messages, model:, temperature: nil, max_tokens: nil, tools: {}, tool_prefs: nil, params: {})
@@ -244,6 +236,23 @@ module Legion
244
236
  )
245
237
  end
246
238
 
239
+ def model_info_from_summary(summary)
240
+ model = value(summary, :model_id)
241
+ input_mods = Array(value(summary, :input_modalities)).map { |m| m.to_s.downcase }
242
+ output_mods = Array(value(summary, :output_modalities)).map { |m| m.to_s.downcase }
243
+
244
+ Legion::Extensions::Llm::Model::Info.new(
245
+ id: model,
246
+ name: alias_for(model) || model,
247
+ provider: :bedrock,
248
+ family: (normalize_provider(value(summary, :provider_name)) || model_family_for(model)).to_s,
249
+ capabilities: capabilities_from_modalities(input_mods, output_mods, summary),
250
+ modalities_input: input_mods,
251
+ modalities_output: output_mods,
252
+ metadata: normalize_response(summary)
253
+ )
254
+ end
255
+
247
256
  def build_offering(model:, model_family:, usage_type:, instance_id: :default, alias_name: nil,
248
257
  capabilities: nil, metadata: {})
249
258
  Legion::Extensions::Llm::Routing::ModelOffering.new(
@@ -480,6 +489,18 @@ module Legion
480
489
  capabilities
481
490
  end
482
491
 
492
+ def capabilities_from_modalities(input_mods, output_mods, summary)
493
+ caps = []
494
+ caps << :embedding if output_mods.include?('embedding')
495
+ unless caps.include?(:embedding)
496
+ caps << :completion
497
+ caps << :streaming if value(summary, :response_streaming_supported)
498
+ end
499
+ caps << :vision if input_mods.include?('image')
500
+ caps << :tools if caps.include?(:completion)
501
+ caps
502
+ end
503
+
483
504
  def model_family_for(model)
484
505
  normalize_provider(model.to_s.split('.').first)
485
506
  end
@@ -4,7 +4,7 @@ module Legion
4
4
  module Extensions
5
5
  module Llm
6
6
  module Bedrock
7
- VERSION = '0.1.5'
7
+ VERSION = '0.2.0'
8
8
  end
9
9
  end
10
10
  end
@@ -2,8 +2,6 @@
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'
7
5
  require 'legion/extensions/llm/bedrock/version'
8
6
 
9
7
  module Legion
@@ -16,34 +14,34 @@ module Legion
16
14
  PROVIDER_FAMILY = :bedrock
17
15
 
18
16
  def self.default_settings
19
- ::Legion::Extensions::Llm.provider_settings(
20
- family: PROVIDER_FAMILY,
21
- discovery: { enabled: false, live: false, regions: %w[us-east-1 us-west-2] },
22
- instance: {
23
- endpoint: 'https://bedrock-runtime.us-east-1.amazonaws.com',
24
- region: 'us-east-1',
25
- tier: :frontier,
26
- transport: :aws_sdk,
27
- credentials: {
28
- provider: 'aws-sdk-default-chain',
29
- access_key_id: 'env://AWS_ACCESS_KEY_ID',
30
- secret_access_key: 'env://AWS_SECRET_ACCESS_KEY',
31
- session_token: 'env://AWS_SESSION_TOKEN',
32
- profile: 'env://AWS_PROFILE'
33
- },
34
- usage: { inference: true, embedding: true, token_counting: true },
35
- limits: { concurrency: 4 }
36
- }
37
- )
17
+ {
18
+ enabled: false,
19
+ default_model: 'us.anthropic.claude-sonnet-4-6',
20
+ region: 'us-east-2',
21
+ bearer_token: nil,
22
+ api_key: nil,
23
+ secret_key: nil,
24
+ session_token: nil,
25
+ model_whitelist: [],
26
+ model_blacklist: [],
27
+ model_cache_ttl: 3600,
28
+ tls: { enabled: false, verify: :peer },
29
+ instances: {}
30
+ }
38
31
  end
39
32
 
40
33
  def self.provider_class
41
34
  Provider
42
35
  end
36
+
37
+ def self.registry_publisher
38
+ @registry_publisher ||= Legion::Extensions::Llm::RegistryPublisher.new(provider_family: PROVIDER_FAMILY)
39
+ end
43
40
  end
44
41
  end
45
42
  end
46
43
  end
47
44
 
48
- Legion::Extensions::Llm::Provider.register(Legion::Extensions::Llm::Bedrock::PROVIDER_FAMILY,
49
- Legion::Extensions::Llm::Bedrock::Provider)
45
+ Legion::Extensions::Llm::Configuration.register_provider_options(
46
+ Legion::Extensions::Llm::Bedrock::Provider.configuration_options
47
+ )
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.5
4
+ version: 0.2.0
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.5
88
+ version: 0.2.0
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.5
95
+ version: 0.2.0
96
96
  description: Amazon Bedrock provider integration for the LegionIO LLM routing framework.
97
97
  email:
98
98
  - matthewdiverson@gmail.com
@@ -112,10 +112,6 @@ 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
119
115
  - lib/legion/extensions/llm/bedrock/version.rb
120
116
  homepage: https://github.com/LegionIO/lex-llm-bedrock
121
117
  licenses:
@@ -1,95 +0,0 @@
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
- include Legion::Logging::Helper
10
-
11
- def readiness(readiness)
12
- registry_event_class.public_send(
13
- readiness[:ready] ? :available : :unavailable,
14
- provider_offering(readiness),
15
- runtime: runtime_metadata,
16
- health: readiness_health(readiness),
17
- metadata: readiness_metadata(readiness)
18
- )
19
- end
20
-
21
- def offering_available(offering, readiness:)
22
- registry_event_class.available(
23
- offering,
24
- runtime: runtime_metadata,
25
- health: offering_health(readiness),
26
- metadata: offering_metadata
27
- )
28
- end
29
-
30
- private
31
-
32
- def provider_offering(readiness)
33
- {
34
- provider_family: :bedrock,
35
- provider_instance: provider_instance,
36
- transport: :aws_sdk,
37
- model: 'provider-readiness',
38
- usage_type: :inference,
39
- capabilities: [],
40
- health: readiness_health(readiness),
41
- metadata: { lex: :llm_bedrock, provider_readiness: true }
42
- }
43
- end
44
-
45
- def readiness_health(readiness)
46
- health = {
47
- ready: readiness[:ready] == true,
48
- status: readiness[:ready] ? :available : :unavailable,
49
- checked: readiness[:checked] != false
50
- }
51
- add_readiness_error(health, readiness)
52
- end
53
-
54
- def add_readiness_error(health, source)
55
- error_class = source[:error] || source['error']
56
- error_message = source[:message] || source['message']
57
- health[:error_class] = error_class if error_class
58
- health[:error] = error_message if error_message
59
- health
60
- end
61
-
62
- def offering_health(readiness)
63
- ready = readiness.fetch(:ready, true) == true
64
- { ready:, status: ready ? :available : :degraded, checked: readiness[:checked] != false }
65
- end
66
-
67
- def readiness_metadata(readiness)
68
- {
69
- extension: :lex_llm_bedrock,
70
- provider: :bedrock,
71
- configured: readiness[:configured] == true,
72
- live: readiness[:live] == true
73
- }
74
- end
75
-
76
- def offering_metadata
77
- { extension: :lex_llm_bedrock, provider: :bedrock }
78
- end
79
-
80
- def runtime_metadata
81
- { node: provider_instance }
82
- end
83
-
84
- def provider_instance
85
- :bedrock
86
- end
87
-
88
- def registry_event_class
89
- ::Legion::Extensions::Llm::Routing::RegistryEvent
90
- end
91
- end
92
- end
93
- end
94
- end
95
- end
@@ -1,98 +0,0 @@
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
- include Legion::Logging::Helper
10
-
11
- APP_ID = 'lex-llm-bedrock'
12
-
13
- def initialize(builder: RegistryEventBuilder.new)
14
- @builder = builder
15
- end
16
-
17
- def publish_readiness_async(readiness)
18
- log.debug { 'bedrock.registry_publisher.publish_readiness_async: scheduling readiness event' }
19
- schedule { publish_event(@builder.readiness(readiness)) }
20
- end
21
-
22
- def publish_offerings_async(offerings, readiness:)
23
- log.debug do
24
- "bedrock.registry_publisher.publish_offerings_async: scheduling #{Array(offerings).size} offerings"
25
- end
26
- schedule do
27
- Array(offerings).each do |offering|
28
- publish_event(@builder.offering_available(offering, readiness:))
29
- end
30
- end
31
- end
32
-
33
- private
34
-
35
- def schedule(&)
36
- return false unless publishing_available?
37
-
38
- Thread.new do
39
- Thread.current.abort_on_exception = false
40
- yield
41
- rescue StandardError => e
42
- handle_exception(e, level: :debug, handled: true, operation: 'bedrock.registry_publisher.schedule')
43
- end
44
- rescue StandardError => e
45
- handle_exception(e, level: :debug, handled: true, operation: 'bedrock.registry_publisher.schedule')
46
- false
47
- end
48
-
49
- def publish_event(event)
50
- return false unless publishing_available?
51
-
52
- message_class.new(event:, app_id: APP_ID).publish(spool: false)
53
- rescue StandardError => e
54
- handle_exception(e, level: :warn, handled: true, operation: 'bedrock.registry_publisher.publish_event')
55
- false
56
- end
57
-
58
- def publishing_available?
59
- return false unless registry_event_available?
60
- return false unless transport_message_available?
61
- return true unless defined?(::Legion::Transport::Connection)
62
- return true unless ::Legion::Transport::Connection.respond_to?(:session_open?)
63
-
64
- ::Legion::Transport::Connection.session_open?
65
- rescue StandardError => e
66
- handle_exception(e, level: :debug, handled: true,
67
- operation: 'bedrock.registry_publisher.publishing_available?')
68
- false
69
- end
70
-
71
- def registry_event_available?
72
- defined?(::Legion::Extensions::Llm::Routing::RegistryEvent)
73
- end
74
-
75
- def transport_message_available?
76
- return true if message_class_defined?
77
- return false unless defined?(::Legion::Transport::Message) && defined?(::Legion::Transport::Exchange)
78
-
79
- require 'legion/extensions/llm/bedrock/transport/messages/registry_event'
80
- message_class_defined?
81
- rescue LoadError => e
82
- handle_exception(e, level: :debug, handled: true,
83
- operation: 'bedrock.registry_publisher.transport_message_available?')
84
- false
85
- end
86
-
87
- def message_class_defined?
88
- defined?(::Legion::Extensions::Llm::Bedrock::Transport::Messages::RegistryEvent)
89
- end
90
-
91
- def message_class
92
- ::Legion::Extensions::Llm::Bedrock::Transport::Messages::RegistryEvent
93
- end
94
- end
95
- end
96
- end
97
- end
98
- end
@@ -1,24 +0,0 @@
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
@@ -1,42 +0,0 @@
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