Class: LittleGhost::Providers::OpenRouter

Inherits:
OpenAICompatible show all
Defined in:
lib/little_ghost/providers/open_router.rb,
lib/little_ghost/providers/open_router/catalog_source.rb

Overview

OpenRouter gives one LittleGhost provider access to models routed through OpenRouter. Agents may select an OpenRouter target directly or keep a logical role while shared configuration selects its physical model.

provider = LittleGhost::Providers::OpenRouter.new(
api_key: ENV.fetch("OPENROUTER_API_KEY"),
model: ENV.fetch("OPENROUTER_MODEL"),
app_name: "Support Console"
)

site_url and app_name populate attribution headers. Capability metadata controls structured output, tools, tool choice, and parameter filtering. Requests that need a capability ask OpenRouter to route only to providers that advertise it.

Defined Under Namespace

Classes: CatalogSource

Constant Summary collapse

DEFAULT_BASE_URL =

The OpenRouter API endpoint used when base_url is omitted.

"https://openrouter.ai/api/v1/"
TOP_LEVEL_CACHE_MODELS =

:nodoc:

["anthropic/", "~anthropic/"].freeze
MESSAGE_CACHE_MODELS =
[
  "google/gemini",
  "qwen/qwen3-max",
  "qwen/qwen-plus",
  "qwen/qwen3.6-plus",
  "qwen/qwen3-coder-plus",
  "qwen/qwen3-coder-flash",
  "deepseek/deepseek-v3.2"
].freeze

Constants inherited from OpenAICompatible

LittleGhost::Providers::OpenAICompatible::CONTEXT_OVERFLOW_MARKERS, LittleGhost::Providers::OpenAICompatible::INITIAL_RETRY_DELAY, LittleGhost::Providers::OpenAICompatible::MAX_RETRY_DELAY, LittleGhost::Providers::OpenAICompatible::TRANSIENT_STREAM_ERROR_TYPES

Instance Attribute Summary

Attributes inherited from OpenAICompatible

#api, #model

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from OpenAICompatible

#stream

Methods inherited from Base

#stream

Constructor Details

#initialize(site_url: nil, app_name: nil, base_url: DEFAULT_BASE_URL, **arguments) ⇒ OpenRouter

Configures an OpenRouter client. All OpenAICompatible options, including api_key, model, retry limits, timeouts, and custom transport, apply.



41
42
43
44
45
# File 'lib/little_ghost/providers/open_router.rb', line 41

def initialize(site_url: nil, app_name: nil, base_url: DEFAULT_BASE_URL, **arguments)
  @site_url = site_url
  @app_name = app_name
  super(base_url:, api: :chat_completions, **arguments)
end

Class Method Details

.request_optionsObject

Adds OpenRouter attribution to the shared OpenAI-compatible policy.



24
# File 'lib/little_ghost/providers/open_router.rb', line 24

def self.request_options = (super + [:app_name]).freeze

Instance Method Details

#capabilities(metadata: {}) ⇒ Object

Reads model capabilities from OpenRouter supported_parameters metadata. Missing metadata produces ModelCapabilities.unknown.



49
50
51
52
53
54
55
56
57
58
59
60
# File 'lib/little_ghost/providers/open_router.rb', line 49

def capabilities(metadata: {})
  parameters = [:supported_parameters] || ["supported_parameters"]
  return ModelCapabilities.unknown unless parameters.is_a?(Array)

  values = parameters.map(&:to_s)
  ModelCapabilities.new(
    native_structured_output: values.any? { |value| %w[structured_outputs response_format].include?(value) },
    tools: values.include?("tools"),
    tool_choice: values.include?("tool_choice"),
    supported_parameters: values
  )
end

#prepare_request(request, capabilities:) ⇒ Object

Filters unsupported model settings when the request requires advertised capabilities.



64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
# File 'lib/little_ghost/providers/open_router.rb', line 64

def prepare_request(request, capabilities:)
  return request if request.required_capabilities.empty?
  return request unless capabilities.supported_parameters

  settings = filter_supported_settings(request.settings, capabilities)
  ModelRequest.new(
    messages: request.messages,
    tools: request.tools,
    settings:,
    output_schema: request.output_schema,
    tool_choice: request.tool_choice,
    required_capabilities: request.required_capabilities,
    cancellation_token: request.cancellation_token,
    deadline: request.deadline
  )
end