@adhdev/daemon-standalone 1.0.18-rc.18 → 1.0.18-rc.2

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.
@@ -21,7 +21,6 @@ declare class SessionHostServer extends EventEmitter {
21
21
  private recentTransitions;
22
22
  private exitWaiters;
23
23
  private lastNoOutputInputWarnAt;
24
- private stopRequests;
25
24
  constructor(options?: SessionHostServerOptions);
26
25
  start(): Promise<void>;
27
26
  stop(): Promise<void>;
@@ -48,12 +47,6 @@ declare class SessionHostServer extends EventEmitter {
48
47
  private restorePersistedRuntimes;
49
48
  private pruneDuplicateRuntime;
50
49
  private startRuntime;
51
- /**
52
- * Handle a PTY termination: classify the (exitCode, signal) pair, stamp the
53
- * record + tombstone, emit exactly one structured diagnostic, and schedule
54
- * cleanup of the live persistence file (the tombstone is retained).
55
- */
56
- private handleRuntimeExit;
57
50
  }
58
51
 
59
52
  export { SessionHostServer, type SessionHostServerOptions };
@@ -21,7 +21,6 @@ declare class SessionHostServer extends EventEmitter {
21
21
  private recentTransitions;
22
22
  private exitWaiters;
23
23
  private lastNoOutputInputWarnAt;
24
- private stopRequests;
25
24
  constructor(options?: SessionHostServerOptions);
26
25
  start(): Promise<void>;
27
26
  stop(): Promise<void>;
@@ -48,12 +47,6 @@ declare class SessionHostServer extends EventEmitter {
48
47
  private restorePersistedRuntimes;
49
48
  private pruneDuplicateRuntime;
50
49
  private startRuntime;
51
- /**
52
- * Handle a PTY termination: classify the (exitCode, signal) pair, stamp the
53
- * record + tombstone, emit exactly one structured diagnostic, and schedule
54
- * cleanup of the live persistence file (the tombstone is retained).
55
- */
56
- private handleRuntimeExit;
57
50
  }
58
51
 
59
52
  export { SessionHostServer, type SessionHostServerOptions };
@@ -279,16 +279,13 @@ var PtySessionRuntime = class {
279
279
  this.respondToTerminalQueries(data);
280
280
  this.onDataCallback(data);
281
281
  });
282
- this.ptyProcess.onExit(({ exitCode, signal }) => {
282
+ this.ptyProcess.onExit(({ exitCode }) => {
283
283
  this.ptyProcess = null;
284
284
  this.screenMirror?.dispose();
285
285
  this.screenMirror = null;
286
286
  this.pendingQueryScanTail = "";
287
287
  this.terminalModeScanTail = "";
288
- this.onExitCallback(
289
- typeof exitCode === "number" ? exitCode : null,
290
- typeof signal === "number" ? signal : null
291
- );
288
+ this.onExitCallback(exitCode ?? null);
292
289
  });
293
290
  return this.ptyProcess.pid;
294
291
  }
@@ -400,12 +397,10 @@ var path = __toESM(require("path"));
400
397
  var SessionHostStorage = class {
401
398
  rootDir;
402
399
  runtimesDir;
403
- tombstonesDir;
404
400
  constructor(options = {}) {
405
401
  const appName = options.appName || "adhdev";
406
402
  this.rootDir = path.join(os2.homedir(), ".adhdev", "session-host", appName);
407
403
  this.runtimesDir = path.join(this.rootDir, "runtimes");
408
- this.tombstonesDir = path.join(this.rootDir, "tombstones");
409
404
  }
410
405
  loadAll() {
411
406
  if (!fs2.existsSync(this.runtimesDir)) return [];
@@ -441,52 +436,6 @@ var SessionHostStorage = class {
441
436
  } catch {
442
437
  }
443
438
  }
444
- /**
445
- * Persist a compact termination tombstone. Kept in a separate directory from
446
- * live runtimes so it survives the post-exit cleanup of the runtime file and
447
- * remains inspectable for post-mortem diagnostics.
448
- */
449
- saveTombstone(sessionId, termination) {
450
- fs2.mkdirSync(this.tombstonesDir, { recursive: true });
451
- const filePath = path.join(this.tombstonesDir, `${sessionId}.json`);
452
- const payload = {
453
- sessionId,
454
- termination,
455
- updatedAt: Date.now()
456
- };
457
- fs2.writeFileSync(filePath, JSON.stringify(payload, null, 2), "utf8");
458
- }
459
- loadTombstone(sessionId) {
460
- const filePath = path.join(this.tombstonesDir, `${sessionId}.json`);
461
- try {
462
- const parsed = JSON.parse(fs2.readFileSync(filePath, "utf8"));
463
- return parsed?.sessionId ? parsed : null;
464
- } catch {
465
- return null;
466
- }
467
- }
468
- loadAllTombstones() {
469
- if (!fs2.existsSync(this.tombstonesDir)) return [];
470
- const entries = fs2.readdirSync(this.tombstonesDir, { withFileTypes: true });
471
- const states = [];
472
- for (const entry of entries) {
473
- if (!entry.isFile() || !entry.name.endsWith(".json")) continue;
474
- const fullPath = path.join(this.tombstonesDir, entry.name);
475
- try {
476
- const parsed = JSON.parse(fs2.readFileSync(fullPath, "utf8"));
477
- if (parsed?.sessionId) states.push(parsed);
478
- } catch {
479
- }
480
- }
481
- return states.sort((a, b) => (b.updatedAt || 0) - (a.updatedAt || 0));
482
- }
483
- removeTombstone(sessionId) {
484
- const filePath = path.join(this.tombstonesDir, `${sessionId}.json`);
485
- try {
486
- fs2.unlinkSync(filePath);
487
- } catch {
488
- }
489
- }
490
439
  };
491
440
 
492
441
  // src/session-diagnostics.ts
@@ -697,9 +646,6 @@ var SessionHostServer = class extends import_events.EventEmitter {
697
646
  recentTransitions = [];
698
647
  exitWaiters = /* @__PURE__ */ new Map();
699
648
  lastNoOutputInputWarnAt = /* @__PURE__ */ new Map();
700
- // Records the most recent explicit stop/delete/restart/prune request per
701
- // session so the termination diagnostic can attribute the exit to it.
702
- stopRequests = /* @__PURE__ */ new Map();
703
649
  constructor(options = {}) {
704
650
  super();
705
651
  this.endpoint = options.endpoint || (0, import_session_host_core4.getDefaultSessionHostEndpoint)(options.appName || "adhdev");
@@ -897,7 +843,6 @@ var SessionHostServer = class extends import_events.EventEmitter {
897
843
  return { success: true, result: this.registry.getSession(request.payload.sessionId) };
898
844
  }
899
845
  case "stop_session": {
900
- this.stopRequests.set(request.payload.sessionId, "stop");
901
846
  this.registry.setLifecycle(request.payload.sessionId, "stopping");
902
847
  this.persistNow(request.payload.sessionId);
903
848
  this.requireRuntime(request.payload.sessionId).stop();
@@ -912,7 +857,6 @@ var SessionHostServer = class extends import_events.EventEmitter {
912
857
  if (!request.payload.force) {
913
858
  return { success: false, error: `Session ${record.sessionId} is still running; pass force to stop and delete it` };
914
859
  }
915
- this.stopRequests.set(record.sessionId, "delete");
916
860
  this.registry.setLifecycle(record.sessionId, "stopping");
917
861
  this.persistNow(record.sessionId);
918
862
  this.requireRuntime(record.sessionId).stop();
@@ -922,8 +866,6 @@ var SessionHostServer = class extends import_events.EventEmitter {
922
866
  }
923
867
  this.registry.deleteSession(record.sessionId);
924
868
  this.storage.remove(record.sessionId);
925
- this.storage.removeTombstone(record.sessionId);
926
- this.stopRequests.delete(record.sessionId);
927
869
  this.emitEvent({ type: "session_deleted", sessionId: record.sessionId });
928
870
  this.recordRuntimeTransition(record.sessionId, "delete_session", record.lifecycle, void 0, true);
929
871
  return { success: true, result: { sessionId: record.sessionId, deleted: true } };
@@ -1231,7 +1173,6 @@ var SessionHostServer = class extends import_events.EventEmitter {
1231
1173
  throw new Error(`Unknown session: ${sessionId}`);
1232
1174
  }
1233
1175
  if (this.runtimes.has(sessionId)) {
1234
- this.stopRequests.set(sessionId, "restart");
1235
1176
  this.registry.setLifecycle(sessionId, "stopping");
1236
1177
  this.persistNow(sessionId);
1237
1178
  this.recordRuntimeTransition(sessionId, "restart_requested", "stopping", void 0, true);
@@ -1302,7 +1243,6 @@ var SessionHostServer = class extends import_events.EventEmitter {
1302
1243
  true
1303
1244
  );
1304
1245
  if (this.runtimes.has(record.sessionId)) {
1305
- this.stopRequests.set(record.sessionId, "prune");
1306
1246
  this.registry.setLifecycle(record.sessionId, "stopping");
1307
1247
  this.persistNow(record.sessionId);
1308
1248
  this.requireRuntime(record.sessionId).stop();
@@ -1312,8 +1252,6 @@ var SessionHostServer = class extends import_events.EventEmitter {
1312
1252
  }
1313
1253
  this.registry.deleteSession(record.sessionId);
1314
1254
  this.storage.remove(record.sessionId);
1315
- this.storage.removeTombstone(record.sessionId);
1316
- this.stopRequests.delete(record.sessionId);
1317
1255
  }
1318
1256
  startRuntime(record, payload, startEventType) {
1319
1257
  const runtime = new PtySessionRuntime({
@@ -1324,7 +1262,22 @@ var SessionHostServer = class extends import_events.EventEmitter {
1324
1262
  this.schedulePersist(record.sessionId);
1325
1263
  this.emitEvent({ type: "session_output", sessionId: record.sessionId, seq, data });
1326
1264
  },
1327
- onExit: (exitCode, signal) => this.handleRuntimeExit(record, exitCode, signal)
1265
+ onExit: (exitCode) => {
1266
+ this.registry.markStopped(record.sessionId, exitCode === 0 ? "stopped" : "failed");
1267
+ this.runtimes.delete(record.sessionId);
1268
+ this.resolveExitWaiters(record.sessionId, exitCode);
1269
+ this.persistNow(record.sessionId);
1270
+ this.emitEvent({ type: "session_exit", sessionId: record.sessionId, exitCode });
1271
+ this.recordRuntimeTransition(
1272
+ record.sessionId,
1273
+ "session_exit",
1274
+ exitCode === 0 ? "stopped" : "failed",
1275
+ void 0,
1276
+ exitCode === 0,
1277
+ exitCode === 0 ? void 0 : `exitCode=${exitCode}`
1278
+ );
1279
+ setTimeout(() => this.storage.remove(record.sessionId), 5e3);
1280
+ }
1328
1281
  });
1329
1282
  this.registry.setLifecycle(record.sessionId, "starting");
1330
1283
  const pid = runtime.start();
@@ -1335,58 +1288,6 @@ var SessionHostServer = class extends import_events.EventEmitter {
1335
1288
  this.recordRuntimeTransition(record.sessionId, startEventType, startedRecord.lifecycle, `pid=${pid}`, true);
1336
1289
  return startedRecord;
1337
1290
  }
1338
- /**
1339
- * Handle a PTY termination: classify the (exitCode, signal) pair, stamp the
1340
- * record + tombstone, emit exactly one structured diagnostic, and schedule
1341
- * cleanup of the live persistence file (the tombstone is retained).
1342
- */
1343
- handleRuntimeExit(record, exitCode, signal) {
1344
- const priorRecord = this.registry.getSession(record.sessionId);
1345
- const termination = (0, import_session_host_core4.classifyTermination)({
1346
- exitCode,
1347
- signal,
1348
- osPid: priorRecord?.osPid,
1349
- previousLifecycle: priorRecord?.lifecycle,
1350
- lastOutputAt: priorRecord?.lastActivityAt,
1351
- requestedStop: this.stopRequests.get(record.sessionId),
1352
- terminatedAt: Date.now()
1353
- });
1354
- this.stopRequests.delete(record.sessionId);
1355
- this.registry.markStopped(record.sessionId, termination.lifecycle, termination);
1356
- this.runtimes.delete(record.sessionId);
1357
- this.resolveExitWaiters(record.sessionId, exitCode);
1358
- this.persistNow(record.sessionId);
1359
- this.storage.saveTombstone(record.sessionId, termination);
1360
- this.emitEvent({ type: "session_exit", sessionId: record.sessionId, exitCode, signal, termination });
1361
- const summary = `reason=${termination.reason} exitCode=${termination.exitCode === null ? "unknown" : termination.exitCode} signal=${termination.signal ?? "none"}`;
1362
- this.recordHostLog(
1363
- termination.lifecycle === "stopped" ? "info" : "warn",
1364
- `session terminated: ${summary}`,
1365
- record.sessionId,
1366
- {
1367
- runtimeKey: record.runtimeKey,
1368
- providerType: record.providerType,
1369
- osPid: termination.osPid,
1370
- exitCode: termination.exitCode,
1371
- signal: termination.signal,
1372
- reason: termination.reason,
1373
- previousLifecycle: termination.previousLifecycle,
1374
- lifecycle: termination.lifecycle,
1375
- lastOutputAt: termination.lastOutputAt,
1376
- requestedStop: termination.requestedStop
1377
- }
1378
- );
1379
- this.recordRuntimeTransition(
1380
- record.sessionId,
1381
- "session_exit",
1382
- termination.lifecycle,
1383
- summary,
1384
- termination.lifecycle === "stopped",
1385
- termination.lifecycle === "stopped" ? void 0 : summary
1386
- );
1387
- setTimeout(() => this.storage.remove(record.sessionId), 5e3).unref?.();
1388
- return termination;
1389
- }
1390
1291
  };
1391
1292
 
1392
1293
  // src/index.ts