@dmsdc-ai/aigentry-telepty 0.1.89 → 0.1.90
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/cli.js +65 -19
- package/package.json +1 -1
package/cli.js
CHANGED
|
@@ -357,6 +357,61 @@ function startDetachedDaemon() {
|
|
|
357
357
|
cp.unref();
|
|
358
358
|
}
|
|
359
359
|
|
|
360
|
+
async function waitForDaemonHealth(maxMs = 5000) {
|
|
361
|
+
const deadline = Date.now() + maxMs;
|
|
362
|
+
while (Date.now() < deadline) {
|
|
363
|
+
try {
|
|
364
|
+
const meta = await getDaemonMeta('127.0.0.1');
|
|
365
|
+
if (meta && meta.version) return meta;
|
|
366
|
+
} catch {}
|
|
367
|
+
await new Promise(r => setTimeout(r, 300));
|
|
368
|
+
}
|
|
369
|
+
return null;
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
async function restartDaemonGraceful(options = {}) {
|
|
373
|
+
const maxAttempts = options.maxAttempts || 3;
|
|
374
|
+
const requiredCapabilities = options.requiredCapabilities || [];
|
|
375
|
+
|
|
376
|
+
for (let attempt = 1; attempt <= maxAttempts; attempt++) {
|
|
377
|
+
// (a) Kill existing daemon processes
|
|
378
|
+
const results = cleanupDaemonProcesses();
|
|
379
|
+
|
|
380
|
+
// (b) Wait up to 3s for old processes to fully exit
|
|
381
|
+
if (results.stopped.length > 0) {
|
|
382
|
+
const { isProcessRunning } = require('./daemon-control');
|
|
383
|
+
const killDeadline = Date.now() + 3000;
|
|
384
|
+
for (const item of results.stopped) {
|
|
385
|
+
while (Date.now() < killDeadline && isProcessRunning(item.pid)) {
|
|
386
|
+
await new Promise(r => setTimeout(r, 100));
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
// (c) Start new daemon
|
|
392
|
+
startDetachedDaemon();
|
|
393
|
+
|
|
394
|
+
// (d) Wait for new daemon to respond with correct version
|
|
395
|
+
const meta = await waitForDaemonHealth(5000);
|
|
396
|
+
if (meta && meta.version === pkg.version) {
|
|
397
|
+
const hasCapabilities = requiredCapabilities.every(c => (meta.capabilities || []).includes(c));
|
|
398
|
+
if (hasCapabilities || requiredCapabilities.length === 0) {
|
|
399
|
+
return { success: true, meta, attempt };
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
// Retry with backoff
|
|
404
|
+
if (attempt < maxAttempts) {
|
|
405
|
+
const backoff = 1000 * attempt;
|
|
406
|
+
process.stdout.write(`\x1b[33m⚠️ Daemon restart attempt ${attempt}/${maxAttempts} failed. Retrying in ${backoff / 1000}s...\x1b[0m\n`);
|
|
407
|
+
await new Promise(r => setTimeout(r, backoff));
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
console.error(`\x1b[31m❌ Daemon restart failed after ${maxAttempts} attempts. Run "telepty daemon" manually to start.\x1b[0m`);
|
|
412
|
+
return { success: false, meta: null, attempt: maxAttempts };
|
|
413
|
+
}
|
|
414
|
+
|
|
360
415
|
function renderInteractiveHeader() {
|
|
361
416
|
const runtimeInfo = getRuntimeInfo(__dirname);
|
|
362
417
|
console.clear();
|
|
@@ -403,14 +458,13 @@ async function repairLocalDaemon(options = {}) {
|
|
|
403
458
|
return { stopped: results.stopped.length, failed: results.failed.length, meta: null };
|
|
404
459
|
}
|
|
405
460
|
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
}
|
|
413
|
-
return { stopped: results.stopped.length, failed: results.failed.length, meta, versionMatch };
|
|
461
|
+
const restartResult = await restartDaemonGraceful();
|
|
462
|
+
return {
|
|
463
|
+
stopped: results.stopped.length,
|
|
464
|
+
failed: results.failed.length,
|
|
465
|
+
meta: restartResult.meta,
|
|
466
|
+
versionMatch: restartResult.success
|
|
467
|
+
};
|
|
414
468
|
}
|
|
415
469
|
|
|
416
470
|
function getDiscoveryHosts() {
|
|
@@ -477,30 +531,22 @@ async function ensureDaemonRunning(options = {}) {
|
|
|
477
531
|
// Version mismatch: running daemon is older than installed CLI
|
|
478
532
|
if (meta && meta.version !== pkg.version) {
|
|
479
533
|
process.stdout.write(`\x1b[33m⚙️ Daemon version mismatch (running v${meta.version}, installed v${pkg.version}). Restarting...\x1b[0m\n`);
|
|
480
|
-
|
|
534
|
+
await restartDaemonGraceful({ requiredCapabilities });
|
|
535
|
+
return;
|
|
481
536
|
} else {
|
|
482
537
|
return;
|
|
483
538
|
}
|
|
484
539
|
} else if (sessionsRes.ok && !meta) {
|
|
485
540
|
process.stdout.write('\x1b[33m⚙️ Found an older local telepty daemon. Restarting it...\x1b[0m\n');
|
|
486
|
-
cleanupDaemonProcesses();
|
|
487
541
|
} else if (sessionsRes.ok && meta) {
|
|
488
542
|
process.stdout.write('\x1b[33m⚙️ Found a local telepty daemon without the required features. Restarting it...\x1b[0m\n');
|
|
489
|
-
cleanupDaemonProcesses();
|
|
490
543
|
}
|
|
491
544
|
} catch (e) {
|
|
492
545
|
// Continue to auto-start below.
|
|
493
546
|
}
|
|
494
547
|
|
|
495
548
|
process.stdout.write('\x1b[33m⚙️ Auto-starting local telepty daemon...\x1b[0m\n');
|
|
496
|
-
|
|
497
|
-
startDetachedDaemon();
|
|
498
|
-
await new Promise(r => setTimeout(r, 1000));
|
|
499
|
-
|
|
500
|
-
const meta = await getDaemonMeta('127.0.0.1');
|
|
501
|
-
if (!meta || !requiredCapabilities.every((item) => meta.capabilities.includes(item))) {
|
|
502
|
-
console.error('❌ Failed to start a compatible local telepty daemon. Open telepty and choose "Repair local daemon", or rerun the installer.');
|
|
503
|
-
}
|
|
549
|
+
await restartDaemonGraceful({ requiredCapabilities });
|
|
504
550
|
}
|
|
505
551
|
|
|
506
552
|
async function manageInteractiveAttach(sessionId, targetHost) {
|