Skip to content

feat: add OpenRouter as alternative LLM provider - #7

Merged
TimInTech merged 2 commits into
mainfrom
feat/openrouter-llm-provider
Jun 17, 2026
Merged

feat: add OpenRouter as alternative LLM provider#7
TimInTech merged 2 commits into
mainfrom
feat/openrouter-llm-provider

Conversation

@TimInTech

Copy link
Copy Markdown
Owner

What changed?

Optionaler LLM-Provider neben OpenAI:

  • Provider-Auswahl OpenAI (Default) / OpenRouter / Eigener Endpunkt (OpenAI-kompatibel).
  • LLMService nimmt jetzt base_url + model entgegen; gpt-4o-mini ist nur noch Default.
  • Drei neue, nicht-geheime Config-Felder: llm_provider, llm_base_url (http(s)://-Pflicht, sonst leer), llm_model (Fallback gpt-4o-mini) mit Validierung.
  • Einstellungen (KI-Tab): Anbieter-Dropdown + base_url-/Modell-Felder, Auto-Prefill der OpenRouter-URL.
  • Beide LLMService-Bauorte (Init + Settings-Save) laufen über einen gemeinsamen Helfer BlitztextApp._build_llm_service() → keine Drift mehr.
  • Provider ist autoritativ: bei openai wird eine evtl. gespeicherte base_url ignoriert (OpenAI-Standardendpunkt). OpenRouter wird nur bei expliziter Auswahl genutzt.
  • .venv/ zu .gitignore ergänzt.

Why?

Ermöglicht das Routen der Umschreib-Workflows über OpenRouter (oder jeden anderen OpenAI-kompatiblen Endpunkt), ohne den Default zu ändern. OpenAI bleibt Standardpfad, OpenRouter ist rein optional. Kein Cloud-TTS in diesem PR.

How did you test it?

  • QT_QPA_PLATFORM=offscreen WHISPER_GUI_TESTS=1 python -m pytest -q203 passed.
  • Neue Tests: Config-Felder/Validierung, base_url/model-Weitergabe (openai via sys.modules injiziert → Tests laufen ohne echtes Paket), Settings-Persistenz + Provider-Prefill, Regressionstests für _build_llm_service (inkl. Provider-autoritativ bei openai).
  • Offscreen-Smoke des realen SettingsDialog: Provider-Wechsel füllt base_url, Speichern persistiert die Felder, config.json enthält keinen Key.
  • CI-Secret-Scan-Muster lokal: sauber.

AI assistance

Ja — umgesetzt mit Claude Code (TDD), read-only gegengeprüft von Codex (GPT-5.4) sowie den code-reviewer- und security-reviewer-Agents (ein Codex-Finding zur Provider-Autorität wurde behoben).

Checklist

  • I ran pytest tests/ (offscreen) — 203 passed.
  • I did not commit API keys, tokens, private recordings, or confidential transcripts.
  • I considered whether this changes privacy, security, or data flow — Secret-Modell unverändert (nur Env-Var-Name in config.json, Key aus secrets.env), base_url auf http(s):// validiert.
  • I kept the change focused on the Linux scope — kein TTS, kein Version-Bump, kein Tag/Release.

OpenRouter ist OpenAI-kompatibel: konfigurierbare base_url + Modell
werden in den bestehenden openai-Client gereicht. Neue, nicht-geheime
Config-Felder llm_provider/llm_base_url/llm_model mit Validierung
(Provider-Whitelist, http(s)://-Pflicht fuer base_url, Modell-Fallback).
Anbieter-Dropdown sowie base_url-/Modell-Felder im KI-Tab mit
Auto-Prefill fuer OpenRouter.

Beide LLMService-Konstruktionsorte (Init + Settings-Save) ueber
_build_llm_service() zusammengefuehrt, damit base_url/model nicht
auseinanderlaufen.

Secret-Modell unveraendert: nur Env-Var-Name in config.json, Key aus
secrets.env. Hotkey/Auto-Paste/Whisper unangetastet.
Codex-Finalreview-Finding: llm_provider wurde gespeichert, aber base_url
bedingungslos verwendet. Bei manuell editierter config.json (Provider
"openai" + gesetzte base_url) waere OpenRouter trotz OpenAI-Auswahl genutzt
worden.

_build_llm_service() ignoriert jetzt eine gespeicherte base_url, wenn der
Provider "openai" ist -> OpenAI-Standardendpunkt. OpenRouter/eigener
Endpunkt nutzen base_url nur bei expliziter Auswahl. Regressionstest
ergaenzt.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: ec724c9efa

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread app/blitztext_linux.py
Comment on lines +355 to +358
if provider == "openrouter":
if not self.edit_base_url.text().strip():
self.edit_base_url.setText("https://openrouter.ai/api/v1")
self.edit_base_url.setEnabled(True)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Avoid reusing the OpenAI key for OpenRouter

When a user with an existing OPENAI_API_KEY switches to OpenRouter, this branch only fills base_url; edit_api_key_env remains at the default unless the user notices and changes it manually. _build_llm_service() then resolves that OpenAI token and the SDK sends it as the Authorization header to openrouter.ai, so the common provider-switch path both fails and discloses the user's OpenAI key to the new provider. Please either switch/clear the env field for OpenRouter or block saving until a provider-appropriate key env is selected.

Useful? React with 👍 / 👎.

Comment thread app/blitztext_linux.py
autoritativ: bei "openai" wird eine evtl. gespeicherte base_url ignoriert,
damit der OpenAI-Standardendpunkt genutzt wird (OpenRouter nur bei Auswahl).
"""
base_url = "" if self.config.llm_provider == "openai" else self.config.llm_base_url

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Reject empty endpoints for non-OpenAI providers

For openrouter or custom, an empty llm_base_url can still reach this line because invalid URLs are normalized to "" and custom can be saved blank. Passing that through makes LLMService instantiate the OpenAI SDK with base_url=None, which routes the configured non-OpenAI flow (including the provider token and transcript) to the default OpenAI endpoint instead of failing fast. Please require a non-empty base URL whenever the selected provider is not openai.

Useful? React with 👍 / 👎.

@TimInTech
TimInTech merged commit c989d10 into main Jun 17, 2026
7 checks passed
@TimInTech
TimInTech deleted the feat/openrouter-llm-provider branch June 17, 2026 23:51
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.

1 participant