lex-llm-ollama 0.2.0 → 0.2.6

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: 599e2c13614a5f4a912562dda8336e43cee73a4934d95a782e6d231374ad322e
4
- data.tar.gz: aab71c8eb82f54d91da01f4a68547cfcdc33ac53cad06c02fad02ef0d901931c
3
+ metadata.gz: b4d5bd8102f3cc484e81ec31067f899306246ee6b333a87528874a6afedaffdc
4
+ data.tar.gz: 7a56c5e3608f88cc40075ae0ba249e05af48d8dc2487ec5ba4b300c054d7d65f
5
5
  SHA512:
6
- metadata.gz: 33e4999dbe5781060c429020fccf0cbb0a090ef0cba142c0a136be53e81587a0f66efd053f3e8daa887134718b6a9429ff2bc8febad1cd0e307faf92c193612d
7
- data.tar.gz: 6a43fb12fa810b332586e0bb92ec1ab600d82b089d2cb14db65b922708e3c590fabaaf724170ba5c04aa9f5367bde7cb05285ff31ef52e4b43875948fa94beda
6
+ metadata.gz: 375772149e7b1641cfea2f3446c08d2d50155f07bb92f3b90e7e7f00fac91541754e9f085531ea20ab7af7c49a6fdbb68145d9e9f5131d236493882e358e0420
7
+ data.tar.gz: f450168705b4b7b0dd340f9cdeed6294dc39bd7053902c23d8f820ea8310f3088206435cecd4bfa208d4f9aeba220127568cf379731f325a9d51042c802850c6
@@ -8,8 +8,20 @@ jobs:
8
8
  ci:
9
9
  uses: LegionIO/.github/.github/workflows/ci.yml@main
10
10
 
11
+ excluded-files:
12
+ uses: LegionIO/.github/.github/workflows/excluded-files.yml@main
13
+
14
+ security:
15
+ uses: LegionIO/.github/.github/workflows/security-scan.yml@main
16
+
17
+ version-changelog:
18
+ uses: LegionIO/.github/.github/workflows/version-changelog.yml@main
19
+
20
+ dependency-review:
21
+ uses: LegionIO/.github/.github/workflows/dependency-review.yml@main
22
+
11
23
  release:
12
- needs: ci
24
+ needs: [ci, excluded-files, security]
13
25
  if: github.event_name == 'push' && github.ref == 'refs/heads/main'
14
26
  uses: LegionIO/.github/.github/workflows/release.yml@main
15
27
  secrets:
data/CHANGELOG.md CHANGED
@@ -1,5 +1,40 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.2.6 - 2026-05-06
4
+
5
+ - Load provider-owned fleet actors through the LegionIO subscription base and the canonical Ollama provider root.
6
+ - Keep fleet runners anchored on the provider root namespace so provider constants and instance discovery are always loaded.
7
+ - Preserve configured transport and tier metadata when Ollama builds routing offerings.
8
+ - Gate release publishing on the shared security workflow.
9
+
10
+ ## 0.2.5 - 2026-05-06
11
+
12
+ - Mark cached offering discovery fallback exceptions as handled.
13
+ - Refresh README provider contract, fleet responder, development gate, and license details.
14
+
15
+ ## 0.2.4 - 2026-05-06
16
+
17
+ - Use the shared `lex-llm` fleet provider responder helper for provider-owned fleet workers.
18
+ - Remove the runtime `legion-llm` dependency and require `lex-llm >= 0.4.3` for responder-side fleet execution.
19
+
20
+ ## 0.2.3 - 2026-05-06
21
+
22
+ - Remove require-time provider self-registration; `legion-llm` now owns adapter creation and registry writes from loaded provider discovery metadata.
23
+ - Bump dependency floors to `lex-llm >= 0.4.1` and `legion-llm >= 0.9.1`.
24
+
25
+ ## 0.2.2 - 2026-05-06
26
+
27
+ - Add provider contract specs for the shared keyword-only `lex-llm` provider API.
28
+ - Move Ollama defaults back to `Legion::Extensions::Llm.provider_settings` with instance-level fleet responder settings.
29
+ - Serve non-live Ollama offering reads from cached live model discovery instead of probing the configured endpoint.
30
+ - Add provider-owned fleet responder actor and runner backed by `legion-llm` fleet policy execution.
31
+ - Bump the transport dependency floor to `legion-transport >= 1.4.14`.
32
+
33
+ ## 0.2.1 - 2026-05-03
34
+
35
+ - Normalize configured Ollama instance endpoint aliases to `base_url`.
36
+ - Use instance `base_url` config before provider defaults.
37
+
3
38
  ## 0.2.0 - 2026-05-01
