lex-llm-gemini 0.1.7 → 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: 3b4d2bbf521fe7cd5757553aff5a6d61c1a9e9ffbe18c683058710ab19a8a6ff
4
- data.tar.gz: 98d0db7b428b68d0543682c43a27d77fde00aee8bb02377195c37224e9429fef
3
+ metadata.gz: '0788daea481b47eead29eb391fa566a2f02540f1f0f5b4c8aca382b457de8c33'
4
+ data.tar.gz: 356fd313c188e9d585ca9d7a3f9f7fd8b1ab9d687edba232266ea168c306135f
5
5
  SHA512:
6
- metadata.gz: c40e3408f31507e4de8622e65676a2eb67849a05964dee02585545647563a4655fe808a3673782b1819bc7828a1f9fd3af900aa57ce09f6119ba28caefe01813
7
- data.tar.gz: bacceead0f9edceed7da8efb605fe516f0ea7110c57f47cf8b16bad77805e74d8a1a99d37ffec056fa4affdd2c4e6a30f45c7a5812c03221182038373a45c784
6
+ metadata.gz: '09edc833e89707be34a90292622615b2fcd391d19cee2baa73d29ed7a6f12b1d520cee837684f9db28349488e7d54f7ff312414b6e3ede280627da4d821d456e'
7
+ data.tar.gz: 634a5703a52c3d0554a47141265430ea1dbe10b43dfef892923ea4b0b4e7a278a914a76a9c1c109196ea27f09d9c5fb2dabdade8b302aff888185f9731a236b4
data/.rubocop.yml CHANGED
@@ -14,5 +14,7 @@ Metrics/BlockLength:
14
14
  - spec/**/*
15
15
  Metrics/MethodLength:
16
16
  Enabled: false
17
+ RSpec/ExampleLength:
18
+ Enabled: false
17
19
  RSpec/MultipleExpectations:
18
20
  Enabled: false
data/CHANGELOG.md CHANGED
@@ -1,5 +1,15 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.2.0 - 2026-04-30
4
+
5
+ - **Breaking**: Adopt the base contract from lex-llm 0.1.9.
6
+ - Replace `default_settings` with a flat settings hash (enabled, default_model, api_key, whitelist/blacklist, tls, instances).
7
+ - Remove local `RegistryPublisher` and `RegistryEventBuilder`; use the parameterized base classes from lex-llm.
8
+ - Remove local `transport/` directory (exchanges and messages); the shared `llm.registry` transport in lex-llm is used instead.
9
+ - Remove the deprecated `Provider.register` call; configuration options are registered directly.
10
+ - Update `parse_list_models_response` to use the new `Model::Info` constructor (context_length, modalities_input/output, metadata for max_output_tokens).
11
+ - Require `lex-llm >= 0.1.9`.
12
+
3
13
  ## 0.1.7 - 2026-04-30
4
14
 
5
15
  - Audit logging, rescue blocks, and README for full observability.
@@ -26,5 +26,5 @@ Gem::Specification.new do |spec|
26
26
  spec.add_dependency 'legion-json', '>= 1.2.1'
27
27
  spec.add_dependency 'legion-logging', '>= 1.3.2'
28
28
  spec.add_dependency 'legion-settings', '>= 1.3.14'
29
- spec.add_dependency 'lex-llm', '>= 0.1.5'
29
+ spec.add_dependency 'lex-llm', '>= 0.2.0'
30
30
  end
@@ -8,7 +8,7 @@ module Legion
8
8
  module Gemini
9
9
  # Gemini provider implementation for the Legion::Extensions::Llm base provider contract.
10
10
  class Provider < Legion::Extensions::Llm::Provider # rubocop:disable Metrics/ClassLength
11
- include Legion::Logging::Helper if defined?(Legion::Logging::Helper)
11
+ include Legion::Logging::Helper
12
12
 
13
13
  class << self
14
14
  attr_writer :registry_publisher
@@ -19,7 +19,7 @@ module Legion
19
19
  def capabilities = Capabilities
20
20
 
21
21
  def registry_publisher
22
- @registry_publisher ||= RegistryPublisher.new
22
+ @registry_publisher ||= Legion::Extensions::Llm::RegistryPublisher.new(provider_family: :gemini)
23
23
  end
24
24
  end
25
25
 
@@ -283,16 +283,18 @@ module Legion
283
283
  Array(response.body['models']).map do |model_data|
284
284
  model_id = model_data.fetch('name').delete_prefix('models/')
285
285
  methods = Array(model_data['supportedGenerationMethods'])
286
+ input_mods, output_mods = modalities_for(methods)
286
287
 
