ragent-cli 1.7.0 → 1.7.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.
- package/dist/index.js +85 -33
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -31,7 +31,7 @@ var require_package = __commonJS({
|
|
|
31
31
|
"package.json"(exports2, module2) {
|
|
32
32
|
module2.exports = {
|
|
33
33
|
name: "ragent-cli",
|
|
34
|
-
version: "1.7.
|
|
34
|
+
version: "1.7.2",
|
|
35
35
|
description: "CLI agent for rAgent Live \u2014 browser-first terminal control plane for AI coding agents",
|
|
36
36
|
main: "dist/index.js",
|
|
37
37
|
bin: {
|
|
@@ -575,14 +575,17 @@ async function collectSessionInventory(hostId, command) {
|
|
|
575
575
|
for (const s of [...screen, ...zellij]) {
|
|
576
576
|
if (s.pids) s.pids.forEach((p) => multiplexerPids.add(p));
|
|
577
577
|
}
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
578
|
+
const tmuxChildTasks = tmux.flatMap(
|
|
579
|
+
(s) => (s.pids ?? []).map(async (pid) => ({ session: s, pid, childInfo: await getChildAgentInfo(pid) }))
|
|
580
|
+
);
|
|
581
|
+
const tmuxChildResults = await Promise.all(tmuxChildTasks);
|
|
582
|
+
for (const { session: s, pid, childInfo } of tmuxChildResults) {
|
|
583
|
+
multiplexerPids.add(pid);
|
|
584
|
+
if (childInfo) {
|
|
585
|
+
childInfo.childPids.forEach((p) => multiplexerPids.add(p));
|
|
586
|
+
if (!s.agentType && childInfo.agentType) {
|
|
587
|
+
s.agentType = childInfo.agentType;
|
|
588
|
+
s.command = childInfo.command;
|
|
586
589
|
}
|
|
587
590
|
}
|
|
588
591
|
}
|
|
@@ -606,12 +609,13 @@ function detectAgentType(command) {
|
|
|
606
609
|
const cmd = command.toLowerCase();
|
|
607
610
|
const parts = cmd.split(/\s+/);
|
|
608
611
|
const binary = parts[0]?.split("/").pop() ?? "";
|
|
609
|
-
const
|
|
610
|
-
|
|
612
|
+
const rawScriptArg = binary === "node" && parts[1] ? parts[1].split("/").pop() ?? "" : "";
|
|
613
|
+
const scriptArg = rawScriptArg.replace(/\.m?js$/, "");
|
|
614
|
+
if (binary === "claude" || binary === "claude-code" || scriptArg === "cli" && cmd.includes("claude-code")) {
|
|
611
615
|
if (cmd.includes("--chrome-native-host")) return void 0;
|
|
612
616
|
return "Claude Code";
|
|
613
617
|
}
|
|
614
|
-
if (binary === "codex" || scriptArg === "codex" || cmd.includes("codex-cli")) return "Codex CLI";
|
|
618
|
+
if (binary === "codex" || scriptArg === "codex" && cmd.includes("@openai/codex") || cmd.includes("codex-cli")) return "Codex CLI";
|
|
615
619
|
if (binary === "aider") return "aider";
|
|
616
620
|
if (binary === "cursor") {
|
|
617
621
|
if (isElectronProcess(cmd)) return void 0;
|
|
@@ -621,9 +625,9 @@ function detectAgentType(command) {
|
|
|
621
625
|
if (isElectronProcess(cmd)) return void 0;
|
|
622
626
|
return "Windsurf";
|
|
623
627
|
}
|
|
624
|
-
if (binary === "gemini") return "Gemini CLI";
|
|
628
|
+
if (binary === "gemini" || scriptArg === "gemini" && cmd.includes("gemini-cli")) return "Gemini CLI";
|
|
625
629
|
if (binary === "amazon-q" || binary === "amazon_q") return "Amazon Q";
|
|
626
|
-
if (binary === "copilot") return "Copilot CLI";
|
|
630
|
+
if (binary === "copilot" || scriptArg === "copilot" && cmd.includes("@github/copilot")) return "Copilot CLI";
|
|
627
631
|
return void 0;
|
|
628
632
|
}
|
|
629
633
|
function sessionInventoryFingerprint(sessions) {
|
|
@@ -1289,18 +1293,32 @@ var SessionStreamer = class {
|
|
|
1289
1293
|
if (!paneTarget || !cleanEnv) return false;
|
|
1290
1294
|
stream.initializing = true;
|
|
1291
1295
|
try {
|
|
1296
|
+
let alternateScreen = false;
|
|
1292
1297
|
try {
|
|
1293
|
-
const
|
|
1298
|
+
const altFlag = (0, import_node_child_process2.execFileSync)(
|
|
1294
1299
|
"tmux",
|
|
1295
|
-
["
|
|
1296
|
-
{ env: cleanEnv, timeout:
|
|
1297
|
-
);
|
|
1298
|
-
|
|
1299
|
-
this.sendFn(sessionId, scrollback.replace(/\n/g, "\r\n"));
|
|
1300
|
-
}
|
|
1300
|
+
["display-message", "-t", paneTarget, "-p", "#{alternate_on}"],
|
|
1301
|
+
{ env: cleanEnv, timeout: 5e3, encoding: "utf-8" }
|
|
1302
|
+
).trim();
|
|
1303
|
+
alternateScreen = altFlag === "1";
|
|
1301
1304
|
} catch {
|
|
1302
1305
|
}
|
|
1303
|
-
|
|
1306
|
+
if (alternateScreen) {
|
|
1307
|
+
this.sendFn(sessionId, "\x1B[?1049h\x1B[0m\x1B[2J\x1B[H");
|
|
1308
|
+
} else {
|
|
1309
|
+
try {
|
|
1310
|
+
const scrollback = (0, import_node_child_process2.execFileSync)(
|
|
1311
|
+
"tmux",
|
|
1312
|
+
["capture-pane", "-t", paneTarget, "-p", "-e", "-S", "-5000", "-E", "-1"],
|
|
1313
|
+
{ env: cleanEnv, timeout: 1e4, encoding: "utf-8" }
|
|
1314
|
+
);
|
|
1315
|
+
if (scrollback && scrollback.length > 0) {
|
|
1316
|
+
this.sendFn(sessionId, scrollback.replace(/\n/g, "\r\n"));
|
|
1317
|
+
}
|
|
1318
|
+
} catch {
|
|
1319
|
+
}
|
|
1320
|
+
this.sendFn(sessionId, "\x1B[?1049l\x1B[0m\x1B[2J\x1B[H");
|
|
1321
|
+
}
|
|
1304
1322
|
try {
|
|
1305
1323
|
const initial = (0, import_node_child_process2.execFileSync)(
|
|
1306
1324
|
"tmux",
|
|
@@ -1414,18 +1432,33 @@ var SessionStreamer = class {
|
|
|
1414
1432
|
this.onStreamStopped?.(sessionId);
|
|
1415
1433
|
}
|
|
1416
1434
|
});
|
|
1435
|
+
let alternateScreen = false;
|
|
1417
1436
|
try {
|
|
1418
|
-
const
|
|
1437
|
+
const altFlag = (0, import_node_child_process2.execFileSync)(
|
|
1419
1438
|
"tmux",
|
|
1420
|
-
["
|
|
1421
|
-
{ env: cleanEnv, timeout:
|
|
1422
|
-
);
|
|
1423
|
-
|
|
1424
|
-
this.sendFn(sessionId, scrollback.replace(/\n/g, "\r\n"));
|
|
1425
|
-
}
|
|
1439
|
+
["display-message", "-t", paneTarget, "-p", "#{alternate_on}"],
|
|
1440
|
+
{ env: cleanEnv, timeout: 5e3, encoding: "utf-8" }
|
|
1441
|
+
).trim();
|
|
1442
|
+
alternateScreen = altFlag === "1";
|
|
1426
1443
|
} catch {
|
|
1427
1444
|
}
|
|
1428
|
-
|
|
1445
|
+
stream.alternateScreen = alternateScreen;
|
|
1446
|
+
if (alternateScreen) {
|
|
1447
|
+
this.sendFn(sessionId, "\x1B[?1049h\x1B[0m\x1B[2J\x1B[H");
|
|
1448
|
+
} else {
|
|
1449
|
+
try {
|
|
1450
|
+
const scrollback = (0, import_node_child_process2.execFileSync)(
|
|
1451
|
+
"tmux",
|
|
1452
|
+
["capture-pane", "-t", paneTarget, "-p", "-e", "-S", "-5000", "-E", "-1"],
|
|
1453
|
+
{ env: cleanEnv, timeout: 1e4, encoding: "utf-8" }
|
|
1454
|
+
);
|
|
1455
|
+
if (scrollback && scrollback.length > 0) {
|
|
1456
|
+
this.sendFn(sessionId, scrollback.replace(/\n/g, "\r\n"));
|
|
1457
|
+
}
|
|
1458
|
+
} catch {
|
|
1459
|
+
}
|
|
1460
|
+
this.sendFn(sessionId, "\x1B[?1049l\x1B[0m\x1B[2J\x1B[H");
|
|
1461
|
+
}
|
|
1429
1462
|
try {
|
|
1430
1463
|
const initial = (0, import_node_child_process2.execFileSync)(
|
|
1431
1464
|
"tmux",
|
|
@@ -1573,8 +1606,18 @@ var SessionStreamer = class {
|
|
|
1573
1606
|
if (!pid) return false;
|
|
1574
1607
|
if (!(0, import_node_fs.existsSync)(`/proc/${pid}`)) {
|
|
1575
1608
|
console.warn(`[rAgent] Process ${pid} does not exist (no /proc/${pid}).`);
|
|
1609
|
+
this.sendFn(sessionId, "\r\n[rAgent] Process is no longer running. It will be removed on next sync.\r\n");
|
|
1576
1610
|
return false;
|
|
1577
1611
|
}
|
|
1612
|
+
try {
|
|
1613
|
+
const stat = (0, import_node_fs.readFileSync)(`/proc/${pid}/stat`, "utf8");
|
|
1614
|
+
if (stat.includes(") Z")) {
|
|
1615
|
+
console.warn(`[rAgent] Process ${pid} is a zombie.`);
|
|
1616
|
+
this.sendFn(sessionId, "\r\n[rAgent] Process has exited (zombie). It will be removed on next sync.\r\n");
|
|
1617
|
+
return false;
|
|
1618
|
+
}
|
|
1619
|
+
} catch {
|
|
1620
|
+
}
|
|
1578
1621
|
try {
|
|
1579
1622
|
const straceProc = (0, import_node_child_process2.spawn)(
|
|
1580
1623
|
"strace",
|
|
@@ -1632,7 +1675,11 @@ var SessionStreamer = class {
|
|
|
1632
1675
|
const remaining = stream.utf8Decoder.end();
|
|
1633
1676
|
if (remaining) this.sendFn(sessionId, remaining);
|
|
1634
1677
|
if (code === 1) {
|
|
1635
|
-
|
|
1678
|
+
if (pid && !(0, import_node_fs.existsSync)(`/proc/${pid}`)) {
|
|
1679
|
+
this.sendFn(sessionId, "\r\n[rAgent] Process has exited. It will be removed on next sync.\r\n");
|
|
1680
|
+
} else {
|
|
1681
|
+
this.sendFn(sessionId, "\r\n[rAgent] Permission denied: cannot attach to process.\r\nTo enable process tracing, run:\r\n sudo sysctl kernel.yama.ptrace_scope=0\r\n");
|
|
1682
|
+
}
|
|
1636
1683
|
}
|
|
1637
1684
|
stream.stopped = true;
|
|
1638
1685
|
this.active.delete(sessionId);
|
|
@@ -2723,8 +2770,13 @@ var ControlDispatcher = class {
|
|
|
2723
2770
|
process.kill(pid, "SIGTERM");
|
|
2724
2771
|
console.log(`[rAgent] Sent SIGTERM to process ${pid} (${sessionId}).`);
|
|
2725
2772
|
} catch (error) {
|
|
2726
|
-
const
|
|
2727
|
-
|
|
2773
|
+
const code = error.code;
|
|
2774
|
+
if (code === "ESRCH") {
|
|
2775
|
+
console.log(`[rAgent] Process ${pid} already exited, cleaning up.`);
|
|
2776
|
+
} else {
|
|
2777
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
2778
|
+
console.warn(`[rAgent] Failed to kill process ${pid}: ${message}`);
|
|
2779
|
+
}
|
|
2728
2780
|
}
|
|
2729
2781
|
await this.syncInventory();
|
|
2730
2782
|
}
|