Module: Legion::Extensions::Llm::Openai::InstanceDiscovery

Extended by:
Logging::Helper
Defined in:
lib/legion/extensions/llm/openai/instance_discovery.rb

Overview

Candidate collection and normalization for Openai.discover_instances. Extracted from the Openai module to keep it within Metrics limits. The synthetic instances.default entry (placeholder env:// key nested under credentials) can surface here without a top-level api_key; dedup_and_log_candidates skips disabled and credential-less candidates so discover_instances only returns claimable instances.

Class Method Summary collapse

Class Method Details

.add_named_instance_candidates(candidates, settings_config) ⇒ Object



59
60
61
62
63
64
65
66
67
68
# File 'lib/legion/extensions/llm/openai/instance_discovery.rb', line 59

def add_named_instance_candidates(candidates, settings_config)
  settings_instances(settings_config).each do |name, config|
    next unless config.is_a?(Hash)

    normalized = normalize_instance_config(config)
    dedup_key = normalized[:openai_api_key]
    normalized[:api_key] = dedup_key if dedup_key
    candidates[name.to_sym] = normalized.merge(tier: :frontier)
  end
end

.add_settings_key_candidate(candidates, settings_config) ⇒ Object



48
49
50
51
52
53
54
55
56
57
# File 'lib/legion/extensions/llm/openai/instance_discovery.rb', line 48

def add_settings_key_candidate(candidates, settings_config)
  return unless settings_config.is_a?(Hash) && !settings_config.empty?

  settings_key = settings_config[:api_key] || settings_config['api_key']
  return unless settings_key

  candidates[:settings] = normalize_instance_config(settings_config).merge(
    api_key: settings_key, openai_api_key: settings_key, tier: :frontier
  )
end

.collect_codex_candidates(candidates) ⇒ Object



33
34
35
36
37
38
39
40
# File 'lib/legion/extensions/llm/openai/instance_discovery.rb', line 33

def collect_codex_candidates(candidates)
  codex_tok = CredentialSources.codex_token
  candidates[:codex] = { api_key: codex_tok, openai_api_key: codex_tok, tier: :frontier } if codex_tok
  codex_key = CredentialSources.codex_openai_key
  candidates[:codex_key] = { api_key: codex_key, openai_api_key: codex_key, tier: :frontier } if codex_key
  claude_key = CredentialSources.claude_config_value(:openaiApiKey)
  candidates[:claude] = { api_key: claude_key, openai_api_key: claude_key, tier: :frontier } if claude_key
end

.collect_env_key_candidates(candidates) ⇒ Object



26
27
28
29
30
31
# File 'lib/legion/extensions/llm/openai/instance_discovery.rb', line 26

def collect_env_key_candidates(candidates)
  env_key = CredentialSources.env('OPENAI_API_KEY')
  candidates[:env] = { api_key: env_key, openai_api_key: env_key, tier: :frontier } if env_key
  codex_env = CredentialSources.env('CODEX_API_KEY')
  candidates[:codex_env] = { api_key: codex_env, openai_api_key: codex_env, tier: :frontier } if codex_env
end

.collect_settings_candidates(candidates) ⇒ Object



42
43
44
45
46
# File 'lib/legion/extensions/llm/openai/instance_discovery.rb', line 42

def collect_settings_candidates(candidates)
  settings_config = CredentialSources.setting(:extensions, :llm, :openai)
  add_settings_key_candidate(candidates, settings_config)
  add_named_instance_candidates(candidates, settings_config)
end

.dedup_and_log_candidates(candidates) ⇒ Object



70
71
72
73
74
75
76
77
# File 'lib/legion/extensions/llm/openai/instance_discovery.rb', line 70

def dedup_and_log_candidates(candidates)
  deduped = CredentialSources.dedup_credentials(candidates)
  discovered = deduped.reject { |_, config| config[:enabled] == false || unresolved_credential?(config) }
                      .transform_values { |cfg| sanitize_instance_config(cfg) }
  instance_names = discovered.keys.sort_by(&:to_s).join(', ')
  log.debug { "Discovered #{discovered.size} OpenAI provider instance candidate(s): #{instance_names}" }
  discovered
end

.discoverObject



18
19
20
21
22
23
24
# File 'lib/legion/extensions/llm/openai/instance_discovery.rb', line 18

def discover
  candidates = {}
  collect_env_key_candidates(candidates)
  collect_codex_candidates(candidates)
  collect_settings_candidates(candidates)
  dedup_and_log_candidates(candidates)
end

.normalize_instance_config(config) ⇒ Object



97
98
99
100
101
# File 'lib/legion/extensions/llm/openai/instance_discovery.rb', line 97

def normalize_instance_config(config)
  normalized = config.to_h.transform_keys { |key| key.respond_to?(:to_sym) ? key.to_sym : key }
  normalize_openai_aliases(normalized)
  normalized.compact.except(:instances)
end

.normalize_openai_aliases(normalized) ⇒ Object



103
104
105
106
107
108
109
110
111
112
# File 'lib/legion/extensions/llm/openai/instance_discovery.rb', line 103

def normalize_openai_aliases(normalized)
  {
    openai_api_key: %i[api_key],
    openai_api_base: %i[base_url api_base endpoint],
    openai_organization_id: %i[organization_id],
    openai_project_id: %i[project_id]
  }.each do |target, sources|
    sources.each { |src| normalized[target] ||= normalized.delete(src) }
  end
end

.sanitize_instance_config(config) ⇒ Object



114
115
116
# File 'lib/legion/extensions/llm/openai/instance_discovery.rb', line 114

def sanitize_instance_config(config)
  config.except(:api_key, :organization_id, :project_id)
end

.settings_instances(config) ⇒ Object



90
91
92
93
94
95
# File 'lib/legion/extensions/llm/openai/instance_discovery.rb', line 90

def settings_instances(config)
  return {} unless config.is_a?(Hash)

  instances = config[:instances] || config['instances']
  instances.is_a?(Hash) ? instances : {}
end

.unresolved_credential?(config) ⇒ Boolean

enabled: false is a skip, not a credential: a disabled instance is never claimed (the discovery pipeline reads this method as the single claimable source). A nil credential or an unresolved env:// / vault:// placeholder (the synthetic provider_settings default nests env://OPENAI_API_KEY) cannot authenticate and is never claimed.

Returns:

  • (Boolean)


85
86
87
88
# File 'lib/legion/extensions/llm/openai/instance_discovery.rb', line 85

def unresolved_credential?(config)
  cred = config[:openai_api_key]
  cred.nil? || cred.to_s.match?(%r{\A(vault|env)://})
end