draken 0.1.5 → 0.2.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.
- package/ACCEPTANCE.md +31 -0
- package/CHANGELOG.md +33 -0
- package/CONTRIBUTING.md +129 -0
- package/MEMORY.md +98 -0
- package/PERSONA.md +67 -0
- package/README.md +156 -78
- package/SETUP.md +111 -0
- package/SOURCES.md +75 -0
- package/TRAY.md +54 -0
- package/VOICE.md +118 -0
- package/dist/auth/middleware.d.ts +3 -1
- package/dist/auth/middleware.d.ts.map +1 -1
- package/dist/auth/middleware.js +20 -15
- package/dist/auth/middleware.js.map +1 -1
- package/dist/cli.js +77 -58
- package/dist/cli.js.map +1 -1
- package/dist/db/agent-migration.d.ts +7 -0
- package/dist/db/agent-migration.d.ts.map +1 -0
- package/dist/db/agent-migration.js +36 -0
- package/dist/db/agent-migration.js.map +1 -0
- package/dist/db/evidence.d.ts +37 -0
- package/dist/db/evidence.d.ts.map +1 -0
- package/dist/db/evidence.js +110 -0
- package/dist/db/evidence.js.map +1 -0
- package/dist/db/pointer-migration.d.ts +7 -0
- package/dist/db/pointer-migration.d.ts.map +1 -0
- package/dist/db/pointer-migration.js +117 -0
- package/dist/db/pointer-migration.js.map +1 -0
- package/dist/db/retained-text.d.ts +8 -0
- package/dist/db/retained-text.d.ts.map +1 -0
- package/dist/db/retained-text.js +36 -0
- package/dist/db/retained-text.js.map +1 -0
- package/dist/db/schema.d.ts +1 -5
- package/dist/db/schema.d.ts.map +1 -1
- package/dist/db/schema.js +200 -55
- package/dist/db/schema.js.map +1 -1
- package/dist/db/snapshot-pointers.d.ts +5 -0
- package/dist/db/snapshot-pointers.d.ts.map +1 -0
- package/dist/db/snapshot-pointers.js +174 -0
- package/dist/db/snapshot-pointers.js.map +1 -0
- package/dist/memory/automatic.d.ts +38 -0
- package/dist/memory/automatic.d.ts.map +1 -0
- package/dist/memory/automatic.js +155 -0
- package/dist/memory/automatic.js.map +1 -0
- package/dist/memory/context.d.ts +12 -0
- package/dist/memory/context.d.ts.map +1 -0
- package/dist/memory/context.js +59 -0
- package/dist/memory/context.js.map +1 -0
- package/dist/memory/embedding-pool.d.ts +28 -0
- package/dist/memory/embedding-pool.d.ts.map +1 -0
- package/dist/memory/embedding-pool.js +135 -0
- package/dist/memory/embedding-pool.js.map +1 -0
- package/dist/memory/embedding-worker.d.ts +2 -0
- package/dist/memory/embedding-worker.d.ts.map +1 -0
- package/dist/memory/embedding-worker.js +32 -0
- package/dist/memory/embedding-worker.js.map +1 -0
- package/dist/memory/index.d.ts +26 -0
- package/dist/memory/index.d.ts.map +1 -0
- package/dist/memory/index.js +283 -0
- package/dist/memory/index.js.map +1 -0
- package/dist/memory/model.d.ts +15 -0
- package/dist/memory/model.d.ts.map +1 -0
- package/dist/memory/model.js +152 -0
- package/dist/memory/model.js.map +1 -0
- package/dist/memory/service.d.ts +8 -0
- package/dist/memory/service.d.ts.map +1 -0
- package/dist/memory/service.js +217 -0
- package/dist/memory/service.js.map +1 -0
- package/dist/memory/sources.d.ts +15 -0
- package/dist/memory/sources.d.ts.map +1 -0
- package/dist/memory/sources.js +87 -0
- package/dist/memory/sources.js.map +1 -0
- package/dist/memory/stamps.d.ts +13 -0
- package/dist/memory/stamps.d.ts.map +1 -0
- package/dist/memory/stamps.js +101 -0
- package/dist/memory/stamps.js.map +1 -0
- package/dist/memory/storage.d.ts +5 -0
- package/dist/memory/storage.d.ts.map +1 -0
- package/dist/memory/storage.js +107 -0
- package/dist/memory/storage.js.map +1 -0
- package/dist/memory/types.d.ts +68 -0
- package/dist/memory/types.d.ts.map +1 -0
- package/dist/memory/types.js +8 -0
- package/dist/memory/types.js.map +1 -0
- package/dist/memory/worker.d.ts +2 -0
- package/dist/memory/worker.d.ts.map +1 -0
- package/dist/memory/worker.js +82 -0
- package/dist/memory/worker.js.map +1 -0
- package/dist/npm-cli.d.ts +4 -0
- package/dist/npm-cli.d.ts.map +1 -0
- package/dist/npm-cli.js +36 -0
- package/dist/npm-cli.js.map +1 -0
- package/dist/pi/runtime.d.ts +34 -0
- package/dist/pi/runtime.d.ts.map +1 -0
- package/dist/pi/runtime.js +210 -0
- package/dist/pi/runtime.js.map +1 -0
- package/dist/pi/setup.d.ts +5 -0
- package/dist/pi/setup.d.ts.map +1 -0
- package/dist/pi/setup.js +147 -0
- package/dist/pi/setup.js.map +1 -0
- package/dist/routes/auth.d.ts.map +1 -1
- package/dist/routes/auth.js +3 -1
- package/dist/routes/auth.js.map +1 -1
- package/dist/routes/live-voice.d.ts +3 -0
- package/dist/routes/live-voice.d.ts.map +1 -0
- package/dist/routes/live-voice.js +49 -0
- package/dist/routes/live-voice.js.map +1 -0
- package/dist/routes/{browse.d.ts → memory.d.ts} +1 -1
- package/dist/routes/memory.d.ts.map +1 -0
- package/dist/routes/memory.js +18 -0
- package/dist/routes/memory.js.map +1 -0
- package/dist/routes/{tasks.d.ts → sync.d.ts} +1 -1
- package/dist/routes/sync.d.ts.map +1 -0
- package/dist/routes/sync.js +127 -0
- package/dist/routes/sync.js.map +1 -0
- package/dist/routes/{projects.d.ts → voice.d.ts} +1 -1
- package/dist/routes/voice.d.ts.map +1 -0
- package/dist/routes/voice.js +35 -0
- package/dist/routes/voice.js.map +1 -0
- package/dist/server-state.d.ts +30 -0
- package/dist/server-state.d.ts.map +1 -0
- package/dist/server-state.js +113 -0
- package/dist/server-state.js.map +1 -0
- package/dist/server-status.d.ts +7 -0
- package/dist/server-status.d.ts.map +1 -0
- package/dist/server-status.js +34 -0
- package/dist/server-status.js.map +1 -0
- package/dist/server.d.ts +5 -1
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +148 -46
- package/dist/server.js.map +1 -1
- package/dist/sources/adapters.d.ts +15 -0
- package/dist/sources/adapters.d.ts.map +1 -0
- package/dist/sources/adapters.js +159 -0
- package/dist/sources/adapters.js.map +1 -0
- package/dist/sources/registry.d.ts +17 -0
- package/dist/sources/registry.d.ts.map +1 -0
- package/dist/sources/registry.js +56 -0
- package/dist/sources/registry.js.map +1 -0
- package/dist/sync/collector.d.ts +3 -0
- package/dist/sync/collector.d.ts.map +1 -0
- package/dist/sync/collector.js +284 -0
- package/dist/sync/collector.js.map +1 -0
- package/dist/sync/cost.d.ts +7 -0
- package/dist/sync/cost.d.ts.map +1 -0
- package/dist/sync/cost.js +31 -0
- package/dist/sync/cost.js.map +1 -0
- package/dist/sync/jsonl.d.ts +34 -0
- package/dist/sync/jsonl.d.ts.map +1 -0
- package/dist/sync/jsonl.js +161 -0
- package/dist/sync/jsonl.js.map +1 -0
- package/dist/sync/manager.d.ts +12 -0
- package/dist/sync/manager.d.ts.map +1 -0
- package/dist/sync/manager.js +211 -0
- package/dist/sync/manager.js.map +1 -0
- package/dist/sync/normalize.d.ts +22 -0
- package/dist/sync/normalize.d.ts.map +1 -0
- package/dist/sync/normalize.js +107 -0
- package/dist/sync/normalize.js.map +1 -0
- package/dist/sync/pi-output.d.ts +33 -0
- package/dist/sync/pi-output.d.ts.map +1 -0
- package/dist/sync/pi-output.js +186 -0
- package/dist/sync/pi-output.js.map +1 -0
- package/dist/sync/pi.d.ts +15 -0
- package/dist/sync/pi.d.ts.map +1 -0
- package/dist/sync/pi.js +149 -0
- package/dist/sync/pi.js.map +1 -0
- package/dist/sync/recap.d.ts +25 -0
- package/dist/sync/recap.d.ts.map +1 -0
- package/dist/sync/recap.js +118 -0
- package/dist/sync/recap.js.map +1 -0
- package/dist/sync/references.d.ts +10 -0
- package/dist/sync/references.d.ts.map +1 -0
- package/dist/sync/references.js +50 -0
- package/dist/sync/references.js.map +1 -0
- package/dist/sync/source-files.d.ts +16 -0
- package/dist/sync/source-files.d.ts.map +1 -0
- package/dist/sync/source-files.js +56 -0
- package/dist/sync/source-files.js.map +1 -0
- package/dist/sync/store.d.ts +36 -0
- package/dist/sync/store.d.ts.map +1 -0
- package/dist/sync/store.js +359 -0
- package/dist/sync/store.js.map +1 -0
- package/dist/sync/summary-budget.d.ts +19 -0
- package/dist/sync/summary-budget.d.ts.map +1 -0
- package/dist/sync/summary-budget.js +39 -0
- package/dist/sync/summary-budget.js.map +1 -0
- package/dist/sync/tree.d.ts +69 -0
- package/dist/sync/tree.d.ts.map +1 -0
- package/dist/sync/tree.js +599 -0
- package/dist/sync/tree.js.map +1 -0
- package/dist/tray/controller.d.ts +51 -0
- package/dist/tray/controller.d.ts.map +1 -0
- package/dist/tray/controller.js +178 -0
- package/dist/tray/controller.js.map +1 -0
- package/dist/tray/launcher.d.ts +3 -0
- package/dist/tray/launcher.d.ts.map +1 -0
- package/dist/tray/launcher.js +47 -0
- package/dist/tray/launcher.js.map +1 -0
- package/dist/tray/native.d.ts +12 -0
- package/dist/tray/native.d.ts.map +1 -0
- package/dist/tray/native.js +93 -0
- package/dist/tray/native.js.map +1 -0
- package/dist/tray/processes.d.ts +5 -0
- package/dist/tray/processes.d.ts.map +1 -0
- package/dist/tray/processes.js +99 -0
- package/dist/tray/processes.js.map +1 -0
- package/dist/tray/worker.d.ts +4 -0
- package/dist/tray/worker.d.ts.map +1 -0
- package/dist/tray/worker.js +150 -0
- package/dist/tray/worker.js.map +1 -0
- package/dist/types.d.ts +212 -20
- package/dist/types.d.ts.map +1 -1
- package/dist/voice/continuation.d.ts +25 -0
- package/dist/voice/continuation.d.ts.map +1 -0
- package/dist/voice/continuation.js +94 -0
- package/dist/voice/continuation.js.map +1 -0
- package/dist/voice/legacy-history.d.ts +5 -0
- package/dist/voice/legacy-history.d.ts.map +1 -0
- package/dist/voice/legacy-history.js +34 -0
- package/dist/voice/legacy-history.js.map +1 -0
- package/dist/voice/live-context.d.ts +14 -0
- package/dist/voice/live-context.d.ts.map +1 -0
- package/dist/voice/live-context.js +137 -0
- package/dist/voice/live-context.js.map +1 -0
- package/dist/voice/live.d.ts +37 -0
- package/dist/voice/live.d.ts.map +1 -0
- package/dist/voice/live.js +448 -0
- package/dist/voice/live.js.map +1 -0
- package/package.json +49 -16
- package/public/assets/index-CYz_kpAp.js +126 -0
- package/public/assets/index-DmRid5xE.css +1 -0
- package/public/assets/index-Ymd62i3g.js +40 -0
- package/public/assets/persona-C_m1CVKe.css +1 -0
- package/public/assets/persona-XbLvCqRT.js +1 -0
- package/public/assets/scene-CBV2oPhA.js +3854 -0
- package/public/index.html +6 -8
- package/public/persona/THREE-LICENSE.txt +21 -0
- package/public/persona/call-poster.webp +0 -0
- package/public/persona/reference.jpg +0 -0
- package/public/persona/sample.wav +0 -0
- package/public/persona.html +7 -0
- package/runtime/pi/package-lock.json +1549 -0
- package/runtime/pi/package.json +12 -0
- package/tests/fixtures/voice-question.wav +0 -0
- package/tray/assets/error.ico +0 -0
- package/tray/assets/error.png +0 -0
- package/tray/assets/running.ico +0 -0
- package/tray/assets/running.png +0 -0
- package/tray/assets/starting.ico +0 -0
- package/tray/assets/starting.png +0 -0
- package/tray/assets/stopped.ico +0 -0
- package/tray/assets/stopped.png +0 -0
- package/tray/assets/stopping.ico +0 -0
- package/tray/assets/stopping.png +0 -0
- package/tray/macos.js +72 -0
- package/tray/windows.ps1 +104 -0
- package/voice/realtime/README.md +84 -0
- package/voice/realtime/backend.mjs +81 -0
- package/voice/realtime/native.mjs +210 -0
- package/voice/realtime/peer.d.mts +15 -0
- package/voice/realtime/peer.mjs +116 -0
- package/voice/realtime/probe-browser.mjs +81 -0
- package/voice/realtime/probe-server.mjs +86 -0
- package/voice/realtime/probe.html +11 -0
- package/voice/realtime/probe.mjs +42 -0
- package/voice/realtime/rpc.mjs +118 -0
- package/voice/realtime/setup.mjs +32 -0
- package/voice/tls.mjs +49 -0
- package/dist/db/queries.d.ts +0 -16
- package/dist/db/queries.d.ts.map +0 -1
- package/dist/db/queries.js +0 -91
- package/dist/db/queries.js.map +0 -1
- package/dist/docker/dockerfile.d.ts +0 -50
- package/dist/docker/dockerfile.d.ts.map +0 -1
- package/dist/docker/dockerfile.js +0 -160
- package/dist/docker/dockerfile.js.map +0 -1
- package/dist/docker/manager.d.ts +0 -42
- package/dist/docker/manager.d.ts.map +0 -1
- package/dist/docker/manager.js +0 -421
- package/dist/docker/manager.js.map +0 -1
- package/dist/git/status.d.ts +0 -76
- package/dist/git/status.d.ts.map +0 -1
- package/dist/git/status.js +0 -332
- package/dist/git/status.js.map +0 -1
- package/dist/routes/browse.d.ts.map +0 -1
- package/dist/routes/browse.js +0 -49
- package/dist/routes/browse.js.map +0 -1
- package/dist/routes/git.d.ts +0 -9
- package/dist/routes/git.d.ts.map +0 -1
- package/dist/routes/git.js +0 -338
- package/dist/routes/git.js.map +0 -1
- package/dist/routes/projects.d.ts.map +0 -1
- package/dist/routes/projects.js +0 -220
- package/dist/routes/projects.js.map +0 -1
- package/dist/routes/tasks.d.ts.map +0 -1
- package/dist/routes/tasks.js +0 -313
- package/dist/routes/tasks.js.map +0 -1
- package/draken.dockerfile.template +0 -18
- package/public/assets/index-3ngsG5kF.css +0 -1
- package/public/assets/index-B3YSD0ee.js +0 -252
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const express_1 = require("express");
|
|
4
|
+
const schema_1 = require("../db/schema");
|
|
5
|
+
const runtime_1 = require("../pi/runtime");
|
|
6
|
+
const collector_1 = require("../sync/collector");
|
|
7
|
+
const store_1 = require("../sync/store");
|
|
8
|
+
const manager_1 = require("../sync/manager");
|
|
9
|
+
const automatic_1 = require("../memory/automatic");
|
|
10
|
+
const router = (0, express_1.Router)();
|
|
11
|
+
const route = (handler) => (req, res, next) => { Promise.resolve().then(() => handler(req, res)).catch(next); };
|
|
12
|
+
function id(req) {
|
|
13
|
+
const value = Number(req.params.id);
|
|
14
|
+
if (!Number.isSafeInteger(value) || value < 1)
|
|
15
|
+
throw new store_1.HttpError(400, 'Invalid sync ID');
|
|
16
|
+
return value;
|
|
17
|
+
}
|
|
18
|
+
function text(value, name, max = 4000) {
|
|
19
|
+
if (typeof value !== 'string' || value.length > max)
|
|
20
|
+
throw new store_1.HttpError(400, `${name} must be text of at most ${max} characters`);
|
|
21
|
+
return value.trim();
|
|
22
|
+
}
|
|
23
|
+
router.get('/setup', route(async (req, res) => {
|
|
24
|
+
if (Object.keys(req.query).some(key => key !== 'refresh') || (req.query.refresh !== undefined && req.query.refresh !== '1'))
|
|
25
|
+
throw new store_1.HttpError(400, 'Unknown setup status option');
|
|
26
|
+
res.json({ pi: await (0, runtime_1.piSetupStatus)(req.query.refresh === '1'), data_dir: (0, schema_1.getDataDir)() });
|
|
27
|
+
}));
|
|
28
|
+
router.get('/settings/auto-index', route((_req, res) => res.json((0, automatic_1.autoIndexSettings)())));
|
|
29
|
+
router.patch('/settings/auto-index', route((req, res) => {
|
|
30
|
+
if (!req.body || Array.isArray(req.body) || Object.keys(req.body).length !== 1 || !Object.hasOwn(req.body, 'enabled'))
|
|
31
|
+
throw new store_1.HttpError(400, 'Only enabled is accepted');
|
|
32
|
+
res.json((0, automatic_1.setAutoIndex)(req.body.enabled));
|
|
33
|
+
}));
|
|
34
|
+
router.use((req, _res, next) => { if (['POST', 'PATCH', 'DELETE'].includes(req.method))
|
|
35
|
+
(0, automatic_1.yieldBackgroundIndexing)(); next(); });
|
|
36
|
+
router.get('/home', route((req, res) => {
|
|
37
|
+
const before = req.query.before === undefined ? undefined : Number(req.query.before);
|
|
38
|
+
if (before !== undefined && (!Number.isSafeInteger(before) || before < 1))
|
|
39
|
+
throw new store_1.HttpError(400, 'Invalid history cursor');
|
|
40
|
+
res.json((0, store_1.homeOverview)(before));
|
|
41
|
+
}));
|
|
42
|
+
let starting = false;
|
|
43
|
+
router.post('/syncs/start-call', route(async (req, res) => {
|
|
44
|
+
const requestId = req.body?.request_id;
|
|
45
|
+
if (typeof requestId !== 'string' || !/^[a-f0-9]{8}-(?:[a-f0-9]{4}-){3}[a-f0-9]{12}$/.test(requestId))
|
|
46
|
+
throw new store_1.HttpError(400, 'A request ID is required');
|
|
47
|
+
// One scan/start operation at a time, including the async indexing interval.
|
|
48
|
+
if (starting)
|
|
49
|
+
throw new store_1.HttpError(409, 'A sync is already being prepared');
|
|
50
|
+
const prior = (0, schema_1.getDb)().prepare('SELECT sync_id FROM sync_presentations WHERE request_id=?').get(requestId);
|
|
51
|
+
if (prior) {
|
|
52
|
+
res.status(202).json({ sync: (0, store_1.getSync)(prior.sync_id), scan: { files: 0, added: 0, warnings: [] } });
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
if (store_1.busySyncs.size || store_1.activeVoiceSyncs.size)
|
|
56
|
+
throw new store_1.HttpError(409, 'End the active call or wait for preparation before starting another sync.');
|
|
57
|
+
starting = true;
|
|
58
|
+
try {
|
|
59
|
+
const setup = await (0, runtime_1.piSetupStatus)(true);
|
|
60
|
+
if (setup.state !== 'configured')
|
|
61
|
+
throw new store_1.HttpError(503, setup.message);
|
|
62
|
+
const scan = await (0, collector_1.scanSessions)(), sync = (0, store_1.startConversationSync)(requestId);
|
|
63
|
+
res.status(202).json({ sync: (0, manager_1.launchReply)(sync.id), scan });
|
|
64
|
+
}
|
|
65
|
+
finally {
|
|
66
|
+
starting = false;
|
|
67
|
+
}
|
|
68
|
+
}));
|
|
69
|
+
router.post('/syncs/:id/recap', route((req, res) => res.status(202).json((0, manager_1.launchRecap)(id(req)))));
|
|
70
|
+
router.get('/overview', route((_req, res) => res.json((0, store_1.overview)())));
|
|
71
|
+
router.patch('/agents/:agent', route((req, res) => {
|
|
72
|
+
if (!req.body || Array.isArray(req.body) || Object.keys(req.body).length !== 1 || typeof req.body.enabled !== 'boolean')
|
|
73
|
+
throw new store_1.HttpError(400, 'Only boolean enabled is accepted');
|
|
74
|
+
res.json((0, store_1.setAgentEnabled)(String(req.params.agent), req.body.enabled));
|
|
75
|
+
}));
|
|
76
|
+
router.post('/scan', route(async (_req, res) => res.json(await (0, collector_1.scanSessions)())));
|
|
77
|
+
router.patch('/sessions/:sessionId', route((req, res) => {
|
|
78
|
+
if (typeof req.body?.included !== 'boolean')
|
|
79
|
+
throw new store_1.HttpError(400, 'included must be a boolean');
|
|
80
|
+
(0, store_1.setIncluded)(String(req.params.sessionId), req.body.included);
|
|
81
|
+
res.json((0, store_1.overview)());
|
|
82
|
+
}));
|
|
83
|
+
router.post('/syncs', route(async (req, res) => {
|
|
84
|
+
const since = req.body?.history_since;
|
|
85
|
+
if (since !== undefined && since !== null && typeof since !== 'string')
|
|
86
|
+
throw new store_1.HttpError(400, 'history_since must be a date string or null');
|
|
87
|
+
const scan = await (0, collector_1.scanSessions)();
|
|
88
|
+
res.json({ sync: (0, store_1.startSync)(since), scan });
|
|
89
|
+
}));
|
|
90
|
+
router.get('/syncs/:id', route((req, res) => res.json((0, store_1.getSync)(id(req)))));
|
|
91
|
+
router.get('/syncs/:id/progress', route((req, res) => res.json((0, store_1.getProgress)(id(req)))));
|
|
92
|
+
router.get('/syncs/:id/tree/:key', route((req, res) => res.json((0, store_1.getTreeNode)(id(req), String(req.params.key)))));
|
|
93
|
+
router.post('/syncs/:id/expand', route(async (req, res) => {
|
|
94
|
+
const scan = await (0, collector_1.scanSessions)();
|
|
95
|
+
res.json({ sync: (0, store_1.expandSnapshot)(id(req)), scan });
|
|
96
|
+
}));
|
|
97
|
+
router.patch('/syncs/:id/models', route((req, res) => {
|
|
98
|
+
res.json((0, store_1.configureModels)(id(req), {
|
|
99
|
+
summary: text(req.body?.summary, 'Summary model', 200),
|
|
100
|
+
final: text(req.body?.final, 'Final model', 200),
|
|
101
|
+
max_invocations: req.body?.max_invocations,
|
|
102
|
+
}));
|
|
103
|
+
}));
|
|
104
|
+
router.post('/syncs/:id/cancel', route((req, res) => {
|
|
105
|
+
(0, manager_1.cancelReply)(id(req));
|
|
106
|
+
res.status(202).json((0, store_1.getProgress)(id(req)));
|
|
107
|
+
}));
|
|
108
|
+
router.patch('/syncs/:id/notes', route((req, res) => {
|
|
109
|
+
res.json((0, store_1.saveNotes)(id(req), text(req.body?.decisions, 'Decisions'), text(req.body?.carry_forward, 'Carry forward')));
|
|
110
|
+
}));
|
|
111
|
+
router.post('/syncs/:id/briefing', route((req, res) => {
|
|
112
|
+
res.status(202).json((0, manager_1.launchReply)(id(req)));
|
|
113
|
+
}));
|
|
114
|
+
router.post('/syncs/:id/messages', route((req, res) => {
|
|
115
|
+
const question = text(req.body?.message, 'Message');
|
|
116
|
+
if (!question)
|
|
117
|
+
throw new store_1.HttpError(400, 'Message cannot be empty');
|
|
118
|
+
if (Object.keys(req.body).some(key => key !== 'message'))
|
|
119
|
+
throw new store_1.HttpError(400, 'Unknown discussion option. Refresh the page.');
|
|
120
|
+
res.status(202).json((0, manager_1.launchReply)(id(req), question));
|
|
121
|
+
}));
|
|
122
|
+
router.post('/syncs/:id/complete', route((req, res) => {
|
|
123
|
+
res.json((0, store_1.completeSync)(id(req), text(req.body?.decisions, 'Decisions'), text(req.body?.carry_forward, 'Carry forward'), req.body?.reviewed === true));
|
|
124
|
+
}));
|
|
125
|
+
router.post('/syncs/:id/discard', route((req, res) => res.json((0, store_1.discardSync)(id(req)))));
|
|
126
|
+
exports.default = router;
|
|
127
|
+
//# sourceMappingURL=sync.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sync.js","sourceRoot":"","sources":["../../src/routes/sync.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"voice.d.ts","sourceRoot":"","sources":["../../src/routes/voice.ts"],"names":[],"mappings":"AAQA,QAAA,MAAM,MAAM,4CAAW,CAAC;AAsBxB,eAAe,MAAM,CAAC"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const express_1 = require("express");
|
|
7
|
+
const fs_1 = __importDefault(require("fs"));
|
|
8
|
+
const crypto_1 = require("crypto");
|
|
9
|
+
const store_1 = require("../sync/store");
|
|
10
|
+
const legacy_history_1 = require("../voice/legacy-history");
|
|
11
|
+
const live_1 = require("../voice/live");
|
|
12
|
+
const live_voice_1 = __importDefault(require("./live-voice"));
|
|
13
|
+
const router = (0, express_1.Router)();
|
|
14
|
+
const route = (handler) => (req, res, next) => { Promise.resolve().then(() => handler(req, res)).catch(next); };
|
|
15
|
+
router.use('/live', live_voice_1.default);
|
|
16
|
+
router.get('/status', route(async (_req, res) => res.json({
|
|
17
|
+
...await (0, live_1.liveStatus)(),
|
|
18
|
+
certificateAvailable: Boolean(process.env.DRAKEN_TLS_CA && fs_1.default.existsSync(process.env.DRAKEN_TLS_CA)),
|
|
19
|
+
})));
|
|
20
|
+
router.get('/certificate', route((_req, res) => {
|
|
21
|
+
if (!process.env.DRAKEN_TLS_CA)
|
|
22
|
+
throw new store_1.HttpError(404, 'No local certificate download is configured');
|
|
23
|
+
// Re-encode only the public certificate; never serve a key or an arbitrary source file.
|
|
24
|
+
const certificate = new crypto_1.X509Certificate(fs_1.default.readFileSync(process.env.DRAKEN_TLS_CA));
|
|
25
|
+
res.set({ 'Content-Type': 'application/x-x509-ca-cert', 'Content-Disposition': 'attachment; filename="draken-local-root.crt"', 'X-Content-Type-Options': 'nosniff' });
|
|
26
|
+
res.send(certificate.raw);
|
|
27
|
+
}));
|
|
28
|
+
router.get('/syncs/:syncId/history', route((req, res) => {
|
|
29
|
+
const syncId = Number(req.params.syncId);
|
|
30
|
+
if (!Number.isSafeInteger(syncId) || syncId < 1)
|
|
31
|
+
throw new store_1.HttpError(400, 'Invalid sync ID');
|
|
32
|
+
res.json([...(0, legacy_history_1.legacyCallHistory)(syncId), ...(0, live_1.liveHistory)(syncId)].sort((a, b) => b.started_at.localeCompare(a.started_at)).slice(0, 10));
|
|
33
|
+
}));
|
|
34
|
+
exports.default = router;
|
|
35
|
+
//# sourceMappingURL=voice.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"voice.js","sourceRoot":"","sources":["../../src/routes/voice.ts"],"names":[],"mappings":";;;;;AAAA,qCAAkE;AAClE,4CAAoB;AACpB,mCAAyC;AACzC,yCAA0C;AAC1C,4DAA4D;AAC5D,wCAAwD;AACxD,8DAAsC;AAEtC,MAAM,MAAM,GAAG,IAAA,gBAAM,GAAE,CAAC;AACxB,MAAM,KAAK,GAAG,CAAC,OAAoE,EAAE,EAAE,CACrF,CAAC,GAAY,EAAE,GAAa,EAAE,IAAkB,EAAE,EAAE,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;AAExH,MAAM,CAAC,GAAG,CAAC,OAAO,EAAE,oBAAU,CAAC,CAAC;AAChC,MAAM,CAAC,GAAG,CAAC,SAAS,EAAE,KAAK,CAAC,KAAK,EAAE,IAAI,EAAE,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC;IACxD,GAAG,MAAM,IAAA,iBAAU,GAAE;IACrB,oBAAoB,EAAE,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,aAAa,IAAI,YAAE,CAAC,UAAU,CAAC,OAAO,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC;CACrG,CAAC,CAAC,CAAC,CAAC;AACL,MAAM,CAAC,GAAG,CAAC,cAAc,EAAE,KAAK,CAAC,CAAC,IAAI,EAAE,GAAG,EAAE,EAAE;IAC7C,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,aAAa;QAAE,MAAM,IAAI,iBAAS,CAAC,GAAG,EAAE,6CAA6C,CAAC,CAAC;IACxG,wFAAwF;IACxF,MAAM,WAAW,GAAG,IAAI,wBAAe,CAAC,YAAE,CAAC,YAAY,CAAC,OAAO,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC,CAAC;IACpF,GAAG,CAAC,GAAG,CAAC,EAAE,cAAc,EAAE,4BAA4B,EAAE,qBAAqB,EAAE,8CAA8C,EAAE,wBAAwB,EAAE,SAAS,EAAE,CAAC,CAAC;IACtK,GAAG,CAAC,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;AAC5B,CAAC,CAAC,CAAC,CAAC;AACJ,MAAM,CAAC,GAAG,CAAC,wBAAwB,EAAE,KAAK,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE;IACtD,MAAM,MAAM,GAAG,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;IACzC,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,MAAM,GAAG,CAAC;QAAE,MAAM,IAAI,iBAAS,CAAC,GAAG,EAAE,iBAAiB,CAAC,CAAC;IAC7F,GAAG,CAAC,IAAI,CAAC,CAAC,GAAG,IAAA,kCAAiB,EAAC,MAAM,CAAC,EAAE,GAAG,IAAA,kBAAW,EAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,aAAa,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC;AACzI,CAAC,CAAC,CAAC,CAAC;AAEJ,kBAAe,MAAM,CAAC"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/** Last successful bind, not a claim that the process is still alive. Kept after
|
|
2
|
+
* shutdown so status can check the same address; a live instance match is required. */
|
|
3
|
+
export declare function rememberServer(instance: string, http: {
|
|
4
|
+
address: string;
|
|
5
|
+
port: number;
|
|
6
|
+
}, https?: {
|
|
7
|
+
address: string;
|
|
8
|
+
port: number;
|
|
9
|
+
}): {
|
|
10
|
+
url: string;
|
|
11
|
+
open: string;
|
|
12
|
+
instance: string;
|
|
13
|
+
};
|
|
14
|
+
/** Where a new server would bind with this process's environment, not saved state. */
|
|
15
|
+
export declare function configuredServerTarget(): {
|
|
16
|
+
url: string;
|
|
17
|
+
open: string;
|
|
18
|
+
instance: undefined;
|
|
19
|
+
};
|
|
20
|
+
export declare function recordedServerTarget(): {
|
|
21
|
+
url: string;
|
|
22
|
+
open: string;
|
|
23
|
+
instance: string;
|
|
24
|
+
} | undefined;
|
|
25
|
+
export declare function serverTarget(): {
|
|
26
|
+
url: string;
|
|
27
|
+
open: string;
|
|
28
|
+
instance: string | undefined;
|
|
29
|
+
};
|
|
30
|
+
//# sourceMappingURL=server-state.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server-state.d.ts","sourceRoot":"","sources":["../src/server-state.ts"],"names":[],"mappings":"AAqDA;uFACuF;AACvF,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,EAAE,KAAK,CAAC,EAAE;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE;;;;EAOlI;AAED,sFAAsF;AACtF,wBAAgB,sBAAsB;;;;EAKrC;AAED,wBAAgB,oBAAoB;;;;cAGnC;AAED,wBAAgB,YAAY;;;;EAa3B"}
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.rememberServer = rememberServer;
|
|
7
|
+
exports.configuredServerTarget = configuredServerTarget;
|
|
8
|
+
exports.recordedServerTarget = recordedServerTarget;
|
|
9
|
+
exports.serverTarget = serverTarget;
|
|
10
|
+
const fs_1 = __importDefault(require("fs"));
|
|
11
|
+
const path_1 = __importDefault(require("path"));
|
|
12
|
+
const net_1 = require("net");
|
|
13
|
+
const crypto_1 = require("crypto");
|
|
14
|
+
const schema_1 = require("./db/schema");
|
|
15
|
+
const stateFile = () => path_1.default.join((0, schema_1.getDataDir)(), 'server-state.json');
|
|
16
|
+
const idPattern = /^[a-f0-9]{8}-(?:[a-f0-9]{4}-){3}[a-f0-9]{12}$/;
|
|
17
|
+
function endpoint(host, port, secure = false) {
|
|
18
|
+
if (!Number.isInteger(port) || port < 1 || port > 65535)
|
|
19
|
+
throw new Error('Invalid status port');
|
|
20
|
+
const local = host === '0.0.0.0' ? '127.0.0.1' : host === '::' ? '::1' : host;
|
|
21
|
+
const address = local.includes(':') && !local.startsWith('[') ? `[${local}]` : local;
|
|
22
|
+
const value = new URL(`${secure ? 'https' : 'http'}://${address}:${port}`);
|
|
23
|
+
if (value.username || value.password || value.pathname !== '/' || value.search || value.hash)
|
|
24
|
+
throw new Error('Invalid status address');
|
|
25
|
+
return value.origin;
|
|
26
|
+
}
|
|
27
|
+
function readState() {
|
|
28
|
+
let fd;
|
|
29
|
+
try {
|
|
30
|
+
if (fs_1.default.lstatSync(stateFile()).isSymbolicLink())
|
|
31
|
+
throw new Error('Invalid server record');
|
|
32
|
+
fd = fs_1.default.openSync(stateFile(), fs_1.default.constants.O_RDONLY | (fs_1.default.constants.O_NOFOLLOW || 0));
|
|
33
|
+
const stat = fs_1.default.fstatSync(fd);
|
|
34
|
+
if (!stat.isFile() || stat.size > 4096)
|
|
35
|
+
throw new Error('Invalid server record');
|
|
36
|
+
const bytes = Buffer.alloc(4097), length = fs_1.default.readSync(fd, bytes, 0, bytes.length, 0);
|
|
37
|
+
if (length > 4096)
|
|
38
|
+
throw new Error('Invalid server record');
|
|
39
|
+
const value = JSON.parse(bytes.subarray(0, length).toString('utf8'));
|
|
40
|
+
if (value.version !== 1 || typeof value.instance !== 'string' || !idPattern.test(value.instance) || !Number.isSafeInteger(value.pid) || value.pid < 1
|
|
41
|
+
|| typeof value.started_at !== 'string' || !Number.isFinite(Date.parse(value.started_at)))
|
|
42
|
+
throw new Error('Invalid server record');
|
|
43
|
+
for (const [key, protocol] of [['http_url', 'http:'], ['https_url', 'https:']]) {
|
|
44
|
+
if (key === 'https_url' && value[key] === null)
|
|
45
|
+
continue;
|
|
46
|
+
if (typeof value[key] !== 'string' || value[key].length > 256)
|
|
47
|
+
throw new Error('Invalid server record');
|
|
48
|
+
const url = new URL(value[key]);
|
|
49
|
+
// Saved addresses come from the actual bound sockets, never arbitrary URLs
|
|
50
|
+
// or dashboard input. Explicit operator overrides may still use DNS names.
|
|
51
|
+
if (url.protocol !== protocol || url.port === '0' || !(0, net_1.isIP)(url.hostname.replace(/^\[|\]$/g, '')) || url.origin !== value[key])
|
|
52
|
+
throw new Error('Invalid server record');
|
|
53
|
+
}
|
|
54
|
+
return value;
|
|
55
|
+
}
|
|
56
|
+
catch (error) {
|
|
57
|
+
if (error.code === 'ENOENT')
|
|
58
|
+
return;
|
|
59
|
+
throw new Error('The saved server address is invalid. Check server-state.json in DRAKEN_DATA_DIR, or supply an explicit DRAKEN_HOST/DRAKEN_PORT override.');
|
|
60
|
+
}
|
|
61
|
+
finally {
|
|
62
|
+
if (fd !== undefined)
|
|
63
|
+
fs_1.default.closeSync(fd);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
/** Last successful bind, not a claim that the process is still alive. Kept after
|
|
67
|
+
* shutdown so status can check the same address; a live instance match is required. */
|
|
68
|
+
function rememberServer(instance, http, https) {
|
|
69
|
+
const state = { version: 1, instance, pid: process.pid, http_url: endpoint(http.address, http.port),
|
|
70
|
+
https_url: https ? endpoint(https.address, https.port, true) : null, started_at: new Date().toISOString() };
|
|
71
|
+
const temp = path_1.default.join((0, schema_1.getDataDir)(), `.server-state-${(0, crypto_1.randomUUID)()}.tmp`);
|
|
72
|
+
try {
|
|
73
|
+
fs_1.default.writeFileSync(temp, JSON.stringify(state) + '\n', { mode: 0o600, flag: 'wx' });
|
|
74
|
+
fs_1.default.renameSync(temp, stateFile());
|
|
75
|
+
}
|
|
76
|
+
finally {
|
|
77
|
+
fs_1.default.rmSync(temp, { force: true });
|
|
78
|
+
}
|
|
79
|
+
return { url: state.http_url, open: state.https_url || state.http_url, instance };
|
|
80
|
+
}
|
|
81
|
+
/** Where a new server would bind with this process's environment, not saved state. */
|
|
82
|
+
function configuredServerTarget() {
|
|
83
|
+
const host = process.env.DRAKEN_HOST || '127.0.0.1';
|
|
84
|
+
const url = endpoint(host, Number(process.env.DRAKEN_PORT || 40333));
|
|
85
|
+
return { url, open: process.env.DRAKEN_HTTPS_PORT && process.env.DRAKEN_HTTPS_PORT !== '0'
|
|
86
|
+
? endpoint(host, Number(process.env.DRAKEN_HTTPS_PORT), true) : url, instance: undefined };
|
|
87
|
+
}
|
|
88
|
+
function recordedServerTarget() {
|
|
89
|
+
const saved = readState();
|
|
90
|
+
return saved ? { url: saved.http_url, open: saved.https_url || saved.http_url, instance: saved.instance } : undefined;
|
|
91
|
+
}
|
|
92
|
+
function serverTarget() {
|
|
93
|
+
const explicit = Boolean(process.env.DRAKEN_HOST || process.env.DRAKEN_PORT);
|
|
94
|
+
let saved;
|
|
95
|
+
try {
|
|
96
|
+
saved = readState();
|
|
97
|
+
}
|
|
98
|
+
catch (error) {
|
|
99
|
+
if (!explicit)
|
|
100
|
+
throw error;
|
|
101
|
+
}
|
|
102
|
+
if (explicit) {
|
|
103
|
+
const last = saved && new URL(saved.http_url);
|
|
104
|
+
const host = process.env.DRAKEN_HOST || last?.hostname || '127.0.0.1';
|
|
105
|
+
const port = Number(process.env.DRAKEN_PORT || last?.port || (last ? '80' : '40333'));
|
|
106
|
+
const url = endpoint(host, port), same = url === saved?.http_url;
|
|
107
|
+
return { url, open: same ? saved.https_url || url : url, instance: same ? saved.instance : undefined };
|
|
108
|
+
}
|
|
109
|
+
if (saved)
|
|
110
|
+
return { url: saved.http_url, open: saved.https_url || saved.http_url, instance: saved.instance };
|
|
111
|
+
return { url: 'http://127.0.0.1:40333', open: 'http://127.0.0.1:40333', instance: undefined };
|
|
112
|
+
}
|
|
113
|
+
//# sourceMappingURL=server-state.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server-state.js","sourceRoot":"","sources":["../src/server-state.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { serverTarget } from './server-state';
|
|
2
|
+
export type ServerTarget = ReturnType<typeof serverTarget>;
|
|
3
|
+
/** Connectivity only. Never obtains credentials, follows redirects, or calls models. */
|
|
4
|
+
export declare function probeServer(target: ServerTarget): Promise<{
|
|
5
|
+
instance?: string;
|
|
6
|
+
}>;
|
|
7
|
+
//# sourceMappingURL=server-status.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server-status.d.ts","sourceRoot":"","sources":["../src/server-status.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAE9C,MAAM,MAAM,YAAY,GAAG,UAAU,CAAC,OAAO,YAAY,CAAC,CAAC;AAE3D,wFAAwF;AACxF,wBAAsB,WAAW,CAAC,MAAM,EAAE,YAAY,GAAG,OAAO,CAAC;IAAE,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,CAgBtF"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.probeServer = probeServer;
|
|
4
|
+
/** Connectivity only. Never obtains credentials, follows redirects, or calls models. */
|
|
5
|
+
async function probeServer(target) {
|
|
6
|
+
const response = await fetch(target.url + '/api/auth/status', { signal: AbortSignal.timeout(2500), redirect: 'error' });
|
|
7
|
+
if (!response.ok || !response.body) {
|
|
8
|
+
await response.body?.cancel();
|
|
9
|
+
throw new Error('Server did not respond as Draken');
|
|
10
|
+
}
|
|
11
|
+
const reader = response.body.getReader(), chunks = [];
|
|
12
|
+
let size = 0;
|
|
13
|
+
try {
|
|
14
|
+
for (;;) {
|
|
15
|
+
const part = await reader.read();
|
|
16
|
+
if (part.done)
|
|
17
|
+
break;
|
|
18
|
+
size += part.value.byteLength;
|
|
19
|
+
if (size > 8192)
|
|
20
|
+
throw new Error('Oversized server status');
|
|
21
|
+
chunks.push(part.value);
|
|
22
|
+
}
|
|
23
|
+
const identity = JSON.parse(Buffer.concat(chunks).toString('utf8'));
|
|
24
|
+
if (identity.application !== 'draken')
|
|
25
|
+
throw new Error('Server did not respond as Draken');
|
|
26
|
+
if (target.instance && identity.instance !== target.instance)
|
|
27
|
+
throw new Error('Different server instance');
|
|
28
|
+
return { instance: typeof identity.instance === 'string' ? identity.instance : undefined };
|
|
29
|
+
}
|
|
30
|
+
finally {
|
|
31
|
+
await reader.cancel().catch(() => { });
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
//# sourceMappingURL=server-status.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server-status.js","sourceRoot":"","sources":["../src/server-status.ts"],"names":[],"mappings":";;AAKA,kCAgBC;AAjBD,wFAAwF;AACjF,KAAK,UAAU,WAAW,CAAC,MAAoB;IACpD,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,MAAM,CAAC,GAAG,GAAG,kBAAkB,EAAE,EAAE,MAAM,EAAE,WAAW,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC,CAAC;IACxH,IAAI,CAAC,QAAQ,CAAC,EAAE,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC;QAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,CAAC;QAAC,MAAM,IAAI,KAAK,CAAC,kCAAkC,CAAC,CAAC;IAAC,CAAC;IAC3H,MAAM,MAAM,GAAG,QAAQ,CAAC,IAAI,CAAC,SAAS,EAAE,EAAE,MAAM,GAAiB,EAAE,CAAC;IAAC,IAAI,IAAI,GAAG,CAAC,CAAC;IAClF,IAAI,CAAC;QACH,SAAS,CAAC;YACR,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,IAAI,EAAE,CAAC;YAAC,IAAI,IAAI,CAAC,IAAI;gBAAE,MAAM;YACvD,IAAI,IAAI,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC;YAC9B,IAAI,IAAI,GAAG,IAAI;gBAAE,MAAM,IAAI,KAAK,CAAC,yBAAyB,CAAC,CAAC;YAC5D,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAC1B,CAAC;QACD,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC;QACpE,IAAI,QAAQ,CAAC,WAAW,KAAK,QAAQ;YAAE,MAAM,IAAI,KAAK,CAAC,kCAAkC,CAAC,CAAC;QAC3F,IAAI,MAAM,CAAC,QAAQ,IAAI,QAAQ,CAAC,QAAQ,KAAK,MAAM,CAAC,QAAQ;YAAE,MAAM,IAAI,KAAK,CAAC,2BAA2B,CAAC,CAAC;QAC3G,OAAO,EAAE,QAAQ,EAAE,OAAO,QAAQ,CAAC,QAAQ,KAAK,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC,SAAS,EAAE,CAAC;IAC7F,CAAC;YAAS,CAAC;QAAC,MAAM,MAAM,CAAC,MAAM,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;IAAC,CAAC;AACtD,CAAC"}
|
package/dist/server.d.ts
CHANGED
package/dist/server.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":""}
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAoBA,wBAAgB,SAAS,CAAC,OAAO,GAAE;IAAE,SAAS,CAAC,EAAE,MAAM,CAAC;IAAC,UAAU,CAAC,EAAE,MAAM,CAAA;CAAO,+CAkClF;AAED,wBAAgB,WAAW,CAAC,SAAS,UAAQ,GAAG,IAAI,CA8DnD"}
|
package/dist/server.js
CHANGED
|
@@ -3,58 +3,160 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.createApp = createApp;
|
|
7
|
+
exports.startServer = startServer;
|
|
6
8
|
const express_1 = __importDefault(require("express"));
|
|
7
9
|
const path_1 = __importDefault(require("path"));
|
|
10
|
+
const fs_1 = __importDefault(require("fs"));
|
|
11
|
+
const https_1 = __importDefault(require("https"));
|
|
12
|
+
const crypto_1 = require("crypto");
|
|
13
|
+
const server_state_1 = require("./server-state");
|
|
8
14
|
const schema_1 = require("./db/schema");
|
|
9
15
|
const middleware_1 = require("./auth/middleware");
|
|
10
|
-
const manager_1 = require("./docker/manager");
|
|
11
16
|
const auth_1 = __importDefault(require("./routes/auth"));
|
|
12
|
-
const
|
|
13
|
-
const
|
|
14
|
-
const
|
|
15
|
-
const
|
|
16
|
-
const
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
17
|
+
const sync_1 = __importDefault(require("./routes/sync"));
|
|
18
|
+
const memory_1 = __importDefault(require("./routes/memory"));
|
|
19
|
+
const service_1 = require("./memory/service");
|
|
20
|
+
const automatic_1 = require("./memory/automatic");
|
|
21
|
+
const voice_1 = __importDefault(require("./routes/voice"));
|
|
22
|
+
const legacy_history_1 = require("./voice/legacy-history");
|
|
23
|
+
const live_1 = require("./voice/live");
|
|
24
|
+
const store_1 = require("./sync/store");
|
|
25
|
+
const manager_1 = require("./sync/manager");
|
|
26
|
+
const runtime_1 = require("./pi/runtime");
|
|
27
|
+
function createApp(options = {}) {
|
|
28
|
+
const app = (0, express_1.default)();
|
|
29
|
+
app.locals.drakenInstance = options.instanceId;
|
|
30
|
+
const staticDir = options.staticDir || path_1.default.join(__dirname, '../public');
|
|
31
|
+
app.disable('x-powered-by');
|
|
32
|
+
app.use(express_1.default.json({ limit: '32kb' }));
|
|
33
|
+
app.use('/api', (req, res, next) => {
|
|
34
|
+
// This local application exposes private transcripts. No cross-origin API access.
|
|
35
|
+
if (req.headers.origin) {
|
|
36
|
+
try {
|
|
37
|
+
if (new URL(req.headers.origin).host !== req.headers.host)
|
|
38
|
+
return res.status(403).json({ error: 'Cross-origin requests are not allowed' });
|
|
39
|
+
}
|
|
40
|
+
catch {
|
|
41
|
+
return res.status(403).json({ error: 'Invalid origin' });
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
if (req.headers['sec-fetch-site'] === 'cross-site')
|
|
45
|
+
return res.status(403).json({ error: 'Cross-site requests are not allowed' });
|
|
46
|
+
if ((0, middleware_1.isNoAuthMode)()) {
|
|
47
|
+
const hostname = (req.headers.host || '').replace(/:\d+$/, '');
|
|
48
|
+
if (!['localhost', '127.0.0.1', '[::1]'].includes(hostname))
|
|
49
|
+
return res.status(403).json({ error: 'Local mode requires a loopback host' });
|
|
50
|
+
}
|
|
51
|
+
res.setHeader('Cache-Control', 'no-store');
|
|
52
|
+
next();
|
|
53
|
+
});
|
|
54
|
+
app.use('/api/auth', auth_1.default);
|
|
55
|
+
app.use('/api/voice', middleware_1.authMiddleware, voice_1.default);
|
|
56
|
+
app.use('/api/memory', middleware_1.authMiddleware, memory_1.default);
|
|
57
|
+
app.use('/api', middleware_1.authMiddleware, sync_1.default);
|
|
58
|
+
app.use('/api', (_req, res) => res.status(404).json({ error: 'API route not found' }));
|
|
59
|
+
app.use(express_1.default.static(staticDir));
|
|
60
|
+
app.get('*', (_req, res) => res.sendFile(path_1.default.join(staticDir, 'index.html')));
|
|
61
|
+
app.use((error, _req, res, _next) => {
|
|
62
|
+
const status = error instanceof store_1.HttpError ? error.status : error.status === 400 || error.status === 413 ? error.status : 500;
|
|
63
|
+
if (status === 500)
|
|
64
|
+
console.error('Draken request failed:', error.message);
|
|
65
|
+
res.status(status).json({ error: status === 500 ? 'Internal error. See the local server log.' : error.message });
|
|
66
|
+
});
|
|
67
|
+
return app;
|
|
68
|
+
}
|
|
69
|
+
function startServer(trayOwned = false) {
|
|
70
|
+
if (trayOwned && (!process.send || !process.connected))
|
|
71
|
+
throw new Error('The tray launcher disconnected. No server was started.');
|
|
20
72
|
(0, middleware_1.validateAuthConfig)();
|
|
21
|
-
|
|
22
|
-
|
|
73
|
+
(0, live_1.validateVoiceConfig)();
|
|
74
|
+
const host = process.env.DRAKEN_HOST || '127.0.0.1';
|
|
75
|
+
const port = Number(process.env.DRAKEN_PORT || 40333);
|
|
76
|
+
if (!Number.isInteger(port) || port < 1 || port > 65535)
|
|
77
|
+
throw new Error('DRAKEN_PORT must be between 1 and 65535');
|
|
78
|
+
if ((0, middleware_1.isNoAuthMode)() && !(0, middleware_1.isLoopbackHost)(host)) {
|
|
79
|
+
throw new Error('No-auth mode may only bind to loopback. Configure authentication before exposing Draken.');
|
|
80
|
+
}
|
|
81
|
+
const httpsPort = Number(process.env.DRAKEN_HTTPS_PORT || 0);
|
|
82
|
+
if (!Number.isInteger(httpsPort) || httpsPort < 0 || httpsPort > 65535 || (httpsPort !== 0 && httpsPort === port))
|
|
83
|
+
throw new Error('DRAKEN_HTTPS_PORT must be a different valid port');
|
|
84
|
+
const tls = httpsPort ? { cert: fs_1.default.readFileSync(process.env.DRAKEN_TLS_CERT || ''), key: fs_1.default.readFileSync(process.env.DRAKEN_TLS_KEY || '') } : null;
|
|
85
|
+
// Bind before recovery: a second launch on an occupied port must not mark the
|
|
86
|
+
// actual server's active runs/calls interrupted or mutate its database.
|
|
87
|
+
let ready = false, listening = 0, stopping = false;
|
|
88
|
+
const instanceId = (0, crypto_1.randomUUID)();
|
|
89
|
+
const app = (0, express_1.default)();
|
|
90
|
+
app.use((_req, res, next) => ready ? next() : res.status(503).json({ error: 'Draken is starting or stopping.' }));
|
|
91
|
+
app.use(createApp({ instanceId }));
|
|
92
|
+
const bound = () => {
|
|
93
|
+
if (++listening !== (tls ? 2 : 1) || stopping)
|
|
94
|
+
return;
|
|
95
|
+
try {
|
|
96
|
+
(0, schema_1.getDb)();
|
|
97
|
+
(0, store_1.recoverInterruptedRuns)();
|
|
98
|
+
(0, legacy_history_1.recoverLegacyCalls)();
|
|
99
|
+
(0, live_1.recoverLiveCalls)();
|
|
100
|
+
const httpAddress = server.address(), secureAddress = secureServer?.address();
|
|
101
|
+
if (!httpAddress || typeof httpAddress === 'string' || typeof secureAddress === 'string')
|
|
102
|
+
throw new Error('Cannot record the listening address');
|
|
103
|
+
const target = (0, server_state_1.rememberServer)(instanceId, httpAddress, secureAddress || undefined);
|
|
104
|
+
ready = true;
|
|
105
|
+
if (trayOwned)
|
|
106
|
+
process.send({ type: 'draken-ready', target }, error => { if (error)
|
|
107
|
+
shutdown(1); });
|
|
108
|
+
const display = host.includes(':') && !host.startsWith('[') ? `[${host}]` : host;
|
|
109
|
+
console.log(`Draken sync running at http://${display}:${port}`);
|
|
110
|
+
if (tls)
|
|
111
|
+
console.log(`Draken voice page: https://${display}:${httpsPort}`);
|
|
112
|
+
console.log((trayOwned ? 'Managed by Draken tray. Use its menu to stop the server; closing the browser does not.\n' : 'Keep this terminal open. Ctrl+C stops the server; closing the browser does not.\n') + 'First use / missing pi: draken setup → draken login (inside pi, type /login, then /quit).\nAlready have pi? Keep your configured installation; draken doctor checks summary setup.\nVoice: draken voice setup → draken voice login (separate ChatGPT sign-in).\nUse the same server user and environment for these commands. Select history in Settings → Agents & sessions, then Sync with Draken.\nCheck server connectivity with draken status. No startup login, model download, provider call or microphone capture is performed.');
|
|
113
|
+
(0, automatic_1.startBackgroundIndexing)();
|
|
114
|
+
}
|
|
115
|
+
catch (error) {
|
|
116
|
+
console.error(error instanceof Error ? error.message : 'Draken startup failed');
|
|
117
|
+
shutdown(1);
|
|
118
|
+
}
|
|
119
|
+
};
|
|
120
|
+
const secureServer = tls ? https_1.default.createServer(tls, app).listen(httpsPort, host, bound) : null;
|
|
121
|
+
const server = app.listen(port, host, bound);
|
|
122
|
+
const shutdown = (code = 0) => {
|
|
123
|
+
if (stopping)
|
|
124
|
+
return;
|
|
125
|
+
stopping = true;
|
|
126
|
+
ready = false;
|
|
127
|
+
const backgroundStopped = (0, automatic_1.stopBackgroundIndexing)();
|
|
128
|
+
(0, manager_1.stopManagerProcesses)();
|
|
129
|
+
(0, service_1.stopHistory)();
|
|
130
|
+
secureServer?.close();
|
|
131
|
+
const closed = new Promise(resolve => server.close(() => resolve()));
|
|
132
|
+
void Promise.all([closed, (0, live_1.stopLiveCalls)(), backgroundStopped, (0, runtime_1.stopPiChecks)()]).finally(() => { (0, schema_1.closeDb)(); process.exit(code); });
|
|
133
|
+
setTimeout(() => process.exit(code), 6500).unref();
|
|
134
|
+
};
|
|
135
|
+
const failed = (error) => {
|
|
136
|
+
console.error(error.code === 'EADDRINUSE' ? 'Draken could not bind: a configured port is already in use. Run draken status; do not start a second server.' : `Draken could not listen (${error.code || 'unknown error'}). Check the bind address, ports and server log.`);
|
|
137
|
+
shutdown(1);
|
|
138
|
+
};
|
|
139
|
+
server.once('error', failed);
|
|
140
|
+
secureServer?.once('error', failed);
|
|
141
|
+
if (trayOwned) {
|
|
142
|
+
// Only the owning child-process IPC channel can request this. There is no
|
|
143
|
+
// HTTP shutdown endpoint, PID-file kill, or Windows forced termination.
|
|
144
|
+
process.on('message', (message) => {
|
|
145
|
+
if (message?.type === 'draken-shutdown' && message.instance === instanceId)
|
|
146
|
+
shutdown();
|
|
147
|
+
});
|
|
148
|
+
process.once('disconnect', () => shutdown());
|
|
149
|
+
}
|
|
150
|
+
process.once('SIGINT', () => shutdown());
|
|
151
|
+
process.once('SIGTERM', () => shutdown());
|
|
23
152
|
}
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
153
|
+
if (require.main === module) {
|
|
154
|
+
try {
|
|
155
|
+
startServer();
|
|
156
|
+
}
|
|
157
|
+
catch (error) {
|
|
158
|
+
console.error(error instanceof Error ? error.message : error);
|
|
159
|
+
process.exitCode = 1;
|
|
160
|
+
}
|
|
27
161
|
}
|
|
28
|
-
const app = (0, express_1.default)();
|
|
29
|
-
// Middleware
|
|
30
|
-
app.use(express_1.default.json());
|
|
31
|
-
app.use(express_1.default.static(path_1.default.join(__dirname, '../public')));
|
|
32
|
-
// Auth routes (public - no auth required)
|
|
33
|
-
app.use('/api/auth', auth_1.default);
|
|
34
|
-
// Protected API Routes (auth required if configured)
|
|
35
|
-
app.use('/api/projects', middleware_1.authMiddleware, projects_1.default);
|
|
36
|
-
app.use('/api/tasks', middleware_1.authMiddleware, tasks_1.default);
|
|
37
|
-
app.use('/api/browse', middleware_1.authMiddleware, browse_1.default);
|
|
38
|
-
app.use('/api/git', middleware_1.authMiddleware, git_1.default);
|
|
39
|
-
// Client-side routing - serve index.html for all non-API routes
|
|
40
|
-
app.get('*', (req, res) => {
|
|
41
|
-
res.sendFile(path_1.default.join(__dirname, '../public/index.html'));
|
|
42
|
-
});
|
|
43
|
-
// Initialize database
|
|
44
|
-
(0, schema_1.getDb)();
|
|
45
|
-
// Graceful shutdown
|
|
46
|
-
process.on('SIGINT', () => {
|
|
47
|
-
console.log('\nShutting down...');
|
|
48
|
-
(0, schema_1.closeDb)();
|
|
49
|
-
process.exit(0);
|
|
50
|
-
});
|
|
51
|
-
process.on('SIGTERM', () => {
|
|
52
|
-
console.log('\nShutting down...');
|
|
53
|
-
(0, schema_1.closeDb)();
|
|
54
|
-
process.exit(0);
|
|
55
|
-
});
|
|
56
|
-
// Start server
|
|
57
|
-
app.listen(PORT, () => {
|
|
58
|
-
console.log(`Draken dashboard running at http://localhost:${PORT}`);
|
|
59
|
-
});
|
|
60
162
|
//# sourceMappingURL=server.js.map
|