lex-llm-ollama 0.2.25 → 0.3.4
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 +4 -4
- data/CHANGELOG.md +65 -0
- data/Gemfile +2 -0
- data/lex-llm-ollama.gemspec +4 -2
- data/lib/legion/extensions/llm/ollama/actors/discovery_refresh.rb +999 -110
- data/lib/legion/extensions/llm/ollama/actors/fleet_worker.rb +8 -9
- data/lib/legion/extensions/llm/ollama/provider.rb +22 -18
- data/lib/legion/extensions/llm/ollama/runners/fleet_worker.rb +10 -13
- data/lib/legion/extensions/llm/ollama/translator.rb +1 -1
- data/lib/legion/extensions/llm/ollama/version.rb +1 -1
- data/lib/legion/extensions/llm/ollama.rb +52 -36
- metadata +5 -5
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: a7cb2a1511c933e0174c414ba400ef0d7fcc700feeb2ac866be66004447f9df9
|
|
4
|
+
data.tar.gz: 90756cc1de56697e25880b801a07016a6e0d6b5edda22025b053850716e267cf
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 603aee402d7b5f0733369fb78c45430ac452ae33d2f8cf05adc7871552ba19f556cd43ab9cf3986ad8a9644798fd0924b394c5d39aff4150ffcc5714003ec299
|
|
7
|
+
data.tar.gz: 27a834f6be3252033fcc7f8028d8fd44f2056202bb7adf441f01b34f35832791aa6ac69c55db782398a509255af45f6c0ede82733d21dc7b19aa166683590b53
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,70 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [Unreleased]
|
|
4
|
+
|
|
5
|
+
### Fixed
|
|
6
|
+
- Remove synthetic-default discovery filtering and its once-per-boot warning; configured discovery now passes every instance entry through normal enabled and endpoint validation.
|
|
7
|
+
- **D1 Callable dispatch** — `OllamaCallable` now implements the fleet dispatch ops (`chat`, `stream_chat`, `embed`, `count_tokens`) by delegating to a per-instance `Ollama::Provider` (previously hardcoded fake payloads that swallowed `messages:` into `**`); errors propagate unrescued for `normalize_dispatch_error`; `disconnect` closes the Provider. Optional `provider:` injection seam for specs (production builds the real Provider lazily).
|
|
8
|
+
- **D15 Raw-string model at the dispatch boundary** — the fleet passes `model:` as the offering's raw id (String). Ollama's render path is string-tolerant (`model.respond_to?(:id) ? model.id : model`) for chat and embed, embed places the model verbatim in the `Embedding` response object, and count_tokens ignores it — so the raw string passes through UNWRAPPED on every op (wrapping would serialize a `Data` object into the wire payload or the response object); `Model::Info` instances pass through unchanged.
|
|
9
|
+
- **D4 Initial-failure recovery** — an instance whose initial readiness failed stays claimable: each tick probes while `:initializing` and re-activates via `activate_instance_snapshot` (fresh probe token, current offerings, sequence 0) on the first passing probe. Previously the instance stayed `:initializing` for the process lifetime (`replace_instance_snapshot`/`readiness_succeeded` refuse to operate on an `:initializing` scope).
|
|
10
|
+
- **D4 Tick reconcile** — configured instances are re-scanned every tick: instances configured after boot are claimed without a restart; removed instances are retired from the Registry and their settings health cleared.
|
|
11
|
+
- **D3 Unconfigured phantom** — only operator-configured instances are claimed. The synthetic `instances.default` section (provider_settings nests the extension's own instance defaults there) is skipped with a warn while it is still the unmodified extension default; named instances are always operator-authored; `enabled: false` and endpoint-less entries are skipped with a warn. No host/port fallback in `derive_instance_id` (raises on a missing endpoint instead).
|
|
12
|
+
- **D3 Legacy port-scan phantom** — the entry module's `discover_local_instance` socket probe (fabricated `:local` when 127.0.0.1:11434 answers) is deleted; `Ollama.discover_instances` and the SSOT actor share one source (`Ollama.configured_instances`).
|
|
13
|
+
- **D2 Bridge** — `Publisher` constructed with the `ScopedRefresher::LegacyCoordinatorAdapter` so SSOT commits project into the old `Legion::LLM::Inventory` coordinator during the mixed-version window.
|
|
14
|
+
- **D8/D17 Error shapes** — `normalize_dispatch_error` delegates to the base `Provider#normalize_dispatch_error` classification (every `Llm::*Error` the ErrorMiddleware raises, plus the raw Faraday transport errors it does not wrap: connection failure — the Ollama down-signal — and timeout) and layers provider-specific detection on top: a 5xx body reporting the model not loaded/loading is `:model_not_ready`, and raw Faraday HTTP status errors (which the base leaves as `:provider_error`) are refined by status. Body/status detection reads every real error shape (`Faraday::Response` from Llm errors, `Faraday::Env` from real Faraday 2.x errors, plain Hash) — no `is_a?(Hash)`-only gate. Readiness status detection handles Response/Env/Hash shapes.
|
|
15
|
+
- **D9 Cadence interval** — actor `time` reads the registered `discovery.interval_seconds` (never nil; falls back to the registered default); dead `self.every_seconds` removed.
|
|
16
|
+
- **D12 State store** — `@instance_states` moved from a plain `Hash` to a `Concurrent::Map` (timer/dispatch/shutdown threads).
|
|
17
|
+
- **D13 Fleet dispatch** — fleet `Subscription` actor's `runner_class` returns the runner CONSTANT (a String cannot be `send`-ed by the `runner_class.send(fn, **message)` dispatch path) and the runner accepts the envelope as kwargs (`handle_fleet_request(**opts)`), matching the dispatch shape.
|
|
18
|
+
- **D14 Health display** — after each registry commit the actor writes `settings[:instances][<config_name>][:health]` (legacy 4-key shape: `circuit_state`/`denied`/`available`/`adjustment` + display `reason`/`observed_at`(ISO8601 UTC)/`last_probe_outcome`/`source`) and `[:capabilities]`; cleared on removal/shutdown. Display-only — routing authority stays the in-memory `AvailabilityFact`.
|
|
19
|
+
- **D16 Loud discovery** — `discover_offerings_for_instance` rescues only `Faraday::Error`/`Legion::JSON::ParseError` (transport/parse); programming errors (`NameError`/`NoMethodError`/`ArgumentError`) propagate instead of publishing an activated instance with an empty offering set. The actor-runtime soft guard (`rescue LoadError` + `return unless defined?`) now raises `LoadError` (fail loud).
|
|
20
|
+
- **D3-churn** — offerings are compared on identity/status fields (not `Data#==`, which fresh `Time.now` `observed_at` stamps poison) so an unchanged catalog no longer triggers `replace_instance_snapshot` every tick.
|
|
21
|
+
- **Standard sweep** — `require_relative` → `require`; in-method `require 'faraday'` hoisted to file top; `extend Core if const_defined?` guard removed (hard dep); logic extracted from the actor class into `EvidenceBuilder`, `ValueEvidenceBuilder`, `ModelDiscovery`, `ConfigResolver`, `HttpClient`, `ProbeRunner`, `HealthChecker`, `OfferingComparison`, `DisplayHealth`, `InstanceComponents`, `InstanceLifecycle` modules so all files sit under Metrics limits.
|
|
22
|
+
- **D6 Specs** — conformance harness now returns the PRODUCTION `OllamaCallable` (the `TrackingOllamaCallable` re-implementation is deleted) and delegates identity/draft building to the actor's real helpers; error fixtures use real Faraday 2.x `Faraday::Env` shapes; new D17 Llm-error-shape classification tests; new D15 per-op raw-string render-path tests; kit glob narrowed to the consumed example-group files (lex-llm self-test specs no longer run in this suite); NEW `actor/discovery_refresh_spec.rb` lifecycle coverage (multi-instance claim/activate, D3 phantom handling, D4 recovery, tick reconcile, D9 interval, D14 health, churn, D16 loud errors, shutdown).
|
|
23
|
+
- **D10 Lock** — `Gemfile.lock` regenerated locally (gitignored): lex-llm now resolves 0.7.0 (gemspec requires `>= 0.7.0`; the stale lock pinned 0.6.17, where the SSOT inventory layer does not exist).
|
|
24
|
+
- **Instance identity is now the operator's config NAME** — the discovery actor previously keyed instances by the derived `host:port` string (`derive_instance_id`, now `derive_physical_id`). The derived id silently inerted the router's `instances.<name>` settings lookups (per-instance tuning, weight, preferred context windows) and collapsed distinct config names that share an endpoint. Discovery now publishes `InstanceKey.instance_id` = the config name and carries the derived `host:port` in the secondary `physical_id` field (dedup/diagnostics only — it never participates in equality, hashing, or registry-scope identity). Two config names pointing at the same endpoint stay distinct instances. A modified `instances.default` is skipped in `claimable_instance_config` (the single source shared by the discovery actor and the fleet responder) because the lex-llm foundation reserves `default` as an instance identity; no host/port fallback in `derive_physical_id` (raises on a missing endpoint instead).
|
|
25
|
+
- **Embedding models now authoritatively exclude chat** — an embedding model published `chat: :supported`/`stream_chat: :supported`, so a plain chat request could be misrouted to an embedding-only model. The evidence builder now branches on `embed_supported` (matching bedrock): embedding models publish `chat`/`stream_chat` as `:unsupported` and `embed` as `:supported`; chat models publish `embed` as `:unsupported`.
|
|
26
|
+
- **lex-llm 0.7.1 floor** — the gemspec now requires `lex-llm >= 0.7.1`: the name-identity `InstanceKey` with the secondary `physical_id` field and the reserved-`default` rejection (0.7.0's `InstanceKey` has no `physical_id` and accepts any instance_id).
|
|
27
|
+
- **Single actor registration** — the provider module no longer extends Core at file level, so the boot-time submodule walk skips it and the gem's own top-level extension load is the sole actor registration (eliminates the double-claim / FencedPublisherError).
|
|
28
|
+
- **Synthetic-default skip warn** — the `reason=synthetic_default` skip warn now fires once per boot instead of every discovery tick (was permanent WARN noise).
|
|
29
|
+
|
|
30
|
+
## [0.3.2] - 2026-08-13
|
|
31
|
+
|
|
32
|
+
### Fixed
|
|
33
|
+
- **§1 settings access via .dig:** `api_base` now reads `settings[:instances][:default][:endpoint]` using bracket notation instead of the prohibited `.dig` form.
|
|
34
|
+
- **§9 default model substitution removed:** `translator.rb` `render_request` no longer falls back to `'default'` when model is absent from request metadata; the field is omitted (compacted) so the exact selected model must be provided by the executor.
|
|
35
|
+
- **§1 swallowed rescue fixed:** `extract_host_port` in the discovery actor now calls `handle_exception` and re-raises on `URI::InvalidURIError` instead of silently returning `'unknown:0'`.
|
|
36
|
+
- **§1 swallowed rescue fixed:** `check_readiness` rescues now call `handle_exception` (with `handled: true`) before constructing the `ReadinessResult`, preserving the log audit trail.
|
|
37
|
+
- **§1 cop strictness reverted:** `RSpec/MultipleMemoizedHelpers: Max: 7` removed from `.rubocop.yml`; conformance spec refactored to comply with the default maximum of 5 memoized helpers per context.
|
|
38
|
+
|
|
39
|
+
## [0.3.1] - 2026-08-13
|
|
40
|
+
|
|
41
|
+
### Fixed
|
|
42
|
+
- **§8 health firewall:** Connection failures, timeouts, and 5xx errors stay request-local and never map to `:instance_unavailable`. Only an explicit flat service-unavailable wire signal maps to that outcome.
|
|
43
|
+
- **§9 no `:default` substitution:** `offering_from_model` derives a stable `instance_id` from the configured endpoint URL (`host:port`) instead of substituting the `:default` symbol.
|
|
44
|
+
- **§1 rubocop:disable removed:** All `rubocop:disable` comments removed from source and spec files; underlying causes fixed.
|
|
45
|
+
- **§1 swallowed rescue fixed:** `coordinator.finish_probe` failure now logged with `handle_exception` rather than silently swallowed.
|
|
46
|
+
- **§1 settings path corrected:** `api_base` reads `settings.dig(:instances, :default, :endpoint)` instead of the non-existent top-level `settings[:endpoint]`, preventing invalid base URL construction.
|
|
47
|
+
- **§2/§5 second publication engine removed:** `readiness` and `discover_live_offerings` no longer call `registry_publisher.publish_readiness_async` or `publish_models_async`; the SSOT v3 actor is the sole publication path.
|
|
48
|
+
- **Provider capabilities corrected:** `vision?`, `functions?`, `embedding?` return `false` (not `true`) as the static predicate; evidence-based values are derived per-model by the discovery actor.
|
|
49
|
+
- **Settings `embedding: true` removed:** Blanket embedding capability removed from usage defaults; embedding is declared per-model by the discovery actor based on `/api/tags` family evidence.
|
|
50
|
+
|
|
51
|
+
## [0.3.0] - 2026-08-13
|
|
52
|
+
|
|
53
|
+
### Changed
|
|
54
|
+
- **SSOT v3 provider migration.** Replace legacy `ScopedRefresher`/`Legion::LLM::Call::Registry` discovery with direct `Inventory::Publisher` claim/activate/replace lifecycle using the lex-llm 0.7.0 runtime contract.
|
|
55
|
+
- Discovery actor now claims exact Ollama instances, builds complete `OfferingDraft` snapshots from `/api/tags` and `/api/show`, and probes readiness via `/api/tags` (non-inference, no model load).
|
|
56
|
+
- Per-model operation evidence: chat/stream_chat always supported, embed supported only for embedding models, image/transcribe/translate/speak/moderate unsupported, count_tokens unknown.
|
|
57
|
+
- Per-model capability evidence from `/api/show` response (tools, thinking, vision) with honest unknown when unavailable.
|
|
58
|
+
- Remove `default_model: 'qwen3.5:latest'` from settings. Omitted model reaches the router unconstrained; provider invocation receives the exact selected model.
|
|
59
|
+
- Stable InstanceKey derivation: `host:port` from the configured endpoint URL.
|
|
60
|
+
- Normalized dispatch errors: connection failure stays `connection_failure`, 503 stays `overloaded`, timeouts stay `timeout`. No raw status code produces `instance_unavailable`.
|
|
61
|
+
- Graceful shutdown removes all claimed instances.
|
|
62
|
+
- Raise gemspec floor to `lex-llm >= 0.7.0`.
|
|
63
|
+
|
|
64
|
+
### Added
|
|
65
|
+
- `OllamaCallable` wrapper implementing `disconnect` and `normalize_dispatch_error(error:)` for the SSOT callable contract.
|
|
66
|
+
- SSOT v3 conformance spec exercising shared provider examples.
|
|
67
|
+
|
|
3
68
|
## [0.2.25] - 2026-08-04
|
|
4
69
|
|
|
5
70
|
### Changed
|
data/Gemfile
CHANGED
data/lex-llm-ollama.gemspec
CHANGED
|
@@ -25,7 +25,9 @@ Gem::Specification.new do |spec|
|
|
|
25
25
|
|
|
26
26
|
spec.add_dependency 'legion-json', '>= 1.2.1'
|
|
27
27
|
spec.add_dependency 'legion-logging', '>= 1.3.2'
|
|
28
|
-
spec.add_dependency 'legion-settings', '>= 1.
|
|
28
|
+
spec.add_dependency 'legion-settings', '>= 1.4.2'
|
|
29
29
|
spec.add_dependency 'legion-transport', '>= 1.4.14'
|
|
30
|
-
|
|
30
|
+
# 0.7.1 carries the name-identity InstanceKey (instance_id = config name +
|
|
31
|
+
# secondary physical_id field) that the SSOT v3 discovery actor publishes.
|
|
32
|
+
spec.add_dependency 'lex-llm', '>= 0.7.1'
|
|
31
33
|
end
|