lex-llm-ollama 0.3.4 → 0.3.5
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:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: c00ff8929f8723127315d78b2141144a64319b2af41526098397717f4833568a
|
|
4
|
+
data.tar.gz: 2bc5494b6cdd8ec0f4268218e530719baeadd75126c71f70bdbbc96f4e4fc468
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: b3a2b92564e059f37584612350f1e67a1f260d224b3237feaa8ba3158d4cef7d741765930dbd6a3d34694fcb7d8b1ce50ec43da743874a558134fbe32a9ad454
|
|
7
|
+
data.tar.gz: 6f79d61f8fd32e268d1363c21a78209f41a78560d8f22f8a60cfe0d5c35f97a3987e0900fb111b99b5721fe23d94bc9842f4132f86a3fe64c2f828c10c38984f
|
data/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,10 @@
|
|
|
3
3
|
## [Unreleased]
|
|
4
4
|
|
|
5
5
|
### Fixed
|
|
6
|
+
- **Complete discovery change detection** — ordinary discovery now compares the complete stable `OfferingDraft#to_h` contract as an order-independent, duplicate-count-preserving multiset. Only evidence `observed_at` telemetry is excluded; quota domains, metadata, publication source, scalar evidence authority, and every other draft field trigger one atomic replacement when changed.
|
|
7
|
+
- **Startup claim atomicity** — initial model discovery and write-time weight validation now complete before Ollama constructs a callable, coordinator, or Registry claim, so malformed settings cannot leave an orphan `:initializing` publication status or token; the next corrected discovery pass claims and activates the instance exactly once without a restart or operator repair.
|
|
8
|
+
- **SSOT v3 write-time weights** — Ollama drafts now publish the validated four-axis weight pair from live settings, and the existing discovery cadence atomically reconciles weight-only changes, initialization/activation races, sequence/cache updates, removals, and dormant configured-weight logging through lex-llm 0.7.6. No Settings callback, reload, reset, migration, restart, or operator action is introduced.
|
|
9
|
+
- **D14 callable-path wire conformance** — the actual `OllamaCallable#chat` path now accepts Task-01 canonical folded messages and renders the authoritative system content as the leading Ollama `role: system` message; legacy message tool-result handling remains intact.
|
|
6
10
|
- 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
11
|
- **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
12
|
- **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.
|
data/lex-llm-ollama.gemspec
CHANGED
|
@@ -27,7 +27,6 @@ Gem::Specification.new do |spec|
|
|
|
27
27
|
spec.add_dependency 'legion-logging', '>= 1.3.2'
|
|
28
28
|
spec.add_dependency 'legion-settings', '>= 1.4.2'
|
|
29
29
|
spec.add_dependency 'legion-transport', '>= 1.4.14'
|
|
30
|
-
# 0.7.
|
|
31
|
-
|
|
32
|
-
spec.add_dependency 'lex-llm', '>= 0.7.1'
|
|
30
|
+
# 0.7.6 adds write-time WeightSchema records and the atomic writer reconciler.
|
|
31
|
+
spec.add_dependency 'lex-llm', '>= 0.7.6'
|
|
33
32
|
end
|
|
@@ -23,6 +23,7 @@ require 'legion/extensions/llm/inventory/identity'
|
|
|
23
23
|
require 'legion/extensions/llm/inventory/records'
|
|
24
24
|
require 'legion/extensions/llm/inventory/evidence'
|
|
25
25
|
require 'legion/extensions/llm/inventory/probe_coordinator'
|
|
26
|
+
require 'legion/extensions/llm/inventory/weight_reconciler'
|
|
26
27
|
require 'legion/extensions/llm/routing/provider_outcome'
|
|
27
28
|
require 'legion/extensions/llm/taxonomies'
|
|
28
29
|
require 'legion/extensions/llm/capabilities'
|
|
@@ -248,6 +249,13 @@ module Legion
|
|
|
248
249
|
tier = instance_cfg[:tier] || :local
|
|
249
250
|
detail = fetch_model_detail_safe(model_name: model_name, instance_cfg: instance_cfg)
|
|
250
251
|
embed_supported = embedding_model?(model_name: model_name, model_data: model_data)
|
|
252
|
+
weight_inputs = Legion::Extensions::Llm::Inventory::WeightSchema.weight_inputs(
|
|
253
|
+
settings: Legion::Settings,
|
|
254
|
+
instance_key: instance_key,
|
|
255
|
+
provider_native_key: model_name,
|
|
256
|
+
model: model_name,
|
|
257
|
+
tier: tier
|
|
258
|
+
)
|
|
251
259
|
|
|
252
260
|
Legion::Extensions::Llm::Inventory::OfferingDraft.new(
|
|
253
261
|
provider_native_key: model_name,
|
|
@@ -267,7 +275,9 @@ module Legion
|
|
|
267
275
|
quota_domains: {},
|
|
268
276
|
metadata: build_offering_metadata(model_name: model_name, model_data: model_data)
|
|
269
277
|
.merge(instance_id: instance_key.instance_id),
|
|
270
|
-
publication_source: :provider_catalog
|
|
278
|
+
publication_source: :provider_catalog,
|
|
279
|
+
weight_inputs: weight_inputs,
|
|
280
|
+
base_weight: Legion::Extensions::Llm::Inventory::WeightSchema.base_weight(weight_inputs)
|
|
271
281
|
)
|
|
272
282
|
end
|
|
273
283
|
|
|
@@ -401,7 +411,7 @@ module Legion
|
|
|
401
411
|
# name is the CONFIG NAME — the @instance_states key. The
|
|
402
412
|
# publisher calls use the state's instance_id + physical_id pair.
|
|
403
413
|
def handle_reactive_probe(name:, request:)
|
|
404
|
-
state = @instance_states[name]
|
|
414
|
+
state = @state_mutex.synchronize { @instance_states[name] }
|
|
405
415
|
return unless state
|
|
406
416
|
|
|
407
417
|
coordinator = state[:probe_coordinator]
|
|
@@ -503,52 +513,40 @@ module Legion
|
|
|
503
513
|
|
|
504
514
|
# ── Offering change comparison helpers ───────────────────────────────
|
|
505
515
|
module OfferingComparison
|
|
516
|
+
SCALAR_EVIDENCE_FIELDS = %i[
|
|
517
|
+
context_evidence max_output_evidence embedding_dimensions_evidence
|
|
518
|
+
model_revision_evidence tokenizer_evidence
|
|
519
|
+
].freeze
|
|
520
|
+
|
|
506
521
|
private
|
|
507
522
|
|
|
508
|
-
#
|
|
509
|
-
#
|
|
510
|
-
#
|
|
511
|
-
# unchanged (replace churn on every tick).
|
|
523
|
+
# Every draft embeds fresh evidence observed_at telemetry. Compare
|
|
524
|
+
# the complete stable draft contract as a multiset so catalog order
|
|
525
|
+
# is irrelevant while duplicate counts remain significant.
|
|
512
526
|
def offerings_changed?(previous:, current:)
|
|
513
|
-
current
|
|
514
|
-
previous.map { |draft| offering_signature(draft) }
|
|
527
|
+
offering_multiset(current) != offering_multiset(previous)
|
|
515
528
|
end
|
|
516
529
|
|
|
517
|
-
def
|
|
518
|
-
|
|
519
|
-
draft.provider_native_key,
|
|
520
|
-
draft.model,
|
|
521
|
-
draft.tier,
|
|
522
|
-
operation_signature(draft),
|
|
523
|
-
capability_signature(draft),
|
|
524
|
-
value_signature(draft)
|
|
525
|
-
]
|
|
530
|
+
def offering_multiset(offerings)
|
|
531
|
+
offerings.map { |draft| stable_offering_state(draft) }.tally
|
|
526
532
|
end
|
|
527
533
|
|
|
528
|
-
def
|
|
529
|
-
draft.
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
[evidence.capability, evidence.status, evidence.source]
|
|
537
|
-
end.sort
|
|
534
|
+
def stable_offering_state(draft)
|
|
535
|
+
state = draft.to_h
|
|
536
|
+
state[:operation_evidence] = stable_evidence_map(draft.operation_evidence)
|
|
537
|
+
state[:capability_evidence] = stable_evidence_map(draft.capability_evidence)
|
|
538
|
+
SCALAR_EVIDENCE_FIELDS.each do |field|
|
|
539
|
+
state[field] = stable_evidence(draft.public_send(field))
|
|
540
|
+
end
|
|
541
|
+
state
|
|
538
542
|
end
|
|
539
543
|
|
|
540
|
-
def
|
|
541
|
-
|
|
542
|
-
value_pair(draft.context_evidence),
|
|
543
|
-
value_pair(draft.max_output_evidence),
|
|
544
|
-
value_pair(draft.embedding_dimensions_evidence),
|
|
545
|
-
value_pair(draft.model_revision_evidence),
|
|
546
|
-
value_pair(draft.tokenizer_evidence)
|
|
547
|
-
]
|
|
544
|
+
def stable_evidence_map(evidence)
|
|
545
|
+
evidence.transform_values { |entry| stable_evidence(entry) }
|
|
548
546
|
end
|
|
549
547
|
|
|
550
|
-
def
|
|
551
|
-
|
|
548
|
+
def stable_evidence(evidence)
|
|
549
|
+
evidence.to_h.except(:observed_at)
|
|
552
550
|
end
|
|
553
551
|
end
|
|
554
552
|
|
|
@@ -668,11 +666,11 @@ module Legion
|
|
|
668
666
|
instance_id = name.to_s
|
|
669
667
|
physical_id = derive_physical_id(instance_cfg: instance_cfg)
|
|
670
668
|
instance_key = build_instance_key(instance_id: instance_id, physical_id: physical_id)
|
|
669
|
+
offerings = discover_offerings_for_instance(instance_cfg: instance_cfg, instance_key: instance_key)
|
|
671
670
|
components = build_instance_components(
|
|
672
671
|
name: name.to_sym, instance_id: instance_id, physical_id: physical_id,
|
|
673
672
|
instance_cfg: instance_cfg, instance_key: instance_key
|
|
674
673
|
)
|
|
675
|
-
offerings = discover_offerings_for_instance(instance_cfg: instance_cfg, instance_key: instance_key)
|
|
676
674
|
state = {
|
|
677
675
|
name: name.to_sym,
|
|
678
676
|
instance_id: instance_id,
|
|
@@ -685,25 +683,113 @@ module Legion
|
|
|
685
683
|
sequence: 0,
|
|
686
684
|
offerings: offerings
|
|
687
685
|
}
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
686
|
+
Legion::Extensions::Llm::Inventory::WeightReconciler.track_initializing!(
|
|
687
|
+
states: @instance_states,
|
|
688
|
+
state_key: name.to_sym,
|
|
689
|
+
state: state,
|
|
690
|
+
mutex: @state_mutex
|
|
691
|
+
)
|
|
692
|
+
settled = settle_initial_readiness(state: state)
|
|
693
|
+
sync_display_health(state: state) if settled
|
|
691
694
|
end
|
|
692
695
|
|
|
693
696
|
def drop_instance(name:, state:)
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
697
|
+
removed = @state_mutex.synchronize do
|
|
698
|
+
next false unless @instance_states[name].equal?(state)
|
|
699
|
+
|
|
700
|
+
publisher.remove_instance(
|
|
701
|
+
instance_id: state[:instance_id], physical_id: state[:physical_id],
|
|
702
|
+
publisher_token: state[:publisher_token]
|
|
703
|
+
)
|
|
704
|
+
@instance_states.delete(name)
|
|
705
|
+
true
|
|
706
|
+
end
|
|
707
|
+
return unless removed
|
|
708
|
+
|
|
698
709
|
state[:callable]&.disconnect
|
|
699
710
|
clear_display_health(name: state[:name])
|
|
700
|
-
@instance_states.delete(name)
|
|
701
711
|
rescue StandardError => e
|
|
702
712
|
handle_exception(e, level: :warn, operation: 'ollama.actor.remove_instance',
|
|
703
713
|
instance_id: state[:instance_id])
|
|
704
714
|
end
|
|
705
715
|
end
|
|
706
716
|
|
|
717
|
+
# Atomic adapters and dormant observation shared by the existing
|
|
718
|
+
# discovery cadence. Sequence and cache mutation remain owned by
|
|
719
|
+
# lex-llm's WeightReconciler.
|
|
720
|
+
module WeightPublication
|
|
721
|
+
private
|
|
722
|
+
|
|
723
|
+
def replace_offerings_if_changed(state:)
|
|
724
|
+
new_offerings = discover_offerings_for_instance(
|
|
725
|
+
instance_cfg: state[:instance_cfg], instance_key: state[:instance_key]
|
|
726
|
+
)
|
|
727
|
+
changed = Legion::Extensions::Llm::Inventory::WeightReconciler.commit_if_changed!(
|
|
728
|
+
settings: Legion::Settings,
|
|
729
|
+
instance_id: state[:instance_id],
|
|
730
|
+
state: state,
|
|
731
|
+
discovered_offerings: new_offerings,
|
|
732
|
+
mutex: @state_mutex,
|
|
733
|
+
equivalent: lambda do |previous, current|
|
|
734
|
+
!offerings_changed?(previous: previous, current: current)
|
|
735
|
+
end,
|
|
736
|
+
replace: method(:replace_weight_snapshot)
|
|
737
|
+
)
|
|
738
|
+
published = @state_mutex.synchronize { state[:published] }
|
|
739
|
+
sync_display_health(state: state) if changed && published
|
|
740
|
+
changed
|
|
741
|
+
end
|
|
742
|
+
|
|
743
|
+
def replace_weight_snapshot(instance_id:, state:, offerings:, sequence:)
|
|
744
|
+
publisher.replace_instance_snapshot(
|
|
745
|
+
instance_id: instance_id,
|
|
746
|
+
physical_id: state[:physical_id],
|
|
747
|
+
publisher_token: state.fetch(:publisher_token),
|
|
748
|
+
offerings: offerings,
|
|
749
|
+
sequence: sequence
|
|
750
|
+
)
|
|
751
|
+
end
|
|
752
|
+
|
|
753
|
+
def activate_weight_snapshot(instance_id:, state:, offerings:, sequence:, probe_token:)
|
|
754
|
+
publisher.activate_instance_snapshot(
|
|
755
|
+
instance_id: instance_id,
|
|
756
|
+
physical_id: state.fetch(:physical_id),
|
|
757
|
+
publisher_token: state.fetch(:publisher_token),
|
|
758
|
+
offerings: offerings,
|
|
759
|
+
sequence: sequence,
|
|
760
|
+
probe_token: probe_token
|
|
761
|
+
)
|
|
762
|
+
end
|
|
763
|
+
|
|
764
|
+
def observe_dormant_weights
|
|
765
|
+
Legion::Extensions::Llm::Inventory::WeightReconciler.observe_dormant!(
|
|
766
|
+
settings: Legion::Settings,
|
|
767
|
+
provider_family: :ollama,
|
|
768
|
+
states: @instance_states,
|
|
769
|
+
mutex: @state_mutex,
|
|
770
|
+
tracker: @dormant_weight_tracker,
|
|
771
|
+
dormant_logger: lambda do |key|
|
|
772
|
+
log.info do
|
|
773
|
+
"[llm][ollama] action=dormant_weight weight_key=#{key.inspect} no_lane_published=true"
|
|
774
|
+
end
|
|
775
|
+
end
|
|
776
|
+
)
|
|
777
|
+
end
|
|
778
|
+
|
|
779
|
+
def remove_all_instances
|
|
780
|
+
return unless @instance_states
|
|
781
|
+
|
|
782
|
+
states = @state_mutex.synchronize { @instance_states.each_pair.to_a }
|
|
783
|
+
states.each do |name, state|
|
|
784
|
+
drop_instance(name: name, state: state)
|
|
785
|
+
end
|
|
786
|
+
@state_mutex.synchronize do
|
|
787
|
+
@instance_states.clear
|
|
788
|
+
@dormant_weight_tracker.clear!
|
|
789
|
+
end
|
|
790
|
+
end
|
|
791
|
+
end
|
|
792
|
+
|
|
707
793
|
# Per-instance SSOT lifecycle: reconcile configured instances each
|
|
708
794
|
# tick, run the readiness state machine (initial probe, recovery
|
|
709
795
|
# while :initializing, cadence probes, snapshot replacement), and
|
|
@@ -713,6 +799,8 @@ module Legion
|
|
|
713
799
|
|
|
714
800
|
def initial_discovery
|
|
715
801
|
@instance_states = Concurrent::Map.new
|
|
802
|
+
@state_mutex = Mutex.new
|
|
803
|
+
@dormant_weight_tracker = Legion::Extensions::Llm::Inventory::DormantWeightTracker.new
|
|
716
804
|
reconcile_and_refresh
|
|
717
805
|
end
|
|
718
806
|
|
|
@@ -728,10 +816,11 @@ module Legion
|
|
|
728
816
|
# distinct, independently-managed instances.
|
|
729
817
|
def reconcile_and_refresh
|
|
730
818
|
configured = configured_instances
|
|
731
|
-
existing = @instance_states.keys
|
|
819
|
+
existing = @state_mutex.synchronize { @instance_states.keys }
|
|
732
820
|
add_newly_configured_instances(configured: configured)
|
|
733
821
|
remove_unconfigured_instances(configured: configured)
|
|
734
|
-
@
|
|
822
|
+
states = @state_mutex.synchronize { @instance_states.each_pair.to_a }
|
|
823
|
+
states.each do |name, state|
|
|
735
824
|
next unless existing.include?(name)
|
|
736
825
|
|
|
737
826
|
refresh_instance(state: state)
|
|
@@ -739,11 +828,13 @@ module Legion
|
|
|
739
828
|
handle_exception(e, level: :warn, operation: 'ollama.actor.refresh_instance',
|
|
740
829
|
instance_id: state[:instance_id])
|
|
741
830
|
end
|
|
831
|
+
observe_dormant_weights
|
|
742
832
|
end
|
|
743
833
|
|
|
744
834
|
def add_newly_configured_instances(configured:)
|
|
745
835
|
configured.each do |name, instance_cfg|
|
|
746
|
-
|
|
836
|
+
tracked = @state_mutex.synchronize { @instance_states.key?(name.to_sym) }
|
|
837
|
+
next if tracked
|
|
747
838
|
|
|
748
839
|
claim_and_activate_instance(name: name, instance_cfg: instance_cfg)
|
|
749
840
|
rescue StandardError => e
|
|
@@ -752,7 +843,8 @@ module Legion
|
|
|
752
843
|
end
|
|
753
844
|
|
|
754
845
|
def remove_unconfigured_instances(configured:)
|
|
755
|
-
@
|
|
846
|
+
states = @state_mutex.synchronize { @instance_states.each_pair.to_a }
|
|
847
|
+
states.each do |name, state|
|
|
756
848
|
next if configured.key?(name)
|
|
757
849
|
|
|
758
850
|
drop_instance(name: name, state: state)
|
|
@@ -772,68 +864,48 @@ module Legion
|
|
|
772
864
|
)
|
|
773
865
|
readiness = check_readiness(instance_cfg: state[:instance_cfg])
|
|
774
866
|
if readiness.ready?
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
867
|
+
Legion::Extensions::Llm::Inventory::WeightReconciler.activate_tracked!(
|
|
868
|
+
settings: Legion::Settings,
|
|
869
|
+
instance_id: instance_id,
|
|
870
|
+
state_key: state[:name],
|
|
871
|
+
state: state,
|
|
872
|
+
states: @instance_states,
|
|
873
|
+
mutex: @state_mutex,
|
|
874
|
+
probe_token: probe_token,
|
|
875
|
+
activate: method(:activate_weight_snapshot),
|
|
876
|
+
activation_sequence: ->(tracked) { tracked.fetch(:sequence) }
|
|
779
877
|
)
|
|
780
878
|
else
|
|
879
|
+
tracked = @state_mutex.synchronize { @instance_states[state[:name]].equal?(state) }
|
|
880
|
+
return false unless tracked
|
|
881
|
+
|
|
781
882
|
publisher.readiness_failed(
|
|
782
883
|
instance_id: instance_id, physical_id: physical_id,
|
|
783
884
|
probe_token: probe_token, reason: readiness.reason
|
|
784
885
|
)
|
|
886
|
+
true
|
|
785
887
|
end
|
|
786
888
|
end
|
|
787
889
|
|
|
788
890
|
def refresh_instance(state:)
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
else
|
|
891
|
+
published = @state_mutex.synchronize { state[:published] }
|
|
892
|
+
if published
|
|
792
893
|
replace_offerings_if_changed(state: state)
|
|
793
894
|
run_cadence_probe(state: state)
|
|
895
|
+
else
|
|
896
|
+
retry_initial_activation(state: state)
|
|
794
897
|
end
|
|
795
898
|
end
|
|
796
899
|
|
|
797
|
-
def publication_state(instance_key:)
|
|
798
|
-
publisher.snapshot.publication_status(instance_key: instance_key).state
|
|
799
|
-
end
|
|
800
|
-
|
|
801
900
|
# An instance that failed initial readiness stays :initializing —
|
|
802
901
|
# readiness_succeeded and replace_instance_snapshot both refuse to
|
|
803
902
|
# operate on an :initializing scope, so without this re-activation
|
|
804
903
|
# path a transient outage at boot pins the instance for the process
|
|
805
904
|
# lifetime. Re-probe each tick and activate once readiness passes.
|
|
806
905
|
def retry_initial_activation(state:)
|
|
807
|
-
state
|
|
808
|
-
|
|
809
|
-
)
|
|
810
|
-
settle_initial_readiness(state: state)
|
|
811
|
-
sync_display_health(state: state)
|
|
812
|
-
end
|
|
813
|
-
|
|
814
|
-
def replace_offerings_if_changed(state:)
|
|
815
|
-
new_offerings = discover_offerings_for_instance(
|
|
816
|
-
instance_cfg: state[:instance_cfg], instance_key: state[:instance_key]
|
|
817
|
-
)
|
|
818
|
-
return unless offerings_changed?(previous: state[:offerings], current: new_offerings)
|
|
819
|
-
|
|
820
|
-
state[:sequence] += 1
|
|
821
|
-
publisher.replace_instance_snapshot(
|
|
822
|
-
instance_id: state[:instance_id], physical_id: state[:physical_id],
|
|
823
|
-
publisher_token: state[:publisher_token],
|
|
824
|
-
offerings: new_offerings, sequence: state[:sequence]
|
|
825
|
-
)
|
|
826
|
-
state[:offerings] = new_offerings
|
|
827
|
-
sync_display_health(state: state)
|
|
828
|
-
end
|
|
829
|
-
|
|
830
|
-
def remove_all_instances
|
|
831
|
-
return unless @instance_states
|
|
832
|
-
|
|
833
|
-
@instance_states.each do |name, state|
|
|
834
|
-
drop_instance(name: name, state: state)
|
|
835
|
-
end
|
|
836
|
-
@instance_states.clear
|
|
906
|
+
replace_offerings_if_changed(state: state)
|
|
907
|
+
settled = settle_initial_readiness(state: state)
|
|
908
|
+
sync_display_health(state: state) if settled
|
|
837
909
|
end
|
|
838
910
|
end
|
|
839
911
|
|
|
@@ -857,6 +929,7 @@ module Legion
|
|
|
857
929
|
include OfferingComparison
|
|
858
930
|
include DisplayHealth
|
|
859
931
|
include InstanceComponents
|
|
932
|
+
include WeightPublication
|
|
860
933
|
include InstanceLifecycle
|
|
861
934
|
|
|
862
935
|
def runner_class = self.class
|
|
@@ -405,7 +405,12 @@ module Legion
|
|
|
405
405
|
content = message.content
|
|
406
406
|
payload = { role: message.role.to_s, content: format_content(content) }
|
|
407
407
|
payload[:images] = encoded_attachments(content) if content.respond_to?(:attachments)
|
|
408
|
-
|
|
408
|
+
tool_result = if message.respond_to?(:tool_result?)
|
|
409
|
+
message.tool_result?
|
|
410
|
+
else
|
|
411
|
+
message.role.to_sym == :tool
|
|
412
|
+
end
|
|
413
|
+
payload[:tool_call_id] = message.tool_call_id if tool_result && message.respond_to?(:tool_call_id)
|
|
409
414
|
payload
|
|
410
415
|
end
|
|
411
416
|
end
|
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.3.
|
|
4
|
+
version: 0.3.5
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- LegionIO
|
|
@@ -71,14 +71,14 @@ dependencies:
|
|
|
71
71
|
requirements:
|
|
72
72
|
- - ">="
|
|
73
73
|
- !ruby/object:Gem::Version
|
|
74
|
-
version: 0.7.
|
|
74
|
+
version: 0.7.6
|
|
75
75
|
type: :runtime
|
|
76
76
|
prerelease: false
|
|
77
77
|
version_requirements: !ruby/object:Gem::Requirement
|
|
78
78
|
requirements:
|
|
79
79
|
- - ">="
|
|
80
80
|
- !ruby/object:Gem::Version
|
|
81
|
-
version: 0.7.
|
|
81
|
+
version: 0.7.6
|
|
82
82
|
description: Ollama provider integration for the LegionIO LLM routing framework.
|
|
83
83
|
email:
|
|
84
84
|
- matthewdiverson@gmail.com
|