pantheon-opencode 1.5.0-beta.1 → 1.5.0-beta.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.pantheon/code-mode/manifest.json +21 -0
- package/CHANGELOG.md +1054 -0
- package/README.md +171 -16
- package/README.pt-BR.md +99 -13
- package/bin/pantheon-init.mjs +178 -21
- package/package.json +23 -15
- package/plugin.json +1 -1
- package/pyproject.toml +65 -0
- package/scripts/code_mode_server.py +431 -55
- package/scripts/cost.mjs +30 -14
- package/scripts/dev-tui.sh +48 -0
- package/scripts/doctor.mjs +207 -9
- package/scripts/install/cli-ui.mjs +17 -11
- package/scripts/install/config-migration.mjs +4 -6
- package/scripts/install/opencode.mjs +137 -35
- package/scripts/install/plugin.mjs +3 -33
- package/scripts/install/shared.mjs +43 -2
- package/scripts/install/strings.mjs +129 -0
- package/scripts/install-mcp.mjs +1 -0
- package/scripts/manifest-inventory.mjs +410 -0
- package/scripts/mcp_persistence_server.py +537 -128
- package/scripts/package-evidence.mjs +242 -0
- package/scripts/probe-context-rehydrate.mjs +240 -0
- package/scripts/probe-pantheon-cost.mjs +313 -0
- package/scripts/release-beta-version.mjs +56 -60
- package/scripts/sync-artifacts.mjs +169 -0
- package/scripts/sync-tui.mjs +121 -53
- package/scripts/test-opencode-v1-v2-sandbox.sh +367 -96
- package/scripts/validation-policy.mjs +7 -7
- package/scripts/version-check.mjs +113 -108
- package/scripts/versioning.mjs +230 -86
- package/src/agents/mnemosyne.md +1 -1
- package/src/agents/zeus.md +2 -2
- package/src/mcp/code_mode_server.py +431 -55
- package/src/mcp/mcp_persistence_server.py +537 -128
- package/src/pantheon/auto-wake.ts +1 -5
- package/src/pantheon/background-job-board.ts +43 -1
- package/src/pantheon/compaction-handoff.ts +304 -0
- package/src/pantheon/cost-command.ts +345 -62
- package/src/pantheon/delegate-manager.ts +390 -8
- package/src/pantheon/delegation-finalize.ts +32 -0
- package/src/pantheon/delegation.ts +235 -18
- package/src/pantheon/file-persistence-salvage.ts +64 -0
- package/src/pantheon/file-persistence.ts +194 -45
- package/src/pantheon/native-probe.ts +234 -0
- package/src/pantheon/native-task-status.ts +139 -0
- package/src/pantheon/provider-capabilities.ts +221 -0
- package/src/pantheon/provider-stream-tracker.ts +182 -0
- package/src/pantheon/shared-board.ts +37 -0
- package/src/pantheon/task-result-guard.ts +107 -0
- package/src/pantheon/token-opt.ts +146 -12
- package/src/pantheon/tool-ceiling.ts +159 -0
- package/src/pantheon/v2-events.ts +18 -1
- package/src/plugin-v2.ts +2 -14
- package/src/plugin.ts +28 -17
- package/src/plugins/pantheon-hooks.ts +51 -0
- package/src/plugins/tui/dist/server.d.ts +1 -1
- package/src/plugins/tui/dist/server.d.ts.map +1 -1
- package/src/plugins/tui/dist/server.js +1 -1
- package/src/plugins/tui/dist/server.js.map +1 -1
- package/src/plugins/tui/dist/tui.d.ts +137 -27
- package/src/plugins/tui/dist/tui.d.ts.map +1 -1
- package/src/plugins/tui/dist/tui.js +459 -163
- package/src/plugins/tui/dist/tui.js.map +1 -1
- package/src/plugins/tui/dist/tui.tsx +506 -103
- package/src/plugins/tui/package-lock.json +2 -2
- package/src/plugins/tui/package.json +1 -1
- package/src/plugins/tui/src/index.tsx +506 -103
- package/.pantheon/code-mode/.gitkeep +0 -0
- package/.pantheon/code-mode/.pantheon/deepwork/initial-token-40k/checkpoint-1.json +0 -8
- package/.pantheon/code-mode/.pantheon/deepwork/initial-token-40k/checkpoint-10.json +0 -8
- package/.pantheon/code-mode/.pantheon/deepwork/initial-token-40k/checkpoint-11.json +0 -8
- package/.pantheon/code-mode/.pantheon/deepwork/initial-token-40k/checkpoint-2.json +0 -8
- package/.pantheon/code-mode/.pantheon/deepwork/initial-token-40k/checkpoint-3.json +0 -8
- package/.pantheon/code-mode/.pantheon/deepwork/initial-token-40k/checkpoint-4.json +0 -8
- package/.pantheon/code-mode/.pantheon/deepwork/initial-token-40k/checkpoint-5.json +0 -8
- package/.pantheon/code-mode/.pantheon/deepwork/initial-token-40k/checkpoint-6.json +0 -8
- package/.pantheon/code-mode/.pantheon/deepwork/initial-token-40k/checkpoint-7.json +0 -8
- package/.pantheon/code-mode/.pantheon/deepwork/initial-token-40k/checkpoint-8.json +0 -8
- package/.pantheon/code-mode/.pantheon/deepwork/initial-token-40k/checkpoint-9.json +0 -8
- package/.pantheon/code-mode/.pantheon/deepwork/initial-token-40k/heartbeat.json +0 -8
- package/.pantheon/code-mode/.pantheon/deepwork/initial-token-40k/session.json +0 -11
- package/src/pantheon/delegate-task-adapter.ts +0 -444
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { createComponent, createElement, createTextNode, effect, insert, insertNode, memo, setProp } from "@opentui/solid";
|
|
2
2
|
import { Buffer } from "node:buffer";
|
|
3
|
-
import { mkdir, readFile, readdir, writeFile } from "node:fs/promises";
|
|
3
|
+
import { appendFile, mkdir, readFile, readdir, writeFile } from "node:fs/promises";
|
|
4
4
|
import { homedir } from "node:os";
|
|
5
5
|
import { dirname, join } from "node:path";
|
|
6
6
|
import { fileURLToPath } from "node:url";
|
|
@@ -164,7 +164,7 @@ async function detectVersion(api) {
|
|
|
164
164
|
if (ver) return ver;
|
|
165
165
|
}
|
|
166
166
|
} catch {}
|
|
167
|
-
return "1.5.0";
|
|
167
|
+
return "1.5.0-beta.11";
|
|
168
168
|
}
|
|
169
169
|
/**
|
|
170
170
|
* usage-bar — AI subscription usage gauge for the opencode TUI.
|
|
@@ -868,19 +868,32 @@ function tuiLogPath(projectRoot) {
|
|
|
868
868
|
* falling back to startedAt, descending). Shared by the md reader and
|
|
869
869
|
* mergeDelegationSources. */
|
|
870
870
|
function compareDelegationEntries(a, b) {
|
|
871
|
-
const
|
|
872
|
-
const
|
|
871
|
+
const isActive = (st) => st === "running" || st === "retry" || st === "stale-running" ? 1 : 0;
|
|
872
|
+
const aRun = isActive(a.state);
|
|
873
|
+
const bRun = isActive(b.state);
|
|
873
874
|
if (aRun !== bRun) return bRun - aRun;
|
|
874
875
|
return (b.updatedAt ?? b.startedAt) - (a.updatedAt ?? a.startedAt);
|
|
875
876
|
}
|
|
876
|
-
/**
|
|
877
|
-
* recent terminal reports
|
|
878
|
-
*
|
|
879
|
-
*
|
|
877
|
+
/** Split the panel list: active jobs (running/retry, stale-marked) first,
|
|
878
|
+
* then the most recent terminal reports, then the archived tail (paginated
|
|
879
|
+
* in the View). Pure — so the history-only panel (no sessionID) is testable
|
|
880
|
+
* without the TUI runtime. */
|
|
881
|
+
function splitDelegationList(all, maxRecent = 8, now = Date.now(), staleThresholdMs = 1800 * 1e3) {
|
|
882
|
+
const isActiveState = (st) => st === "running" || st === "retry" || st === "stale-running";
|
|
883
|
+
const active = all.filter((d) => isActiveState(d.state)).map((d) => markStaleIfRunning(d, now, staleThresholdMs));
|
|
884
|
+
const terminal = all.filter((d) => !isActiveState(d.state));
|
|
885
|
+
return {
|
|
886
|
+
active,
|
|
887
|
+
recent: terminal.slice(0, maxRecent),
|
|
888
|
+
archived: terminal.slice(maxRecent)
|
|
889
|
+
};
|
|
890
|
+
}
|
|
891
|
+
/** The list the panel actually renders (kept for the header count and
|
|
892
|
+
* existing tests): active jobs first, then the most recent terminal
|
|
893
|
+
* reports (capped) — the archived tail is rendered separately. Pure. */
|
|
880
894
|
function visibleDelegationList(all, maxTerminal = 8, now = Date.now(), staleThresholdMs = 1800 * 1e3) {
|
|
881
|
-
const
|
|
882
|
-
|
|
883
|
-
return [...running, ...terminal];
|
|
895
|
+
const { active, recent } = splitDelegationList(all, maxTerminal, now, staleThresholdMs);
|
|
896
|
+
return [...active, ...recent];
|
|
884
897
|
}
|
|
885
898
|
/** Default stale-running threshold: 30 minutes. */
|
|
886
899
|
const STALE_RUNNING_THRESHOLD_MS = 1800 * 1e3;
|
|
@@ -918,10 +931,11 @@ function fmtElapsed(ms) {
|
|
|
918
931
|
if (minutes > 0) return `${minutes}m ${seconds}s`;
|
|
919
932
|
return `${seconds}s`;
|
|
920
933
|
}
|
|
921
|
-
/** Elapsed label for one entry:
|
|
922
|
-
*
|
|
934
|
+
/** Elapsed label for one entry: an ACTIVE entry (running/retry/stale-running)
|
|
935
|
+
* ticks `now - startedAt`; a terminal one is fixed at
|
|
936
|
+
* `updatedAt - startedAt` (em dash when no finalized timestamp). */
|
|
923
937
|
function delegationElapsed(entry, now) {
|
|
924
|
-
if (entry.state === "running" || entry.state === "stale-running") return fmtElapsed(now - entry.startedAt);
|
|
938
|
+
if (entry.state === "running" || entry.state === "retry" || entry.state === "stale-running") return fmtElapsed(now - entry.startedAt);
|
|
925
939
|
return entry.updatedAt !== null ? fmtElapsed(entry.updatedAt - entry.startedAt) : "—";
|
|
926
940
|
}
|
|
927
941
|
/** The activity labels shown by the animated row. Keeping this pure makes the
|
|
@@ -935,6 +949,7 @@ function delegationActivity(entry) {
|
|
|
935
949
|
return "working";
|
|
936
950
|
}
|
|
937
951
|
function delegationActivityLabel(entry) {
|
|
952
|
+
if (entry.state === "retry") return "RETRYING";
|
|
938
953
|
switch (delegationActivity(entry)) {
|
|
939
954
|
case "delegating": return "DELEGATING";
|
|
940
955
|
case "working": return "WORKING";
|
|
@@ -956,11 +971,114 @@ const DELEGATION_SPINNER_FRAMES = [
|
|
|
956
971
|
"⠇",
|
|
957
972
|
"⠏"
|
|
958
973
|
];
|
|
959
|
-
/** Return a deterministic spinner frame. The View ticks this every
|
|
974
|
+
/** Return a deterministic spinner frame. The View ticks this every 1000ms
|
|
975
|
+
* (not 140ms — the fast tick flickered without adding information). */
|
|
960
976
|
function delegationSpinnerFrame(now) {
|
|
961
|
-
const index = Math.floor(Math.max(0, now) /
|
|
977
|
+
const index = Math.floor(Math.max(0, now) / 1e3) % DELEGATION_SPINNER_FRAMES.length;
|
|
962
978
|
return DELEGATION_SPINNER_FRAMES[index] ?? DELEGATION_SPINNER_FRAMES[0];
|
|
963
979
|
}
|
|
980
|
+
/** Every state the row knows how to draw: the real BackgroundJobBoard FSM
|
|
981
|
+
* (src/pantheon/background-job-board.ts) plus the TUI display-only states
|
|
982
|
+
* (`retry`, `stale-running`). Fase 1 deliberately omits speculative
|
|
983
|
+
* blocked/paused/scheduled/skipped. There is no `pending` display state: a
|
|
984
|
+
* pre-dispatch tool part maps to `running` in {@link reduceDelegationToolPart}. */
|
|
985
|
+
/** Static glyph per display state. `running` shows its base spinner frame;
|
|
986
|
+
* callers that animate must prefer {@link delegationStateMarker}. Unicode
|
|
987
|
+
* geometric shapes only (no Nerd Font) — shape is an independent channel
|
|
988
|
+
* from color, so rows stay legible without color. */
|
|
989
|
+
const DELEGATION_STATE_GLYPHS = {
|
|
990
|
+
running: "⠋",
|
|
991
|
+
retry: "⟳",
|
|
992
|
+
"stale-running": "⚠",
|
|
993
|
+
completed: "✓",
|
|
994
|
+
error: "✕",
|
|
995
|
+
cancelled: "−",
|
|
996
|
+
startup_failed: "⚠",
|
|
997
|
+
startup_unknown: "⚠"
|
|
998
|
+
};
|
|
999
|
+
function delegationStateGlyph(state) {
|
|
1000
|
+
return DELEGATION_STATE_GLYPHS[state];
|
|
1001
|
+
}
|
|
1002
|
+
/** Row marker (`<glyph> `) — the state channel. `running` animates through
|
|
1003
|
+
* {@link delegationSpinnerFrame} for the given tick; every other state is
|
|
1004
|
+
* static. Pure. */
|
|
1005
|
+
function delegationStateMarker(state, now = Date.now()) {
|
|
1006
|
+
return `${state === "running" ? delegationSpinnerFrame(now) : delegationStateGlyph(state)} `;
|
|
1007
|
+
}
|
|
1008
|
+
/** Semantic tone mapped to the TUI theme at the row ({@link DelegationRow}).
|
|
1009
|
+
* Kept separate + pure so the color channel is testable without booting the
|
|
1010
|
+
* renderer. */
|
|
1011
|
+
function delegationStateTone(state) {
|
|
1012
|
+
switch (state) {
|
|
1013
|
+
case "running":
|
|
1014
|
+
case "retry":
|
|
1015
|
+
case "startup_unknown": return "warning";
|
|
1016
|
+
case "stale-running":
|
|
1017
|
+
case "error":
|
|
1018
|
+
case "startup_failed": return "error";
|
|
1019
|
+
case "completed": return "success";
|
|
1020
|
+
case "cancelled": return "muted";
|
|
1021
|
+
}
|
|
1022
|
+
}
|
|
1023
|
+
/** Bounded tracker: child session id → latest running tool call. */
|
|
1024
|
+
const latestToolActivity = /* @__PURE__ */ new Map();
|
|
1025
|
+
const MAX_TOOL_ACTIVITY_ENTRIES = 200;
|
|
1026
|
+
const TOOL_ACTIVITY_TTL_MS = 300 * 1e3;
|
|
1027
|
+
/** Archived-section pagination state — module-level so it survives sidebar
|
|
1028
|
+
* remounts (route changes) without leaking into the component tree. */
|
|
1029
|
+
const archivedUiState = { page: 0 };
|
|
1030
|
+
/** First usable summary string from common tool input fields. */
|
|
1031
|
+
function summarizeToolInput(input) {
|
|
1032
|
+
if (!input) return "";
|
|
1033
|
+
for (const key of [
|
|
1034
|
+
"command",
|
|
1035
|
+
"description",
|
|
1036
|
+
"prompt",
|
|
1037
|
+
"filePath",
|
|
1038
|
+
"pattern",
|
|
1039
|
+
"url",
|
|
1040
|
+
"query"
|
|
1041
|
+
]) {
|
|
1042
|
+
const value = input[key];
|
|
1043
|
+
if (typeof value === "string" && value.trim() !== "") return value;
|
|
1044
|
+
}
|
|
1045
|
+
return "";
|
|
1046
|
+
}
|
|
1047
|
+
/** Reduce one message.part.updated tool part to displayable activity.
|
|
1048
|
+
* Returns null for non-tool parts, completed/error parts (no live activity)
|
|
1049
|
+
* or parts without a session id. Pure. */
|
|
1050
|
+
function extractToolActivity(part, now = Date.now()) {
|
|
1051
|
+
if (part?.type !== "tool") return null;
|
|
1052
|
+
const status = part.state?.status;
|
|
1053
|
+
if (status !== "pending" && status !== "running") return null;
|
|
1054
|
+
const sessionID = typeof part.sessionID === "string" ? part.sessionID : "";
|
|
1055
|
+
if (sessionID === "") return null;
|
|
1056
|
+
return {
|
|
1057
|
+
sessionID,
|
|
1058
|
+
activity: {
|
|
1059
|
+
tool: typeof part.tool === "string" && part.tool !== "" ? part.tool : "tool",
|
|
1060
|
+
summary: summarizeToolInput(part.state?.input).replace(/\s+/g, " ").trim().slice(0, 48),
|
|
1061
|
+
at: now
|
|
1062
|
+
}
|
|
1063
|
+
};
|
|
1064
|
+
}
|
|
1065
|
+
/** Record an activity sample (bounded map, oldest dropped). */
|
|
1066
|
+
function trackToolActivity(map, sessionID, activity) {
|
|
1067
|
+
if (sessionID === "") return;
|
|
1068
|
+
if (map.size >= MAX_TOOL_ACTIVITY_ENTRIES) {
|
|
1069
|
+
const oldest = map.keys().next().value;
|
|
1070
|
+
if (oldest !== void 0) map.delete(oldest);
|
|
1071
|
+
}
|
|
1072
|
+
map.set(sessionID, activity);
|
|
1073
|
+
}
|
|
1074
|
+
/** Latest live activity for a child session, or null when absent/stale. */
|
|
1075
|
+
function latestToolActivityFor(map, sessionID, now = Date.now(), ttlMs = TOOL_ACTIVITY_TTL_MS) {
|
|
1076
|
+
if (!sessionID) return null;
|
|
1077
|
+
const hit = map.get(sessionID);
|
|
1078
|
+
if (hit === void 0) return null;
|
|
1079
|
+
if (now - hit.at > ttlMs) return null;
|
|
1080
|
+
return hit;
|
|
1081
|
+
}
|
|
964
1082
|
/** Merge the immediate tool-event channel into the child-session channel.
|
|
965
1083
|
*
|
|
966
1084
|
* Children remain the durable source, while live entries make a delegation
|
|
@@ -1023,10 +1141,12 @@ const DELEGATE_TASKID_PATTERN = /\(task\s+([a-z0-9_]+)\)/i;
|
|
|
1023
1141
|
const READ_ALIAS_PATTERN = /^[a-z]{2,8}-\d+$/i;
|
|
1024
1142
|
/** Extract the tool name + args from a `message.part.updated` part and
|
|
1025
1143
|
* reduce it to what the panel needs. Returns null for anything that is
|
|
1026
|
-
* not a pantheon delegation tool part
|
|
1144
|
+
* not a pantheon delegation tool part, the native `task` subagent tool
|
|
1145
|
+
* (same parentID === caller mechanism — its children render `nat:`),
|
|
1146
|
+
* or is missing its callID. */
|
|
1027
1147
|
function parseDelegationToolPart(part, now = Date.now()) {
|
|
1028
1148
|
if (part.type !== "tool") return null;
|
|
1029
|
-
if (part.tool !== "pantheon_delegate" && part.tool !== "pantheon_delegation_read") return null;
|
|
1149
|
+
if (part.tool !== "pantheon_delegate" && part.tool !== "pantheon_delegation_read" && part.tool !== "task") return null;
|
|
1030
1150
|
const callID = part.callID;
|
|
1031
1151
|
if (callID === void 0 || callID === "") return null;
|
|
1032
1152
|
const sessionID = part.sessionID ?? "";
|
|
@@ -1058,8 +1178,8 @@ function parseDelegationToolPart(part, now = Date.now()) {
|
|
|
1058
1178
|
endAt
|
|
1059
1179
|
};
|
|
1060
1180
|
}
|
|
1061
|
-
const agent = typeof input.agent === "string" ? input.agent : "agent";
|
|
1062
|
-
const description = typeof input.description === "string" ? input.description : "";
|
|
1181
|
+
const agent = typeof input.agent === "string" ? input.agent : typeof input.subagent_type === "string" ? input.subagent_type : "agent";
|
|
1182
|
+
const description = typeof input.description === "string" ? input.description : typeof input.prompt === "string" ? input.prompt.slice(0, 120) : "";
|
|
1063
1183
|
let alias = null;
|
|
1064
1184
|
let taskID = null;
|
|
1065
1185
|
if (status === "completed") {
|
|
@@ -1071,7 +1191,7 @@ function parseDelegationToolPart(part, now = Date.now()) {
|
|
|
1071
1191
|
callID,
|
|
1072
1192
|
partID: part.id ?? "",
|
|
1073
1193
|
sessionID,
|
|
1074
|
-
tool: "pantheon_delegate",
|
|
1194
|
+
tool: part.tool === "task" ? "task" : "pantheon_delegate",
|
|
1075
1195
|
agent,
|
|
1076
1196
|
description,
|
|
1077
1197
|
status,
|
|
@@ -1120,7 +1240,7 @@ function reduceDelegationToolPart(map, part, now = Date.now()) {
|
|
|
1120
1240
|
callID: parsed.callID,
|
|
1121
1241
|
partID: parsed.partID,
|
|
1122
1242
|
sessionID: parsed.sessionID,
|
|
1123
|
-
tool:
|
|
1243
|
+
tool: parsed.tool,
|
|
1124
1244
|
agent: parsed.agent ?? "agent",
|
|
1125
1245
|
description: parsed.description,
|
|
1126
1246
|
alias: existing?.alias ?? null,
|
|
@@ -1137,7 +1257,7 @@ function reduceDelegationToolPart(map, part, now = Date.now()) {
|
|
|
1137
1257
|
callID: parsed.callID,
|
|
1138
1258
|
partID: parsed.partID,
|
|
1139
1259
|
sessionID: parsed.sessionID,
|
|
1140
|
-
tool:
|
|
1260
|
+
tool: parsed.tool,
|
|
1141
1261
|
agent: parsed.agent ?? "agent",
|
|
1142
1262
|
description: parsed.description,
|
|
1143
1263
|
alias: parsed.alias,
|
|
@@ -1182,11 +1302,14 @@ function removeDelegationEntry(map, partIDOrCallID) {
|
|
|
1182
1302
|
}
|
|
1183
1303
|
return false;
|
|
1184
1304
|
}
|
|
1185
|
-
/** Collect pantheon delegation tool parts from a session's messages.
|
|
1305
|
+
/** Collect pantheon delegation + native task tool parts from a session's messages.
|
|
1186
1306
|
* Messages may carry their parts inline (duck-typed `msg.parts`); when
|
|
1187
1307
|
* they don't, the optional `getParts(messageID)` callback is used (the TUI
|
|
1188
|
-
* SDK exposes `api.state.part(messageID)`).
|
|
1189
|
-
*
|
|
1308
|
+
* SDK exposes `api.state.part(messageID)`). The native `task` tool spawns a
|
|
1309
|
+
* child session with parentID = caller — the same mechanism as
|
|
1310
|
+
* pantheon_delegate — so its parts feed the live-map as the native signal
|
|
1311
|
+
* (rows render `nat:` via the children channel). Pure w.r.t. I/O — used
|
|
1312
|
+
* by the mount re-scan to re-seed the live map after compaction/attach. */
|
|
1190
1313
|
function collectDelegationToolParts(messages, getParts) {
|
|
1191
1314
|
const out = [];
|
|
1192
1315
|
for (const msg of messages ?? []) {
|
|
@@ -1196,7 +1319,7 @@ function collectDelegationToolParts(messages, getParts) {
|
|
|
1196
1319
|
if (!parts) continue;
|
|
1197
1320
|
for (const raw of parts) {
|
|
1198
1321
|
const part = raw;
|
|
1199
|
-
if (part?.type === "tool" && (part.tool === "pantheon_delegate" || part.tool === "pantheon_delegation_read")) out.push(part);
|
|
1322
|
+
if (part?.type === "tool" && (part.tool === "pantheon_delegate" || part.tool === "pantheon_delegation_read" || part.tool === "task")) out.push(part);
|
|
1200
1323
|
}
|
|
1201
1324
|
}
|
|
1202
1325
|
return out;
|
|
@@ -1309,16 +1432,102 @@ function buildChildrenPath(id) {
|
|
|
1309
1432
|
* correct it as soon as terminal data exists). */
|
|
1310
1433
|
function childStatusToState(status) {
|
|
1311
1434
|
if (status === "idle") return "completed";
|
|
1435
|
+
if (status === "retry") return "retry";
|
|
1312
1436
|
return "running";
|
|
1313
1437
|
}
|
|
1314
|
-
/**
|
|
1315
|
-
* (
|
|
1316
|
-
*
|
|
1317
|
-
*
|
|
1318
|
-
*
|
|
1319
|
-
*
|
|
1438
|
+
/** Short row prefix for a delegation entry (one of the two visual channels
|
|
1439
|
+
* that split native task() work from pantheon_delegate jobs — the other is
|
|
1440
|
+
* {@link delegationIcon}):
|
|
1441
|
+
*
|
|
1442
|
+
* - `nat:<agent>` — a native task() child (source 'children-only', no board
|
|
1443
|
+
* report). The child session carries no board alias, so the agent IS the
|
|
1444
|
+
* identity.
|
|
1445
|
+
* - `pan:<alias>` — a pantheon_delegate board row (`pan:apo-1`), the same
|
|
1446
|
+
* alias the manager prints in pantheon_delegation_list.
|
|
1447
|
+
*
|
|
1448
|
+
* Short prefixes keep the narrow sidebar readable (the old
|
|
1449
|
+
* `pan:apo-1`/`nat:` tags ate the row width). */
|
|
1320
1450
|
function delegationTag(entry) {
|
|
1321
|
-
return entry.source === "children-only" ?
|
|
1451
|
+
return entry.source === "children-only" ? `nat:${entry.agent}` : `pan:${entry.alias}`;
|
|
1452
|
+
}
|
|
1453
|
+
/** Row glyph: hollow diamond `◇` for native task() children (info color,
|
|
1454
|
+
* outline) vs filled diamond `◆` for pantheon_delegate rows (state color).
|
|
1455
|
+
* Shape + color are independent channels, so the split stays legible even
|
|
1456
|
+
* without color. */
|
|
1457
|
+
function delegationIcon(entry) {
|
|
1458
|
+
return entry.source === "children-only" ? "◇" : "◆";
|
|
1459
|
+
}
|
|
1460
|
+
/** Row identity after the status marker + glyph. Pantheon rows append the
|
|
1461
|
+
* agent (`pan:apo-1 apollo`); native rows already carry it inside the tag
|
|
1462
|
+
* (`nat:apollo`) and must not duplicate it. */
|
|
1463
|
+
function formatDelegationIdentity(entry) {
|
|
1464
|
+
return entry.source === "children-only" ? delegationTag(entry) : `${delegationTag(entry)} ${entry.agent}`;
|
|
1465
|
+
}
|
|
1466
|
+
/** Max description width on the row detail line — the old 180-char slice
|
|
1467
|
+
* wrapped the sidebar; 44 keeps one readable line. */
|
|
1468
|
+
const DELEGATION_DESCRIPTION_MAX = 44;
|
|
1469
|
+
/** Lazily-built grapheme segmenter. `Intl.Segmenter` keeps ZWJ emoji families
|
|
1470
|
+
* (and skin-tone/variation sequences) intact; `Array.from` (code points) is
|
|
1471
|
+
* the fallback for runtimes without it. */
|
|
1472
|
+
let graphemeSegmenter;
|
|
1473
|
+
/** Split `text` into display graphemes so truncation never cuts a multi-unit
|
|
1474
|
+
* emoji in half (surrogate pair → mojibake). */
|
|
1475
|
+
function splitGraphemes(text) {
|
|
1476
|
+
if (typeof Intl !== "undefined" && typeof Intl.Segmenter === "function") {
|
|
1477
|
+
graphemeSegmenter ??= new Intl.Segmenter("pt", { granularity: "grapheme" });
|
|
1478
|
+
return Array.from(graphemeSegmenter.segment(text), (s) => s.segment);
|
|
1479
|
+
}
|
|
1480
|
+
return Array.from(text);
|
|
1481
|
+
}
|
|
1482
|
+
/** Truncate a description to `max` graphemes appending `…` when cut. Exact
|
|
1483
|
+
* `max`-length text is left untouched. Grapheme-granular, so an emoji made of
|
|
1484
|
+
* several code points is never split into mojibake at the boundary. Pure. */
|
|
1485
|
+
function truncateDelegationDescription(text, max = 44) {
|
|
1486
|
+
const graphemes = splitGraphemes(text);
|
|
1487
|
+
if (graphemes.length <= max) return text;
|
|
1488
|
+
return `${graphemes.slice(0, Math.max(0, max - 1)).join("")}\u2026`;
|
|
1489
|
+
}
|
|
1490
|
+
/** Fixed elapsed-time box: right-aligned to `width` (default 8) so elapsed
|
|
1491
|
+
* values line up across rows, e.g. ` 12s`. A label that already fills
|
|
1492
|
+
* the box is returned untouched. Pure. */
|
|
1493
|
+
const DELEGATION_ELAPSED_WIDTH = 8;
|
|
1494
|
+
function formatDelegationElapsed(entry, now, width = 8) {
|
|
1495
|
+
const label = delegationElapsed(entry, now);
|
|
1496
|
+
if (label.length >= width) return label;
|
|
1497
|
+
return `${" ".repeat(width - label.length)}${label}`;
|
|
1498
|
+
}
|
|
1499
|
+
/** First row line: `<marker><glyph> <identity>`. The marker already carries
|
|
1500
|
+
* its trailing space. Pure — the row renders the returned string verbatim. */
|
|
1501
|
+
function formatDelegationRow(entry, marker) {
|
|
1502
|
+
return `${marker}${delegationIcon(entry)} ${formatDelegationIdentity(entry)}`;
|
|
1503
|
+
}
|
|
1504
|
+
/** Header summary: `(N active · M done · nat:K pan:M)`. Active counts
|
|
1505
|
+
* running/retry AND display-only stale-running (a stale row is still a live
|
|
1506
|
+
* job — it must never read as done). Pure. */
|
|
1507
|
+
function formatDelegationHeader(entries) {
|
|
1508
|
+
let active = 0;
|
|
1509
|
+
for (const e of entries) if (e.state === "running" || e.state === "retry" || e.state === "stale-running") active++;
|
|
1510
|
+
const done = entries.length - active;
|
|
1511
|
+
const counts = countDelegationSources(entries);
|
|
1512
|
+
return `(${active} active \u00b7 ${done} done \u00b7 nat:${counts.native} pan:${counts.pantheon})`;
|
|
1513
|
+
}
|
|
1514
|
+
/** Split a display list into native task() rows vs pantheon_delegate rows.
|
|
1515
|
+
* Native = source 'children-only' (no board report); everything else counts
|
|
1516
|
+
* as pantheon. Pure — powers the header breakdown + the hooks.log line. */
|
|
1517
|
+
function countDelegationSources(entries) {
|
|
1518
|
+
let native = 0;
|
|
1519
|
+
for (const e of entries) if (e.source === "children-only") native++;
|
|
1520
|
+
return {
|
|
1521
|
+
native,
|
|
1522
|
+
pantheon: entries.length - native,
|
|
1523
|
+
total: entries.length
|
|
1524
|
+
};
|
|
1525
|
+
}
|
|
1526
|
+
/** Diagnostic hooks.log line for a panel re-fetch, with the children
|
|
1527
|
+
* breakdown (pantheon = children WITH a board report, native = children
|
|
1528
|
+
* WITHOUT one). Pure — the View logs the returned string verbatim. */
|
|
1529
|
+
function formatPanelLogLine(children, pantheon, native, md, events) {
|
|
1530
|
+
return `panel: children=${children}(pantheon=${pantheon} native=${native}) md=${md} events=${events}`;
|
|
1322
1531
|
}
|
|
1323
1532
|
/** Turn child sessions (PRIMARY) enriched with md reports into the display
|
|
1324
1533
|
* list. One entry per child id (duplicates across re-fetches collapse).
|
|
@@ -1328,10 +1537,14 @@ function delegationTag(entry) {
|
|
|
1328
1537
|
* itself (fallback 'agent'), state derived from its status, startedAt from
|
|
1329
1538
|
* time.created. A report-less child is a NATIVE task() child (every
|
|
1330
1539
|
* child of the current session — pantheon_delegate OR the native `task()`
|
|
1331
|
-
* tool — carries parentID = caller), so it gets source 'children-only'
|
|
1332
|
-
* and the `
|
|
1540
|
+
* tool — carries parentID = caller), so it gets source 'children-only',
|
|
1541
|
+
* the internal alias 'native-task' and the `nat:` tag instead of a
|
|
1542
|
+
* board alias. The 'task nativa' description fallback keeps the row
|
|
1543
|
+
* non-empty when the child carries no title.
|
|
1333
1544
|
* Terminal md state wins over the derived state; a running md defers to
|
|
1334
|
-
* the child's live status.
|
|
1545
|
+
* the child's live status. A running child is NEVER archived — it always
|
|
1546
|
+
* lands in the active split (splitDelegationList active = running/retry).
|
|
1547
|
+
* Sorted running-first (compareDelegationEntries).
|
|
1335
1548
|
* Pure — no I/O. */
|
|
1336
1549
|
function childrenToDelegationEntries(children, md, now = Date.now()) {
|
|
1337
1550
|
const byTaskID = /* @__PURE__ */ new Map();
|
|
@@ -1344,7 +1557,7 @@ function childrenToDelegationEntries(children, md, now = Date.now()) {
|
|
|
1344
1557
|
const mdEntry = byTaskID.get(child.id);
|
|
1345
1558
|
const state = mdEntry !== void 0 && mdEntry.state !== "running" ? mdEntry.state : childStatusToState(child.status);
|
|
1346
1559
|
out.push({
|
|
1347
|
-
alias: mdEntry?.alias ?? "task",
|
|
1560
|
+
alias: mdEntry?.alias ?? "native-task",
|
|
1348
1561
|
sessionID: mdEntry?.sessionID ?? "",
|
|
1349
1562
|
taskID: child.id,
|
|
1350
1563
|
agent: mdEntry?.agent ?? child.agent ?? "agent",
|
|
@@ -1352,7 +1565,7 @@ function childrenToDelegationEntries(children, md, now = Date.now()) {
|
|
|
1352
1565
|
startedAt: mdEntry?.startedAt ?? child.time?.created ?? now,
|
|
1353
1566
|
updatedAt: mdEntry?.updatedAt ?? (state === "running" || state === "stale-running" ? null : child.time?.updated ?? null),
|
|
1354
1567
|
timedOut: mdEntry?.timedOut ?? false,
|
|
1355
|
-
description: mdEntry !== void 0 && mdEntry.description !== "" ? mdEntry.description : child.title
|
|
1568
|
+
description: mdEntry !== void 0 && mdEntry.description !== "" ? mdEntry.description : child.title !== void 0 && child.title !== "" ? child.title : "task nativa",
|
|
1356
1569
|
source: mdEntry !== void 0 ? "md" : "children-only"
|
|
1357
1570
|
});
|
|
1358
1571
|
}
|
|
@@ -1395,7 +1608,11 @@ function createTuiLogger(projectRoot, module = "pantheon-tui") {
|
|
|
1395
1608
|
await mkdir(dirname(logPath), { recursive: true });
|
|
1396
1609
|
const stamp = (/* @__PURE__ */ new Date()).toISOString();
|
|
1397
1610
|
await appendFile(logPath, `${lines.map((l) => `[${stamp}] [${module}] ${l}`).join("\n")}\n`, "utf8");
|
|
1398
|
-
} catch {
|
|
1611
|
+
} catch (err) {
|
|
1612
|
+
if (echo) try {
|
|
1613
|
+
process.stderr.write(`[${module}] file-log failed: ${formatArg(err)}\n`);
|
|
1614
|
+
} catch {}
|
|
1615
|
+
}
|
|
1399
1616
|
})();
|
|
1400
1617
|
if (echo) for (const line of lines) console.log(`[${module}] ${line}`);
|
|
1401
1618
|
};
|
|
@@ -1429,56 +1646,64 @@ function DelegationRow(props) {
|
|
|
1429
1646
|
const theme = () => props.api.theme.current;
|
|
1430
1647
|
const color = createMemo(() => {
|
|
1431
1648
|
const t = theme();
|
|
1432
|
-
switch (props.job.state) {
|
|
1433
|
-
case "
|
|
1434
|
-
case "stale-running": return t.error;
|
|
1435
|
-
case "completed": return t.success;
|
|
1649
|
+
switch (delegationStateTone(props.job.state)) {
|
|
1650
|
+
case "warning": return t.warning;
|
|
1436
1651
|
case "error": return t.error;
|
|
1652
|
+
case "success": return t.success;
|
|
1437
1653
|
default: return t.textMuted;
|
|
1438
1654
|
}
|
|
1439
1655
|
});
|
|
1440
|
-
const marker = createMemo(() =>
|
|
1441
|
-
if (props.job.state === "running") return `${delegationSpinnerFrame(props.animationNow)} `;
|
|
1442
|
-
if (props.job.state === "stale-running") return "⚠ ";
|
|
1443
|
-
switch (props.job.state) {
|
|
1444
|
-
case "completed": return "✓ ";
|
|
1445
|
-
case "error": return "✕ ";
|
|
1446
|
-
default: return "○ ";
|
|
1447
|
-
}
|
|
1448
|
-
});
|
|
1656
|
+
const marker = createMemo(() => delegationStateMarker(props.job.state, props.animationNow));
|
|
1449
1657
|
const tagColor = createMemo(() => props.job.source === "children-only" ? theme().info : color());
|
|
1450
|
-
const
|
|
1451
|
-
|
|
1452
|
-
|
|
1453
|
-
});
|
|
1658
|
+
const description = createMemo(() => truncateDelegationDescription(props.job.description));
|
|
1659
|
+
const elapsed = createMemo(() => formatDelegationElapsed(props.job, props.now));
|
|
1660
|
+
const activity = createMemo(() => latestToolActivityFor(latestToolActivity, props.job.taskID, props.now));
|
|
1454
1661
|
const open = () => {
|
|
1455
1662
|
navigateToDelegationSession(props.api.route, props.job.taskID);
|
|
1456
1663
|
};
|
|
1457
1664
|
return (() => {
|
|
1458
|
-
var _el$13 = createElement("box"), _el$14 = createElement("box"), _el$15 = createElement("text"), _el$16 = createElement("
|
|
1665
|
+
var _el$13 = createElement("box"), _el$14 = createElement("box"), _el$15 = createElement("text"), _el$16 = createElement("box"), _el$18 = createElement("text");
|
|
1459
1666
|
insertNode(_el$13, _el$14);
|
|
1460
|
-
insertNode(_el$13, _el$
|
|
1667
|
+
insertNode(_el$13, _el$16);
|
|
1461
1668
|
setProp(_el$13, "onMouseDown", open);
|
|
1462
1669
|
insertNode(_el$14, _el$15);
|
|
1463
|
-
insertNode(_el$14, _el$16);
|
|
1464
|
-
insertNode(_el$14, _el$17);
|
|
1465
1670
|
setProp(_el$14, "flexDirection", "row");
|
|
1466
|
-
insert(_el$15, marker);
|
|
1467
|
-
|
|
1468
|
-
|
|
1469
|
-
insert(_el$
|
|
1671
|
+
insert(_el$15, () => formatDelegationRow(props.job, marker()));
|
|
1672
|
+
insertNode(_el$16, _el$18);
|
|
1673
|
+
setProp(_el$16, "flexDirection", "row");
|
|
1674
|
+
insert(_el$16, createComponent(Show, {
|
|
1675
|
+
get when() {
|
|
1676
|
+
return description() !== "";
|
|
1677
|
+
},
|
|
1678
|
+
get children() {
|
|
1679
|
+
var _el$17 = createElement("text");
|
|
1680
|
+
insert(_el$17, description);
|
|
1681
|
+
effect((_$p) => setProp(_el$17, "fg", theme().textMuted, _$p));
|
|
1682
|
+
return _el$17;
|
|
1683
|
+
}
|
|
1684
|
+
}), _el$18);
|
|
1685
|
+
insert(_el$18, elapsed);
|
|
1686
|
+
insert(_el$13, createComponent(Show, {
|
|
1687
|
+
get when() {
|
|
1688
|
+
return activity();
|
|
1689
|
+
},
|
|
1690
|
+
children: (a) => (() => {
|
|
1691
|
+
var _el$19 = createElement("text");
|
|
1692
|
+
insert(_el$19, () => ` \u21b3 ${truncateDelegationDescription(`${a().tool}${a().summary !== "" ? ` ${a().summary}` : ""}`)}`);
|
|
1693
|
+
effect((_$p) => setProp(_el$19, "fg", theme().textMuted, _$p));
|
|
1694
|
+
return _el$19;
|
|
1695
|
+
})()
|
|
1696
|
+
}), null);
|
|
1470
1697
|
effect((_p$) => {
|
|
1471
|
-
var _v$5 =
|
|
1698
|
+
var _v$5 = tagColor(), _v$6 = description() !== "" ? "space-between" : "flex-end", _v$7 = theme().textMuted;
|
|
1472
1699
|
_v$5 !== _p$.e && (_p$.e = setProp(_el$15, "fg", _v$5, _p$.e));
|
|
1473
|
-
_v$6 !== _p$.t && (_p$.t = setProp(_el$16, "
|
|
1474
|
-
_v$7 !== _p$.a && (_p$.a = setProp(_el$
|
|
1475
|
-
_v$8 !== _p$.o && (_p$.o = setProp(_el$18, "fg", _v$8, _p$.o));
|
|
1700
|
+
_v$6 !== _p$.t && (_p$.t = setProp(_el$16, "justifyContent", _v$6, _p$.t));
|
|
1701
|
+
_v$7 !== _p$.a && (_p$.a = setProp(_el$18, "fg", _v$7, _p$.a));
|
|
1476
1702
|
return _p$;
|
|
1477
1703
|
}, {
|
|
1478
1704
|
e: void 0,
|
|
1479
1705
|
t: void 0,
|
|
1480
|
-
a: void 0
|
|
1481
|
-
o: void 0
|
|
1706
|
+
a: void 0
|
|
1482
1707
|
});
|
|
1483
1708
|
return _el$13;
|
|
1484
1709
|
})();
|
|
@@ -1560,7 +1785,7 @@ function View(props) {
|
|
|
1560
1785
|
});
|
|
1561
1786
|
if (sessionID === null) {
|
|
1562
1787
|
setChildDelegations(md);
|
|
1563
|
-
panelLog.info(
|
|
1788
|
+
panelLog.info(`${formatPanelLogLine(0, 0, 0, md.length, eventRefreshCount)} (no sessionID — history shown)`);
|
|
1564
1789
|
return;
|
|
1565
1790
|
}
|
|
1566
1791
|
let children = [];
|
|
@@ -1587,14 +1812,23 @@ function View(props) {
|
|
|
1587
1812
|
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);
|
|
1588
1813
|
const liveEntries = [...props.liveStore.map.values()].filter((entry) => entry.sessionID === sessionID);
|
|
1589
1814
|
setChildDelegations(mergeChildDelegationSources(childEntries, liveEntries));
|
|
1590
|
-
|
|
1815
|
+
const counts = countDelegationSources(childEntries);
|
|
1816
|
+
panelLog.info(formatPanelLogLine(children.length, counts.pantheon, counts.native, md.length, eventRefreshCount));
|
|
1591
1817
|
} finally {
|
|
1592
1818
|
delegationsInflight = null;
|
|
1593
1819
|
}
|
|
1594
1820
|
})();
|
|
1595
1821
|
return delegationsInflight;
|
|
1596
1822
|
};
|
|
1597
|
-
const
|
|
1823
|
+
const delegationSplit = createMemo(() => splitDelegationList(childDelegations()));
|
|
1824
|
+
const visibleDelegations = createMemo(() => [...delegationSplit().active, ...delegationSplit().recent]);
|
|
1825
|
+
const delegationHeader = createMemo(() => formatDelegationHeader(childDelegations()));
|
|
1826
|
+
const [archivedPage, setArchivedPage] = createSignal(archivedUiState.page);
|
|
1827
|
+
const clampArchivedPage = (page, pages) => {
|
|
1828
|
+
const clamped = Math.max(0, Math.min(page, Math.max(0, pages - 1)));
|
|
1829
|
+
archivedUiState.page = clamped;
|
|
1830
|
+
setArchivedPage(clamped);
|
|
1831
|
+
};
|
|
1598
1832
|
onMount(() => {
|
|
1599
1833
|
const cleanup = [];
|
|
1600
1834
|
try {
|
|
@@ -1623,7 +1857,7 @@ function View(props) {
|
|
|
1623
1857
|
refreshDelegations();
|
|
1624
1858
|
}, 1e3);
|
|
1625
1859
|
cleanup.push(() => clearInterval(poll));
|
|
1626
|
-
const animation = setInterval(() => setAnimationNow(Date.now()),
|
|
1860
|
+
const animation = setInterval(() => setAnimationNow(Date.now()), 1e3);
|
|
1627
1861
|
cleanup.push(() => clearInterval(animation));
|
|
1628
1862
|
try {
|
|
1629
1863
|
const sdk = props.api.state?.session;
|
|
@@ -1643,78 +1877,78 @@ function View(props) {
|
|
|
1643
1877
|
}));
|
|
1644
1878
|
});
|
|
1645
1879
|
const HR = () => (() => {
|
|
1646
|
-
var _el$
|
|
1647
|
-
insertNode(_el$
|
|
1648
|
-
effect((_$p) => setProp(_el$
|
|
1649
|
-
return _el$
|
|
1880
|
+
var _el$20 = createElement("text");
|
|
1881
|
+
insertNode(_el$20, createTextNode(`────────────────────────────`));
|
|
1882
|
+
effect((_$p) => setProp(_el$20, "fg", theme().textMuted, _$p));
|
|
1883
|
+
return _el$20;
|
|
1650
1884
|
})();
|
|
1651
1885
|
return (() => {
|
|
1652
|
-
var _el$
|
|
1653
|
-
insertNode(_el$
|
|
1654
|
-
insertNode(_el$
|
|
1655
|
-
insertNode(_el$
|
|
1656
|
-
setProp(_el$
|
|
1657
|
-
setProp(_el$
|
|
1658
|
-
setProp(_el$
|
|
1659
|
-
insert(_el$
|
|
1660
|
-
insert(_el$
|
|
1886
|
+
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");
|
|
1887
|
+
insertNode(_el$22, _el$23);
|
|
1888
|
+
insertNode(_el$22, _el$24);
|
|
1889
|
+
insertNode(_el$22, _el$28);
|
|
1890
|
+
setProp(_el$22, "flexDirection", "column");
|
|
1891
|
+
setProp(_el$22, "width", "100%");
|
|
1892
|
+
setProp(_el$23, "attributes", 1);
|
|
1893
|
+
insert(_el$23, () => `Pantheon${props.version ? ` v${props.version}` : ""}`);
|
|
1894
|
+
insert(_el$22, createComponent(Show, {
|
|
1661
1895
|
get when() {
|
|
1662
1896
|
return branch();
|
|
1663
1897
|
},
|
|
1664
1898
|
children: (b) => (() => {
|
|
1665
|
-
var _el$
|
|
1666
|
-
insert(_el$
|
|
1667
|
-
effect((_$p) => setProp(_el$
|
|
1668
|
-
return _el$
|
|
1899
|
+
var _el$32 = createElement("text");
|
|
1900
|
+
insert(_el$32, b);
|
|
1901
|
+
effect((_$p) => setProp(_el$32, "fg", theme().textMuted, _$p));
|
|
1902
|
+
return _el$32;
|
|
1669
1903
|
})()
|
|
1670
|
-
}), _el$
|
|
1671
|
-
insert(_el$
|
|
1904
|
+
}), _el$24);
|
|
1905
|
+
insert(_el$22, createComponent(Show, {
|
|
1672
1906
|
get when() {
|
|
1673
1907
|
return preset().name;
|
|
1674
1908
|
},
|
|
1675
1909
|
get fallback() {
|
|
1676
1910
|
return (() => {
|
|
1677
|
-
var _el$
|
|
1678
|
-
insertNode(_el$
|
|
1679
|
-
setProp(_el$
|
|
1680
|
-
setProp(_el$
|
|
1681
|
-
insertNode(_el$
|
|
1682
|
-
effect((_$p) => setProp(_el$
|
|
1683
|
-
return _el$
|
|
1911
|
+
var _el$33 = createElement("box"), _el$34 = createElement("text");
|
|
1912
|
+
insertNode(_el$33, _el$34);
|
|
1913
|
+
setProp(_el$33, "flexDirection", "row");
|
|
1914
|
+
setProp(_el$33, "gap", 1);
|
|
1915
|
+
insertNode(_el$34, createTextNode(`Preset: default`));
|
|
1916
|
+
effect((_$p) => setProp(_el$34, "fg", theme().textMuted, _$p));
|
|
1917
|
+
return _el$33;
|
|
1684
1918
|
})();
|
|
1685
1919
|
},
|
|
1686
1920
|
children: (name) => (() => {
|
|
1687
|
-
var _el$
|
|
1688
|
-
insertNode(_el$
|
|
1689
|
-
insertNode(_el$
|
|
1690
|
-
insertNode(_el$
|
|
1691
|
-
setProp(_el$
|
|
1692
|
-
setProp(_el$
|
|
1693
|
-
insertNode(_el$
|
|
1694
|
-
insert(_el$
|
|
1695
|
-
insert(_el$
|
|
1921
|
+
var _el$36 = createElement("box"), _el$37 = createElement("text"), _el$39 = createElement("text"), _el$40 = createElement("text");
|
|
1922
|
+
insertNode(_el$36, _el$37);
|
|
1923
|
+
insertNode(_el$36, _el$39);
|
|
1924
|
+
insertNode(_el$36, _el$40);
|
|
1925
|
+
setProp(_el$36, "flexDirection", "row");
|
|
1926
|
+
setProp(_el$36, "gap", 1);
|
|
1927
|
+
insertNode(_el$37, createTextNode(`⚡ Preset:`));
|
|
1928
|
+
insert(_el$39, name);
|
|
1929
|
+
insert(_el$40, () => `(${preset().source ?? ""})`);
|
|
1696
1930
|
effect((_p$) => {
|
|
1697
|
-
var _v$
|
|
1698
|
-
_v$
|
|
1699
|
-
_v$
|
|
1700
|
-
_v$
|
|
1931
|
+
var _v$11 = theme().textMuted, _v$12 = theme().accent, _v$13 = theme().textMuted;
|
|
1932
|
+
_v$11 !== _p$.e && (_p$.e = setProp(_el$37, "fg", _v$11, _p$.e));
|
|
1933
|
+
_v$12 !== _p$.t && (_p$.t = setProp(_el$39, "fg", _v$12, _p$.t));
|
|
1934
|
+
_v$13 !== _p$.a && (_p$.a = setProp(_el$40, "fg", _v$13, _p$.a));
|
|
1701
1935
|
return _p$;
|
|
1702
1936
|
}, {
|
|
1703
1937
|
e: void 0,
|
|
1704
1938
|
t: void 0,
|
|
1705
1939
|
a: void 0
|
|
1706
1940
|
});
|
|
1707
|
-
return _el$
|
|
1941
|
+
return _el$36;
|
|
1708
1942
|
})()
|
|
1709
|
-
}), _el$
|
|
1710
|
-
insert(_el$
|
|
1711
|
-
insertNode(_el$
|
|
1712
|
-
insertNode(_el$
|
|
1713
|
-
setProp(_el$
|
|
1714
|
-
setProp(_el$
|
|
1715
|
-
insert(_el$
|
|
1716
|
-
insert(_el$
|
|
1717
|
-
insert(_el$
|
|
1943
|
+
}), _el$24);
|
|
1944
|
+
insert(_el$22, createComponent(HR, {}), _el$24);
|
|
1945
|
+
insertNode(_el$24, _el$25);
|
|
1946
|
+
insertNode(_el$24, _el$26);
|
|
1947
|
+
setProp(_el$24, "onMouseDown", () => setShowSessions((x) => !x));
|
|
1948
|
+
setProp(_el$25, "attributes", 1);
|
|
1949
|
+
insert(_el$25, () => `${showSessions() ? "▼" : "▶"} Sessions`);
|
|
1950
|
+
insert(_el$26, () => ` (${String(totalSessions())})`);
|
|
1951
|
+
insert(_el$22, createComponent(Show, {
|
|
1718
1952
|
get when() {
|
|
1719
1953
|
return showSessions();
|
|
1720
1954
|
},
|
|
@@ -1725,19 +1959,19 @@ function View(props) {
|
|
|
1725
1959
|
},
|
|
1726
1960
|
get fallback() {
|
|
1727
1961
|
return (() => {
|
|
1728
|
-
var _el$
|
|
1729
|
-
insertNode(_el$
|
|
1730
|
-
setProp(_el$
|
|
1731
|
-
insertNode(_el$
|
|
1732
|
-
effect((_$p) => setProp(_el$
|
|
1733
|
-
return _el$
|
|
1962
|
+
var _el$41 = createElement("box"), _el$42 = createElement("text");
|
|
1963
|
+
insertNode(_el$41, _el$42);
|
|
1964
|
+
setProp(_el$41, "marginLeft", 1);
|
|
1965
|
+
insertNode(_el$42, createTextNode(`No recent sessions`));
|
|
1966
|
+
effect((_$p) => setProp(_el$42, "fg", theme().textMuted, _$p));
|
|
1967
|
+
return _el$41;
|
|
1734
1968
|
})();
|
|
1735
1969
|
},
|
|
1736
1970
|
get children() {
|
|
1737
|
-
var _el$
|
|
1738
|
-
setProp(_el$
|
|
1739
|
-
setProp(_el$
|
|
1740
|
-
insert(_el$
|
|
1971
|
+
var _el$27 = createElement("box");
|
|
1972
|
+
setProp(_el$27, "marginLeft", 1);
|
|
1973
|
+
setProp(_el$27, "flexDirection", "column");
|
|
1974
|
+
insert(_el$27, createComponent(For, {
|
|
1741
1975
|
get each() {
|
|
1742
1976
|
return recentSessions();
|
|
1743
1977
|
},
|
|
@@ -1748,18 +1982,18 @@ function View(props) {
|
|
|
1748
1982
|
session: ses
|
|
1749
1983
|
})
|
|
1750
1984
|
}));
|
|
1751
|
-
return _el$
|
|
1985
|
+
return _el$27;
|
|
1752
1986
|
}
|
|
1753
1987
|
});
|
|
1754
1988
|
}
|
|
1755
|
-
}), _el$
|
|
1756
|
-
insertNode(_el$
|
|
1757
|
-
insertNode(_el$
|
|
1758
|
-
setProp(_el$
|
|
1759
|
-
setProp(_el$
|
|
1760
|
-
insert(_el$
|
|
1761
|
-
insert(_el$
|
|
1762
|
-
insert(_el$
|
|
1989
|
+
}), _el$28);
|
|
1990
|
+
insertNode(_el$28, _el$29);
|
|
1991
|
+
insertNode(_el$28, _el$30);
|
|
1992
|
+
setProp(_el$28, "onMouseDown", () => setShowDelegations((x) => !x));
|
|
1993
|
+
setProp(_el$29, "attributes", 1);
|
|
1994
|
+
insert(_el$29, () => `${showDelegations() ? "▼" : "▶"} Delegations`);
|
|
1995
|
+
insert(_el$30, () => ` ${delegationHeader()}`);
|
|
1996
|
+
insert(_el$22, createComponent(Show, {
|
|
1763
1997
|
get when() {
|
|
1764
1998
|
return showDelegations();
|
|
1765
1999
|
},
|
|
@@ -1770,19 +2004,19 @@ function View(props) {
|
|
|
1770
2004
|
},
|
|
1771
2005
|
get fallback() {
|
|
1772
2006
|
return (() => {
|
|
1773
|
-
var _el$
|
|
1774
|
-
insertNode(_el$
|
|
1775
|
-
setProp(_el$
|
|
1776
|
-
insertNode(_el$
|
|
1777
|
-
effect((_$p) => setProp(_el$
|
|
1778
|
-
return _el$
|
|
2007
|
+
var _el$44 = createElement("box"), _el$45 = createElement("text");
|
|
2008
|
+
insertNode(_el$44, _el$45);
|
|
2009
|
+
setProp(_el$44, "marginLeft", 1);
|
|
2010
|
+
insertNode(_el$45, createTextNode(`No delegations`));
|
|
2011
|
+
effect((_$p) => setProp(_el$45, "fg", theme().textMuted, _$p));
|
|
2012
|
+
return _el$44;
|
|
1779
2013
|
})();
|
|
1780
2014
|
},
|
|
1781
2015
|
get children() {
|
|
1782
|
-
var _el$
|
|
1783
|
-
setProp(_el$
|
|
1784
|
-
setProp(_el$
|
|
1785
|
-
insert(_el$
|
|
2016
|
+
var _el$31 = createElement("box");
|
|
2017
|
+
setProp(_el$31, "marginLeft", 1);
|
|
2018
|
+
setProp(_el$31, "flexDirection", "column");
|
|
2019
|
+
insert(_el$31, createComponent(For, {
|
|
1786
2020
|
get each() {
|
|
1787
2021
|
return visibleDelegations();
|
|
1788
2022
|
},
|
|
@@ -1798,19 +2032,79 @@ function View(props) {
|
|
|
1798
2032
|
return animationNow();
|
|
1799
2033
|
}
|
|
1800
2034
|
})
|
|
1801
|
-
}));
|
|
1802
|
-
|
|
2035
|
+
}), null);
|
|
2036
|
+
insert(_el$31, createComponent(Show, {
|
|
2037
|
+
get when() {
|
|
2038
|
+
return delegationSplit().archived.length > 0;
|
|
2039
|
+
},
|
|
2040
|
+
get children() {
|
|
2041
|
+
return (() => {
|
|
2042
|
+
const archived = delegationSplit().archived;
|
|
2043
|
+
const pageSize = 8;
|
|
2044
|
+
const pages = Math.ceil(archived.length / pageSize);
|
|
2045
|
+
const page = Math.min(archivedPage(), pages - 1);
|
|
2046
|
+
const slice = archived.slice(page * pageSize, page * pageSize + pageSize);
|
|
2047
|
+
return (() => {
|
|
2048
|
+
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");
|
|
2049
|
+
insertNode(_el$47, _el$48);
|
|
2050
|
+
setProp(_el$47, "flexDirection", "column");
|
|
2051
|
+
insertNode(_el$48, _el$49);
|
|
2052
|
+
insertNode(_el$48, _el$51);
|
|
2053
|
+
insertNode(_el$48, _el$52);
|
|
2054
|
+
insertNode(_el$48, _el$53);
|
|
2055
|
+
setProp(_el$48, "flexDirection", "row");
|
|
2056
|
+
setProp(_el$48, "marginLeft", 0);
|
|
2057
|
+
insertNode(_el$49, createTextNode(`‹ `));
|
|
2058
|
+
setProp(_el$49, "onMouseDown", () => clampArchivedPage(page - 1, pages));
|
|
2059
|
+
insert(_el$51, () => `Archived (${archived.length}) `);
|
|
2060
|
+
insert(_el$52, `${page + 1}/${pages}`);
|
|
2061
|
+
insertNode(_el$53, createTextNode(` ›`));
|
|
2062
|
+
setProp(_el$53, "onMouseDown", () => clampArchivedPage(page + 1, pages));
|
|
2063
|
+
insert(_el$47, createComponent(For, {
|
|
2064
|
+
each: slice,
|
|
2065
|
+
children: (job) => createComponent(DelegationRow, {
|
|
2066
|
+
get api() {
|
|
2067
|
+
return props.api;
|
|
2068
|
+
},
|
|
2069
|
+
job,
|
|
2070
|
+
get now() {
|
|
2071
|
+
return now();
|
|
2072
|
+
},
|
|
2073
|
+
get animationNow() {
|
|
2074
|
+
return animationNow();
|
|
2075
|
+
}
|
|
2076
|
+
})
|
|
2077
|
+
}), null);
|
|
2078
|
+
effect((_p$) => {
|
|
2079
|
+
var _v$14 = theme().textMuted, _v$15 = theme().textMuted, _v$16 = theme().textMuted, _v$17 = theme().textMuted;
|
|
2080
|
+
_v$14 !== _p$.e && (_p$.e = setProp(_el$49, "fg", _v$14, _p$.e));
|
|
2081
|
+
_v$15 !== _p$.t && (_p$.t = setProp(_el$51, "fg", _v$15, _p$.t));
|
|
2082
|
+
_v$16 !== _p$.a && (_p$.a = setProp(_el$52, "fg", _v$16, _p$.a));
|
|
2083
|
+
_v$17 !== _p$.o && (_p$.o = setProp(_el$53, "fg", _v$17, _p$.o));
|
|
2084
|
+
return _p$;
|
|
2085
|
+
}, {
|
|
2086
|
+
e: void 0,
|
|
2087
|
+
t: void 0,
|
|
2088
|
+
a: void 0,
|
|
2089
|
+
o: void 0
|
|
2090
|
+
});
|
|
2091
|
+
return _el$47;
|
|
2092
|
+
})();
|
|
2093
|
+
})();
|
|
2094
|
+
}
|
|
2095
|
+
}), null);
|
|
2096
|
+
return _el$31;
|
|
1803
2097
|
}
|
|
1804
2098
|
});
|
|
1805
2099
|
}
|
|
1806
2100
|
}), null);
|
|
1807
2101
|
effect((_p$) => {
|
|
1808
|
-
var _v$
|
|
1809
|
-
_v$
|
|
1810
|
-
_v$
|
|
1811
|
-
_v$
|
|
1812
|
-
_v$
|
|
1813
|
-
_v$
|
|
2102
|
+
var _v$8 = theme().accent, _v$9 = theme().text, _v$0 = theme().textMuted, _v$1 = theme().text, _v$10 = theme().textMuted;
|
|
2103
|
+
_v$8 !== _p$.e && (_p$.e = setProp(_el$23, "fg", _v$8, _p$.e));
|
|
2104
|
+
_v$9 !== _p$.t && (_p$.t = setProp(_el$25, "fg", _v$9, _p$.t));
|
|
2105
|
+
_v$0 !== _p$.a && (_p$.a = setProp(_el$26, "fg", _v$0, _p$.a));
|
|
2106
|
+
_v$1 !== _p$.o && (_p$.o = setProp(_el$29, "fg", _v$1, _p$.o));
|
|
2107
|
+
_v$10 !== _p$.i && (_p$.i = setProp(_el$30, "fg", _v$10, _p$.i));
|
|
1814
2108
|
return _p$;
|
|
1815
2109
|
}, {
|
|
1816
2110
|
e: void 0,
|
|
@@ -1819,7 +2113,7 @@ function View(props) {
|
|
|
1819
2113
|
o: void 0,
|
|
1820
2114
|
i: void 0
|
|
1821
2115
|
});
|
|
1822
|
-
return _el$
|
|
2116
|
+
return _el$22;
|
|
1823
2117
|
})();
|
|
1824
2118
|
}
|
|
1825
2119
|
const tui = (api, _options, _meta) => {
|
|
@@ -1839,6 +2133,8 @@ const tui = (api, _options, _meta) => {
|
|
|
1839
2133
|
const props = event?.properties ?? {};
|
|
1840
2134
|
const part = props.part ?? props.info?.part;
|
|
1841
2135
|
if (part === void 0) return;
|
|
2136
|
+
const sample = extractToolActivity(part);
|
|
2137
|
+
if (sample !== null) trackToolActivity(latestToolActivity, sample.sessionID, sample.activity);
|
|
1842
2138
|
if (reduceDelegationToolPart(liveStore.map, part)) liveStore.bump();
|
|
1843
2139
|
}));
|
|
1844
2140
|
} catch {}
|
|
@@ -1877,6 +2173,6 @@ const plugin = {
|
|
|
1877
2173
|
setup: async () => {}
|
|
1878
2174
|
};
|
|
1879
2175
|
//#endregion
|
|
1880
|
-
export { IDLE_SILENCE_MS, STALE_RUNNING_THRESHOLD_MS, buildChildrenPath, childStatusToState, childrenToDelegationEntries, collectDelegationToolParts, compareDelegationEntries, plugin as default, delegationActivity, delegationActivityLabel, delegationElapsed, delegationSpinnerFrame, delegationTag, fmtElapsed, isValidSessionId, markStaleIfRunning, mergeChildDelegationSources, mergeDelegationSources, navigateToDelegationSession, panelLogDir, parseDelegationMarkdown, parseDelegationToolPart, readAllDelegationEntries, readDelegationEntries, reduceDelegationToolPart, removeDelegationEntry, resolveCurrentSessionID, resolveDelegationsDir, safeSessionPath, seedLiveDelegationMap, toDelegationEntry, tuiLogPath, visibleDelegationList };
|
|
2176
|
+
export { DELEGATION_DESCRIPTION_MAX, DELEGATION_ELAPSED_WIDTH, DELEGATION_STATE_GLYPHS, IDLE_SILENCE_MS, STALE_RUNNING_THRESHOLD_MS, buildChildrenPath, childStatusToState, childrenToDelegationEntries, collectDelegationToolParts, compareDelegationEntries, countDelegationSources, plugin as default, delegationActivity, delegationActivityLabel, delegationElapsed, delegationIcon, delegationSpinnerFrame, delegationStateGlyph, delegationStateMarker, delegationStateTone, 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 };
|
|
1881
2177
|
|
|
1882
2178
|
//# sourceMappingURL=tui.js.map
|