cli-remote-agent 1.0.8 → 1.0.11

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
@@ -215,7 +215,7 @@ var init_types = __esm({
215
215
  });
216
216
 
217
217
  // ../shared/src/protocol.ts
218
- var AGENT_HEARTBEAT, TERMINAL_OUTPUT, TERMINAL_EXIT, TERMINAL_OPEN, TERMINAL_INPUT, TERMINAL_RESIZE, TERMINAL_CLOSE, SESSION_ATTACH, SESSION_DETACH, SESSION_BUFFER, SESSION_SYNC, SESSION_SYNC_RESULT, VPN_LIST, VPN_CONNECT, VPN_DISCONNECT, VPN_UPDATE, FILES_LIST, FILES_DOWNLOAD, FILES_LIST_RESULT, FILES_DOWNLOAD_READY, FILES_DOWNLOAD_ERROR, AGENT_EXEC, AGENT_EXEC_RESULT, CLAUDE_CONV_READ, CLAUDE_CONV_DATA, CLAUDE_SESSIONS_LIST, CLAUDE_SESSIONS_RESULT, CLAUDE_HOOK, TMUX_LIST, TMUX_LIST_RESULT, TMUX_KILL, TMUX_KILL_RESULT;
218
+ var AGENT_HEARTBEAT, TERMINAL_OUTPUT, TERMINAL_EXIT, TERMINAL_OPEN, TERMINAL_INPUT, TERMINAL_RESIZE, TERMINAL_CLOSE, SESSION_ATTACH, SESSION_DETACH, SESSION_BUFFER, SESSION_SYNC, SESSION_SYNC_RESULT, VPN_LIST, VPN_CONNECT, VPN_DISCONNECT, VPN_UPDATE, FILES_LIST, FILES_DOWNLOAD, FILES_LIST_RESULT, FILES_DOWNLOAD_READY, FILES_DOWNLOAD_ERROR, AGENT_EXEC, AGENT_EXEC_RESULT, CLAUDE_CONV_READ, CLAUDE_CONV_DATA, CLAUDE_SESSIONS_LIST, CLAUDE_SESSIONS_RESULT, CLAUDE_HOOK, TMUX_LIST, TMUX_LIST_RESULT, TMUX_KILL, TMUX_KILL_RESULT, TMUX_SCROLL;
219
219
  var init_protocol = __esm({
220
220
  "../shared/src/protocol.ts"() {
221
221
  "use strict";
@@ -251,6 +251,7 @@ var init_protocol = __esm({
251
251
  TMUX_LIST_RESULT = "tmux:list:result";
252
252
  TMUX_KILL = "tmux:kill";
253
253
  TMUX_KILL_RESULT = "tmux:kill:result";
254
+ TMUX_SCROLL = "tmux:scroll";
254
255
  }
255
256
  });
256
257
 
@@ -550,6 +551,7 @@ function getLiveClaudeSessions() {
550
551
  out.push({
551
552
  pid: obj.pid,
552
553
  cwd: typeof obj.cwd === "string" ? obj.cwd : "",
554
+ sessionId: typeof obj.sessionId === "string" ? obj.sessionId : void 0,
553
555
  name: typeof obj.name === "string" ? obj.name : void 0,
554
556
  status: typeof obj.status === "string" ? obj.status : void 0,
555
557
  updatedAt: typeof obj.updatedAt === "number" ? obj.updatedAt : void 0
@@ -580,6 +582,15 @@ function isDescendantOf(pid, ancestor, parents) {
580
582
  }
581
583
  return false;
582
584
  }
585
+ async function findClaudeSessionForPtyPid(ptyPid) {
586
+ const live = getLiveClaudeSessions().filter((s) => s.sessionId);
587
+ if (live.length === 0) return null;
588
+ const parents = await getPidParents();
589
+ for (let i = live.length - 1; i >= 0; i--) {
590
+ if (isDescendantOf(live[i].pid, ptyPid, parents)) return live[i].sessionId;
591
+ }
592
+ return null;
593
+ }
583
594
  var import_fs6, import_path5, import_os2, import_child_process2, import_util, execFileAsync, LIVE_SESSIONS_DIR;
584
595
  var init_claude_live = __esm({
585
596
  "src/claude-live.ts"() {
@@ -647,6 +658,41 @@ async function killTmuxSession(name) {
647
658
  return { ok: false, error: msg };
648
659
  }
649
660
  }
661
+ async function scrollTmux(name, direction) {
662
+ const bin = resolveTmuxPath();
663
+ if (!bin) return { inCopyMode: false };
664
+ const target = `=${name}`;
665
+ const run = (args) => execFileAsync2(bin, args, { timeout: 4e3 }).catch(() => {
666
+ });
667
+ const inMode = async () => {
668
+ try {
669
+ const { stdout } = await execFileAsync2(bin, ["display-message", "-t", target, "-p", "#{pane_in_mode}"], { timeout: 3e3 });
670
+ return stdout.trim() === "1";
671
+ } catch {
672
+ return false;
673
+ }
674
+ };
675
+ if (direction === "exit") {
676
+ if (await inMode()) await run(["send-keys", "-t", target, "-X", "cancel"]);
677
+ return { inCopyMode: false };
678
+ }
679
+ if (direction === "up") {
680
+ await run(["copy-mode", "-t", target]);
681
+ await run(["send-keys", "-t", target, "-X", "halfpage-up"]);
682
+ return { inCopyMode: true };
683
+ }
684
+ if (!await inMode()) return { inCopyMode: false };
685
+ await run(["send-keys", "-t", target, "-X", "halfpage-down"]);
686
+ try {
687
+ const { stdout } = await execFileAsync2(bin, ["display-message", "-t", target, "-p", "#{scroll_position}"], { timeout: 3e3 });
688
+ if ((parseInt(stdout.trim(), 10) || 0) === 0) {
689
+ await run(["send-keys", "-t", target, "-X", "cancel"]);
690
+ return { inCopyMode: false };
691
+ }
692
+ } catch {
693
+ }
694
+ return { inCopyMode: true };
695
+ }
650
696
  async function enrichWithPanesAndClaude(sessions2) {
651
697
  if (IS_WIN || sessions2.length === 0) return;
652
698
  try {
@@ -845,6 +891,9 @@ var init_pty_session = __esm({
845
891
  });
846
892
  }
847
893
  }
894
+ get pid() {
895
+ return this.pty.pid;
896
+ }
848
897
  write(data) {
849
898
  this.pty.write(data);
850
899
  }
@@ -911,6 +960,9 @@ function createTerminalSession(sessionId, cols, rows, shellPreference, cwd, onDa
911
960
  sessions.set(sessionId, session);
912
961
  logger.info({ sessionId, cols, rows }, "PTY session created");
913
962
  }
963
+ function getSessionPid(sessionId) {
964
+ return sessions.get(sessionId)?.pid;
965
+ }
914
966
  function writeToSession(sessionId, data) {
915
967
  sessions.get(sessionId)?.write(data);
916
968
  }
@@ -1805,7 +1857,7 @@ var init_claude_conversation = __esm({
1805
1857
 
1806
1858
  // src/index.ts
1807
1859
  var index_exports = {};
1808
- var import_socket, config, lock, socket, SESSION_MAX_IDLE_MS, reaperInterval, vpnProfiles;
1860
+ var import_socket, config, lock, socket, SESSION_MAX_IDLE_MS, reaperInterval, sessionTmuxName, sessionInCopyMode, vpnProfiles;
1809
1861
  var init_index = __esm({
1810
1862
  "src/index.ts"() {
1811
1863
  "use strict";
@@ -1824,6 +1876,7 @@ var init_index = __esm({
1824
1876
  init_claude_sessions();
1825
1877
  init_claude_conversation();
1826
1878
  init_terminal_manager();
1879
+ init_claude_live();
1827
1880
  if (!isConfigured()) {
1828
1881
  console.error("No agent configured. Run: crc-agent setup");
1829
1882
  process.exit(1);
@@ -1894,9 +1947,12 @@ var init_index = __esm({
1894
1947
  socket.emit(CLAUDE_HOOK, payload);
1895
1948
  }
1896
1949
  });
1950
+ sessionTmuxName = /* @__PURE__ */ new Map();
1951
+ sessionInCopyMode = /* @__PURE__ */ new Map();
1897
1952
  socket.on(TERMINAL_OPEN, (payload) => {
1898
1953
  const { sessionId, cols, rows, tmux, launch } = payload;
1899
1954
  if (!sessionId) return;
1955
+ if (tmux) sessionTmuxName.set(sessionId, tmux);
1900
1956
  let launchSpec;
1901
1957
  if (tmux) {
1902
1958
  const spec = buildTmuxLaunch(tmux, launch);
@@ -1920,6 +1976,8 @@ var init_index = __esm({
1920
1976
  },
1921
1977
  (sid, exitCode) => {
1922
1978
  socket.emit(TERMINAL_EXIT, { sessionId: sid, exitCode });
1979
+ sessionTmuxName.delete(sid);
1980
+ sessionInCopyMode.delete(sid);
1923
1981
  },
1924
1982
  launchSpec
1925
1983
  );
@@ -1941,7 +1999,20 @@ var init_index = __esm({
1941
1999
  logger.info({ name, ok: result.ok, error: result.error }, "tmux kill requested");
1942
2000
  socket.emit(TMUX_KILL_RESULT, { requestId, name, ok: result.ok, error: result.error });
1943
2001
  });
2002
+ socket.on(TMUX_SCROLL, async (payload) => {
2003
+ const { sessionId, direction } = payload;
2004
+ const name = sessionId && sessionTmuxName.get(sessionId);
2005
+ if (!name) return;
2006
+ const { inCopyMode } = await scrollTmux(name, direction);
2007
+ sessionInCopyMode.set(sessionId, inCopyMode);
2008
+ });
1944
2009
  socket.on(TERMINAL_INPUT, (payload) => {
2010
+ const name = sessionTmuxName.get(payload.sessionId);
2011
+ if (name && sessionInCopyMode.get(payload.sessionId)) {
2012
+ sessionInCopyMode.set(payload.sessionId, false);
2013
+ scrollTmux(name, "exit").catch(() => {
2014
+ });
2015
+ }
1945
2016
  writeToSession(payload.sessionId, payload.data);
1946
2017
  });
1947
2018
  socket.on(TERMINAL_RESIZE, (payload) => {
@@ -1949,6 +2020,8 @@ var init_index = __esm({
1949
2020
  });
1950
2021
  socket.on(TERMINAL_CLOSE, (payload) => {
1951
2022
  closeSession(payload.sessionId);
2023
+ sessionTmuxName.delete(payload.sessionId);
2024
+ sessionInCopyMode.delete(payload.sessionId);
1952
2025
  });
1953
2026
  socket.on(SESSION_SYNC, () => {
1954
2027
  const aliveIds = getAliveSessionIds();
@@ -2025,7 +2098,17 @@ var init_index = __esm({
2025
2098
  });
2026
2099
  socket.on(CLAUDE_CONV_READ, async (payload) => {
2027
2100
  try {
2028
- const result = await readConversation(payload.projectPath, payload.afterLine || 0, payload.sessionId);
2101
+ let sessionId = payload.sessionId;
2102
+ if (!sessionId && payload.terminalSessionId) {
2103
+ const ptyPid = getSessionPid(payload.terminalSessionId);
2104
+ const resolved = ptyPid ? await findClaudeSessionForPtyPid(ptyPid) : null;
2105
+ if (!resolved) {
2106
+ socket.emit(CLAUDE_CONV_DATA, { sessionId: "", messages: [], totalLines: 0 });
2107
+ return;
2108
+ }
2109
+ sessionId = resolved;
2110
+ }
2111
+ const result = await readConversation(payload.projectPath, payload.afterLine || 0, sessionId);
2029
2112
  if (result) {
2030
2113
  socket.emit(CLAUDE_CONV_DATA, {
2031
2114
  sessionId: result.sessionId,