@sma1lboy/rove 0.9.72 → 0.9.74
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 +376 -375
- package/dist/cli/kobe-run.js +376 -375
- package/dist/cli/pty-host-node.mjs +61 -5
- package/dist/cli/rove-run.js +376 -375
- 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";
|
|
@@ -375,15 +376,33 @@ function frameToLine(frame) {
|
|
|
375
376
|
// ../kobe-daemon/src/daemon/pty-exit-store.ts
|
|
376
377
|
import { mkdirSync, readFileSync as readFileSync2, writeFileSync } from "node:fs";
|
|
377
378
|
import { dirname as dirname2 } from "node:path";
|
|
379
|
+
|
|
380
|
+
// ../kobe-daemon/src/daemon/terminal-rows.ts
|
|
381
|
+
var CURSOR_DOWN_RE = /\x1b\[(\d*)[BE]/g;
|
|
382
|
+
var CURSOR_POSITION_RE = /\x1b\[[\d;]*[Hf]/g;
|
|
383
|
+
var MAX_ROWS_PER_ESCAPE = 200;
|
|
384
|
+
var ANSI_RE = /\x1b\[[0-9;?]*[ -/]*[@-~]|\x1b\][^\x07\x1b]*(?:\x07|\x1b\\)?|\x1b[@-_]/g;
|
|
385
|
+
function breakRowsOnCursorMotion(raw) {
|
|
386
|
+
return raw.replace(CURSOR_DOWN_RE, (_m, count) => `
|
|
387
|
+
`.repeat(Math.min(MAX_ROWS_PER_ESCAPE, Math.max(1, Number.parseInt(count, 10) || 1)))).replace(CURSOR_POSITION_RE, `
|
|
388
|
+
`);
|
|
389
|
+
}
|
|
390
|
+
function terminalRows(raw, maxLineChars) {
|
|
391
|
+
const plain = breakRowsOnCursorMotion(raw).replace(ANSI_RE, "").replace(/\r\n/g, `
|
|
392
|
+
`);
|
|
393
|
+
return plain.split(`
|
|
394
|
+
`).map((line) => {
|
|
395
|
+
const overwritten = line.split("\r").pop() ?? "";
|
|
396
|
+
return maxLineChars === undefined ? overwritten : overwritten.slice(0, maxLineChars);
|
|
397
|
+
});
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
// ../kobe-daemon/src/daemon/pty-exit-store.ts
|
|
378
401
|
var MAX_RECORDS = 50;
|
|
379
402
|
var TAIL_LINES = 40;
|
|
380
403
|
var TAIL_LINE_CHARS = 500;
|
|
381
|
-
var ANSI_RE = /\x1b\[[0-9;?]*[ -/]*[@-~]|\x1b\][^\x07\x1b]*(?:\x07|\x1b\\)?|\x1b[@-_]/g;
|
|
382
404
|
function plainTail(raw) {
|
|
383
|
-
const
|
|
384
|
-
`);
|
|
385
|
-
const lines = plain.split(`
|
|
386
|
-
`).map((line) => (line.split("\r").pop() ?? "").slice(0, TAIL_LINE_CHARS));
|
|
405
|
+
const lines = terminalRows(raw, TAIL_LINE_CHARS);
|
|
387
406
|
while (lines.length > 0 && (lines[lines.length - 1] ?? "").trim() === "")
|
|
388
407
|
lines.pop();
|
|
389
408
|
return lines.slice(-TAIL_LINES);
|
|
@@ -1285,6 +1304,14 @@ class PtyHost {
|
|
|
1285
1304
|
|
|
1286
1305
|
// ../kobe-daemon/src/daemon/pty-server.ts
|
|
1287
1306
|
var DEFAULT_IDLE_EXIT_MS = 60000;
|
|
1307
|
+
var DEFAULT_ORPHAN_CHECK_MS = 30000;
|
|
1308
|
+
function resolveMaxLifetimeMs() {
|
|
1309
|
+
const raw = process.env.KOBE_PTY_MAX_LIFETIME_MS;
|
|
1310
|
+
if (raw === undefined)
|
|
1311
|
+
return null;
|
|
1312
|
+
const n = Number(raw);
|
|
1313
|
+
return Number.isFinite(n) && n > 0 ? n : null;
|
|
1314
|
+
}
|
|
1288
1315
|
function resolveIdleExitMs() {
|
|
1289
1316
|
const raw = process.env.KOBE_PTY_IDLE_EXIT_MS;
|
|
1290
1317
|
if (raw === undefined)
|
|
@@ -1297,6 +1324,9 @@ async function startPtyHostServer(options = {}) {
|
|
|
1297
1324
|
const pidPath = options.pidPath ?? defaultPtyHostPidPath();
|
|
1298
1325
|
const freezeDir = options.freezeDir ?? defaultPtyFreezeDir();
|
|
1299
1326
|
const idleExitMs = options.idleExitMs || resolveIdleExitMs();
|
|
1327
|
+
const orphanCheckMs = options.orphanCheckMs || DEFAULT_ORPHAN_CHECK_MS;
|
|
1328
|
+
const maxLifetimeMs = options.maxLifetimeMs ?? resolveMaxLifetimeMs();
|
|
1329
|
+
const bootedAtMs = Date.now();
|
|
1300
1330
|
const log = options.log ?? (() => {});
|
|
1301
1331
|
const clients = new Set;
|
|
1302
1332
|
let stopping = false;
|
|
@@ -1318,6 +1348,31 @@ async function startPtyHostServer(options = {}) {
|
|
|
1318
1348
|
stop();
|
|
1319
1349
|
}, idleExitMs);
|
|
1320
1350
|
};
|
|
1351
|
+
const orphaned = () => {
|
|
1352
|
+
if (maxLifetimeMs !== null && Date.now() - bootedAtMs >= maxLifetimeMs) {
|
|
1353
|
+
return `exceeded its ${maxLifetimeMs}ms lifetime ceiling`;
|
|
1354
|
+
}
|
|
1355
|
+
let owner;
|
|
1356
|
+
try {
|
|
1357
|
+
owner = readFileSync4(pidPath, "utf8").trim();
|
|
1358
|
+
} catch {
|
|
1359
|
+
return `pidfile ${pidPath} is gone`;
|
|
1360
|
+
}
|
|
1361
|
+
const pid = Number.parseInt(owner, 10);
|
|
1362
|
+
if (pid === process.pid)
|
|
1363
|
+
return null;
|
|
1364
|
+
return Number.isInteger(pid) ? `pidfile ${pidPath} now names pid ${pid}` : `pidfile ${pidPath} is unreadable`;
|
|
1365
|
+
};
|
|
1366
|
+
const orphanTimer = setInterval(() => {
|
|
1367
|
+
if (stopping)
|
|
1368
|
+
return;
|
|
1369
|
+
const reason = orphaned();
|
|
1370
|
+
if (!reason)
|
|
1371
|
+
return;
|
|
1372
|
+
log("orphan", `${reason} — exiting rather than outliving my owner`);
|
|
1373
|
+
stop();
|
|
1374
|
+
}, orphanCheckMs);
|
|
1375
|
+
orphanTimer.unref?.();
|
|
1321
1376
|
const ptys = new PtyHost({
|
|
1322
1377
|
onSessionStart: cancelIdle,
|
|
1323
1378
|
onSessionEnd: () => {
|
|
@@ -1371,6 +1426,7 @@ async function startPtyHostServer(options = {}) {
|
|
|
1371
1426
|
return;
|
|
1372
1427
|
stopping = true;
|
|
1373
1428
|
cancelIdle();
|
|
1429
|
+
clearInterval(orphanTimer);
|
|
1374
1430
|
await ptys.shutdown();
|
|
1375
1431
|
if (wipeFreezeOnStop)
|
|
1376
1432
|
clearFrozenSessions(freezeDir);
|