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.
- package/CHANGELOG.md +44 -0
- package/package.json +1 -2
- package/plugin.json +1 -1
- package/pyproject.toml +1 -1
- package/scripts/dev-tui.sh +48 -0
- package/scripts/doctor.mjs +32 -3
- package/scripts/install/plugin.mjs +9 -12
- package/scripts/sync-tui.mjs +8 -11
- package/src/pantheon/session-guard.ts +2 -2
- package/src/plugins/tui/dist/tui.d.ts +90 -8
- package/src/plugins/tui/dist/tui.d.ts.map +1 -1
- package/src/plugins/tui/dist/tui.js +355 -104
- package/src/plugins/tui/package-lock.json +2 -2
- package/src/plugins/tui/package.json +2 -2
- package/src/plugins/tui/src/index.tsx +410 -59
- package/src/plugins/tui/dist/tui.tsx +0 -2968
|
@@ -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
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
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.
|
|
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`.
|
|
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
|
-
|
|
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 "
|
|
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
|
|
1733
|
-
const panelLog = createTuiLogger(
|
|
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(
|
|
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
|
|
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(
|
|
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$
|
|
1868
|
-
insert(_el$
|
|
1869
|
-
effect((_$p) => setProp(_el$
|
|
1870
|
-
return _el$
|
|
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$
|
|
1880
|
-
insertNode(_el$
|
|
1881
|
-
setProp(_el$
|
|
1882
|
-
setProp(_el$
|
|
1883
|
-
insertNode(_el$
|
|
1884
|
-
effect((_$p) => setProp(_el$
|
|
1885
|
-
return _el$
|
|
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$
|
|
1890
|
-
insertNode(_el$
|
|
1891
|
-
insertNode(_el$
|
|
1892
|
-
insertNode(_el$
|
|
1893
|
-
setProp(_el$
|
|
1894
|
-
setProp(_el$
|
|
1895
|
-
insertNode(_el$
|
|
1896
|
-
insert(_el$
|
|
1897
|
-
insert(_el$
|
|
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$
|
|
1900
|
-
_v$
|
|
1901
|
-
_v$
|
|
1902
|
-
_v$
|
|
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$
|
|
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$
|
|
1931
|
-
insertNode(_el$
|
|
1932
|
-
setProp(_el$
|
|
1933
|
-
insertNode(_el$
|
|
1934
|
-
effect((_$p) => setProp(_el$
|
|
1935
|
-
return _el$
|
|
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$
|
|
1976
|
-
insertNode(_el$
|
|
1977
|
-
setProp(_el$
|
|
1978
|
-
insertNode(_el$
|
|
1979
|
-
effect((_$p) => setProp(_el$
|
|
1980
|
-
return _el$
|
|
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$
|
|
1985
|
-
setProp(_el$
|
|
1986
|
-
setProp(_el$
|
|
1987
|
-
insert(_el$
|
|
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$
|
|
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$
|
|
2017
|
-
insertNode(_el$
|
|
2018
|
-
setProp(_el$
|
|
2019
|
-
insertNode(_el$
|
|
2020
|
-
insertNode(_el$
|
|
2021
|
-
insertNode(_el$
|
|
2022
|
-
insertNode(_el$
|
|
2023
|
-
setProp(_el$
|
|
2024
|
-
setProp(_el$
|
|
2025
|
-
insertNode(_el$
|
|
2026
|
-
setProp(_el$
|
|
2027
|
-
insert(_el$
|
|
2028
|
-
insert(_el$
|
|
2029
|
-
insertNode(_el$
|
|
2030
|
-
setProp(_el$
|
|
2031
|
-
insert(_el$
|
|
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$
|
|
2048
|
-
_v$
|
|
2049
|
-
_v$
|
|
2050
|
-
_v$
|
|
2051
|
-
_v$
|
|
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$
|
|
2298
|
+
return _el$55;
|
|
2060
2299
|
})();
|
|
2061
2300
|
})();
|
|
2062
2301
|
}
|
|
2063
2302
|
}), null);
|
|
2064
|
-
return _el$
|
|
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
|