@sma1lboy/rove 0.9.71 → 0.9.73
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 +375 -374
- package/dist/cli/kobe-run.js +375 -374
- package/dist/cli/pty-host-node.mjs +38 -0
- package/dist/cli/rove-run.js +375 -374
- package/dist/skills/rove/SKILL.md +41 -1
- package/package.json +1 -1
|
@@ -186,6 +186,7 @@ async function nodePtyDriver(spawn) {
|
|
|
186
186
|
}
|
|
187
187
|
|
|
188
188
|
// ../kobe-daemon/src/daemon/pty-server.ts
|
|
189
|
+
import { readFileSync as readFileSync4 } from "node:fs";
|
|
189
190
|
import { mkdir as mkdir2, unlink as unlink2, writeFile } from "node:fs/promises";
|
|
190
191
|
import { createServer } from "node:net";
|
|
191
192
|
import { dirname as dirname3 } from "node:path";
|
|
@@ -1285,6 +1286,14 @@ class PtyHost {
|
|
|
1285
1286
|
|
|
1286
1287
|
// ../kobe-daemon/src/daemon/pty-server.ts
|
|
1287
1288
|
var DEFAULT_IDLE_EXIT_MS = 60000;
|
|
1289
|
+
var DEFAULT_ORPHAN_CHECK_MS = 30000;
|
|
1290
|
+
function resolveMaxLifetimeMs() {
|
|
1291
|
+
const raw = process.env.KOBE_PTY_MAX_LIFETIME_MS;
|
|
1292
|
+
if (raw === undefined)
|
|
1293
|
+
return null;
|
|
1294
|
+
const n = Number(raw);
|
|
1295
|
+
return Number.isFinite(n) && n > 0 ? n : null;
|
|
1296
|
+
}
|
|
1288
1297
|
function resolveIdleExitMs() {
|
|
1289
1298
|
const raw = process.env.KOBE_PTY_IDLE_EXIT_MS;
|
|
1290
1299
|
if (raw === undefined)
|
|
@@ -1297,6 +1306,9 @@ async function startPtyHostServer(options = {}) {
|
|
|
1297
1306
|
const pidPath = options.pidPath ?? defaultPtyHostPidPath();
|
|
1298
1307
|
const freezeDir = options.freezeDir ?? defaultPtyFreezeDir();
|
|
1299
1308
|
const idleExitMs = options.idleExitMs || resolveIdleExitMs();
|
|
1309
|
+
const orphanCheckMs = options.orphanCheckMs || DEFAULT_ORPHAN_CHECK_MS;
|
|
1310
|
+
const maxLifetimeMs = options.maxLifetimeMs ?? resolveMaxLifetimeMs();
|
|
1311
|
+
const bootedAtMs = Date.now();
|
|
1300
1312
|
const log = options.log ?? (() => {});
|
|
1301
1313
|
const clients = new Set;
|
|
1302
1314
|
let stopping = false;
|
|
@@ -1318,6 +1330,31 @@ async function startPtyHostServer(options = {}) {
|
|
|
1318
1330
|
stop();
|
|
1319
1331
|
}, idleExitMs);
|
|
1320
1332
|
};
|
|
1333
|
+
const orphaned = () => {
|
|
1334
|
+
if (maxLifetimeMs !== null && Date.now() - bootedAtMs >= maxLifetimeMs) {
|
|
1335
|
+
return `exceeded its ${maxLifetimeMs}ms lifetime ceiling`;
|
|
1336
|
+
}
|
|
1337
|
+
let owner;
|
|
1338
|
+
try {
|
|
1339
|
+
owner = readFileSync4(pidPath, "utf8").trim();
|
|
1340
|
+
} catch {
|
|
1341
|
+
return `pidfile ${pidPath} is gone`;
|
|
1342
|
+
}
|
|
1343
|
+
const pid = Number.parseInt(owner, 10);
|
|
1344
|
+
if (pid === process.pid)
|
|
1345
|
+
return null;
|
|
1346
|
+
return Number.isInteger(pid) ? `pidfile ${pidPath} now names pid ${pid}` : `pidfile ${pidPath} is unreadable`;
|
|
1347
|
+
};
|
|
1348
|
+
const orphanTimer = setInterval(() => {
|
|
1349
|
+
if (stopping)
|
|
1350
|
+
return;
|
|
1351
|
+
const reason = orphaned();
|
|
1352
|
+
if (!reason)
|
|
1353
|
+
return;
|
|
1354
|
+
log("orphan", `${reason} — exiting rather than outliving my owner`);
|
|
1355
|
+
stop();
|
|
1356
|
+
}, orphanCheckMs);
|
|
1357
|
+
orphanTimer.unref?.();
|
|
1321
1358
|
const ptys = new PtyHost({
|
|
1322
1359
|
onSessionStart: cancelIdle,
|
|
1323
1360
|
onSessionEnd: () => {
|
|
@@ -1371,6 +1408,7 @@ async function startPtyHostServer(options = {}) {
|
|
|
1371
1408
|
return;
|
|
1372
1409
|
stopping = true;
|
|
1373
1410
|
cancelIdle();
|
|
1411
|
+
clearInterval(orphanTimer);
|
|
1374
1412
|
await ptys.shutdown();
|
|
1375
1413
|
if (wipeFreezeOnStop)
|
|
1376
1414
|
clearFrozenSessions(freezeDir);
|