287
288
  Legion::Extensions::Llm::Model::Info.new(
288
289
  id: model_id,
289
290
  name: model_data['displayName'] || model_id,
290
291
  provider: provider,
291
- context_window: model_data['inputTokenLimit'],
292
- max_output_tokens: model_data['outputTokenLimit'],
292
+ context_length: model_data['inputTokenLimit'],
293
293
  capabilities: capabilities.critical_capabilities_for(model_data),
294
- modalities: modalities_for(methods),
294
+ modalities_input: input_mods,
295
+ modalities_output: output_mods,
295
296
  metadata: {
297
+ max_output_tokens: model_data['outputTokenLimit'],
296
298
  version: model_data['version'],
297
299
  description: model_data['description'],
298
300
  supported_generation_methods: methods
@@ -302,9 +304,9 @@ module Legion
302
304
  end
303
305
 
304
306
  def modalities_for(methods)
305
- return { input: %w[text], output: %w[embeddings] } if methods.include?('embedContent')
307
+ return [%w[text], %w[embeddings]] if methods.include?('embedContent')
306
308
 
307
- { input: %w[text image audio video], output: %w[text] }
309
+ [%w[text image audio video], %w[text]]
308
310
  end
309
311
 
310
312
  def render_embedding_payload(text, model:, dimensions:)
@@ -4,7 +4,7 @@ module Legion
4
4
  module Extensions
5
5
  module Llm
6
6
  module Gemini
7
- VERSION = '0.1.7'
7
+ VERSION = '0.2.0'
8
8
  end
9
9
  end
10
10
  end
@@ -1,42 +1,39 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'legion/extensions/llm'
4
- require 'legion/extensions/llm/gemini/registry_event_builder'
5
- require 'legion/extensions/llm/gemini/registry_publisher'
6
4
  require 'legion/extensions/llm/gemini/provider'
7
5
  require 'legion/extensions/llm/gemini/version'
8
6
 
9
7
  module Legion
10
8
  module Extensions
9
+ # LLM provider framework namespace (reopened by provider extensions).
11
10
  module Llm
12
11
  # Gemini provider extension namespace.
13
12
  module Gemini
14
13
  extend ::Legion::Extensions::Core if ::Legion::Extensions.const_defined?(:Core, false)
15
- extend Legion::Logging::Helper if defined?(Legion::Logging::Helper)
14
+ extend Legion::Logging::Helper
16
15
 
17
16
  PROVIDER_FAMILY = :gemini
18
17
 
19
18
  def self.default_settings
20
- ::Legion::Extensions::Llm.provider_settings(
21
- family: PROVIDER_FAMILY,
22
- instance: {
23
- endpoint: 'https://generativelanguage.googleapis.com/v1beta',
24
- tier: :frontier,
25
- transport: :http,
26
- credentials: { api_key: 'env://GEMINI_API_KEY' },
27
- usage: { inference: true, embedding: true },
28
- limits: { concurrency: 4 }
29
- }
30
- )
19
+ {
20
+ enabled: false,
21
+ default_model: 'gemini-2.0-flash',
22
+ api_key: nil,
23
+ model_whitelist: [],
24
+ model_blacklist: [],
25
+ model_cache_ttl: 3600,
26
+ tls: { enabled: false, verify: :peer },
27
+ instances: {}
28
+ }
31
29
  end
32
30
 
33
31
  def self.provider_class
34
32
  Provider
35
33
  end
36
34
  end
35
+
36
+ Configuration.register_provider_options(Gemini::Provider.configuration_options)
37
37
  end
38
38
  end
39
39
  end
40
-
41
- Legion::Extensions::Llm::Provider.register(Legion::Extensions::Llm::Gemini::PROVIDER_FAMILY,
42
- Legion::Extensions::Llm::Gemini::Provider)
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: lex-llm-gemini
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.7
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - LegionIO
@@ -57,14 +57,14 @@ dependencies:
57
57
  requirements:
58
58
  - - ">="
59
59
  - !ruby/object:Gem::Version
60
- version: 0.1.5
60
+ version: 0.2.0
61
61
  type: :runtime
62
62
  prerelease: false
63
63
  version_requirements: !ruby/object:Gem::Requirement
64
64
  requirements:
65
65
  - - ">="
66
66
  - !ruby/object:Gem::Version
67
- version: 0.1.5
67
+ version: 0.2.0
68
68
  description: Gemini provider integration for the LegionIO LLM routing framework.
69
69
  email:
70
70
  - matthewdiverson@gmail.com
@@ -84,10 +84,6 @@ files:
84
84
  - lex-llm-gemini.gemspec
85
85
  - lib/legion/extensions/llm/gemini.rb
86
86
  - lib/legion/extensions/llm/gemini/provider.rb
87
- - lib/legion/extensions/llm/gemini/registry_event_builder.rb
88
- - lib/legion/extensions/llm/gemini/registry_publisher.rb
89
- - lib/legion/extensions/llm/gemini/transport/exchanges/llm_registry.rb
90
- - lib/legion/extensions/llm/gemini/transport/messages/registry_event.rb
91
87
  - lib/legion/extensions/llm/gemini/version.rb
92
88
  homepage: https://github.com/LegionIO/lex-llm-gemini
93
89
  licenses:
@@ -1,75 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Legion
4
- module Extensions
5
- module Llm
6
- module Gemini
7
- # Builds sanitized lex-llm registry envelopes for Gemini provider state.
8
- class RegistryEventBuilder
9
- include Legion::Logging::Helper if defined?(Legion::Logging::Helper)
10
-
11
- def model_available(model, readiness:)
12
- registry_event_class.available(
13
- model_offering(model),
14
- runtime: runtime_metadata,
15
- health: model_health(readiness),
16
- metadata: model_metadata(model)
17
- )
18
- end
19
-
20
- private
21
-
22
- def model_offering(model)
23
- {
24
- provider_family: :gemini,
25
- provider_instance: provider_instance,
26
- transport: :http,
27
- model: model.id,
28
- usage_type: usage_type_for(model),
29
- capabilities: Array(model.capabilities).map(&:to_sym),
30
- limits: model_limits(model),
31
- metadata: { lex: :llm_gemini, model_name: model.name }.compact
32
- }
33
- end
34
-
35
- def model_health(readiness)
36
- ready = readiness.fetch(:ready, true) == true
37
- { ready:, status: ready ? :available : :degraded }
38
- end
39
-
40
- def model_metadata(model)
41
- { extension: :lex_llm_gemini, provider: :gemini, model_type: model.type }
42
- end
43
-
44
- def runtime_metadata
45
- { node: provider_instance }
46
- end
47
-
48
- def model_limits(model)
49
- {
50
- context_window: model.context_window,
51
- max_output_tokens: model.max_output_tokens
52
- }.compact
53
- end
54
-
55
- def usage_type_for(model)
56
- model.type == 'embedding' ? :embedding : :inference
57
- end
58
-
59
- def provider_instance
60
- configured_node = (::Legion::Settings.dig(:node, :canonical_name) if defined?(::Legion::Settings))
61
- value = configured_node.to_s.strip
62
- value.empty? ? :gemini : value.to_sym
63
- rescue StandardError => e
64
- handle_exception(e, level: :debug, handled: true, operation: 'gemini.registry.provider_instance')
65
- :gemini
66
- end
67
-
68
- def registry_event_class
69
- ::Legion::Extensions::Llm::Routing::RegistryEvent
70
- end
71
- end
72
- end
73
- end
74
- end
75
- end
@@ -1,89 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Legion
4
- module Extensions
5
- module Llm
6
- module Gemini
7
- # Best-effort publisher for Gemini provider availability events.
8
- class RegistryPublisher
9
- include Legion::Logging::Helper if defined?(Legion::Logging::Helper)
10
-
11
- APP_ID = 'lex-llm-gemini'
12
-
13
- def initialize(builder: RegistryEventBuilder.new)
14
- @builder = builder
15
- end
16
-
17
- def publish_models_async(models, readiness:)
18
- log.info { "publishing #{Array(models).size} model event(s) to llm.registry" }
19
- schedule do
20
- Array(models).each do |model|
21
- publish_event(@builder.model_available(model, readiness:))
22
- end
23
- end
24
- end
25
-
26
- private
27
-
28
- def schedule(&)
29
- return false unless publishing_available?
30
-
31
- Thread.new do
32
- Thread.current.abort_on_exception = false
33
- yield
34
- rescue StandardError => e
35
- handle_exception(e, level: :debug, handled: true, operation: 'gemini.registry.schedule_thread')
36
- end
37
- rescue StandardError => e
38
- handle_exception(e, level: :debug, handled: true, operation: 'gemini.registry.schedule')
39
- false
40
- end
41
-
42
- def publish_event(event)
43
- return false unless publishing_available?
44
-
45
- message_class.new(event:, app_id: APP_ID).publish(spool: false)
46
- rescue StandardError => e
47
- handle_exception(e, level: :warn, handled: true, operation: 'gemini.registry.publish_event')
48
- false
49
- end
50
-
51
- def publishing_available?
52
- return false unless registry_event_available?
53
- return false unless transport_message_available?
54
- return true unless defined?(::Legion::Transport::Connection)
55
- return true unless ::Legion::Transport::Connection.respond_to?(:session_open?)
56
-
57
- ::Legion::Transport::Connection.session_open?
58
- rescue StandardError => e
59
- handle_exception(e, level: :debug, handled: true, operation: 'gemini.registry.publishing_available?')
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/gemini/transport/messages/registry_event'
72
- message_class_defined?
73
- rescue LoadError => e
74
- handle_exception(e, level: :debug, handled: true, operation: 'gemini.registry.transport_load')
75
- false
76
- end
77
-
78
- def message_class_defined?
79
- defined?(::Legion::Extensions::Llm::Gemini::Transport::Messages::RegistryEvent)
80
- end
81
-
82
- def message_class
83
- ::Legion::Extensions::Llm::Gemini::Transport::Messages::RegistryEvent
84
- end
85
- end
86
- end
87
- end
88
- end
89
- end
@@ -1,24 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Legion
4
- module Extensions
5
- module Llm
6
- module Gemini
7
- module Transport
8
- module Exchanges
9
- # Topic exchange for Gemini 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/gemini/transport/exchanges/llm_registry'
4
-
5
- module Legion
6
- module Extensions
7
- module Llm
8
- module Gemini
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