// Custom production server: wraps adapter-node's generated request handler in // a plain http.Server so we can also intercept WebSocket upgrade requests, // which SvelteKit itself has no hook for (see src/lib/server/core/ws-handler.ts). // // `.env` is not auto-loaded here (SvelteKit's own adapter-node doesn't in // production either) — run with `node --env-file=.env server.js` locally, or // provide OPENAI_API_KEY / REALTIME_TOKEN_SECRET via your deployment's real // secret mechanism. import { createServer } from 'node:http'; import { handler } from './build/handler.js'; import { NoopAnalyticsRecorder, SqliteAnalyticsRecorder } from './build-server/server/core/analytics.js'; import { loadConfig } from './build-server/server/core/config.js'; import { resolveSessionDefaults } from './build-server/server/core/defaults.js'; import { selectProvider } from './build-server/server/core/providers/index.js'; import { handleRealtimeUpgrade } from './build-server/server/core/ws-handler.js'; import { toolRegistry } from './build-server/server/project/tools/index.js'; import { SESSION_PERSONA } from './build-server/project/persona.js'; // Parses/validates every env var this app reads and throws one aggregate // error if anything required is missing or invalid — see docs/CONFIGURATION.md. const config = loadConfig(); const provider = selectProvider(config); const recorder = config.analytics.enabled ? new SqliteAnalyticsRecorder(config.analytics.dbPath, config.analytics) : new NoopAnalyticsRecorder(); // server/core never imports project code directly (see docs/TOOLS.md) — this // composition root is one of the two places (alongside vite.config.ts) that // merges core defaults with the project's persona and tool registry. const defaults = { ...resolveSessionDefaults(SESSION_PERSONA, config.session), toolRegistry }; const server = createServer(handler); server.on('upgrade', (req, socket, head) => { handleRealtimeUpgrade(req, socket, head, { provider, defaults, recorder, clientToolTimeoutMs: config.session.clientToolTimeoutMs, // This entrypoint only ever runs in production (see dev-plugin.ts for // the dev side) — debug-log forwarding here requires a valid // DEBUG_ACCESS_KEY on each connection. See docs/LOGGING.md. isDev: false, // Gates the `messages` category's console mirror only — browser // forwarding above is unaffected. See DEBUG_LOG_MESSAGES in // docs/CONFIGURATION.md. logMessages: config.debug.messages }); }); server.listen(config.port, () => { console.log(`listening on port ${config.port}`); });