claudemesh-cli 1.31.0 → 1.31.1

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.
@@ -104,7 +104,7 @@ __export(exports_urls, {
104
104
  VERSION: () => VERSION,
105
105
  URLS: () => URLS
106
106
  });
107
- var URLS, VERSION = "1.31.0", env;
107
+ var URLS, VERSION = "1.31.1", env;
108
108
  var init_urls = __esm(() => {
109
109
  URLS = {
110
110
  BROKER: process.env.CLAUDEMESH_BROKER_URL ?? "wss://ic.claudemesh.com/ws",
@@ -9335,21 +9335,45 @@ function bindSseStream(res, bus) {
9335
9335
  }
9336
9336
 
9337
9337
  // src/daemon/process-info.ts
9338
- import { execFileSync } from "node:child_process";
9339
- function getProcessStartTime(pid) {
9338
+ import { execFile as execFile2 } from "node:child_process";
9339
+ import { promisify } from "node:util";
9340
+ async function getProcessStartTime(pid) {
9340
9341
  if (!Number.isFinite(pid) || pid <= 0)
9341
9342
  return null;
9342
9343
  try {
9343
- const out = execFileSync("ps", ["-o", "lstart=", "-p", String(pid)], {
9344
+ const { stdout } = await execFileAsync("ps", ["-o", "lstart=", "-p", String(pid)], {
9344
9345
  encoding: "utf8",
9345
- timeout: 1000,
9346
- stdio: ["ignore", "pipe", "ignore"]
9347
- }).trim();
9346
+ timeout: 1000
9347
+ });
9348
+ const out = stdout.trim();
9348
9349
  return out.length > 0 ? out : null;
9349
9350
  } catch {
9350
9351
  return null;
9351
9352
  }
9352
9353
  }
9354
+ async function getProcessStartTimes(pids) {
9355
+ const result = new Map;
9356
+ const valid = pids.filter((p) => Number.isFinite(p) && p > 0);
9357
+ if (valid.length === 0)
9358
+ return result;
9359
+ try {
9360
+ const { stdout } = await execFileAsync("ps", ["-o", "pid=,lstart=", "-p", valid.join(",")], { encoding: "utf8", timeout: 2000 });
9361
+ for (const raw of stdout.split(`
9362
+ `)) {
9363
+ const line = raw.trim();
9364
+ if (!line)
9365
+ continue;
9366
+ const m = /^(\d+)\s+(.+)$/.exec(line);
9367
+ if (!m)
9368
+ continue;
9369
+ const pid = Number.parseInt(m[1], 10);
9370
+ const lstart = m[2].trim();
9371
+ if (Number.isFinite(pid) && lstart.length > 0)
9372
+ result.set(pid, lstart);
9373
+ }
9374
+ } catch {}
9375
+ return result;
9376
+ }
9353
9377
  function isPidAlive(pid) {
9354
9378
  if (!Number.isFinite(pid) || pid <= 0)
9355
9379
  return false;
@@ -9360,13 +9384,18 @@ function isPidAlive(pid) {
9360
9384
  return false;
9361
9385
  }
9362
9386
  }
9363
- var init_process_info = () => {};
9387
+ var execFileAsync;
9388
+ var init_process_info = __esm(() => {
9389
+ execFileAsync = promisify(execFile2);
9390
+ });
9364
9391
 
9365
9392
  // src/daemon/session-registry.ts
9366
9393
  function startReaper() {
9367
9394
  if (reaperHandle)
9368
9395
  return;
9369
- reaperHandle = setInterval(reapDead, REAPER_INTERVAL_MS).unref?.() ?? reaperHandle;
9396
+ reaperHandle = setInterval(() => {
9397
+ reapDead();
9398
+ }, REAPER_INTERVAL_MS).unref?.() ?? reaperHandle;
9370
9399
  }
9371
9400
  function setRegistryHooks(next) {
9372
9401
  hooks.onRegister = next.onRegister;
@@ -9383,15 +9412,26 @@ function registerSession(info) {
9383
9412
  } catch {}
9384
9413
  }
9385
9414
  }
9386
- const startTime = info.startTime ?? getProcessStartTime(info.pid) ?? undefined;
9387
- const stored = { ...info, startTime, registeredAt: Date.now() };
9415
+ const stored = { ...info, registeredAt: Date.now() };
9388
9416
  byToken.set(info.token, stored);
9389
9417
  bySessionId.set(info.sessionId, info.token);
9390
9418
  try {
9391
9419
  hooks.onRegister?.(stored);
9392
9420
  } catch {}
9421
+ if (stored.startTime === undefined) {
9422
+ captureStartTimeAsync(info.token, info.pid);
9423
+ }
9393
9424
  return stored;
9394
9425
  }
9426
+ async function captureStartTimeAsync(token, pid) {
9427
+ const lstart = await getProcessStartTime(pid);
9428
+ if (lstart === null)
9429
+ return;
9430
+ const entry = byToken.get(token);
9431
+ if (!entry || entry.pid !== pid)
9432
+ return;
9433
+ entry.startTime = lstart;
9434
+ }
9395
9435
  function deregisterByToken(token) {
9396
9436
  const entry = byToken.get(token);
9397
9437
  if (!entry)
@@ -9417,9 +9457,11 @@ function resolveToken(token) {
9417
9457
  function listSessions() {
9418
9458
  return [...byToken.values()];
9419
9459
  }
9420
- function reapDead() {
9460
+ async function reapDead() {
9461
+ const entries = [...byToken.entries()];
9421
9462
  const dead = [];
9422
- for (const [token, info] of byToken.entries()) {
9463
+ const survivors = [];
9464
+ for (const [token, info] of entries) {
9423
9465
  if (Date.now() - info.registeredAt > TTL_MS) {
9424
9466
  dead.push(token);
9425
9467
  continue;
@@ -9428,13 +9470,22 @@ function reapDead() {
9428
9470
  dead.push(token);
9429
9471
  continue;
9430
9472
  }
9431
- if (info.startTime !== undefined) {
9432
- const live = getProcessStartTime(info.pid);
9433
- if (live !== null && live !== info.startTime) {
9434
- dead.push(token);
9435
- continue;
9473
+ survivors.push([token, info]);
9474
+ }
9475
+ const guardedPids = survivors.filter(([, info]) => info.startTime !== undefined).map(([, info]) => info.pid);
9476
+ if (guardedPids.length > 0) {
9477
+ try {
9478
+ const live = await getProcessStartTimes(guardedPids);
9479
+ for (const [token, info] of survivors) {
9480
+ if (info.startTime === undefined)
9481
+ continue;
9482
+ const lstart = live.get(info.pid);
9483
+ if (lstart === undefined)
9484
+ continue;
9485
+ if (lstart !== info.startTime)
9486
+ dead.push(token);
9436
9487
  }
9437
- }
9488
+ } catch {}
9438
9489
  }
9439
9490
  for (const t of dead)
9440
9491
  deregisterByToken(t);
@@ -19989,4 +20040,4 @@ main().catch((err) => {
19989
20040
  process.exit(EXIT.INTERNAL_ERROR);
19990
20041
  });
19991
20042
 
19992
- //# debugId=CD2B8A691C15D42A64756E2164756E21
20043
+ //# debugId=59AFA8DBDD2CE8AD64756E2164756E21