cli-remote-agent 1.0.6 → 1.0.7

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.js CHANGED
@@ -427,6 +427,51 @@ var init_local_control = __esm({
427
427
  }
428
428
  });
429
429
 
430
+ // src/pty-helper-fix.ts
431
+ function ensurePtyHelperExecutable() {
432
+ if (process.platform === "win32") return;
433
+ try {
434
+ const nodeRequire = (0, import_node_module.createRequire)(__filename);
435
+ const ptyMain = nodeRequire.resolve("node-pty");
436
+ const ptyDir = import_path3.default.dirname(import_path3.default.dirname(ptyMain));
437
+ const candidates = [import_path3.default.join(ptyDir, "build", "Release", "spawn-helper")];
438
+ const prebuilds = import_path3.default.join(ptyDir, "prebuilds");
439
+ try {
440
+ for (const d of import_fs4.default.readdirSync(prebuilds)) {
441
+ candidates.push(import_path3.default.join(prebuilds, d, "spawn-helper"));
442
+ }
443
+ } catch {
444
+ }
445
+ for (const file of candidates) {
446
+ try {
447
+ const mode = import_fs4.default.statSync(file).mode;
448
+ if (!(mode & 73)) {
449
+ import_fs4.default.chmodSync(file, mode | 493);
450
+ logger.info({ file }, "Restored execute bit on node-pty spawn-helper");
451
+ }
452
+ } catch {
453
+ }
454
+ }
455
+ if (process.platform === "darwin") {
456
+ (0, import_node_child_process.execFile)("xattr", ["-dr", "com.apple.quarantine", ptyDir], () => {
457
+ });
458
+ }
459
+ } catch (err) {
460
+ logger.warn({ error: err?.message }, "Could not verify node-pty spawn-helper permissions");
461
+ }
462
+ }
463
+ var import_node_module, import_node_child_process, import_fs4, import_path3;
464
+ var init_pty_helper_fix = __esm({
465
+ "src/pty-helper-fix.ts"() {
466
+ "use strict";
467
+ import_node_module = require("module");
468
+ import_node_child_process = require("child_process");
469
+ import_fs4 = __toESM(require("fs"));
470
+ import_path3 = __toESM(require("path"));
471
+ init_logger();
472
+ }
473
+ });
474
+
430
475
  // src/claude-live.ts
