@hydra-acp/browser 0.1.10 → 0.1.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.
Files changed (2) hide show
  1. package/dist/ui/index.html +75 -4
  2. package/package.json +1 -1
@@ -54,6 +54,8 @@ pre code { background: transparent; padding: 0; }
54
54
  .pill { font-size: 0.8rem; color: var(--muted); padding: 0.15rem 0.5rem; border: 1px solid var(--border); border-radius: 999px; display: inline-flex; align-items: center; gap: 0.3rem; }
55
55
  .pill.clickable { cursor: pointer; }
56
56
  .pill.clickable:hover { background: var(--panel-2); color: var(--fg); }
57
+ .host-select { font-size: 0.8rem; color: var(--muted); padding: 0.15rem 0.5rem; border-radius: 999px; background: transparent; border: 1px solid var(--border); cursor: pointer; }
58
+ .host-select:hover { background: var(--panel-2); color: var(--fg); }
57
59
  .pill.ready { color: var(--good); border-color: var(--good); }
58
60
  .pill.working { color: var(--warn); border-color: var(--warn); }
59
61
  .pill.working .dot { animation: pill-pulse 1.1s ease-in-out infinite; }
@@ -72,6 +74,7 @@ pre code { background: transparent; padding: 0; }
72
74
  .badge { font-size: 0.75rem; padding: 0.1rem 0.45rem; border-radius: 999px; border: 1px solid var(--border); color: var(--muted); }
73
75
  .badge.live { color: var(--good); border-color: var(--good); }
74
76
  .badge.cold { color: var(--warn); border-color: var(--warn); }
77
+ .badge.imported { color: var(--accent); border-color: var(--accent); }
75
78
  .card .actions { display: flex; gap: 0.4rem; }
76
79
  .card .actions button { padding: 0.25rem 0.55rem; font-size: 0.85rem; }
77
80
  .empty { color: var(--muted); padding: 2rem; text-align: center; }
@@ -11674,6 +11677,7 @@ pre code { background: transparent; padding: 0; }
11674
11677
  },
11675
11678
  state.showCold ? "all" : "live"
11676
11679
  ),
11680
+ renderHostFilter(),
11677
11681
  el("span", { class: "spacer" }),
11678
11682
  el(
11679
11683
  "button",
@@ -11686,13 +11690,66 @@ pre code { background: transparent; padding: 0; }
11686
11690
  el("button", { onclick: openSessionModal }, "New Session")
11687
11691
  );
11688
11692
  }
