From 1811418fd7a8ade1e870ada215699ffe5bd6fe18 Mon Sep 17 00:00:00 2001 From: Aurora Date: Fri, 5 Jun 2026 20:42:09 -0400 Subject: [PATCH] =?UTF-8?q?fix(workspace):=20add=20COOP+COEP=20(credential?= =?UTF-8?q?less)=20headers=20so=20embedded=20HermesWorld=20WebGL=20keeps?= =?UTF-8?q?=20SharedArrayBuffer=20multithreading=20=E2=80=94=20matches=20s?= =?UTF-8?q?tandalone=20web=20client=20latency/perf=20instead=20of=20droppi?= =?UTF-8?q?ng=20to=20single-threaded=20in=20the=20iframe?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- vite.config.ts | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/vite.config.ts b/vite.config.ts index 3b5c38de..8cd4c5c3 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -480,6 +480,19 @@ const config = defineConfig(({ mode, command }) => { ], }, server: { + // Cross-origin isolation so the embedded HermesWorld WebGL client keeps + // SharedArrayBuffer multithreading (matches the standalone web client at + // play.hermes-world.ai). Without these, the iframe silently drops to a + // single thread → render+physics+netcode contend on one thread → inflated + // ping / worse frame pacing even though network RTT is identical. + // COEP 'credentialless' enables isolation WITHOUT requiring CORP headers + // on every cross-origin asset (fonts/images); the web client already sends + // cross-origin-resource-policy: cross-origin so the iframe still embeds. + // Same-origin agent API (/ws-claude, /api/claude-proxy) is unaffected. + headers: { + 'Cross-Origin-Opener-Policy': 'same-origin', + 'Cross-Origin-Embedder-Policy': 'credentialless', + }, // Force IPv4 — 'localhost' resolves to ::1 (IPv6) on Windows, breaking connectivity host: '0.0.0.0', // Port precedence: @@ -575,6 +588,17 @@ const config = defineConfig(({ mode, command }) => { if (command !== 'serve') return }, configureServer(server) { + // Cross-origin isolation headers on EVERY response so the embedded + // HermesWorld WebGL client keeps SharedArrayBuffer multithreading + // (matches play.hermes-world.ai). Injected via middleware because the + // TanStack Start SSR handler owns the HTML response and overrides + // vite's server.headers. COEP 'credentialless' avoids requiring CORP + // on every cross-origin asset; same-origin agent API is unaffected. + server.middlewares.use((_req, res, next) => { + res.setHeader('Cross-Origin-Opener-Policy', 'same-origin') + res.setHeader('Cross-Origin-Embedder-Policy', 'credentialless') + next() + }) server.middlewares.use(async (req, res, next) => { const requestPath = req.url?.split('?')[0] if (req.method === 'GET' && requestPath === '/api/healthcheck') {