// 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 { join } from 'node:path'; import { handler } from './build/handler.js'; import { SqliteAnalyticsRecorder } from './build-server/server/core/analytics.js'; import { DEFAULT_SESSION_DEFAULTS } from './build-server/server/core/defaults.js'; import { OpenAiRealtimeProvider } from './build-server/server/core/providers/openai.js'; import { handleRealtimeUpgrade } from './build-server/server/core/ws-handler.js'; import { toolRegistry } from './build-server/server/project/tools/index.js'; const apiKey = process.env.OPENAI_API_KEY; if (!apiKey) { throw new Error('OPENAI_API_KEY is not set. See .env.example.'); } const provider = new OpenAiRealtimeProvider({ apiKey }); const dbPath = process.env.ANALYTICS_DB_PATH ?? join(process.cwd(), 'data', 'analytics.db'); const recorder = new SqliteAnalyticsRecorder(dbPath); // 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 tool registry. const defaults = { ...DEFAULT_SESSION_DEFAULTS, toolRegistry }; const server = createServer(handler); server.on('upgrade', (req, socket, head) => { handleRealtimeUpgrade(req, socket, head, { provider, defaults, recorder }); }); const port = process.env.PORT ? Number(process.env.PORT) : 3000; server.listen(port, () => { console.log(`listening on port ${port}`); });