4
39
 
5
40
  - Add auto-discovery via CredentialSources and AutoRegistration from lex-llm 0.3.0
data/Gemfile CHANGED
@@ -4,6 +4,8 @@ source 'https://rubygems.org'
4
4
 
5
5
  group :test do
6
6
  llm_base_path = ENV.fetch('LEX_LLM_PATH', File.expand_path('../lex-llm', __dir__))
7
+ transport_path = ENV.fetch('LEGION_TRANSPORT_PATH', File.expand_path('../../legion-transport', __dir__))
8
+ gem 'legion-transport', path: transport_path if File.directory?(transport_path)
7
9
  gem 'lex-llm', path: llm_base_path if File.directory?(llm_base_path)
8
10
  end
9
11
 
data/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  LegionIO LLM provider extension for [Ollama](https://ollama.ai).
4
4
 
5
- This gem lives under `Legion::Extensions::Llm::Ollama` and depends on `lex-llm` (>= 0.1.9) for shared provider-neutral routing, fleet, transport, and registry primitives.
5
+ This gem lives under `Legion::Extensions::Llm::Ollama` and depends on `lex-llm >= 0.4.3` for shared provider-neutral routing, response normalization, fleet envelopes, responder execution, transport, and registry primitives. It does not carry a runtime `legion-llm` dependency; `legion-llm` owns higher-level routing and can discover this provider through normal extension loading.
6
6
 
7
7
  Load it with `require 'legion/extensions/llm/ollama'`.
8
8
 
@@ -16,18 +16,22 @@ Load it with `require 'legion/extensions/llm/ollama'`.
16
16
  - Model download helper through `POST /api/pull`
17
17
  - Embeddings through `POST /api/embed`
18
18
  - Best-effort `llm.registry` availability events via the shared `Legion::Extensions::Llm::RegistryPublisher`
19
- - Full settings schema with model whitelist/blacklist, TLS, and multi-host base URL resolution
19
+ - Local socket discovery plus configured instance discovery through the shared `lex-llm` credential sources
20
+ - Provider-owned fleet response handling through `Legion::Extensions::Llm::Fleet::ProviderResponder`
20
21
  - Full `Legion::Logging::Helper` integration with structured `handle_exception` in every rescue block
21
22
 
22
23
  ## Architecture
23
24
 
24
25
  ```
25
26
  Legion::Extensions::Llm::Ollama
26
- ├── Provider # Ollama provider (chat, stream, embed, models, readiness)
27
+ ├── Provider # Ollama provider (chat, stream, embed, models, readiness)
28
+ ├── Actor::FleetWorker # Optional provider-owned fleet subscription actor
29
+ ├── Runners::FleetWorker # Delegates fleet execution to lex-llm
27
30
  └── (shared from lex-llm)
28
- ├── RegistryPublisher # Best-effort async llm.registry event publishing
29
- ├── RegistryEventBuilder # Sanitized registry envelope construction
30
- └── Transport/ # Shared exchange and message classes
31
+ ├── Fleet::ProviderResponder
32
+ ├── RegistryPublisher
33
+ ├── RegistryEventBuilder
34
+ └── Transport/
31
35
  ```
32
36
 
33
37
  ## Defaults
@@ -35,35 +39,71 @@ Legion::Extensions::Llm::Ollama
35
39
  ```ruby
36
40
  Legion::Extensions::Llm::Ollama.default_settings
37
41
  # {
38
- # enabled: false,
39
- # base_url: '127.0.0.1:11434',
40
- # default_model: 'qwen3.5:latest',
41
- # model_whitelist: [],
42
- # model_blacklist: [],
43
- # model_cache_ttl: 60,
44
- # tls: { enabled: false, verify: :peer },
45
- # instances: {}
42
+ # enabled: true,
43
+ # provider_family: :ollama,
44
+ # instances: {
45
+ # default: {
46
+ # endpoint: 'http://127.0.0.1:11434',
47
+ # default_model: 'qwen3.5:latest',
48
+ # tier: :local,
49
+ # transport: :http,
50
+ # credentials: {},
51
+ # usage: { inference: true, embedding: true, image: false },
52
+ # limits: { concurrency: 1 },
53
+ # fleet: {
54
+ # enabled: false,
55
+ # respond_to_requests: false,
56
+ # capabilities: %i[chat stream_chat embed],
57
+ # lanes: [],
58
+ # concurrency: 1,
59
+ # queue_suffix: nil
60
+ # }
61
+ # }
62
+ # }
46
63
  # }
47
64
  ```
48
65
 
49
66
  ## Configuration
50
67
 
51
- ```ruby
52
- Legion::Extensions::Llm.configure do |config|
53
- config.default_model = "qwen3.6:27b"
54
- config.default_embedding_model = "nomic-embed-text:latest"
55
- end
68
+ `discover_instances` returns a local `http://127.0.0.1:11434` instance when the Ollama socket is reachable. Additional instances can be supplied under the shared LLM extension configuration and may use `base_url`, `endpoint`, `api_base`, or `ollama_api_base`; the extension normalizes those aliases to `base_url`.
69
+
70
+ ```yaml
71
+ extensions:
72
+ llm:
73
+ ollama:
74
+ instances:
75
+ lab:
76
+ base_url: http://ollama-lab:11434
77
+ default_model: qwen3.5:latest
78
+ ```
79
+
80
+ ## Fleet Responder
81
+
82
+ Provider instances can opt in to consuming Legion LLM fleet requests. The provider-owned fleet actor only starts when at least one discovered instance enables `respond_to_requests`, and the runner delegates execution to the shared `lex-llm` responder helper.
83
+
84
+ ```yaml
85
+ extensions:
86
+ llm:
87
+ ollama:
88
+ instances:
89
+ local:
90
+ fleet:
91
+ enabled: true
92
+ respond_to_requests: true
93
+ capabilities:
94
+ - chat
95
+ - stream_chat
96
+ - embed
56
97
  ```
57
98
 
58
99
  ## Development
59
100
 
60
101
  ```bash
61
102
  bundle install
62
- bundle exec rspec # 0 failures
63
- bundle exec rubocop -A # auto-fix
64
- bundle exec rubocop # lint check
103
+ bundle exec rspec --format json --out tmp/rspec_results.json --format progress --out tmp/rspec_progress.txt
104
+ bundle exec rubocop -A
65
105
  ```
66
106
 
67
107
  ## License
68
108
 
69
- Apache-2.0
109
+ MIT
@@ -26,5 +26,6 @@ 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.3.0'
29
+ spec.add_dependency 'legion-transport', '>= 1.4.14'
30
+ spec.add_dependency 'lex-llm', '>= 0.4.3'
30
31
  end
@@ -0,0 +1,43 @@
1
+ # frozen_string_literal: true
2
+
3
+ begin
4
+ require 'legion/extensions/actors/subscription'
5
+ rescue LoadError => e
6
+ warn(e.message) if $VERBOSE
7
+ end
8
+
9
+ unless defined?(Legion::Extensions::Actors::Subscription)
10
+ raise LoadError, 'LegionIO actor runtime is required for Ollama fleet worker'
11
+ end
12
+
13
+ require 'legion/extensions/llm/ollama'
14
+ require 'legion/extensions/llm/fleet/provider_responder'
15
+
16
+ module Legion
17
+ module Extensions
18
+ module Llm
19
+ module Ollama
20
+ module Actor
21
+ # Subscription actor for Ollama fleet request consumption.
22
+ class FleetWorker < Legion::Extensions::Actors::Subscription
23
+ def runner_class
24
+ 'Legion::Extensions::Llm::Ollama::Runners::FleetWorker'
25
+ end
26
+
27
+ def runner_function
28
+ 'handle_fleet_request'
29
+ end
30
+
31
+ def use_runner?
32
+ false
33
+ end
34
+
35
+ def enabled?
36
+ Legion::Extensions::Llm::Fleet::ProviderResponder.enabled_for?(Ollama.discover_instances)
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
@@ -41,7 +41,7 @@ module Legion
41
41
  end
42
42
 
43
43
  def config_base_url
44
- settings[:base_url]
44
+ config.respond_to?(:base_url) ? config.base_url : settings[:base_url]
45
45
  end
46
46
 
47
47
  def completion_url = '/api/chat'
@@ -92,8 +92,62 @@ module Legion
92
92
  raise
93
93
  end
94
94
 
95
+ def discover_offerings(live: false, **)
96
+ models = if live
97
+ @cached_models = list_models
98
+ else
99
+ Array(@cached_models)
100
+ end
101
+ models.map { |model_info| offering_from_model(model_info) }
102
+ rescue StandardError => e
103
+ handle_exception(e, level: :warn, handled: true, operation: 'ollama.discover_offerings')
104
+ []
105
+ end
106
+
95
107
  private
96
108
 
109
+ def offering_from_model(model_info)
110
+ Legion::Extensions::Llm::Routing::ModelOffering.new(
111
+ provider_family: :ollama,
112
+ instance_id: config.respond_to?(:instance_id) ? config.instance_id : :default,
113
+ transport: offering_transport,
114
+ tier: offering_tier,
115
+ model: model_info.id,
116
+ usage_type: offering_usage_type(model_info),
117
+ capabilities: offering_capabilities(model_info),
118
+ limits: offering_limits(model_info),
119
+ metadata: offering_metadata(model_info)
120
+ )
121
+ end
122
+
123
+ def offering_transport
124
+ config.respond_to?(:transport) ? config.transport : :http
125
+ end
126
+
127
+ def offering_tier
128
+ config.respond_to?(:tier) ? config.tier : :local
129
+ end
130
+
131
+ def offering_usage_type(model_info)
132
+ model_info.embedding? ? :embedding : :inference
133
+ end
134
+
135
+ def offering_capabilities(model_info)
136
+ model_info.capabilities.map(&:to_s)
137
+ end
138
+
139
+ def offering_limits(model_info)
140
+ { context_window: model_info.context_length }.compact
141
+ end
142
+
143
+ def offering_metadata(model_info)
144
+ {
145
+ context_length: model_info.context_length,
146
+ family: model_info.family,
147
+ size_bytes: model_info.size_bytes
148
+ }.compact
149
+ end
150
+
97
151
  def ollama_keep_alive
98
152
  settings[:keep_alive]
99
153
  end
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'legion/extensions/llm/fleet/provider_responder'
4
+ require 'legion/extensions/llm/ollama'
5
+
6
+ module Legion
7
+ module Extensions
8
+ module Llm
9
+ module Ollama
10
+ module Runners
11
+ # Runner entrypoint for Ollama fleet request execution.
12
+ module FleetWorker
13
+ module_function
14
+
15
+ def handle_fleet_request(payload, delivery: nil, properties: nil)
16
+ Legion::Extensions::Llm::Fleet::ProviderResponder.call(
17
+ payload: payload,
18
+ provider_family: Ollama::PROVIDER_FAMILY,
19
+ provider_class: Ollama::Provider,
20
+ provider_instances: -> { Ollama.discover_instances },
21
+ delivery: delivery,
22
+ properties: properties
23
+ )
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -4,7 +4,7 @@ module Legion
4
4
  module Extensions
5
5
  module Llm
6
6
  module Ollama
7
- VERSION = '0.2.0'
7
+ VERSION = '0.2.6'
8
8
  end
9
9
  end
10
10
  end
@@ -16,16 +16,26 @@ module Legion
16
16
  PROVIDER_FAMILY = :ollama
17
17
 
18
18
  def self.default_settings
19
- {
20
- enabled: false,
21
- base_url: '127.0.0.1:11434',
22
- default_model: 'qwen3.5:latest',
23
- model_whitelist: [],
24
- model_blacklist: [],
25
- model_cache_ttl: 60,
26
- tls: { enabled: false, verify: :peer },
27
- instances: {}
28
- }
19
+ ::Legion::Extensions::Llm.provider_settings(
20
+ family: PROVIDER_FAMILY,
21
+ instance: {
22
+ endpoint: 'http://127.0.0.1:11434',
23
+ default_model: 'qwen3.5:latest',
24
+ tier: :local,
25
+ transport: :http,
26
+ credentials: {},
27
+ usage: { inference: true, embedding: true, image: false },
28
+ limits: { concurrency: 1 },
29
+ fleet: {
30
+ enabled: false,
31
+ respond_to_requests: false,
32
+ capabilities: %i[chat stream_chat embed],
33
+ lanes: [],
34
+ concurrency: 1,
35
+ queue_suffix: nil
36
+ }
37
+ }
38
+ )
29
39
  end
30
40
 
31
41
  def self.provider_class
@@ -50,7 +60,7 @@ module Legion
50
60
  configured = CredentialSources.setting(:extensions, :llm, :ollama, :instances)
51
61
  if configured.is_a?(Hash)
52
62
  configured.each do |name, config|
53
- instances[name.to_sym] = config.merge(
63
+ instances[name.to_sym] = normalize_instance_config(config).merge(
54
64
  tier: :direct,
55
65
  capabilities: %i[completion embedding vision]
56
66
  )
@@ -59,9 +69,15 @@ module Legion
59
69
 
60
70
  instances
61
71
  end
72
+
73
+ def self.normalize_instance_config(config)
74
+ normalized = config.to_h.transform_keys { |key| key.respond_to?(:to_sym) ? key.to_sym : key }
75
+ normalized[:base_url] ||= normalized.delete(:ollama_api_base)
76
+ normalized[:base_url] ||= normalized.delete(:api_base)
77
+ normalized[:base_url] ||= normalized.delete(:endpoint)
78
+ normalized.compact
79
+ end
62
80
  end
63
81
  end
64
82
  end
65
83
  end
66
-
67
- Legion::Extensions::Llm::Ollama.register_discovered_instances
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: lex-llm-ollama
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.2.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - LegionIO
@@ -51,20 +51,34 @@ dependencies:
51
51
  - - ">="
52
52
  - !ruby/object:Gem::Version
53
53
  version: 1.3.14
54
+ - !ruby/object:Gem::Dependency
55
+ name: legion-transport
56
+ requirement: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - ">="
59
+ - !ruby/object:Gem::Version
60
+ version: 1.4.14
61
+ type: :runtime
62
+ prerelease: false
63
+ version_requirements: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - ">="
66
+ - !ruby/object:Gem::Version
67
+ version: 1.4.14
54
68
  - !ruby/object:Gem::Dependency
55
69
  name: lex-llm
56
70
  requirement: !ruby/object:Gem::Requirement
57
71
  requirements:
58
72
  - - ">="
59
73
  - !ruby/object:Gem::Version
60
- version: 0.3.0
74
+ version: 0.4.3
61
75
  type: :runtime
62
76
  prerelease: false
63
77
  version_requirements: !ruby/object:Gem::Requirement
64
78
  requirements:
65
79
  - - ">="
66
80
  - !ruby/object:Gem::Version
67
- version: 0.3.0
81
+ version: 0.4.3
68
82
  description: Ollama provider integration for the LegionIO LLM routing framework.
69
83
  email:
70
84
  - matthewdiverson@gmail.com
@@ -83,7 +97,9 @@ files:
83
97
  - README.md
84
98
  - lex-llm-ollama.gemspec
85
99
  - lib/legion/extensions/llm/ollama.rb
100
+ - lib/legion/extensions/llm/ollama/actors/fleet_worker.rb
86
101
  - lib/legion/extensions/llm/ollama/provider.rb
102
+ - lib/legion/extensions/llm/ollama/runners/fleet_worker.rb
87
103
  - lib/legion/extensions/llm/ollama/version.rb
88
104
  homepage: https://github.com/LegionIO/lex-llm-ollama
89
105
  licenses: