Module: Legion::Extensions::Llm::Ollama::Runners::Discovery

Extended by:
Discovery
Includes:
Discovery::Pipeline
Included in:
Discovery
Defined in:
lib/legion/extensions/llm/ollama/runners/discovery.rb

Overview

Ollama discovery runner: ONLY the Ollama-specific work. Reconcile, claim, activate, probe (cadence + reactive), replace, weight publication, dormant-weight tracking, and health display are all mixed in from the shared Discovery::Pipeline. Weight is NOT computed here — the shared WeightReconciler recomputes the write-time weight from live settings at publish.

Ollama is local (no auth). Its catalog is GET /api/tags -> body with the model id under :name (not :id). Readiness is a non-inference GET /api/tags. Per-model detail (context window, capabilities, embedding dimensions) is optional enrichment from POST /api/show.

Instance Method Summary collapse

Instance Method Details

#build_callable(instance_cfg:) ⇒ Object



58
59
60
# File 'lib/legion/extensions/llm/ollama/runners/discovery.rb', line 58

def build_callable(instance_cfg:)
  Legion::Extensions::Llm::Ollama::Helpers::Callable.new(instance_cfg: instance_cfg, logger: log)
end

#build_offering_draft(instance_cfg:, instance_key:, model_id:, model_data:) ⇒ Object

── Offering draft (evidence + metadata; NO weight) ───────────────



88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
# File 'lib/legion/extensions/llm/ollama/runners/discovery.rb', line 88

def build_offering_draft(instance_cfg:, instance_key:, model_id:, model_data:)
  tier = instance_cfg[:tier] || :local
  detail = fetch_model_detail_safe(model_name: model_id, instance_cfg: instance_cfg)
  embed_supported = embedding_model?(model_name: model_id, model_data: model_data)

  Legion::Extensions::Llm::Inventory::OfferingDraft.new(
    provider_native_key: model_id,
    model: model_id,
    tier: tier,
    operation_evidence: build_operation_evidence(embed_supported: embed_supported),
    capability_evidence: build_capability_evidence(model_name: model_id, model_data: model_data,
                                                   detail: detail),
    context_evidence: build_context_evidence(detail: detail),
    max_output_evidence: absent_value_evidence,
    embedding_dimensions_evidence: build_embedding_dimensions_evidence(embed_supported: embed_supported,
                                                                       detail: detail),
    model_revision_evidence: build_model_revision_evidence(model_data: model_data),
    tokenizer_evidence: absent_value_evidence,
    quota_domains: {},
    metadata: (model_name: model_id, model_data: model_data)
              .merge(instance_id: instance_key.instance_id),
    publication_source: :provider_catalog
  )
end

#catalog_base_url(instance_cfg:) ⇒ Object

── Ollama instance config / connection ───────────────────────────



32
33
34
# File 'lib/legion/extensions/llm/ollama/runners/discovery.rb', line 32

def catalog_base_url(instance_cfg:)
  (instance_cfg[:base_url] || instance_cfg[:endpoint]).to_s
end

#derive_physical_id(instance_cfg:) ⇒ Object

Secondary PHYSICAL id (dedup/diagnostics), not identity: the exact host:port the operator configured. No host or port fallback (a fallback physical id would mask a missing endpoint).



65
66
67
68
69
70
71
72
# File 'lib/legion/extensions/llm/ollama/runners/discovery.rb', line 65

def derive_physical_id(instance_cfg:)
  base_url = instance_cfg[:base_url] || instance_cfg[:endpoint]
  unless base_url.is_a?(String) && !base_url.strip.empty?
    raise ArgumentError, "ollama instance has no endpoint: #{base_url.inspect}"
  end

  extract_host_port(url: base_url)
end

#extract_host_port(url:) ⇒ Object



74
75
76
77
78
79
80
81
82
83
84
# File 'lib/legion/extensions/llm/ollama/runners/discovery.rb', line 74

def extract_host_port(url:)
  uri = URI.parse(url.to_s)
  host = uri.host
  raise ArgumentError, "ollama instance endpoint has no host: #{url.inspect}" if host.nil? || host.empty?

  "#{host}:#{uri.port}"
rescue URI::InvalidURIError => e
  handle_exception(e, level: :warn, handled: true, operation: 'ollama.runner.discovery.extract_host_port',
                      url: url.to_s)
  raise
end

#fetch_raw_models(instance_cfg:) ⇒ Object

/api/tags -> body (not /v1/models -> body).



44
45
46
47
48
49
50
51
52
53
54
55
56
# File 'lib/legion/extensions/llm/ollama/runners/discovery.rb', line 44

def fetch_raw_models(instance_cfg:)
  conn = build_connection(base_url: catalog_base_url(instance_cfg: instance_cfg),
                          instance_cfg: instance_cfg, timeout: 15, open_timeout: 5)
  response = conn.get('/api/tags')
  unless response.status.between?(
    200, 299
  )
    raise CatalogFetchFailure,
          "ollama /api/tags returned HTTP #{response.status}"
  end

  Array(Legion::JSON.load(response.body).fetch(:models, []))
end

#health_pathObject



36
# File 'lib/legion/extensions/llm/ollama/runners/discovery.rb', line 36

def health_path = '/api/tags'

#model_id_from(model_data) ⇒ Object

/api/tags lists models under :name, not :id.



39
40
41
# File 'lib/legion/extensions/llm/ollama/runners/discovery.rb', line 39

def model_id_from(model_data)
  (model_data[:name] || model_data['name']).to_s
end