From ed01ab8c8d907015382dd200633ae4e34f0a39dc Mon Sep 17 00:00:00 2001 From: Curryraj Date: Thu, 30 Jul 2026 03:04:41 +0800 Subject: [PATCH] fix: proxy WebSocket upgrades to the API in dev (#692) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The Vite dev proxy forwards `/v1` as plain HTTP with no `ws: true`, so the WebSocket upgrade for `/v1/agents/events` is never proxied. The socket does not open, does not error, and does not close — it just sits silent — so every live agent view is empty under `npm run dev` while working in a production build, where the frontend is served from the same origin as the API. That covers the per-agent live trace on the Agents page, which subscribes via `useAgentEvents` (`frontend/src/lib/useAgentEvents.ts`). The silence is what makes it costly: with no error to see, it reads as "no events are being emitted" rather than "the transport never connected", so the search starts on the server side. Verified on Windows 11 with `jarvis start` running: before, a `new WebSocket('ws://localhost:5173/v1/agents/events')` from the dev page never fired open, error or close within 6s. After, it opens, and a real agent tick delivers 8 events (agent_tick_start, inference_start/end, tool_call_start/end, agent_tick_end). `changeOrigin` is set alongside so the upgrade request carries the target's host, which some setups require when the API is not on localhost. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Claude Opus 5 --- frontend/vite.config.ts | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/frontend/vite.config.ts b/frontend/vite.config.ts index c196d2bc..f9974126 100644 --- a/frontend/vite.config.ts +++ b/frontend/vite.config.ts @@ -54,7 +54,15 @@ export default defineConfig({ server: { port: 5173, proxy: { - '/v1': process.env.VITE_API_URL || 'http://localhost:8000', + // ws: true is required for the /v1/agents/events WebSocket. Without it + // Vite proxies the HTTP request but not the upgrade, so the socket never + // opens — no error, no close event, just silence — and every live agent + // view sits empty in dev while working in a production build. + '/v1': { + target: process.env.VITE_API_URL || 'http://localhost:8000', + changeOrigin: true, + ws: true, + }, '/health': process.env.VITE_API_URL || 'http://localhost:8000', '/api': process.env.VITE_API_URL || 'http://localhost:8000', },