adhdev 0.8.11 → 0.8.13
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/cli/index.js +7985 -960
- package/dist/cli/index.js.map +1 -1
- package/dist/index.js +7332 -511
- package/dist/index.js.map +1 -1
- package/package.json +9 -2
- package/vendor/session-host-daemon/index.js +39 -55
- package/vendor/session-host-daemon/index.js.map +1 -1
- package/vendor/session-host-daemon/index.mjs +26 -42
- package/vendor/session-host-daemon/index.mjs.map +1 -1
- package/vendor/session-host-daemon/node_modules/@adhdev/session-host-core/index.d.mts +30 -1
- package/vendor/session-host-daemon/node_modules/@adhdev/session-host-core/index.d.ts +30 -1
- package/vendor/session-host-daemon/node_modules/@adhdev/session-host-core/index.js +73 -6
- package/vendor/session-host-daemon/node_modules/@adhdev/session-host-core/index.js.map +1 -1
- package/vendor/session-host-daemon/node_modules/@adhdev/session-host-core/index.mjs +77 -6
- package/vendor/session-host-daemon/node_modules/@adhdev/session-host-core/index.mjs.map +1 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "adhdev",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.13",
|
|
4
4
|
"description": "ADHDev — Agent Dashboard Hub for Dev. Remote-control AI coding agents from anywhere.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"bin": {
|
|
@@ -55,9 +55,16 @@
|
|
|
55
55
|
"node-pty": "1.2.0-beta.12",
|
|
56
56
|
"open": "^10.1.0",
|
|
57
57
|
"ora": "^8.0.0",
|
|
58
|
-
"sharp": "^0.34.5",
|
|
59
58
|
"ws": "^8.19.0"
|
|
60
59
|
},
|
|
60
|
+
"optionalDependencies": {
|
|
61
|
+
"sharp": "^0.34.5",
|
|
62
|
+
"@img/sharp-win32-x64": "^0.34.5",
|
|
63
|
+
"@img/sharp-darwin-arm64": "^0.34.5",
|
|
64
|
+
"@img/sharp-darwin-x64": "^0.34.5",
|
|
65
|
+
"@img/sharp-linux-x64": "^0.34.5",
|
|
66
|
+
"@img/sharp-linux-arm64": "^0.34.5"
|
|
67
|
+
},
|
|
61
68
|
"devDependencies": {
|
|
62
69
|
"@types/inquirer": "^9.0.0",
|
|
63
70
|
"@types/node": "^22.0.0",
|
|
@@ -37,51 +37,32 @@ module.exports = __toCommonJS(index_exports);
|
|
|
37
37
|
var import_crypto = require("crypto");
|
|
38
38
|
var fs4 = __toESM(require("fs"));
|
|
39
39
|
var os3 = __toESM(require("os"));
|
|
40
|
-
var
|
|
41
|
-
var
|
|
40
|
+
var path2 = __toESM(require("path"));
|
|
41
|
+
var import_session_host_core3 = require("@adhdev/session-host-core");
|
|
42
42
|
|
|
43
43
|
// src/server.ts
|
|
44
44
|
var import_events = require("events");
|
|
45
45
|
var fs3 = __toESM(require("fs"));
|
|
46
46
|
var net = __toESM(require("net"));
|
|
47
|
-
var
|
|
47
|
+
var import_session_host_core2 = require("@adhdev/session-host-core");
|
|
48
48
|
|
|
49
49
|
// src/runtime.ts
|
|
50
50
|
var fs = __toESM(require("fs"));
|
|
51
51
|
var os = __toESM(require("os"));
|
|
52
|
-
var path = __toESM(require("path"));
|
|
53
52
|
var pty = __toESM(require("node-pty"));
|
|
53
|
+
var import_session_host_core = require("@adhdev/session-host-core");
|
|
54
54
|
var terminalMirrorFactory;
|
|
55
55
|
var terminalMirrorWarning = null;
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
if (!(stat.mode & 73)) {
|
|
65
|
-
fs5.chmodSync(helper, stat.mode | 493);
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
} catch {
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
function buildRuntimeEnv(baseEnv, launchEnv) {
|
|
72
|
-
const env = {};
|
|
73
|
-
const source = { ...baseEnv, ...launchEnv || {} };
|
|
74
|
-
for (const [key, value] of Object.entries(source)) {
|
|
75
|
-
if (typeof value !== "string") continue;
|
|
76
|
-
env[key] = value;
|
|
77
|
-
}
|
|
78
|
-
for (const key of Object.keys(env)) {
|
|
79
|
-
if (key === "INIT_CWD" || key === "NO_COLOR" || key === "FORCE_COLOR" || key === "npm_command" || key === "npm_execpath" || key === "npm_node_execpath" || key.startsWith("npm_") || key.startsWith("npm_config_") || key.startsWith("npm_package_") || key.startsWith("npm_lifecycle_") || key.startsWith("PNPM_") || key.startsWith("YARN_") || key.startsWith("BUN_")) {
|
|
80
|
-
delete env[key];
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
return env;
|
|
56
|
+
var terminalMirrorBackendLogged = false;
|
|
57
|
+
(0, import_session_host_core.ensureNodePtySpawnHelperPermissions)((msg) => console.log(`[session-host] ${msg}`));
|
|
58
|
+
function logTerminalMirrorBackend(message, level = "info") {
|
|
59
|
+
if (terminalMirrorBackendLogged) return;
|
|
60
|
+
terminalMirrorBackendLogged = true;
|
|
61
|
+
const prefix = "[session-host]";
|
|
62
|
+
if (level === "warn") console.warn(`${prefix} ${message}`);
|
|
63
|
+
else console.log(`${prefix} ${message}`);
|
|
84
64
|
}
|
|
65
|
+
var buildRuntimeEnv = import_session_host_core.sanitizeSpawnEnv;
|
|
85
66
|
function computeTerminalQueryTail(buffer) {
|
|
86
67
|
const prefixes = ["\x1B[6n", "\x1B[?6n"];
|
|
87
68
|
const maxLength = prefixes.reduce((n, value) => Math.max(n, value.length), 0) - 1;
|
|
@@ -186,15 +167,18 @@ function getTerminalMirrorFactory() {
|
|
|
186
167
|
throw new Error("@adhdev/ghostty-vt-node does not export createTerminal()");
|
|
187
168
|
}
|
|
188
169
|
terminalMirrorFactory = (options) => binding.createTerminal(options);
|
|
170
|
+
logTerminalMirrorBackend("terminal mirror backend=ghostty-vt");
|
|
189
171
|
return terminalMirrorFactory;
|
|
190
172
|
} catch (ghosttyError) {
|
|
191
173
|
try {
|
|
192
174
|
terminalMirrorFactory = createXtermMirror;
|
|
193
175
|
terminalMirrorWarning = `Ghostty VT unavailable; falling back to xterm mirror (${ghosttyError?.message || String(ghosttyError)})`;
|
|
176
|
+
logTerminalMirrorBackend(terminalMirrorWarning, "warn");
|
|
194
177
|
return terminalMirrorFactory;
|
|
195
178
|
} catch (xtermError) {
|
|
196
179
|
terminalMirrorFactory = null;
|
|
197
180
|
terminalMirrorWarning = `No terminal mirror backend available (ghostty: ${ghosttyError?.message || String(ghosttyError)}; xterm: ${xtermError?.message || String(xtermError)})`;
|
|
181
|
+
logTerminalMirrorBackend(terminalMirrorWarning, "warn");
|
|
198
182
|
throw new Error(terminalMirrorWarning);
|
|
199
183
|
}
|
|
200
184
|
}
|
|
@@ -232,7 +216,7 @@ var PtySessionRuntime = class {
|
|
|
232
216
|
}
|
|
233
217
|
}
|
|
234
218
|
this.ptyProcess = pty.spawn(command, args, {
|
|
235
|
-
name:
|
|
219
|
+
name: "xterm-256color",
|
|
236
220
|
cols: this.cols,
|
|
237
221
|
rows: this.rows,
|
|
238
222
|
cwd,
|
|
@@ -292,14 +276,14 @@ var PtySessionRuntime = class {
|
|
|
292
276
|
// src/storage.ts
|
|
293
277
|
var fs2 = __toESM(require("fs"));
|
|
294
278
|
var os2 = __toESM(require("os"));
|
|
295
|
-
var
|
|
279
|
+
var path = __toESM(require("path"));
|
|
296
280
|
var SessionHostStorage = class {
|
|
297
281
|
rootDir;
|
|
298
282
|
runtimesDir;
|
|
299
283
|
constructor(options = {}) {
|
|
300
284
|
const appName = options.appName || "adhdev";
|
|
301
|
-
this.rootDir =
|
|
302
|
-
this.runtimesDir =
|
|
285
|
+
this.rootDir = path.join(os2.homedir(), ".adhdev", "session-host", appName);
|
|
286
|
+
this.runtimesDir = path.join(this.rootDir, "runtimes");
|
|
303
287
|
}
|
|
304
288
|
loadAll() {
|
|
305
289
|
if (!fs2.existsSync(this.runtimesDir)) return [];
|
|
@@ -307,7 +291,7 @@ var SessionHostStorage = class {
|
|
|
307
291
|
const states = [];
|
|
308
292
|
for (const entry of entries) {
|
|
309
293
|
if (!entry.isFile() || !entry.name.endsWith(".json")) continue;
|
|
310
|
-
const fullPath =
|
|
294
|
+
const fullPath = path.join(this.runtimesDir, entry.name);
|
|
311
295
|
try {
|
|
312
296
|
const parsed = JSON.parse(fs2.readFileSync(fullPath, "utf8"));
|
|
313
297
|
if (parsed?.record?.sessionId) {
|
|
@@ -320,7 +304,7 @@ var SessionHostStorage = class {
|
|
|
320
304
|
}
|
|
321
305
|
save(record, snapshot) {
|
|
322
306
|
fs2.mkdirSync(this.runtimesDir, { recursive: true });
|
|
323
|
-
const filePath =
|
|
307
|
+
const filePath = path.join(this.runtimesDir, `${record.sessionId}.json`);
|
|
324
308
|
const payload = {
|
|
325
309
|
record,
|
|
326
310
|
snapshot,
|
|
@@ -329,7 +313,7 @@ var SessionHostStorage = class {
|
|
|
329
313
|
fs2.writeFileSync(filePath, JSON.stringify(payload, null, 2), "utf8");
|
|
330
314
|
}
|
|
331
315
|
remove(sessionId) {
|
|
332
|
-
const filePath =
|
|
316
|
+
const filePath = path.join(this.runtimesDir, `${sessionId}.json`);
|
|
333
317
|
try {
|
|
334
318
|
fs2.unlinkSync(filePath);
|
|
335
319
|
} catch {
|
|
@@ -340,7 +324,7 @@ var SessionHostStorage = class {
|
|
|
340
324
|
// src/server.ts
|
|
341
325
|
var SessionHostServer = class extends import_events.EventEmitter {
|
|
342
326
|
endpoint;
|
|
343
|
-
registry = new
|
|
327
|
+
registry = new import_session_host_core2.SessionHostRegistry();
|
|
344
328
|
runtimes = /* @__PURE__ */ new Map();
|
|
345
329
|
storage;
|
|
346
330
|
ipcServer = null;
|
|
@@ -348,7 +332,7 @@ var SessionHostServer = class extends import_events.EventEmitter {
|
|
|
348
332
|
persistTimers = /* @__PURE__ */ new Map();
|
|
349
333
|
constructor(options = {}) {
|
|
350
334
|
super();
|
|
351
|
-
this.endpoint = options.endpoint || (0,
|
|
335
|
+
this.endpoint = options.endpoint || (0, import_session_host_core2.getDefaultSessionHostEndpoint)(options.appName || "adhdev");
|
|
352
336
|
this.storage = new SessionHostStorage({ appName: options.appName || "adhdev" });
|
|
353
337
|
}
|
|
354
338
|
async start() {
|
|
@@ -363,13 +347,13 @@ var SessionHostServer = class extends import_events.EventEmitter {
|
|
|
363
347
|
socket.on("close", () => {
|
|
364
348
|
this.sockets.delete(socket);
|
|
365
349
|
});
|
|
366
|
-
socket.on("data", (0,
|
|
350
|
+
socket.on("data", (0, import_session_host_core2.createLineParser)((envelope) => {
|
|
367
351
|
if (envelope.kind !== "request") return;
|
|
368
352
|
void this.handleIncomingRequest(socket, envelope);
|
|
369
353
|
}));
|
|
370
354
|
});
|
|
371
|
-
await new Promise((
|
|
372
|
-
this.ipcServer?.once("listening", () =>
|
|
355
|
+
await new Promise((resolve, reject) => {
|
|
356
|
+
this.ipcServer?.once("listening", () => resolve());
|
|
373
357
|
this.ipcServer?.once("error", reject);
|
|
374
358
|
this.ipcServer?.listen(this.endpoint.path);
|
|
375
359
|
});
|
|
@@ -402,7 +386,7 @@ var SessionHostServer = class extends import_events.EventEmitter {
|
|
|
402
386
|
if (this.ipcServer) {
|
|
403
387
|
const server = this.ipcServer;
|
|
404
388
|
this.ipcServer = null;
|
|
405
|
-
await new Promise((
|
|
389
|
+
await new Promise((resolve) => server.close(() => resolve()));
|
|
406
390
|
}
|
|
407
391
|
if (this.endpoint.kind === "unix") {
|
|
408
392
|
try {
|
|
@@ -547,7 +531,7 @@ var SessionHostServer = class extends import_events.EventEmitter {
|
|
|
547
531
|
}
|
|
548
532
|
emitEvent(event) {
|
|
549
533
|
for (const socket of this.sockets) {
|
|
550
|
-
(0,
|
|
534
|
+
(0, import_session_host_core2.writeEnvelope)(socket, {
|
|
551
535
|
kind: "event",
|
|
552
536
|
event
|
|
553
537
|
});
|
|
@@ -556,7 +540,7 @@ var SessionHostServer = class extends import_events.EventEmitter {
|
|
|
556
540
|
}
|
|
557
541
|
async handleIncomingRequest(socket, envelope) {
|
|
558
542
|
const response = await this.handleRequest(envelope.request);
|
|
559
|
-
(0,
|
|
543
|
+
(0, import_session_host_core2.writeEnvelope)(socket, (0, import_session_host_core2.createResponseEnvelope)(envelope.requestId, response));
|
|
560
544
|
}
|
|
561
545
|
schedulePersist(sessionId) {
|
|
562
546
|
const existing = this.persistTimers.get(sessionId);
|
|
@@ -717,9 +701,9 @@ var SessionHostServer = class extends import_events.EventEmitter {
|
|
|
717
701
|
// src/index.ts
|
|
718
702
|
var SESSION_HOST_APP_NAME = process.env.ADHDEV_SESSION_HOST_NAME || "adhdev";
|
|
719
703
|
function getSessionHostPidFile(appName) {
|
|
720
|
-
const dir =
|
|
704
|
+
const dir = path2.join(os3.homedir(), ".adhdev");
|
|
721
705
|
if (!fs4.existsSync(dir)) fs4.mkdirSync(dir, { recursive: true });
|
|
722
|
-
return
|
|
706
|
+
return path2.join(dir, `${appName}-session-host.pid`);
|
|
723
707
|
}
|
|
724
708
|
function writeSessionHostPid(appName) {
|
|
725
709
|
fs4.writeFileSync(getSessionHostPidFile(appName), String(process.pid), "utf8");
|
|
@@ -766,7 +750,7 @@ async function runServer() {
|
|
|
766
750
|
});
|
|
767
751
|
}
|
|
768
752
|
async function listRuntimes(showAll = false) {
|
|
769
|
-
const client = new
|
|
753
|
+
const client = new import_session_host_core3.SessionHostClient({ endpoint: (0, import_session_host_core3.getDefaultSessionHostEndpoint)(SESSION_HOST_APP_NAME) });
|
|
770
754
|
try {
|
|
771
755
|
const response = await client.request({
|
|
772
756
|
type: "list_sessions",
|
|
@@ -785,7 +769,7 @@ async function listRuntimes(showAll = false) {
|
|
|
785
769
|
console.log([
|
|
786
770
|
runtime.runtimeKey,
|
|
787
771
|
runtime.lifecycle,
|
|
788
|
-
(0,
|
|
772
|
+
(0, import_session_host_core3.formatRuntimeOwner)(runtime),
|
|
789
773
|
runtime.workspaceLabel,
|
|
790
774
|
runtime.sessionId,
|
|
791
775
|
runtime.displayName
|
|
@@ -797,7 +781,7 @@ async function listRuntimes(showAll = false) {
|
|
|
797
781
|
}
|
|
798
782
|
}
|
|
799
783
|
async function attachRuntime(target, readOnly = false, takeover = false) {
|
|
800
|
-
const client = new
|
|
784
|
+
const client = new import_session_host_core3.SessionHostClient({ endpoint: (0, import_session_host_core3.getDefaultSessionHostEndpoint)(SESSION_HOST_APP_NAME) });
|
|
801
785
|
const clientId = `local-terminal-${process.pid}-${(0, import_crypto.randomUUID)().slice(0, 8)}`;
|
|
802
786
|
let lastSeq = 0;
|
|
803
787
|
let restoredRawMode = false;
|
|
@@ -892,7 +876,7 @@ async function attachRuntime(target, readOnly = false, takeover = false) {
|
|
|
892
876
|
if (!listResponse.success || !listResponse.result) {
|
|
893
877
|
throw new Error(listResponse.error || "Failed to list runtimes");
|
|
894
878
|
}
|
|
895
|
-
let runtimeRecord = (0,
|
|
879
|
+
let runtimeRecord = (0, import_session_host_core3.resolveRuntimeRecord)(listResponse.result, target);
|
|
896
880
|
runtimeId = runtimeRecord.sessionId;
|
|
897
881
|
if (runtimeRecord.lifecycle === "interrupted" && !readOnly) {
|
|
898
882
|
const resumeResponse = await client.request({
|
|
@@ -1034,13 +1018,13 @@ async function main() {
|
|
|
1034
1018
|
if (!target) {
|
|
1035
1019
|
throw new Error("runtime target is required: adhdev-sessiond resume <runtimeId|runtimeKey>");
|
|
1036
1020
|
}
|
|
1037
|
-
const client = new
|
|
1021
|
+
const client = new import_session_host_core3.SessionHostClient({ endpoint: (0, import_session_host_core3.getDefaultSessionHostEndpoint)(SESSION_HOST_APP_NAME) });
|
|
1038
1022
|
try {
|
|
1039
1023
|
const listResponse = await client.request({ type: "list_sessions", payload: {} });
|
|
1040
1024
|
if (!listResponse.success || !listResponse.result) {
|
|
1041
1025
|
throw new Error(listResponse.error || "Failed to list runtimes");
|
|
1042
1026
|
}
|
|
1043
|
-
const runtimeRecord = (0,
|
|
1027
|
+
const runtimeRecord = (0, import_session_host_core3.resolveRuntimeRecord)(listResponse.result, target);
|
|
1044
1028
|
const resumeResponse = await client.request({
|
|
1045
1029
|
type: "resume_session",
|
|
1046
1030
|
payload: {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/server.ts","../src/runtime.ts","../src/storage.ts"],"sourcesContent":["#!/usr/bin/env node\n\nimport { randomUUID } from 'crypto';\nimport * as fs from 'fs';\nimport * as os from 'os';\nimport * as path from 'path';\nimport {\n SessionHostClient,\n formatRuntimeOwner,\n getDefaultSessionHostEndpoint,\n resolveRuntimeRecord,\n type SessionHostEvent,\n type SessionHostRecord,\n} from '@adhdev/session-host-core';\nimport { SessionHostServer } from './server.js';\n\nexport { SessionHostServer } from './server.js';\nexport type { SessionHostServerOptions } from './server.js';\n\nconst SESSION_HOST_APP_NAME = process.env.ADHDEV_SESSION_HOST_NAME || 'adhdev';\n\nfunction getSessionHostPidFile(appName: string): string {\n const dir = path.join(os.homedir(), '.adhdev');\n if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });\n return path.join(dir, `${appName}-session-host.pid`);\n}\n\nfunction writeSessionHostPid(appName: string): void {\n fs.writeFileSync(getSessionHostPidFile(appName), String(process.pid), 'utf8');\n}\n\nfunction removeSessionHostPid(appName: string): void {\n try {\n fs.unlinkSync(getSessionHostPidFile(appName));\n } catch {\n // noop\n }\n}\n\nfunction parseArgs(argv: string[]) {\n const [command, ...rest] = argv;\n const readOnly = rest.includes('--read-only');\n const takeover = rest.includes('--takeover');\n const showAll = rest.includes('--all');\n const positional = rest.filter((arg) => arg !== '--read-only' && arg !== '--takeover' && arg !== '--all');\n return {\n command: command || 'serve',\n positional,\n readOnly,\n takeover,\n showAll,\n };\n}\n\nasync function runServer(): Promise<void> {\n const server = new SessionHostServer({ appName: SESSION_HOST_APP_NAME });\n writeSessionHostPid(SESSION_HOST_APP_NAME);\n await server.start();\n\n process.on('SIGINT', async () => {\n await server.stop();\n removeSessionHostPid(SESSION_HOST_APP_NAME);\n process.exit(0);\n });\n\n process.on('SIGTERM', async () => {\n await server.stop();\n removeSessionHostPid(SESSION_HOST_APP_NAME);\n process.exit(0);\n });\n\n // Fallback: flush persistence on any exit (covers Windows where SIGTERM is unsupported)\n process.on('exit', () => {\n server.flushAllPersistence();\n removeSessionHostPid(SESSION_HOST_APP_NAME);\n });\n\n // Keep the host alive; IPC transport wiring comes next.\n await new Promise<void>(() => {});\n}\n\nasync function listRuntimes(showAll = false): Promise<void> {\n const client = new SessionHostClient({ endpoint: getDefaultSessionHostEndpoint(SESSION_HOST_APP_NAME) });\n try {\n const response = await client.request<SessionHostRecord[]>({\n type: 'list_sessions',\n payload: {},\n });\n if (!response.success) {\n throw new Error(response.error || 'Failed to list runtimes');\n }\n const runtimes = (response.result || []).filter((runtime: SessionHostRecord) => showAll || runtime.lifecycle !== 'stopped');\n if (runtimes.length === 0) {\n console.log('No runtimes.');\n return;\n }\n console.log('runtimeKey\\tlifecycle\\towner\\tworkspace\\tid\\tdisplayName');\n for (const runtime of runtimes) {\n console.log([\n runtime.runtimeKey,\n runtime.lifecycle,\n formatRuntimeOwner(runtime),\n runtime.workspaceLabel,\n runtime.sessionId,\n runtime.displayName,\n ].join('\\t'));\n }\n } finally {\n await client.close().catch(() => {});\n }\n}\n\nasync function attachRuntime(target: string, readOnly = false, takeover = false): Promise<void> {\n const client = new SessionHostClient({ endpoint: getDefaultSessionHostEndpoint(SESSION_HOST_APP_NAME) });\n const clientId = `local-terminal-${process.pid}-${randomUUID().slice(0, 8)}`;\n let lastSeq = 0;\n let restoredRawMode = false;\n let runtimeId = '';\n let localReadOnly = readOnly;\n\n const cleanup = async () => {\n process.stdout.off('resize', handleResize);\n process.stdin.off('data', handleInput);\n process.stdin.pause();\n if (process.stdin.isTTY && restoredRawMode) {\n process.stdin.setRawMode(false);\n }\n await client.request({\n type: 'release_write',\n payload: {\n sessionId: runtimeId,\n clientId,\n },\n }).catch(() => ({ success: false }));\n await client.request({\n type: 'detach_session',\n payload: {\n sessionId: runtimeId,\n clientId,\n },\n }).catch(() => ({ success: false }));\n await client.close().catch(() => {});\n };\n\n const handleResize = () => {\n void client.request({\n type: 'resize_session',\n payload: {\n sessionId: runtimeId,\n cols: process.stdout.columns || 80,\n rows: process.stdout.rows || 24,\n },\n }).catch(() => ({ success: false }));\n };\n\n const sendInputWithTakeover = async (data: string) => {\n let response = await client.request({\n type: 'send_input',\n payload: {\n sessionId: runtimeId,\n clientId,\n data,\n },\n });\n if (!response.success && response.error?.startsWith('Write owned by ')) {\n const ownerResponse = await client.request<SessionHostRecord>({\n type: 'acquire_write',\n payload: {\n sessionId: runtimeId,\n clientId,\n ownerType: 'user',\n force: true,\n },\n });\n if (ownerResponse.success && ownerResponse.result) {\n response = await client.request({\n type: 'send_input',\n payload: {\n sessionId: runtimeId,\n clientId,\n data,\n },\n });\n if (response.success) {\n process.stderr.write(`Took control of ${ownerResponse.result.runtimeKey}.\\n`);\n }\n }\n }\n return response;\n };\n\n const handleInput = (chunk: Buffer) => {\n if (!localReadOnly && chunk.length === 1 && chunk[0] === 0x1d) {\n void cleanup().finally(() => process.exit(0));\n return;\n }\n if (localReadOnly) return;\n void sendInputWithTakeover(chunk.toString('utf8')).catch(() => ({ success: false }));\n };\n\n try {\n if (readOnly && takeover) {\n throw new Error('Use either --read-only or --takeover, not both');\n }\n\n const listResponse = await client.request<SessionHostRecord[]>({\n type: 'list_sessions',\n payload: {},\n });\n if (!listResponse.success || !listResponse.result) {\n throw new Error(listResponse.error || 'Failed to list runtimes');\n }\n let runtimeRecord = resolveRuntimeRecord(listResponse.result, target);\n runtimeId = runtimeRecord.sessionId;\n\n if (runtimeRecord.lifecycle === 'interrupted' && !readOnly) {\n const resumeResponse = await client.request<SessionHostRecord>({\n type: 'resume_session',\n payload: {\n sessionId: runtimeId,\n },\n });\n if (resumeResponse.success && resumeResponse.result) {\n runtimeRecord = resumeResponse.result;\n } else {\n process.stderr.write(\n `Runtime ${runtimeRecord.runtimeKey} could not be resumed automatically: ${resumeResponse.error || 'unknown error'}\\n`,\n );\n }\n }\n\n let effectiveReadOnly = readOnly;\n if (!effectiveReadOnly && runtimeRecord.writeOwner && runtimeRecord.writeOwner.clientId !== clientId && !takeover) {\n process.stderr.write(\n `Runtime ${runtimeRecord.runtimeKey} is currently owned by ${runtimeRecord.writeOwner.clientId}; first input will take control here.\\n`,\n );\n }\n localReadOnly = effectiveReadOnly;\n\n const attachResponse = await client.request<SessionHostRecord>({\n type: 'attach_session',\n payload: {\n sessionId: runtimeId,\n clientId,\n clientType: 'local-terminal',\n readOnly: effectiveReadOnly,\n },\n });\n if (!attachResponse.success) {\n throw new Error(attachResponse.error || `Failed to attach runtime ${runtimeId}`);\n }\n const attachedRecord = attachResponse.result || null;\n\n if (!effectiveReadOnly && takeover) {\n const ownerResponse = await client.request<SessionHostRecord>({\n type: 'acquire_write',\n payload: {\n sessionId: runtimeId,\n clientId,\n ownerType: 'user',\n force: takeover,\n },\n });\n if (!ownerResponse.success) {\n throw new Error(ownerResponse.error || `Failed to acquire write owner for runtime ${runtimeId}`);\n }\n }\n\n const snapshotResponse = await client.request<{ seq: number; text: string; truncated: boolean; cols?: number; rows?: number }>({\n type: 'get_snapshot',\n payload: { sessionId: runtimeId },\n });\n if (!snapshotResponse.success) {\n throw new Error(snapshotResponse.error || `Failed to read runtime snapshot ${runtimeId}`);\n }\n lastSeq = snapshotResponse.result?.seq || 0;\n if (snapshotResponse.result?.text) {\n process.stdout.write(snapshotResponse.result.text);\n }\n if (attachedRecord?.lifecycle === 'stopped' || attachedRecord?.lifecycle === 'failed' || attachedRecord?.lifecycle === 'interrupted') {\n process.stderr.write(`Runtime ${attachedRecord.runtimeKey} is already ${attachedRecord.lifecycle}. Detached after snapshot.\\n`);\n await cleanup();\n return;\n }\n\n const stopSignals = ['SIGINT', 'SIGTERM', 'SIGHUP'] as const;\n const signalHandlers = stopSignals.map((signal) => {\n const handler = () => {\n void cleanup().finally(() => process.exit(0));\n };\n process.on(signal, handler);\n return { signal, handler };\n });\n\n const unsubscribe = client.onEvent((event: SessionHostEvent) => {\n if (event.sessionId !== runtimeId) return;\n if (event.type === 'session_output') {\n if (event.seq <= lastSeq) return;\n lastSeq = event.seq;\n process.stdout.write(event.data);\n return;\n }\n if (event.type === 'session_exit') {\n void cleanup().finally(() => {\n for (const { signal, handler } of signalHandlers) {\n process.off(signal, handler);\n }\n unsubscribe();\n process.exit(event.exitCode ?? 0);\n });\n }\n });\n\n process.stdout.on('resize', handleResize);\n process.stdin.on('data', handleInput);\n process.stdin.resume();\n if (process.stdin.isTTY) {\n process.stdin.setRawMode(true);\n restoredRawMode = true;\n }\n handleResize();\n if (!effectiveReadOnly) {\n process.stderr.write(`Attached to runtime ${attachedRecord?.runtimeKey || runtimeId}. Press Ctrl+] to detach.\\n`);\n } else {\n process.stderr.write(`Attached to runtime ${attachedRecord?.runtimeKey || runtimeId} (read-only).\\n`);\n }\n await new Promise<void>(() => {});\n } catch (error) {\n await cleanup().catch(() => {});\n throw error;\n }\n}\n\nasync function main(): Promise<void> {\n const { command, positional, readOnly, takeover, showAll } = parseArgs(process.argv.slice(2));\n if (command === 'serve') {\n await runServer();\n return;\n }\n if (command === 'list') {\n await listRuntimes(showAll);\n return;\n }\n if (command === 'attach') {\n const target = positional[0];\n if (!target) {\n throw new Error('runtime target is required: adhdev-sessiond attach <runtimeId|runtimeKey>');\n }\n await attachRuntime(target, readOnly, takeover);\n return;\n }\n if (command === 'resume') {\n const target = positional[0];\n if (!target) {\n throw new Error('runtime target is required: adhdev-sessiond resume <runtimeId|runtimeKey>');\n }\n const client = new SessionHostClient({ endpoint: getDefaultSessionHostEndpoint(SESSION_HOST_APP_NAME) });\n try {\n const listResponse = await client.request<SessionHostRecord[]>({ type: 'list_sessions', payload: {} });\n if (!listResponse.success || !listResponse.result) {\n throw new Error(listResponse.error || 'Failed to list runtimes');\n }\n const runtimeRecord = resolveRuntimeRecord(listResponse.result, target);\n const resumeResponse = await client.request<SessionHostRecord>({\n type: 'resume_session',\n payload: {\n sessionId: runtimeRecord.sessionId,\n },\n });\n if (!resumeResponse.success || !resumeResponse.result) {\n throw new Error(resumeResponse.error || `Failed to resume runtime ${runtimeRecord.runtimeKey}`);\n }\n console.log(`Resumed ${resumeResponse.result.runtimeKey} (${resumeResponse.result.sessionId})`);\n } finally {\n await client.close().catch(() => {});\n }\n return;\n }\n throw new Error(`Unknown command: ${command}`);\n}\n\nif (require.main === module) {\n // Prevent native crashes (e.g. node-pty on Windows) from silently killing the server process\n process.on('uncaughtException', (err) => {\n console.error(`[session-host] Uncaught exception: ${err?.message}\\n${err?.stack || ''}`);\n // Do not exit — keep the server alive for existing sessions\n });\n process.on('unhandledRejection', (reason: any) => {\n console.error(`[session-host] Unhandled rejection: ${reason?.message || reason}`);\n });\n\n void main().catch((error) => {\n console.error(error instanceof Error ? error.message : error);\n process.exit(1);\n });\n}\n","import { EventEmitter } from 'events';\nimport * as fs from 'fs';\nimport * as net from 'net';\nimport {\n SessionHostRegistry,\n createLineParser,\n createResponseEnvelope,\n getDefaultSessionHostEndpoint,\n writeEnvelope,\n} from '@adhdev/session-host-core';\nimport type {\n CreateSessionPayload,\n SessionAttachedClient,\n SessionHostEndpoint,\n SessionHostEvent,\n SessionHostRecord,\n SessionHostRequestEnvelope,\n SessionHostRequest,\n SessionHostResponse,\n} from '@adhdev/session-host-core';\nimport { PtySessionRuntime } from './runtime.js';\nimport { SessionHostStorage, type PersistedRuntimeState } from './storage.js';\n\nexport interface SessionHostServerOptions {\n endpoint?: SessionHostEndpoint;\n appName?: string;\n}\n\nexport class SessionHostServer extends EventEmitter {\n readonly endpoint: SessionHostEndpoint;\n readonly registry = new SessionHostRegistry();\n private runtimes = new Map<string, PtySessionRuntime>();\n private readonly storage: SessionHostStorage;\n private ipcServer: net.Server | null = null;\n private sockets = new Set<net.Socket>();\n private persistTimers = new Map<string, NodeJS.Timeout>();\n\n constructor(options: SessionHostServerOptions = {}) {\n super();\n this.endpoint = options.endpoint || getDefaultSessionHostEndpoint(options.appName || 'adhdev');\n this.storage = new SessionHostStorage({ appName: options.appName || 'adhdev' });\n }\n\n async start(): Promise<void> {\n if (this.endpoint.kind === 'unix') {\n try {\n fs.unlinkSync(this.endpoint.path);\n } catch {\n // noop\n }\n }\n\n this.ipcServer = net.createServer((socket) => {\n this.sockets.add(socket);\n socket.on('close', () => {\n this.sockets.delete(socket);\n });\n socket.on('data', createLineParser((envelope) => {\n if (envelope.kind !== 'request') return;\n void this.handleIncomingRequest(socket, envelope);\n }));\n });\n\n await new Promise<void>((resolve, reject) => {\n this.ipcServer?.once('listening', () => resolve());\n this.ipcServer?.once('error', reject);\n this.ipcServer?.listen(this.endpoint.path);\n });\n\n this.emit('log', `session host endpoint ready: ${this.endpoint.path}`);\n // Do not block readiness on restoring/resuming persisted runtimes.\n // Startup callers only need the IPC endpoint to accept connections.\n setTimeout(() => {\n try {\n this.restorePersistedRuntimes();\n } catch (error: any) {\n this.emit('log', `session host restore failed: ${error?.message || String(error)}`);\n }\n }, 0);\n }\n\n async stop(): Promise<void> {\n this.flushAllPersistence();\n for (const runtime of this.runtimes.values()) {\n try {\n runtime.stop();\n } catch {\n // noop\n }\n }\n this.runtimes.clear();\n for (const timer of this.persistTimers.values()) {\n clearTimeout(timer);\n }\n this.persistTimers.clear();\n for (const socket of this.sockets) {\n socket.destroy();\n }\n this.sockets.clear();\n if (this.ipcServer) {\n const server = this.ipcServer;\n this.ipcServer = null;\n await new Promise<void>((resolve) => server.close(() => resolve()));\n }\n if (this.endpoint.kind === 'unix') {\n try {\n fs.unlinkSync(this.endpoint.path);\n } catch {\n // noop\n }\n }\n this.removeAllListeners();\n }\n\n async handleRequest(request: SessionHostRequest): Promise<SessionHostResponse> {\n try {\n switch (request.type) {\n case 'create_session': {\n const record = this.registry.createSession(request.payload);\n this.schedulePersist(record.sessionId);\n this.emitEvent({ type: 'session_created', sessionId: record.sessionId, record });\n try {\n const startedRecord = this.startRuntime(record, request.payload, 'session_started');\n return { success: true, result: startedRecord };\n } catch (error: any) {\n this.registry.markStopped(record.sessionId, 'failed');\n this.persistNow(record.sessionId);\n return { success: false, error: error?.message || String(error) };\n }\n }\n case 'list_sessions':\n return { success: true, result: this.registry.listSessions() };\n case 'attach_session': {\n const record = this.registry.attachClient(request.payload);\n this.schedulePersist(record.sessionId);\n const client = record.attachedClients.find(item => item.clientId === request.payload.clientId);\n if (client) {\n this.emitEvent({ type: 'client_attached', sessionId: record.sessionId, client });\n }\n return { success: true, result: record };\n }\n case 'detach_session': {\n const record = this.registry.detachClient(request.payload);\n this.schedulePersist(record.sessionId);\n this.emitEvent({ type: 'client_detached', sessionId: record.sessionId, clientId: request.payload.clientId });\n return { success: true, result: record };\n }\n case 'acquire_write': {\n const record = this.registry.acquireWrite(request.payload);\n this.persistNow(record.sessionId);\n this.emitEvent({ type: 'write_owner_changed', sessionId: record.sessionId, owner: record.writeOwner });\n return { success: true, result: record };\n }\n case 'release_write': {\n const record = this.registry.releaseWrite(request.payload);\n this.persistNow(record.sessionId);\n this.emitEvent({ type: 'write_owner_changed', sessionId: record.sessionId, owner: record.writeOwner });\n return { success: true, result: record };\n }\n case 'get_snapshot':\n return { success: true, result: this.getSnapshot(request.payload.sessionId, request.payload.sinceSeq) };\n case 'clear_session_buffer': {\n const record = this.registry.clearBuffer(request.payload.sessionId);\n this.persistNow(record.sessionId);\n this.emitEvent({ type: 'session_cleared', sessionId: record.sessionId });\n return { success: true, result: record };\n }\n case 'update_session_meta': {\n const record = this.registry.updateSessionMeta(\n request.payload.sessionId,\n request.payload.meta || {},\n request.payload.replace === true,\n );\n this.persistNow(record.sessionId);\n return { success: true, result: record };\n }\n case 'send_input': {\n const client = this.getAttachedClient(request.payload.sessionId, request.payload.clientId);\n if (client?.readOnly) {\n return { success: false, error: `Client ${request.payload.clientId} is read-only` };\n }\n const session = this.registry.getSession(request.payload.sessionId);\n if (session?.writeOwner && session.writeOwner.clientId !== request.payload.clientId) {\n return { success: false, error: `Write owned by ${session.writeOwner.clientId}` };\n }\n this.requireRuntime(request.payload.sessionId).write(request.payload.data);\n return { success: true, result: this.registry.getSession(request.payload.sessionId) };\n }\n case 'resize_session': {\n this.requireRuntime(request.payload.sessionId).resize(request.payload.cols, request.payload.rows);\n const record = this.registry.getSession(request.payload.sessionId);\n if (record) {\n this.registry.restoreSession(\n {\n ...record,\n meta: {\n ...(record.meta || {}),\n sessionHostCols: request.payload.cols,\n sessionHostRows: request.payload.rows,\n },\n },\n this.registry.getSnapshot(request.payload.sessionId),\n );\n }\n this.schedulePersist(request.payload.sessionId);\n this.emitEvent({\n type: 'session_resized',\n sessionId: request.payload.sessionId,\n cols: request.payload.cols,\n rows: request.payload.rows,\n });\n return { success: true, result: this.registry.getSession(request.payload.sessionId) };\n }\n case 'stop_session': {\n this.registry.setLifecycle(request.payload.sessionId, 'stopping');\n this.persistNow(request.payload.sessionId);\n this.requireRuntime(request.payload.sessionId).stop();\n this.emitEvent({ type: 'session_stopped', sessionId: request.payload.sessionId });\n return { success: true, result: this.registry.getSession(request.payload.sessionId) };\n }\n case 'resume_session': {\n const existing = this.registry.getSession(request.payload.sessionId);\n if (!existing) {\n return { success: false, error: `Unknown session: ${request.payload.sessionId}` };\n }\n if (this.runtimes.has(request.payload.sessionId)) {\n return { success: true, result: existing };\n }\n const resumed = this.startRuntime(existing, this.buildPayloadFromRecord(existing), 'session_resumed');\n return { success: true, result: resumed };\n }\n default:\n return { success: false, error: `Unsupported session host request: ${(request as { type?: string })?.type || 'unknown'}` };\n }\n } catch (error: any) {\n return { success: false, error: error?.message || String(error) };\n }\n }\n\n private requireRuntime(sessionId: string): PtySessionRuntime {\n const runtime = this.runtimes.get(sessionId);\n if (!runtime) throw new Error(`Runtime not found for session: ${sessionId}`);\n return runtime;\n }\n\n private getAttachedClient(sessionId: string, clientId: string): SessionAttachedClient | null {\n const session = this.registry.getSession(sessionId);\n return session?.attachedClients.find((client) => client.clientId === clientId) || null;\n }\n\n private emitEvent(event: SessionHostEvent): void {\n for (const socket of this.sockets) {\n writeEnvelope(socket, {\n kind: 'event',\n event,\n });\n }\n this.emit('event', event);\n }\n\n private async handleIncomingRequest(socket: net.Socket, envelope: SessionHostRequestEnvelope): Promise<void> {\n const response = await this.handleRequest(envelope.request);\n writeEnvelope(socket, createResponseEnvelope(envelope.requestId, response));\n }\n\n private schedulePersist(sessionId: string): void {\n const existing = this.persistTimers.get(sessionId);\n if (existing) clearTimeout(existing);\n this.persistTimers.set(sessionId, setTimeout(() => {\n this.persistTimers.delete(sessionId);\n this.persistNow(sessionId);\n }, 200));\n }\n\n private persistNow(sessionId: string): void {\n const record = this.registry.getSession(sessionId);\n if (!record) return;\n const snapshot = this.getSnapshot(sessionId);\n this.storage.save(record, snapshot);\n }\n\n private getSnapshot(sessionId: string, sinceSeq?: number) {\n const snapshot = this.registry.getSnapshot(sessionId, sinceSeq);\n const record = this.registry.getSession(sessionId);\n if (typeof sinceSeq === 'number') {\n return {\n ...snapshot,\n cols: typeof record?.meta?.sessionHostCols === 'number' ? (record.meta.sessionHostCols as number) : 80,\n rows: typeof record?.meta?.sessionHostRows === 'number' ? (record.meta.sessionHostRows as number) : 24,\n };\n }\n\n const runtime = this.runtimes.get(sessionId);\n const runtimeText = runtime?.getSnapshotText?.() || '';\n if (!runtimeText) {\n return {\n ...snapshot,\n cols: typeof record?.meta?.sessionHostCols === 'number' ? (record.meta.sessionHostCols as number) : 80,\n rows: typeof record?.meta?.sessionHostRows === 'number' ? (record.meta.sessionHostRows as number) : 24,\n };\n }\n\n return {\n ...snapshot,\n text: runtimeText,\n truncated: false,\n cols: typeof record?.meta?.sessionHostCols === 'number' ? (record.meta.sessionHostCols as number) : 80,\n rows: typeof record?.meta?.sessionHostRows === 'number' ? (record.meta.sessionHostRows as number) : 24,\n };\n }\n\n flushAllPersistence(): void {\n for (const sessionId of this.runtimes.keys()) {\n this.persistNow(sessionId);\n }\n for (const record of this.registry.listSessions()) {\n this.persistNow(record.sessionId);\n }\n }\n\n private restorePersistedRuntimes(): void {\n const states = this.storage.loadAll();\n const runtimesToResume: Array<{\n persisted: PersistedRuntimeState;\n recoveredRecord: SessionHostRecord;\n }> = [];\n let skippedOrphanLiveSessions = 0;\n for (const persisted of states) {\n const wasLiveRuntime = !['stopped', 'failed'].includes(persisted.record.lifecycle);\n const hadAttachedClients = Array.isArray(persisted.record.attachedClients) && persisted.record.attachedClients.length > 0;\n const hadWriteOwner = !!persisted.record.writeOwner;\n const shouldAutoResume = wasLiveRuntime && (hadAttachedClients || hadWriteOwner);\n const recoveredRecord: SessionHostRecord = {\n ...persisted.record,\n attachedClients: [],\n writeOwner: null,\n lifecycle: shouldAutoResume ? 'interrupted' : (wasLiveRuntime ? 'stopped' : persisted.record.lifecycle),\n lastActivityAt: Date.now(),\n meta: {\n ...(persisted.record.meta || {}),\n restoredFromStorage: true,\n runtimeRecoveryState: shouldAutoResume\n ? 'host_restart_interrupted'\n : (wasLiveRuntime ? 'orphan_snapshot' : 'snapshot'),\n runtimeHadAttachedClientsAtCrash: hadAttachedClients,\n runtimeHadWriteOwnerAtCrash: hadWriteOwner,\n },\n };\n this.registry.restoreSession(recoveredRecord, persisted.snapshot);\n this.storage.save(recoveredRecord, persisted.snapshot);\n if (shouldAutoResume) {\n runtimesToResume.push({ persisted, recoveredRecord });\n } else if (wasLiveRuntime) {\n skippedOrphanLiveSessions += 1;\n }\n }\n\n if (skippedOrphanLiveSessions > 0) {\n this.emit('log', `session host skipped ${skippedOrphanLiveSessions} orphan live runtime(s) during restore`);\n }\n\n for (const { persisted, recoveredRecord } of runtimesToResume) {\n try {\n const resumed = this.startRuntime(\n recoveredRecord,\n this.buildPayloadFromRecord(recoveredRecord),\n 'session_resumed',\n );\n const resumedMeta = {\n ...(resumed.meta || {}),\n restoredFromStorage: true,\n runtimeRecoveryState: 'auto_resumed',\n };\n this.registry.restoreSession(\n { ...resumed, meta: resumedMeta },\n this.registry.getSnapshot(resumed.sessionId),\n );\n this.persistNow(resumed.sessionId);\n } catch (error: any) {\n const interrupted = this.registry.setLifecycle(recoveredRecord.sessionId, 'interrupted');\n this.registry.restoreSession({\n ...interrupted,\n meta: {\n ...(interrupted.meta || {}),\n restoredFromStorage: true,\n runtimeRecoveryState: 'resume_failed',\n runtimeRecoveryError: error?.message || String(error),\n },\n }, persisted.snapshot);\n this.persistNow(recoveredRecord.sessionId);\n }\n }\n }\n\n private buildPayloadFromRecord(record: SessionHostRecord): CreateSessionPayload {\n return {\n sessionId: record.sessionId,\n runtimeKey: record.runtimeKey,\n displayName: record.displayName,\n providerType: record.providerType,\n category: record.category,\n workspace: record.workspace,\n launchCommand: record.launchCommand,\n cols: typeof record.meta?.sessionHostCols === 'number' ? (record.meta.sessionHostCols as number) : 80,\n rows: typeof record.meta?.sessionHostRows === 'number' ? (record.meta.sessionHostRows as number) : 24,\n meta: record.meta,\n };\n }\n\n private startRuntime(\n record: SessionHostRecord,\n payload: CreateSessionPayload,\n startEventType: 'session_started' | 'session_resumed',\n ): SessionHostRecord {\n const runtime = new PtySessionRuntime({\n sessionId: record.sessionId,\n payload,\n onData: (data) => {\n const { seq } = this.registry.appendOutput(record.sessionId, data);\n this.schedulePersist(record.sessionId);\n this.emitEvent({ type: 'session_output', sessionId: record.sessionId, seq, data });\n },\n onExit: (exitCode) => {\n this.registry.markStopped(record.sessionId, exitCode === 0 ? 'stopped' : 'failed');\n this.runtimes.delete(record.sessionId);\n this.persistNow(record.sessionId);\n this.emitEvent({ type: 'session_exit', sessionId: record.sessionId, exitCode });\n // Clean up persistence file after a brief delay (allow post-mortem reads)\n setTimeout(() => this.storage.remove(record.sessionId), 5_000);\n },\n });\n\n this.registry.setLifecycle(record.sessionId, 'starting');\n const pid = runtime.start();\n this.runtimes.set(record.sessionId, runtime);\n const startedRecord = this.registry.markStarted(record.sessionId, pid);\n this.persistNow(record.sessionId);\n this.emitEvent({ type: startEventType, sessionId: record.sessionId, pid });\n return startedRecord;\n }\n}\n","import * as fs from 'fs';\nimport * as os from 'os';\nimport * as path from 'path';\nimport * as pty from 'node-pty';\nimport type { IPty } from 'node-pty';\nimport type { CreateSessionPayload } from '@adhdev/session-host-core';\n\ntype TerminalMirrorHandle = {\n write(data: string | Uint8Array): void;\n resize(cols: number, rows: number): void;\n formatVT(): string;\n getCursorPosition(): { col: number; row: number };\n dispose(): void;\n};\n\ntype GhosttyTerminalHandle = {\n write(data: string | Uint8Array): void;\n resize(cols: number, rows: number): void;\n formatVT(): string;\n getCursorPosition(): { col: number; row: number };\n dispose(): void;\n};\n\ntype GhosttyBinding = {\n createTerminal(options: { cols: number; rows: number; scrollback: number }): GhosttyTerminalHandle;\n};\n\ntype XtermBufferLine = {\n translateToString(trimRight?: boolean): string;\n};\n\ntype XtermBuffer = {\n length: number;\n viewportY: number;\n cursorX?: number;\n cursorY?: number;\n getLine(index: number): XtermBufferLine | undefined;\n};\n\ntype XtermTerminal = {\n buffer: { active: XtermBuffer };\n write(data: string, callback?: () => void): void;\n resize(cols: number, rows: number): void;\n dispose(): void;\n};\n\ntype XtermCtor = new (options: { cols: number; rows: number; scrollback: number }) => XtermTerminal;\n\nlet terminalMirrorFactory:\n | ((options: { cols: number; rows: number; scrollback: number }) => TerminalMirrorHandle)\n | null\n | undefined;\nlet terminalMirrorWarning: string | null = null;\n\nif (os.platform() !== 'win32') {\n try {\n const fs = require('fs');\n const ptyDir = path.resolve(path.dirname(require.resolve('node-pty')), '..');\n const platformArch = `${os.platform()}-${os.arch()}`;\n const helper = path.join(ptyDir, 'prebuilds', platformArch, 'spawn-helper');\n if (fs.existsSync(helper)) {\n const stat = fs.statSync(helper);\n if (!(stat.mode & 0o111)) {\n fs.chmodSync(helper, stat.mode | 0o755);\n }\n }\n } catch {\n // best-effort: node-pty still works on most installs without this\n }\n}\n\nexport interface PtyRuntimeOptions {\n sessionId: string;\n payload: CreateSessionPayload;\n onData: (data: string) => void;\n onExit: (exitCode: number | null) => void;\n}\n\nfunction buildRuntimeEnv(baseEnv: NodeJS.ProcessEnv, launchEnv?: Record<string, string>): Record<string, string> {\n const env: Record<string, string> = {};\n const source = { ...baseEnv, ...(launchEnv || {}) } as NodeJS.ProcessEnv;\n\n for (const [key, value] of Object.entries(source)) {\n if (typeof value !== 'string') continue;\n env[key] = value;\n }\n\n for (const key of Object.keys(env)) {\n if (\n key === 'INIT_CWD'\n || key === 'NO_COLOR'\n || key === 'FORCE_COLOR'\n || key === 'npm_command'\n || key === 'npm_execpath'\n || key === 'npm_node_execpath'\n || key.startsWith('npm_')\n || key.startsWith('npm_config_')\n || key.startsWith('npm_package_')\n || key.startsWith('npm_lifecycle_')\n || key.startsWith('PNPM_')\n || key.startsWith('YARN_')\n || key.startsWith('BUN_')\n ) {\n delete env[key];\n }\n }\n\n return env;\n}\n\nfunction computeTerminalQueryTail(buffer: string): string {\n const prefixes = ['\\x1b[6n', '\\x1b[?6n'];\n const maxLength = prefixes.reduce((n, value) => Math.max(n, value.length), 0) - 1;\n const start = Math.max(0, buffer.length - maxLength);\n for (let i = start; i < buffer.length; i++) {\n const suffix = buffer.slice(i);\n if (prefixes.some((pattern) => suffix.length < pattern.length && pattern.startsWith(suffix))) {\n return suffix;\n }\n }\n return '';\n}\n\nfunction formatXtermViewport(terminal: XtermTerminal, rows: number): string {\n const buffer = terminal.buffer.active;\n const start = Math.max(0, buffer.viewportY || 0);\n const end = Math.max(start, Math.min(buffer.length || 0, start + Math.max(1, rows | 0)));\n const lines: string[] = [];\n\n for (let i = start; i < end; i++) {\n const line = buffer.getLine(i);\n lines.push(line ? line.translateToString(true) : '');\n }\n\n let first = 0;\n let last = lines.length;\n while (first < last && !lines[first]?.trim()) first++;\n while (last > first && !lines[last - 1]?.trim()) last--;\n return lines.slice(first, last).join('\\n');\n}\n\nfunction createXtermMirror(options: { cols: number; rows: number; scrollback: number }): TerminalMirrorHandle {\n // eslint-disable-next-line @typescript-eslint/no-var-requires\n const mod = require('@xterm/xterm');\n const Terminal = (mod.Terminal || mod.default?.Terminal || mod.default) as XtermCtor | undefined;\n if (!Terminal) {\n throw new Error('@xterm/xterm Terminal export not found');\n }\n\n let currentRows = Math.max(1, options.rows | 0);\n const terminal = new Terminal({\n cols: Math.max(1, options.cols | 0),\n rows: currentRows,\n scrollback: Math.max(0, options.scrollback | 0),\n });\n\n return {\n write(data: string | Uint8Array): void {\n if (!data) return;\n terminal.write(typeof data === 'string' ? data : Buffer.from(data).toString('utf8'));\n },\n resize(cols: number, rows: number): void {\n currentRows = Math.max(1, rows | 0);\n terminal.resize(Math.max(1, cols | 0), currentRows);\n },\n formatVT(): string {\n return formatXtermViewport(terminal, currentRows);\n },\n getCursorPosition(): { col: number; row: number } {\n const buffer = terminal.buffer.active;\n return {\n col: Math.max(0, buffer.cursorX || 0),\n row: Math.max(0, buffer.cursorY || 0),\n };\n },\n dispose(): void {\n terminal.dispose();\n },\n };\n}\n\nfunction normalizeGhosttyBinding(mod: any): GhosttyBinding | null {\n const raw = mod?.default?.createTerminal ? mod.default : mod?.createTerminal ? mod : null;\n if (!raw) return null;\n\n // Wrap the native handle to fill in any missing methods (pre-built binaries may lack\n // formatVT / getCursorPosition if built before those methods were added to the Rust side).\n return {\n createTerminal(options: { cols: number; rows: number; scrollback: number }): GhosttyTerminalHandle {\n const handle = raw.createTerminal(options) as any;\n return {\n write(data: string | Uint8Array): void { handle.write(data); },\n resize(cols: number, rows: number): void { handle.resize(cols, rows); },\n formatVT(): string {\n if (typeof handle.formatVT === 'function') return handle.formatVT();\n // Fallback: formatPlainText is always available in the shipped bindings\n if (typeof handle.formatPlainText === 'function') return handle.formatPlainText({ trim: false }) as string;\n return '';\n },\n getCursorPosition(): { col: number; row: number } {\n if (typeof handle.getCursorPosition === 'function') return handle.getCursorPosition() as { col: number; row: number };\n return { col: 0, row: 0 };\n },\n dispose(): void { handle.dispose(); },\n };\n },\n };\n}\n\nfunction getTerminalMirrorFactory(): (options: { cols: number; rows: number; scrollback: number }) => TerminalMirrorHandle {\n if (terminalMirrorFactory) return terminalMirrorFactory;\n if (terminalMirrorFactory === null) {\n throw new Error(terminalMirrorWarning || 'No terminal mirror backend available');\n }\n\n try {\n // eslint-disable-next-line @typescript-eslint/no-var-requires\n const ghosttyMod = require('@adhdev/ghostty-vt-node');\n const binding = normalizeGhosttyBinding(ghosttyMod);\n if (!binding) {\n throw new Error('@adhdev/ghostty-vt-node does not export createTerminal()');\n }\n terminalMirrorFactory = (options) => binding.createTerminal(options);\n return terminalMirrorFactory;\n } catch (ghosttyError: any) {\n try {\n terminalMirrorFactory = createXtermMirror;\n terminalMirrorWarning = `Ghostty VT unavailable; falling back to xterm mirror (${ghosttyError?.message || String(ghosttyError)})`;\n return terminalMirrorFactory;\n } catch (xtermError: any) {\n terminalMirrorFactory = null;\n terminalMirrorWarning = `No terminal mirror backend available (ghostty: ${ghosttyError?.message || String(ghosttyError)}; xterm: ${xtermError?.message || String(xtermError)})`;\n throw new Error(terminalMirrorWarning);\n }\n }\n}\n\nexport class PtySessionRuntime {\n readonly sessionId: string;\n readonly payload: CreateSessionPayload;\n readonly cols: number;\n readonly rows: number;\n\n private ptyProcess: IPty | null = null;\n private screenMirror: TerminalMirrorHandle | null = null;\n private pendingQueryScanTail = '';\n private onDataCallback: (data: string) => void;\n private onExitCallback: (exitCode: number | null) => void;\n\n constructor(options: PtyRuntimeOptions) {\n this.sessionId = options.sessionId;\n this.payload = options.payload;\n this.cols = options.payload.cols || 80;\n this.rows = options.payload.rows || 24;\n this.onDataCallback = options.onData;\n this.onExitCallback = options.onExit;\n }\n\n start(): number {\n if (this.ptyProcess) return this.ptyProcess.pid;\n\n const command = this.payload.launchCommand.command;\n const args = this.payload.launchCommand.args || [];\n const env = buildRuntimeEnv(process.env, this.payload.launchCommand.env);\n\n // Validate workspace directory — an invalid cwd causes a native crash on Windows\n // (node-pty error code 267: ERROR_DIRECTORY) that bypasses JS try/catch\n let cwd = this.payload.workspace || process.cwd();\n if (cwd) {\n try {\n const stat = fs.statSync(cwd);\n if (!stat.isDirectory()) cwd = os.homedir();\n } catch {\n cwd = os.homedir();\n }\n }\n\n this.ptyProcess = pty.spawn(command, args, {\n name: os.platform() === 'win32' ? 'xterm-color' : 'xterm-256color',\n cols: this.cols,\n rows: this.rows,\n cwd,\n env,\n });\n this.screenMirror = getTerminalMirrorFactory()({\n cols: this.cols,\n rows: this.rows,\n scrollback: 32768,\n });\n\n this.ptyProcess.onData((data: string) => {\n this.screenMirror?.write(data);\n this.respondToTerminalQueries(data);\n this.onDataCallback(data);\n });\n\n this.ptyProcess.onExit(({ exitCode }) => {\n this.ptyProcess = null;\n this.screenMirror?.dispose();\n this.screenMirror = null;\n this.pendingQueryScanTail = '';\n this.onExitCallback(exitCode ?? null);\n });\n\n return this.ptyProcess.pid;\n }\n\n write(data: string): void {\n if (!this.ptyProcess) throw new Error(`Session not running: ${this.sessionId}`);\n this.ptyProcess.write(data);\n }\n\n resize(cols: number, rows: number): void {\n if (!this.ptyProcess) throw new Error(`Session not running: ${this.sessionId}`);\n this.ptyProcess.resize(cols, rows);\n this.screenMirror?.resize(cols, rows);\n }\n\n stop(): void {\n if (!this.ptyProcess) return;\n this.ptyProcess.kill();\n }\n\n getSnapshotText(): string {\n return this.screenMirror?.formatVT() || '';\n }\n\n private respondToTerminalQueries(data: string): void {\n if (!this.ptyProcess || !this.screenMirror || !data) return;\n\n const combined = this.pendingQueryScanTail + data;\n const regex = /\\x1b\\[(\\?)?6n/g;\n let match: RegExpExecArray | null;\n\n while ((match = regex.exec(combined)) !== null) {\n const cursor = this.screenMirror.getCursorPosition();\n const row = Math.max(1, (cursor.row | 0) + 1);\n const col = Math.max(1, (cursor.col | 0) + 1);\n const response = match[1]\n ? `\\x1b[?${row};${col}R`\n : `\\x1b[${row};${col}R`;\n this.ptyProcess.write(response);\n }\n\n this.pendingQueryScanTail = computeTerminalQueryTail(combined);\n }\n}\n","import * as fs from 'fs';\nimport * as os from 'os';\nimport * as path from 'path';\nimport type { SessionBufferSnapshot, SessionHostRecord } from '@adhdev/session-host-core';\n\nexport interface PersistedRuntimeState {\n record: SessionHostRecord;\n snapshot: SessionBufferSnapshot;\n updatedAt: number;\n}\n\ninterface SessionHostStorageOptions {\n appName?: string;\n}\n\nexport class SessionHostStorage {\n private readonly rootDir: string;\n private readonly runtimesDir: string;\n\n constructor(options: SessionHostStorageOptions = {}) {\n const appName = options.appName || 'adhdev';\n this.rootDir = path.join(os.homedir(), '.adhdev', 'session-host', appName);\n this.runtimesDir = path.join(this.rootDir, 'runtimes');\n }\n\n loadAll(): PersistedRuntimeState[] {\n if (!fs.existsSync(this.runtimesDir)) return [];\n const entries = fs.readdirSync(this.runtimesDir, { withFileTypes: true });\n const states: PersistedRuntimeState[] = [];\n for (const entry of entries) {\n if (!entry.isFile() || !entry.name.endsWith('.json')) continue;\n const fullPath = path.join(this.runtimesDir, entry.name);\n try {\n const parsed = JSON.parse(fs.readFileSync(fullPath, 'utf8')) as PersistedRuntimeState;\n if (parsed?.record?.sessionId) {\n states.push(parsed);\n }\n } catch {\n // Ignore malformed snapshots; host should still boot.\n }\n }\n return states.sort((a, b) => (b.updatedAt || 0) - (a.updatedAt || 0));\n }\n\n save(record: SessionHostRecord, snapshot: SessionBufferSnapshot): void {\n fs.mkdirSync(this.runtimesDir, { recursive: true });\n const filePath = path.join(this.runtimesDir, `${record.sessionId}.json`);\n const payload: PersistedRuntimeState = {\n record,\n snapshot,\n updatedAt: Date.now(),\n };\n fs.writeFileSync(filePath, JSON.stringify(payload, null, 2), 'utf8');\n }\n\n remove(sessionId: string): void {\n const filePath = path.join(this.runtimesDir, `${sessionId}.json`);\n try {\n fs.unlinkSync(filePath);\n } catch {\n // File may not exist — ignore.\n }\n }\n}\n"],"mappings":"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","names":["fs","os","path","import_session_host_core","fs","fs","fs","os","path","resolve"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/server.ts","../src/runtime.ts","../src/storage.ts"],"sourcesContent":["#!/usr/bin/env node\n\nimport { randomUUID } from 'crypto';\nimport * as fs from 'fs';\nimport * as os from 'os';\nimport * as path from 'path';\nimport {\n SessionHostClient,\n formatRuntimeOwner,\n getDefaultSessionHostEndpoint,\n resolveRuntimeRecord,\n type SessionHostEvent,\n type SessionHostRecord,\n} from '@adhdev/session-host-core';\nimport { SessionHostServer } from './server.js';\n\nexport { SessionHostServer } from './server.js';\nexport type { SessionHostServerOptions } from './server.js';\n\nconst SESSION_HOST_APP_NAME = process.env.ADHDEV_SESSION_HOST_NAME || 'adhdev';\n\nfunction getSessionHostPidFile(appName: string): string {\n const dir = path.join(os.homedir(), '.adhdev');\n if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });\n return path.join(dir, `${appName}-session-host.pid`);\n}\n\nfunction writeSessionHostPid(appName: string): void {\n fs.writeFileSync(getSessionHostPidFile(appName), String(process.pid), 'utf8');\n}\n\nfunction removeSessionHostPid(appName: string): void {\n try {\n fs.unlinkSync(getSessionHostPidFile(appName));\n } catch {\n // noop\n }\n}\n\nfunction parseArgs(argv: string[]) {\n const [command, ...rest] = argv;\n const readOnly = rest.includes('--read-only');\n const takeover = rest.includes('--takeover');\n const showAll = rest.includes('--all');\n const positional = rest.filter((arg) => arg !== '--read-only' && arg !== '--takeover' && arg !== '--all');\n return {\n command: command || 'serve',\n positional,\n readOnly,\n takeover,\n showAll,\n };\n}\n\nasync function runServer(): Promise<void> {\n const server = new SessionHostServer({ appName: SESSION_HOST_APP_NAME });\n writeSessionHostPid(SESSION_HOST_APP_NAME);\n await server.start();\n\n process.on('SIGINT', async () => {\n await server.stop();\n removeSessionHostPid(SESSION_HOST_APP_NAME);\n process.exit(0);\n });\n\n process.on('SIGTERM', async () => {\n await server.stop();\n removeSessionHostPid(SESSION_HOST_APP_NAME);\n process.exit(0);\n });\n\n // Fallback: flush persistence on any exit (covers Windows where SIGTERM is unsupported)\n process.on('exit', () => {\n server.flushAllPersistence();\n removeSessionHostPid(SESSION_HOST_APP_NAME);\n });\n\n // Keep the host alive; IPC transport wiring comes next.\n await new Promise<void>(() => {});\n}\n\nasync function listRuntimes(showAll = false): Promise<void> {\n const client = new SessionHostClient({ endpoint: getDefaultSessionHostEndpoint(SESSION_HOST_APP_NAME) });\n try {\n const response = await client.request<SessionHostRecord[]>({\n type: 'list_sessions',\n payload: {},\n });\n if (!response.success) {\n throw new Error(response.error || 'Failed to list runtimes');\n }\n const runtimes = (response.result || []).filter((runtime: SessionHostRecord) => showAll || runtime.lifecycle !== 'stopped');\n if (runtimes.length === 0) {\n console.log('No runtimes.');\n return;\n }\n console.log('runtimeKey\\tlifecycle\\towner\\tworkspace\\tid\\tdisplayName');\n for (const runtime of runtimes) {\n console.log([\n runtime.runtimeKey,\n runtime.lifecycle,\n formatRuntimeOwner(runtime),\n runtime.workspaceLabel,\n runtime.sessionId,\n runtime.displayName,\n ].join('\\t'));\n }\n } finally {\n await client.close().catch(() => {});\n }\n}\n\nasync function attachRuntime(target: string, readOnly = false, takeover = false): Promise<void> {\n const client = new SessionHostClient({ endpoint: getDefaultSessionHostEndpoint(SESSION_HOST_APP_NAME) });\n const clientId = `local-terminal-${process.pid}-${randomUUID().slice(0, 8)}`;\n let lastSeq = 0;\n let restoredRawMode = false;\n let runtimeId = '';\n let localReadOnly = readOnly;\n\n const cleanup = async () => {\n process.stdout.off('resize', handleResize);\n process.stdin.off('data', handleInput);\n process.stdin.pause();\n if (process.stdin.isTTY && restoredRawMode) {\n process.stdin.setRawMode(false);\n }\n await client.request({\n type: 'release_write',\n payload: {\n sessionId: runtimeId,\n clientId,\n },\n }).catch(() => ({ success: false }));\n await client.request({\n type: 'detach_session',\n payload: {\n sessionId: runtimeId,\n clientId,\n },\n }).catch(() => ({ success: false }));\n await client.close().catch(() => {});\n };\n\n const handleResize = () => {\n void client.request({\n type: 'resize_session',\n payload: {\n sessionId: runtimeId,\n cols: process.stdout.columns || 80,\n rows: process.stdout.rows || 24,\n },\n }).catch(() => ({ success: false }));\n };\n\n const sendInputWithTakeover = async (data: string) => {\n let response = await client.request({\n type: 'send_input',\n payload: {\n sessionId: runtimeId,\n clientId,\n data,\n },\n });\n if (!response.success && response.error?.startsWith('Write owned by ')) {\n const ownerResponse = await client.request<SessionHostRecord>({\n type: 'acquire_write',\n payload: {\n sessionId: runtimeId,\n clientId,\n ownerType: 'user',\n force: true,\n },\n });\n if (ownerResponse.success && ownerResponse.result) {\n response = await client.request({\n type: 'send_input',\n payload: {\n sessionId: runtimeId,\n clientId,\n data,\n },\n });\n if (response.success) {\n process.stderr.write(`Took control of ${ownerResponse.result.runtimeKey}.\\n`);\n }\n }\n }\n return response;\n };\n\n const handleInput = (chunk: Buffer) => {\n if (!localReadOnly && chunk.length === 1 && chunk[0] === 0x1d) {\n void cleanup().finally(() => process.exit(0));\n return;\n }\n if (localReadOnly) return;\n void sendInputWithTakeover(chunk.toString('utf8')).catch(() => ({ success: false }));\n };\n\n try {\n if (readOnly && takeover) {\n throw new Error('Use either --read-only or --takeover, not both');\n }\n\n const listResponse = await client.request<SessionHostRecord[]>({\n type: 'list_sessions',\n payload: {},\n });\n if (!listResponse.success || !listResponse.result) {\n throw new Error(listResponse.error || 'Failed to list runtimes');\n }\n let runtimeRecord = resolveRuntimeRecord(listResponse.result, target);\n runtimeId = runtimeRecord.sessionId;\n\n if (runtimeRecord.lifecycle === 'interrupted' && !readOnly) {\n const resumeResponse = await client.request<SessionHostRecord>({\n type: 'resume_session',\n payload: {\n sessionId: runtimeId,\n },\n });\n if (resumeResponse.success && resumeResponse.result) {\n runtimeRecord = resumeResponse.result;\n } else {\n process.stderr.write(\n `Runtime ${runtimeRecord.runtimeKey} could not be resumed automatically: ${resumeResponse.error || 'unknown error'}\\n`,\n );\n }\n }\n\n let effectiveReadOnly = readOnly;\n if (!effectiveReadOnly && runtimeRecord.writeOwner && runtimeRecord.writeOwner.clientId !== clientId && !takeover) {\n process.stderr.write(\n `Runtime ${runtimeRecord.runtimeKey} is currently owned by ${runtimeRecord.writeOwner.clientId}; first input will take control here.\\n`,\n );\n }\n localReadOnly = effectiveReadOnly;\n\n const attachResponse = await client.request<SessionHostRecord>({\n type: 'attach_session',\n payload: {\n sessionId: runtimeId,\n clientId,\n clientType: 'local-terminal',\n readOnly: effectiveReadOnly,\n },\n });\n if (!attachResponse.success) {\n throw new Error(attachResponse.error || `Failed to attach runtime ${runtimeId}`);\n }\n const attachedRecord = attachResponse.result || null;\n\n if (!effectiveReadOnly && takeover) {\n const ownerResponse = await client.request<SessionHostRecord>({\n type: 'acquire_write',\n payload: {\n sessionId: runtimeId,\n clientId,\n ownerType: 'user',\n force: takeover,\n },\n });\n if (!ownerResponse.success) {\n throw new Error(ownerResponse.error || `Failed to acquire write owner for runtime ${runtimeId}`);\n }\n }\n\n const snapshotResponse = await client.request<{ seq: number; text: string; truncated: boolean; cols?: number; rows?: number }>({\n type: 'get_snapshot',\n payload: { sessionId: runtimeId },\n });\n if (!snapshotResponse.success) {\n throw new Error(snapshotResponse.error || `Failed to read runtime snapshot ${runtimeId}`);\n }\n lastSeq = snapshotResponse.result?.seq || 0;\n if (snapshotResponse.result?.text) {\n process.stdout.write(snapshotResponse.result.text);\n }\n if (attachedRecord?.lifecycle === 'stopped' || attachedRecord?.lifecycle === 'failed' || attachedRecord?.lifecycle === 'interrupted') {\n process.stderr.write(`Runtime ${attachedRecord.runtimeKey} is already ${attachedRecord.lifecycle}. Detached after snapshot.\\n`);\n await cleanup();\n return;\n }\n\n const stopSignals = ['SIGINT', 'SIGTERM', 'SIGHUP'] as const;\n const signalHandlers = stopSignals.map((signal) => {\n const handler = () => {\n void cleanup().finally(() => process.exit(0));\n };\n process.on(signal, handler);\n return { signal, handler };\n });\n\n const unsubscribe = client.onEvent((event: SessionHostEvent) => {\n if (event.sessionId !== runtimeId) return;\n if (event.type === 'session_output') {\n if (event.seq <= lastSeq) return;\n lastSeq = event.seq;\n process.stdout.write(event.data);\n return;\n }\n if (event.type === 'session_exit') {\n void cleanup().finally(() => {\n for (const { signal, handler } of signalHandlers) {\n process.off(signal, handler);\n }\n unsubscribe();\n process.exit(event.exitCode ?? 0);\n });\n }\n });\n\n process.stdout.on('resize', handleResize);\n process.stdin.on('data', handleInput);\n process.stdin.resume();\n if (process.stdin.isTTY) {\n process.stdin.setRawMode(true);\n restoredRawMode = true;\n }\n handleResize();\n if (!effectiveReadOnly) {\n process.stderr.write(`Attached to runtime ${attachedRecord?.runtimeKey || runtimeId}. Press Ctrl+] to detach.\\n`);\n } else {\n process.stderr.write(`Attached to runtime ${attachedRecord?.runtimeKey || runtimeId} (read-only).\\n`);\n }\n await new Promise<void>(() => {});\n } catch (error) {\n await cleanup().catch(() => {});\n throw error;\n }\n}\n\nasync function main(): Promise<void> {\n const { command, positional, readOnly, takeover, showAll } = parseArgs(process.argv.slice(2));\n if (command === 'serve') {\n await runServer();\n return;\n }\n if (command === 'list') {\n await listRuntimes(showAll);\n return;\n }\n if (command === 'attach') {\n const target = positional[0];\n if (!target) {\n throw new Error('runtime target is required: adhdev-sessiond attach <runtimeId|runtimeKey>');\n }\n await attachRuntime(target, readOnly, takeover);\n return;\n }\n if (command === 'resume') {\n const target = positional[0];\n if (!target) {\n throw new Error('runtime target is required: adhdev-sessiond resume <runtimeId|runtimeKey>');\n }\n const client = new SessionHostClient({ endpoint: getDefaultSessionHostEndpoint(SESSION_HOST_APP_NAME) });\n try {\n const listResponse = await client.request<SessionHostRecord[]>({ type: 'list_sessions', payload: {} });\n if (!listResponse.success || !listResponse.result) {\n throw new Error(listResponse.error || 'Failed to list runtimes');\n }\n const runtimeRecord = resolveRuntimeRecord(listResponse.result, target);\n const resumeResponse = await client.request<SessionHostRecord>({\n type: 'resume_session',\n payload: {\n sessionId: runtimeRecord.sessionId,\n },\n });\n if (!resumeResponse.success || !resumeResponse.result) {\n throw new Error(resumeResponse.error || `Failed to resume runtime ${runtimeRecord.runtimeKey}`);\n }\n console.log(`Resumed ${resumeResponse.result.runtimeKey} (${resumeResponse.result.sessionId})`);\n } finally {\n await client.close().catch(() => {});\n }\n return;\n }\n throw new Error(`Unknown command: ${command}`);\n}\n\nif (require.main === module) {\n // Prevent native crashes (e.g. node-pty on Windows) from silently killing the server process\n process.on('uncaughtException', (err) => {\n console.error(`[session-host] Uncaught exception: ${err?.message}\\n${err?.stack || ''}`);\n // Do not exit — keep the server alive for existing sessions\n });\n process.on('unhandledRejection', (reason: any) => {\n console.error(`[session-host] Unhandled rejection: ${reason?.message || reason}`);\n });\n\n void main().catch((error) => {\n console.error(error instanceof Error ? error.message : error);\n process.exit(1);\n });\n}\n","import { EventEmitter } from 'events';\nimport * as fs from 'fs';\nimport * as net from 'net';\nimport {\n SessionHostRegistry,\n createLineParser,\n createResponseEnvelope,\n getDefaultSessionHostEndpoint,\n writeEnvelope,\n} from '@adhdev/session-host-core';\nimport type {\n CreateSessionPayload,\n SessionAttachedClient,\n SessionHostEndpoint,\n SessionHostEvent,\n SessionHostRecord,\n SessionHostRequestEnvelope,\n SessionHostRequest,\n SessionHostResponse,\n} from '@adhdev/session-host-core';\nimport { PtySessionRuntime } from './runtime.js';\nimport { SessionHostStorage, type PersistedRuntimeState } from './storage.js';\n\nexport interface SessionHostServerOptions {\n endpoint?: SessionHostEndpoint;\n appName?: string;\n}\n\nexport class SessionHostServer extends EventEmitter {\n readonly endpoint: SessionHostEndpoint;\n readonly registry = new SessionHostRegistry();\n private runtimes = new Map<string, PtySessionRuntime>();\n private readonly storage: SessionHostStorage;\n private ipcServer: net.Server | null = null;\n private sockets = new Set<net.Socket>();\n private persistTimers = new Map<string, NodeJS.Timeout>();\n\n constructor(options: SessionHostServerOptions = {}) {\n super();\n this.endpoint = options.endpoint || getDefaultSessionHostEndpoint(options.appName || 'adhdev');\n this.storage = new SessionHostStorage({ appName: options.appName || 'adhdev' });\n }\n\n async start(): Promise<void> {\n if (this.endpoint.kind === 'unix') {\n try {\n fs.unlinkSync(this.endpoint.path);\n } catch {\n // noop\n }\n }\n\n this.ipcServer = net.createServer((socket) => {\n this.sockets.add(socket);\n socket.on('close', () => {\n this.sockets.delete(socket);\n });\n socket.on('data', createLineParser((envelope) => {\n if (envelope.kind !== 'request') return;\n void this.handleIncomingRequest(socket, envelope);\n }));\n });\n\n await new Promise<void>((resolve, reject) => {\n this.ipcServer?.once('listening', () => resolve());\n this.ipcServer?.once('error', reject);\n this.ipcServer?.listen(this.endpoint.path);\n });\n\n this.emit('log', `session host endpoint ready: ${this.endpoint.path}`);\n // Do not block readiness on restoring/resuming persisted runtimes.\n // Startup callers only need the IPC endpoint to accept connections.\n setTimeout(() => {\n try {\n this.restorePersistedRuntimes();\n } catch (error: any) {\n this.emit('log', `session host restore failed: ${error?.message || String(error)}`);\n }\n }, 0);\n }\n\n async stop(): Promise<void> {\n this.flushAllPersistence();\n for (const runtime of this.runtimes.values()) {\n try {\n runtime.stop();\n } catch {\n // noop\n }\n }\n this.runtimes.clear();\n for (const timer of this.persistTimers.values()) {\n clearTimeout(timer);\n }\n this.persistTimers.clear();\n for (const socket of this.sockets) {\n socket.destroy();\n }\n this.sockets.clear();\n if (this.ipcServer) {\n const server = this.ipcServer;\n this.ipcServer = null;\n await new Promise<void>((resolve) => server.close(() => resolve()));\n }\n if (this.endpoint.kind === 'unix') {\n try {\n fs.unlinkSync(this.endpoint.path);\n } catch {\n // noop\n }\n }\n this.removeAllListeners();\n }\n\n async handleRequest(request: SessionHostRequest): Promise<SessionHostResponse> {\n try {\n switch (request.type) {\n case 'create_session': {\n const record = this.registry.createSession(request.payload);\n this.schedulePersist(record.sessionId);\n this.emitEvent({ type: 'session_created', sessionId: record.sessionId, record });\n try {\n const startedRecord = this.startRuntime(record, request.payload, 'session_started');\n return { success: true, result: startedRecord };\n } catch (error: any) {\n this.registry.markStopped(record.sessionId, 'failed');\n this.persistNow(record.sessionId);\n return { success: false, error: error?.message || String(error) };\n }\n }\n case 'list_sessions':\n return { success: true, result: this.registry.listSessions() };\n case 'attach_session': {\n const record = this.registry.attachClient(request.payload);\n this.schedulePersist(record.sessionId);\n const client = record.attachedClients.find(item => item.clientId === request.payload.clientId);\n if (client) {\n this.emitEvent({ type: 'client_attached', sessionId: record.sessionId, client });\n }\n return { success: true, result: record };\n }\n case 'detach_session': {\n const record = this.registry.detachClient(request.payload);\n this.schedulePersist(record.sessionId);\n this.emitEvent({ type: 'client_detached', sessionId: record.sessionId, clientId: request.payload.clientId });\n return { success: true, result: record };\n }\n case 'acquire_write': {\n const record = this.registry.acquireWrite(request.payload);\n this.persistNow(record.sessionId);\n this.emitEvent({ type: 'write_owner_changed', sessionId: record.sessionId, owner: record.writeOwner });\n return { success: true, result: record };\n }\n case 'release_write': {\n const record = this.registry.releaseWrite(request.payload);\n this.persistNow(record.sessionId);\n this.emitEvent({ type: 'write_owner_changed', sessionId: record.sessionId, owner: record.writeOwner });\n return { success: true, result: record };\n }\n case 'get_snapshot':\n return { success: true, result: this.getSnapshot(request.payload.sessionId, request.payload.sinceSeq) };\n case 'clear_session_buffer': {\n const record = this.registry.clearBuffer(request.payload.sessionId);\n this.persistNow(record.sessionId);\n this.emitEvent({ type: 'session_cleared', sessionId: record.sessionId });\n return { success: true, result: record };\n }\n case 'update_session_meta': {\n const record = this.registry.updateSessionMeta(\n request.payload.sessionId,\n request.payload.meta || {},\n request.payload.replace === true,\n );\n this.persistNow(record.sessionId);\n return { success: true, result: record };\n }\n case 'send_input': {\n const client = this.getAttachedClient(request.payload.sessionId, request.payload.clientId);\n if (client?.readOnly) {\n return { success: false, error: `Client ${request.payload.clientId} is read-only` };\n }\n const session = this.registry.getSession(request.payload.sessionId);\n if (session?.writeOwner && session.writeOwner.clientId !== request.payload.clientId) {\n return { success: false, error: `Write owned by ${session.writeOwner.clientId}` };\n }\n this.requireRuntime(request.payload.sessionId).write(request.payload.data);\n return { success: true, result: this.registry.getSession(request.payload.sessionId) };\n }\n case 'resize_session': {\n this.requireRuntime(request.payload.sessionId).resize(request.payload.cols, request.payload.rows);\n const record = this.registry.getSession(request.payload.sessionId);\n if (record) {\n this.registry.restoreSession(\n {\n ...record,\n meta: {\n ...(record.meta || {}),\n sessionHostCols: request.payload.cols,\n sessionHostRows: request.payload.rows,\n },\n },\n this.registry.getSnapshot(request.payload.sessionId),\n );\n }\n this.schedulePersist(request.payload.sessionId);\n this.emitEvent({\n type: 'session_resized',\n sessionId: request.payload.sessionId,\n cols: request.payload.cols,\n rows: request.payload.rows,\n });\n return { success: true, result: this.registry.getSession(request.payload.sessionId) };\n }\n case 'stop_session': {\n this.registry.setLifecycle(request.payload.sessionId, 'stopping');\n this.persistNow(request.payload.sessionId);\n this.requireRuntime(request.payload.sessionId).stop();\n this.emitEvent({ type: 'session_stopped', sessionId: request.payload.sessionId });\n return { success: true, result: this.registry.getSession(request.payload.sessionId) };\n }\n case 'resume_session': {\n const existing = this.registry.getSession(request.payload.sessionId);\n if (!existing) {\n return { success: false, error: `Unknown session: ${request.payload.sessionId}` };\n }\n if (this.runtimes.has(request.payload.sessionId)) {\n return { success: true, result: existing };\n }\n const resumed = this.startRuntime(existing, this.buildPayloadFromRecord(existing), 'session_resumed');\n return { success: true, result: resumed };\n }\n default:\n return { success: false, error: `Unsupported session host request: ${(request as { type?: string })?.type || 'unknown'}` };\n }\n } catch (error: any) {\n return { success: false, error: error?.message || String(error) };\n }\n }\n\n private requireRuntime(sessionId: string): PtySessionRuntime {\n const runtime = this.runtimes.get(sessionId);\n if (!runtime) throw new Error(`Runtime not found for session: ${sessionId}`);\n return runtime;\n }\n\n private getAttachedClient(sessionId: string, clientId: string): SessionAttachedClient | null {\n const session = this.registry.getSession(sessionId);\n return session?.attachedClients.find((client) => client.clientId === clientId) || null;\n }\n\n private emitEvent(event: SessionHostEvent): void {\n for (const socket of this.sockets) {\n writeEnvelope(socket, {\n kind: 'event',\n event,\n });\n }\n this.emit('event', event);\n }\n\n private async handleIncomingRequest(socket: net.Socket, envelope: SessionHostRequestEnvelope): Promise<void> {\n const response = await this.handleRequest(envelope.request);\n writeEnvelope(socket, createResponseEnvelope(envelope.requestId, response));\n }\n\n private schedulePersist(sessionId: string): void {\n const existing = this.persistTimers.get(sessionId);\n if (existing) clearTimeout(existing);\n this.persistTimers.set(sessionId, setTimeout(() => {\n this.persistTimers.delete(sessionId);\n this.persistNow(sessionId);\n }, 200));\n }\n\n private persistNow(sessionId: string): void {\n const record = this.registry.getSession(sessionId);\n if (!record) return;\n const snapshot = this.getSnapshot(sessionId);\n this.storage.save(record, snapshot);\n }\n\n private getSnapshot(sessionId: string, sinceSeq?: number) {\n const snapshot = this.registry.getSnapshot(sessionId, sinceSeq);\n const record = this.registry.getSession(sessionId);\n if (typeof sinceSeq === 'number') {\n return {\n ...snapshot,\n cols: typeof record?.meta?.sessionHostCols === 'number' ? (record.meta.sessionHostCols as number) : 80,\n rows: typeof record?.meta?.sessionHostRows === 'number' ? (record.meta.sessionHostRows as number) : 24,\n };\n }\n\n const runtime = this.runtimes.get(sessionId);\n const runtimeText = runtime?.getSnapshotText?.() || '';\n if (!runtimeText) {\n return {\n ...snapshot,\n cols: typeof record?.meta?.sessionHostCols === 'number' ? (record.meta.sessionHostCols as number) : 80,\n rows: typeof record?.meta?.sessionHostRows === 'number' ? (record.meta.sessionHostRows as number) : 24,\n };\n }\n\n return {\n ...snapshot,\n text: runtimeText,\n truncated: false,\n cols: typeof record?.meta?.sessionHostCols === 'number' ? (record.meta.sessionHostCols as number) : 80,\n rows: typeof record?.meta?.sessionHostRows === 'number' ? (record.meta.sessionHostRows as number) : 24,\n };\n }\n\n flushAllPersistence(): void {\n for (const sessionId of this.runtimes.keys()) {\n this.persistNow(sessionId);\n }\n for (const record of this.registry.listSessions()) {\n this.persistNow(record.sessionId);\n }\n }\n\n private restorePersistedRuntimes(): void {\n const states = this.storage.loadAll();\n const runtimesToResume: Array<{\n persisted: PersistedRuntimeState;\n recoveredRecord: SessionHostRecord;\n }> = [];\n let skippedOrphanLiveSessions = 0;\n for (const persisted of states) {\n const wasLiveRuntime = !['stopped', 'failed'].includes(persisted.record.lifecycle);\n const hadAttachedClients = Array.isArray(persisted.record.attachedClients) && persisted.record.attachedClients.length > 0;\n const hadWriteOwner = !!persisted.record.writeOwner;\n const shouldAutoResume = wasLiveRuntime && (hadAttachedClients || hadWriteOwner);\n const recoveredRecord: SessionHostRecord = {\n ...persisted.record,\n attachedClients: [],\n writeOwner: null,\n lifecycle: shouldAutoResume ? 'interrupted' : (wasLiveRuntime ? 'stopped' : persisted.record.lifecycle),\n lastActivityAt: Date.now(),\n meta: {\n ...(persisted.record.meta || {}),\n restoredFromStorage: true,\n runtimeRecoveryState: shouldAutoResume\n ? 'host_restart_interrupted'\n : (wasLiveRuntime ? 'orphan_snapshot' : 'snapshot'),\n runtimeHadAttachedClientsAtCrash: hadAttachedClients,\n runtimeHadWriteOwnerAtCrash: hadWriteOwner,\n },\n };\n this.registry.restoreSession(recoveredRecord, persisted.snapshot);\n this.storage.save(recoveredRecord, persisted.snapshot);\n if (shouldAutoResume) {\n runtimesToResume.push({ persisted, recoveredRecord });\n } else if (wasLiveRuntime) {\n skippedOrphanLiveSessions += 1;\n }\n }\n\n if (skippedOrphanLiveSessions > 0) {\n this.emit('log', `session host skipped ${skippedOrphanLiveSessions} orphan live runtime(s) during restore`);\n }\n\n for (const { persisted, recoveredRecord } of runtimesToResume) {\n try {\n const resumed = this.startRuntime(\n recoveredRecord,\n this.buildPayloadFromRecord(recoveredRecord),\n 'session_resumed',\n );\n const resumedMeta = {\n ...(resumed.meta || {}),\n restoredFromStorage: true,\n runtimeRecoveryState: 'auto_resumed',\n };\n this.registry.restoreSession(\n { ...resumed, meta: resumedMeta },\n this.registry.getSnapshot(resumed.sessionId),\n );\n this.persistNow(resumed.sessionId);\n } catch (error: any) {\n const interrupted = this.registry.setLifecycle(recoveredRecord.sessionId, 'interrupted');\n this.registry.restoreSession({\n ...interrupted,\n meta: {\n ...(interrupted.meta || {}),\n restoredFromStorage: true,\n runtimeRecoveryState: 'resume_failed',\n runtimeRecoveryError: error?.message || String(error),\n },\n }, persisted.snapshot);\n this.persistNow(recoveredRecord.sessionId);\n }\n }\n }\n\n private buildPayloadFromRecord(record: SessionHostRecord): CreateSessionPayload {\n return {\n sessionId: record.sessionId,\n runtimeKey: record.runtimeKey,\n displayName: record.displayName,\n providerType: record.providerType,\n category: record.category,\n workspace: record.workspace,\n launchCommand: record.launchCommand,\n cols: typeof record.meta?.sessionHostCols === 'number' ? (record.meta.sessionHostCols as number) : 80,\n rows: typeof record.meta?.sessionHostRows === 'number' ? (record.meta.sessionHostRows as number) : 24,\n meta: record.meta,\n };\n }\n\n private startRuntime(\n record: SessionHostRecord,\n payload: CreateSessionPayload,\n startEventType: 'session_started' | 'session_resumed',\n ): SessionHostRecord {\n const runtime = new PtySessionRuntime({\n sessionId: record.sessionId,\n payload,\n onData: (data) => {\n const { seq } = this.registry.appendOutput(record.sessionId, data);\n this.schedulePersist(record.sessionId);\n this.emitEvent({ type: 'session_output', sessionId: record.sessionId, seq, data });\n },\n onExit: (exitCode) => {\n this.registry.markStopped(record.sessionId, exitCode === 0 ? 'stopped' : 'failed');\n this.runtimes.delete(record.sessionId);\n this.persistNow(record.sessionId);\n this.emitEvent({ type: 'session_exit', sessionId: record.sessionId, exitCode });\n // Clean up persistence file after a brief delay (allow post-mortem reads)\n setTimeout(() => this.storage.remove(record.sessionId), 5_000);\n },\n });\n\n this.registry.setLifecycle(record.sessionId, 'starting');\n const pid = runtime.start();\n this.runtimes.set(record.sessionId, runtime);\n const startedRecord = this.registry.markStarted(record.sessionId, pid);\n this.persistNow(record.sessionId);\n this.emitEvent({ type: startEventType, sessionId: record.sessionId, pid });\n return startedRecord;\n }\n}\n","import * as fs from 'fs';\nimport * as os from 'os';\nimport * as path from 'path';\nimport * as pty from 'node-pty';\nimport type { IPty } from 'node-pty';\nimport type { CreateSessionPayload } from '@adhdev/session-host-core';\nimport { sanitizeSpawnEnv, ensureNodePtySpawnHelperPermissions } from '@adhdev/session-host-core';\n\ntype TerminalMirrorHandle = {\n write(data: string | Uint8Array): void;\n resize(cols: number, rows: number): void;\n formatVT(): string;\n getCursorPosition(): { col: number; row: number };\n dispose(): void;\n};\n\ntype GhosttyTerminalHandle = {\n write(data: string | Uint8Array): void;\n resize(cols: number, rows: number): void;\n formatVT(): string;\n getCursorPosition(): { col: number; row: number };\n dispose(): void;\n};\n\ntype GhosttyBinding = {\n createTerminal(options: { cols: number; rows: number; scrollback: number }): GhosttyTerminalHandle;\n};\n\ntype XtermBufferLine = {\n translateToString(trimRight?: boolean): string;\n};\n\ntype XtermBuffer = {\n length: number;\n viewportY: number;\n cursorX?: number;\n cursorY?: number;\n getLine(index: number): XtermBufferLine | undefined;\n};\n\ntype XtermTerminal = {\n buffer: { active: XtermBuffer };\n write(data: string, callback?: () => void): void;\n resize(cols: number, rows: number): void;\n dispose(): void;\n};\n\ntype XtermCtor = new (options: { cols: number; rows: number; scrollback: number }) => XtermTerminal;\n\nlet terminalMirrorFactory:\n | ((options: { cols: number; rows: number; scrollback: number }) => TerminalMirrorHandle)\n | null\n | undefined;\nlet terminalMirrorWarning: string | null = null;\nlet terminalMirrorBackendLogged = false;\n\nensureNodePtySpawnHelperPermissions((msg: string) => console.log(`[session-host] ${msg}`));\n\nfunction logTerminalMirrorBackend(message: string, level: 'info' | 'warn' = 'info'): void {\n if (terminalMirrorBackendLogged) return;\n terminalMirrorBackendLogged = true;\n const prefix = '[session-host]';\n if (level === 'warn') console.warn(`${prefix} ${message}`);\n else console.log(`${prefix} ${message}`);\n}\n\nexport interface PtyRuntimeOptions {\n sessionId: string;\n payload: CreateSessionPayload;\n onData: (data: string) => void;\n onExit: (exitCode: number | null) => void;\n}\n\n// Use shared spawn env sanitizer — alias for backward compat within this file\nconst buildRuntimeEnv = sanitizeSpawnEnv;\n\nfunction computeTerminalQueryTail(buffer: string): string {\n const prefixes = ['\\x1b[6n', '\\x1b[?6n'];\n const maxLength = prefixes.reduce((n, value) => Math.max(n, value.length), 0) - 1;\n const start = Math.max(0, buffer.length - maxLength);\n for (let i = start; i < buffer.length; i++) {\n const suffix = buffer.slice(i);\n if (prefixes.some((pattern) => suffix.length < pattern.length && pattern.startsWith(suffix))) {\n return suffix;\n }\n }\n return '';\n}\n\nfunction formatXtermViewport(terminal: XtermTerminal, rows: number): string {\n const buffer = terminal.buffer.active;\n const start = Math.max(0, buffer.viewportY || 0);\n const end = Math.max(start, Math.min(buffer.length || 0, start + Math.max(1, rows | 0)));\n const lines: string[] = [];\n\n for (let i = start; i < end; i++) {\n const line = buffer.getLine(i);\n lines.push(line ? line.translateToString(true) : '');\n }\n\n let first = 0;\n let last = lines.length;\n while (first < last && !lines[first]?.trim()) first++;\n while (last > first && !lines[last - 1]?.trim()) last--;\n return lines.slice(first, last).join('\\n');\n}\n\nfunction createXtermMirror(options: { cols: number; rows: number; scrollback: number }): TerminalMirrorHandle {\n // eslint-disable-next-line @typescript-eslint/no-var-requires\n const mod = require('@xterm/xterm');\n const Terminal = (mod.Terminal || mod.default?.Terminal || mod.default) as XtermCtor | undefined;\n if (!Terminal) {\n throw new Error('@xterm/xterm Terminal export not found');\n }\n\n let currentRows = Math.max(1, options.rows | 0);\n const terminal = new Terminal({\n cols: Math.max(1, options.cols | 0),\n rows: currentRows,\n scrollback: Math.max(0, options.scrollback | 0),\n });\n\n return {\n write(data: string | Uint8Array): void {\n if (!data) return;\n terminal.write(typeof data === 'string' ? data : Buffer.from(data).toString('utf8'));\n },\n resize(cols: number, rows: number): void {\n currentRows = Math.max(1, rows | 0);\n terminal.resize(Math.max(1, cols | 0), currentRows);\n },\n formatVT(): string {\n return formatXtermViewport(terminal, currentRows);\n },\n getCursorPosition(): { col: number; row: number } {\n const buffer = terminal.buffer.active;\n return {\n col: Math.max(0, buffer.cursorX || 0),\n row: Math.max(0, buffer.cursorY || 0),\n };\n },\n dispose(): void {\n terminal.dispose();\n },\n };\n}\n\nfunction normalizeGhosttyBinding(mod: any): GhosttyBinding | null {\n const raw = mod?.default?.createTerminal ? mod.default : mod?.createTerminal ? mod : null;\n if (!raw) return null;\n\n // Wrap the native handle to fill in any missing methods (pre-built binaries may lack\n // formatVT / getCursorPosition if built before those methods were added to the Rust side).\n return {\n createTerminal(options: { cols: number; rows: number; scrollback: number }): GhosttyTerminalHandle {\n const handle = raw.createTerminal(options) as any;\n return {\n write(data: string | Uint8Array): void { handle.write(data); },\n resize(cols: number, rows: number): void { handle.resize(cols, rows); },\n formatVT(): string {\n if (typeof handle.formatVT === 'function') return handle.formatVT();\n // Fallback: formatPlainText is always available in the shipped bindings\n if (typeof handle.formatPlainText === 'function') return handle.formatPlainText({ trim: false }) as string;\n return '';\n },\n getCursorPosition(): { col: number; row: number } {\n if (typeof handle.getCursorPosition === 'function') return handle.getCursorPosition() as { col: number; row: number };\n return { col: 0, row: 0 };\n },\n dispose(): void { handle.dispose(); },\n };\n },\n };\n}\n\nfunction getTerminalMirrorFactory(): (options: { cols: number; rows: number; scrollback: number }) => TerminalMirrorHandle {\n if (terminalMirrorFactory) return terminalMirrorFactory;\n if (terminalMirrorFactory === null) {\n throw new Error(terminalMirrorWarning || 'No terminal mirror backend available');\n }\n\n try {\n // eslint-disable-next-line @typescript-eslint/no-var-requires\n const ghosttyMod = require('@adhdev/ghostty-vt-node');\n const binding = normalizeGhosttyBinding(ghosttyMod);\n if (!binding) {\n throw new Error('@adhdev/ghostty-vt-node does not export createTerminal()');\n }\n terminalMirrorFactory = (options) => binding.createTerminal(options);\n logTerminalMirrorBackend('terminal mirror backend=ghostty-vt');\n return terminalMirrorFactory;\n } catch (ghosttyError: any) {\n try {\n terminalMirrorFactory = createXtermMirror;\n terminalMirrorWarning = `Ghostty VT unavailable; falling back to xterm mirror (${ghosttyError?.message || String(ghosttyError)})`;\n logTerminalMirrorBackend(terminalMirrorWarning, 'warn');\n return terminalMirrorFactory;\n } catch (xtermError: any) {\n terminalMirrorFactory = null;\n terminalMirrorWarning = `No terminal mirror backend available (ghostty: ${ghosttyError?.message || String(ghosttyError)}; xterm: ${xtermError?.message || String(xtermError)})`;\n logTerminalMirrorBackend(terminalMirrorWarning, 'warn');\n throw new Error(terminalMirrorWarning);\n }\n }\n}\n\nexport class PtySessionRuntime {\n readonly sessionId: string;\n readonly payload: CreateSessionPayload;\n readonly cols: number;\n readonly rows: number;\n\n private ptyProcess: IPty | null = null;\n private screenMirror: TerminalMirrorHandle | null = null;\n private pendingQueryScanTail = '';\n private onDataCallback: (data: string) => void;\n private onExitCallback: (exitCode: number | null) => void;\n\n constructor(options: PtyRuntimeOptions) {\n this.sessionId = options.sessionId;\n this.payload = options.payload;\n this.cols = options.payload.cols || 80;\n this.rows = options.payload.rows || 24;\n this.onDataCallback = options.onData;\n this.onExitCallback = options.onExit;\n }\n\n start(): number {\n if (this.ptyProcess) return this.ptyProcess.pid;\n\n const command = this.payload.launchCommand.command;\n const args = this.payload.launchCommand.args || [];\n const env = buildRuntimeEnv(process.env, this.payload.launchCommand.env);\n\n // Validate workspace directory — an invalid cwd causes a native crash on Windows\n // (node-pty error code 267: ERROR_DIRECTORY) that bypasses JS try/catch\n let cwd = this.payload.workspace || process.cwd();\n if (cwd) {\n try {\n const stat = fs.statSync(cwd);\n if (!stat.isDirectory()) cwd = os.homedir();\n } catch {\n cwd = os.homedir();\n }\n }\n\n this.ptyProcess = pty.spawn(command, args, {\n name: 'xterm-256color',\n cols: this.cols,\n rows: this.rows,\n cwd,\n env,\n });\n this.screenMirror = getTerminalMirrorFactory()({\n cols: this.cols,\n rows: this.rows,\n scrollback: 32768,\n });\n\n this.ptyProcess.onData((data: string) => {\n this.screenMirror?.write(data);\n this.respondToTerminalQueries(data);\n this.onDataCallback(data);\n });\n\n this.ptyProcess.onExit(({ exitCode }) => {\n this.ptyProcess = null;\n this.screenMirror?.dispose();\n this.screenMirror = null;\n this.pendingQueryScanTail = '';\n this.onExitCallback(exitCode ?? null);\n });\n\n return this.ptyProcess.pid;\n }\n\n write(data: string): void {\n if (!this.ptyProcess) throw new Error(`Session not running: ${this.sessionId}`);\n this.ptyProcess.write(data);\n }\n\n resize(cols: number, rows: number): void {\n if (!this.ptyProcess) throw new Error(`Session not running: ${this.sessionId}`);\n this.ptyProcess.resize(cols, rows);\n this.screenMirror?.resize(cols, rows);\n }\n\n stop(): void {\n if (!this.ptyProcess) return;\n this.ptyProcess.kill();\n }\n\n getSnapshotText(): string {\n return this.screenMirror?.formatVT() || '';\n }\n\n private respondToTerminalQueries(data: string): void {\n if (!this.ptyProcess || !this.screenMirror || !data) return;\n\n const combined = this.pendingQueryScanTail + data;\n const regex = /\\x1b\\[(\\?)?6n/g;\n let match: RegExpExecArray | null;\n\n while ((match = regex.exec(combined)) !== null) {\n const cursor = this.screenMirror.getCursorPosition();\n const row = Math.max(1, (cursor.row | 0) + 1);\n const col = Math.max(1, (cursor.col | 0) + 1);\n const response = match[1]\n ? `\\x1b[?${row};${col}R`\n : `\\x1b[${row};${col}R`;\n this.ptyProcess.write(response);\n }\n\n this.pendingQueryScanTail = computeTerminalQueryTail(combined);\n }\n}\n","import * as fs from 'fs';\nimport * as os from 'os';\nimport * as path from 'path';\nimport type { SessionBufferSnapshot, SessionHostRecord } from '@adhdev/session-host-core';\n\nexport interface PersistedRuntimeState {\n record: SessionHostRecord;\n snapshot: SessionBufferSnapshot;\n updatedAt: number;\n}\n\ninterface SessionHostStorageOptions {\n appName?: string;\n}\n\nexport class SessionHostStorage {\n private readonly rootDir: string;\n private readonly runtimesDir: string;\n\n constructor(options: SessionHostStorageOptions = {}) {\n const appName = options.appName || 'adhdev';\n this.rootDir = path.join(os.homedir(), '.adhdev', 'session-host', appName);\n this.runtimesDir = path.join(this.rootDir, 'runtimes');\n }\n\n loadAll(): PersistedRuntimeState[] {\n if (!fs.existsSync(this.runtimesDir)) return [];\n const entries = fs.readdirSync(this.runtimesDir, { withFileTypes: true });\n const states: PersistedRuntimeState[] = [];\n for (const entry of entries) {\n if (!entry.isFile() || !entry.name.endsWith('.json')) continue;\n const fullPath = path.join(this.runtimesDir, entry.name);\n try {\n const parsed = JSON.parse(fs.readFileSync(fullPath, 'utf8')) as PersistedRuntimeState;\n if (parsed?.record?.sessionId) {\n states.push(parsed);\n }\n } catch {\n // Ignore malformed snapshots; host should still boot.\n }\n }\n return states.sort((a, b) => (b.updatedAt || 0) - (a.updatedAt || 0));\n }\n\n save(record: SessionHostRecord, snapshot: SessionBufferSnapshot): void {\n fs.mkdirSync(this.runtimesDir, { recursive: true });\n const filePath = path.join(this.runtimesDir, `${record.sessionId}.json`);\n const payload: PersistedRuntimeState = {\n record,\n snapshot,\n updatedAt: Date.now(),\n };\n fs.writeFileSync(filePath, JSON.stringify(payload, null, 2), 'utf8');\n }\n\n remove(sessionId: string): void {\n const filePath = path.join(this.runtimesDir, `${sessionId}.json`);\n try {\n fs.unlinkSync(filePath);\n } catch {\n // File may not exist — ignore.\n }\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAEA,oBAA2B;AAC3B,IAAAA,MAAoB;AACpB,IAAAC,MAAoB;AACpB,IAAAC,QAAsB;AACtB,IAAAC,4BAOO;;;ACbP,oBAA6B;AAC7B,IAAAC,MAAoB;AACpB,UAAqB;AACrB,IAAAC,4BAMO;;;ACTP,SAAoB;AACpB,SAAoB;AAEpB,UAAqB;AAGrB,+BAAsE;AA2CtE,IAAI;AAIJ,IAAI,wBAAuC;AAC3C,IAAI,8BAA8B;AAAA,IAElC,8DAAoC,CAAC,QAAgB,QAAQ,IAAI,kBAAkB,GAAG,EAAE,CAAC;AAEzF,SAAS,yBAAyB,SAAiB,QAAyB,QAAc;AACxF,MAAI,4BAA6B;AACjC,gCAA8B;AAC9B,QAAM,SAAS;AACf,MAAI,UAAU,OAAQ,SAAQ,KAAK,GAAG,MAAM,IAAI,OAAO,EAAE;AAAA,MACpD,SAAQ,IAAI,GAAG,MAAM,IAAI,OAAO,EAAE;AACzC;AAUA,IAAM,kBAAkB;AAExB,SAAS,yBAAyB,QAAwB;AACxD,QAAM,WAAW,CAAC,WAAW,UAAU;AACvC,QAAM,YAAY,SAAS,OAAO,CAAC,GAAG,UAAU,KAAK,IAAI,GAAG,MAAM,MAAM,GAAG,CAAC,IAAI;AAChF,QAAM,QAAQ,KAAK,IAAI,GAAG,OAAO,SAAS,SAAS;AACnD,WAAS,IAAI,OAAO,IAAI,OAAO,QAAQ,KAAK;AAC1C,UAAM,SAAS,OAAO,MAAM,CAAC;AAC7B,QAAI,SAAS,KAAK,CAAC,YAAY,OAAO,SAAS,QAAQ,UAAU,QAAQ,WAAW,MAAM,CAAC,GAAG;AAC5F,aAAO;AAAA,IACT;AAAA,EACF;AACA,SAAO;AACT;AAEA,SAAS,oBAAoB,UAAyB,MAAsB;AAC1E,QAAM,SAAS,SAAS,OAAO;AAC/B,QAAM,QAAQ,KAAK,IAAI,GAAG,OAAO,aAAa,CAAC;AAC/C,QAAM,MAAM,KAAK,IAAI,OAAO,KAAK,IAAI,OAAO,UAAU,GAAG,QAAQ,KAAK,IAAI,GAAG,OAAO,CAAC,CAAC,CAAC;AACvF,QAAM,QAAkB,CAAC;AAEzB,WAAS,IAAI,OAAO,IAAI,KAAK,KAAK;AAChC,UAAM,OAAO,OAAO,QAAQ,CAAC;AAC7B,UAAM,KAAK,OAAO,KAAK,kBAAkB,IAAI,IAAI,EAAE;AAAA,EACrD;AAEA,MAAI,QAAQ;AACZ,MAAI,OAAO,MAAM;AACjB,SAAO,QAAQ,QAAQ,CAAC,MAAM,KAAK,GAAG,KAAK,EAAG;AAC9C,SAAO,OAAO,SAAS,CAAC,MAAM,OAAO,CAAC,GAAG,KAAK,EAAG;AACjD,SAAO,MAAM,MAAM,OAAO,IAAI,EAAE,KAAK,IAAI;AAC3C;AAEA,SAAS,kBAAkB,SAAmF;AAE5G,QAAM,MAAM,QAAQ,cAAc;AAClC,QAAM,WAAY,IAAI,YAAY,IAAI,SAAS,YAAY,IAAI;AAC/D,MAAI,CAAC,UAAU;AACb,UAAM,IAAI,MAAM,wCAAwC;AAAA,EAC1D;AAEA,MAAI,cAAc,KAAK,IAAI,GAAG,QAAQ,OAAO,CAAC;AAC9C,QAAM,WAAW,IAAI,SAAS;AAAA,IAC5B,MAAM,KAAK,IAAI,GAAG,QAAQ,OAAO,CAAC;AAAA,IAClC,MAAM;AAAA,IACN,YAAY,KAAK,IAAI,GAAG,QAAQ,aAAa,CAAC;AAAA,EAChD,CAAC;AAED,SAAO;AAAA,IACL,MAAM,MAAiC;AACrC,UAAI,CAAC,KAAM;AACX,eAAS,MAAM,OAAO,SAAS,WAAW,OAAO,OAAO,KAAK,IAAI,EAAE,SAAS,MAAM,CAAC;AAAA,IACrF;AAAA,IACA,OAAO,MAAc,MAAoB;AACvC,oBAAc,KAAK,IAAI,GAAG,OAAO,CAAC;AAClC,eAAS,OAAO,KAAK,IAAI,GAAG,OAAO,CAAC,GAAG,WAAW;AAAA,IACpD;AAAA,IACA,WAAmB;AACjB,aAAO,oBAAoB,UAAU,WAAW;AAAA,IAClD;AAAA,IACA,oBAAkD;AAChD,YAAM,SAAS,SAAS,OAAO;AAC/B,aAAO;AAAA,QACL,KAAK,KAAK,IAAI,GAAG,OAAO,WAAW,CAAC;AAAA,QACpC,KAAK,KAAK,IAAI,GAAG,OAAO,WAAW,CAAC;AAAA,MACtC;AAAA,IACF;AAAA,IACA,UAAgB;AACd,eAAS,QAAQ;AAAA,IACnB;AAAA,EACF;AACF;AAEA,SAAS,wBAAwB,KAAiC;AAChE,QAAM,MAAM,KAAK,SAAS,iBAAiB,IAAI,UAAU,KAAK,iBAAiB,MAAM;AACrF,MAAI,CAAC,IAAK,QAAO;AAIjB,SAAO;AAAA,IACL,eAAe,SAAoF;AACjG,YAAM,SAAS,IAAI,eAAe,OAAO;AACzC,aAAO;AAAA,QACL,MAAM,MAAiC;AAAE,iBAAO,MAAM,IAAI;AAAA,QAAG;AAAA,QAC7D,OAAO,MAAc,MAAoB;AAAE,iBAAO,OAAO,MAAM,IAAI;AAAA,QAAG;AAAA,QACtE,WAAmB;AACjB,cAAI,OAAO,OAAO,aAAa,WAAY,QAAO,OAAO,SAAS;AAElE,cAAI,OAAO,OAAO,oBAAoB,WAAY,QAAO,OAAO,gBAAgB,EAAE,MAAM,MAAM,CAAC;AAC/F,iBAAO;AAAA,QACT;AAAA,QACA,oBAAkD;AAChD,cAAI,OAAO,OAAO,sBAAsB,WAAY,QAAO,OAAO,kBAAkB;AACpF,iBAAO,EAAE,KAAK,GAAG,KAAK,EAAE;AAAA,QAC1B;AAAA,QACA,UAAgB;AAAE,iBAAO,QAAQ;AAAA,QAAG;AAAA,MACtC;AAAA,IACF;AAAA,EACF;AACF;AAEA,SAAS,2BAAkH;AACzH,MAAI,sBAAuB,QAAO;AAClC,MAAI,0BAA0B,MAAM;AAClC,UAAM,IAAI,MAAM,yBAAyB,sCAAsC;AAAA,EACjF;AAEA,MAAI;AAEF,UAAM,aAAa,QAAQ,yBAAyB;AACpD,UAAM,UAAU,wBAAwB,UAAU;AAClD,QAAI,CAAC,SAAS;AACZ,YAAM,IAAI,MAAM,0DAA0D;AAAA,IAC5E;AACA,4BAAwB,CAAC,YAAY,QAAQ,eAAe,OAAO;AACnE,6BAAyB,oCAAoC;AAC7D,WAAO;AAAA,EACT,SAAS,cAAmB;AAC1B,QAAI;AACF,8BAAwB;AACxB,8BAAwB,yDAAyD,cAAc,WAAW,OAAO,YAAY,CAAC;AAC9H,+BAAyB,uBAAuB,MAAM;AACtD,aAAO;AAAA,IACT,SAAS,YAAiB;AACxB,8BAAwB;AACxB,8BAAwB,kDAAkD,cAAc,WAAW,OAAO,YAAY,CAAC,YAAY,YAAY,WAAW,OAAO,UAAU,CAAC;AAC5K,+BAAyB,uBAAuB,MAAM;AACtD,YAAM,IAAI,MAAM,qBAAqB;AAAA,IACvC;AAAA,EACF;AACF;AAEO,IAAM,oBAAN,MAAwB;AAAA,EACpB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAED,aAA0B;AAAA,EAC1B,eAA4C;AAAA,EAC5C,uBAAuB;AAAA,EACvB;AAAA,EACA;AAAA,EAER,YAAY,SAA4B;AACtC,SAAK,YAAY,QAAQ;AACzB,SAAK,UAAU,QAAQ;AACvB,SAAK,OAAO,QAAQ,QAAQ,QAAQ;AACpC,SAAK,OAAO,QAAQ,QAAQ,QAAQ;AACpC,SAAK,iBAAiB,QAAQ;AAC9B,SAAK,iBAAiB,QAAQ;AAAA,EAChC;AAAA,EAEA,QAAgB;AACd,QAAI,KAAK,WAAY,QAAO,KAAK,WAAW;AAE5C,UAAM,UAAU,KAAK,QAAQ,cAAc;AAC3C,UAAM,OAAO,KAAK,QAAQ,cAAc,QAAQ,CAAC;AACjD,UAAM,MAAM,gBAAgB,QAAQ,KAAK,KAAK,QAAQ,cAAc,GAAG;AAIvE,QAAI,MAAM,KAAK,QAAQ,aAAa,QAAQ,IAAI;AAChD,QAAI,KAAK;AACP,UAAI;AACF,cAAM,OAAU,YAAS,GAAG;AAC5B,YAAI,CAAC,KAAK,YAAY,EAAG,OAAS,WAAQ;AAAA,MAC5C,QAAQ;AACN,cAAS,WAAQ;AAAA,MACnB;AAAA,IACF;AAEA,SAAK,aAAiB,UAAM,SAAS,MAAM;AAAA,MACzC,MAAM;AAAA,MACN,MAAM,KAAK;AAAA,MACX,MAAM,KAAK;AAAA,MACX;AAAA,MACA;AAAA,IACF,CAAC;AACD,SAAK,eAAe,yBAAyB,EAAE;AAAA,MAC7C,MAAM,KAAK;AAAA,MACX,MAAM,KAAK;AAAA,MACX,YAAY;AAAA,IACd,CAAC;AAED,SAAK,WAAW,OAAO,CAAC,SAAiB;AACvC,WAAK,cAAc,MAAM,IAAI;AAC7B,WAAK,yBAAyB,IAAI;AAClC,WAAK,eAAe,IAAI;AAAA,IAC1B,CAAC;AAED,SAAK,WAAW,OAAO,CAAC,EAAE,SAAS,MAAM;AACvC,WAAK,aAAa;AAClB,WAAK,cAAc,QAAQ;AAC3B,WAAK,eAAe;AACpB,WAAK,uBAAuB;AAC5B,WAAK,eAAe,YAAY,IAAI;AAAA,IACtC,CAAC;AAED,WAAO,KAAK,WAAW;AAAA,EACzB;AAAA,EAEA,MAAM,MAAoB;AACxB,QAAI,CAAC,KAAK,WAAY,OAAM,IAAI,MAAM,wBAAwB,KAAK,SAAS,EAAE;AAC9E,SAAK,WAAW,MAAM,IAAI;AAAA,EAC5B;AAAA,EAEA,OAAO,MAAc,MAAoB;AACvC,QAAI,CAAC,KAAK,WAAY,OAAM,IAAI,MAAM,wBAAwB,KAAK,SAAS,EAAE;AAC9E,SAAK,WAAW,OAAO,MAAM,IAAI;AACjC,SAAK,cAAc,OAAO,MAAM,IAAI;AAAA,EACtC;AAAA,EAEA,OAAa;AACX,QAAI,CAAC,KAAK,WAAY;AACtB,SAAK,WAAW,KAAK;AAAA,EACvB;AAAA,EAEA,kBAA0B;AACxB,WAAO,KAAK,cAAc,SAAS,KAAK;AAAA,EAC1C;AAAA,EAEQ,yBAAyB,MAAoB;AACnD,QAAI,CAAC,KAAK,cAAc,CAAC,KAAK,gBAAgB,CAAC,KAAM;AAErD,UAAM,WAAW,KAAK,uBAAuB;AAC7C,UAAM,QAAQ;AACd,QAAI;AAEJ,YAAQ,QAAQ,MAAM,KAAK,QAAQ,OAAO,MAAM;AAC9C,YAAM,SAAS,KAAK,aAAa,kBAAkB;AACnD,YAAM,MAAM,KAAK,IAAI,IAAI,OAAO,MAAM,KAAK,CAAC;AAC5C,YAAM,MAAM,KAAK,IAAI,IAAI,OAAO,MAAM,KAAK,CAAC;AAC5C,YAAM,WAAW,MAAM,CAAC,IACpB,SAAS,GAAG,IAAI,GAAG,MACnB,QAAQ,GAAG,IAAI,GAAG;AACtB,WAAK,WAAW,MAAM,QAAQ;AAAA,IAChC;AAEA,SAAK,uBAAuB,yBAAyB,QAAQ;AAAA,EAC/D;AACF;;;AC3TA,IAAAC,MAAoB;AACpB,IAAAC,MAAoB;AACpB,WAAsB;AAaf,IAAM,qBAAN,MAAyB;AAAA,EACb;AAAA,EACA;AAAA,EAEjB,YAAY,UAAqC,CAAC,GAAG;AACnD,UAAM,UAAU,QAAQ,WAAW;AACnC,SAAK,UAAe,UAAQ,YAAQ,GAAG,WAAW,gBAAgB,OAAO;AACzE,SAAK,cAAmB,UAAK,KAAK,SAAS,UAAU;AAAA,EACvD;AAAA,EAEA,UAAmC;AACjC,QAAI,CAAI,eAAW,KAAK,WAAW,EAAG,QAAO,CAAC;AAC9C,UAAM,UAAa,gBAAY,KAAK,aAAa,EAAE,eAAe,KAAK,CAAC;AACxE,UAAM,SAAkC,CAAC;AACzC,eAAW,SAAS,SAAS;AAC3B,UAAI,CAAC,MAAM,OAAO,KAAK,CAAC,MAAM,KAAK,SAAS,OAAO,EAAG;AACtD,YAAM,WAAgB,UAAK,KAAK,aAAa,MAAM,IAAI;AACvD,UAAI;AACF,cAAM,SAAS,KAAK,MAAS,iBAAa,UAAU,MAAM,CAAC;AAC3D,YAAI,QAAQ,QAAQ,WAAW;AAC7B,iBAAO,KAAK,MAAM;AAAA,QACpB;AAAA,MACF,QAAQ;AAAA,MAER;AAAA,IACF;AACA,WAAO,OAAO,KAAK,CAAC,GAAG,OAAO,EAAE,aAAa,MAAM,EAAE,aAAa,EAAE;AAAA,EACtE;AAAA,EAEA,KAAK,QAA2B,UAAuC;AACrE,IAAG,cAAU,KAAK,aAAa,EAAE,WAAW,KAAK,CAAC;AAClD,UAAM,WAAgB,UAAK,KAAK,aAAa,GAAG,OAAO,SAAS,OAAO;AACvE,UAAM,UAAiC;AAAA,MACrC;AAAA,MACA;AAAA,MACA,WAAW,KAAK,IAAI;AAAA,IACtB;AACA,IAAG,kBAAc,UAAU,KAAK,UAAU,SAAS,MAAM,CAAC,GAAG,MAAM;AAAA,EACrE;AAAA,EAEA,OAAO,WAAyB;AAC9B,UAAM,WAAgB,UAAK,KAAK,aAAa,GAAG,SAAS,OAAO;AAChE,QAAI;AACF,MAAG,eAAW,QAAQ;AAAA,IACxB,QAAQ;AAAA,IAER;AAAA,EACF;AACF;;;AFnCO,IAAM,oBAAN,cAAgC,2BAAa;AAAA,EACzC;AAAA,EACA,WAAW,IAAI,8CAAoB;AAAA,EACpC,WAAW,oBAAI,IAA+B;AAAA,EACrC;AAAA,EACT,YAA+B;AAAA,EAC/B,UAAU,oBAAI,IAAgB;AAAA,EAC9B,gBAAgB,oBAAI,IAA4B;AAAA,EAExD,YAAY,UAAoC,CAAC,GAAG;AAClD,UAAM;AACN,SAAK,WAAW,QAAQ,gBAAY,yDAA8B,QAAQ,WAAW,QAAQ;AAC7F,SAAK,UAAU,IAAI,mBAAmB,EAAE,SAAS,QAAQ,WAAW,SAAS,CAAC;AAAA,EAChF;AAAA,EAEA,MAAM,QAAuB;AAC3B,QAAI,KAAK,SAAS,SAAS,QAAQ;AACjC,UAAI;AACF,QAAG,eAAW,KAAK,SAAS,IAAI;AAAA,MAClC,QAAQ;AAAA,MAER;AAAA,IACF;AAEA,SAAK,YAAgB,iBAAa,CAAC,WAAW;AAC5C,WAAK,QAAQ,IAAI,MAAM;AACvB,aAAO,GAAG,SAAS,MAAM;AACvB,aAAK,QAAQ,OAAO,MAAM;AAAA,MAC5B,CAAC;AACD,aAAO,GAAG,YAAQ,4CAAiB,CAAC,aAAa;AAC/C,YAAI,SAAS,SAAS,UAAW;AACjC,aAAK,KAAK,sBAAsB,QAAQ,QAAQ;AAAA,MAClD,CAAC,CAAC;AAAA,IACJ,CAAC;AAED,UAAM,IAAI,QAAc,CAAC,SAAS,WAAW;AAC3C,WAAK,WAAW,KAAK,aAAa,MAAM,QAAQ,CAAC;AACjD,WAAK,WAAW,KAAK,SAAS,MAAM;AACpC,WAAK,WAAW,OAAO,KAAK,SAAS,IAAI;AAAA,IAC3C,CAAC;AAED,SAAK,KAAK,OAAO,gCAAgC,KAAK,SAAS,IAAI,EAAE;AAGrE,eAAW,MAAM;AACf,UAAI;AACF,aAAK,yBAAyB;AAAA,MAChC,SAAS,OAAY;AACnB,aAAK,KAAK,OAAO,gCAAgC,OAAO,WAAW,OAAO,KAAK,CAAC,EAAE;AAAA,MACpF;AAAA,IACF,GAAG,CAAC;AAAA,EACN;AAAA,EAEA,MAAM,OAAsB;AAC1B,SAAK,oBAAoB;AACzB,eAAW,WAAW,KAAK,SAAS,OAAO,GAAG;AAC5C,UAAI;AACF,gBAAQ,KAAK;AAAA,MACf,QAAQ;AAAA,MAER;AAAA,IACF;AACA,SAAK,SAAS,MAAM;AACpB,eAAW,SAAS,KAAK,cAAc,OAAO,GAAG;AAC/C,mBAAa,KAAK;AAAA,IACpB;AACA,SAAK,cAAc,MAAM;AACzB,eAAW,UAAU,KAAK,SAAS;AACjC,aAAO,QAAQ;AAAA,IACjB;AACA,SAAK,QAAQ,MAAM;AACnB,QAAI,KAAK,WAAW;AAClB,YAAM,SAAS,KAAK;AACpB,WAAK,YAAY;AACjB,YAAM,IAAI,QAAc,CAAC,YAAY,OAAO,MAAM,MAAM,QAAQ,CAAC,CAAC;AAAA,IACpE;AACA,QAAI,KAAK,SAAS,SAAS,QAAQ;AACjC,UAAI;AACF,QAAG,eAAW,KAAK,SAAS,IAAI;AAAA,MAClC,QAAQ;AAAA,MAER;AAAA,IACF;AACA,SAAK,mBAAmB;AAAA,EAC1B;AAAA,EAEA,MAAM,cAAc,SAA2D;AAC7E,QAAI;AACF,cAAQ,QAAQ,MAAM;AAAA,QACpB,KAAK,kBAAkB;AACrB,gBAAM,SAAS,KAAK,SAAS,cAAc,QAAQ,OAAO;AAC1D,eAAK,gBAAgB,OAAO,SAAS;AACrC,eAAK,UAAU,EAAE,MAAM,mBAAmB,WAAW,OAAO,WAAW,OAAO,CAAC;AAC/E,cAAI;AACF,kBAAM,gBAAgB,KAAK,aAAa,QAAQ,QAAQ,SAAS,iBAAiB;AAClF,mBAAO,EAAE,SAAS,MAAM,QAAQ,cAAc;AAAA,UAChD,SAAS,OAAY;AACnB,iBAAK,SAAS,YAAY,OAAO,WAAW,QAAQ;AACpD,iBAAK,WAAW,OAAO,SAAS;AAChC,mBAAO,EAAE,SAAS,OAAO,OAAO,OAAO,WAAW,OAAO,KAAK,EAAE;AAAA,UAClE;AAAA,QACF;AAAA,QACA,KAAK;AACH,iBAAO,EAAE,SAAS,MAAM,QAAQ,KAAK,SAAS,aAAa,EAAE;AAAA,QAC/D,KAAK,kBAAkB;AACrB,gBAAM,SAAS,KAAK,SAAS,aAAa,QAAQ,OAAO;AACzD,eAAK,gBAAgB,OAAO,SAAS;AACrC,gBAAM,SAAS,OAAO,gBAAgB,KAAK,UAAQ,KAAK,aAAa,QAAQ,QAAQ,QAAQ;AAC7F,cAAI,QAAQ;AACV,iBAAK,UAAU,EAAE,MAAM,mBAAmB,WAAW,OAAO,WAAW,OAAO,CAAC;AAAA,UACjF;AACA,iBAAO,EAAE,SAAS,MAAM,QAAQ,OAAO;AAAA,QACzC;AAAA,QACA,KAAK,kBAAkB;AACrB,gBAAM,SAAS,KAAK,SAAS,aAAa,QAAQ,OAAO;AACzD,eAAK,gBAAgB,OAAO,SAAS;AACrC,eAAK,UAAU,EAAE,MAAM,mBAAmB,WAAW,OAAO,WAAW,UAAU,QAAQ,QAAQ,SAAS,CAAC;AAC3G,iBAAO,EAAE,SAAS,MAAM,QAAQ,OAAO;AAAA,QACzC;AAAA,QACA,KAAK,iBAAiB;AACpB,gBAAM,SAAS,KAAK,SAAS,aAAa,QAAQ,OAAO;AACzD,eAAK,WAAW,OAAO,SAAS;AAChC,eAAK,UAAU,EAAE,MAAM,uBAAuB,WAAW,OAAO,WAAW,OAAO,OAAO,WAAW,CAAC;AACrG,iBAAO,EAAE,SAAS,MAAM,QAAQ,OAAO;AAAA,QACzC;AAAA,QACA,KAAK,iBAAiB;AACpB,gBAAM,SAAS,KAAK,SAAS,aAAa,QAAQ,OAAO;AACzD,eAAK,WAAW,OAAO,SAAS;AAChC,eAAK,UAAU,EAAE,MAAM,uBAAuB,WAAW,OAAO,WAAW,OAAO,OAAO,WAAW,CAAC;AACrG,iBAAO,EAAE,SAAS,MAAM,QAAQ,OAAO;AAAA,QACzC;AAAA,QACA,KAAK;AACH,iBAAO,EAAE,SAAS,MAAM,QAAQ,KAAK,YAAY,QAAQ,QAAQ,WAAW,QAAQ,QAAQ,QAAQ,EAAE;AAAA,QACxG,KAAK,wBAAwB;AAC3B,gBAAM,SAAS,KAAK,SAAS,YAAY,QAAQ,QAAQ,SAAS;AAClE,eAAK,WAAW,OAAO,SAAS;AAChC,eAAK,UAAU,EAAE,MAAM,mBAAmB,WAAW,OAAO,UAAU,CAAC;AACvE,iBAAO,EAAE,SAAS,MAAM,QAAQ,OAAO;AAAA,QACzC;AAAA,QACA,KAAK,uBAAuB;AAC1B,gBAAM,SAAS,KAAK,SAAS;AAAA,YAC3B,QAAQ,QAAQ;AAAA,YAChB,QAAQ,QAAQ,QAAQ,CAAC;AAAA,YACzB,QAAQ,QAAQ,YAAY;AAAA,UAC9B;AACA,eAAK,WAAW,OAAO,SAAS;AAChC,iBAAO,EAAE,SAAS,MAAM,QAAQ,OAAO;AAAA,QACzC;AAAA,QACA,KAAK,cAAc;AACjB,gBAAM,SAAS,KAAK,kBAAkB,QAAQ,QAAQ,WAAW,QAAQ,QAAQ,QAAQ;AACzF,cAAI,QAAQ,UAAU;AACpB,mBAAO,EAAE,SAAS,OAAO,OAAO,UAAU,QAAQ,QAAQ,QAAQ,gBAAgB;AAAA,UACpF;AACA,gBAAM,UAAU,KAAK,SAAS,WAAW,QAAQ,QAAQ,SAAS;AAClE,cAAI,SAAS,cAAc,QAAQ,WAAW,aAAa,QAAQ,QAAQ,UAAU;AACnF,mBAAO,EAAE,SAAS,OAAO,OAAO,kBAAkB,QAAQ,WAAW,QAAQ,GAAG;AAAA,UAClF;AACA,eAAK,eAAe,QAAQ,QAAQ,SAAS,EAAE,MAAM,QAAQ,QAAQ,IAAI;AACzE,iBAAO,EAAE,SAAS,MAAM,QAAQ,KAAK,SAAS,WAAW,QAAQ,QAAQ,SAAS,EAAE;AAAA,QACtF;AAAA,QACA,KAAK,kBAAkB;AACrB,eAAK,eAAe,QAAQ,QAAQ,SAAS,EAAE,OAAO,QAAQ,QAAQ,MAAM,QAAQ,QAAQ,IAAI;AAChG,gBAAM,SAAS,KAAK,SAAS,WAAW,QAAQ,QAAQ,SAAS;AACjE,cAAI,QAAQ;AACV,iBAAK,SAAS;AAAA,cACZ;AAAA,gBACE,GAAG;AAAA,gBACH,MAAM;AAAA,kBACJ,GAAI,OAAO,QAAQ,CAAC;AAAA,kBACpB,iBAAiB,QAAQ,QAAQ;AAAA,kBACjC,iBAAiB,QAAQ,QAAQ;AAAA,gBACnC;AAAA,cACF;AAAA,cACA,KAAK,SAAS,YAAY,QAAQ,QAAQ,SAAS;AAAA,YACrD;AAAA,UACF;AACA,eAAK,gBAAgB,QAAQ,QAAQ,SAAS;AAC9C,eAAK,UAAU;AAAA,YACb,MAAM;AAAA,YACN,WAAW,QAAQ,QAAQ;AAAA,YAC3B,MAAM,QAAQ,QAAQ;AAAA,YACtB,MAAM,QAAQ,QAAQ;AAAA,UACxB,CAAC;AACD,iBAAO,EAAE,SAAS,MAAM,QAAQ,KAAK,SAAS,WAAW,QAAQ,QAAQ,SAAS,EAAE;AAAA,QACtF;AAAA,QACA,KAAK,gBAAgB;AACnB,eAAK,SAAS,aAAa,QAAQ,QAAQ,WAAW,UAAU;AAChE,eAAK,WAAW,QAAQ,QAAQ,SAAS;AACzC,eAAK,eAAe,QAAQ,QAAQ,SAAS,EAAE,KAAK;AACpD,eAAK,UAAU,EAAE,MAAM,mBAAmB,WAAW,QAAQ,QAAQ,UAAU,CAAC;AAChF,iBAAO,EAAE,SAAS,MAAM,QAAQ,KAAK,SAAS,WAAW,QAAQ,QAAQ,SAAS,EAAE;AAAA,QACtF;AAAA,QACA,KAAK,kBAAkB;AACrB,gBAAM,WAAW,KAAK,SAAS,WAAW,QAAQ,QAAQ,SAAS;AACnE,cAAI,CAAC,UAAU;AACb,mBAAO,EAAE,SAAS,OAAO,OAAO,oBAAoB,QAAQ,QAAQ,SAAS,GAAG;AAAA,UAClF;AACA,cAAI,KAAK,SAAS,IAAI,QAAQ,QAAQ,SAAS,GAAG;AAChD,mBAAO,EAAE,SAAS,MAAM,QAAQ,SAAS;AAAA,UAC3C;AACA,gBAAM,UAAU,KAAK,aAAa,UAAU,KAAK,uBAAuB,QAAQ,GAAG,iBAAiB;AACpG,iBAAO,EAAE,SAAS,MAAM,QAAQ,QAAQ;AAAA,QAC1C;AAAA,QACA;AACE,iBAAO,EAAE,SAAS,OAAO,OAAO,qCAAsC,SAA+B,QAAQ,SAAS,GAAG;AAAA,MAC7H;AAAA,IACF,SAAS,OAAY;AACnB,aAAO,EAAE,SAAS,OAAO,OAAO,OAAO,WAAW,OAAO,KAAK,EAAE;AAAA,IAClE;AAAA,EACF;AAAA,EAEQ,eAAe,WAAsC;AAC3D,UAAM,UAAU,KAAK,SAAS,IAAI,SAAS;AAC3C,QAAI,CAAC,QAAS,OAAM,IAAI,MAAM,kCAAkC,SAAS,EAAE;AAC3E,WAAO;AAAA,EACT;AAAA,EAEQ,kBAAkB,WAAmB,UAAgD;AAC3F,UAAM,UAAU,KAAK,SAAS,WAAW,SAAS;AAClD,WAAO,SAAS,gBAAgB,KAAK,CAAC,WAAW,OAAO,aAAa,QAAQ,KAAK;AAAA,EACpF;AAAA,EAEQ,UAAU,OAA+B;AAC/C,eAAW,UAAU,KAAK,SAAS;AACjC,mDAAc,QAAQ;AAAA,QACpB,MAAM;AAAA,QACN;AAAA,MACF,CAAC;AAAA,IACH;AACA,SAAK,KAAK,SAAS,KAAK;AAAA,EAC1B;AAAA,EAEA,MAAc,sBAAsB,QAAoB,UAAqD;AAC3G,UAAM,WAAW,MAAM,KAAK,cAAc,SAAS,OAAO;AAC1D,iDAAc,YAAQ,kDAAuB,SAAS,WAAW,QAAQ,CAAC;AAAA,EAC5E;AAAA,EAEQ,gBAAgB,WAAyB;AAC/C,UAAM,WAAW,KAAK,cAAc,IAAI,SAAS;AACjD,QAAI,SAAU,cAAa,QAAQ;AACnC,SAAK,cAAc,IAAI,WAAW,WAAW,MAAM;AACjD,WAAK,cAAc,OAAO,SAAS;AACnC,WAAK,WAAW,SAAS;AAAA,IAC3B,GAAG,GAAG,CAAC;AAAA,EACT;AAAA,EAEQ,WAAW,WAAyB;AAC1C,UAAM,SAAS,KAAK,SAAS,WAAW,SAAS;AACjD,QAAI,CAAC,OAAQ;AACb,UAAM,WAAW,KAAK,YAAY,SAAS;AAC3C,SAAK,QAAQ,KAAK,QAAQ,QAAQ;AAAA,EACpC;AAAA,EAEQ,YAAY,WAAmB,UAAmB;AACxD,UAAM,WAAW,KAAK,SAAS,YAAY,WAAW,QAAQ;AAC9D,UAAM,SAAS,KAAK,SAAS,WAAW,SAAS;AACjD,QAAI,OAAO,aAAa,UAAU;AAChC,aAAO;AAAA,QACL,GAAG;AAAA,QACH,MAAM,OAAO,QAAQ,MAAM,oBAAoB,WAAY,OAAO,KAAK,kBAA6B;AAAA,QACpG,MAAM,OAAO,QAAQ,MAAM,oBAAoB,WAAY,OAAO,KAAK,kBAA6B;AAAA,MACtG;AAAA,IACF;AAEA,UAAM,UAAU,KAAK,SAAS,IAAI,SAAS;AAC3C,UAAM,cAAc,SAAS,kBAAkB,KAAK;AACpD,QAAI,CAAC,aAAa;AAChB,aAAO;AAAA,QACL,GAAG;AAAA,QACH,MAAM,OAAO,QAAQ,MAAM,oBAAoB,WAAY,OAAO,KAAK,kBAA6B;AAAA,QACpG,MAAM,OAAO,QAAQ,MAAM,oBAAoB,WAAY,OAAO,KAAK,kBAA6B;AAAA,MACtG;AAAA,IACF;AAEA,WAAO;AAAA,MACL,GAAG;AAAA,MACH,MAAM;AAAA,MACN,WAAW;AAAA,MACX,MAAM,OAAO,QAAQ,MAAM,oBAAoB,WAAY,OAAO,KAAK,kBAA6B;AAAA,MACpG,MAAM,OAAO,QAAQ,MAAM,oBAAoB,WAAY,OAAO,KAAK,kBAA6B;AAAA,IACtG;AAAA,EACF;AAAA,EAEA,sBAA4B;AAC1B,eAAW,aAAa,KAAK,SAAS,KAAK,GAAG;AAC5C,WAAK,WAAW,SAAS;AAAA,IAC3B;AACA,eAAW,UAAU,KAAK,SAAS,aAAa,GAAG;AACjD,WAAK,WAAW,OAAO,SAAS;AAAA,IAClC;AAAA,EACF;AAAA,EAEQ,2BAAiC;AACvC,UAAM,SAAS,KAAK,QAAQ,QAAQ;AACpC,UAAM,mBAGD,CAAC;AACN,QAAI,4BAA4B;AAChC,eAAW,aAAa,QAAQ;AAC9B,YAAM,iBAAiB,CAAC,CAAC,WAAW,QAAQ,EAAE,SAAS,UAAU,OAAO,SAAS;AACjF,YAAM,qBAAqB,MAAM,QAAQ,UAAU,OAAO,eAAe,KAAK,UAAU,OAAO,gBAAgB,SAAS;AACxH,YAAM,gBAAgB,CAAC,CAAC,UAAU,OAAO;AACzC,YAAM,mBAAmB,mBAAmB,sBAAsB;AAClE,YAAM,kBAAqC;AAAA,QACzC,GAAG,UAAU;AAAA,QACb,iBAAiB,CAAC;AAAA,QAClB,YAAY;AAAA,QACZ,WAAW,mBAAmB,gBAAiB,iBAAiB,YAAY,UAAU,OAAO;AAAA,QAC7F,gBAAgB,KAAK,IAAI;AAAA,QACzB,MAAM;AAAA,UACJ,GAAI,UAAU,OAAO,QAAQ,CAAC;AAAA,UAC9B,qBAAqB;AAAA,UACrB,sBAAsB,mBAClB,6BACC,iBAAiB,oBAAoB;AAAA,UAC1C,kCAAkC;AAAA,UAClC,6BAA6B;AAAA,QAC/B;AAAA,MACF;AACA,WAAK,SAAS,eAAe,iBAAiB,UAAU,QAAQ;AAChE,WAAK,QAAQ,KAAK,iBAAiB,UAAU,QAAQ;AACrD,UAAI,kBAAkB;AACpB,yBAAiB,KAAK,EAAE,WAAW,gBAAgB,CAAC;AAAA,MACtD,WAAW,gBAAgB;AACzB,qCAA6B;AAAA,MAC/B;AAAA,IACF;AAEA,QAAI,4BAA4B,GAAG;AACjC,WAAK,KAAK,OAAO,wBAAwB,yBAAyB,wCAAwC;AAAA,IAC5G;AAEA,eAAW,EAAE,WAAW,gBAAgB,KAAK,kBAAkB;AAC7D,UAAI;AACF,cAAM,UAAU,KAAK;AAAA,UACnB;AAAA,UACA,KAAK,uBAAuB,eAAe;AAAA,UAC3C;AAAA,QACF;AACA,cAAM,cAAc;AAAA,UAClB,GAAI,QAAQ,QAAQ,CAAC;AAAA,UACrB,qBAAqB;AAAA,UACrB,sBAAsB;AAAA,QACxB;AACA,aAAK,SAAS;AAAA,UACZ,EAAE,GAAG,SAAS,MAAM,YAAY;AAAA,UAChC,KAAK,SAAS,YAAY,QAAQ,SAAS;AAAA,QAC7C;AACA,aAAK,WAAW,QAAQ,SAAS;AAAA,MACnC,SAAS,OAAY;AACnB,cAAM,cAAc,KAAK,SAAS,aAAa,gBAAgB,WAAW,aAAa;AACvF,aAAK,SAAS,eAAe;AAAA,UAC3B,GAAG;AAAA,UACH,MAAM;AAAA,YACJ,GAAI,YAAY,QAAQ,CAAC;AAAA,YACzB,qBAAqB;AAAA,YACrB,sBAAsB;AAAA,YACtB,sBAAsB,OAAO,WAAW,OAAO,KAAK;AAAA,UACtD;AAAA,QACF,GAAG,UAAU,QAAQ;AACrB,aAAK,WAAW,gBAAgB,SAAS;AAAA,MAC3C;AAAA,IACF;AAAA,EACF;AAAA,EAEQ,uBAAuB,QAAiD;AAC9E,WAAO;AAAA,MACL,WAAW,OAAO;AAAA,MAClB,YAAY,OAAO;AAAA,MACnB,aAAa,OAAO;AAAA,MACpB,cAAc,OAAO;AAAA,MACrB,UAAU,OAAO;AAAA,MACjB,WAAW,OAAO;AAAA,MAClB,eAAe,OAAO;AAAA,MACtB,MAAM,OAAO,OAAO,MAAM,oBAAoB,WAAY,OAAO,KAAK,kBAA6B;AAAA,MACnG,MAAM,OAAO,OAAO,MAAM,oBAAoB,WAAY,OAAO,KAAK,kBAA6B;AAAA,MACnG,MAAM,OAAO;AAAA,IACf;AAAA,EACF;AAAA,EAEQ,aACN,QACA,SACA,gBACmB;AACnB,UAAM,UAAU,IAAI,kBAAkB;AAAA,MACpC,WAAW,OAAO;AAAA,MAClB;AAAA,MACA,QAAQ,CAAC,SAAS;AAChB,cAAM,EAAE,IAAI,IAAI,KAAK,SAAS,aAAa,OAAO,WAAW,IAAI;AACjE,aAAK,gBAAgB,OAAO,SAAS;AACrC,aAAK,UAAU,EAAE,MAAM,kBAAkB,WAAW,OAAO,WAAW,KAAK,KAAK,CAAC;AAAA,MACnF;AAAA,MACA,QAAQ,CAAC,aAAa;AACpB,aAAK,SAAS,YAAY,OAAO,WAAW,aAAa,IAAI,YAAY,QAAQ;AACjF,aAAK,SAAS,OAAO,OAAO,SAAS;AACrC,aAAK,WAAW,OAAO,SAAS;AAChC,aAAK,UAAU,EAAE,MAAM,gBAAgB,WAAW,OAAO,WAAW,SAAS,CAAC;AAE9E,mBAAW,MAAM,KAAK,QAAQ,OAAO,OAAO,SAAS,GAAG,GAAK;AAAA,MAC/D;AAAA,IACF,CAAC;AAED,SAAK,SAAS,aAAa,OAAO,WAAW,UAAU;AACvD,UAAM,MAAM,QAAQ,MAAM;AAC1B,SAAK,SAAS,IAAI,OAAO,WAAW,OAAO;AAC3C,UAAM,gBAAgB,KAAK,SAAS,YAAY,OAAO,WAAW,GAAG;AACrE,SAAK,WAAW,OAAO,SAAS;AAChC,SAAK,UAAU,EAAE,MAAM,gBAAgB,WAAW,OAAO,WAAW,IAAI,CAAC;AACzE,WAAO;AAAA,EACT;AACF;;;ADraA,IAAM,wBAAwB,QAAQ,IAAI,4BAA4B;AAEtE,SAAS,sBAAsB,SAAyB;AACtD,QAAM,MAAW,WAAQ,YAAQ,GAAG,SAAS;AAC7C,MAAI,CAAI,eAAW,GAAG,EAAG,CAAG,cAAU,KAAK,EAAE,WAAW,KAAK,CAAC;AAC9D,SAAY,WAAK,KAAK,GAAG,OAAO,mBAAmB;AACrD;AAEA,SAAS,oBAAoB,SAAuB;AAClD,EAAG,kBAAc,sBAAsB,OAAO,GAAG,OAAO,QAAQ,GAAG,GAAG,MAAM;AAC9E;AAEA,SAAS,qBAAqB,SAAuB;AACnD,MAAI;AACF,IAAG,eAAW,sBAAsB,OAAO,CAAC;AAAA,EAC9C,QAAQ;AAAA,EAER;AACF;AAEA,SAAS,UAAU,MAAgB;AACjC,QAAM,CAAC,SAAS,GAAG,IAAI,IAAI;AAC3B,QAAM,WAAW,KAAK,SAAS,aAAa;AAC5C,QAAM,WAAW,KAAK,SAAS,YAAY;AAC3C,QAAM,UAAU,KAAK,SAAS,OAAO;AACrC,QAAM,aAAa,KAAK,OAAO,CAAC,QAAQ,QAAQ,iBAAiB,QAAQ,gBAAgB,QAAQ,OAAO;AACxG,SAAO;AAAA,IACL,SAAS,WAAW;AAAA,IACpB;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;AAEA,eAAe,YAA2B;AACxC,QAAM,SAAS,IAAI,kBAAkB,EAAE,SAAS,sBAAsB,CAAC;AACvE,sBAAoB,qBAAqB;AACzC,QAAM,OAAO,MAAM;AAEnB,UAAQ,GAAG,UAAU,YAAY;AAC/B,UAAM,OAAO,KAAK;AAClB,yBAAqB,qBAAqB;AAC1C,YAAQ,KAAK,CAAC;AAAA,EAChB,CAAC;AAED,UAAQ,GAAG,WAAW,YAAY;AAChC,UAAM,OAAO,KAAK;AAClB,yBAAqB,qBAAqB;AAC1C,YAAQ,KAAK,CAAC;AAAA,EAChB,CAAC;AAGD,UAAQ,GAAG,QAAQ,MAAM;AACvB,WAAO,oBAAoB;AAC3B,yBAAqB,qBAAqB;AAAA,EAC5C,CAAC;AAGD,QAAM,IAAI,QAAc,MAAM;AAAA,EAAC,CAAC;AAClC;AAEA,eAAe,aAAa,UAAU,OAAsB;AAC1D,QAAM,SAAS,IAAI,4CAAkB,EAAE,cAAU,yDAA8B,qBAAqB,EAAE,CAAC;AACvG,MAAI;AACF,UAAM,WAAW,MAAM,OAAO,QAA6B;AAAA,MACzD,MAAM;AAAA,MACN,SAAS,CAAC;AAAA,IACZ,CAAC;AACD,QAAI,CAAC,SAAS,SAAS;AACrB,YAAM,IAAI,MAAM,SAAS,SAAS,yBAAyB;AAAA,IAC7D;AACA,UAAM,YAAY,SAAS,UAAU,CAAC,GAAG,OAAO,CAAC,YAA+B,WAAW,QAAQ,cAAc,SAAS;AAC1H,QAAI,SAAS,WAAW,GAAG;AACzB,cAAQ,IAAI,cAAc;AAC1B;AAAA,IACF;AACA,YAAQ,IAAI,qDAA0D;AACtE,eAAW,WAAW,UAAU;AAC9B,cAAQ,IAAI;AAAA,QACV,QAAQ;AAAA,QACR,QAAQ;AAAA,YACR,8CAAmB,OAAO;AAAA,QAC1B,QAAQ;AAAA,QACR,QAAQ;AAAA,QACR,QAAQ;AAAA,MACV,EAAE,KAAK,GAAI,CAAC;AAAA,IACd;AAAA,EACF,UAAE;AACA,UAAM,OAAO,MAAM,EAAE,MAAM,MAAM;AAAA,IAAC,CAAC;AAAA,EACrC;AACF;AAEA,eAAe,cAAc,QAAgB,WAAW,OAAO,WAAW,OAAsB;AAC9F,QAAM,SAAS,IAAI,4CAAkB,EAAE,cAAU,yDAA8B,qBAAqB,EAAE,CAAC;AACvG,QAAM,WAAW,kBAAkB,QAAQ,GAAG,QAAI,0BAAW,EAAE,MAAM,GAAG,CAAC,CAAC;AAC1E,MAAI,UAAU;AACd,MAAI,kBAAkB;AACtB,MAAI,YAAY;AAChB,MAAI,gBAAgB;AAEpB,QAAM,UAAU,YAAY;AAC1B,YAAQ,OAAO,IAAI,UAAU,YAAY;AACzC,YAAQ,MAAM,IAAI,QAAQ,WAAW;AACrC,YAAQ,MAAM,MAAM;AACpB,QAAI,QAAQ,MAAM,SAAS,iBAAiB;AAC1C,cAAQ,MAAM,WAAW,KAAK;AAAA,IAChC;AACA,UAAM,OAAO,QAAQ;AAAA,MACnB,MAAM;AAAA,MACN,SAAS;AAAA,QACP,WAAW;AAAA,QACX;AAAA,MACF;AAAA,IACF,CAAC,EAAE,MAAM,OAAO,EAAE,SAAS,MAAM,EAAE;AACnC,UAAM,OAAO,QAAQ;AAAA,MACnB,MAAM;AAAA,MACN,SAAS;AAAA,QACP,WAAW;AAAA,QACX;AAAA,MACF;AAAA,IACF,CAAC,EAAE,MAAM,OAAO,EAAE,SAAS,MAAM,EAAE;AACnC,UAAM,OAAO,MAAM,EAAE,MAAM,MAAM;AAAA,IAAC,CAAC;AAAA,EACrC;AAEA,QAAM,eAAe,MAAM;AACzB,SAAK,OAAO,QAAQ;AAAA,MAClB,MAAM;AAAA,MACN,SAAS;AAAA,QACP,WAAW;AAAA,QACX,MAAM,QAAQ,OAAO,WAAW;AAAA,QAChC,MAAM,QAAQ,OAAO,QAAQ;AAAA,MAC/B;AAAA,IACF,CAAC,EAAE,MAAM,OAAO,EAAE,SAAS,MAAM,EAAE;AAAA,EACrC;AAEA,QAAM,wBAAwB,OAAO,SAAiB;AACpD,QAAI,WAAW,MAAM,OAAO,QAAQ;AAAA,MAClC,MAAM;AAAA,MACN,SAAS;AAAA,QACP,WAAW;AAAA,QACX;AAAA,QACA;AAAA,MACF;AAAA,IACF,CAAC;AACD,QAAI,CAAC,SAAS,WAAW,SAAS,OAAO,WAAW,iBAAiB,GAAG;AACtE,YAAM,gBAAgB,MAAM,OAAO,QAA2B;AAAA,QAC5D,MAAM;AAAA,QACN,SAAS;AAAA,UACP,WAAW;AAAA,UACX;AAAA,UACA,WAAW;AAAA,UACX,OAAO;AAAA,QACT;AAAA,MACF,CAAC;AACD,UAAI,cAAc,WAAW,cAAc,QAAQ;AACjD,mBAAW,MAAM,OAAO,QAAQ;AAAA,UAC9B,MAAM;AAAA,UACN,SAAS;AAAA,YACP,WAAW;AAAA,YACX;AAAA,YACA;AAAA,UACF;AAAA,QACF,CAAC;AACD,YAAI,SAAS,SAAS;AACpB,kBAAQ,OAAO,MAAM,mBAAmB,cAAc,OAAO,UAAU;AAAA,CAAK;AAAA,QAC9E;AAAA,MACF;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAEA,QAAM,cAAc,CAAC,UAAkB;AACrC,QAAI,CAAC,iBAAiB,MAAM,WAAW,KAAK,MAAM,CAAC,MAAM,IAAM;AAC7D,WAAK,QAAQ,EAAE,QAAQ,MAAM,QAAQ,KAAK,CAAC,CAAC;AAC5C;AAAA,IACF;AACA,QAAI,cAAe;AACnB,SAAK,sBAAsB,MAAM,SAAS,MAAM,CAAC,EAAE,MAAM,OAAO,EAAE,SAAS,MAAM,EAAE;AAAA,EACrF;AAEA,MAAI;AACF,QAAI,YAAY,UAAU;AACxB,YAAM,IAAI,MAAM,gDAAgD;AAAA,IAClE;AAEA,UAAM,eAAe,MAAM,OAAO,QAA6B;AAAA,MAC7D,MAAM;AAAA,MACN,SAAS,CAAC;AAAA,IACZ,CAAC;AACD,QAAI,CAAC,aAAa,WAAW,CAAC,aAAa,QAAQ;AACjD,YAAM,IAAI,MAAM,aAAa,SAAS,yBAAyB;AAAA,IACjE;AACA,QAAI,oBAAgB,gDAAqB,aAAa,QAAQ,MAAM;AACpE,gBAAY,cAAc;AAE1B,QAAI,cAAc,cAAc,iBAAiB,CAAC,UAAU;AAC1D,YAAM,iBAAiB,MAAM,OAAO,QAA2B;AAAA,QAC7D,MAAM;AAAA,QACN,SAAS;AAAA,UACP,WAAW;AAAA,QACb;AAAA,MACF,CAAC;AACD,UAAI,eAAe,WAAW,eAAe,QAAQ;AACnD,wBAAgB,eAAe;AAAA,MACjC,OAAO;AACL,gBAAQ,OAAO;AAAA,UACb,WAAW,cAAc,UAAU,wCAAwC,eAAe,SAAS,eAAe;AAAA;AAAA,QACpH;AAAA,MACF;AAAA,IACF;AAEA,QAAI,oBAAoB;AACxB,QAAI,CAAC,qBAAqB,cAAc,cAAc,cAAc,WAAW,aAAa,YAAY,CAAC,UAAU;AACjH,cAAQ,OAAO;AAAA,QACb,WAAW,cAAc,UAAU,0BAA0B,cAAc,WAAW,QAAQ;AAAA;AAAA,MAChG;AAAA,IACF;AACA,oBAAgB;AAEhB,UAAM,iBAAiB,MAAM,OAAO,QAA2B;AAAA,MAC7D,MAAM;AAAA,MACN,SAAS;AAAA,QACP,WAAW;AAAA,QACX;AAAA,QACA,YAAY;AAAA,QACZ,UAAU;AAAA,MACZ;AAAA,IACF,CAAC;AACD,QAAI,CAAC,eAAe,SAAS;AAC3B,YAAM,IAAI,MAAM,eAAe,SAAS,4BAA4B,SAAS,EAAE;AAAA,IACjF;AACA,UAAM,iBAAiB,eAAe,UAAU;AAEhD,QAAI,CAAC,qBAAqB,UAAU;AAClC,YAAM,gBAAgB,MAAM,OAAO,QAA2B;AAAA,QAC5D,MAAM;AAAA,QACN,SAAS;AAAA,UACP,WAAW;AAAA,UACX;AAAA,UACA,WAAW;AAAA,UACX,OAAO;AAAA,QACT;AAAA,MACF,CAAC;AACD,UAAI,CAAC,cAAc,SAAS;AAC1B,cAAM,IAAI,MAAM,cAAc,SAAS,6CAA6C,SAAS,EAAE;AAAA,MACjG;AAAA,IACF;AAEA,UAAM,mBAAmB,MAAM,OAAO,QAAyF;AAAA,MAC7H,MAAM;AAAA,MACN,SAAS,EAAE,WAAW,UAAU;AAAA,IAClC,CAAC;AACD,QAAI,CAAC,iBAAiB,SAAS;AAC7B,YAAM,IAAI,MAAM,iBAAiB,SAAS,mCAAmC,SAAS,EAAE;AAAA,IAC1F;AACA,cAAU,iBAAiB,QAAQ,OAAO;AAC1C,QAAI,iBAAiB,QAAQ,MAAM;AACjC,cAAQ,OAAO,MAAM,iBAAiB,OAAO,IAAI;AAAA,IACnD;AACA,QAAI,gBAAgB,cAAc,aAAa,gBAAgB,cAAc,YAAY,gBAAgB,cAAc,eAAe;AACpI,cAAQ,OAAO,MAAM,WAAW,eAAe,UAAU,eAAe,eAAe,SAAS;AAAA,CAA8B;AAC9H,YAAM,QAAQ;AACd;AAAA,IACF;AAEA,UAAM,cAAc,CAAC,UAAU,WAAW,QAAQ;AAClD,UAAM,iBAAiB,YAAY,IAAI,CAAC,WAAW;AACjD,YAAM,UAAU,MAAM;AACpB,aAAK,QAAQ,EAAE,QAAQ,MAAM,QAAQ,KAAK,CAAC,CAAC;AAAA,MAC9C;AACA,cAAQ,GAAG,QAAQ,OAAO;AAC1B,aAAO,EAAE,QAAQ,QAAQ;AAAA,IAC3B,CAAC;AAED,UAAM,cAAc,OAAO,QAAQ,CAAC,UAA4B;AAC9D,UAAI,MAAM,cAAc,UAAW;AACnC,UAAI,MAAM,SAAS,kBAAkB;AACnC,YAAI,MAAM,OAAO,QAAS;AAC1B,kBAAU,MAAM;AAChB,gBAAQ,OAAO,MAAM,MAAM,IAAI;AAC/B;AAAA,MACF;AACA,UAAI,MAAM,SAAS,gBAAgB;AACjC,aAAK,QAAQ,EAAE,QAAQ,MAAM;AAC3B,qBAAW,EAAE,QAAQ,QAAQ,KAAK,gBAAgB;AAChD,oBAAQ,IAAI,QAAQ,OAAO;AAAA,UAC7B;AACA,sBAAY;AACZ,kBAAQ,KAAK,MAAM,YAAY,CAAC;AAAA,QAClC,CAAC;AAAA,MACH;AAAA,IACF,CAAC;AAED,YAAQ,OAAO,GAAG,UAAU,YAAY;AACxC,YAAQ,MAAM,GAAG,QAAQ,WAAW;AACpC,YAAQ,MAAM,OAAO;AACrB,QAAI,QAAQ,MAAM,OAAO;AACvB,cAAQ,MAAM,WAAW,IAAI;AAC7B,wBAAkB;AAAA,IACpB;AACA,iBAAa;AACb,QAAI,CAAC,mBAAmB;AACtB,cAAQ,OAAO,MAAM,uBAAuB,gBAAgB,cAAc,SAAS;AAAA,CAA6B;AAAA,IAClH,OAAO;AACL,cAAQ,OAAO,MAAM,uBAAuB,gBAAgB,cAAc,SAAS;AAAA,CAAiB;AAAA,IACtG;AACA,UAAM,IAAI,QAAc,MAAM;AAAA,IAAC,CAAC;AAAA,EAClC,SAAS,OAAO;AACd,UAAM,QAAQ,EAAE,MAAM,MAAM;AAAA,IAAC,CAAC;AAC9B,UAAM;AAAA,EACR;AACF;AAEA,eAAe,OAAsB;AACnC,QAAM,EAAE,SAAS,YAAY,UAAU,UAAU,QAAQ,IAAI,UAAU,QAAQ,KAAK,MAAM,CAAC,CAAC;AAC5F,MAAI,YAAY,SAAS;AACvB,UAAM,UAAU;AAChB;AAAA,EACF;AACA,MAAI,YAAY,QAAQ;AACtB,UAAM,aAAa,OAAO;AAC1B;AAAA,EACF;AACA,MAAI,YAAY,UAAU;AACxB,UAAM,SAAS,WAAW,CAAC;AAC3B,QAAI,CAAC,QAAQ;AACX,YAAM,IAAI,MAAM,2EAA2E;AAAA,IAC7F;AACA,UAAM,cAAc,QAAQ,UAAU,QAAQ;AAC9C;AAAA,EACF;AACA,MAAI,YAAY,UAAU;AACxB,UAAM,SAAS,WAAW,CAAC;AAC3B,QAAI,CAAC,QAAQ;AACX,YAAM,IAAI,MAAM,2EAA2E;AAAA,IAC7F;AACA,UAAM,SAAS,IAAI,4CAAkB,EAAE,cAAU,yDAA8B,qBAAqB,EAAE,CAAC;AACvG,QAAI;AACF,YAAM,eAAe,MAAM,OAAO,QAA6B,EAAE,MAAM,iBAAiB,SAAS,CAAC,EAAE,CAAC;AACrG,UAAI,CAAC,aAAa,WAAW,CAAC,aAAa,QAAQ;AACjD,cAAM,IAAI,MAAM,aAAa,SAAS,yBAAyB;AAAA,MACjE;AACA,YAAM,oBAAgB,gDAAqB,aAAa,QAAQ,MAAM;AACtE,YAAM,iBAAiB,MAAM,OAAO,QAA2B;AAAA,QAC7D,MAAM;AAAA,QACN,SAAS;AAAA,UACP,WAAW,cAAc;AAAA,QAC3B;AAAA,MACF,CAAC;AACD,UAAI,CAAC,eAAe,WAAW,CAAC,eAAe,QAAQ;AACrD,cAAM,IAAI,MAAM,eAAe,SAAS,4BAA4B,cAAc,UAAU,EAAE;AAAA,MAChG;AACA,cAAQ,IAAI,WAAW,eAAe,OAAO,UAAU,KAAK,eAAe,OAAO,SAAS,GAAG;AAAA,IAChG,UAAE;AACA,YAAM,OAAO,MAAM,EAAE,MAAM,MAAM;AAAA,MAAC,CAAC;AAAA,IACrC;AACA;AAAA,EACF;AACA,QAAM,IAAI,MAAM,oBAAoB,OAAO,EAAE;AAC/C;AAEA,IAAI,QAAQ,SAAS,QAAQ;AAE3B,UAAQ,GAAG,qBAAqB,CAAC,QAAQ;AACvC,YAAQ,MAAM,sCAAsC,KAAK,OAAO;AAAA,EAAK,KAAK,SAAS,EAAE,EAAE;AAAA,EAEzF,CAAC;AACD,UAAQ,GAAG,sBAAsB,CAAC,WAAgB;AAChD,YAAQ,MAAM,uCAAuC,QAAQ,WAAW,MAAM,EAAE;AAAA,EAClF,CAAC;AAED,OAAK,KAAK,EAAE,MAAM,CAAC,UAAU;AAC3B,YAAQ,MAAM,iBAAiB,QAAQ,MAAM,UAAU,KAAK;AAC5D,YAAQ,KAAK,CAAC;AAAA,EAChB,CAAC;AACH;","names":["fs","os","path","import_session_host_core","fs","import_session_host_core","fs","os"]}
|