meldivo 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +161 -0
  3. package/THIRD_PARTY_NOTICES.md +59 -0
  4. package/bin/meldivo.mjs +514 -0
  5. package/dist/server/harnesses/claude.js +407 -0
  6. package/dist/server/harnesses/claude.js.map +1 -0
  7. package/dist/server/harnesses/index.js +27 -0
  8. package/dist/server/harnesses/index.js.map +1 -0
  9. package/dist/server/harnesses/opencode.js +391 -0
  10. package/dist/server/harnesses/opencode.js.map +1 -0
  11. package/dist/server/harnesses/pi.js +364 -0
  12. package/dist/server/harnesses/pi.js.map +1 -0
  13. package/dist/server/harnesses/types.js +2 -0
  14. package/dist/server/harnesses/types.js.map +1 -0
  15. package/dist/server/hub.js +126 -0
  16. package/dist/server/hub.js.map +1 -0
  17. package/dist/server/index.js +515 -0
  18. package/dist/server/index.js.map +1 -0
  19. package/dist/server/logger.js +98 -0
  20. package/dist/server/logger.js.map +1 -0
  21. package/dist/server/qr.js +16 -0
  22. package/dist/server/qr.js.map +1 -0
  23. package/dist/server/remote.js +166 -0
  24. package/dist/server/remote.js.map +1 -0
  25. package/dist/server/speech.js +323 -0
  26. package/dist/server/speech.js.map +1 -0
  27. package/dist/server/state.js +91 -0
  28. package/dist/server/state.js.map +1 -0
  29. package/dist/web/apple-touch-icon.png +0 -0
  30. package/dist/web/assets/_commonjsHelpers-CqkleIqs.js +1 -0
  31. package/dist/web/assets/browser-CujOq0-h.js +8 -0
  32. package/dist/web/assets/index-B1UGHGdh.css +1 -0
  33. package/dist/web/assets/index-CNq_igvY.js +43 -0
  34. package/dist/web/assets/index-CeWj4ejR.js +2948 -0
  35. package/dist/web/favicon-32.png +0 -0
  36. package/dist/web/index.html +15 -0
  37. package/dist/web/logo-192.png +0 -0
  38. package/dist/web/logo-512.png +0 -0
  39. package/dist/web/voice-assets/ort-wasm-simd-threaded.mjs +59 -0
  40. package/dist/web/voice-assets/ort-wasm-simd-threaded.wasm +0 -0
  41. package/dist/web/voice-assets/silero_vad_v5.onnx +0 -0
  42. package/dist/web/voice-assets/vad.worklet.bundle.min.js +1 -0
  43. package/package.json +78 -0