11693
+ function renderHostFilter() {
11694
+ const hostsSeen = /* @__PURE__ */ new Set();
11695
+ for (const s of state.sessions) {
11696
+ if (s.importedFromMachine && !s.upstreamSessionId) {
11697
+ hostsSeen.add(s.importedFromMachine);
11698
+ }
11699
+ }
11700
+ const hosts = [...hostsSeen].sort();
11701
+ const select = el("select", {
11702
+ class: "host-select",
11703
+ title: "Filter sessions by origin host",
11704
+ onchange: (e) => {
11705
+ const value = e.target.value;
11706
+ setState({ hostFilter: value });
11707
+ }
11708
+ });
11709
+ const addOption = (value, label) => {
11710
+ const opt = document.createElement("option");
11711
+ opt.value = value;
11712
+ opt.textContent = label;
11713
+ if (state.hostFilter === value) {
11714
+ opt.selected = true;
11715
+ }
11716
+ select.appendChild(opt);
11717
+ };
11718
+ addOption("__local", "host: local");
11719
+ for (const h of hosts) {
11720
+ addOption(h, `host: ${h}`);
11721
+ }
11722
+ addOption("__all", "host: all");
11723
+ if (state.hostFilter !== "__local" && state.hostFilter !== "__all" && !hosts.includes(state.hostFilter)) {
11724
+ select.value = state.hostFilter;
11725
+ }
11726
+ return select;
11727
+ }
11689
11728
  function renderList() {
11690
- const visible = state.showCold ? state.sessions : state.sessions.filter((s) => s.status !== "cold");
11691
- const hiddenCold = state.sessions.length - visible.length;
11729
+ let visible = state.showCold ? state.sessions : state.sessions.filter((s) => s.status !== "cold");
11730
+ if (state.hostFilter === "__local") {
11731
+ visible = visible.filter(
11732
+ (s) => !s.importedFromMachine || !!s.upstreamSessionId
11733
+ );
11734
+ } else if (state.hostFilter !== "__all") {
11735
+ visible = visible.filter(
11736
+ (s) => s.importedFromMachine === state.hostFilter && !s.upstreamSessionId
11737
+ );
11738
+ }
11739
+ const hiddenCold = state.showCold ? 0 : state.sessions.filter((s) => s.status === "cold").length;
11692
11740
  const groups = groupSessions(visible, state.groupBy);
11693
11741
  const list = el("div", { class: "list" });
11694
11742
  if (visible.length === 0) {
11695
- const msg = state.sessions.length === 0 ? "No sessions. Use + to create one, or run `hydra-acp launch <agent>` from your editor." : `No live sessions. ${hiddenCold} cold session${hiddenCold === 1 ? "" : "s"} hidden \u2014 click "live" to switch to "all".`;
11743
+ let msg;
11744
+ if (state.sessions.length === 0) {
11745
+ msg = "No sessions. Use + to create one, or run `hydra-acp launch <agent>` from your editor.";
11746
+ } else if (state.hostFilter === "__local") {
11747
+ msg = "No local sessions. Switch the host filter to see imported sessions.";
11748
+ } else if (state.hostFilter !== "__all") {
11749
+ msg = `No sessions from ${state.hostFilter}. Try a different host.`;
11750
+ } else {
11751
+ msg = `No live sessions. ${hiddenCold} cold session${hiddenCold === 1 ? "" : "s"} hidden \u2014 click "live" to switch to "all".`;
11752
+ }
11696
11753
  list.appendChild(el("div", { class: "empty" }, msg));
11697
11754
  }
11698
11755
  for (const g of groups) {
@@ -11770,7 +11827,17 @@ pre code { background: transparent; padding: 0; }
11770
11827
  },
11771
11828
  s.status === "cold" ? "cold" : "live"
11772
11829
  ),
11773
- el("span", { class: "badge" }, `${s.attachedClients ?? 0} attached`)
11830
+ el("span", { class: "badge" }, `${s.attachedClients ?? 0} attached`),
11831
+ ...s.importedFromMachine && !s.upstreamSessionId ? [
11832
+ el(
11833
+ "span",
11834
+ {
11835
+ class: "badge imported",
11836
+ title: `Passive mirror imported from ${s.importedFromMachine} \u2014 attach to start working on it here.`
11837
+ },
11838
+ `\u2190 ${s.importedFromMachine}`
11839
+ )
11840
+ ] : []
11774
11841
  ),
11775
11842
  el(
11776
11843
  "div",
@@ -12885,6 +12952,10 @@ ${recent}`;
12885
12952
  // toggle in the topbar reveals them; clicking one attaches over
12886
12953
  // WSS, which causes hydra to resurrect it from disk automatically.
12887
12954
  showCold: false,
12955
+ // Default to local: imported sessions (from peer hosts via the
12956
+ // archiver) are noisy if they all show up alongside the user's own
12957
+ // work. The dropdown lets them switch to a specific peer or "all".
12958
+ hostFilter: "__local",
12888
12959
  banner: null,
12889
12960
  modal: null,
12890
12961
  current: null
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hydra-acp/browser",
3
- "version": "0.1.10",
3
+ "version": "0.1.11",
4
4
  "description": "Browser-based UI for hydra-acp sessions.",
5
5
  "license": "MIT",
6
6
  "type": "module",