pantheon-opencode 1.5.0-beta.10 → 1.5.0-beta.12

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.
@@ -10,9 +10,10 @@ import { For, Show, createEffect, createMemo, createResource, createSignal, onCl
10
10
  /**
11
11
  * pantheon-tui — Pantheon TUI plugin for opencode.
12
12
  *
13
- * Single self-contained entry file: `tsdown && cp src/index.tsx dist/tui.tsx`
14
- * keeps the no-build load path working (dist/tui.tsx is raw source, transpiled
15
- * on the fly by opencode). All feature code lives in this one file.
13
+ * Bundled entry: `tsdown` emits `dist/tui.js`, and the package `exports`
14
+ * (`./tui` → ./dist/tui.js, `./server` → ./dist/server.js) is the ONLY load
15
+ * path — no raw TSX copy is shipped. Because the bundle inlines relative
16
+ * imports, this entry may be split into modules without breaking the loader.
16
17
  *
17
18
  * Slots:
18
19
  * - sidebar_content (order 900) — Pantheon sidebar (header/version/
@@ -164,7 +165,7 @@ async function detectVersion(api) {
164
165
  if (ver) return ver;
165
166
  }
166
167
  } catch {}
167
- return "1.5.0-beta.10";
168
+ return "1.5.0-beta.12";
168
169
  }
169
170
  /**
170
171
  * usage-bar — AI subscription usage gauge for the opencode TUI.
@@ -839,17 +840,74 @@ async function readDelegationEntries(dir) {
839
840
  async function readAllDelegationEntries(root) {
840
841
  return readDelegationEntries(join(root, ".pantheon", "delegations"));
841
842
  }
843
+ /** The persisted subset of BackgroundJobRecord the panel consumes. Duck-typed
844
+ * so a corrupt/older record never breaks parsing. */
845
+ /** The FilePersistence state path: `<root>/.pantheon/board/state.json`. */
846
+ function boardStatePath(root) {
847
+ return join(root, ".pantheon", "board", "state.json");
848
+ }
849
+ /** Validate one parsed record, keeping only the fields the panel uses.
850
+ * Returns null for anything without a taskID/state (a corrupt entry is
851
+ * skipped individually — the rest of the snapshot still loads). */
852
+ function normalizeBoardRecord(item) {
853
+ if (typeof item !== "object" || item === null) return null;
854
+ const rec = item;
855
+ if (typeof rec.taskID !== "string" || rec.taskID === "") return null;
856
+ if (typeof rec.state !== "string" || rec.state === "") return null;
857
+ const record = {
858
+ taskID: rec.taskID,
859
+ parentSessionID: typeof rec.parentSessionID === "string" ? rec.parentSessionID : "",
860
+ agent: typeof rec.agent === "string" && rec.agent !== "" ? rec.agent : "agent",
861
+ state: rec.state,
862
+ alias: typeof rec.alias === "string" ? rec.alias : ""
863
+ };
864
+ if (typeof rec.description === "string") record.description = rec.description;
865
+ if (typeof rec.launchedAt === "number" && Number.isFinite(rec.launchedAt)) record.launchedAt = rec.launchedAt;
866
+ if (typeof rec.completedAt === "number" && Number.isFinite(rec.completedAt)) record.completedAt = rec.completedAt;
867
+ if (typeof rec.updatedAt === "number" && Number.isFinite(rec.updatedAt)) record.updatedAt = rec.updatedAt;
868
+ if (typeof rec.timedOut === "boolean") record.timedOut = rec.timedOut;
869
+ return record;
870
+ }
871
+ /** Read `.pantheon/board/state.json` (the cross-session job board snapshot).
872
+ * Fail-open: missing file, corrupt JSON, non-array payload or an unreadable
873
+ * path all yield [] — the panel keeps rendering from the other channels. */
874
+ async function readBoardState(root) {
875
+ let raw;
876
+ try {
877
+ raw = await readFile(boardStatePath(root), "utf8");
878
+ } catch {
879
+ return [];
880
+ }
881
+ let parsed;
882
+ try {
883
+ parsed = JSON.parse(raw);
884
+ } catch {
885
+ return [];
886
+ }
887
+ if (!Array.isArray(parsed)) return [];
888
+ const records = [];
889
+ for (const item of parsed) {
890
+ const record = normalizeBoardRecord(item);
891
+ if (record !== null) records.push(record);
892
+ }
893
+ return records;
894
+ }
895
+ /** Resolve the PROJECT ROOT used by every pantheon file channel. `directory`
896
+ * wins over `worktree` (the old `resolveDelegationsDir` already did this);
897
+ * an absent/empty root or `/` (no git — e.g. the sandbox test project) falls
898
+ * back to cwd. Standardised here so the delegations md, the board state file
899
+ * and the panel logger all read the SAME root (audit finding: the channels
900
+ * resolved the root independently). Pure — no I/O. */
901
+ function resolvePantheonRoot(state, cwd = process.cwd()) {
902
+ const root = state?.directory ?? state?.worktree ?? "";
903
+ if (root === "" || root === "/") return cwd;
904
+ return root;
905
+ }
842
906
  /** Resolve the directory where the job board writes delegation md reports.
843
907
  * The board writes `.pantheon/delegations` RELATIVE to the server cwd,
844
- * which the TUI exposes as `TuiState.path.directory`. `project` does NOT
845
- * exist on `TuiState.path` (the old `state?.project ?? state?.worktree`
846
- * resolution was always undefined for the first term) and `worktree` is
847
- * `/` when there is no git (e.g. the sandbox test project) — a root of
848
- * `''` or `'/'` must fall back to `process.cwd()`. */
908
+ * which the TUI exposes as `TuiState.path.directory`. */
849
909
  function resolveDelegationsDir(state, cwd = process.cwd()) {
850
- const root = state?.directory ?? state?.worktree ?? "";
851
- if (root === "" || root === "/") return join(cwd, ".pantheon", "delegations");
852
- return join(root, ".pantheon", "delegations");
910
+ return join(resolvePantheonRoot(state, cwd), ".pantheon", "delegations");
853
911
  }
854
912
  /** Project root derived from the delegations dir: `<root>/.pantheon/delegations`
855
913
  * → `<root>`. Used to point the panel logger at the REAL hooks.log — passing
@@ -977,6 +1035,49 @@ function delegationSpinnerFrame(now) {
977
1035
  const index = Math.floor(Math.max(0, now) / 1e3) % DELEGATION_SPINNER_FRAMES.length;
978
1036
  return DELEGATION_SPINNER_FRAMES[index] ?? DELEGATION_SPINNER_FRAMES[0];
979
1037
  }
1038
+ /** Every state the row knows how to draw: the real BackgroundJobBoard FSM
1039
+ * (src/pantheon/background-job-board.ts) plus the TUI display-only states
1040
+ * (`retry`, `stale-running`). Fase 1 deliberately omits speculative
1041
+ * blocked/paused/scheduled/skipped. There is no `pending` display state: a
1042
+ * pre-dispatch tool part maps to `running` in {@link reduceDelegationToolPart}. */
1043
+ /** Static glyph per display state. `running` shows its base spinner frame;
1044
+ * callers that animate must prefer {@link delegationStateMarker}. Unicode
1045
+ * geometric shapes only (no Nerd Font) — shape is an independent channel
1046
+ * from color, so rows stay legible without color. */
1047
+ const DELEGATION_STATE_GLYPHS = {
1048
+ running: "⠋",
1049
+ retry: "⟳",
1050
+ "stale-running": "⚠",
1051
+ completed: "✓",
1052
+ error: "✕",
1053
+ cancelled: "−",
1054
+ startup_failed: "⚠",
1055
+ startup_unknown: "⚠"
1056
+ };
1057
+ function delegationStateGlyph(state) {
1058
+ return DELEGATION_STATE_GLYPHS[state];
1059
+ }
1060
+ /** Row marker (`<glyph> `) — the state channel. `running` animates through
1061
+ * {@link delegationSpinnerFrame} for the given tick; every other state is
1062
+ * static. Pure. */
1063
+ function delegationStateMarker(state, now = Date.now()) {
1064
+ return `${state === "running" ? delegationSpinnerFrame(now) : delegationStateGlyph(state)} `;
1065
+ }
1066
+ /** Semantic tone mapped to the TUI theme at the row ({@link DelegationRow}).
1067
+ * Kept separate + pure so the color channel is testable without booting the
1068
+ * renderer. */
1069
+ function delegationStateTone(state) {
1070
+ switch (state) {
1071
+ case "running":
1072
+ case "retry":
1073
+ case "startup_unknown": return "warning";
1074
+ case "stale-running":
1075
+ case "error":
1076
+ case "startup_failed": return "error";
1077
+ case "completed": return "success";
1078
+ case "cancelled": return "muted";
1079
+ }
1080
+ }
980
1081
  /** Bounded tracker: child session id → latest running tool call. */
981
1082
  const latestToolActivity = /* @__PURE__ */ new Map();
982
1083
  const MAX_TOOL_ACTIVITY_ENTRIES = 200;
@@ -1336,6 +1437,106 @@ function mergeDelegationSources(live, md) {
1336
1437
  all.sort(compareDelegationEntries);
1337
1438
  return all;
1338
1439
  }
1440
+ /** Job-board FSM → panel display state. `reconciled` is intentionally absent:
1441
+ * the panel parser rejects it (a reconciled job is done and folded away). */
1442
+ const BOARD_STATE_TO_DISPLAY = {
1443
+ running: "running",
1444
+ completed: "completed",
1445
+ error: "error",
1446
+ startup_failed: "startup_failed",
1447
+ startup_unknown: "startup_unknown",
1448
+ cancelled: "cancelled"
1449
+ };
1450
+ /** Map one persisted board record into the display shape. Returns null for
1451
+ * states the panel does not render (reconciled / unknown). Pure. */
1452
+ function boardRecordToDelegationEntry(record) {
1453
+ const state = BOARD_STATE_TO_DISPLAY[record.state];
1454
+ if (state === void 0) return null;
1455
+ const running = state === "running";
1456
+ return {
1457
+ alias: record.alias !== "" ? record.alias : `job-${record.taskID.slice(0, 8)}`,
1458
+ sessionID: record.parentSessionID,
1459
+ taskID: record.taskID,
1460
+ agent: record.agent,
1461
+ state,
1462
+ startedAt: record.launchedAt ?? record.updatedAt ?? 0,
1463
+ updatedAt: running ? null : record.completedAt ?? record.updatedAt ?? null,
1464
+ timedOut: record.timedOut === true,
1465
+ description: record.description ?? "",
1466
+ source: "board"
1467
+ };
1468
+ }
1469
+ /** Map a whole board snapshot, dropping unrenderable states. Sorted like every
1470
+ * other channel (running first, then most recent). Pure. */
1471
+ function boardRecordsToDelegationEntries(records) {
1472
+ const out = [];
1473
+ for (const record of records) {
1474
+ const entry = boardRecordToDelegationEntry(record);
1475
+ if (entry !== null) out.push(entry);
1476
+ }
1477
+ out.sort(compareDelegationEntries);
1478
+ return out;
1479
+ }
1480
+ /** Merge the board over any other channel. The board is AUTHORITATIVE for
1481
+ * state/alias/agent (it is the persisted FSM) and it is the only channel
1482
+ * that carries jobs from OTHER sessions. Dedup by taskID first, then by
1483
+ * (sessionID, alias) — aliases are per parent session. Pure. */
1484
+ function mergeBoardDelegationSources(base, board) {
1485
+ const key = (sessionID, alias) => `${sessionID}\u0000${alias}`;
1486
+ const byTaskID = /* @__PURE__ */ new Map();
1487
+ const bySessionAlias = /* @__PURE__ */ new Map();
1488
+ const out = [...base];
1489
+ out.forEach((entry, index) => {
1490
+ if (entry.taskID !== void 0) byTaskID.set(entry.taskID, index);
1491
+ bySessionAlias.set(key(entry.sessionID, entry.alias), index);
1492
+ });
1493
+ for (const incoming of board) {
1494
+ const index = (incoming.taskID !== void 0 ? byTaskID.get(incoming.taskID) : void 0) ?? bySessionAlias.get(key(incoming.sessionID, incoming.alias));
1495
+ if (index === void 0) {
1496
+ out.push(incoming);
1497
+ const next = out.length - 1;
1498
+ if (incoming.taskID !== void 0) byTaskID.set(incoming.taskID, next);
1499
+ bySessionAlias.set(key(incoming.sessionID, incoming.alias), next);
1500
+ continue;
1501
+ }
1502
+ out[index] = incoming;
1503
+ }
1504
+ out.sort(compareDelegationEntries);
1505
+ return out;
1506
+ }
1507
+ /** 'session' = focused session only (default); 'all' = every session the
1508
+ * board knows about. */
1509
+ /** api.kv key holding the persisted scope (defaults to 'session'). */
1510
+ const DELEGATION_SCOPE_KV_KEY = "delegations.scope";
1511
+ /** Structural subset of TuiKV — kept local so the pure helpers are testable
1512
+ * without the TUI runtime. */
1513
+ /** Read the persisted scope; anything malformed/absent → 'session'. */
1514
+ function readDelegationScope(kv) {
1515
+ try {
1516
+ return kv?.get?.("delegations.scope", "session") === "all" ? "all" : "session";
1517
+ } catch {
1518
+ return "session";
1519
+ }
1520
+ }
1521
+ /** Persist the scope. Failure is non-fatal — the signal keeps it in memory. */
1522
+ function writeDelegationScope(kv, scope) {
1523
+ try {
1524
+ kv?.set?.(DELEGATION_SCOPE_KV_KEY, scope);
1525
+ } catch {}
1526
+ }
1527
+ /** Keyboard/click toggle target. Pure. */
1528
+ function nextDelegationScope(scope) {
1529
+ return scope === "session" ? "all" : "session";
1530
+ }
1531
+ /** Keep only the focused session's jobs ('session') or all of them ('all').
1532
+ * An empty sessionID marks a current-session child (the children channel is
1533
+ * session-scoped and only fills sessionID from a matching md report), so it
1534
+ * counts as the current session. With no resolved session there is nothing
1535
+ * to scope against — fail-open to the full list. Pure. */
1536
+ function filterDelegationsByScope(entries, scope, sessionID) {
1537
+ if (scope === "all" || sessionID === null) return [...entries];
1538
+ return entries.filter((entry) => entry.sessionID === sessionID || entry.sessionID === "");
1539
+ }
1339
1540
  /** Server-aligned session id validity: opencode rejects anything not starting
1340
1541
  * with "ses" (SchemaError). This deliberately mirrors that exact contract —
1341
1542
  * nothing stricter, nothing looser — so a template placeholder ("{sessionID}"),
@@ -1603,25 +1804,14 @@ function DelegationRow(props) {
1603
1804
  const theme = () => props.api.theme.current;
1604
1805
  const color = createMemo(() => {
1605
1806
  const t = theme();
1606
- switch (props.job.state) {
1607
- case "running": return t.warning;
1608
- case "retry": return t.warning;
1609
- case "stale-running": return t.error;
1610
- case "completed": return t.success;
1807
+ switch (delegationStateTone(props.job.state)) {
1808
+ case "warning": return t.warning;
1611
1809
  case "error": return t.error;
1810
+ case "success": return t.success;
1612
1811
  default: return t.textMuted;
1613
1812
  }
1614
1813
  });
1615
- const marker = createMemo(() => {
1616
- if (props.job.state === "running") return `${delegationSpinnerFrame(props.animationNow)} `;
1617
- if (props.job.state === "retry") return "⟳ ";
1618
- if (props.job.state === "stale-running") return "⚠ ";
1619
- switch (props.job.state) {
1620
- case "completed": return "✓ ";
1621
- case "error": return "✕ ";
1622
- default: return "○ ";
1623
- }
1624
- });
1814
+ const marker = createMemo(() => delegationStateMarker(props.job.state, props.animationNow));
1625
1815
  const tagColor = createMemo(() => props.job.source === "children-only" ? theme().info : color());
1626
1816
  const description = createMemo(() => truncateDelegationDescription(props.job.description));
1627
1817
  const elapsed = createMemo(() => formatDelegationElapsed(props.job, props.now));
@@ -1729,8 +1919,13 @@ function View(props) {
1729
1919
  return (b.time?.updated ?? b.updated ?? 0) - ta;
1730
1920
  }).slice(0, 8);
1731
1921
  });
1732
- const delegationsDir = createMemo(() => resolveDelegationsDir(props.api.state.path));
1733
- const panelLog = createTuiLogger(panelLogDir(delegationsDir()));
1922
+ const projectRoot = createMemo(() => resolvePantheonRoot(props.api.state.path));
1923
+ const panelLog = createTuiLogger(projectRoot());
1924
+ const [delegationScope, setDelegationScope] = createSignal(readDelegationScope(props.api.kv));
1925
+ const applyDelegationScope = (scope) => {
1926
+ setDelegationScope(scope);
1927
+ writeDelegationScope(props.api.kv, scope);
1928
+ };
1734
1929
  const [childDelegations, setChildDelegations] = createSignal([]);
1735
1930
  const [now, setNow] = createSignal(Date.now());
1736
1931
  const [animationNow, setAnimationNow] = createSignal(Date.now());
@@ -1743,17 +1938,23 @@ function View(props) {
1743
1938
  const state = props.api.state;
1744
1939
  let md = [];
1745
1940
  try {
1746
- md = await readAllDelegationEntries(panelLogDir(delegationsDir()));
1941
+ md = await readAllDelegationEntries(projectRoot());
1747
1942
  } catch {
1748
1943
  md = [];
1749
1944
  }
1945
+ let board = [];
1946
+ try {
1947
+ board = boardRecordsToDelegationEntries(await readBoardState(projectRoot()));
1948
+ } catch {
1949
+ board = [];
1950
+ }
1750
1951
  const sessionID = resolveCurrentSessionID({
1751
1952
  sessionID: props.sessionID,
1752
1953
  api: props.api
1753
1954
  });
1754
1955
  if (sessionID === null) {
1755
- setChildDelegations(md);
1756
- panelLog.info(`${formatPanelLogLine(0, 0, 0, md.length, eventRefreshCount)} (no sessionID — history shown)`);
1956
+ setChildDelegations(mergeBoardDelegationSources(md, board));
1957
+ panelLog.info(`${formatPanelLogLine(0, 0, 0, md.length, eventRefreshCount)} (no sessionID — history+board shown)`);
1757
1958
  return;
1758
1959
  }
1759
1960
  let children = [];
@@ -1777,9 +1978,10 @@ function View(props) {
1777
1978
  ...c,
1778
1979
  status: resolveStatus(c.id)
1779
1980
  })), md, now());
1981
+ for (const entry of childEntries) if (entry.sessionID === "") entry.sessionID = sessionID;
1780
1982
  for (const [k, v] of props.liveStore.map) if (v.alias === null && v.taskID === null && Date.now() - v.startedAt > 3e4) props.liveStore.map.delete(k);
1781
1983
  const liveEntries = [...props.liveStore.map.values()].filter((entry) => entry.sessionID === sessionID);
1782
- setChildDelegations(mergeChildDelegationSources(childEntries, liveEntries));
1984
+ setChildDelegations(mergeBoardDelegationSources(mergeChildDelegationSources(childEntries, liveEntries), board));
1783
1985
  const counts = countDelegationSources(childEntries);
1784
1986
  panelLog.info(formatPanelLogLine(children.length, counts.pantheon, counts.native, md.length, eventRefreshCount));
1785
1987
  } finally {
@@ -1788,9 +1990,13 @@ function View(props) {
1788
1990
  })();
1789
1991
  return delegationsInflight;
1790
1992
  };
1791
- const delegationSplit = createMemo(() => splitDelegationList(childDelegations()));
1993
+ const scopedDelegations = createMemo(() => filterDelegationsByScope(childDelegations(), delegationScope(), resolveCurrentSessionID({
1994
+ sessionID: props.sessionID,
1995
+ api: props.api
1996
+ })));
1997
+ const delegationSplit = createMemo(() => splitDelegationList(scopedDelegations()));
1792
1998
  const visibleDelegations = createMemo(() => [...delegationSplit().active, ...delegationSplit().recent]);
1793
- const delegationHeader = createMemo(() => formatDelegationHeader(childDelegations()));
1999
+ const delegationHeader = createMemo(() => formatDelegationHeader(scopedDelegations()));
1794
2000
  const [archivedPage, setArchivedPage] = createSignal(archivedUiState.page);
1795
2001
  const clampArchivedPage = (page, pages) => {
1796
2002
  const clamped = Math.max(0, Math.min(page, Math.max(0, pages - 1)));
@@ -1840,6 +2046,23 @@ function View(props) {
1840
2046
  if (parts.length > 0 && seedLiveDelegationMap(props.liveStore.map, parts) > 0) props.liveStore.bump();
1841
2047
  }
1842
2048
  } catch {}
2049
+ try {
2050
+ const keymap = props.api?.keymap;
2051
+ if (typeof keymap?.registerLayer === "function") {
2052
+ const off = keymap.registerLayer({
2053
+ priority: 1e3,
2054
+ commands: [{
2055
+ name: "pantheon.delegations.toggleScope",
2056
+ run: () => applyDelegationScope(nextDelegationScope(delegationScope()))
2057
+ }],
2058
+ bindings: [{
2059
+ key: "ctrl+shift+d",
2060
+ cmd: "pantheon.delegations.toggleScope"
2061
+ }]
2062
+ });
2063
+ if (typeof off === "function") cleanup.push(off);
2064
+ }
2065
+ } catch {}
1843
2066
  onCleanup(() => cleanup.forEach((fn) => {
1844
2067
  fn();
1845
2068
  }));
@@ -1851,7 +2074,7 @@ function View(props) {
1851
2074
  return _el$20;
1852
2075
  })();
1853
2076
  return (() => {
1854
- var _el$22 = createElement("box"), _el$23 = createElement("text"), _el$24 = createElement("box"), _el$25 = createElement("text"), _el$26 = createElement("text"), _el$28 = createElement("box"), _el$29 = createElement("text"), _el$30 = createElement("text");
2077
+ var _el$22 = createElement("box"), _el$23 = createElement("text"), _el$24 = createElement("box"), _el$25 = createElement("text"), _el$26 = createElement("text"), _el$28 = createElement("box"), _el$29 = createElement("text"), _el$30 = createElement("text"), _el$31 = createElement("text"), _el$33 = createElement("text"), _el$35 = createElement("text"), _el$37 = createElement("text");
1855
2078
  insertNode(_el$22, _el$23);
1856
2079
  insertNode(_el$22, _el$24);
1857
2080
  insertNode(_el$22, _el$28);
@@ -1864,10 +2087,10 @@ function View(props) {
1864
2087
  return branch();
1865
2088
  },
1866
2089
  children: (b) => (() => {
1867
- var _el$32 = createElement("text");
1868
- insert(_el$32, b);
1869
- effect((_$p) => setProp(_el$32, "fg", theme().textMuted, _$p));
1870
- return _el$32;
2090
+ var _el$40 = createElement("text");
2091
+ insert(_el$40, b);
2092
+ effect((_$p) => setProp(_el$40, "fg", theme().textMuted, _$p));
2093
+ return _el$40;
1871
2094
  })()
1872
2095
  }), _el$24);
1873
2096
  insert(_el$22, createComponent(Show, {
@@ -1876,37 +2099,37 @@ function View(props) {
1876
2099
  },
1877
2100
  get fallback() {
1878
2101
  return (() => {
1879
- var _el$33 = createElement("box"), _el$34 = createElement("text");
1880
- insertNode(_el$33, _el$34);
1881
- setProp(_el$33, "flexDirection", "row");
1882
- setProp(_el$33, "gap", 1);
1883
- insertNode(_el$34, createTextNode(`Preset: default`));
1884
- effect((_$p) => setProp(_el$34, "fg", theme().textMuted, _$p));
1885
- return _el$33;
2102
+ var _el$41 = createElement("box"), _el$42 = createElement("text");
2103
+ insertNode(_el$41, _el$42);
2104
+ setProp(_el$41, "flexDirection", "row");
2105
+ setProp(_el$41, "gap", 1);
2106
+ insertNode(_el$42, createTextNode(`Preset: default`));
2107
+ effect((_$p) => setProp(_el$42, "fg", theme().textMuted, _$p));
2108
+ return _el$41;
1886
2109
  })();
1887
2110
  },
1888
2111
  children: (name) => (() => {
1889
- var _el$36 = createElement("box"), _el$37 = createElement("text"), _el$39 = createElement("text"), _el$40 = createElement("text");
1890
- insertNode(_el$36, _el$37);
1891
- insertNode(_el$36, _el$39);
1892
- insertNode(_el$36, _el$40);
1893
- setProp(_el$36, "flexDirection", "row");
1894
- setProp(_el$36, "gap", 1);
1895
- insertNode(_el$37, createTextNode(`⚡ Preset:`));
1896
- insert(_el$39, name);
1897
- insert(_el$40, () => `(${preset().source ?? ""})`);
2112
+ var _el$44 = createElement("box"), _el$45 = createElement("text"), _el$47 = createElement("text"), _el$48 = createElement("text");
2113
+ insertNode(_el$44, _el$45);
2114
+ insertNode(_el$44, _el$47);
2115
+ insertNode(_el$44, _el$48);
2116
+ setProp(_el$44, "flexDirection", "row");
2117
+ setProp(_el$44, "gap", 1);
2118
+ insertNode(_el$45, createTextNode(`⚡ Preset:`));
2119
+ insert(_el$47, name);
2120
+ insert(_el$48, () => `(${preset().source ?? ""})`);
1898
2121
  effect((_p$) => {
1899
- var _v$11 = theme().textMuted, _v$12 = theme().accent, _v$13 = theme().textMuted;
1900
- _v$11 !== _p$.e && (_p$.e = setProp(_el$37, "fg", _v$11, _p$.e));
1901
- _v$12 !== _p$.t && (_p$.t = setProp(_el$39, "fg", _v$12, _p$.t));
1902
- _v$13 !== _p$.a && (_p$.a = setProp(_el$40, "fg", _v$13, _p$.a));
2122
+ var _v$17 = theme().textMuted, _v$18 = theme().accent, _v$19 = theme().textMuted;
2123
+ _v$17 !== _p$.e && (_p$.e = setProp(_el$45, "fg", _v$17, _p$.e));
2124
+ _v$18 !== _p$.t && (_p$.t = setProp(_el$47, "fg", _v$18, _p$.t));
2125
+ _v$19 !== _p$.a && (_p$.a = setProp(_el$48, "fg", _v$19, _p$.a));
1903
2126
  return _p$;
1904
2127
  }, {
1905
2128
  e: void 0,
1906
2129
  t: void 0,
1907
2130
  a: void 0
1908
2131
  });
1909
- return _el$36;
2132
+ return _el$44;
1910
2133
  })()
1911
2134
  }), _el$24);
1912
2135
  insert(_el$22, createComponent(HR, {}), _el$24);
@@ -1927,12 +2150,12 @@ function View(props) {
1927
2150
  },
1928
2151
  get fallback() {
1929
2152
  return (() => {
1930
- var _el$41 = createElement("box"), _el$42 = createElement("text");
1931
- insertNode(_el$41, _el$42);
1932
- setProp(_el$41, "marginLeft", 1);
1933
- insertNode(_el$42, createTextNode(`No recent sessions`));
1934
- effect((_$p) => setProp(_el$42, "fg", theme().textMuted, _$p));
1935
- return _el$41;
2153
+ var _el$49 = createElement("box"), _el$50 = createElement("text");
2154
+ insertNode(_el$49, _el$50);
2155
+ setProp(_el$49, "marginLeft", 1);
2156
+ insertNode(_el$50, createTextNode(`No recent sessions`));
2157
+ effect((_$p) => setProp(_el$50, "fg", theme().textMuted, _$p));
2158
+ return _el$49;
1936
2159
  })();
1937
2160
  },
1938
2161
  get children() {
@@ -1957,10 +2180,26 @@ function View(props) {
1957
2180
  }), _el$28);
1958
2181
  insertNode(_el$28, _el$29);
1959
2182
  insertNode(_el$28, _el$30);
2183
+ insertNode(_el$28, _el$31);
2184
+ insertNode(_el$28, _el$33);
2185
+ insertNode(_el$28, _el$35);
2186
+ insertNode(_el$28, _el$37);
1960
2187
  setProp(_el$28, "onMouseDown", () => setShowDelegations((x) => !x));
1961
2188
  setProp(_el$29, "attributes", 1);
1962
2189
  insert(_el$29, () => `${showDelegations() ? "▼" : "▶"} Delegations`);
1963
2190
  insert(_el$30, () => ` ${delegationHeader()}`);
2191
+ insertNode(_el$31, createTextNode(` `));
2192
+ insertNode(_el$33, createTextNode(`[Sessão]`));
2193
+ setProp(_el$33, "onMouseDown", (e) => {
2194
+ if (typeof e === "object" && e !== null && "stopPropagation" in e) e.stopPropagation();
2195
+ applyDelegationScope("session");
2196
+ });
2197
+ insertNode(_el$35, createTextNode(`/`));
2198
+ insertNode(_el$37, createTextNode(`[Tudo]`));
2199
+ setProp(_el$37, "onMouseDown", (e) => {
2200
+ if (typeof e === "object" && e !== null && "stopPropagation" in e) e.stopPropagation();
2201
+ applyDelegationScope("all");
2202
+ });
1964
2203
  insert(_el$22, createComponent(Show, {
1965
2204
  get when() {
1966
2205
  return showDelegations();
@@ -1972,19 +2211,19 @@ function View(props) {
1972
2211
  },
1973
2212
  get fallback() {
1974
2213
  return (() => {
1975
- var _el$44 = createElement("box"), _el$45 = createElement("text");
1976
- insertNode(_el$44, _el$45);
1977
- setProp(_el$44, "marginLeft", 1);
1978
- insertNode(_el$45, createTextNode(`No delegations`));
1979
- effect((_$p) => setProp(_el$45, "fg", theme().textMuted, _$p));
1980
- return _el$44;
2214
+ var _el$52 = createElement("box"), _el$53 = createElement("text");
2215
+ insertNode(_el$52, _el$53);
2216
+ setProp(_el$52, "marginLeft", 1);
2217
+ insertNode(_el$53, createTextNode(`No delegations`));
2218
+ effect((_$p) => setProp(_el$53, "fg", theme().textMuted, _$p));
2219
+ return _el$52;
1981
2220
  })();
1982
2221
  },
1983
2222
  get children() {
1984
- var _el$31 = createElement("box");
1985
- setProp(_el$31, "marginLeft", 1);
1986
- setProp(_el$31, "flexDirection", "column");
1987
- insert(_el$31, createComponent(For, {
2223
+ var _el$39 = createElement("box");
2224
+ setProp(_el$39, "marginLeft", 1);
2225
+ setProp(_el$39, "flexDirection", "column");
2226
+ insert(_el$39, createComponent(For, {
1988
2227
  get each() {
1989
2228
  return visibleDelegations();
1990
2229
  },
@@ -2001,7 +2240,7 @@ function View(props) {
2001
2240
  }
2002
2241
  })
2003
2242
  }), null);
2004
- insert(_el$31, createComponent(Show, {
2243
+ insert(_el$39, createComponent(Show, {
2005
2244
  get when() {
2006
2245
  return delegationSplit().archived.length > 0;
2007
2246
  },
@@ -2013,22 +2252,22 @@ function View(props) {
2013
2252
  const page = Math.min(archivedPage(), pages - 1);
2014
2253
  const slice = archived.slice(page * pageSize, page * pageSize + pageSize);
2015
2254
  return (() => {
2016
- var _el$47 = createElement("box"), _el$48 = createElement("box"), _el$49 = createElement("text"), _el$51 = createElement("text"), _el$52 = createElement("text"), _el$53 = createElement("text");
2017
- insertNode(_el$47, _el$48);
2018
- setProp(_el$47, "flexDirection", "column");
2019
- insertNode(_el$48, _el$49);
2020
- insertNode(_el$48, _el$51);
2021
- insertNode(_el$48, _el$52);
2022
- insertNode(_el$48, _el$53);
2023
- setProp(_el$48, "flexDirection", "row");
2024
- setProp(_el$48, "marginLeft", 0);
2025
- insertNode(_el$49, createTextNode(`‹ `));
2026
- setProp(_el$49, "onMouseDown", () => clampArchivedPage(page - 1, pages));
2027
- insert(_el$51, () => `Archived (${archived.length}) `);
2028
- insert(_el$52, `${page + 1}/${pages}`);
2029
- insertNode(_el$53, createTextNode(` ›`));
2030
- setProp(_el$53, "onMouseDown", () => clampArchivedPage(page + 1, pages));
2031
- insert(_el$47, createComponent(For, {
2255
+ var _el$55 = createElement("box"), _el$56 = createElement("box"), _el$57 = createElement("text"), _el$59 = createElement("text"), _el$60 = createElement("text"), _el$61 = createElement("text");
2256
+ insertNode(_el$55, _el$56);
2257
+ setProp(_el$55, "flexDirection", "column");
2258
+ insertNode(_el$56, _el$57);
2259
+ insertNode(_el$56, _el$59);
2260
+ insertNode(_el$56, _el$60);
2261
+ insertNode(_el$56, _el$61);
2262
+ setProp(_el$56, "flexDirection", "row");
2263
+ setProp(_el$56, "marginLeft", 0);
2264
+ insertNode(_el$57, createTextNode(`‹ `));
2265
+ setProp(_el$57, "onMouseDown", () => clampArchivedPage(page - 1, pages));
2266
+ insert(_el$59, () => `Archived (${archived.length}) `);
2267
+ insert(_el$60, `${page + 1}/${pages}`);
2268
+ insertNode(_el$61, createTextNode(` ›`));
2269
+ setProp(_el$61, "onMouseDown", () => clampArchivedPage(page + 1, pages));
2270
+ insert(_el$55, createComponent(For, {
2032
2271
  each: slice,
2033
2272
  children: (job) => createComponent(DelegationRow, {
2034
2273
  get api() {
@@ -2044,11 +2283,11 @@ function View(props) {
2044
2283
  })
2045
2284
  }), null);
2046
2285
  effect((_p$) => {
2047
- var _v$14 = theme().textMuted, _v$15 = theme().textMuted, _v$16 = theme().textMuted, _v$17 = theme().textMuted;
2048
- _v$14 !== _p$.e && (_p$.e = setProp(_el$49, "fg", _v$14, _p$.e));
2049
- _v$15 !== _p$.t && (_p$.t = setProp(_el$51, "fg", _v$15, _p$.t));
2050
- _v$16 !== _p$.a && (_p$.a = setProp(_el$52, "fg", _v$16, _p$.a));
2051
- _v$17 !== _p$.o && (_p$.o = setProp(_el$53, "fg", _v$17, _p$.o));
2286
+ var _v$20 = theme().textMuted, _v$21 = theme().textMuted, _v$22 = theme().textMuted, _v$23 = theme().textMuted;
2287
+ _v$20 !== _p$.e && (_p$.e = setProp(_el$57, "fg", _v$20, _p$.e));
2288
+ _v$21 !== _p$.t && (_p$.t = setProp(_el$59, "fg", _v$21, _p$.t));
2289
+ _v$22 !== _p$.a && (_p$.a = setProp(_el$60, "fg", _v$22, _p$.a));
2290
+ _v$23 !== _p$.o && (_p$.o = setProp(_el$61, "fg", _v$23, _p$.o));
2052
2291
  return _p$;
2053
2292
  }, {
2054
2293
  e: void 0,
@@ -2056,30 +2295,42 @@ function View(props) {
2056
2295
  a: void 0,
2057
2296
  o: void 0
2058
2297
  });
2059
- return _el$47;
2298
+ return _el$55;
2060
2299
  })();
2061
2300
  })();
2062
2301
  }
2063
2302
  }), null);
2064
- return _el$31;
2303
+ return _el$39;
2065
2304
  }
2066
2305
  });
2067
2306
  }
2068
2307
  }), null);
2069
2308
  effect((_p$) => {
2070
- var _v$8 = theme().accent, _v$9 = theme().text, _v$0 = theme().textMuted, _v$1 = theme().text, _v$10 = theme().textMuted;
2309
+ var _v$8 = theme().accent, _v$9 = theme().text, _v$0 = theme().textMuted, _v$1 = theme().text, _v$10 = theme().textMuted, _v$11 = theme().textMuted, _v$12 = delegationScope() === "session" ? theme().accent : theme().textMuted, _v$13 = delegationScope() === "session" ? 1 : void 0, _v$14 = theme().textMuted, _v$15 = delegationScope() === "all" ? theme().accent : theme().textMuted, _v$16 = delegationScope() === "all" ? 1 : void 0;
2071
2310
  _v$8 !== _p$.e && (_p$.e = setProp(_el$23, "fg", _v$8, _p$.e));
2072
2311
  _v$9 !== _p$.t && (_p$.t = setProp(_el$25, "fg", _v$9, _p$.t));
2073
2312
  _v$0 !== _p$.a && (_p$.a = setProp(_el$26, "fg", _v$0, _p$.a));
2074
2313
  _v$1 !== _p$.o && (_p$.o = setProp(_el$29, "fg", _v$1, _p$.o));
2075
2314
  _v$10 !== _p$.i && (_p$.i = setProp(_el$30, "fg", _v$10, _p$.i));
2315
+ _v$11 !== _p$.n && (_p$.n = setProp(_el$31, "fg", _v$11, _p$.n));
2316
+ _v$12 !== _p$.s && (_p$.s = setProp(_el$33, "fg", _v$12, _p$.s));
2317
+ _v$13 !== _p$.h && (_p$.h = setProp(_el$33, "attributes", _v$13, _p$.h));
2318
+ _v$14 !== _p$.r && (_p$.r = setProp(_el$35, "fg", _v$14, _p$.r));
2319
+ _v$15 !== _p$.d && (_p$.d = setProp(_el$37, "fg", _v$15, _p$.d));
2320
+ _v$16 !== _p$.l && (_p$.l = setProp(_el$37, "attributes", _v$16, _p$.l));
2076
2321
  return _p$;
2077
2322
  }, {
2078
2323
  e: void 0,
2079
2324
  t: void 0,
2080
2325
  a: void 0,
2081
2326
  o: void 0,
2082
- i: void 0
2327
+ i: void 0,
2328
+ n: void 0,
2329
+ s: void 0,
2330
+ h: void 0,
2331
+ r: void 0,
2332
+ d: void 0,
2333
+ l: void 0
2083
2334
  });
2084
2335
  return _el$22;
2085
2336
  })();
@@ -2141,6 +2392,6 @@ const plugin = {
2141
2392
  setup: async () => {}
2142
2393
  };
2143
2394
  //#endregion
2144
- export { DELEGATION_DESCRIPTION_MAX, DELEGATION_ELAPSED_WIDTH, IDLE_SILENCE_MS, STALE_RUNNING_THRESHOLD_MS, buildChildrenPath, childStatusToState, childrenToDelegationEntries, collectDelegationToolParts, compareDelegationEntries, countDelegationSources, plugin as default, delegationActivity, delegationActivityLabel, delegationElapsed, delegationIcon, delegationSpinnerFrame, delegationTag, extractToolActivity, fmtElapsed, formatDelegationElapsed, formatDelegationHeader, formatDelegationIdentity, formatDelegationRow, formatPanelLogLine, isValidSessionId, latestToolActivityFor, markStaleIfRunning, mergeChildDelegationSources, mergeDelegationSources, navigateToDelegationSession, panelLogDir, parseDelegationMarkdown, parseDelegationToolPart, readAllDelegationEntries, readDelegationEntries, reduceDelegationToolPart, removeDelegationEntry, resolveCurrentSessionID, resolveDelegationsDir, safeSessionPath, seedLiveDelegationMap, splitDelegationList, toDelegationEntry, trackToolActivity, truncateDelegationDescription, tuiLogPath, visibleDelegationList };
2395
+ export { DELEGATION_DESCRIPTION_MAX, DELEGATION_ELAPSED_WIDTH, DELEGATION_SCOPE_KV_KEY, DELEGATION_STATE_GLYPHS, IDLE_SILENCE_MS, STALE_RUNNING_THRESHOLD_MS, boardRecordToDelegationEntry, boardRecordsToDelegationEntries, boardStatePath, buildChildrenPath, childStatusToState, childrenToDelegationEntries, collectDelegationToolParts, compareDelegationEntries, countDelegationSources, plugin as default, delegationActivity, delegationActivityLabel, delegationElapsed, delegationIcon, delegationSpinnerFrame, delegationStateGlyph, delegationStateMarker, delegationStateTone, delegationTag, extractToolActivity, filterDelegationsByScope, fmtElapsed, formatDelegationElapsed, formatDelegationHeader, formatDelegationIdentity, formatDelegationRow, formatPanelLogLine, isValidSessionId, latestToolActivityFor, markStaleIfRunning, mergeBoardDelegationSources, mergeChildDelegationSources, mergeDelegationSources, navigateToDelegationSession, nextDelegationScope, panelLogDir, parseDelegationMarkdown, parseDelegationToolPart, readAllDelegationEntries, readBoardState, readDelegationEntries, readDelegationScope, reduceDelegationToolPart, removeDelegationEntry, resolveCurrentSessionID, resolveDelegationsDir, resolvePantheonRoot, safeSessionPath, seedLiveDelegationMap, splitDelegationList, toDelegationEntry, trackToolActivity, truncateDelegationDescription, tuiLogPath, visibleDelegationList, writeDelegationScope };
2145
2396
 
2146
2397
  //# sourceMappingURL=tui.js.map