lex-llm-mlx 0.1.6 → 0.1.7

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: 6305c1739c33374352cd5bda241303bd3e4dbfa742a162a7b11276be46eccb97
4
- data.tar.gz: f50421895c2cf1472393b0687aed78e8ae98b27a130fd95a2038060faa588377
3
+ metadata.gz: b4c018fd3b44a629665783ce38fd5c0f5429ab41452b2e8829079a08c2807860
4
+ data.tar.gz: d75bf991619c7d3bf8bc4d7b0aaf77cdb11e6a352595e210ef36f2b6e094cecb
5
5
  SHA512:
6
- metadata.gz: 86b833f891fe19fbb9f8e136a0da466d3a1cd1dc4c6af02eb5cab62fe3fffb2f8684c20c9f6a978859f44f756c4dbbb51004effe42d120d117f02ef13e3545de
7
- data.tar.gz: d3f422a95aac94dcd185c754cd5f1806edd86d77ff73b6a429c838dbd6369f51298a7ff1f38019ccc455509b66a9525a2cb30893cd5f7fad0ff8499f2cfebb77
6
+ metadata.gz: cee424e550ad1ee7cf3a19f791f3bf72434b170efbb50e3e952d5eb502943f442b14ba29344b26575657a390785ad4749ad8d95f7c34454f9d7852160584ff4a
7
+ data.tar.gz: 287b5609ee6788ce4865d1b4f1fb49e344198fe5ca1b828f806742810d82d29e1a18fa28c2404b9a8b0144878ea3d52154fb3e702286f02f2a836239f0d7f316
data/CHANGELOG.md CHANGED
@@ -1,5 +1,13 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.1.7 - 2026-04-30
4
+
5
+ - Add `Legion::Logging::Helper` to `Mlx` module and `RegistryPublisher` for standardized logging.
6
+ - Replace all bare rescue blocks with `handle_exception` calls for full observability.
7
+ - Add info-level action logging for health checks, readiness, model discovery, and registry publishing.
8
+ - Remove custom `log_publish_failure` method in favor of `handle_exception`.
9
+ - Update README to document registry event publishing, transport layer, and architecture.
10
+
3
11
  ## 0.1.6 - 2026-04-28
4
12
 
5
13
  - Publish best-effort `llm.registry` live readiness and discovered-model availability events using `lex-llm` registry envelopes when transport is already available.
data/README.md CHANGED
@@ -12,7 +12,21 @@ Load it with `require 'legion/extensions/llm/mlx'`.
12
12
  - OpenAI-compatible chat, streaming, model listing, and embeddings endpoint wrappers.
13
13
  - Heuristic chat, embedding, and vision capability mapping for discovered local models.
14
14
  - Local-first defaults for MLX servers running on MacBook, Mac Studio, or local Apple Silicon hosts.
15
- - Shared Legion settings, JSON, and logging dependencies.
15
+ - Best-effort `llm.registry` event publishing for readiness and model availability when transport is available.
16
+ - Shared Legion settings, JSON, and logging dependencies with full `Legion::Logging::Helper` integration.
17
+
18
+ ## Architecture
19
+
20
+ ```
21
+ Legion::Extensions::Llm::Mlx
22
+ Mlx (module) # Extension namespace, provider registration, default settings
23
+ Provider # MLX provider — health, readiness, model listing, OpenAI-compatible adapter
24
+ RegistryPublisher # Async publisher for llm.registry readiness/model availability events
25
+ RegistryEventBuilder # Builds sanitized lex-llm registry envelopes for MLX provider state
26
+ Transport::
27
+ Messages::RegistryEvent # AMQP message for llm.registry exchange
28
+ Exchanges::LlmRegistry # Topic exchange definition for llm.registry
29
+ ```
16
30
 
17
31
  ## Default Settings
18
32
 
@@ -41,3 +55,30 @@ end
41
55
  - `health_url`: `/health`
42
56
 
43
57
  The provider uses the shared `Legion::Extensions::Llm::Provider::OpenAICompatible` adapter so Legion routing can treat MLX, vLLM, OpenAI, and other compatible servers consistently while preserving provider-specific settings and health behavior.
58
+
59
+ ## Registry Event Publishing
60
+
61
+ When `Legion::Transport` and `lex-llm` routing are available, the provider publishes best-effort events to the `llm.registry` topic exchange:
62
+
63
+ - **Readiness events** — published asynchronously when `readiness(live: true)` is called.
64
+ - **Model availability events** — published asynchronously after `list_models` discovers models.
65
+
66
+ Publishing is fire-and-forget in background threads; failures never block the provider.
67
+
68
+ ## Dependencies
69
+
70
+ | Gem | Required | Purpose |
71
+ |-----|----------|---------|
72
+ | `legion-json` (>= 1.2.1) | Yes | JSON serialization |
73
+ | `legion-logging` (>= 1.3.2) | Yes | Structured logging via Helper |
74
+ | `legion-settings` (>= 1.3.14) | Yes | Configuration |
75
+ | `lex-llm` (>= 0.1.5) | Yes | Shared provider base, routing, fleet |
76
+
77
+ ## Development
78
+
79
+ ```bash
80
+ bundle install
81
+ bundle exec rspec # 0 failures
82
+ bundle exec rubocop -A # auto-fix
83
+ bundle exec rubocop # lint check
84
+ ```
@@ -62,17 +62,21 @@ module Legion
62
62
  def health_url = '/health'
