@hydra-acp/cli 0.1.26 → 0.1.28

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.
Files changed (2) hide show
  1. package/dist/cli.js +120 -8
  2. package/package.json +1 -1
package/dist/cli.js CHANGED
@@ -4655,15 +4655,32 @@ async function runSessionsList(opts = {}) {
4655
4655
  process.exit(1);
4656
4656
  }
4657
4657
  const body = await response.json();
4658
+ const host = opts.host ?? "local";
4659
+ const hostFiltered = host === "all" ? body.sessions : host === "local" ? body.sessions.filter(
4660
+ (s) => !s.importedFromMachine || !!s.upstreamSessionId
4661
+ ) : body.sessions.filter(
4662
+ (s) => s.importedFromMachine === host && !s.upstreamSessionId
4663
+ );
4658
4664
  if (opts.json) {
4659
- process.stdout.write(JSON.stringify(body.sessions, null, 2) + "\n");
4665
+ process.stdout.write(JSON.stringify(hostFiltered, null, 2) + "\n");
4660
4666
  return;
4661
4667
  }
4662
- if (body.sessions.length === 0) {
4668
+ if (hostFiltered.length === 0) {
4669
+ if (host === "local" && body.sessions.length > 0) {
4670
+ process.stdout.write(
4671
+ "No local sessions. Use --host=all to include imported sessions.\n"
4672
+ );
4673
+ return;
4674
+ }
4675
+ if (host !== "local" && host !== "all") {
4676
+ process.stdout.write(`No sessions from ${host}.
4677
+ `);
4678
+ return;
4679
+ }
4663
4680
  process.stdout.write("No active sessions.\n");
4664
4681
  return;
4665
4682
  }
4666
- const sorted = body.sessions.slice().sort((a, b) => {
4683
+ const sorted = hostFiltered.slice().sort((a, b) => {
4667
4684
  const liveDiff = (b.status === "live" ? 1 : 0) - (a.status === "live" ? 1 : 0);
4668
4685
  if (liveDiff !== 0) {
4669
4686
  return liveDiff;
@@ -5414,8 +5431,18 @@ async function pickSession(term, opts) {
5414
5431
  return b.updatedAt.localeCompare(a.updatedAt);
5415
5432
  });
5416
5433
  };
5434
+ let cwdOnly = false;
5435
+ let hostFilter = "__local";
5436
+ if (opts.currentSessionId !== void 0) {
5437
+ const current = opts.sessions.find(
5438
+ (s) => s.sessionId === opts.currentSessionId
5439
+ );
5440
+ if (current?.importedFromMachine) {
5441
+ hostFilter = "__all";
5442
+ }
5443
+ }
5417
5444
  let allSessions = sortSessions(opts.sessions);
5418
- let visible = allSessions;
5445
+ let visible = filterByHost(allSessions, hostFilter);
5419
5446
  let rows = visible.map((s) => toRow(s, Date.now()));
5420
5447
  let widths = computeWidths(rows);
5421
5448
  let total = 1 + visible.length;
@@ -5429,7 +5456,6 @@ async function pickSession(term, opts) {
5429
5456
  }
5430
5457
  let searchActive = false;
5431
5458
  let searchTerm = "";
5432
- let cwdOnly = false;
5433
5459
  let mode = "normal";
5434
5460
  let pendingAction = null;
5435
5461
  let renameBuffer = "";
@@ -5463,6 +5489,7 @@ async function pickSession(term, opts) {
5463
5489
  if (cwdOnly) {
5464
5490
  base = base.filter((s) => s.cwd === opts.cwd);
5465
5491
  }
5492
+ base = filterByHost(base, hostFilter);
5466
5493
  if (searchActive && searchTerm.length > 0) {
5467
5494
  visible = base.filter((s) => matchesSearch(s, searchTerm));
5468
5495
  } else {
@@ -5515,6 +5542,11 @@ async function pickSession(term, opts) {
5515
5542
  if (cwdOnly) {
5516
5543
  parts.push("cwd-only");
5517
5544
  }
5545
+ if (hostFilter !== "__all") {
5546
+ parts.push(
5547
+ hostFilter === "__local" ? "host: local" : `host: ${hostFilter}`
5548
+ );
5549
+ }
5518
5550
  if (above > 0) {
5519
5551
  parts.push(`\u2191 ${above} above`);
5520
5552
  }
@@ -5896,6 +5928,20 @@ async function pickSession(term, opts) {
5896
5928
  renderFromScratch();
5897
5929
  return;
5898
5930
  }
5931
+ if (name === "h" || name === "H") {
5932
+ const keepId = selectedIdx > 0 ? visible[selectedIdx - 1]?.sessionId : void 0;
5933
+ hostFilter = nextHostFilter(hostFilter, allSessions);
5934
+ applyFilter();
5935
+ if (keepId !== void 0) {
5936
+ const idx = visible.findIndex((s) => s.sessionId === keepId);
5937
+ if (idx >= 0) {
5938
+ selectedIdx = idx + 1;
5939
+ adjustScroll();
5940
+ }
5941
+ }
5942
+ renderFromScratch();
5943
+ return;
5944
+ }
5899
5945
  if (name === "r" || name === "R") {
5900
5946
  const currentId = selectedIdx > 0 ? visible[selectedIdx - 1]?.sessionId : void 0;
5901
5947
  void refresh(currentId);
@@ -6026,6 +6072,33 @@ function formatNewSessionLabel(cwd, maxWidth) {
6026
6072
  const budget = Math.max(1, maxWidth - prefix.length);
6027
6073
  return prefix + truncateMiddle(shortenHomePath(cwd), budget);
6028
6074
  }
6075
+ function filterByHost(sessions, hostFilter) {
6076
+ if (hostFilter === "__all") {
6077
+ return sessions;
6078
+ }
6079
+ if (hostFilter === "__local") {
6080
+ return sessions.filter(
6081
+ (s) => !s.importedFromMachine || !!s.upstreamSessionId
6082
+ );
6083
+ }
6084
+ return sessions.filter(
6085
+ (s) => s.importedFromMachine === hostFilter && !s.upstreamSessionId
6086
+ );
6087
+ }
6088
+ function nextHostFilter(current, sessions) {
6089
+ const hosts = /* @__PURE__ */ new Set();
6090
+ for (const s of sessions) {
6091
+ if (s.importedFromMachine && !s.upstreamSessionId) {
6092
+ hosts.add(s.importedFromMachine);
6093
+ }
6094
+ }
6095
+ const ordered = ["__local", ...[...hosts].sort(), "__all"];
6096
+ const idx = ordered.indexOf(current);
6097
+ if (idx === -1) {
6098
+ return "__local";
6099
+ }
6100
+ return ordered[(idx + 1) % ordered.length] ?? "__local";
6101
+ }
6029
6102
  function matchesSearch(s, term) {
6030
6103
  if (term.length === 0) {
6031
6104
  return true;
@@ -6064,6 +6137,7 @@ var init_picker = __esm({
6064
6137
  null,
6065
6138
  ["/", "search sessions"],
6066
6139
  ["o", "toggle cwd-only filter"],
6140
+ ["h", "cycle host filter (local / <peer> / all)"],
6067
6141
  ["r", "refresh from daemon"],
6068
6142
  null,
6069
6143
  ["k", "kill the selected live session"],
@@ -6991,6 +7065,42 @@ var init_screen = __esm({
6991
7065
  return;
6992
7066
  }
6993
7067
  }
7068
+ const csiUCtrlMap = {
7069
+ 97: "ctrl-a",
7070
+ 98: "ctrl-b",
7071
+ 99: "ctrl-c",
7072
+ 100: "ctrl-d",
7073
+ 101: "ctrl-e",
7074
+ 102: "ctrl-f",
7075
+ 103: "ctrl-g",
7076
+ 107: "ctrl-k",
7077
+ 108: "ctrl-l",
7078
+ 110: "ctrl-n",
7079
+ 111: "ctrl-o",
7080
+ 112: "ctrl-p",
7081
+ 114: "ctrl-r",
7082
+ 115: "ctrl-s",
7083
+ 116: "ctrl-t",
7084
+ 117: "ctrl-u",
7085
+ 118: "ctrl-v",
7086
+ 119: "ctrl-w",
7087
+ 121: "ctrl-y"
7088
+ };
7089
+ const csiUCtrlRe = /\x1b\[(\d+);5u/;
7090
+ const m = csiUCtrlRe.exec(text);
7091
+ if (m !== null) {
7092
+ const keyName = csiUCtrlMap[parseInt(m[1], 10)];
7093
+ if (keyName !== void 0) {
7094
+ const parts = text.split(m[0]);
7095
+ for (let i = 0; i < parts.length; i++) {
7096
+ if (parts[i].length > 0)
7097
+ this.handleRawStdin(Buffer.from(parts[i], "binary"));
7098
+ if (i < parts.length - 1)
7099
+ this.onKey([{ type: "key", name: keyName }]);
7100
+ }
7101
+ return;
7102
+ }
7103
+ }
6994
7104
  }
6995
7105
  this.handleRawStdinSegment(text);
6996
7106
  }
@@ -18287,7 +18397,8 @@ async function main() {
18287
18397
  if (sub === void 0 || sub === "list") {
18288
18398
  await runSessionsList({
18289
18399
  all: flags.all === true,
18290
- json: flags.json === true
18400
+ json: flags.json === true,
18401
+ host: typeof flags.host === "string" ? flags.host : void 0
18291
18402
  });
18292
18403
  return;
18293
18404
  }
@@ -18480,8 +18591,9 @@ function printHelp() {
18480
18591
  " hydra-acp daemon start [--foreground] Start daemon (detached by default; --foreground to attach)",
18481
18592
  " hydra-acp daemon stop|restart|status",
18482
18593
  " hydra-acp daemon logs [-f] [-n N] Tail or follow the daemon log",
18483
- " hydra-acp session [list] [--all] [--json]",
18484
- " List sessions (live + 20 most-recent cold; --all for everything; --json emits the raw daemon response as JSON for scripts)",
18594
+ " hydra-acp session [list] [--all] [--json] [--host=<host>]",
18595
+ " List sessions (live + 20 most-recent cold; --all for everything; --json emits JSON for scripts).",
18596
+ " --host filters by origin machine: 'local' (default) shows only sessions created here, 'all' shows everything, or pass a hostname (e.g. machine-b) to show only imports from that peer.",
18485
18597
  " hydra-acp session kill <id> Demote a live session to cold (keeps the on-disk record)",
18486
18598
  " hydra-acp session remove <id> Remove a session entirely (live or cold)",
18487
18599
  " hydra-acp session export <id> [--out <file>|.]",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hydra-acp/cli",
3
- "version": "0.1.26",
3
+ "version": "0.1.28",
4
4
  "description": "Multi-client ACP session daemon: spawn agents, attach over WSS, multiplex sessions across editors.",
5
5
  "license": "MIT",
6
6
  "type": "module",