perplexed 0.3.1 Published

Perplexed 0.3.1 — Perplexity streaming restored after CORS enforcement change

Perplexity streaming broke when Perplexity's API stopped including the CORS headers that Electron's Chromium renderer requires. Every streaming query — modal and directory templates alike — was silently failing with a 200 OK response that Obsidian couldn't read. 0.3.1 routes all streaming through Node.js https instead of fetch, bypassing CORS enforcement entirely. Non-streaming requests were never affected.

Why care?

If you upgraded to Obsidian recently or noticed that Ask Perplexity and your directory templates silently stopped producing output — no streamed text, no error message in the note, just a CORS error in the developer console — this release fixes it.

Perplexity's API changed its CORS headers. Electron's Chromium renderer enforces CORS strictly: if a server's response doesn't include Access-Control-Allow-Origin for the calling origin, Chromium reads the response headers and then refuses to hand the body to the calling code. The request was completing successfully on Perplexity's end (200 OK), but the plugin received nothing because Chromium blocked access to the body.

Every streaming query was affected: the quick Ask Perplexity modal, the deep-research modal, and the directory-template batch runner (streamPerplexityToFile). Non-streaming requests (the toggle-off path) were never affected — they already used Obsidian's request() function, which routes through the main process and has no CORS constraint.

0.3.1 routes all streaming through Node.js's built-in https module. Node.js operates below the Chromium layer entirely — it's a direct OS socket connection. CORS is a browser concept; it doesn't exist at the socket level.

What changed?

Two files, minimal surface area:

src/services/perplexityService.ts — the modal query path. activeWindow.fetch replaced with https.request from node:https. The resulting Node.js IncomingMessage stream is wrapped in a Web ReadableStream<Uint8Array> and handed to the existing handleStreamingResponse method. The SSE parsing, idle-timeout, chunk accumulation, citations, and images handling are untouched.

src/services/directoryTemplateService.ts — the streamPerplexityToFile function. Same approach. The existing AbortController (used by the ceiling timer and user-cancel path) is threaded directly into https.request's signal option — abort behavior is fully preserved.

Before:  activeWindow.fetch → Chromium renderer → CORS enforcement → body blocked
After:   https.request → Node.js network stack → OS socket → no CORS

No changes to the Perplexity API payload, model list, streaming protocol, or any vault-side behavior. This is a pure transport-layer swap.

Upgrade notes

No action required. Reload the plugin after upgrading (Settings → Community Plugins → Perplexed → toggle off, then on) and streaming will work immediately. There are no vault-template changes, no new cft-block keys, no settings-pane changes.

If you are running Perplexed via a development symlink (ln -s from the repo into your vault's .obsidian/plugins/), run pnpm build from the perplexed/ directory and then reload the plugin.

Compatibility

minAppVersion: 1.8.10 — unchanged. Desktop-only — unchanged. No new external dependencies; the fix uses node:https from Node.js's standard library, which is already available in Obsidian's Electron runtime. All 0.3.0 features (three analyst-grade templates, per-template timeout and max-tokens overrides, rendering-discipline partials) are fully intact.

Engineering changelog