pantheon-opencode 1.5.0-beta.13 → 1.5.0-beta.15
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 +59 -0
- package/package.json +1 -1
- package/plugin.json +1 -1
- package/pyproject.toml +2 -5
- package/src/agents/zeus.md +4 -26
- package/src/pantheon/background-job-board.ts +4 -4
- package/src/pantheon/delegate-manager.ts +95 -10
- package/src/pantheon/delegation-classifier.ts +3 -4
- package/src/pantheon/delegation-finalize.ts +69 -7
- package/src/pantheon/delegation.ts +16 -4
- package/src/pantheon/presets.d.mts +0 -20
- package/src/pantheon/presets.mjs +0 -64
- package/src/pantheon/toon-codec.ts +1 -1
- package/src/plugin-v2.ts +4 -6
- package/src/plugin.ts +6 -6
- package/src/plugins/pantheon-hooks.ts +1 -1
- package/src/plugins/tui/dist/tui.d.ts +57 -40
- package/src/plugins/tui/dist/tui.d.ts.map +1 -1
- package/src/plugins/tui/dist/tui.js +145 -54
- package/src/plugins/tui/package-lock.json +2 -2
- package/src/plugins/tui/package.json +1 -1
- package/src/plugins/tui/src/index.tsx +245 -83
- package/src/routing.yml +0 -16
- package/scripts/hash_verify.py +0 -192
- package/scripts/test-context-compression.sh +0 -169
- package/src/pantheon/auto-wake.ts +0 -85
- package/src/pantheon/chat-reminders.ts +0 -9
- package/src/pantheon/comment-checker.ts +0 -48
- package/src/pantheon/compaction-assert.ts +0 -160
- package/src/pantheon/compaction-handoff.ts +0 -304
- package/src/pantheon/cost-tracker.ts +0 -108
- package/src/pantheon/dispatch-guard.ts +0 -109
- package/src/pantheon/permission-eval.ts +0 -284
- package/src/pantheon/preemptive-compact.ts +0 -76
- package/src/pantheon/provider-capabilities.ts +0 -221
- package/src/pantheon/provider-stream-tracker.ts +0 -182
- package/src/pantheon/retry-policy.ts +0 -212
- package/src/pantheon/token-opt.ts +0 -689
- package/src/pantheon/v2-events.ts +0 -148
- package/src/pantheon/v2-hooks.ts +0 -287
- package/src/pantheon/v2-tool-definitions.ts +0 -331
- package/src/pantheon/zeus-delegate-with-retry.ts +0 -406
|
@@ -165,7 +165,7 @@ async function detectVersion(api) {
|
|
|
165
165
|
if (ver) return ver;
|
|
166
166
|
}
|
|
167
167
|
} catch {}
|
|
168
|
-
return "1.5.0-beta.
|
|
168
|
+
return "1.5.0-beta.15";
|
|
169
169
|
}
|
|
170
170
|
/**
|
|
171
171
|
* usage-bar — AI subscription usage gauge for the opencode TUI.
|
|
@@ -832,11 +832,12 @@ async function readDelegationEntries(dir) {
|
|
|
832
832
|
}
|
|
833
833
|
/** Read delegation reports from EVERY session under
|
|
834
834
|
* `<root>/.pantheon/delegations/<sessionID>/<alias>.md` — the panel's
|
|
835
|
-
*
|
|
836
|
-
*
|
|
837
|
-
*
|
|
838
|
-
*
|
|
839
|
-
*
|
|
835
|
+
* ENRICHMENT source. The read is deliberately unfiltered (each entry carries
|
|
836
|
+
* its directory's sessionID, so a taskID match can enrich any channel);
|
|
837
|
+
* callers MUST scope the merged result with {@link filterDelegationsToSession}
|
|
838
|
+
* before rendering — only the active session's reports are shown. Entries are
|
|
839
|
+
* running first, Finalized desc (the sort applied by readDelegationEntries).
|
|
840
|
+
* Fail-open: a missing/unreadable directory yields []. */
|
|
840
841
|
async function readAllDelegationEntries(root) {
|
|
841
842
|
return readDelegationEntries(join(root, ".pantheon", "delegations"));
|
|
842
843
|
}
|
|
@@ -939,8 +940,13 @@ function compareDelegationEntries(a, b) {
|
|
|
939
940
|
function splitDelegationList(all, maxRecent = 8, now = Date.now(), staleThresholdMs = 1800 * 1e3) {
|
|
940
941
|
const isActiveState = (st) => st === "running" || st === "retry" || st === "stale-running";
|
|
941
942
|
return {
|
|
942
|
-
active: all.filter((d) => isActiveState(d.state)).map((d) => markStaleIfRunning(d, now, staleThresholdMs)),
|
|
943
|
-
recent: all.filter((d) => !isActiveState(d.state)).
|
|
943
|
+
active: all.filter((d) => isActiveState(d.state)).map((d) => markStaleIfRunning(d, now, staleThresholdMs)).sort(compareDelegationEntries),
|
|
944
|
+
recent: all.filter((d) => !isActiveState(d.state)).filter((d) => {
|
|
945
|
+
if (d.updatedAt === null || !Number.isFinite(d.updatedAt)) return true;
|
|
946
|
+
const age = now - d.updatedAt;
|
|
947
|
+
if (age < 0) return true;
|
|
948
|
+
return age < (delegationRowStatus(d.state) === "failed" ? DELEGATION_FAILED_RETENTION_MS : DELEGATION_DONE_RETENTION_MS);
|
|
949
|
+
}).sort(compareDelegationEntries).slice(0, maxRecent)
|
|
944
950
|
};
|
|
945
951
|
}
|
|
946
952
|
/** Live-first window used by {@link ceilingDelegationList} (kept for the
|
|
@@ -956,6 +962,15 @@ const STALE_RUNNING_THRESHOLD_MS = 1800 * 1e3;
|
|
|
956
962
|
* considered stale. Combined with the stale-running threshold to produce the
|
|
957
963
|
* display-only `stale-running` state. */
|
|
958
964
|
const IDLE_SILENCE_MS = 60 * 1e3;
|
|
965
|
+
/** Visual-only terminal retention windows. Reports remain on disk and in the
|
|
966
|
+
* board; these constants only control which rows enter the TUI window. */
|
|
967
|
+
const DELEGATION_DONE_RETENTION_MS = 120 * 1e3;
|
|
968
|
+
const DELEGATION_FAILED_RETENTION_MS = 600 * 1e3;
|
|
969
|
+
/** Alias-less NATIVE task() live entries never receive a board alias (the
|
|
970
|
+
* task tool output carries none), so the 30s alias-less prune in
|
|
971
|
+
* mergeChildDelegationSources must not apply to them — 5 minutes covers a
|
|
972
|
+
* slow child listing while still bounding the live map. */
|
|
973
|
+
const NATIVE_LIVE_ALIASLESS_TTL_MS = 300 * 1e3;
|
|
959
974
|
/**
|
|
960
975
|
* Mark a running entry as `stale-running` if it has been running longer than
|
|
961
976
|
* the threshold AND has no recent activity (no `updatedAt` change in the last
|
|
@@ -1039,20 +1054,21 @@ function delegationSpinnerFrame(now) {
|
|
|
1039
1054
|
* pre-dispatch tool part maps to `running` in {@link reduceDelegationToolPart}. */
|
|
1040
1055
|
/** Semantic tone mapped to the TUI theme at the row ({@link DelegationRow}).
|
|
1041
1056
|
* Kept separate + pure so the color channel is testable without booting the
|
|
1042
|
-
* renderer.
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
*
|
|
1057
|
+
* renderer. Every display state resolves to one of the three status colors;
|
|
1058
|
+
* the row paints its whole content with it (see {@link DelegationRow}). */
|
|
1059
|
+
/** Status → color mapping for the whole-row tone. Red = failure, green =
|
|
1060
|
+
* terminal, yellow = in flight. The glyph remains a redundant channel so the
|
|
1061
|
+
* state stays legible in monochrome. Display-only; no behavior change. */
|
|
1046
1062
|
function delegationStateTone(state) {
|
|
1047
1063
|
switch (state) {
|
|
1048
1064
|
case "running":
|
|
1049
1065
|
case "retry":
|
|
1050
|
-
case "startup_unknown":
|
|
1051
|
-
case "stale-running":
|
|
1066
|
+
case "startup_unknown":
|
|
1067
|
+
case "stale-running": return "warning";
|
|
1052
1068
|
case "error":
|
|
1053
1069
|
case "startup_failed": return "error";
|
|
1054
|
-
case "completed":
|
|
1055
|
-
case "cancelled": return "
|
|
1070
|
+
case "completed":
|
|
1071
|
+
case "cancelled": return "success";
|
|
1056
1072
|
}
|
|
1057
1073
|
}
|
|
1058
1074
|
/** Bounded tracker: child session id → latest running tool call. */
|
|
@@ -1127,13 +1143,11 @@ function mergeChildDelegationSources(children, live) {
|
|
|
1127
1143
|
bySessionAlias.set(key(entry.sessionID, entry.alias), index);
|
|
1128
1144
|
});
|
|
1129
1145
|
for (const liveEntry of live) {
|
|
1130
|
-
|
|
1146
|
+
const aliaslessTTL = liveEntry.tool === "task" ? NATIVE_LIVE_ALIASLESS_TTL_MS : 3e4;
|
|
1147
|
+
if (liveEntry.alias === null && liveEntry.taskID === null && Date.now() - liveEntry.startedAt > aliaslessTTL) continue;
|
|
1131
1148
|
const incoming = toDelegationEntry(liveEntry);
|
|
1132
1149
|
const isNativeLive = liveEntry.tool === "task" && liveEntry.alias === null;
|
|
1133
|
-
if (isNativeLive)
|
|
1134
|
-
incoming.source = "children-only";
|
|
1135
|
-
incoming.alias = "native-task";
|
|
1136
|
-
}
|
|
1150
|
+
if (isNativeLive) incoming.source = "children-only";
|
|
1137
1151
|
const index = (incoming.taskID !== void 0 ? byTask.get(incoming.taskID) : void 0) ?? (incoming.alias !== "" ? bySessionAlias.get(key(incoming.sessionID, incoming.alias)) : void 0);
|
|
1138
1152
|
if (index === void 0) {
|
|
1139
1153
|
result.push(incoming);
|
|
@@ -1456,10 +1470,29 @@ function boardRecordsToDelegationEntries(records) {
|
|
|
1456
1470
|
out.sort(compareDelegationEntries);
|
|
1457
1471
|
return out;
|
|
1458
1472
|
}
|
|
1473
|
+
/** Active (non-terminal) display states — a job in one of these is still live. */
|
|
1474
|
+
function isActiveDelegationState(state) {
|
|
1475
|
+
return state === "running" || state === "retry" || state === "stale-running";
|
|
1476
|
+
}
|
|
1477
|
+
/** Temporal guard for the board merge (recycled-alias regression): board
|
|
1478
|
+
* aliases recycle across jobs (apo-1 of a previous job), so a board
|
|
1479
|
+
* terminal record only closes a running entry when its Finalized timestamp
|
|
1480
|
+
* is STRICTLY NEWER than the entry it would close. Older/equal/missing
|
|
1481
|
+
* keeps the live entry — when in doubt the live job wins. Pure. */
|
|
1482
|
+
function shouldKeepRunningOverBoardTerminal(existing, incoming) {
|
|
1483
|
+
if (existing === void 0) return false;
|
|
1484
|
+
if (!isActiveDelegationState(existing.state)) return false;
|
|
1485
|
+
if (isActiveDelegationState(incoming.state)) return false;
|
|
1486
|
+
const incomingTs = incoming.updatedAt;
|
|
1487
|
+
if (incomingTs === null) return true;
|
|
1488
|
+
return incomingTs <= (existing.updatedAt ?? existing.startedAt);
|
|
1489
|
+
}
|
|
1459
1490
|
/** Merge the board over any other channel. The board is AUTHORITATIVE for
|
|
1460
|
-
* state/alias/agent (it is the persisted FSM)
|
|
1461
|
-
*
|
|
1462
|
-
*
|
|
1491
|
+
* state/alias/agent (it is the persisted FSM). This merge is intentionally
|
|
1492
|
+
* UNSCOPED so the board can enrich an active-session row (dedup by taskID);
|
|
1493
|
+
* the caller scopes the merged list with {@link filterDelegationsToSession},
|
|
1494
|
+
* which is what keeps other-session board jobs out of the panel. Dedup by
|
|
1495
|
+
* taskID first, then by (sessionID, alias) — aliases are per parent session. Pure. */
|
|
1463
1496
|
function mergeBoardDelegationSources(base, board) {
|
|
1464
1497
|
const key = (sessionID, alias) => `${sessionID}\u0000${alias}`;
|
|
1465
1498
|
const byTaskID = /* @__PURE__ */ new Map();
|
|
@@ -1478,6 +1511,7 @@ function mergeBoardDelegationSources(base, board) {
|
|
|
1478
1511
|
bySessionAlias.set(key(incoming.sessionID, incoming.alias), next);
|
|
1479
1512
|
continue;
|
|
1480
1513
|
}
|
|
1514
|
+
if (shouldKeepRunningOverBoardTerminal(out[index], incoming)) continue;
|
|
1481
1515
|
out[index] = {
|
|
1482
1516
|
...incoming,
|
|
1483
1517
|
sessionID: incoming.sessionID !== "" ? incoming.sessionID : out[index]?.sessionID ?? ""
|
|
@@ -1486,6 +1520,26 @@ function mergeBoardDelegationSources(base, board) {
|
|
|
1486
1520
|
out.sort(compareDelegationEntries);
|
|
1487
1521
|
return out;
|
|
1488
1522
|
}
|
|
1523
|
+
/** Scope a fully-merged display list to the ACTIVE session only.
|
|
1524
|
+
*
|
|
1525
|
+
* The panel is session-scoped: rows from other sessions (board snapshot, md
|
|
1526
|
+
* history under `.pantheon/delegations/<other-session>/`) and rows with no
|
|
1527
|
+
* attributable session (empty sessionID) are DROPPED. The previous
|
|
1528
|
+
* cross-session behavior rendered those rows and clicking them led to
|
|
1529
|
+
* "Session not found" — there is no cross-session channel anymore.
|
|
1530
|
+
*
|
|
1531
|
+
* The board/md channels still feed the merge UNFILTERED so the board can
|
|
1532
|
+
* ENRICH an active-session row with state/alias/agent (dedup by taskID), but
|
|
1533
|
+
* they can never introduce a row for another session: this filter is applied
|
|
1534
|
+
* ONCE, after every merge (children + live + md + board).
|
|
1535
|
+
*
|
|
1536
|
+
* Returns [] when no active session resolves (null/placeholder) — there is no
|
|
1537
|
+
* scope to show. Native children always carry the active session id (stamped
|
|
1538
|
+
* by `childrenToDelegationEntries`), so they survive the filter. Pure. */
|
|
1539
|
+
function filterDelegationsToSession(entries, activeSessionID) {
|
|
1540
|
+
if (!isValidSessionId(activeSessionID)) return [];
|
|
1541
|
+
return entries.filter((entry) => entry.sessionID === activeSessionID);
|
|
1542
|
+
}
|
|
1489
1543
|
/** Server-aligned session id validity: opencode rejects anything not starting
|
|
1490
1544
|
* with "ses" (SchemaError). This deliberately mirrors that exact contract —
|
|
1491
1545
|
* nothing stricter, nothing looser — so a template placeholder ("{sessionID}"),
|
|
@@ -1583,10 +1637,13 @@ function delegationRowMarker(state, now = Date.now()) {
|
|
|
1583
1637
|
return `${status === "active" ? delegationSpinnerFrame(now) : delegationRowGlyph(status)} `;
|
|
1584
1638
|
}
|
|
1585
1639
|
/** ONE identity per row: the short board alias (`apo-1`); a row without a
|
|
1586
|
-
* board alias (native task() child
|
|
1587
|
-
*
|
|
1640
|
+
* board alias (native task() child `native-task` / `native-<id>`, or an
|
|
1641
|
+
* alias-less native live row `live-<callID>` kept as children-only) shows
|
|
1642
|
+
* the agent instead — never alias + agent stacked. Pure. */
|
|
1588
1643
|
function delegationRowIdentity(entry) {
|
|
1589
|
-
if (entry.
|
|
1644
|
+
if (entry.agent === "") return entry.alias;
|
|
1645
|
+
if (entry.alias === "native-task" || entry.alias.startsWith("native-")) return entry.agent;
|
|
1646
|
+
if (entry.alias.startsWith("live-") && entry.source === "children-only") return entry.agent;
|
|
1590
1647
|
return entry.alias;
|
|
1591
1648
|
}
|
|
1592
1649
|
/** Fixed alias cell, pad-right + hard-truncate to `width` (default 7) so
|
|
@@ -1662,14 +1719,20 @@ function formatDelegationHeader(entries) {
|
|
|
1662
1719
|
const tail = failed > 0 ? ` · ${failed} failed` : "";
|
|
1663
1720
|
return `(${active} active · ${done} done${tail})`;
|
|
1664
1721
|
}
|
|
1665
|
-
/** Cap the panel: live rows first, then most-recent terminal rows, at
|
|
1666
|
-
* `maxVisible` total.
|
|
1667
|
-
*
|
|
1722
|
+
/** Cap the panel: live rows first, then most-recent retained terminal rows, at
|
|
1723
|
+
* most `maxVisible` total. Hidden counts describe the retained render list,
|
|
1724
|
+
* not expired history. */
|
|
1668
1725
|
function ceilingDelegationList(all, maxVisible = 8, now = Date.now()) {
|
|
1669
|
-
const
|
|
1726
|
+
const { active, recent } = splitDelegationList(all, all.length, now);
|
|
1727
|
+
const visibleActive = active.slice(0, maxVisible);
|
|
1728
|
+
const visible = [...visibleActive, ...recent.slice(0, Math.max(0, maxVisible - visibleActive.length))];
|
|
1729
|
+
const hiddenActive = Math.max(0, active.length - visibleActive.length);
|
|
1730
|
+
const hiddenTerminal = Math.max(0, recent.length - (visible.length - visibleActive.length));
|
|
1670
1731
|
return {
|
|
1671
1732
|
visible,
|
|
1672
|
-
hidden:
|
|
1733
|
+
hidden: hiddenActive + hiddenTerminal,
|
|
1734
|
+
hiddenActive,
|
|
1735
|
+
hiddenTerminal
|
|
1673
1736
|
};
|
|
1674
1737
|
}
|
|
1675
1738
|
/** Split a display list into native task() rows vs pantheon_delegate rows.
|
|
@@ -1698,11 +1761,13 @@ function formatPanelLogLine(children, pantheon, native, md, events) {
|
|
|
1698
1761
|
* itself (fallback 'agent'), state derived from its status, startedAt from
|
|
1699
1762
|
* time.created. A report-less child is a NATIVE task() child (every
|
|
1700
1763
|
* child of the current session — pantheon_delegate OR the native `task()`
|
|
1701
|
-
* tool — carries parentID = caller), so it gets source 'children-only',
|
|
1702
|
-
*
|
|
1703
|
-
* board alias. The 'task nativa' description fallback
|
|
1704
|
-
* non-empty when the child carries no title.
|
|
1705
|
-
*
|
|
1764
|
+
* tool — carries parentID = caller), so it gets source 'children-only', a
|
|
1765
|
+
* per-child alias 'native-<last4 of the child id>' (one identity per native
|
|
1766
|
+
* row) instead of a board alias. The 'task nativa' description fallback
|
|
1767
|
+
* keeps the row non-empty when the child carries no title.
|
|
1768
|
+
* A FRESH terminal md state wins over the derived state (a stale md report
|
|
1769
|
+
* from a previous incarnation never flips a live child — see
|
|
1770
|
+
* mdTerminalCoversChild); a running md defers to
|
|
1706
1771
|
* the child's live status. A running child is NEVER archived — it always
|
|
1707
1772
|
* lands in the active split (splitDelegationList active = running/retry).
|
|
1708
1773
|
* `parentSessionID` (the focused session id) is stamped on report-less
|
|
@@ -1710,6 +1775,20 @@ function formatPanelLogLine(children, pantheon, native, md, events) {
|
|
|
1710
1775
|
* unscoped ('').
|
|
1711
1776
|
* Sorted running-first (compareDelegationEntries).
|
|
1712
1777
|
* Pure — no I/O. */
|
|
1778
|
+
/** Temporal guard for the children channel (same recycled-alias class as the
|
|
1779
|
+
* board merge): an md terminal report matched by taskID may still belong to
|
|
1780
|
+
* a PREVIOUS job incarnation. Accept it only when its Finalized timestamp
|
|
1781
|
+
* covers the child's latest activity, when either side has no timestamp to
|
|
1782
|
+
* compare, or when both startedAt agree on a single job incarnation.
|
|
1783
|
+
* Pure — no I/O. */
|
|
1784
|
+
function mdTerminalCoversChild(md, child) {
|
|
1785
|
+
const childUpdated = child.time?.updated;
|
|
1786
|
+
if (md.updatedAt !== null && childUpdated !== void 0) {
|
|
1787
|
+
if (md.updatedAt >= childUpdated) return true;
|
|
1788
|
+
return md.startedAt === child.time?.created;
|
|
1789
|
+
}
|
|
1790
|
+
return true;
|
|
1791
|
+
}
|
|
1713
1792
|
function childrenToDelegationEntries(children, md, now = Date.now(), parentSessionID = "") {
|
|
1714
1793
|
const byTaskID = /* @__PURE__ */ new Map();
|
|
1715
1794
|
for (const m of md) if (m.taskID !== void 0 && !byTaskID.has(m.taskID)) byTaskID.set(m.taskID, m);
|
|
@@ -1719,9 +1798,9 @@ function childrenToDelegationEntries(children, md, now = Date.now(), parentSessi
|
|
|
1719
1798
|
if (child.id === "" || seen.has(child.id)) continue;
|
|
1720
1799
|
seen.add(child.id);
|
|
1721
1800
|
const mdEntry = byTaskID.get(child.id);
|
|
1722
|
-
const state = mdEntry !== void 0 && mdEntry.state !== "running" ? mdEntry.state : childStatusToState(child.status);
|
|
1801
|
+
const state = mdEntry !== void 0 && mdEntry.state !== "running" && mdTerminalCoversChild(mdEntry, child) ? mdEntry.state : childStatusToState(child.status);
|
|
1723
1802
|
out.push({
|
|
1724
|
-
alias: mdEntry?.alias ??
|
|
1803
|
+
alias: mdEntry?.alias ?? `native-${child.id.slice(-4)}`,
|
|
1725
1804
|
sessionID: mdEntry?.sessionID ?? parentSessionID,
|
|
1726
1805
|
taskID: child.id,
|
|
1727
1806
|
agent: mdEntry?.agent ?? child.agent ?? "agent",
|
|
@@ -1743,8 +1822,19 @@ function childrenToDelegationEntries(children, md, now = Date.now(), parentSessi
|
|
|
1743
1822
|
* unsubstituted "{sessionID}" placeholder can never be routed. */
|
|
1744
1823
|
function navigateToDelegationSession(route, taskID) {
|
|
1745
1824
|
if (typeof route?.navigate !== "function" || !isValidSessionId(taskID)) return false;
|
|
1746
|
-
|
|
1747
|
-
|
|
1825
|
+
try {
|
|
1826
|
+
const navigation = route.navigate("session", { sessionID: taskID });
|
|
1827
|
+
if (navigation !== void 0) Promise.resolve(navigation).catch(() => void 0);
|
|
1828
|
+
return true;
|
|
1829
|
+
} catch {
|
|
1830
|
+
return false;
|
|
1831
|
+
}
|
|
1832
|
+
}
|
|
1833
|
+
/** Build the mouse handler used by each delegation row. */
|
|
1834
|
+
function createDelegationRowOpenHandler(route, taskID) {
|
|
1835
|
+
return () => {
|
|
1836
|
+
navigateToDelegationSession(route, taskID);
|
|
1837
|
+
};
|
|
1748
1838
|
}
|
|
1749
1839
|
/** Silence-by-default panel logger.
|
|
1750
1840
|
* @param projectRoot the PROJECT ROOT — the logger appends to
|
|
@@ -1822,9 +1912,7 @@ function DelegationRow(props) {
|
|
|
1822
1912
|
const elapsed = createMemo(() => formatDelegationElapsed(props.job, props.now));
|
|
1823
1913
|
const description = createMemo(() => truncateDelegationDescription(props.job.description));
|
|
1824
1914
|
const activity = createMemo(() => latestToolActivityFor(latestToolActivity, props.job.taskID, props.now));
|
|
1825
|
-
const open = ()
|
|
1826
|
-
navigateToDelegationSession(props.api.route, props.job.taskID);
|
|
1827
|
-
};
|
|
1915
|
+
const open = createDelegationRowOpenHandler(props.api.route, props.job.taskID);
|
|
1828
1916
|
return (() => {
|
|
1829
1917
|
var _el$13 = createElement("box"), _el$14 = createElement("box"), _el$15 = createElement("text"), _el$16 = createElement("span"), _el$17 = createElement("span");
|
|
1830
1918
|
insertNode(_el$13, _el$14);
|
|
@@ -1842,7 +1930,7 @@ function DelegationRow(props) {
|
|
|
1842
1930
|
get children() {
|
|
1843
1931
|
var _el$18 = createElement("text");
|
|
1844
1932
|
insert(_el$18, () => ` ${description()}`);
|
|
1845
|
-
effect((_$p) => setProp(_el$18, "fg",
|
|
1933
|
+
effect((_$p) => setProp(_el$18, "fg", tone(), _$p));
|
|
1846
1934
|
return _el$18;
|
|
1847
1935
|
}
|
|
1848
1936
|
}), null);
|
|
@@ -1853,12 +1941,12 @@ function DelegationRow(props) {
|
|
|
1853
1941
|
children: (a) => (() => {
|
|
1854
1942
|
var _el$19 = createElement("text");
|
|
1855
1943
|
insert(_el$19, () => ` ↳ ${truncateDelegationDescription(`${a().tool}${a().summary !== "" ? ` ${a().summary}` : ""}`)}`);
|
|
1856
|
-
effect((_$p) => setProp(_el$19, "fg",
|
|
1944
|
+
effect((_$p) => setProp(_el$19, "fg", tone(), _$p));
|
|
1857
1945
|
return _el$19;
|
|
1858
1946
|
})()
|
|
1859
1947
|
}), null);
|
|
1860
1948
|
effect((_p$) => {
|
|
1861
|
-
var _v$5 = tone(), _v$6 =
|
|
1949
|
+
var _v$5 = tone(), _v$6 = tone();
|
|
1862
1950
|
_v$5 !== _p$.e && (_p$.e = setProp(_el$16, "fg", _v$5, _p$.e));
|
|
1863
1951
|
_v$6 !== _p$.t && (_p$.t = setProp(_el$17, "fg", _v$6, _p$.t));
|
|
1864
1952
|
return _p$;
|
|
@@ -1951,8 +2039,8 @@ function View(props) {
|
|
|
1951
2039
|
api: props.api
|
|
1952
2040
|
});
|
|
1953
2041
|
if (sessionID === null) {
|
|
1954
|
-
setChildDelegations(mergeBoardDelegationSources(md, board));
|
|
1955
|
-
panelLog.info(`${formatPanelLogLine(0, 0, 0, md.length, eventRefreshCount)} (no sessionID —
|
|
2042
|
+
setChildDelegations(filterDelegationsToSession(mergeBoardDelegationSources(md, board), sessionID));
|
|
2043
|
+
panelLog.info(`${formatPanelLogLine(0, 0, 0, md.length, eventRefreshCount)} (no sessionID — inactive panel)`);
|
|
1956
2044
|
return;
|
|
1957
2045
|
}
|
|
1958
2046
|
let children = [];
|
|
@@ -1978,7 +2066,7 @@ function View(props) {
|
|
|
1978
2066
|
})), md, now(), sessionID);
|
|
1979
2067
|
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);
|
|
1980
2068
|
const liveEntries = [...props.liveStore.map.values()].filter((entry) => entry.sessionID === sessionID);
|
|
1981
|
-
setChildDelegations(mergeBoardDelegationSources(mergeChildDelegationSources(childEntries, liveEntries), board));
|
|
2069
|
+
setChildDelegations(filterDelegationsToSession(mergeBoardDelegationSources(mergeChildDelegationSources(childEntries, liveEntries), board), sessionID));
|
|
1982
2070
|
const counts = countDelegationSources(childEntries);
|
|
1983
2071
|
panelLog.info(formatPanelLogLine(children.length, counts.pantheon, counts.native, md.length, eventRefreshCount));
|
|
1984
2072
|
} finally {
|
|
@@ -1988,7 +2076,7 @@ function View(props) {
|
|
|
1988
2076
|
return delegationsInflight;
|
|
1989
2077
|
};
|
|
1990
2078
|
const delegationCeiling = createMemo(() => ceilingDelegationList(childDelegations(), 8, now()));
|
|
1991
|
-
const delegationHeader = createMemo(() => formatDelegationHeader(
|
|
2079
|
+
const delegationHeader = createMemo(() => formatDelegationHeader(delegationCeiling().visible));
|
|
1992
2080
|
onMount(() => {
|
|
1993
2081
|
const cleanup = [];
|
|
1994
2082
|
try {
|
|
@@ -2153,7 +2241,7 @@ function View(props) {
|
|
|
2153
2241
|
setProp(_el$29, "attributes", 1);
|
|
2154
2242
|
insert(_el$29, () => `${showDelegations() ? "▼" : "▶"} Delegations`);
|
|
2155
2243
|
insert(_el$30, (() => {
|
|
2156
|
-
var _c$ = memo(() =>
|
|
2244
|
+
var _c$ = memo(() => delegationCeiling().visible.length > 0);
|
|
2157
2245
|
return () => _c$() ? ` ${delegationHeader()}` : " — idle";
|
|
2158
2246
|
})());
|
|
2159
2247
|
insert(_el$22, createComponent(Show, {
|
|
@@ -2202,7 +2290,10 @@ function View(props) {
|
|
|
2202
2290
|
},
|
|
2203
2291
|
get children() {
|
|
2204
2292
|
var _el$32 = createElement("text");
|
|
2205
|
-
insert(_el$32, () =>
|
|
2293
|
+
insert(_el$32, (() => {
|
|
2294
|
+
var _c$2 = memo(() => delegationCeiling().hiddenActive > 0);
|
|
2295
|
+
return () => _c$2() ? `… +${delegationCeiling().hiddenActive} active` : `… +${delegationCeiling().hiddenTerminal} more`;
|
|
2296
|
+
})());
|
|
2206
2297
|
effect((_$p) => setProp(_el$32, "fg", theme().textMuted, _$p));
|
|
2207
2298
|
return _el$32;
|
|
2208
2299
|
}
|
|
@@ -2287,6 +2378,6 @@ const plugin = {
|
|
|
2287
2378
|
setup: async () => {}
|
|
2288
2379
|
};
|
|
2289
2380
|
//#endregion
|
|
2290
|
-
export { DELEGATION_ALIAS_WIDTH, DELEGATION_DESCRIPTION_MAX, DELEGATION_ELAPSED_WIDTH, DELEGATION_ROW_GLYPHS, DELEGATION_VISIBLE_CEILING, IDLE_SILENCE_MS, STALE_RUNNING_THRESHOLD_MS, boardRecordToDelegationEntry, boardRecordsToDelegationEntries, boardStatePath, buildChildrenPath, ceilingDelegationList, childStatusToState, childrenToDelegationEntries, collectDelegationToolParts, compareDelegationEntries, countDelegationSources, plugin as default, delegationActivity, delegationActivityLabel, delegationElapsed, delegationRowGlyph, delegationRowIdentity, delegationRowMarker, delegationRowStatus, delegationSpinnerFrame, delegationStateTone, extractToolActivity, fmtElapsed, formatDelegationAlias, formatDelegationElapsed, formatDelegationHeader, formatDelegationRowLead, formatPanelLogLine, isValidSessionId, latestToolActivityFor, markStaleIfRunning, mergeBoardDelegationSources, mergeChildDelegationSources, mergeDelegationSources, navigateToDelegationSession, panelLogDir, parseDelegationMarkdown, parseDelegationToolPart, readAllDelegationEntries, readBoardState, readDelegationEntries, reduceDelegationToolPart, removeDelegationEntry, resolveCurrentSessionID, resolveDelegationsDir, resolvePantheonRoot, safeSessionPath, seedLiveDelegationMap, splitDelegationList, toDelegationEntry, trackToolActivity, truncateDelegationDescription, tuiLogPath, visibleDelegationList };
|
|
2381
|
+
export { DELEGATION_ALIAS_WIDTH, DELEGATION_DESCRIPTION_MAX, DELEGATION_DONE_RETENTION_MS, DELEGATION_ELAPSED_WIDTH, DELEGATION_FAILED_RETENTION_MS, DELEGATION_ROW_GLYPHS, DELEGATION_VISIBLE_CEILING, IDLE_SILENCE_MS, NATIVE_LIVE_ALIASLESS_TTL_MS, STALE_RUNNING_THRESHOLD_MS, boardRecordToDelegationEntry, boardRecordsToDelegationEntries, boardStatePath, buildChildrenPath, ceilingDelegationList, childStatusToState, childrenToDelegationEntries, collectDelegationToolParts, compareDelegationEntries, countDelegationSources, createDelegationRowOpenHandler, plugin as default, delegationActivity, delegationActivityLabel, delegationElapsed, delegationRowGlyph, delegationRowIdentity, delegationRowMarker, delegationRowStatus, delegationSpinnerFrame, delegationStateTone, extractToolActivity, filterDelegationsToSession, fmtElapsed, formatDelegationAlias, formatDelegationElapsed, formatDelegationHeader, formatDelegationRowLead, formatPanelLogLine, isValidSessionId, latestToolActivityFor, markStaleIfRunning, mergeBoardDelegationSources, mergeChildDelegationSources, mergeDelegationSources, navigateToDelegationSession, panelLogDir, parseDelegationMarkdown, parseDelegationToolPart, readAllDelegationEntries, readBoardState, readDelegationEntries, reduceDelegationToolPart, removeDelegationEntry, resolveCurrentSessionID, resolveDelegationsDir, resolvePantheonRoot, safeSessionPath, seedLiveDelegationMap, splitDelegationList, toDelegationEntry, trackToolActivity, truncateDelegationDescription, tuiLogPath, visibleDelegationList };
|
|
2291
2382
|
|
|
2292
2383
|
//# sourceMappingURL=tui.js.map
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pantheon-tui",
|
|
3
|
-
"version": "1.5.0-beta.
|
|
3
|
+
"version": "1.5.0-beta.15",
|
|
4
4
|
"lockfileVersion": 3,
|
|
5
5
|
"requires": true,
|
|
6
6
|
"packages": {
|
|
7
7
|
"": {
|
|
8
8
|
"name": "pantheon-tui",
|
|
9
|
-
"version": "1.5.0-beta.
|
|
9
|
+
"version": "1.5.0-beta.15",
|
|
10
10
|
"license": "MIT",
|
|
11
11
|
"dependencies": {
|
|
12
12
|
"@opencode-ai/plugin": ">=1.14.0",
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pantheon-tui",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "1.5.0-beta.
|
|
4
|
+
"version": "1.5.0-beta.15",
|
|
5
5
|
"description": "Pantheon TUI plugin — sidebar (version, preset, sessions, real-time delegations) + AI subscription usage gauges incl. OpenCode Go/Zen dollar limits (vendored, MIT)",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"exports": {
|