@adhdev/daemon-standalone 0.7.5 → 0.7.7
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/dist/index.js +326 -1
- package/dist/index.js.map +1 -1
- package/package.json +7 -2
- package/public/assets/index-BNE24U2u.js +68 -0
- package/public/assets/index-Cc7KAykU.css +1 -0
- package/public/assets/terminal-SgUt8Azj.js +13 -0
- package/public/index.html +3 -4
- package/public/assets/index-Cz2_RMgm.js +0 -65
- package/public/assets/index-ffpzsBTq.css +0 -1
- package/public/assets/terminal-6GBZ9nXN.css +0 -32
- package/public/assets/terminal-Dm9LBRva.js +0 -49
package/dist/index.js
CHANGED
|
@@ -30,6 +30,102 @@ var path = __toESM(require("path"));
|
|
|
30
30
|
var fs = __toESM(require("fs"));
|
|
31
31
|
var os = __toESM(require("os"));
|
|
32
32
|
var import_daemon_core = require("@adhdev/daemon-core");
|
|
33
|
+
|
|
34
|
+
// src/session-host.ts
|
|
35
|
+
var import_child_process = require("child_process");
|
|
36
|
+
var import_session_host_core = require("@adhdev/session-host-core");
|
|
37
|
+
var STARTUP_TIMEOUT_MS = 8e3;
|
|
38
|
+
var STARTUP_POLL_MS = 200;
|
|
39
|
+
var SESSION_HOST_APP_NAME = process.env.ADHDEV_SESSION_HOST_NAME || "adhdev";
|
|
40
|
+
async function canConnect(endpoint) {
|
|
41
|
+
const client = new import_session_host_core.SessionHostClient({ endpoint });
|
|
42
|
+
try {
|
|
43
|
+
await client.connect();
|
|
44
|
+
await client.close();
|
|
45
|
+
return true;
|
|
46
|
+
} catch {
|
|
47
|
+
return false;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
async function waitForReady(endpoint, timeoutMs = STARTUP_TIMEOUT_MS) {
|
|
51
|
+
const deadline = Date.now() + timeoutMs;
|
|
52
|
+
while (Date.now() < deadline) {
|
|
53
|
+
if (await canConnect(endpoint)) return;
|
|
54
|
+
await new Promise((resolve) => setTimeout(resolve, STARTUP_POLL_MS));
|
|
55
|
+
}
|
|
56
|
+
throw new Error(`Session host did not become ready within ${timeoutMs}ms`);
|
|
57
|
+
}
|
|
58
|
+
function resolveSessionHostEntry() {
|
|
59
|
+
return require.resolve("@adhdev/session-host-daemon");
|
|
60
|
+
}
|
|
61
|
+
async function runSessionHostCli(args) {
|
|
62
|
+
const entry = resolveSessionHostEntry();
|
|
63
|
+
const child = (0, import_child_process.spawn)(process.execPath, [entry, ...args], {
|
|
64
|
+
stdio: "inherit",
|
|
65
|
+
env: {
|
|
66
|
+
...process.env,
|
|
67
|
+
ADHDEV_SESSION_HOST_NAME: SESSION_HOST_APP_NAME
|
|
68
|
+
}
|
|
69
|
+
});
|
|
70
|
+
return await new Promise((resolve, reject) => {
|
|
71
|
+
child.on("error", reject);
|
|
72
|
+
child.on("exit", (code) => resolve(code ?? 0));
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
async function ensureSessionHostReady() {
|
|
76
|
+
const endpoint = (0, import_session_host_core.getDefaultSessionHostEndpoint)(SESSION_HOST_APP_NAME);
|
|
77
|
+
if (await canConnect(endpoint)) return endpoint;
|
|
78
|
+
const entry = resolveSessionHostEntry();
|
|
79
|
+
const child = (0, import_child_process.spawn)(process.execPath, [entry], {
|
|
80
|
+
detached: true,
|
|
81
|
+
stdio: "ignore",
|
|
82
|
+
windowsHide: true
|
|
83
|
+
});
|
|
84
|
+
child.unref();
|
|
85
|
+
await waitForReady(endpoint);
|
|
86
|
+
return endpoint;
|
|
87
|
+
}
|
|
88
|
+
async function listHostedCliRuntimes(endpoint) {
|
|
89
|
+
const client = new import_session_host_core.SessionHostClient({ endpoint });
|
|
90
|
+
try {
|
|
91
|
+
const response = await client.request({
|
|
92
|
+
type: "list_sessions",
|
|
93
|
+
payload: {}
|
|
94
|
+
});
|
|
95
|
+
if (!response.success || !response.result) {
|
|
96
|
+
return [];
|
|
97
|
+
}
|
|
98
|
+
return response.result.filter((record) => record.category === "cli" && ["running", "interrupted"].includes(record.lifecycle)).sort((a, b) => b.lastActivityAt - a.lastActivityAt).map((record) => ({
|
|
99
|
+
runtimeId: record.sessionId,
|
|
100
|
+
runtimeKey: record.runtimeKey,
|
|
101
|
+
displayName: record.displayName,
|
|
102
|
+
workspaceLabel: record.workspaceLabel,
|
|
103
|
+
lifecycle: record.lifecycle,
|
|
104
|
+
recoveryState: typeof record.meta?.runtimeRecoveryState === "string" ? String(record.meta.runtimeRecoveryState) : null,
|
|
105
|
+
cliType: record.providerType,
|
|
106
|
+
workspace: record.workspace,
|
|
107
|
+
cliArgs: Array.isArray(record.meta?.cliArgs) ? record.meta.cliArgs : []
|
|
108
|
+
}));
|
|
109
|
+
} finally {
|
|
110
|
+
await client.close().catch(() => {
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
async function proxySessionHostList(showAll = false) {
|
|
115
|
+
await ensureSessionHostReady();
|
|
116
|
+
return runSessionHostCli(["list", ...showAll ? ["--all"] : []]);
|
|
117
|
+
}
|
|
118
|
+
async function proxySessionHostAttach(target, options = {}) {
|
|
119
|
+
await ensureSessionHostReady();
|
|
120
|
+
const args = ["attach", target];
|
|
121
|
+
if (options.readOnly) args.push("--read-only");
|
|
122
|
+
if (options.takeover) args.push("--takeover");
|
|
123
|
+
return runSessionHostCli(args);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
// src/index.ts
|
|
127
|
+
var import_session_host_core2 = require("@adhdev/session-host-core");
|
|
128
|
+
var import_api = require("@adhdev/terminal-mux-control/api");
|
|
33
129
|
var DEFAULT_PORT = 3847;
|
|
34
130
|
var STATUS_INTERVAL = 2e3;
|
|
35
131
|
var pkgVersion = process.env.ADHDEV_PKG_VERSION || "unknown";
|
|
@@ -61,9 +157,12 @@ var StandaloneServer = class {
|
|
|
61
157
|
running = false;
|
|
62
158
|
components = null;
|
|
63
159
|
devServer = null;
|
|
160
|
+
sessionHostEndpoint = null;
|
|
64
161
|
async start(options = {}) {
|
|
65
162
|
const port = options.port || DEFAULT_PORT;
|
|
66
163
|
const host = options.host || "127.0.0.1";
|
|
164
|
+
const sessionHostEndpoint = await ensureSessionHostReady();
|
|
165
|
+
this.sessionHostEndpoint = sessionHostEndpoint;
|
|
67
166
|
this.authToken = options.token || process.env.ADHDEV_TOKEN || null;
|
|
68
167
|
this.components = await (0, import_daemon_core.initDaemonComponents)({
|
|
69
168
|
cliManagerDeps: {
|
|
@@ -81,7 +180,20 @@ var StandaloneServer = class {
|
|
|
81
180
|
}),
|
|
82
181
|
onStatusChange: () => this.broadcastStatus(),
|
|
83
182
|
removeAgentTracking: () => {
|
|
84
|
-
}
|
|
183
|
+
},
|
|
184
|
+
createPtyTransportFactory: ({ runtimeId, providerType, workspace, cliArgs, attachExisting }) => new import_daemon_core.SessionHostPtyTransportFactory({
|
|
185
|
+
endpoint: sessionHostEndpoint,
|
|
186
|
+
clientId: `daemon-${process.pid}`,
|
|
187
|
+
runtimeId,
|
|
188
|
+
providerType,
|
|
189
|
+
workspace,
|
|
190
|
+
attachExisting,
|
|
191
|
+
meta: {
|
|
192
|
+
cliArgs: cliArgs || [],
|
|
193
|
+
managedBy: "adhdev-standalone"
|
|
194
|
+
}
|
|
195
|
+
}),
|
|
196
|
+
listHostedCliRuntimes: async () => listHostedCliRuntimes(sessionHostEndpoint)
|
|
85
197
|
},
|
|
86
198
|
onStatusChange: () => this.broadcastStatus(),
|
|
87
199
|
onStreamsUpdated: (ideType, streams) => {
|
|
@@ -92,6 +204,7 @@ var StandaloneServer = class {
|
|
|
92
204
|
tickIntervalMs: 3e3,
|
|
93
205
|
cdpScanIntervalMs: 15e3
|
|
94
206
|
});
|
|
207
|
+
await this.components.cliManager.restoreHostedSessions();
|
|
95
208
|
if (options.dev) {
|
|
96
209
|
this.devServer = await (0, import_daemon_core.startDaemonDevSupport)({
|
|
97
210
|
components: this.components,
|
|
@@ -190,12 +303,116 @@ var StandaloneServer = class {
|
|
|
190
303
|
}
|
|
191
304
|
}
|
|
192
305
|
const apiPath = url.startsWith("/api/v1/") ? url.slice(7) : null;
|
|
306
|
+
const parsedUrl = new URL(url, `http://${req.headers.host || "localhost"}`);
|
|
193
307
|
if (apiPath === "/status" && method === "GET") {
|
|
194
308
|
const status = this.getStatus(getSharedSnapshot());
|
|
195
309
|
res.writeHead(200, { "Content-Type": "application/json" });
|
|
196
310
|
res.end(JSON.stringify(status));
|
|
197
311
|
return;
|
|
198
312
|
}
|
|
313
|
+
if (apiPath?.startsWith("/mux/")) {
|
|
314
|
+
const muxParts = parsedUrl.pathname.replace(/^\/api\/v1\/mux\//, "").split("/").filter(Boolean);
|
|
315
|
+
const [workspaceSegment, action] = muxParts;
|
|
316
|
+
const workspaceName = workspaceSegment ? decodeURIComponent(workspaceSegment) : "";
|
|
317
|
+
if (!workspaceName || !action) {
|
|
318
|
+
res.writeHead(400, { "Content-Type": "application/json" });
|
|
319
|
+
res.end(JSON.stringify({ error: "Invalid mux route" }));
|
|
320
|
+
return;
|
|
321
|
+
}
|
|
322
|
+
if (action === "state" && method === "GET") {
|
|
323
|
+
void (async () => {
|
|
324
|
+
const result = await (0, import_api.getWorkspaceState)(workspaceName);
|
|
325
|
+
if (!result?.success || !result.result) {
|
|
326
|
+
res.writeHead(404, { "Content-Type": "application/json" });
|
|
327
|
+
res.end(JSON.stringify({ error: result?.error || "Workspace not available" }));
|
|
328
|
+
return;
|
|
329
|
+
}
|
|
330
|
+
res.writeHead(200, { "Content-Type": "application/json" });
|
|
331
|
+
res.end(JSON.stringify(result.result));
|
|
332
|
+
})().catch((error) => {
|
|
333
|
+
res.writeHead(500, { "Content-Type": "application/json" });
|
|
334
|
+
res.end(JSON.stringify({ error: error?.message || String(error) }));
|
|
335
|
+
});
|
|
336
|
+
return;
|
|
337
|
+
}
|
|
338
|
+
if (action === "socket-info" && method === "GET") {
|
|
339
|
+
void (async () => {
|
|
340
|
+
const result = await (0, import_api.getWorkspaceSocketInfo)(workspaceName);
|
|
341
|
+
res.writeHead(200, { "Content-Type": "application/json" });
|
|
342
|
+
res.end(JSON.stringify(result));
|
|
343
|
+
})().catch((error) => {
|
|
344
|
+
res.writeHead(500, { "Content-Type": "application/json" });
|
|
345
|
+
res.end(JSON.stringify({ error: error?.message || String(error) }));
|
|
346
|
+
});
|
|
347
|
+
return;
|
|
348
|
+
}
|
|
349
|
+
if (action === "control" && method === "POST") {
|
|
350
|
+
let body = "";
|
|
351
|
+
req.on("data", (chunk) => {
|
|
352
|
+
body += chunk;
|
|
353
|
+
});
|
|
354
|
+
req.on("end", async () => {
|
|
355
|
+
try {
|
|
356
|
+
const { type, payload } = JSON.parse(body || "{}");
|
|
357
|
+
const result = await (0, import_api.requestWorkspaceControl)(workspaceName, { type, payload });
|
|
358
|
+
if (!result?.success) {
|
|
359
|
+
res.writeHead(404, { "Content-Type": "application/json" });
|
|
360
|
+
res.end(JSON.stringify({ error: result?.error || "Workspace control unavailable" }));
|
|
361
|
+
return;
|
|
362
|
+
}
|
|
363
|
+
res.writeHead(200, { "Content-Type": "application/json" });
|
|
364
|
+
res.end(JSON.stringify(result.result ?? { success: true }));
|
|
365
|
+
} catch (error) {
|
|
366
|
+
res.writeHead(400, { "Content-Type": "application/json" });
|
|
367
|
+
res.end(JSON.stringify({ error: error?.message || String(error) }));
|
|
368
|
+
}
|
|
369
|
+
});
|
|
370
|
+
return;
|
|
371
|
+
}
|
|
372
|
+
if (action === "events" && method === "GET") {
|
|
373
|
+
void this.handleMuxEvents(req, res, workspaceName);
|
|
374
|
+
return;
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
if (apiPath?.startsWith("/runtime/")) {
|
|
378
|
+
const runtimeParts = parsedUrl.pathname.replace(/^\/api\/v1\/runtime\//, "").split("/").filter(Boolean);
|
|
379
|
+
const [sessionSegment, action] = runtimeParts;
|
|
380
|
+
const sessionId = sessionSegment ? decodeURIComponent(sessionSegment) : "";
|
|
381
|
+
if (!sessionId || !action) {
|
|
382
|
+
res.writeHead(400, { "Content-Type": "application/json" });
|
|
383
|
+
res.end(JSON.stringify({ error: "Invalid runtime route" }));
|
|
384
|
+
return;
|
|
385
|
+
}
|
|
386
|
+
if (action === "snapshot" && method === "GET") {
|
|
387
|
+
void (async () => {
|
|
388
|
+
const client = new import_session_host_core2.SessionHostClient({ endpoint: this.sessionHostEndpoint || void 0 });
|
|
389
|
+
try {
|
|
390
|
+
const snapshot = await client.request({
|
|
391
|
+
type: "get_snapshot",
|
|
392
|
+
payload: { sessionId }
|
|
393
|
+
});
|
|
394
|
+
if (!snapshot.success || !snapshot.result) {
|
|
395
|
+
res.writeHead(404, { "Content-Type": "application/json" });
|
|
396
|
+
res.end(JSON.stringify({ error: snapshot.error || "Runtime snapshot unavailable" }));
|
|
397
|
+
return;
|
|
398
|
+
}
|
|
399
|
+
res.writeHead(200, { "Content-Type": "application/json" });
|
|
400
|
+
res.end(JSON.stringify({ sessionId, ...snapshot.result }));
|
|
401
|
+
} finally {
|
|
402
|
+
await client.close().catch(() => {
|
|
403
|
+
});
|
|
404
|
+
}
|
|
405
|
+
})().catch((error) => {
|
|
406
|
+
res.writeHead(500, { "Content-Type": "application/json" });
|
|
407
|
+
res.end(JSON.stringify({ error: error?.message || String(error) }));
|
|
408
|
+
});
|
|
409
|
+
return;
|
|
410
|
+
}
|
|
411
|
+
if (action === "events" && method === "GET") {
|
|
412
|
+
void this.handleRuntimeEvents(req, res, sessionId);
|
|
413
|
+
return;
|
|
414
|
+
}
|
|
415
|
+
}
|
|
199
416
|
if (apiPath === "/command" && method === "POST") {
|
|
200
417
|
let body = "";
|
|
201
418
|
req.on("data", (chunk) => {
|
|
@@ -243,6 +460,90 @@ var StandaloneServer = class {
|
|
|
243
460
|
res.writeHead(404, { "Content-Type": "application/json" });
|
|
244
461
|
res.end(JSON.stringify({ error: "Not found" }));
|
|
245
462
|
}
|
|
463
|
+
async handleMuxEvents(req, res, workspaceName) {
|
|
464
|
+
const socketInfo = await (0, import_api.getWorkspaceSocketInfo)(workspaceName);
|
|
465
|
+
if (!socketInfo.live) {
|
|
466
|
+
res.writeHead(404, { "Content-Type": "application/json" });
|
|
467
|
+
res.end(JSON.stringify({ error: "Workspace control socket unavailable" }));
|
|
468
|
+
return;
|
|
469
|
+
}
|
|
470
|
+
const client = new import_api.AdhMuxControlClient(workspaceName);
|
|
471
|
+
await client.connect();
|
|
472
|
+
res.writeHead(200, {
|
|
473
|
+
"Content-Type": "text/event-stream",
|
|
474
|
+
"Cache-Control": "no-cache, no-transform",
|
|
475
|
+
Connection: "keep-alive",
|
|
476
|
+
"X-Accel-Buffering": "no"
|
|
477
|
+
});
|
|
478
|
+
const writeEvent = (event) => {
|
|
479
|
+
res.write(`event: ${event.type}
|
|
480
|
+
`);
|
|
481
|
+
res.write(`data: ${JSON.stringify(event)}
|
|
482
|
+
|
|
483
|
+
`);
|
|
484
|
+
};
|
|
485
|
+
const initial = await client.request({
|
|
486
|
+
type: "workspace_state"
|
|
487
|
+
});
|
|
488
|
+
if (initial.success && initial.result) {
|
|
489
|
+
writeEvent({
|
|
490
|
+
type: "workspace_update",
|
|
491
|
+
payload: initial.result
|
|
492
|
+
});
|
|
493
|
+
}
|
|
494
|
+
const unsubscribe = client.onEvent(writeEvent);
|
|
495
|
+
const heartbeat = setInterval(() => {
|
|
496
|
+
res.write(": ping\n\n");
|
|
497
|
+
}, 15e3);
|
|
498
|
+
const cleanup = () => {
|
|
499
|
+
clearInterval(heartbeat);
|
|
500
|
+
unsubscribe();
|
|
501
|
+
void client.close().catch(() => {
|
|
502
|
+
});
|
|
503
|
+
};
|
|
504
|
+
req.on("close", cleanup);
|
|
505
|
+
req.on("aborted", cleanup);
|
|
506
|
+
}
|
|
507
|
+
async handleRuntimeEvents(req, res, sessionId) {
|
|
508
|
+
const client = new import_session_host_core2.SessionHostClient({ endpoint: this.sessionHostEndpoint || void 0 });
|
|
509
|
+
await client.connect();
|
|
510
|
+
res.writeHead(200, {
|
|
511
|
+
"Content-Type": "text/event-stream",
|
|
512
|
+
"Cache-Control": "no-cache, no-transform",
|
|
513
|
+
Connection: "keep-alive",
|
|
514
|
+
"X-Accel-Buffering": "no"
|
|
515
|
+
});
|
|
516
|
+
const snapshot = await client.request({
|
|
517
|
+
type: "get_snapshot",
|
|
518
|
+
payload: { sessionId }
|
|
519
|
+
});
|
|
520
|
+
if (snapshot.success && snapshot.result) {
|
|
521
|
+
res.write("event: runtime_snapshot\n");
|
|
522
|
+
res.write(`data: ${JSON.stringify({ sessionId, ...snapshot.result })}
|
|
523
|
+
|
|
524
|
+
`);
|
|
525
|
+
}
|
|
526
|
+
const writeEvent = (event) => {
|
|
527
|
+
if (event.sessionId !== sessionId) return;
|
|
528
|
+
res.write(`event: ${event.type}
|
|
529
|
+
`);
|
|
530
|
+
res.write(`data: ${JSON.stringify(event)}
|
|
531
|
+
|
|
532
|
+
`);
|
|
533
|
+
};
|
|
534
|
+
const unsubscribe = client.onEvent(writeEvent);
|
|
535
|
+
const heartbeat = setInterval(() => {
|
|
536
|
+
res.write(": ping\n\n");
|
|
537
|
+
}, 15e3);
|
|
538
|
+
const cleanup = () => {
|
|
539
|
+
clearInterval(heartbeat);
|
|
540
|
+
unsubscribe();
|
|
541
|
+
void client.close().catch(() => {
|
|
542
|
+
});
|
|
543
|
+
};
|
|
544
|
+
req.on("close", cleanup);
|
|
545
|
+
req.on("aborted", cleanup);
|
|
546
|
+
}
|
|
246
547
|
// ─── WebSocket Handler ───
|
|
247
548
|
handleWsConnection(ws) {
|
|
248
549
|
const MAX_WS_CLIENTS = 10;
|
|
@@ -391,6 +692,23 @@ var StandaloneServer = class {
|
|
|
391
692
|
};
|
|
392
693
|
async function main() {
|
|
393
694
|
const args = process.argv.slice(2);
|
|
695
|
+
const primaryCommand = args[0] || "";
|
|
696
|
+
if (primaryCommand === "attach") {
|
|
697
|
+
const target = args[1];
|
|
698
|
+
if (!target) {
|
|
699
|
+
console.error("Usage: adhdev attach <sessionId> [--read-only|--takeover]");
|
|
700
|
+
process.exit(1);
|
|
701
|
+
}
|
|
702
|
+
const readOnly = args.includes("--read-only");
|
|
703
|
+
const takeover = args.includes("--takeover");
|
|
704
|
+
const exitCode = await proxySessionHostAttach(target, { readOnly, takeover });
|
|
705
|
+
process.exit(exitCode);
|
|
706
|
+
}
|
|
707
|
+
if (primaryCommand === "list" || primaryCommand === "runtimes") {
|
|
708
|
+
const showAll = args.includes("--all");
|
|
709
|
+
const exitCode = await proxySessionHostList(showAll);
|
|
710
|
+
process.exit(exitCode);
|
|
711
|
+
}
|
|
394
712
|
const options = {};
|
|
395
713
|
for (let i = 0; i < args.length; i++) {
|
|
396
714
|
if ((args[i] === "--port" || args[i] === "-p") && args[i + 1]) {
|
|
@@ -417,6 +735,8 @@ async function main() {
|
|
|
417
735
|
if (args[i] === "--help" || args[i] === "-h") {
|
|
418
736
|
console.log(`
|
|
419
737
|
Usage: adhdev-standalone [options]
|
|
738
|
+
adhdev-standalone list [--all]
|
|
739
|
+
adhdev-standalone attach <sessionId> [--read-only|--takeover]
|
|
420
740
|
|
|
421
741
|
Options:
|
|
422
742
|
--port, -p <port> Port to run the standalone server on (default: 3847)
|
|
@@ -426,6 +746,11 @@ Options:
|
|
|
426
746
|
--public <path> Custom path to the web dashboard distribution
|
|
427
747
|
--no-open Do not automatically open the browser on startup
|
|
428
748
|
--help, -h Show this help message
|
|
749
|
+
|
|
750
|
+
Runtime commands:
|
|
751
|
+
list, runtimes Show hosted CLI runtimes
|
|
752
|
+
attach Attach local terminal to a runtime
|
|
753
|
+
open Open a local terminal window running adhmux for a runtime
|
|
429
754
|
`);
|
|
430
755
|
process.exit(0);
|
|
431
756
|
}
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["/**\n * daemon-standalone — Embedded HTTP/WS server for local dashboard\n *\n * Standalone-only server:\n * 1. DaemonCore init (IDE detection, CDP connection, Provider loading)\n * 2. HTTP REST API — /api/v1/status, /api/v1/command\n * 3. WebSocket — ws://localhost:3847/ws (real-time status broadcast + command execution)\n * 4. Static file serving — web-standalone build output\n *\n * Usage:\n * npx @adhdev/daemon-standalone\n * npx @adhdev/daemon-standalone --port 4000\n */\n\nimport { createServer, type IncomingMessage } from 'http';\nimport { WebSocketServer, WebSocket } from 'ws';\nimport * as path from 'path';\nimport * as fs from 'fs';\nimport * as os from 'os';\n\nimport {\n LOG,\n initDaemonComponents,\n startDaemonDevSupport,\n shutdownDaemonComponents,\n loadConfig,\n buildStatusSnapshot,\n forwardAgentStreamsToIdeInstance,\n type DaemonComponents,\n type StatusResponse,\n type AgentEntry,\n} from '@adhdev/daemon-core';\n\n// ─── Constants ───\nconst DEFAULT_PORT = 3847;\nconst STATUS_INTERVAL = 2000;\n\nlet pkgVersion = process.env.ADHDEV_PKG_VERSION || 'unknown';\nif (pkgVersion === 'unknown') {\n try {\n const possiblePaths = [\n path.join(__dirname, '..', 'package.json'),\n path.join(__dirname, 'package.json'),\n ];\n for (const candidate of possiblePaths) {\n try {\n const data = JSON.parse(fs.readFileSync(candidate, 'utf-8'));\n if (data.version) {\n pkgVersion = data.version;\n break;\n }\n } catch { /* noop */ }\n }\n } catch { /* noop */ }\n}\n\n// ─── Types ───\ninterface StandaloneOptions {\n port?: number;\n host?: string;\n publicDir?: string;\n open?: boolean;\n token?: string;\n dev?: boolean;\n}\n\ninterface WsMessage {\n type: string;\n requestId?: string;\n data?: Record<string, any>;\n}\n\n\n// ─── Standalone Server ───\n\nclass StandaloneServer {\n private httpServer: ReturnType<typeof createServer> | null = null;\n private wss: WebSocketServer | null = null;\n private clients = new Set<WebSocket>();\n private authToken: string | null = null;\n private statusTimer: NodeJS.Timeout | null = null;\n private running = false;\n private components: DaemonComponents | null = null;\n private devServer: Awaited<ReturnType<typeof startDaemonDevSupport>> | null = null;\n\n async start(options: StandaloneOptions = {}): Promise<void> {\n const port = options.port || DEFAULT_PORT;\n const host = options.host || '127.0.0.1';\n\n // Auth token setup (opt-in only)\n this.authToken = options.token || process.env.ADHDEV_TOKEN || null;\n\n // Initialize all core components via daemon-core bootstrapper\n this.components = await initDaemonComponents({\n cliManagerDeps: {\n getServerConn: () => null,\n getP2p: () => ({\n broadcastPtyOutput: (key: string, data: string) => {\n if (this.clients.size === 0) return;\n const msg = JSON.stringify({ type: 'pty_output', cliId: key, data });\n for (const client of this.clients) {\n if (client.readyState === 1) { // OPEN\n client.send(msg);\n }\n }\n }\n }),\n onStatusChange: () => this.broadcastStatus(),\n removeAgentTracking: () => {},\n },\n onStatusChange: () => this.broadcastStatus(),\n onStreamsUpdated: (ideType: string, streams: any[]) => {\n if (!this.components) return;\n forwardAgentStreamsToIdeInstance(this.components.instanceManager, ideType, streams);\n this.broadcastStatus();\n },\n tickIntervalMs: 3000,\n cdpScanIntervalMs: 15_000,\n });\n\n // DevServer (optional)\n if (options.dev) {\n this.devServer = await startDaemonDevSupport({\n components: this.components,\n logFn: (msg: string) => console.log(msg),\n });\n }\n\n // 5. HTTP Server\n this.httpServer = createServer((req, res) => {\n this.handleHttp(req, res, options.publicDir);\n });\n\n // 6. WebSocket Server (upgrade)\n this.wss = new WebSocketServer({ noServer: true });\n this.httpServer.on('upgrade', (req, socket, head) => {\n const wsUrl = new URL(req.url || '/', `http://${req.headers.host || 'localhost'}`);\n if (wsUrl.pathname === '/ws') {\n // Token auth for WS\n if (this.authToken) {\n const urlToken = wsUrl.searchParams.get('token');\n if (urlToken !== this.authToken) {\n socket.write('HTTP/1.1 401 Unauthorized\\r\\n\\r\\n');\n socket.destroy();\n return;\n }\n }\n this.wss!.handleUpgrade(req, socket, head, (ws) => {\n this.handleWsConnection(ws);\n });\n } else {\n socket.destroy();\n }\n });\n\n // 7. Status broadcast timer\n this.statusTimer = setInterval(() => {\n this.broadcastStatus();\n }, STATUS_INTERVAL);\n\n // 8. Start listening\n this.running = true;\n await new Promise<void>((resolve) => {\n this.httpServer!.listen(port, host, () => {\n resolve();\n });\n });\n\n console.log('');\n console.log('🚀 ADHDev Standalone Server');\n console.log(` http://${host === '0.0.0.0' ? 'localhost' : host}:${port}`);\n console.log(` ws://${host === '0.0.0.0' ? 'localhost' : host}:${port}/ws`);\n if (host === '0.0.0.0') {\n const lanIps = this.getLanIPs();\n for (const ip of lanIps) {\n console.log(` http://${ip}:${port} (LAN)`);\n }\n }\n if (this.authToken) {\n console.log(` 🔑 Token: ${this.authToken}`);\n }\n console.log('');\n\n const cdpCount = [...this.components.cdpManagers.values()].filter(m => m.isConnected).length;\n console.log(` CDP: ${cdpCount > 0 ? `✅ ${cdpCount} connected` : '❌ none'}`);\n console.log(` Providers: ${this.components.providerLoader.getAll().length} loaded`);\n if (options.dev) {\n console.log(` 🛠️ DevConsole: http://127.0.0.1:19280`);\n }\n console.log('');\n console.log(' Press Ctrl+C to stop.');\n console.log('');\n\n // Open browser\n if (options.open !== false) {\n try {\n const open = (await import('open')).default;\n await open(`http://localhost:${port}`);\n } catch { /* noop */ }\n }\n\n // Signal handling\n process.on('SIGINT', () => this.stop());\n process.on('SIGTERM', () => this.stop());\n }\n\n // ─── HTTP Handler ───\n\n private handleHttp(\n req: IncomingMessage,\n res: import('http').ServerResponse,\n publicDir?: string\n ): void {\n const url = req.url || '/';\n const method = req.method || 'GET';\n let sharedSnapshotCache: ReturnType<StandaloneServer['buildSharedSnapshot']> | null = null;\n const getSharedSnapshot = () => {\n if (!sharedSnapshotCache) sharedSnapshotCache = this.buildSharedSnapshot();\n return sharedSnapshotCache;\n };\n\n // CORS\n res.setHeader('Access-Control-Allow-Origin', '*');\n res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS');\n res.setHeader('Access-Control-Allow-Headers', 'Content-Type, Authorization');\n if (method === 'OPTIONS') {\n res.writeHead(204);\n res.end();\n return;\n }\n\n // Token auth for API routes\n if (this.authToken && url.startsWith('/api/')) {\n const authHeader = req.headers['authorization'];\n const bearerToken = authHeader?.startsWith('Bearer ') ? authHeader.slice(7) : null;\n const queryToken = new URL(url, `http://${req.headers.host || 'localhost'}`).searchParams.get('token');\n if (bearerToken !== this.authToken && queryToken !== this.authToken) {\n res.writeHead(401, { 'Content-Type': 'application/json' });\n res.end(JSON.stringify({ error: 'Unauthorized. Provide token via Authorization header or ?token= query.' }));\n return;\n }\n }\n\n // ─── API Routes (v1) ───\n const apiPath = url.startsWith('/api/v1/') ? url.slice(7) : null; // /api/v1/status → /status\n\n if (apiPath === '/status' && method === 'GET') {\n const status = this.getStatus(getSharedSnapshot());\n res.writeHead(200, { 'Content-Type': 'application/json' });\n res.end(JSON.stringify(status));\n return;\n }\n\n if (apiPath === '/command' && method === 'POST') {\n let body = '';\n req.on('data', (chunk) => { body += chunk; });\n req.on('end', async () => {\n try {\n const { type, payload } = JSON.parse(body);\n const result = await this.executeCommand(type, payload || {});\n res.writeHead(200, { 'Content-Type': 'application/json' });\n res.end(JSON.stringify(result));\n } catch (e: any) {\n res.writeHead(400, { 'Content-Type': 'application/json' });\n res.end(JSON.stringify({ success: false, error: e.message }));\n }\n });\n return;\n }\n\n // ─── Static Files ───\n if (publicDir) {\n const filePath = url === '/' ? '/index.html' : url;\n const fullPath = path.join(publicDir, filePath);\n if (fs.existsSync(fullPath) && fs.statSync(fullPath).isFile()) {\n const ext = path.extname(fullPath);\n const mimeTypes: Record<string, string> = {\n '.html': 'text/html',\n '.js': 'application/javascript',\n '.css': 'text/css',\n '.json': 'application/json',\n '.png': 'image/png',\n '.svg': 'image/svg+xml',\n '.ico': 'image/x-icon',\n '.woff2': 'font/woff2',\n };\n res.writeHead(200, { 'Content-Type': mimeTypes[ext] || 'application/octet-stream' });\n fs.createReadStream(fullPath).pipe(res);\n return;\n }\n // SPA fallback → index.html\n const indexPath = path.join(publicDir, 'index.html');\n if (fs.existsSync(indexPath) && !url.startsWith('/api/')) {\n res.writeHead(200, { 'Content-Type': 'text/html' });\n fs.createReadStream(indexPath).pipe(res);\n return;\n }\n }\n\n // 404\n res.writeHead(404, { 'Content-Type': 'application/json' });\n res.end(JSON.stringify({ error: 'Not found' }));\n }\n\n // ─── WebSocket Handler ───\n\n private handleWsConnection(ws: WebSocket): void {\n // Max client limit to prevent connection storms\n const MAX_WS_CLIENTS = 10;\n if (this.clients.size >= MAX_WS_CLIENTS) {\n // Close oldest connection\n const oldest = this.clients.values().next().value;\n if (oldest) {\n try { (oldest as WebSocket).close(1000, 'Too many connections'); } catch {}\n this.clients.delete(oldest);\n }\n }\n this.clients.add(ws);\n console.log(`[WS] Client connected (total: ${this.clients.size})`);\n\n // Send initial status immediately\n const status = this.getStatus();\n ws.send(JSON.stringify({ type: 'status', data: status }));\n\n ws.on('message', async (raw) => {\n try {\n const msg: WsMessage = JSON.parse(raw.toString());\n if (msg.type === 'command' && msg.data) {\n const { type, payload } = msg.data;\n const requestId = msg.requestId;\n const result = await this.executeCommand(type, payload || {});\n ws.send(JSON.stringify({ type: 'command_result', requestId, data: result }));\n }\n } catch (e: any) {\n const requestId = (() => { try { return JSON.parse(raw.toString()).requestId; } catch { return undefined; } })();\n ws.send(JSON.stringify({ type: 'error', requestId, data: { message: e.message } }));\n }\n });\n\n ws.on('close', () => {\n this.clients.delete(ws);\n console.log(`[WS] Client disconnected (total: ${this.clients.size})`);\n });\n\n ws.on('error', () => {\n this.clients.delete(ws);\n });\n }\n\n // ─── Core Logic ───\n\n private buildSharedSnapshot() {\n const cfgSnap = loadConfig();\n const machineId = cfgSnap.machineId || 'mach_unknown';\n const allStates = this.components!.instanceManager.collectAllStates();\n\n return buildStatusSnapshot({\n allStates,\n cdpManagers: this.components!.cdpManagers as Map<string, unknown>,\n providerLoader: this.components!.providerLoader,\n detectedIdes: this.components!.detectedIdes.value,\n instanceId: `standalone_${machineId}`,\n version: pkgVersion,\n daemonMode: false,\n });\n }\n\n private getStatus(snapshot: ReturnType<StandaloneServer['buildSharedSnapshot']> = this.buildSharedSnapshot()): StatusResponse {\n const cfgSnap = loadConfig();\n\n return {\n ...snapshot,\n id: snapshot.instanceId,\n daemonMode: false,\n type: 'standalone',\n platform: snapshot.machine.platform,\n hostname: snapshot.machine.hostname,\n userName: cfgSnap.userName || undefined,\n system: {\n cpus: snapshot.machine.cpus,\n totalMem: snapshot.machine.totalMem,\n freeMem: snapshot.machine.freeMem,\n availableMem: snapshot.machine.availableMem,\n loadavg: snapshot.machine.loadavg,\n uptime: snapshot.machine.uptime,\n arch: snapshot.machine.arch,\n },\n };\n }\n\n private async executeCommand(type: string, args: any): Promise<any> {\n if (!this.components) {\n return { success: false, error: 'Components not initialized' };\n }\n const result = await this.components.router.execute(type, args, 'standalone');\n if (type.startsWith('workspace_')) this.broadcastStatus();\n return result;\n }\n\n private broadcastStatus(): void {\n if (this.clients.size === 0) return;\n const status = this.getStatus();\n const msg = JSON.stringify({ type: 'status', data: status });\n const cdpCount = [...this.components!.cdpManagers.values()].filter(m => m.isConnected).length;\n LOG.debug('Broadcast', `status → ${this.clients.size} client(s), ${(status as any).sessions?.length || 0} session(s), ${cdpCount} CDP`);\n for (const client of this.clients) {\n if (client.readyState === WebSocket.OPEN) {\n client.send(msg);\n }\n }\n }\n\n // ─── Network ───\n\n private getLanIPs(): string[] {\n const interfaces = os.networkInterfaces();\n const ips: string[] = [];\n for (const iface of Object.values(interfaces)) {\n if (!iface) continue;\n for (const info of iface) {\n if (info.family === 'IPv4' && !info.internal) {\n ips.push(info.address);\n }\n }\n }\n return ips;\n }\n\n // ─── Lifecycle ───\n\n async stop(): Promise<void> {\n if (!this.running) return;\n this.running = false;\n\n console.log('\\n Shutting down...');\n\n if (this.statusTimer) {\n clearInterval(this.statusTimer);\n this.statusTimer = null;\n }\n\n // Close WS clients\n for (const ws of this.clients) {\n try { ws.close(); } catch { /* noop */ }\n }\n this.clients.clear();\n\n // Close WSS\n if (this.wss) {\n this.wss.close();\n this.wss = null;\n }\n\n // Shutdown core components\n if (this.components) {\n await shutdownDaemonComponents(this.components);\n }\n\n // HTTP server\n if (this.httpServer) {\n this.httpServer.close();\n this.httpServer = null;\n }\n\n console.log(' ✓ ADHDev Standalone stopped.\\n');\n process.exit(0);\n }\n}\n\n// ─── CLI ───\n\nasync function main(): Promise<void> {\n const args = process.argv.slice(2);\n const options: StandaloneOptions = {};\n\n // Parse simple args\n for (let i = 0; i < args.length; i++) {\n if ((args[i] === '--port' || args[i] === '-p') && args[i + 1]) {\n options.port = parseInt(args[i + 1]);\n i++;\n }\n if (args[i] === '--host' || args[i] === '-H') {\n options.host = '0.0.0.0';\n }\n if (args[i] === '--public' && args[i + 1]) {\n options.publicDir = args[i + 1];\n i++;\n }\n if (args[i] === '--no-open') {\n options.open = false;\n }\n if (args[i] === '--dev') {\n (options as any).dev = true;\n }\n if (args[i] === '--token' && args[i + 1]) {\n options.token = args[i + 1];\n i++;\n }\n if (args[i] === '--help' || args[i] === '-h') {\n console.log(`\nUsage: adhdev-standalone [options]\n\nOptions:\n --port, -p <port> Port to run the standalone server on (default: 3847)\n --host, -H Allow external network connections (binds to 0.0.0.0)\n --token <token> Set an authentication token for the dashboard UI\n --dev Enable DevConsole to debug and test providers\n --public <path> Custom path to the web dashboard distribution\n --no-open Do not automatically open the browser on startup\n --help, -h Show this help message\n`);\n process.exit(0);\n }\n }\n\n // Try to find web-standalone build\n if (!options.publicDir) {\n const candidates = [\n path.join(__dirname, '../../web-standalone/dist'),\n path.join(__dirname, '../public'),\n path.join(process.cwd(), 'public'),\n ];\n for (const candidate of candidates) {\n if (fs.existsSync(path.join(candidate, 'index.html'))) {\n options.publicDir = candidate;\n break;\n }\n }\n }\n\n const server = new StandaloneServer();\n await server.start(options);\n\n // Keep process alive\n await new Promise<void>(() => {});\n}\n\nmain().catch((e) => {\n console.error('Fatal error:', e);\n process.exit(1);\n});\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/session-host.ts"],"sourcesContent":["/**\n * daemon-standalone — Embedded HTTP/WS server for local dashboard\n *\n * Standalone-only server:\n * 1. DaemonCore init (IDE detection, CDP connection, Provider loading)\n * 2. HTTP REST API — /api/v1/status, /api/v1/command\n * 3. WebSocket — ws://localhost:3847/ws (real-time status broadcast + command execution)\n * 4. Static file serving — web-standalone build output\n *\n * Usage:\n * npx @adhdev/daemon-standalone\n * npx @adhdev/daemon-standalone --port 4000\n */\n\nimport { createServer, type IncomingMessage } from 'http';\nimport { WebSocketServer, WebSocket } from 'ws';\nimport * as path from 'path';\nimport * as fs from 'fs';\nimport * as os from 'os';\n\nimport {\n LOG,\n initDaemonComponents,\n startDaemonDevSupport,\n shutdownDaemonComponents,\n loadConfig,\n buildStatusSnapshot,\n forwardAgentStreamsToIdeInstance,\n SessionHostPtyTransportFactory,\n type DaemonComponents,\n type HostedCliRuntimeDescriptor,\n type StatusResponse,\n type AgentEntry,\n} from '@adhdev/daemon-core';\nimport {\n ensureSessionHostReady,\n listHostedCliRuntimes,\n proxySessionHostAttach,\n proxySessionHostList,\n} from './session-host.js';\nimport { SessionHostClient, type SessionHostEndpoint, type SessionHostEvent } from '@adhdev/session-host-core';\nimport {\n AdhMuxControlClient,\n getWorkspaceSocketInfo,\n getWorkspaceState,\n requestWorkspaceControl,\n type AdhMuxControlEvent,\n} from '@adhdev/terminal-mux-control/api';\n\n// ─── Constants ───\nconst DEFAULT_PORT = 3847;\nconst STATUS_INTERVAL = 2000;\n\nlet pkgVersion = process.env.ADHDEV_PKG_VERSION || 'unknown';\nif (pkgVersion === 'unknown') {\n try {\n const possiblePaths = [\n path.join(__dirname, '..', 'package.json'),\n path.join(__dirname, 'package.json'),\n ];\n for (const candidate of possiblePaths) {\n try {\n const data = JSON.parse(fs.readFileSync(candidate, 'utf-8'));\n if (data.version) {\n pkgVersion = data.version;\n break;\n }\n } catch { /* noop */ }\n }\n } catch { /* noop */ }\n}\n\n// ─── Types ───\ninterface StandaloneOptions {\n port?: number;\n host?: string;\n publicDir?: string;\n open?: boolean;\n token?: string;\n dev?: boolean;\n}\n\ninterface WsMessage {\n type: string;\n requestId?: string;\n data?: Record<string, any>;\n}\n\n\n// ─── Standalone Server ───\n\nclass StandaloneServer {\n private httpServer: ReturnType<typeof createServer> | null = null;\n private wss: WebSocketServer | null = null;\n private clients = new Set<WebSocket>();\n private authToken: string | null = null;\n private statusTimer: NodeJS.Timeout | null = null;\n private running = false;\n private components: DaemonComponents | null = null;\n private devServer: Awaited<ReturnType<typeof startDaemonDevSupport>> | null = null;\n private sessionHostEndpoint: SessionHostEndpoint | null = null;\n\n async start(options: StandaloneOptions = {}): Promise<void> {\n const port = options.port || DEFAULT_PORT;\n const host = options.host || '127.0.0.1';\n const sessionHostEndpoint = await ensureSessionHostReady();\n this.sessionHostEndpoint = sessionHostEndpoint;\n\n // Auth token setup (opt-in only)\n this.authToken = options.token || process.env.ADHDEV_TOKEN || null;\n\n // Initialize all core components via daemon-core bootstrapper\n this.components = await initDaemonComponents({\n cliManagerDeps: {\n getServerConn: () => null,\n getP2p: () => ({\n broadcastPtyOutput: (key: string, data: string) => {\n if (this.clients.size === 0) return;\n const msg = JSON.stringify({ type: 'pty_output', cliId: key, data });\n for (const client of this.clients) {\n if (client.readyState === 1) { // OPEN\n client.send(msg);\n }\n }\n }\n }),\n onStatusChange: () => this.broadcastStatus(),\n removeAgentTracking: () => {},\n createPtyTransportFactory: ({ runtimeId, providerType, workspace, cliArgs, attachExisting }) => (\n new SessionHostPtyTransportFactory({\n endpoint: sessionHostEndpoint,\n clientId: `daemon-${process.pid}`,\n runtimeId,\n providerType,\n workspace,\n attachExisting,\n meta: {\n cliArgs: cliArgs || [],\n managedBy: 'adhdev-standalone',\n },\n })\n ),\n listHostedCliRuntimes: async (): Promise<HostedCliRuntimeDescriptor[]> => (\n listHostedCliRuntimes(sessionHostEndpoint)\n ),\n },\n onStatusChange: () => this.broadcastStatus(),\n onStreamsUpdated: (ideType: string, streams: any[]) => {\n if (!this.components) return;\n forwardAgentStreamsToIdeInstance(this.components.instanceManager, ideType, streams);\n this.broadcastStatus();\n },\n tickIntervalMs: 3000,\n cdpScanIntervalMs: 15_000,\n });\n\n await this.components.cliManager.restoreHostedSessions();\n\n // DevServer (optional)\n if (options.dev) {\n this.devServer = await startDaemonDevSupport({\n components: this.components,\n logFn: (msg: string) => console.log(msg),\n });\n }\n\n // 5. HTTP Server\n this.httpServer = createServer((req, res) => {\n this.handleHttp(req, res, options.publicDir);\n });\n\n // 6. WebSocket Server (upgrade)\n this.wss = new WebSocketServer({ noServer: true });\n this.httpServer.on('upgrade', (req, socket, head) => {\n const wsUrl = new URL(req.url || '/', `http://${req.headers.host || 'localhost'}`);\n if (wsUrl.pathname === '/ws') {\n // Token auth for WS\n if (this.authToken) {\n const urlToken = wsUrl.searchParams.get('token');\n if (urlToken !== this.authToken) {\n socket.write('HTTP/1.1 401 Unauthorized\\r\\n\\r\\n');\n socket.destroy();\n return;\n }\n }\n this.wss!.handleUpgrade(req, socket, head, (ws) => {\n this.handleWsConnection(ws);\n });\n } else {\n socket.destroy();\n }\n });\n\n // 7. Status broadcast timer\n this.statusTimer = setInterval(() => {\n this.broadcastStatus();\n }, STATUS_INTERVAL);\n\n // 8. Start listening\n this.running = true;\n await new Promise<void>((resolve) => {\n this.httpServer!.listen(port, host, () => {\n resolve();\n });\n });\n\n console.log('');\n console.log('🚀 ADHDev Standalone Server');\n console.log(` http://${host === '0.0.0.0' ? 'localhost' : host}:${port}`);\n console.log(` ws://${host === '0.0.0.0' ? 'localhost' : host}:${port}/ws`);\n if (host === '0.0.0.0') {\n const lanIps = this.getLanIPs();\n for (const ip of lanIps) {\n console.log(` http://${ip}:${port} (LAN)`);\n }\n }\n if (this.authToken) {\n console.log(` 🔑 Token: ${this.authToken}`);\n }\n console.log('');\n\n const cdpCount = [...this.components.cdpManagers.values()].filter(m => m.isConnected).length;\n console.log(` CDP: ${cdpCount > 0 ? `✅ ${cdpCount} connected` : '❌ none'}`);\n console.log(` Providers: ${this.components.providerLoader.getAll().length} loaded`);\n if (options.dev) {\n console.log(` 🛠️ DevConsole: http://127.0.0.1:19280`);\n }\n console.log('');\n console.log(' Press Ctrl+C to stop.');\n console.log('');\n\n // Open browser\n if (options.open !== false) {\n try {\n const open = (await import('open')).default;\n await open(`http://localhost:${port}`);\n } catch { /* noop */ }\n }\n\n // Signal handling\n process.on('SIGINT', () => this.stop());\n process.on('SIGTERM', () => this.stop());\n }\n\n // ─── HTTP Handler ───\n\n private handleHttp(\n req: IncomingMessage,\n res: import('http').ServerResponse,\n publicDir?: string\n ): void {\n const url = req.url || '/';\n const method = req.method || 'GET';\n let sharedSnapshotCache: ReturnType<StandaloneServer['buildSharedSnapshot']> | null = null;\n const getSharedSnapshot = () => {\n if (!sharedSnapshotCache) sharedSnapshotCache = this.buildSharedSnapshot();\n return sharedSnapshotCache;\n };\n\n // CORS\n res.setHeader('Access-Control-Allow-Origin', '*');\n res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS');\n res.setHeader('Access-Control-Allow-Headers', 'Content-Type, Authorization');\n if (method === 'OPTIONS') {\n res.writeHead(204);\n res.end();\n return;\n }\n\n // Token auth for API routes\n if (this.authToken && url.startsWith('/api/')) {\n const authHeader = req.headers['authorization'];\n const bearerToken = authHeader?.startsWith('Bearer ') ? authHeader.slice(7) : null;\n const queryToken = new URL(url, `http://${req.headers.host || 'localhost'}`).searchParams.get('token');\n if (bearerToken !== this.authToken && queryToken !== this.authToken) {\n res.writeHead(401, { 'Content-Type': 'application/json' });\n res.end(JSON.stringify({ error: 'Unauthorized. Provide token via Authorization header or ?token= query.' }));\n return;\n }\n }\n\n // ─── API Routes (v1) ───\n const apiPath = url.startsWith('/api/v1/') ? url.slice(7) : null; // /api/v1/status → /status\n const parsedUrl = new URL(url, `http://${req.headers.host || 'localhost'}`);\n\n if (apiPath === '/status' && method === 'GET') {\n const status = this.getStatus(getSharedSnapshot());\n res.writeHead(200, { 'Content-Type': 'application/json' });\n res.end(JSON.stringify(status));\n return;\n }\n\n if (apiPath?.startsWith('/mux/')) {\n const muxParts = parsedUrl.pathname.replace(/^\\/api\\/v1\\/mux\\//, '').split('/').filter(Boolean);\n const [workspaceSegment, action] = muxParts;\n const workspaceName = workspaceSegment ? decodeURIComponent(workspaceSegment) : '';\n\n if (!workspaceName || !action) {\n res.writeHead(400, { 'Content-Type': 'application/json' });\n res.end(JSON.stringify({ error: 'Invalid mux route' }));\n return;\n }\n\n if (action === 'state' && method === 'GET') {\n void (async () => {\n const result = await getWorkspaceState(workspaceName);\n if (!result?.success || !result.result) {\n res.writeHead(404, { 'Content-Type': 'application/json' });\n res.end(JSON.stringify({ error: result?.error || 'Workspace not available' }));\n return;\n }\n res.writeHead(200, { 'Content-Type': 'application/json' });\n res.end(JSON.stringify(result.result));\n })().catch((error: any) => {\n res.writeHead(500, { 'Content-Type': 'application/json' });\n res.end(JSON.stringify({ error: error?.message || String(error) }));\n });\n return;\n }\n\n if (action === 'socket-info' && method === 'GET') {\n void (async () => {\n const result = await getWorkspaceSocketInfo(workspaceName);\n res.writeHead(200, { 'Content-Type': 'application/json' });\n res.end(JSON.stringify(result));\n })().catch((error: any) => {\n res.writeHead(500, { 'Content-Type': 'application/json' });\n res.end(JSON.stringify({ error: error?.message || String(error) }));\n });\n return;\n }\n\n if (action === 'control' && method === 'POST') {\n let body = '';\n req.on('data', (chunk) => { body += chunk; });\n req.on('end', async () => {\n try {\n const { type, payload } = JSON.parse(body || '{}');\n const result = await requestWorkspaceControl(workspaceName, { type, payload });\n if (!result?.success) {\n res.writeHead(404, { 'Content-Type': 'application/json' });\n res.end(JSON.stringify({ error: result?.error || 'Workspace control unavailable' }));\n return;\n }\n res.writeHead(200, { 'Content-Type': 'application/json' });\n res.end(JSON.stringify(result.result ?? { success: true }));\n } catch (error: any) {\n res.writeHead(400, { 'Content-Type': 'application/json' });\n res.end(JSON.stringify({ error: error?.message || String(error) }));\n }\n });\n return;\n }\n\n if (action === 'events' && method === 'GET') {\n void this.handleMuxEvents(req, res, workspaceName);\n return;\n }\n }\n\n if (apiPath?.startsWith('/runtime/')) {\n const runtimeParts = parsedUrl.pathname.replace(/^\\/api\\/v1\\/runtime\\//, '').split('/').filter(Boolean);\n const [sessionSegment, action] = runtimeParts;\n const sessionId = sessionSegment ? decodeURIComponent(sessionSegment) : '';\n\n if (!sessionId || !action) {\n res.writeHead(400, { 'Content-Type': 'application/json' });\n res.end(JSON.stringify({ error: 'Invalid runtime route' }));\n return;\n }\n\n if (action === 'snapshot' && method === 'GET') {\n void (async () => {\n const client = new SessionHostClient({ endpoint: this.sessionHostEndpoint || undefined });\n try {\n const snapshot = await client.request<{ seq: number; text: string; truncated: boolean }>({\n type: 'get_snapshot',\n payload: { sessionId },\n });\n if (!snapshot.success || !snapshot.result) {\n res.writeHead(404, { 'Content-Type': 'application/json' });\n res.end(JSON.stringify({ error: snapshot.error || 'Runtime snapshot unavailable' }));\n return;\n }\n res.writeHead(200, { 'Content-Type': 'application/json' });\n res.end(JSON.stringify({ sessionId, ...snapshot.result }));\n } finally {\n await client.close().catch(() => {});\n }\n })().catch((error: any) => {\n res.writeHead(500, { 'Content-Type': 'application/json' });\n res.end(JSON.stringify({ error: error?.message || String(error) }));\n });\n return;\n }\n\n if (action === 'events' && method === 'GET') {\n void this.handleRuntimeEvents(req, res, sessionId);\n return;\n }\n\n }\n\n if (apiPath === '/command' && method === 'POST') {\n let body = '';\n req.on('data', (chunk) => { body += chunk; });\n req.on('end', async () => {\n try {\n const { type, payload } = JSON.parse(body);\n const result = await this.executeCommand(type, payload || {});\n res.writeHead(200, { 'Content-Type': 'application/json' });\n res.end(JSON.stringify(result));\n } catch (e: any) {\n res.writeHead(400, { 'Content-Type': 'application/json' });\n res.end(JSON.stringify({ success: false, error: e.message }));\n }\n });\n return;\n }\n\n // ─── Static Files ───\n if (publicDir) {\n const filePath = url === '/' ? '/index.html' : url;\n const fullPath = path.join(publicDir, filePath);\n if (fs.existsSync(fullPath) && fs.statSync(fullPath).isFile()) {\n const ext = path.extname(fullPath);\n const mimeTypes: Record<string, string> = {\n '.html': 'text/html',\n '.js': 'application/javascript',\n '.css': 'text/css',\n '.json': 'application/json',\n '.png': 'image/png',\n '.svg': 'image/svg+xml',\n '.ico': 'image/x-icon',\n '.woff2': 'font/woff2',\n };\n res.writeHead(200, { 'Content-Type': mimeTypes[ext] || 'application/octet-stream' });\n fs.createReadStream(fullPath).pipe(res);\n return;\n }\n // SPA fallback → index.html\n const indexPath = path.join(publicDir, 'index.html');\n if (fs.existsSync(indexPath) && !url.startsWith('/api/')) {\n res.writeHead(200, { 'Content-Type': 'text/html' });\n fs.createReadStream(indexPath).pipe(res);\n return;\n }\n }\n\n // 404\n res.writeHead(404, { 'Content-Type': 'application/json' });\n res.end(JSON.stringify({ error: 'Not found' }));\n }\n\n private async handleMuxEvents(\n req: IncomingMessage,\n res: import('http').ServerResponse,\n workspaceName: string,\n ): Promise<void> {\n const socketInfo = await getWorkspaceSocketInfo(workspaceName);\n if (!socketInfo.live) {\n res.writeHead(404, { 'Content-Type': 'application/json' });\n res.end(JSON.stringify({ error: 'Workspace control socket unavailable' }));\n return;\n }\n\n const client = new AdhMuxControlClient(workspaceName);\n await client.connect();\n\n res.writeHead(200, {\n 'Content-Type': 'text/event-stream',\n 'Cache-Control': 'no-cache, no-transform',\n Connection: 'keep-alive',\n 'X-Accel-Buffering': 'no',\n });\n\n const writeEvent = (event: AdhMuxControlEvent) => {\n res.write(`event: ${event.type}\\n`);\n res.write(`data: ${JSON.stringify(event)}\\n\\n`);\n };\n\n const initial = await client.request<{ workspaceName: string; workspace: unknown; panes: unknown[] }>({\n type: 'workspace_state',\n });\n if (initial.success && initial.result) {\n writeEvent({\n type: 'workspace_update',\n payload: initial.result as Record<string, unknown>,\n });\n }\n\n const unsubscribe = client.onEvent(writeEvent);\n const heartbeat = setInterval(() => {\n res.write(': ping\\n\\n');\n }, 15000);\n\n const cleanup = () => {\n clearInterval(heartbeat);\n unsubscribe();\n void client.close().catch(() => {});\n };\n\n req.on('close', cleanup);\n req.on('aborted', cleanup);\n }\n\n private async handleRuntimeEvents(\n req: IncomingMessage,\n res: import('http').ServerResponse,\n sessionId: string,\n ): Promise<void> {\n const client = new SessionHostClient({ endpoint: this.sessionHostEndpoint || undefined });\n await client.connect();\n\n res.writeHead(200, {\n 'Content-Type': 'text/event-stream',\n 'Cache-Control': 'no-cache, no-transform',\n Connection: 'keep-alive',\n 'X-Accel-Buffering': 'no',\n });\n\n const snapshot = await client.request<{ seq: number; text: string; truncated: boolean }>({\n type: 'get_snapshot',\n payload: { sessionId },\n });\n if (snapshot.success && snapshot.result) {\n res.write('event: runtime_snapshot\\n');\n res.write(`data: ${JSON.stringify({ sessionId, ...snapshot.result })}\\n\\n`);\n }\n\n const writeEvent = (event: SessionHostEvent) => {\n if (event.sessionId !== sessionId) return;\n res.write(`event: ${event.type}\\n`);\n res.write(`data: ${JSON.stringify(event)}\\n\\n`);\n };\n\n const unsubscribe = client.onEvent(writeEvent);\n const heartbeat = setInterval(() => {\n res.write(': ping\\n\\n');\n }, 15000);\n\n const cleanup = () => {\n clearInterval(heartbeat);\n unsubscribe();\n void client.close().catch(() => {});\n };\n\n req.on('close', cleanup);\n req.on('aborted', cleanup);\n }\n\n // ─── WebSocket Handler ───\n\n private handleWsConnection(ws: WebSocket): void {\n // Max client limit to prevent connection storms\n const MAX_WS_CLIENTS = 10;\n if (this.clients.size >= MAX_WS_CLIENTS) {\n // Close oldest connection\n const oldest = this.clients.values().next().value;\n if (oldest) {\n try { (oldest as WebSocket).close(1000, 'Too many connections'); } catch {}\n this.clients.delete(oldest);\n }\n }\n this.clients.add(ws);\n console.log(`[WS] Client connected (total: ${this.clients.size})`);\n\n // Send initial status immediately\n const status = this.getStatus();\n ws.send(JSON.stringify({ type: 'status', data: status }));\n\n ws.on('message', async (raw) => {\n try {\n const msg: WsMessage = JSON.parse(raw.toString());\n if (msg.type === 'command' && msg.data) {\n const { type, payload } = msg.data;\n const requestId = msg.requestId;\n const result = await this.executeCommand(type, payload || {});\n ws.send(JSON.stringify({ type: 'command_result', requestId, data: result }));\n }\n } catch (e: any) {\n const requestId = (() => { try { return JSON.parse(raw.toString()).requestId; } catch { return undefined; } })();\n ws.send(JSON.stringify({ type: 'error', requestId, data: { message: e.message } }));\n }\n });\n\n ws.on('close', () => {\n this.clients.delete(ws);\n console.log(`[WS] Client disconnected (total: ${this.clients.size})`);\n });\n\n ws.on('error', () => {\n this.clients.delete(ws);\n });\n }\n\n // ─── Core Logic ───\n\n private buildSharedSnapshot() {\n const cfgSnap = loadConfig();\n const machineId = cfgSnap.machineId || 'mach_unknown';\n const allStates = this.components!.instanceManager.collectAllStates();\n\n return buildStatusSnapshot({\n allStates,\n cdpManagers: this.components!.cdpManagers as Map<string, unknown>,\n providerLoader: this.components!.providerLoader,\n detectedIdes: this.components!.detectedIdes.value,\n instanceId: `standalone_${machineId}`,\n version: pkgVersion,\n daemonMode: false,\n });\n }\n\n private getStatus(snapshot: ReturnType<StandaloneServer['buildSharedSnapshot']> = this.buildSharedSnapshot()): StatusResponse {\n const cfgSnap = loadConfig();\n\n return {\n ...snapshot,\n id: snapshot.instanceId,\n daemonMode: false,\n type: 'standalone',\n platform: snapshot.machine.platform,\n hostname: snapshot.machine.hostname,\n userName: cfgSnap.userName || undefined,\n system: {\n cpus: snapshot.machine.cpus,\n totalMem: snapshot.machine.totalMem,\n freeMem: snapshot.machine.freeMem,\n availableMem: snapshot.machine.availableMem,\n loadavg: snapshot.machine.loadavg,\n uptime: snapshot.machine.uptime,\n arch: snapshot.machine.arch,\n },\n };\n }\n\n private async executeCommand(type: string, args: any): Promise<any> {\n if (!this.components) {\n return { success: false, error: 'Components not initialized' };\n }\n const result = await this.components.router.execute(type, args, 'standalone');\n if (type.startsWith('workspace_')) this.broadcastStatus();\n return result;\n }\n\n private broadcastStatus(): void {\n if (this.clients.size === 0) return;\n const status = this.getStatus();\n const msg = JSON.stringify({ type: 'status', data: status });\n const cdpCount = [...this.components!.cdpManagers.values()].filter(m => m.isConnected).length;\n LOG.debug('Broadcast', `status → ${this.clients.size} client(s), ${(status as any).sessions?.length || 0} session(s), ${cdpCount} CDP`);\n for (const client of this.clients) {\n if (client.readyState === WebSocket.OPEN) {\n client.send(msg);\n }\n }\n }\n\n // ─── Network ───\n\n private getLanIPs(): string[] {\n const interfaces = os.networkInterfaces();\n const ips: string[] = [];\n for (const iface of Object.values(interfaces)) {\n if (!iface) continue;\n for (const info of iface) {\n if (info.family === 'IPv4' && !info.internal) {\n ips.push(info.address);\n }\n }\n }\n return ips;\n }\n\n // ─── Lifecycle ───\n\n async stop(): Promise<void> {\n if (!this.running) return;\n this.running = false;\n\n console.log('\\n Shutting down...');\n\n if (this.statusTimer) {\n clearInterval(this.statusTimer);\n this.statusTimer = null;\n }\n\n // Close WS clients\n for (const ws of this.clients) {\n try { ws.close(); } catch { /* noop */ }\n }\n this.clients.clear();\n\n // Close WSS\n if (this.wss) {\n this.wss.close();\n this.wss = null;\n }\n\n // Shutdown core components\n if (this.components) {\n await shutdownDaemonComponents(this.components);\n }\n\n // HTTP server\n if (this.httpServer) {\n this.httpServer.close();\n this.httpServer = null;\n }\n\n console.log(' ✓ ADHDev Standalone stopped.\\n');\n process.exit(0);\n }\n}\n\n// ─── CLI ───\n\nasync function main(): Promise<void> {\n const args = process.argv.slice(2);\n const primaryCommand = args[0] || '';\n if (primaryCommand === 'attach') {\n const target = args[1];\n if (!target) {\n console.error('Usage: adhdev attach <sessionId> [--read-only|--takeover]');\n process.exit(1);\n }\n const readOnly = args.includes('--read-only');\n const takeover = args.includes('--takeover');\n const exitCode = await proxySessionHostAttach(target, { readOnly, takeover });\n process.exit(exitCode);\n }\n if (primaryCommand === 'list' || primaryCommand === 'runtimes') {\n const showAll = args.includes('--all');\n const exitCode = await proxySessionHostList(showAll);\n process.exit(exitCode);\n }\n const options: StandaloneOptions = {};\n\n // Parse simple args\n for (let i = 0; i < args.length; i++) {\n if ((args[i] === '--port' || args[i] === '-p') && args[i + 1]) {\n options.port = parseInt(args[i + 1]);\n i++;\n }\n if (args[i] === '--host' || args[i] === '-H') {\n options.host = '0.0.0.0';\n }\n if (args[i] === '--public' && args[i + 1]) {\n options.publicDir = args[i + 1];\n i++;\n }\n if (args[i] === '--no-open') {\n options.open = false;\n }\n if (args[i] === '--dev') {\n (options as any).dev = true;\n }\n if (args[i] === '--token' && args[i + 1]) {\n options.token = args[i + 1];\n i++;\n }\n if (args[i] === '--help' || args[i] === '-h') {\n console.log(`\nUsage: adhdev-standalone [options]\n adhdev-standalone list [--all]\n adhdev-standalone attach <sessionId> [--read-only|--takeover]\n\nOptions:\n --port, -p <port> Port to run the standalone server on (default: 3847)\n --host, -H Allow external network connections (binds to 0.0.0.0)\n --token <token> Set an authentication token for the dashboard UI\n --dev Enable DevConsole to debug and test providers\n --public <path> Custom path to the web dashboard distribution\n --no-open Do not automatically open the browser on startup\n --help, -h Show this help message\n\nRuntime commands:\n list, runtimes Show hosted CLI runtimes\n attach Attach local terminal to a runtime\n open Open a local terminal window running adhmux for a runtime\n`);\n process.exit(0);\n }\n }\n\n // Try to find web-standalone build\n if (!options.publicDir) {\n const candidates = [\n path.join(__dirname, '../../web-standalone/dist'),\n path.join(__dirname, '../public'),\n path.join(process.cwd(), 'public'),\n ];\n for (const candidate of candidates) {\n if (fs.existsSync(path.join(candidate, 'index.html'))) {\n options.publicDir = candidate;\n break;\n }\n }\n }\n\n const server = new StandaloneServer();\n await server.start(options);\n\n // Keep process alive\n await new Promise<void>(() => {});\n}\n\nmain().catch((e) => {\n console.error('Fatal error:', e);\n process.exit(1);\n});\n","import { spawn } from 'child_process';\nimport {\n SessionHostClient,\n getDefaultSessionHostEndpoint,\n type SessionHostEndpoint,\n type SessionHostRecord,\n} from '@adhdev/session-host-core';\nimport type { HostedCliRuntimeDescriptor } from '@adhdev/daemon-core';\n\nconst STARTUP_TIMEOUT_MS = 8000;\nconst STARTUP_POLL_MS = 200;\nconst SESSION_HOST_APP_NAME = process.env.ADHDEV_SESSION_HOST_NAME || 'adhdev';\n\nasync function canConnect(endpoint: SessionHostEndpoint): Promise<boolean> {\n const client = new SessionHostClient({ endpoint });\n try {\n await client.connect();\n await client.close();\n return true;\n } catch {\n return false;\n }\n}\n\nasync function waitForReady(endpoint: SessionHostEndpoint, timeoutMs = STARTUP_TIMEOUT_MS): Promise<void> {\n const deadline = Date.now() + timeoutMs;\n while (Date.now() < deadline) {\n if (await canConnect(endpoint)) return;\n await new Promise((resolve) => setTimeout(resolve, STARTUP_POLL_MS));\n }\n throw new Error(`Session host did not become ready within ${timeoutMs}ms`);\n}\n\nfunction resolveSessionHostEntry(): string {\n return require.resolve('@adhdev/session-host-daemon');\n}\n\nasync function runSessionHostCli(args: string[]): Promise<number> {\n const entry = resolveSessionHostEntry();\n const child = spawn(process.execPath, [entry, ...args], {\n stdio: 'inherit',\n env: {\n ...process.env,\n ADHDEV_SESSION_HOST_NAME: SESSION_HOST_APP_NAME,\n },\n });\n return await new Promise<number>((resolve, reject) => {\n child.on('error', reject);\n child.on('exit', (code) => resolve(code ?? 0));\n });\n}\n\nexport async function ensureSessionHostReady(): Promise<SessionHostEndpoint> {\n const endpoint = getDefaultSessionHostEndpoint(SESSION_HOST_APP_NAME);\n if (await canConnect(endpoint)) return endpoint;\n\n const entry = resolveSessionHostEntry();\n const child = spawn(process.execPath, [entry], {\n detached: true,\n stdio: 'ignore',\n windowsHide: true,\n });\n child.unref();\n\n await waitForReady(endpoint);\n return endpoint;\n}\n\nexport async function listHostedCliRuntimes(endpoint: SessionHostEndpoint): Promise<HostedCliRuntimeDescriptor[]> {\n const client = new SessionHostClient({ endpoint });\n try {\n const response = await client.request<SessionHostRecord[]>({\n type: 'list_sessions',\n payload: {},\n });\n if (!response.success || !response.result) {\n return [];\n }\n return response.result\n .filter((record) => record.category === 'cli' && ['running', 'interrupted'].includes(record.lifecycle))\n .sort((a, b) => b.lastActivityAt - a.lastActivityAt)\n .map((record) => ({\n runtimeId: record.sessionId,\n runtimeKey: record.runtimeKey,\n displayName: record.displayName,\n workspaceLabel: record.workspaceLabel,\n lifecycle: record.lifecycle,\n recoveryState: typeof record.meta?.runtimeRecoveryState === 'string' ? String(record.meta.runtimeRecoveryState) : null,\n cliType: record.providerType,\n workspace: record.workspace,\n cliArgs: Array.isArray(record.meta?.cliArgs) ? (record.meta.cliArgs as string[]) : [],\n }));\n } finally {\n await client.close().catch(() => {});\n }\n}\n\nexport async function proxySessionHostList(showAll = false): Promise<number> {\n await ensureSessionHostReady();\n return runSessionHostCli(['list', ...(showAll ? ['--all'] : [])]);\n}\n\nexport async function proxySessionHostAttach(\n target: string,\n options: { readOnly?: boolean; takeover?: boolean } = {},\n): Promise<number> {\n await ensureSessionHostReady();\n const args = ['attach', target];\n if (options.readOnly) args.push('--read-only');\n if (options.takeover) args.push('--takeover');\n return runSessionHostCli(args);\n}\n"],"mappings":"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","names":["import_session_host_core"]}
|
package/package.json
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@adhdev/daemon-standalone",
|
|
3
|
-
"version": "0.7.
|
|
3
|
+
"version": "0.7.7",
|
|
4
4
|
"description": "ADHDev standalone daemon — embedded HTTP/WS server for local dashboard",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"bin": {
|
|
7
|
-
"adhdev-standalone": "./dist/index.js"
|
|
7
|
+
"adhdev-standalone": "./dist/index.js",
|
|
8
|
+
"adhdev": "./dist/index.js"
|
|
8
9
|
},
|
|
9
10
|
"scripts": {
|
|
10
11
|
"build": "tsup",
|
|
@@ -31,6 +32,10 @@
|
|
|
31
32
|
"license": "AGPL-3.0-or-later",
|
|
32
33
|
"dependencies": {
|
|
33
34
|
"@adhdev/daemon-core": "*",
|
|
35
|
+
"@adhdev/session-host-core": "*",
|
|
36
|
+
"@adhdev/session-host-daemon": "*",
|
|
37
|
+
"@adhdev/terminal-mux-cli": "*",
|
|
38
|
+
"@adhdev/terminal-mux-control": "*",
|
|
34
39
|
"open": "^10.1.0",
|
|
35
40
|
"ws": "^8.19.0"
|
|
36
41
|
},
|