Skip to content

feat: definitive OpenRouter integration (v1.4 → v1.6)#11

Merged
sena-labs merged 1 commit into
mainfrom
claude/great-chaum-87f4fc
May 7, 2026
Merged

feat: definitive OpenRouter integration (v1.4 → v1.6)#11
sena-labs merged 1 commit into
mainfrom
claude/great-chaum-87f4fc

Conversation

@sena-labs
Copy link
Copy Markdown
Owner

Summary

Three-version arc that turns the pipe into a comprehensive OpenRouter client mapping the official Python/TypeScript SDK feature surface. Adds 24 new valves, two new helpers, server-side filtering, web search, deprecation handling, generation auditability, and cached-token cost breakdowns. One breaking change (FREE_ONLYFREE_MODEL_FILTER).

Type of Change

  • New feature (non-breaking change that adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to break)
  • Documentation update
  • Test improvement

Changes Made

v1.4.0 — Full catalog visibility

  • OUTPUT_MODALITIES valve — pass output_modalities=all to /models so TTS, audio, image-output, and embedding models surface in the selector (e.g. openai/gpt-4o-mini-tts-*, previously hidden by OpenRouter's text-only default)
  • Provider icon auto-discovery — lazy-load /api/frontend/all-providers and resolve icons for ~20 additional model authors (xAI, Inflection, NVIDIA, Arcee, Morph, Cerebras, …) with hyphen-strip slug normalisation
  • Recognise gstatic faviconV2 URLs in _is_owui_managed_icon

v1.5.0 — Routing capabilities

  • MODEL_VARIANTS — virtual :nitro/:exacto/:thinking/:online/:free/:extended routing that inherits base name & icon
  • Reasoning extrasminimal and xhigh effort levels, REASONING_SUMMARY_MODE (auto/concise/detailed)
  • Anthropic interleaved thinkinganthropic-beta: interleaved-thinking-2025-05-14 header for anthropic/* models
  • Anthropic prompt cache TTL — 5m or 1h
  • ZDR supportZDR_MODELS_ONLY (catalog filter via /endpoints/zdr) and ZDR_ENFORCE (provider.zdr=true)
  • TOOL_CALLING_FILTER trinary
  • HTTP_REFERER_OVERRIDE valve
  • Breaking: FREE_ONLY (bool) → FREE_MODEL_FILTER (all/only/exclude)

v1.6.0 — SDK feature parity

  • Web search plugin — five valves (ENABLE_WEB_SEARCH, WEB_SEARCH_MAX_RESULTS, WEB_SEARCH_PROMPT, WEB_SEARCH_INCLUDE_DOMAINS, WEB_SEARCH_EXCLUDE_DOMAINS); coexists with user-supplied plugins without duplication
  • MODEL_CATEGORY — server-side ?category= filter (programming, roleplay, marketing, science, …)
  • Deprecation handlingexpiration_date != null models tagged ⚠ {name} (deprecated); optional HIDE_DEPRECATED_MODELS
  • REASONING_MAX_TOKENS — hard cap (reasoning.max_tokens)
  • Provider preferences extrasPROVIDER_ONLY, PROVIDER_QUANTIZATIONS, PROVIDER_ALLOW_FALLBACKS, PROVIDER_MAX_PRICE_PROMPT, PROVIDER_MAX_PRICE_COMPLETION
  • SERVICE_TIER — auto/default/flex/priority/scale
  • SHOW_GENERATION_ID — captures id from stream and non-stream chat paths so users can call GET /api/v1/generation?id= for audits
  • Cached prompt-token cost breakdownprompt_tokens_details.cached_tokens / cache_read_input_tokens rendered in the SHOW_COST_INFO footer (Anthropic/OpenAI/Gemini caching)

Testing

  • All unit tests pass (python test_pipe.py551/551 ✓, was 431)
  • New tests added for the changes (+120 assertions)
  • Integration tests pass (python integration_test.py) — not run locally (requires real OPENROUTER_API_KEY); FREE_ONLY references migrated to FREE_MODEL_FILTER
  • CHANGELOG.md updated with v1.4.0, v1.5.0, v1.6.0 entries

Migration notes

Single breaking change: setups using FREE_ONLY=true must switch to FREE_MODEL_FILTER=only. FREE_ONLY=false (the default) needs no change. All other v1.4–v1.6 valves are backwards-compatible (defaults preserve prior behaviour) except OUTPUT_MODALITIES whose default all deliberately widens the catalog.

Out of scope (deferred)

  • /api/v1/responses endpoint (needs request/response/streaming rewrite)
  • Encrypted artifact storage / session-log archives / video-gen / image-gen pipeline / internal tool execution loops / circuit breaker / per-user valves — these belong in a thicker pipe than the manifold model

Checklist

  • My code follows the project's coding standards
  • I have added docstrings to new public methods
  • My changes do not introduce debug print statements beyond [OpenRouter Pipe] logging
  • No secrets, API keys, or credentials are included in this PR
  • My commit messages follow Conventional Commits

🤖 Generated with Claude Code

Three-version arc that turns the pipe into a comprehensive OpenRouter
client mapping the official Python/TypeScript SDK feature surface.

v1.4.0 — Full catalog visibility
- OUTPUT_MODALITIES valve: pass `output_modalities=all` to /models so TTS,
  audio, image-output, and embedding models surface in the selector
  (e.g. openai/gpt-4o-mini-tts-*, previously hidden)
- Provider icon auto-discovery: lazy-load /api/frontend/all-providers and
  resolve icons for ~20 additional model authors (xAI, Inflection,
  NVIDIA, Arcee, Morph, Cerebras, …) with hyphen-strip slug normalisation
- Recognise gstatic faviconV2 URLs in _is_owui_managed_icon

v1.5.0 — Routing capabilities (one breaking change)
- MODEL_VARIANTS: virtual :nitro/:exacto/:thinking/:online/:free/:extended
  routing that inherits base name & icon
- Reasoning extras: minimal & xhigh effort levels, REASONING_SUMMARY_MODE
  (auto/concise/detailed)
- Anthropic interleaved thinking (anthropic-beta header) and configurable
  prompt-cache TTL (5m/1h)
- ZDR support: ZDR_MODELS_ONLY (filter via /endpoints/zdr) and ZDR_ENFORCE
  (provider.zdr=true)
- TOOL_CALLING_FILTER trinary; FREE_ONLY → FREE_MODEL_FILTER
  (all/only/exclude) — BREAKING
- HTTP_REFERER_OVERRIDE valve

v1.6.0 — SDK feature parity
- Web search plugin (5 valves): enable + max_results + custom prompt +
  domain allow/deny lists; coexists with user-supplied plugins
- MODEL_CATEGORY: server-side ?category= filter
- Deprecation handling: ⚠ tag on expiration_date, optional hide
- REASONING_MAX_TOKENS budget cap
- Provider preferences extras: only / quantizations / allow_fallbacks /
  max_price.{prompt,completion}
- SERVICE_TIER hint (auto/default/flex/priority/scale)
- SHOW_GENERATION_ID: surfaces gen-IDs from stream and non-stream paths
  for /generation?id= audit lookups
- Cached prompt-token cost breakdown (Anthropic/OpenAI/Gemini caching)

Tests: 431 → 551 (+120 assertions covering each new code path).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings May 7, 2026 23:34
@sena-labs sena-labs merged commit 19d6abb into main May 7, 2026
6 checks passed
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR updates the OpenRouter manifold pipe from v1.3.0 to v1.6.0, expanding it into a more comprehensive OpenRouter client with broader catalog visibility, additional routing/filtering valves, web search support, and improved audit/cost reporting.

Changes:

  • Extends model catalog fetching/filtering (output modalities, category, free/tool/ZDR filters, deprecated model handling, model variants).
  • Adds request/payload features (web search plugin injection, service tier hinting, expanded reasoning configuration, ZDR enforcement, Anthropic interleaved-thinking + cache TTL).
  • Improves response metadata surfacing (generation ID footer, cached-token cost breakdown) and updates tests/docs accordingly.

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
openrouter_pipe.py Adds new valves/helpers and expands model listing, routing, headers, payload building, and response footers.
test_pipe.py Adds/updates unit tests for new valves and behaviors; migrates FREE_ONLY references to FREE_MODEL_FILTER.
integration_test.py Updates integration test to use FREE_MODEL_FILTER="only".
README.md Updates feature list and configuration documentation for new v1.4–v1.6 capabilities.
function.json Bumps manifest metadata (description/version) to 1.6.0.
CHANGELOG.md Adds entries for v1.4.0–v1.6.0 describing new features and breaking change.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread README.md
Comment on lines +58 to 62
- **Generation auditability** — optional generation ID footer maps each response to OpenRouter's `/generation?id=` activity API.
- **Cached-input savings** — surface cached vs. non-cached prompt tokens in the cost footer (Anthropic prompt caching, OpenAI implicit caching, Gemini context caching).
- **Deprecation visibility** — models with an `expiration_date` are tagged with ⚠ in the selector (or hidden via `HIDE_DEPRECATED_MODELS`).
- **Provider routing** — sort by `price`, `throughput`, or `latency`; prefer or exclude specific providers; enforce `require_parameters`.
- **Reasoning tokens** — `<think>` blocks streamed in real time with configurable effort (`low`, `medium`, `high`).
Comment thread README.md
- **Provider icons** — 13 provider logos synced directly into Open WebUI's model database.
- **Provider icons** — 13 hardcoded fast-path logos plus auto-discovered icons for ~20 more providers (xAI, Inflection, NVIDIA, Arcee, Morph, Cerebras, …) lazy-loaded from OpenRouter's provider registry, all synced directly into Open WebUI's model database.
- **Retry logic** — exponential backoff with jitter on timeout and connection errors.
- **FREE_ONLY mode** — filter to show only free-tier models (`:free` suffix or `0/0` pricing).
Comment thread test_pipe.py
Comment on lines 113 to 120
# Temporarily clear env vars that might interfere
_env_backup = {}
for k in [
"OPENROUTER_API_KEY", "OPENROUTER_BASE_URL",
"OPENROUTER_REASONING_EFFORT", "OPENROUTER_INCLUDE_REASONING",
"OPENROUTER_MODEL_PROVIDERS", "OPENROUTER_INVERT_PROVIDER_LIST",
"OPENROUTER_FREE_ONLY", "OPENROUTER_PROVIDER_SORT",
"OPENROUTER_FREE_MODEL_FILTER", "OPENROUTER_PROVIDER_SORT",
"OPENROUTER_PROVIDER_ORDER", "OPENROUTER_PROVIDER_IGNORE",
Comment thread test_pipe.py
Comment on lines 1017 to 1021
# 15b. FREE_ONLY filter
pipe.valves = Pipe.Valves(OPENROUTER_API_KEY="test-key", FREE_ONLY=True)
pipe.valves = Pipe.Valves(OPENROUTER_API_KEY="test-key", FREE_MODEL_FILTER="only")

# Mock data with pricing info: one :free suffix, one free-by-pricing, one paid
mock_models_pricing = {
Comment thread openrouter_pipe.py
Comment on lines +1294 to +1295
prefix_str = prefix or ""
# Strip the user-set prefix so we can reuse base names verbatim.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants