Skip to content

Add OpenRouter provider support#51

Open
qwadratic wants to merge 1 commit intofarzaa:mainfrom
qwadratic:feature/openrouter-support
Open

Add OpenRouter provider support#51
qwadratic wants to merge 1 commit intofarzaa:mainfrom
qwadratic:feature/openrouter-support

Conversation

@qwadratic
Copy link
Copy Markdown

Summary

Adds an optional OpenRouter dropdown to the companion panel so users can route voice requests through OpenRouter (Sonnet, Opus, ChatGPT, Grok, Gemini, Qwen) instead of Claude direct. Default behavior is unchanged — OpenRouter is opt-in.

Changes

Cloudflare Worker (worker/src/index.ts)

  • New /openrouter-chat route that proxies to https://openrouter.ai/api/v1/chat/completions
  • New OPENROUTER_API_KEY in the Env interface

Swift app

  • New OpenRouterAPI.swift — OpenAI-compatible streaming client (parses choices[0].delta.content SSE events, uses image_url data URIs for vision)
  • CompanionManager: new selectedOpenRouterModel (persisted to UserDefaults), isUsingOpenRouter computed property, and analyzeImageStreamingWithActiveProvider() helper that routes to the right client
  • CompanionPanelView: new "OpenRouter" row with a dropdown menu (Off / Sonnet / Opus / ChatGPT / Grok / Gemini / Qwen). Selecting an OpenRouter model deselects the Claude direct buttons; selecting a Claude direct button clears OpenRouter.

Setup (required before this works)

Merging this PR requires a worker redeploy and a new secret:

cd worker
npx wrangler secret put OPENROUTER_API_KEY
npx wrangler deploy

Without the secret, selecting an OpenRouter model will error — but the default (Claude direct) keeps working, so the blast radius of "merged but not deployed" is low.

Design notes

  • OpenRouter is fully opt-in. Fresh installs still default to Claude Sonnet direct, same as before.
  • The OpenRouter selection is persisted in UserDefaults under selectedOpenRouterModel (separate key from selectedClaudeModel) so the two pickers don't clobber each other.
  • The model list (Sonnet, Opus, ChatGPT, Grok, Gemini, Qwen) is hardcoded in CompanionPanelView.openRouterModels. Easy to edit if you want different defaults.

Test plan

  • Build in Xcode, app launches without errors
  • Open the panel — both "Model" (Sonnet/Opus) and "OpenRouter" (dropdown) rows appear
  • Select an OpenRouter model, push-to-talk, verify response streams and TTS plays
  • Switch to a different OpenRouter model (e.g. Gemini), verify a distinctly different voice/style
  • Switch OpenRouter dropdown back to "Off", verify Claude direct still works
  • Xcode console shows 🌐 OpenRouter streaming request: when OpenRouter is active, and 🌐 Claude streaming request: when it's off

Adds an optional OpenRouter dropdown to the companion panel so users can
route voice requests through OpenRouter (Sonnet, Opus, ChatGPT, Grok,
Gemini, Qwen) instead of Claude direct. Default behavior is unchanged —
OpenRouter is opt-in.

- New /openrouter-chat route on the Cloudflare Worker proxy
- New OpenRouterAPI.swift client using OpenAI-compatible streaming format
- Provider-aware routing in CompanionManager
- OpenRouter model picker dropdown in CompanionPanelView

Requires OPENROUTER_API_KEY worker secret to be set and worker redeploy.
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