Module: Legion::Extensions::Llm::Capabilities

Defined in:
lib/legion/extensions/llm/capabilities.rb

Overview

Capability vocabulary normalization. Collapses aliases so provider-specific capability names (:function_calling from Gemini, :tool_use from Anthropic, :tools from OpenAI) compare as equal. Used on BOTH sides of request_lane capability filtering (lane declaration and router request payload) — without this, vocabulary differences silently mismatch and the router returns no lane.

Constant Summary collapse

CANONICAL =
%i[
  completion embedding streaming tools vision thinking structured_output
  moderation image audio_transcription audio_speech responses
].freeze
ALIASES =
{
  function_calling: :tools,
  tool_use: :tools,
  tool_calls: :tools,
  tool: :tools,
  functions: :tools,
  stream: :streaming,
  stream_chat: :streaming,
  responses_api: :responses,
  embeddings: :embedding,
  embed: :embedding,
  reasoning: :thinking,
  image_generation: :image,
  images: :image,
  audio_generation: :audio_speech,
  speech_generation: :audio_speech,
  transcription: :audio_transcription
}.freeze

Class Method Summary collapse

Class Method Details

.canonical(capability) ⇒ Object



62
63
64
65
# File 'lib/legion/extensions/llm/capabilities.rb', line 62

def canonical(capability)
  sym = capability.to_s.downcase.strip.tr('-', '_').to_sym
  ALIASES.fetch(sym, sym)
end

.include_all?(available, required) ⇒ Boolean

Returns:

  • (Boolean)


54
55
56
57
58
59
60
# File 'lib/legion/extensions/llm/capabilities.rb', line 54

def include_all?(available, required, **)
  required = normalize(required)
  return true if required.empty?

  normalized = normalize(available)
  required.all? { |cap| normalized.include?(cap) }
end

.merge(*sets) ⇒ Object



50
51
52
# File 'lib/legion/extensions/llm/capabilities.rb', line 50

def merge(*sets, **)
  sets.flat_map { |set| normalize(set) }.uniq.freeze
end

.normalize(caps) ⇒ Object

Normalize a capability list — collapse aliases, downcase, dedup.



39
40
41
42
43
44
45
46
47
48
# File 'lib/legion/extensions/llm/capabilities.rb', line 39

def normalize(caps, **)
  Array(caps).compact.each_with_object([]) do |cap, normalized|
    next unless cap.respond_to?(:to_s)

    sym = cap.to_s.downcase.strip.tr('-', '_').to_sym
    next if sym.to_s.empty?

    normalized << canonical(sym)
  end.uniq.freeze
end