Skip to content

fix(desktop): send chat, model lists, and voice management through the Tauri HTTP plugin - #333

Merged
dyascj merged 2 commits into
mainfrom
fix/desktop-provider-http-plugin-v2
Nov 7, 2026
Merged

dyascj merged 2 commits into
mainfrom
fix/desktop-provider-http-plugin-v2

Conversation

@dyascj

@dyascj dyascj commented Nov 7, 2026 •

Copy link
Copy Markdown
Member

Fixes #311. Replaces #312, whose local-speech half already landed in #317.

What changed

On desktop, every direct provider call now goes through providerFetch (the Tauri HTTP plugin, which runs in Rust), so a provider's CORS policy no longer decides whether it works:

  • llm/transport.ts: direct chat streaming and completeJson
  • providers/client-models.ts: every model list plus the vision probes
  • tts/elevenlabs.ts, tts/omnivoice-client.ts (health, clone list, clone upload, synthesize, delete)
  • tts/fish-audio.ts reuses the helper instead of its own plugin import

Desktop requests also drop the Origin header (withoutOrigin, plugin unsafe-headers feature). The plugin stamped the webview origin on every request, and on Windows that is http://tauri.localhost, which a default Ollama install rejects with 403. Connection hints skip origin/CORS advice on desktop (browserOrigin() replaces three copies of getCurrentSiteOrigin). Docs: local-llm-setup.md and troubleshooting.md no longer tell desktop users to set OLLAMA_ORIGINS; SECURITY.md covers the plugin path and unsafe-headers; architecture.md names providerFetch.

Web is unchanged: providerFetch is the browser's fetch there.

Verification

pnpm test 1320/1320 (new: withoutOrigin, desktop hints without origin advice; both watched failing first). pnpm check clean.

A throwaway probe page (branch test/phttp-desktop-probe, not part of this PR) runs the real app functions inside the desktop webview against a mock provider with no CORS headers and 404 preflights, plus real providers.

macOS before/after (tauri dev): main fails 10 of 16 mock checks (model lists, streaming chat, Stop, in-stream errors, 401 body, completeJson, ElevenLabs, OmniVoice) and LM Studio; this branch passes 29/29:

  • mock: streaming arrives incrementally (5 updates over 1.0 s), Stop rejects with AbortError and the server sees the close after 0.4 s, real error messages, STT multipart, local TTS, OmniVoice clone upload, raw UTF-8 response header, public-host TLS
  • real DeepSeek (Flash): model list, streaming, Stop during reasoning, native tool call
  • real Ollama (qwen2.5:1.5b): model list, streaming, Stop, tool call
  • real LM Studio with CORS off (qwen2.5-1.5b-instruct): model list, streaming, Stop, tool call; main cannot reach it at all
  • the provider receives no Origin header

Windows (WebView2), Ubuntu 22.04 and 24.04 (WebKitGTK), CI debug builds: all 21 checks pass on each, including a real Ollama install. Windows Ollama with default settings fails on main and works here.

Small local models sometimes skip a tool call. Measured directly against Ollama with no app involved: qwen2.5:0.5b returns an empty answer in 35% (Ubuntu 22.04), 45% (24.04), 65% (Windows), 35% (macOS) of 20 calls; 1.5b in 25%. Main and this branch miss at the same rate over 20 app-level runs, so the probe allows up to 5 attempts.

Installers from a release dry run of this branch (run 42389528199):

  • Windows NSIS: silent install, launch, still running after 30 s, UI rendered with the avatar and onboarding
  • Ubuntu 22.04 and 24.04: .deb installed and AppImage run, both still running after 30 s
  • macOS universal .dmg (x86_64 + arm64): launched from the mounted image, still running after 25 s

Not covered with real keys: OpenAI, Anthropic, Google, Together, ElevenLabs, Fish Audio. They share the same code path as the DeepSeek and mock checks; the Anthropic request/response path was checked with an invalid key (real invalid x-api-key body comes back).

…e Tauri HTTP plugin

Finishes what #317 started: direct chat streaming and JSON calls, model
discovery and its vision probes, ElevenLabs, and OmniVoice voice
management now use providerFetch, so a provider's CORS policy no longer
decides whether it works on desktop. Fish Audio reuses the helper.
…Ollama works

The HTTP plugin stamps the webview origin on every request, and on
Windows that is http://tauri.localhost, which Ollama's default allowlist
rejects. providerFetch now sends an empty Origin, which the plugin drops
when its unsafe-headers feature is on. Connection hints skip origin and
CORS advice on desktop, and the docs no longer tell desktop users to set
OLLAMA_ORIGINS.
@dyascj
dyascj marked this pull request as ready for review November 7, 2026 16:25
@dyascj
dyascj merged commit 942ba8d into main Nov 7, 2026
7 checks passed
@dyascj
dyascj deleted the fix/desktop-provider-http-plugin-v2 branch November 7, 2026 16:25
@dyascj dyascj mentioned this pull request Nov 7, 2026
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.

Desktop: send provider requests through the Tauri HTTP plugin so CORS can't block them

1 participant