@@ -0,0 +1,515 @@
1
+ import { randomUUID, timingSafeEqual as secureCompare } from "node:crypto";
2
+ import { existsSync, readFileSync } from "node:fs";
3
+ import { createServer as createHttpsServer } from "node:https";
4
+ import { homedir, hostname } from "node:os";
5
+ import path from "node:path";
6
+ import { fileURLToPath, pathToFileURL } from "node:url";
7
+ import express from "express";
8
+ import { createAdapters, listAllSessions } from "./harnesses/index.js";
9
+ import { createLogger, requestLoggingMiddleware } from "./logger.js";
10
+ import { detectRemoteOptions, RemoteManager, remoteGuideUrl } from "./remote.js";
11
+ import { createSherpaEngine } from "./speech.js";
12
+ import { defaultStateDir, SessionStateStore } from "./state.js";
13
+ const VOICE_LEASE_TTL_MS = 15_000;
14
+ const SESSIONS_CACHE_MS = 3_000;
15
+ const SESSIONS_LIMIT = 50;
16
+ const HARNESS_ORDER = ["pi", "opencode", "claude"];
17
+ // Where a user-supplied TLS certificate for remote access lives.
18
+ function tlsDir() {
19
+ const base = process.env.XDG_CONFIG_HOME || path.join(homedir(), ".config");
20
+ return path.join(base, "meldivo", "tls");
21
+ }
22
+ // The lock that keeps only one browser tab recording at a time. It is a
23
+ // single process-wide slot rather than per-session state, since only one
24
+ // voice session is ever meant to be live from this machine.
25
+ class VoiceLease {
26
+ ttlMs;
27
+ active = null;
28
+ constructor(ttlMs) {
29
+ this.ttlMs = ttlMs;
30
+ }
31
+ claim() {
32
+ if (this.active && this.active.expiresAt > Date.now())
33
+ return null;
34
+ this.active = { token: randomUUID(), expiresAt: Date.now() + this.ttlMs };
35
+ return this.active;
36
+ }
37
+ renew(token) {
38
+ if (!token || !this.active || this.active.token !== token)
39
+ return null;
40
+ this.active = { ...this.active, expiresAt: Date.now() + this.ttlMs };
41
+ return this.active;
42
+ }
43
+ release(token) {
44
+ if (token && this.active?.token === token)
45
+ this.active = null;
46
+ }
47
+ }
48
+ export async function startServer(options) {
49
+ const host = options.host ?? "127.0.0.1";
50
+ const secret = options.secret;
51
+ const speech = options.speech ?? createSherpaEngine();
52
+ const webDir = options.webDir ?? fileURLToPath(new URL("../web", import.meta.url));
53
+ const stateDir = options.stateDir ?? defaultStateDir();
54
+ const logger = createLogger();
55
+ const adapters = options.adapters ?? createAdapters();
56
+ const adapterById = new Map(adapters.map((adapter) => [adapter.id, adapter]));
57
+ const stateStore = new SessionStateStore(stateDir);
58
+ const voiceLease = new VoiceLease(VOICE_LEASE_TTL_MS);
59
+ const activeTurns = new Map();
60
+ const homeDir = homedir();
61
+ const app = express();
62
+ let httpsServer;
63
+ let httpsActualPort;
64
+ let sessionsSnapshot;
65
+ app.use(requestLoggingMiddleware(logger));
66
+ app.use(express.json({ limit: "1mb" }));
67
+ app.get("/api/health", (_req, res) => {
68
+ res.json({ ok: true, speech: speech.status() });
69
+ });
70
+ // Every other /api route requires the bearer secret, compared timing-safe.
71
+ app.use("/api", (req, res, next) => {
72
+ const authorization = req.get("authorization");
73
+ const bearer = authorization?.match(/^Bearer\s+(.+)$/i)?.[1];
74
+ if (!bearer || !secureTokenEqual(secret, bearer))
75
+ return res.status(401).json({ error: "Meldivo secret is required" });
76
+ next();
77
+ });
78
+ async function enableHttps() {
79
+ if (httpsServer && httpsActualPort)
80
+ return httpsActualPort;
81
+ const certPath = path.join(tlsDir(), "cert.pem");
82
+ const keyPath = path.join(tlsDir(), "key.pem");
83
+ if (!existsSync(certPath) || !existsSync(keyPath)) {
84
+ throw new Error(`TLS certificate not found at ${certPath}`);
85
+ }
86
+ const cert = readFileSync(certPath);
87
+ const key = readFileSync(keyPath);
88
+ const server = createHttpsServer({ cert, key }, app);
89
+ await new Promise((resolve, reject) => {
90
+ server.listen(options.httpsPort ?? 4443, "0.0.0.0", () => resolve());
91
+ server.once("error", reject);
92
+ });
93
+ httpsServer = server;
94
+ httpsActualPort = server.address().port;
95
+ return httpsActualPort;
96
+ }
97
+ function disableHttps() {
98
+ if (!httpsServer)
99
+ return Promise.resolve();
100
+ const server = httpsServer;
101
+ httpsServer = undefined;
102
+ httpsActualPort = undefined;
103
+ return new Promise((resolve, reject) => {
104
+ server.close((error) => (error ? reject(error) : resolve()));
105
+ });
106
+ }
107
+ const remoteManager = new RemoteManager({
108
+ httpPort: 0, // patched to the real port once listen() resolves, below
109
+ enableHttps,
110
+ disableHttps,
111
+ buildUrl: (origin) => `${origin}/#token=${encodeURIComponent(secret)}`,
112
+ });
113
+ async function getSessionsSnapshot() {
114
+ if (sessionsSnapshot && Date.now() - sessionsSnapshot.at < SESSIONS_CACHE_MS)
115
+ return sessionsSnapshot;
116
+ const [sessions, availability, forkIds] = await Promise.all([
117
+ listAllSessions(adapters, SESSIONS_LIMIT),
118
+ Promise.all(adapters.map(async (adapter) => ({ id: adapter.id, label: adapter.label, available: await adapter.available() }))),
119
+ stateStore.allForkIds(),
120
+ ]);
121
+ // Voice forks are an implementation detail of continuing an open session;
122
+ // hide them from the list so they don't show up as extra sessions.
123
+ const visible = sessions.filter((session) => !forkIds.has(session.id));
124
+ sessionsSnapshot = { at: Date.now(), harnesses: availability, sessions: visible };
125
+ return sessionsSnapshot;
126
+ }
127
+ app.get("/api/sessions", async (_req, res) => {
128
+ const snapshot = await getSessionsSnapshot();
129
+ res.set("Cache-Control", "no-store").json({ machine: hostname(), harnesses: snapshot.harnesses, sessions: snapshot.sessions });
130
+ });
131
+ // Runs one candidate adapter for one turn, streaming its events to `res`.
132
+ // When `allowFallback` is set, events are buffered until the first delta;
133
+ // an error before any delta is swallowed and reported as "failed" so the
134
+ // caller can retry with the next harness instead. Once a delta (or a
135
+ // terminal event) has been seen, the outcome is final ("committed").
136
+ async function attempt(adapter, target, message, signal, res, opts = {}) {
137
+ const allowFallback = opts.allowFallback ?? false;
138
+ const buffered = [];
139
+ let sawDelta = false;
140
+ let sessionId;
141
+ // Persists the session/fork id (if any) *before* the terminal event
142
+ // reaches the client, so a caller's very next request — sent the
143
+ // instant it observes "done" — never races the bookkeeping that
144
+ // request depends on (e.g. the busy-lock for this key, or which
145
+ // session a fork continues).
146
+ const persist = async () => {
147
+ if (sessionId && opts.onSessionId)
148
+ await opts.onSessionId(sessionId);
149
+ };
150
+ const endWith = async (terminal) => {
151
+ await persist();
152
+ flush(res, buffered);
153
+ buffered.length = 0;
154
+ sendEvent(res, terminal);
155
+ if (!res.writableEnded)
156
+ res.end();
157
+ };
158
+ try {
159
+ for await (const event of adapter.send(target, message, signal)) {
160
+ if (event.type === "session")
161
+ sessionId = event.id;
162
+ if (event.type === "delta")
163
+ sawDelta = true;
164
+ if (allowFallback && !sawDelta) {
165
+ if (event.type === "error")
166
+ return "failed";
167
+ if (event.type === "done") {
168
+ await endWith(event);
169
+ return "committed";
170
+ }
171
+ buffered.push(event);
172
+ continue;
173
+ }
174
+ if (event.type === "error" || event.type === "done") {
175
+ await endWith(event);
176
+ return "committed";
177
+ }
178
+ if (buffered.length > 0) {
179
+ flush(res, buffered);
180
+ buffered.length = 0;
181
+ }
182
+ sendEvent(res, event);
183
+ }
184
+ // Defensive: the generator ended without an explicit done/error event.
185
+ await endWith({ type: "done" });
186
+ return "committed";
187
+ }
188
+ catch (error) {
189
+ if (allowFallback && !sawDelta)
190
+ return "failed";
191
+ await endWith({ type: "error", message: messageFor(error) });
192
+ return "committed";
193
+ }
194
+ }
195
+ async function runQuick(message, conversationId, signal, res) {
196
+ const conversation = conversationId ? await stateStore.getConversation(conversationId) : undefined;
197
+ if (conversation) {
198
+ const adapter = adapterById.get(conversation.harness);
199
+ if (adapter) {
200
+ await attempt(adapter, { id: conversation.id, cwd: homeDir, fork: false }, message, signal, res, {
201
+ onSessionId: (id) => (conversationId ? stateStore.setConversation(conversationId, { harness: adapter.id, id }) : undefined),
202
+ });
203
+ return;
204
+ }
205
+ }
206
+ const candidates = [];
207
+ for (const id of HARNESS_ORDER) {
208
+ const adapter = adapterById.get(id);
209
+ if (adapter && (await adapter.available()))
210
+ candidates.push(adapter);
211
+ }
212
+ if (candidates.length === 0) {
213
+ sendEvent(res, { type: "error", message: "No coding-agent CLI is available on this machine" });
214
+ res.end();
215
+ return;
216
+ }
217
+ for (let index = 0; index < candidates.length; index++) {
218
+ const adapter = candidates[index];
219
+ const isLast = index === candidates.length - 1;
220
+ const outcome = await attempt(adapter, { id: null, cwd: homeDir, fork: false }, message, signal, res, {
221
+ allowFallback: !isLast,
222
+ onSessionId: (id) => (conversationId ? stateStore.setConversation(conversationId, { harness: adapter.id, id }) : undefined),
223
+ });
224
+ if (outcome === "committed")
225
+ return;
226
+ const next = candidates[index + 1];
227
+ sendEvent(res, { type: "status", message: `${adapter.label} unavailable, using ${next.label}` });
228
+ }
229
+ }
230
+ async function runNew(harness, message, conversationId, signal, res) {
231
+ const adapter = adapterById.get(harness);
232
+ if (!adapter) {
233
+ sendEvent(res, { type: "error", message: `Unknown harness "${harness}"` });
234
+ res.end();
235
+ return;
236
+ }
237
+ let id = null;
238
+ if (conversationId) {
239
+ const conversation = await stateStore.getConversation(conversationId);
240
+ if (conversation && conversation.harness === harness)
241
+ id = conversation.id;
242
+ }
243
+ await attempt(adapter, { id, cwd: homeDir, fork: false }, message, signal, res, {
244
+ onSessionId: (sessionId) => (conversationId ? stateStore.setConversation(conversationId, { harness, id: sessionId }) : undefined),
245
+ });
246
+ }
247
+ async function findSession(harness, id) {
248
+ const snapshot = await getSessionsSnapshot();
249
+ const cached = snapshot.sessions.find((session) => session.harness === harness && session.id === id);
250
+ if (cached)
251
+ return cached;
252
+ const adapter = adapterById.get(harness);
253
+ if (!adapter)
254
+ return undefined;
255
+ const deeper = await adapter.listSessions(200).catch(() => []);
256
+ return deeper.find((session) => session.id === id);
257
+ }
258
+ async function runExisting(key, harness, id, message, signal, res) {
259
+ const adapter = adapterById.get(harness);
260
+ if (!adapter) {
261
+ sendEvent(res, { type: "error", message: `Unknown harness "${harness}"` });
262
+ res.end();
263
+ return;
264
+ }
265
+ const info = await findSession(harness, id);
266
+ if (!info) {
267
+ sendEvent(res, { type: "error", message: "Session not found" });
268
+ res.end();
269
+ return;
270
+ }
271
+ if (info.open) {
272
+ const forkId = await stateStore.getFork(key);
273
+ if (forkId) {
274
+ await attempt(adapter, { id: forkId, cwd: info.cwd, model: info.model, fork: false }, message, signal, res);
275
+ }
276
+ else {
277
+ await attempt(adapter, { id: info.id, cwd: info.cwd, model: info.model, fork: true }, message, signal, res, {
278
+ onSessionId: (newId) => stateStore.setFork(key, newId),
279
+ });
280
+ }
281
+ }
282
+ else {
283
+ await attempt(adapter, { id: info.id, cwd: info.cwd, model: info.model, fork: false }, message, signal, res);
284
+ }
285
+ }
286
+ app.post("/api/sessions/:key/chat", async (req, res) => {
287
+ const key = req.params.key;
288
+ const message = readMessage(req.body?.message);
289
+ if (!message)
290
+ return res.status(400).json({ error: "message is required" });
291
+ if (activeTurns.has(key))
292
+ return res.status(409).json({ error: "This session is busy" });
293
+ const conversationId = readConversationId(req.body?.conversationId);
294
+ const controller = new AbortController();
295
+ activeTurns.set(key, controller);
296
+ req.on("aborted", () => controller.abort());
297
+ res.on("close", () => {
298
+ if (!res.writableEnded)
299
+ controller.abort();
300
+ });
301
+ res.status(200).set({
302
+ "Content-Type": "text/event-stream; charset=utf-8",
303
+ "Cache-Control": "no-cache, no-transform",
304
+ Connection: "keep-alive",
305
+ "X-Accel-Buffering": "no",
306
+ });
307
+ res.flushHeaders();
308
+ try {
309
+ if (key === "quick") {
310
+ await runQuick(message, conversationId, controller.signal, res);
311
+ }
312
+ else if (key.startsWith("new:")) {
313
+ await runNew(key.slice(4), message, conversationId, controller.signal, res);
314
+ }
315
+ else {
316
+ const sep = key.indexOf(":");
317
+ if (sep < 0) {
318
+ sendEvent(res, { type: "error", message: "Invalid session key" });
319
+ res.end();
320
+ }
321
+ else {
322
+ await runExisting(key, key.slice(0, sep), key.slice(sep + 1), message, controller.signal, res);
323
+ }
324
+ }
325
+ }
326
+ finally {
327
+ if (activeTurns.get(key) === controller)
328
+ activeTurns.delete(key);
329
+ }
330
+ });
331
+ app.post("/api/sessions/:key/cancel", (req, res) => {
332
+ const key = req.params.key;
333
+ const controller = activeTurns.get(key);
334
+ if (!controller)
335
+ return res.status(404).json({ error: "No active turn for this session" });
336
+ controller.abort();
337
+ res.status(204).end();
338
+ });
339
+ app.get("/api/remote", (_req, res) => {
340
+ res.set("Cache-Control", "no-store").json({ options: detectRemoteOptions(), active: remoteManager.status().active, guide: remoteGuideUrl });
341
+ });
342
+ app.post("/api/remote", async (req, res) => {
343
+ const id = readRemoteId(req.body?.id);
344
+ if (!id)
345
+ return res.status(400).json({ error: "id must be one of tailscale, cloudflare, certificate" });
346
+ try {
347
+ const result = await remoteManager.start(id);
348
+ res.status(200).json(result);
349
+ }
350
+ catch (error) {
351
+ res.status(502).json({ error: messageFor(error) });
352
+ }
353
+ });
354
+ app.delete("/api/remote", async (_req, res) => {
355
+ await remoteManager.stop();
356
+ res.status(204).end();
357
+ });
358
+ app.post("/api/voice/lease", (_req, res) => {
359
+ const lease = voiceLease.claim();
360
+ if (!lease)
361
+ return res.status(409).json({ error: "Another voice session is active." });
362
+ res.status(201).json(lease);
363
+ });
364
+ app.post("/api/voice/lease/heartbeat", (req, res) => {
365
+ const lease = voiceLease.renew(readLeaseToken(req.body?.token));
366
+ if (!lease)
367
+ return res.status(409).json({ error: "Voice session is no longer active." });
368
+ res.json(lease);
369
+ });
370
+ app.delete("/api/voice/lease", (req, res) => {
371
+ voiceLease.release(readLeaseToken(req.body?.token));
372
+ res.status(204).end();
373
+ });
374
+ app.post("/api/voice/transcribe", express.raw({ type: "audio/wav", limit: "16mb" }), async (req, res) => {
375
+ if (!Buffer.isBuffer(req.body) || req.body.length < 44 || req.body.toString("ascii", 0, 4) !== "RIFF") {
376
+ return res.status(400).json({ error: "A WAV recording is required" });
377
+ }
378
+ const controller = abortOnDisconnect(req, res);
379
+ try {
380
+ const text = await speech.transcribe(req.body, controller.signal);
381
+ res.json({ text: text.trim() });
382
+ }
383
+ catch (error) {
384
+ if (!controller.signal.aborted && !res.destroyed)
385
+ res.status(502).json({ error: messageFor(error) });
386
+ }
387
+ });
388
+ app.get("/api/voice/voices", (_req, res) => {
389
+ res.set("Cache-Control", "no-store").json({ current: speech.defaultVoice, voices: speech.voices() });
390
+ });
391
+ app.post("/api/voice/speech", async (req, res) => {
392
+ const text = readSpeechText(req.body?.text);
393
+ if (!text)
394
+ return res.status(400).json({ error: "text must contain 1–1200 characters" });
395
+ const requestedVoice = req.body?.voice === undefined ? undefined : readVoice(req.body.voice);
396
+ if (req.body?.voice !== undefined && !requestedVoice)
397
+ return res.status(400).json({ error: "voice must be a valid provider voice ID" });
398
+ const controller = abortOnDisconnect(req, res);
399
+ try {
400
+ const wav = await speech.synthesize(text, requestedVoice ?? speech.defaultVoice, controller.signal);
401
+ if (!controller.signal.aborted && !res.destroyed) {
402
+ res.status(200).set({ "Content-Type": "audio/wav", "Cache-Control": "no-store" }).send(wav);
403
+ }
404
+ }
405
+ catch (error) {
406
+ if (!controller.signal.aborted && !res.destroyed)
407
+ res.status(502).json({ error: messageFor(error) });
408
+ }
409
+ });
410
+ if (webDir && existsSync(webDir)) {
411
+ app.use(express.static(webDir));
412
+ app.get("/{*path}", (req, res, next) => {
413
+ if (req.path === "/api" || req.path.startsWith("/api/"))
414
+ return next();
415
+ res.sendFile(path.join(webDir, "index.html"));
416
+ });
417
+ }
418
+ app.use("/api", (_req, res) => res.status(404).json({ error: "Not found" }));
419
+ let httpServer;
420
+ await new Promise((resolve, reject) => {
421
+ httpServer = app.listen(options.port ?? 0, host, () => resolve());
422
+ httpServer.once("error", reject);
423
+ });
424
+ const actualPort = httpServer.address().port;
425
+ remoteManager.opts.httpPort = actualPort;
426
+ logger.info("server_started", { host, port: actualPort });
427
+ async function close() {
428
+ for (const controller of activeTurns.values())
429
+ controller.abort();
430
+ activeTurns.clear();
431
+ await Promise.all([
432
+ new Promise((resolve, reject) => {
433
+ httpServer.close((error) => (error ? reject(error) : resolve()));
434
+ }),
435
+ remoteManager.stop(),
436
+ disableHttps(),
437
+ ]);
438
+ }
439
+ return { port: actualPort, close };
440
+ }
441
+ function flush(res, events) {
442
+ for (const event of events)
443
+ sendEvent(res, event);
444
+ }
445
+ function secureTokenEqual(expected, candidate) {
446
+ const expectedBytes = Buffer.from(expected);
447
+ const candidateBytes = Buffer.from(candidate);
448
+ return expectedBytes.length === candidateBytes.length && secureCompare(expectedBytes, candidateBytes);
449
+ }
450
+ function readConversationId(value) {
451
+ return typeof value === "string" && /^[A-Za-z0-9_-]{1,100}$/.test(value) ? value : undefined;
452
+ }
453
+ function readMessage(value) {
454
+ if (typeof value !== "string")
455
+ return undefined;
456
+ const text = value.trim();
457
+ return text && text.length <= 12_000 ? text : undefined;
458
+ }
459
+ function readSpeechText(value) {
460
+ if (typeof value !== "string")
461
+ return undefined;
462
+ const text = value.trim();
463
+ return text && text.length <= 1_200 ? text : undefined;
464
+ }
465
+ function readVoice(value) {
466
+ if (typeof value !== "string")
467
+ return undefined;
468
+ const voice = value.trim();
469
+ return /^[A-Za-z0-9._-]{1,100}$/.test(voice) ? voice : undefined;
470
+ }
471
+ function readLeaseToken(value) {
472
+ return typeof value === "string" && value.length >= 16 && value.length <= 128 ? value : null;
473
+ }
474
+ function readRemoteId(value) {
475
+ return value === "tailscale" || value === "cloudflare" || value === "certificate" ? value : undefined;
476
+ }
477
+ function sendEvent(res, event) {
478
+ res.write(`data: ${JSON.stringify(event)}\n\n`);
479
+ }
480
+ function abortOnDisconnect(req, res) {
481
+ const controller = new AbortController();
482
+ req.on("aborted", () => controller.abort());
483
+ res.on("close", () => {
484
+ if (!res.writableEnded)
485
+ controller.abort();
486
+ });
487
+ return controller;
488
+ }
489
+ function messageFor(error) {
490
+ return error instanceof Error ? error.message : "Unexpected upstream error";
491
+ }
492
+ const isMainModule = process.argv[1] !== undefined && import.meta.url === pathToFileURL(process.argv[1]).href;
493
+ if (isMainModule) {
494
+ const secret = process.env.MELDIVO_SECRET;
495
+ if (!secret)
496
+ throw new Error("MELDIVO_SECRET is required");
497
+ const port = numberEnv("MELDIVO_PORT", 4100);
498
+ const httpsPort = numberEnv("MELDIVO_HTTPS_PORT", 4443);
499
+ const publicUrl = process.env.MELDIVO_PUBLIC_URL?.trim() || undefined;
500
+ const modelsDir = process.env.MELDIVO_MODELS_DIR?.trim() || undefined;
501
+ const speech = createSherpaEngine(modelsDir ? { modelsDir } : undefined);
502
+ void startServer({ port, host: "127.0.0.1", secret, publicUrl, speech, httpsPort });
503
+ // Download and load the voice models in the background so the first turn is fast.
504
+ speech.warmup?.().catch((error) => console.error("speech warmup failed:", error));
505
+ }
506
+ function numberEnv(name, fallback) {
507
+ const value = process.env[name];
508
+ if (value === undefined || value === "")
509
+ return fallback;
510
+ const parsed = Number(value);
511
+ if (!Number.isFinite(parsed))
512
+ throw new Error(`${name} must be a number`);
513
+ return parsed;
514
+ }
515
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../server/src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,98 @@
1
+ const levelWeight = { debug: 10, info: 20, warn: 30, error: 40 };
2
+ const knownApiPaths = new Set([
3
+ "/api/health",
4
+ "/api/rooms",
5
+ "/api/voice/lease",
6
+ "/api/voice/lease/heartbeat",
7
+ "/api/voice/transcribe",
8
+ "/api/voice/voices",
9
+ "/api/voice/speech",
10
+ "/api/chat",
11
+ ]);
12
+ const forbiddenField = /(?:api.?key|auth(?:orization)?|password|token|secret|body|content|message|text|transcript|audio)/i;
13
+ export function createLogger(configuredLevel = process.env.LOG_LEVEL) {
14
+ const minimumLevel = parseLevel(configuredLevel);
15
+ const write = (level, event, fields = {}) => {
16
+ if (levelWeight[level] < levelWeight[minimumLevel])
17
+ return;
18
+ const entry = {
19
+ timestamp: new Date().toISOString(),
20
+ level,
21
+ event,
22
+ ...safeFields(fields),
23
+ };
24
+ const line = JSON.stringify(entry);
25
+ if (level === "error")
26
+ console.error(line);
27
+ else
28
+ console.log(line);
29
+ };
30
+ return {
31
+ debug: (event, fields) => write("debug", event, fields),
32
+ info: (event, fields) => write("info", event, fields),
33
+ warn: (event, fields) => write("warn", event, fields),
34
+ error: (event, fields) => write("error", event, fields),
35
+ };
36
+ }
37
+ export function requestLoggingMiddleware(logger) {
38
+ return (req, res, next) => {
39
+ const startedAt = performance.now();
40
+ const requestId = crypto.randomUUID();
41
+ res.locals.requestId = requestId;
42
+ res.setHeader("X-Request-Id", requestId);
43
+ let finished = false;
44
+ res.once("finish", () => {
45
+ finished = true;
46
+ logger.info("http_request", {
47
+ request_id: requestId,
48
+ method: req.method,
49
+ path: safeRequestPath(req.path),
50
+ status: res.statusCode,
51
+ duration_ms: elapsedMs(startedAt),
52
+ });
53
+ });
54
+ res.once("close", () => {
55
+ if (finished)
56
+ return;
57
+ logger.warn("http_request_aborted", {
58
+ request_id: requestId,
59
+ method: req.method,
60
+ path: safeRequestPath(req.path),
61
+ duration_ms: elapsedMs(startedAt),
62
+ });
63
+ });
64
+ next();
65
+ };
66
+ }
67
+ export function requestId(res) {
68
+ return typeof res.locals.requestId === "string" ? res.locals.requestId : "unknown";
69
+ }
70
+ export function elapsedMs(startedAt) {
71
+ return Math.round((performance.now() - startedAt) * 10) / 10;
72
+ }
73
+ function parseLevel(value) {
74
+ const normalized = value?.trim().toLowerCase();
75
+ if (!normalized)
76
+ return "info";
77
+ if (normalized === "debug" || normalized === "info" || normalized === "warn" || normalized === "error")
78
+ return normalized;
79
+ console.warn(JSON.stringify({
80
+ timestamp: new Date().toISOString(),
81
+ level: "warn",
82
+ event: "invalid_log_level",
83
+ configured_level: "invalid",
84
+ default_level: "info",
85
+ }));
86
+ return "info";
87
+ }
88
+ function safeFields(fields) {
89
+ return Object.fromEntries(Object.entries(fields).filter(([name, value]) => value !== undefined && !forbiddenField.test(name)));
90
+ }
91
+ function safeRequestPath(path) {
92
+ if (knownApiPaths.has(path))
93
+ return path;
94
+ if (path.startsWith("/api/"))
95
+ return "/api/unknown";
96
+ return path === "/" ? "/" : "/web-asset";
97
+ }
98
+ //# sourceMappingURL=logger.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logger.js","sourceRoot":"","sources":["../../server/src/logger.ts"],"names":[],"mappings":"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"}