63
63
 
64
64
  def health
65
+ log.info("Checking MLX health at #{api_base}#{health_url}")
65
66
  connection.get(health_url).body
66
67
  end
67
68
 
68
69
  def readiness(live: false)
70
+ log.info("Checking MLX readiness (live=#{live})")
69
71
  super.tap do |metadata|
70
72
  self.class.registry_publisher.publish_readiness_async(metadata) if live
71
73
  end
72
74
  end
73
75
 
74
76
  def list_models
77
+ log.info('Listing available MLX models')
75
78
  super.tap do |models|
79
+ log.info("Discovered #{Array(models).size} MLX models")
76
80
  self.class.registry_publisher.publish_models_async(models, readiness: readiness(live: false))
77
81
  end
78
82
  end
@@ -6,6 +6,8 @@ module Legion
6
6
  module Mlx
7
7
  # Best-effort publisher for MLX provider availability events.
8
8
  class RegistryPublisher
9
+ include Legion::Logging::Helper if defined?(Legion::Logging::Helper)
10
+
9
11
  APP_ID = 'lex-llm-mlx'
10
12
 
11
13
  def initialize(builder: RegistryEventBuilder.new)
@@ -13,10 +15,12 @@ module Legion
13
15
  end
14
16
 
15
17
  def publish_readiness_async(readiness)
18
+ log.info('Publishing MLX readiness event asynchronously')
16
19
  schedule { publish_event(@builder.readiness(readiness)) }
17
20
  end
18
21
 
19
22
  def publish_models_async(models, readiness:)
23
+ log.info("Publishing #{Array(models).size} MLX model availability events asynchronously")
20
24
  schedule do
21
25
  Array(models).each do |model|
22
26
  publish_event(@builder.model_available(model, readiness:))
@@ -33,19 +37,20 @@ module Legion
33
37
  Thread.current.abort_on_exception = false
34
38
  yield
35
39
  rescue StandardError => e
36
- log_publish_failure(e, level: :debug)
40
+ handle_exception(e, level: :debug, handled: true, operation: 'mlx.registry_publisher.schedule_thread')
37
41
  end
38
42
  rescue StandardError => e
39
- log_publish_failure(e, level: :debug)
43
+ handle_exception(e, level: :debug, handled: true, operation: 'mlx.registry_publisher.schedule')
40
44
  false
41
45
  end
42
46
 
43
47
  def publish_event(event)
44
48
  return false unless publishing_available?
45
49
 
50
+ log.info("Publishing MLX registry event: #{event.class}")
46
51
  message_class.new(event:, app_id: APP_ID).publish(spool: false)
47
52
  rescue StandardError => e
48
- log_publish_failure(e)
53
+ handle_exception(e, level: :warn, handled: true, operation: 'mlx.registry_publisher.publish_event')
49
54
  false
50
55
  end
51
56
 
@@ -56,7 +61,9 @@ module Legion
56
61
  return true unless ::Legion::Transport::Connection.respond_to?(:session_open?)
57
62
 
58
63
  ::Legion::Transport::Connection.session_open?
59
- rescue StandardError
64
+ rescue StandardError => e
65
+ handle_exception(e, level: :debug, handled: true,
66
+ operation: 'mlx.registry_publisher.publishing_available?')
60
67
  false
61
68
  end
62
69
 
@@ -70,7 +77,9 @@ module Legion
70
77
 
71
78
  require 'legion/extensions/llm/mlx/transport/messages/registry_event'
72
79
  message_class_defined?
73
- rescue LoadError
80
+ rescue LoadError => e
81
+ handle_exception(e, level: :debug, handled: true,
82
+ operation: 'mlx.registry_publisher.transport_message_available?')
74
83
  false
75
84
  end
76
85
 
@@ -81,18 +90,6 @@ module Legion
81
90
  def message_class
82
91
  ::Legion::Extensions::Llm::Mlx::Transport::Messages::RegistryEvent
83
92
  end
84
-
85
- def log_publish_failure(error, level: :warn)
86
- message = "[lex-llm-mlx] 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
93
  end
97
94
  end
98
95
  end
@@ -4,7 +4,7 @@ module Legion
4
4
  module Extensions
5
5
  module Llm
6
6
  module Mlx
7
- VERSION = '0.1.6'
7
+ VERSION = '0.1.7'
8
8
  end
9
9
  end
10
10
  end
@@ -11,6 +11,7 @@ module Legion
11
11
  module Llm
12
12
  # Mlx provider extension namespace.
13
13
  module Mlx
14
+ extend Legion::Logging::Helper if defined?(Legion::Logging::Helper)
14
15
  extend ::Legion::Extensions::Core if ::Legion::Extensions.const_defined?(:Core, false)
15
16
 
16
17
  PROVIDER_FAMILY = :mlx
@@ -38,3 +39,6 @@ end
38
39
 
39
40
  Legion::Extensions::Llm::Provider.register(Legion::Extensions::Llm::Mlx::PROVIDER_FAMILY,
40
41
  Legion::Extensions::Llm::Mlx::Provider)
42
+ if Legion::Extensions::Llm::Mlx.respond_to?(:log)
43
+ Legion::Extensions::Llm::Mlx.log.info('Registered MLX provider as :mlx')
44
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: lex-llm-mlx
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.6
4
+ version: 0.1.7
5
5
  platform: ruby
6
6
  authors:
7
7
  - LegionIO