fix(workspace): add COOP+COEP (credentialless) headers so embedded HermesWorld WebGL keeps SharedArrayBuffer multithreading — matches standalone web client latency/perf instead of dropping to single-threaded in the iframe

This commit is contained in:
Aurora
2026-06-05 20:42:09 -04:00
parent 51fc76611e
commit 1811418fd7

View File

@@ -480,6 +480,19 @@ const config = defineConfig(({ mode, command }) => {
], ],
}, },
server: { 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 // Force IPv4 — 'localhost' resolves to ::1 (IPv6) on Windows, breaking connectivity
host: '0.0.0.0', host: '0.0.0.0',
// Port precedence: // Port precedence:
@@ -575,6 +588,17 @@ const config = defineConfig(({ mode, command }) => {
if (command !== 'serve') return if (command !== 'serve') return
}, },
configureServer(server) { 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) => { server.middlewares.use(async (req, res, next) => {
const requestPath = req.url?.split('?')[0] const requestPath = req.url?.split('?')[0]
if (req.method === 'GET' && requestPath === '/api/healthcheck') { if (req.method === 'GET' && requestPath === '/api/healthcheck') {