431
476
  function isAlive(pid) {
432
477
  try {
@@ -439,14 +484,14 @@ function isAlive(pid) {
439
484
  function getLiveClaudeSessions() {
440
485
  let files;
441
486
  try {
442
- files = import_fs4.default.readdirSync(LIVE_SESSIONS_DIR).filter((f) => f.endsWith(".json"));
487
+ files = import_fs5.default.readdirSync(LIVE_SESSIONS_DIR).filter((f) => f.endsWith(".json"));
443
488
  } catch {
444
489
  return [];
445
490
  }
446
491
  const out = [];
447
492
  for (const f of files) {
448
493
  try {
449
- const obj = JSON.parse(import_fs4.default.readFileSync(import_path3.default.join(LIVE_SESSIONS_DIR, f), "utf-8"));
494
+ const obj = JSON.parse(import_fs5.default.readFileSync(import_path4.default.join(LIVE_SESSIONS_DIR, f), "utf-8"));
450
495
  if (typeof obj?.pid !== "number" || !isAlive(obj.pid)) continue;
451
496
  out.push({
452
497
  pid: obj.pid,
@@ -481,31 +526,31 @@ function isDescendantOf(pid, ancestor, parents) {
481
526
  }
482
527
  return false;
483
528
  }
484
- var import_fs4, import_path3, import_os2, import_child_process, import_util, execFileAsync, LIVE_SESSIONS_DIR;
529
+ var import_fs5, import_path4, import_os2, import_child_process, import_util, execFileAsync, LIVE_SESSIONS_DIR;
485
530
  var init_claude_live = __esm({
486
531
  "src/claude-live.ts"() {
487
532
  "use strict";
488
- import_fs4 = __toESM(require("fs"));
489
- import_path3 = __toESM(require("path"));
533
+ import_fs5 = __toESM(require("fs"));
534
+ import_path4 = __toESM(require("path"));
490
535
  import_os2 = __toESM(require("os"));
491
536
  import_child_process = require("child_process");
492
537
  import_util = require("util");
493
538
  execFileAsync = (0, import_util.promisify)(import_child_process.execFile);
494
- LIVE_SESSIONS_DIR = import_path3.default.join(import_os2.default.homedir(), ".claude", "sessions");
539
+ LIVE_SESSIONS_DIR = import_path4.default.join(import_os2.default.homedir(), ".claude", "sessions");
495
540
  }
496
541
  });
497
542
 
498
543
  // src/tmux.ts
499
544
  function resolveTmuxPath() {
500
545
  if (cachedTmuxPath !== void 0) return cachedTmuxPath;
501
- const dirs = (process.env.PATH || "").split(import_path4.default.delimiter).filter(Boolean);
546
+ const dirs = (process.env.PATH || "").split(import_path5.default.delimiter).filter(Boolean);
502
547
  for (const extra of ["/opt/homebrew/bin", "/usr/local/bin", "/usr/bin", "/bin", "/opt/local/bin"]) {
503
548
  if (!dirs.includes(extra)) dirs.push(extra);
504
549
  }
505
550
  for (const dir of dirs) {
506
- const candidate = import_path4.default.join(dir, "tmux");
551
+ const candidate = import_path5.default.join(dir, "tmux");
507
552
  try {
508
- import_fs5.default.accessSync(candidate, import_fs5.default.constants.X_OK);
553
+ import_fs6.default.accessSync(candidate, import_fs6.default.constants.X_OK);
509
554
  cachedTmuxPath = candidate;
510
555
  return candidate;
511
556
  } catch {
@@ -555,8 +600,8 @@ async function enrichWithPanesAndClaude(sessions2) {
555
600
  const { file, args } = tmuxCmd(["list-panes", "-a", "-F", paneFmt]);
556
601
  const { stdout } = await execFileAsync2(file, args, { timeout: 6e3 });
557
602
  const panes = stdout.split("\n").map((line) => line.replace(/\r$/, "").trim()).filter(Boolean).map((line) => {
558
- const [session, pid, path9, activeFlags] = line.split(" ");
559
- return { session, pid: parseInt(pid, 10) || 0, path: path9 || "", active: activeFlags === "11" };
603
+ const [session, pid, path10, activeFlags] = line.split(" ");
604
+ return { session, pid: parseInt(pid, 10) || 0, path: path10 || "", active: activeFlags === "11" };
560
605
  });
561
606
  const byName = new Map(sessions2.map((s) => [s.name, s]));
562
607
  for (const pane of panes) {
@@ -595,14 +640,14 @@ function buildTmuxLaunch(name, launch) {
595
640
  if (trimmed) args.push(trimmed);
596
641
  return { file: tmuxBin, args };
597
642
  }
598
- var import_child_process2, import_util2, import_fs5, import_path4, execFileAsync2, IS_WIN, cachedTmuxPath;
643
+ var import_child_process2, import_util2, import_fs6, import_path5, execFileAsync2, IS_WIN, cachedTmuxPath;
599
644
  var init_tmux = __esm({
600
645
  "src/tmux.ts"() {
601
646
  "use strict";
602
647
  import_child_process2 = require("child_process");
603
648
  import_util2 = require("util");
604
- import_fs5 = __toESM(require("fs"));
605
- import_path4 = __toESM(require("path"));
649
+ import_fs6 = __toESM(require("fs"));
650
+ import_path5 = __toESM(require("path"));
606
651
  init_claude_live();
607
652
  execFileAsync2 = (0, import_util2.promisify)(import_child_process2.execFile);
608
653
  IS_WIN = process.platform === "win32";
@@ -632,15 +677,15 @@ var init_shell = __esm({
632
677
 
633
678
  // src/pty-session.ts
634
679
  function ensureInitFiles() {
635
- const versionFile = (0, import_path5.join)(INIT_DIR, ".version");
636
- if ((0, import_fs6.existsSync)(versionFile)) {
680
+ const versionFile = (0, import_path6.join)(INIT_DIR, ".version");
681
+ if ((0, import_fs7.existsSync)(versionFile)) {
637
682
  try {
638
- if ((0, import_fs6.readFileSync)(versionFile, "utf-8").trim() === INIT_VERSION) return;
683
+ if ((0, import_fs7.readFileSync)(versionFile, "utf-8").trim() === INIT_VERSION) return;
639
684
  } catch {
640
685
  }
641
686
  }
642
- (0, import_fs6.mkdirSync)(ZSH_DIR, { recursive: true });
643
- (0, import_fs6.writeFileSync)(BASH_INIT, [
687
+ (0, import_fs7.mkdirSync)(ZSH_DIR, { recursive: true });
688
+ (0, import_fs7.writeFileSync)(BASH_INIT, [
644
689
  "[ -f ~/.bash_profile ] && source ~/.bash_profile",
645
690
  "[ -f ~/.bashrc ] && source ~/.bashrc",
646
691
  "__crc_s=$SECONDS",
@@ -651,11 +696,11 @@ function ensureInitFiles() {
651
696
  `PROMPT_COMMAND='[ "$__crc_armed" = 1 ] && [ \${__crc_elapsed:-0} -ge ${THRESHOLD} ] && printf "\\a"; __crc_armed=1; eval "$__crc_orig_pc"'`,
652
697
  ""
653
698
  ].join("\n"), "utf-8");
654
- (0, import_fs6.writeFileSync)(ZSH_ENV, [
699
+ (0, import_fs7.writeFileSync)(ZSH_ENV, [
655
700
  '[ -f "${ZDOTDIR_ORIG:-$HOME}/.zshenv" ] && source "${ZDOTDIR_ORIG:-$HOME}/.zshenv"',
656
701
  ""
657
702
  ].join("\n"), "utf-8");
658
- (0, import_fs6.writeFileSync)(ZSH_RC, [
703
+ (0, import_fs7.writeFileSync)(ZSH_RC, [
659
704
  '[ -f "${ZDOTDIR_ORIG:-$HOME}/.zshrc" ] && source "${ZDOTDIR_ORIG:-$HOME}/.zshrc"',
660
705
  "__crc_s=$SECONDS",
661
706
  "__crc_armed=0",
@@ -668,36 +713,36 @@ function ensureInitFiles() {
668
713
  "fi",
669
714
  ""
670
715
  ].join("\n"), "utf-8");
671
- (0, import_fs6.writeFileSync)(versionFile, INIT_VERSION, "utf-8");
716
+ (0, import_fs7.writeFileSync)(versionFile, INIT_VERSION, "utf-8");
672
717
  }
673
718
  function resolveCwd(cwd) {
674
719
  const candidates = process.platform === "win32" ? [cwd, (0, import_os3.homedir)(), process.env.USERPROFILE, process.env.HOME] : [cwd, (0, import_os3.homedir)(), process.env.HOME, process.env.USERPROFILE];
675
720
  for (const c of candidates) {
676
721
  if (c) {
677
722
  try {
678
- if ((0, import_fs6.existsSync)(c)) return c;
723
+ if ((0, import_fs7.existsSync)(c)) return c;
679
724
  } catch {
680
725
  }
681
726
  }
682
727
  }
683
728
  return (0, import_os3.homedir)();
684
729
  }
685
- var pty, import_fs6, import_path5, import_os3, THRESHOLD, INIT_DIR, BASH_INIT, ZSH_DIR, ZSH_RC, ZSH_ENV, INIT_VERSION, PtySession;
730
+ var pty, import_fs7, import_path6, import_os3, THRESHOLD, INIT_DIR, BASH_INIT, ZSH_DIR, ZSH_RC, ZSH_ENV, INIT_VERSION, PtySession;
686
731
  var init_pty_session = __esm({
687
732
  "src/pty-session.ts"() {
688
733
  "use strict";
689
734
  pty = __toESM(require("node-pty"));
690
- import_fs6 = require("fs");
691
- import_path5 = require("path");
735
+ import_fs7 = require("fs");
736
+ import_path6 = require("path");
692
737
  import_os3 = require("os");
693
738
  init_src();
694
739
  init_shell();
695
740
  THRESHOLD = 3;
696
- INIT_DIR = (0, import_path5.join)((0, import_os3.tmpdir)(), "crc-shell-init");
697
- BASH_INIT = (0, import_path5.join)(INIT_DIR, "bashrc");
698
- ZSH_DIR = (0, import_path5.join)(INIT_DIR, "zsh");
699
- ZSH_RC = (0, import_path5.join)(ZSH_DIR, ".zshrc");
700
- ZSH_ENV = (0, import_path5.join)(ZSH_DIR, ".zshenv");
741
+ INIT_DIR = (0, import_path6.join)((0, import_os3.tmpdir)(), "crc-shell-init");
742
+ BASH_INIT = (0, import_path6.join)(INIT_DIR, "bashrc");
743
+ ZSH_DIR = (0, import_path6.join)(INIT_DIR, "zsh");
744
+ ZSH_RC = (0, import_path6.join)(ZSH_DIR, ".zshrc");
745
+ ZSH_ENV = (0, import_path6.join)(ZSH_DIR, ".zshenv");
701
746
  INIT_VERSION = "2";
702
747
  PtySession = class {
703
748
  id;
@@ -927,18 +972,18 @@ function buildHeartbeat(homeDir) {
927
972
  memoryUsage: Math.round((totalMem - freeMem) / totalMem * 100),
928
973
  uptime: Math.round(import_os4.default.uptime()),
929
974
  activeSessions: getActiveSessionCount(),
930
- pathSeparator: import_path6.default.sep,
975
+ pathSeparator: import_path7.default.sep,
931
976
  homeDirectory: homeDir || import_os4.default.homedir(),
932
977
  rootPaths: getRootPaths(),
933
978
  capabilities: { terminal: true, fileTransfer: false }
934
979
  };
935
980
  }
936
- var import_os4, import_path6, import_child_process4, prevCpu;
981
+ var import_os4, import_path7, import_child_process4, prevCpu;
937
982
  var init_heartbeat = __esm({
938
983
  "src/heartbeat.ts"() {
939
984
  "use strict";
940
985
  import_os4 = __toESM(require("os"));
941
- import_path6 = __toESM(require("path"));
986
+ import_path7 = __toESM(require("path"));
942
987
  import_child_process4 = require("child_process");
943
988
  init_terminal_manager();
944
989
  prevCpu = null;
@@ -947,28 +992,28 @@ var init_heartbeat = __esm({
947
992
 
948
993
  // src/file-explorer.ts
949
994
  function isInSecretDir(resolved) {
950
- const rel = import_path7.default.relative(SECRET_DIR, resolved);
951
- return rel === "" || !rel.startsWith(".." + import_path7.default.sep) && rel !== ".." && !import_path7.default.isAbsolute(rel);
995
+ const rel = import_path8.default.relative(SECRET_DIR, resolved);
996
+ return rel === "" || !rel.startsWith(".." + import_path8.default.sep) && rel !== ".." && !import_path8.default.isAbsolute(rel);
952
997
  }
953
998
  function listDirectory(dirPath) {
954
999
  try {
955
- const resolved = import_path7.default.resolve(dirPath);
1000
+ const resolved = import_path8.default.resolve(dirPath);
956
1001
  if (isInSecretDir(resolved)) {
957
1002
  return { entries: [], error: "Access denied" };
958
1003
  }
959
- if (!import_fs7.default.existsSync(resolved)) {
1004
+ if (!import_fs8.default.existsSync(resolved)) {
960
1005
  return { entries: [], error: "Path does not exist" };
961
1006
  }
962
- const stat = import_fs7.default.statSync(resolved);
1007
+ const stat = import_fs8.default.statSync(resolved);
963
1008
  if (!stat.isDirectory()) {
964
1009
  return { entries: [], error: "Not a directory" };
965
1010
  }
966
- const dirents = import_fs7.default.readdirSync(resolved, { withFileTypes: true });
1011
+ const dirents = import_fs8.default.readdirSync(resolved, { withFileTypes: true });
967
1012
  const entries = [];
968
1013
  for (const dirent of dirents) {
969
1014
  try {
970
- const fullPath = import_path7.default.join(resolved, dirent.name);
971
- const s = import_fs7.default.statSync(fullPath);
1015
+ const fullPath = import_path8.default.join(resolved, dirent.name);
1016
+ const s = import_fs8.default.statSync(fullPath);
972
1017
  entries.push({
973
1018
  name: dirent.name,
974
1019
  isDirectory: dirent.isDirectory(),
@@ -990,22 +1035,22 @@ function listDirectory(dirPath) {
990
1035
  }
991
1036
  async function downloadFile(filePath, serverUrl, secret, agentId) {
992
1037
  try {
993
- const resolved = import_path7.default.resolve(filePath);
1038
+ const resolved = import_path8.default.resolve(filePath);
994
1039
  if (isInSecretDir(resolved)) {
995
1040
  return { error: "Access denied" };
996
1041
  }
997
- if (!import_fs7.default.existsSync(resolved)) {
1042
+ if (!import_fs8.default.existsSync(resolved)) {
998
1043
  return { error: "File does not exist" };
999
1044
  }
1000
- const stat = import_fs7.default.statSync(resolved);
1045
+ const stat = import_fs8.default.statSync(resolved);
1001
1046
  if (stat.isDirectory()) {
1002
1047
  return { error: "Cannot download a directory" };
1003
1048
  }
1004
1049
  if (stat.size > FILE_MAX_SIZE) {
1005
1050
  return { error: `File too large (max ${FILE_MAX_SIZE} bytes)` };
1006
1051
  }
1007
- const fileName = import_path7.default.basename(resolved);
1008
- const fileStream = import_fs7.default.createReadStream(resolved);
1052
+ const fileName = import_path8.default.basename(resolved);
1053
+ const fileStream = import_fs8.default.createReadStream(resolved);
1009
1054
  const baseUrl = serverUrl.replace("wss://", "https://").replace("ws://", "http://");
1010
1055
  const url = `${baseUrl}/api/files/receive`;
1011
1056
  const res = await fetch(url, {
@@ -1034,16 +1079,16 @@ async function downloadFile(filePath, serverUrl, secret, agentId) {
1034
1079
  return { error: err.message };
1035
1080
  }
1036
1081
  }
1037
- var import_fs7, import_path7, import_os5, SECRET_DIR;
1082
+ var import_fs8, import_path8, import_os5, SECRET_DIR;
1038
1083
  var init_file_explorer = __esm({
1039
1084
  "src/file-explorer.ts"() {
1040
1085
  "use strict";
1041
- import_fs7 = __toESM(require("fs"));
1042
- import_path7 = __toESM(require("path"));
1086
+ import_fs8 = __toESM(require("fs"));
1087
+ import_path8 = __toESM(require("path"));
1043
1088
  import_os5 = __toESM(require("os"));
1044
1089
  init_logger();
1045
1090
  init_src();
1046
- SECRET_DIR = import_path7.default.join(import_os5.default.homedir(), ".crc-agent");
1091
+ SECRET_DIR = import_path8.default.join(import_os5.default.homedir(), ".crc-agent");
1047
1092
  }
1048
1093
  });
1049
1094
 
@@ -1066,8 +1111,8 @@ async function runCmd(cmd2, shell) {
1066
1111
  }
1067
1112
  function getConfigPath(profile) {
1068
1113
  const file = profile.configFile || `${profile.id}.conf`;
1069
- if (import_path8.default.isAbsolute(file)) return file;
1070
- return import_path8.default.join(VPN_DIR, file);
1114
+ if (import_path9.default.isAbsolute(file)) return file;
1115
+ return import_path9.default.join(VPN_DIR, file);
1071
1116
  }
1072
1117
  async function getScutilStatus(serviceName) {
1073
1118
  const { stdout } = await runCmd(`scutil --nc status '${shq(serviceName)}'`);
@@ -1183,7 +1228,7 @@ async function connectWireGuard(profile) {
1183
1228
  const tunnelName = profile.tunnelName || profile.id;
1184
1229
  if (isWindows) {
1185
1230
  const confPath2 = getConfigPath(profile);
1186
- if (!import_fs8.default.existsSync(confPath2)) {
1231
+ if (!import_fs9.default.existsSync(confPath2)) {
1187
1232
  return `Config file not found: ${confPath2}`;
1188
1233
  }
1189
1234
  const script = `
@@ -1209,7 +1254,7 @@ async function connectWireGuard(profile) {
1209
1254
  async function connectOpenVpn(profile) {
1210
1255
  if (isWindows) {
1211
1256
  const confPath2 = getConfigPath(profile);
1212
- if (!import_fs8.default.existsSync(confPath2)) {
1257
+ if (!import_fs9.default.existsSync(confPath2)) {
1213
1258
  return `Config file not found: ${confPath2}`;
1214
1259
  }
1215
1260
  const connector = "C:\\Program Files\\OpenVPN Connect\\ovpnconnector.exe";
@@ -1236,7 +1281,7 @@ async function connectOpenVpn(profile) {
1236
1281
  return scutilStart(profile.serviceName);
1237
1282
  }
1238
1283
  const confPath = getConfigPath(profile);
1239
- if (!import_fs8.default.existsSync(confPath)) {
1284
+ if (!import_fs9.default.existsSync(confPath)) {
1240
1285
  return `Config file not found: ${confPath}`;
1241
1286
  }
1242
1287
  const { stderr } = await runCmd(`sudo openvpn --config '${shq(confPath)}' --daemon`);
@@ -1245,7 +1290,7 @@ async function connectOpenVpn(profile) {
1245
1290
  async function connectAzure(profile) {
1246
1291
  if (isWindows) {
1247
1292
  const confPath = getConfigPath(profile);
1248
- if (!import_fs8.default.existsSync(confPath)) {
1293
+ if (!import_fs9.default.existsSync(confPath)) {
1249
1294
  return `Config file not found: ${confPath}`;
1250
1295
  }
1251
1296
  await runCmd(`& 'AzureVpn.exe' -i '${psq(confPath)}' 2>&1`);
@@ -1365,19 +1410,19 @@ async function disconnectVpn(configs, profileId) {
1365
1410
  }
1366
1411
  return profiles;
1367
1412
  }
1368
- var import_child_process5, import_util3, import_fs8, import_path8, import_os6, execAsync, isWindows, VPN_DIR;
1413
+ var import_child_process5, import_util3, import_fs9, import_path9, import_os6, execAsync, isWindows, VPN_DIR;
1369
1414
  var init_vpn_manager = __esm({
1370
1415
  "src/vpn-manager.ts"() {
1371
1416
  "use strict";
1372
1417
  import_child_process5 = require("child_process");
1373
1418
  import_util3 = require("util");
1374
- import_fs8 = __toESM(require("fs"));
1375
- import_path8 = __toESM(require("path"));
1419
+ import_fs9 = __toESM(require("fs"));
1420
+ import_path9 = __toESM(require("path"));
1376
1421
  import_os6 = __toESM(require("os"));
1377
1422
  init_logger();
1378
1423
  execAsync = (0, import_util3.promisify)(import_child_process5.exec);
1379
1424
  isWindows = process.platform === "win32";
1380
- VPN_DIR = import_path8.default.join(import_os6.default.homedir(), ".crc-agent", "vpn");
1425
+ VPN_DIR = import_path9.default.join(import_os6.default.homedir(), ".crc-agent", "vpn");
1381
1426
  }
1382
1427
  });
1383
1428
 
@@ -1412,7 +1457,7 @@ var init_claude_path = __esm({
1412
1457
  // src/claude-sessions.ts
1413
1458
  async function parseSessionFile(filePath) {
1414
1459
  try {
1415
- const stream = import_fs9.default.createReadStream(filePath, { encoding: "utf-8" });
1460
+ const stream = import_fs10.default.createReadStream(filePath, { encoding: "utf-8" });
1416
1461
  const rl = import_readline2.default.createInterface({ input: stream, crlfDelay: Infinity });
1417
1462
  let firstMessage = "";
1418
1463
  let lastTimestamp = "";
@@ -1460,17 +1505,17 @@ async function parseSessionFile(filePath) {
1460
1505
  }
1461
1506
  async function listClaudeSessions(filterProjectPath) {
1462
1507
  const sessions2 = [];
1463
- if (!import_fs9.default.existsSync(CLAUDE_PROJECTS_DIR)) return sessions2;
1508
+ if (!import_fs10.default.existsSync(CLAUDE_PROJECTS_DIR)) return sessions2;
1464
1509
  const isDirSafe = (d) => {
1465
1510
  try {
1466
- return import_fs9.default.statSync(import_path9.default.join(CLAUDE_PROJECTS_DIR, d)).isDirectory();
1511
+ return import_fs10.default.statSync(import_path10.default.join(CLAUDE_PROJECTS_DIR, d)).isDirectory();
1467
1512
  } catch {
1468
1513
  return false;
1469
1514
  }
1470
1515
  };
1471
1516
  let allEntries;
1472
1517
  try {
1473
- allEntries = import_fs9.default.readdirSync(CLAUDE_PROJECTS_DIR);
1518
+ allEntries = import_fs10.default.readdirSync(CLAUDE_PROJECTS_DIR);
1474
1519
  } catch {
1475
1520
  return sessions2;
1476
1521
  }
@@ -1483,16 +1528,16 @@ async function listClaudeSessions(filterProjectPath) {
1483
1528
  projectDirs = allEntries.filter((d) => isDirSafe(d) && !d.startsWith("-private-"));
1484
1529
  }
1485
1530
  for (const dirName of projectDirs) {
1486
- const dirPath = import_path9.default.join(CLAUDE_PROJECTS_DIR, dirName);
1531
+ const dirPath = import_path10.default.join(CLAUDE_PROJECTS_DIR, dirName);
1487
1532
  let files;
1488
1533
  try {
1489
- files = import_fs9.default.readdirSync(dirPath).filter((f) => f.endsWith(".jsonl"));
1534
+ files = import_fs10.default.readdirSync(dirPath).filter((f) => f.endsWith(".jsonl"));
1490
1535
  } catch {
1491
1536
  continue;
1492
1537
  }
1493
1538
  for (const file of files) {
1494
1539
  const sessionId = file.replace(".jsonl", "");
1495
- const parsed = await parseSessionFile(import_path9.default.join(dirPath, file));
1540
+ const parsed = await parseSessionFile(import_path10.default.join(dirPath, file));
1496
1541
  if (!parsed) continue;
1497
1542
  const projectPath = parsed.cwd || dirName.replace(/^-/, "/").replace(/-/g, "/");
1498
1543
  sessions2.push({
@@ -1510,31 +1555,31 @@ async function listClaudeSessions(filterProjectPath) {
1510
1555
  sessions2.sort((a, b) => b.lastTimestamp > a.lastTimestamp ? 1 : -1);
1511
1556
  return sessions2;
1512
1557
  }
1513
- var import_fs9, import_path9, import_os7, import_readline2, CLAUDE_PROJECTS_DIR;
1558
+ var import_fs10, import_path10, import_os7, import_readline2, CLAUDE_PROJECTS_DIR;
1514
1559
  var init_claude_sessions = __esm({
1515
1560
  "src/claude-sessions.ts"() {
1516
1561
  "use strict";
1517
- import_fs9 = __toESM(require("fs"));
1518
- import_path9 = __toESM(require("path"));
1562
+ import_fs10 = __toESM(require("fs"));
1563
+ import_path10 = __toESM(require("path"));
1519
1564
  import_os7 = __toESM(require("os"));
1520
1565
  import_readline2 = __toESM(require("readline"));
1521
1566
  init_logger();
1522
1567
  init_claude_path();
1523
- CLAUDE_PROJECTS_DIR = import_path9.default.join(import_os7.default.homedir(), ".claude", "projects");
1568
+ CLAUDE_PROJECTS_DIR = import_path10.default.join(import_os7.default.homedir(), ".claude", "projects");
1524
1569
  }
1525
1570
  });
1526
1571
 
1527
1572
  // src/claude-conversation.ts
1528
1573
  function findProjectDir(projectPath) {
1529
1574
  const encoded = encodeProjectPath(projectPath);
1530
- const dirPath = import_path10.default.join(CLAUDE_PROJECTS_DIR2, encoded);
1531
- if (import_fs10.default.existsSync(dirPath)) return dirPath;
1532
- if (!import_fs10.default.existsSync(CLAUDE_PROJECTS_DIR2)) return null;
1575
+ const dirPath = import_path11.default.join(CLAUDE_PROJECTS_DIR2, encoded);
1576
+ if (import_fs11.default.existsSync(dirPath)) return dirPath;
1577
+ if (!import_fs11.default.existsSync(CLAUDE_PROJECTS_DIR2)) return null;
1533
1578
  let allDirs;
1534
1579
  try {
1535
- allDirs = import_fs10.default.readdirSync(CLAUDE_PROJECTS_DIR2).filter((d) => {
1580
+ allDirs = import_fs11.default.readdirSync(CLAUDE_PROJECTS_DIR2).filter((d) => {
1536
1581
  try {
1537
- return import_fs10.default.statSync(import_path10.default.join(CLAUDE_PROJECTS_DIR2, d)).isDirectory();
1582
+ return import_fs11.default.statSync(import_path11.default.join(CLAUDE_PROJECTS_DIR2, d)).isDirectory();
1538
1583
  } catch {
1539
1584
  return false;
1540
1585
  }
@@ -1544,23 +1589,23 @@ function findProjectDir(projectPath) {
1544
1589
  }
1545
1590
  const matches = findProjectDirs(allDirs, projectPath);
1546
1591
  if (matches.length > 0) {
1547
- return import_path10.default.join(CLAUDE_PROJECTS_DIR2, matches[0]);
1592
+ return import_path11.default.join(CLAUDE_PROJECTS_DIR2, matches[0]);
1548
1593
  }
1549
1594
  return null;
1550
1595
  }
1551
1596
  function findSessionFileById(sessionId) {
1552
1597
  if (!/^[A-Za-z0-9._-]+$/.test(sessionId)) return null;
1553
- if (!import_fs10.default.existsSync(CLAUDE_PROJECTS_DIR2)) return null;
1598
+ if (!import_fs11.default.existsSync(CLAUDE_PROJECTS_DIR2)) return null;
1554
1599
  let dirs;
1555
1600
  try {
1556
- dirs = import_fs10.default.readdirSync(CLAUDE_PROJECTS_DIR2);
1601
+ dirs = import_fs11.default.readdirSync(CLAUDE_PROJECTS_DIR2);
1557
1602
  } catch {
1558
1603
  return null;
1559
1604
  }
1560
1605
  for (const dir of dirs) {
1561
- const candidate = import_path10.default.join(CLAUDE_PROJECTS_DIR2, dir, `${sessionId}.jsonl`);
1606
+ const candidate = import_path11.default.join(CLAUDE_PROJECTS_DIR2, dir, `${sessionId}.jsonl`);
1562
1607
  try {
1563
- if (import_fs10.default.statSync(candidate).isFile()) return candidate;
1608
+ if (import_fs11.default.statSync(candidate).isFile()) return candidate;
1564
1609
  } catch {
1565
1610
  }
1566
1611
  }
@@ -1571,20 +1616,20 @@ function findLatestSessionFile(projectPath) {
1571
1616
  if (!dirPath) return null;
1572
1617
  let entries;
1573
1618
  try {
1574
- entries = import_fs10.default.readdirSync(dirPath);
1619
+ entries = import_fs11.default.readdirSync(dirPath);
1575
1620
  } catch {
1576
1621
  return null;
1577
1622
  }
1578
1623
  const files = entries.filter((f) => f.endsWith(".jsonl") && !f.includes("/")).map((f) => {
1579
1624
  try {
1580
- return { name: f, mtime: import_fs10.default.statSync(import_path10.default.join(dirPath, f)).mtimeMs };
1625
+ return { name: f, mtime: import_fs11.default.statSync(import_path11.default.join(dirPath, f)).mtimeMs };
1581
1626
  } catch {
1582
1627
  return null;
1583
1628
  }
1584
1629
  }).filter((f) => f !== null).sort((a, b) => b.mtime - a.mtime);
1585
1630
  if (files.length === 0) return null;
1586
1631
  return {
1587
- filePath: import_path10.default.join(dirPath, files[0].name),
1632
+ filePath: import_path11.default.join(dirPath, files[0].name),
1588
1633
  sessionId: files[0].name.replace(".jsonl", "")
1589
1634
  };
1590
1635
  }
@@ -1594,8 +1639,8 @@ async function readConversation(projectPath, afterLine = 0, specificSessionId) {
1594
1639
  if (specificSessionId) {
1595
1640
  sessionId = specificSessionId;
1596
1641
  const dirPath = findProjectDir(projectPath);
1597
- const direct = dirPath ? import_path10.default.join(dirPath, `${specificSessionId}.jsonl`) : null;
1598
- if (direct && import_fs10.default.existsSync(direct)) {
1642
+ const direct = dirPath ? import_path11.default.join(dirPath, `${specificSessionId}.jsonl`) : null;
1643
+ if (direct && import_fs11.default.existsSync(direct)) {
1599
1644
  filePath = direct;
1600
1645
  } else {
1601
1646
  const byId = findSessionFileById(specificSessionId);
@@ -1609,7 +1654,7 @@ async function readConversation(projectPath, afterLine = 0, specificSessionId) {
1609
1654
  sessionId = found.sessionId;
1610
1655
  }
1611
1656
  try {
1612
- const stream = import_fs10.default.createReadStream(filePath, { encoding: "utf-8" });
1657
+ const stream = import_fs11.default.createReadStream(filePath, { encoding: "utf-8" });
1613
1658
  const rl = import_readline3.default.createInterface({ input: stream, crlfDelay: Infinity });
1614
1659
  const messages = [];
1615
1660
  let lineNum = 0;
@@ -1690,17 +1735,17 @@ async function readConversation(projectPath, afterLine = 0, specificSessionId) {
1690
1735
  return null;
1691
1736
  }
1692
1737
  }
1693
- var import_fs10, import_path10, import_os8, import_readline3, CLAUDE_PROJECTS_DIR2;
1738
+ var import_fs11, import_path11, import_os8, import_readline3, CLAUDE_PROJECTS_DIR2;
1694
1739
  var init_claude_conversation = __esm({
1695
1740
  "src/claude-conversation.ts"() {
1696
1741
  "use strict";
1697
- import_fs10 = __toESM(require("fs"));
1698
- import_path10 = __toESM(require("path"));
1742
+ import_fs11 = __toESM(require("fs"));
1743
+ import_path11 = __toESM(require("path"));
1699
1744
  import_os8 = __toESM(require("os"));
1700
1745
  import_readline3 = __toESM(require("readline"));
1701
1746
  init_logger();
1702
1747
  init_claude_path();
1703
- CLAUDE_PROJECTS_DIR2 = import_path10.default.join(import_os8.default.homedir(), ".claude", "projects");
1748
+ CLAUDE_PROJECTS_DIR2 = import_path11.default.join(import_os8.default.homedir(), ".claude", "projects");
1704
1749
  }
1705
1750
  });
1706
1751
 
@@ -1716,6 +1761,7 @@ var init_index = __esm({
1716
1761
  init_logger();
1717
1762
  init_claude_plugin_installer();
1718
1763
  init_local_control();
1764
+ init_pty_helper_fix();
1719
1765
  init_tmux();
1720
1766
  init_heartbeat();
1721
1767
  init_file_explorer();
@@ -1729,6 +1775,7 @@ var init_index = __esm({
1729
1775
  }
1730
1776
  config = loadConfig();
1731
1777
  logger.info({ agentId: config.agentId, serverUrl: config.serverUrl }, "Starting agent");
1778
+ ensurePtyHelperExecutable();
1732
1779
  process.on("unhandledRejection", (reason) => {
1733
1780
  logger.error({ reason }, "Unhandled promise rejection (agent kept alive)");
1734
1781
  });