pantheon-opencode 1.4.3 → 1.5.0-beta.10
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/README.md +93 -0
- package/.pantheon/code-mode/checkpoint-session.py +7 -0
- package/.pantheon/code-mode/checkpoint-session.sh +11 -0
- package/.pantheon/code-mode/checkpoint_session.py +481 -0
- package/.pantheon/code-mode/compress-inline.py +450 -0
- package/.pantheon/code-mode/eval-llm-judge.py +255 -0
- package/.pantheon/code-mode/eval-monte-carlo.py +368 -0
- package/.pantheon/code-mode/eval-run.py +197 -0
- package/.pantheon/code-mode/eval-static.py +321 -0
- package/.pantheon/code-mode/example-sync.sh +5 -0
- package/.pantheon/code-mode/manifest.json +21 -0
- package/.pantheon/code-mode/session-end-save.py +186 -0
- package/.pantheon/code-mode/session-end-save.sh +18 -0
- package/.pantheon/code-mode/test-allowed.sh +5 -0
- package/.pantheon/code-mode/test-auto-continue-checkpoint.sh +179 -0
- package/.pantheon/code-mode/test-env.sh +7 -0
- package/.pantheon/code-mode/test-prlimit.sh +9 -0
- package/.pantheon/code-mode/test-timeout.sh +6 -0
- package/CHANGELOG.md +1026 -0
- package/README.md +292 -1080
- package/README.pt-BR.md +308 -0
- package/bin/pantheon-init.mjs +207 -31
- package/opencode.json +1 -0
- package/package.json +34 -14
- package/plugin.json +15 -0
- package/pyproject.toml +65 -0
- package/scripts/_pantheon_paths.py +48 -7
- package/scripts/ci-validate-yaml.py +7 -2
- package/scripts/code_mode_server.py +451 -44
- package/scripts/cost.mjs +30 -14
- package/scripts/doctor.mjs +306 -129
- package/scripts/generate-preset-docs.mjs +127 -66
- package/scripts/generate-prompts.sh +2 -2
- package/scripts/install/cli-ui.mjs +23 -10
- package/scripts/install/config-migration.mjs +399 -0
- package/scripts/install/health-check.mjs +3 -3
- package/scripts/install/model-picker.mjs +72 -23
- package/scripts/install/opencode-version.mjs +47 -0
- package/scripts/install/opencode.mjs +396 -121
- package/scripts/install/plugin.mjs +89 -49
- package/scripts/install/shared.mjs +55 -159
- package/scripts/install/strings.mjs +129 -0
- package/scripts/install-mcp.mjs +45 -232
- package/scripts/manifest-inventory.mjs +410 -0
- package/scripts/mcp_persistence_server.py +798 -60
- package/scripts/mcp_resources_server.py +144 -40
- package/scripts/memory_mcp_server.py +2 -2
- 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/recover-zenodo-deposition.mjs +146 -0
- package/scripts/release-beta-version.mjs +56 -60
- package/scripts/sync-artifacts.mjs +169 -0
- package/scripts/sync-tui.mjs +135 -42
- package/scripts/test-opencode-v1-v2-sandbox.sh +862 -0
- package/scripts/uninstall.mjs +298 -954
- package/scripts/validate-zenodo-release.mjs +154 -0
- package/scripts/validation-policy.mjs +7 -7
- package/scripts/version-check.mjs +113 -108
- package/scripts/versioning.mjs +230 -86
- package/scripts/zenodo-artifact.mjs +21 -0
- package/scripts/zenodo-release-state.mjs +53 -0
- package/src/agents/mnemosyne.md +1 -1
- package/src/agents/zeus.md +27 -16
- package/src/mcp/_pantheon_paths.py +48 -7
- package/src/mcp/code_mode_server.py +451 -44
- package/src/mcp/eval_store.py +1 -1
- package/src/mcp/mcp_persistence_server.py +798 -60
- package/src/mcp/mcp_resources_server.py +144 -40
- package/src/mcp/pantheon_vision_server.py +1 -1
- package/src/mcp/toon_codec.py +491 -0
- package/src/pantheon/auto-wake.ts +1 -5
- package/src/pantheon/background-job-board.ts +110 -2
- package/src/pantheon/compaction-handoff.ts +304 -0
- package/src/pantheon/cost-command.ts +356 -69
- package/src/pantheon/delegate-manager.ts +766 -0
- package/src/pantheon/delegation-classifier.ts +307 -0
- package/src/pantheon/delegation-enforce.ts +13 -12
- package/src/pantheon/delegation-finalize.ts +406 -0
- package/src/pantheon/delegation-notify.ts +212 -0
- package/src/pantheon/delegation-toast.ts +73 -0
- package/src/pantheon/delegation.ts +1337 -0
- package/src/pantheon/file-persistence-salvage.ts +64 -0
- package/src/pantheon/file-persistence.ts +194 -45
- package/src/pantheon/goal-loop.ts +2 -2
- package/src/pantheon/goal-store.ts +1 -1
- package/src/pantheon/hashline/tool.ts +2 -2
- package/src/pantheon/model-command.ts +2 -1
- package/src/pantheon/native-probe.ts +234 -0
- package/src/pantheon/native-task-status.ts +139 -0
- package/src/pantheon/permission-eval.ts +284 -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/step-cap.ts +110 -0
- package/src/pantheon/task-result-guard.ts +107 -0
- package/src/pantheon/token-opt.ts +689 -0
- package/src/pantheon/tool-ceiling.ts +159 -0
- package/src/pantheon/toon-codec.ts +481 -0
- package/src/pantheon/tui-version-check.ts +1 -3
- package/src/pantheon/v2-bridge.ts +129 -0
- package/src/pantheon/v2-events.ts +148 -0
- package/src/pantheon/v2-hooks.ts +287 -0
- package/src/pantheon/v2-tool-definitions.ts +331 -0
- package/src/pantheon/zeus-delegate-with-retry.ts +406 -0
- package/src/plugin-v2/index.ts +21 -0
- package/src/plugin-v2.ts +824 -0
- package/src/plugin.ts +261 -51
- package/src/plugins/pantheon-hooks.ts +51 -0
- package/src/plugins/tui/dist/tui.d.ts +116 -24
- package/src/plugins/tui/dist/tui.d.ts.map +1 -1
- package/src/plugins/tui/dist/tui.js +416 -149
- package/src/plugins/tui/dist/tui.tsx +456 -87
- package/src/plugins/tui/package-lock.json +51 -51
- package/src/plugins/tui/package.json +7 -7
- package/src/plugins/tui/src/index.tsx +462 -95
- package/src/skills/README.md +0 -2
- package/src/pantheon/tool-context.ts +0 -41
|
@@ -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.
|
|
167
|
+
return "1.5.0-beta.10";
|
|
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,71 @@ 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
|
+
/** Bounded tracker: child session id → latest running tool call. */
|
|
981
|
+
const latestToolActivity = /* @__PURE__ */ new Map();
|
|
982
|
+
const MAX_TOOL_ACTIVITY_ENTRIES = 200;
|
|
983
|
+
const TOOL_ACTIVITY_TTL_MS = 300 * 1e3;
|
|
984
|
+
/** Archived-section pagination state — module-level so it survives sidebar
|
|
985
|
+
* remounts (route changes) without leaking into the component tree. */
|
|
986
|
+
const archivedUiState = { page: 0 };
|
|
987
|
+
/** First usable summary string from common tool input fields. */
|
|
988
|
+
function summarizeToolInput(input) {
|
|
989
|
+
if (!input) return "";
|
|
990
|
+
for (const key of [
|
|
991
|
+
"command",
|
|
992
|
+
"description",
|
|
993
|
+
"prompt",
|
|
994
|
+
"filePath",
|
|
995
|
+
"pattern",
|
|
996
|
+
"url",
|
|
997
|
+
"query"
|
|
998
|
+
]) {
|
|
999
|
+
const value = input[key];
|
|
1000
|
+
if (typeof value === "string" && value.trim() !== "") return value;
|
|
1001
|
+
}
|
|
1002
|
+
return "";
|
|
1003
|
+
}
|
|
1004
|
+
/** Reduce one message.part.updated tool part to displayable activity.
|
|
1005
|
+
* Returns null for non-tool parts, completed/error parts (no live activity)
|
|
1006
|
+
* or parts without a session id. Pure. */
|
|
1007
|
+
function extractToolActivity(part, now = Date.now()) {
|
|
1008
|
+
if (part?.type !== "tool") return null;
|
|
1009
|
+
const status = part.state?.status;
|
|
1010
|
+
if (status !== "pending" && status !== "running") return null;
|
|
1011
|
+
const sessionID = typeof part.sessionID === "string" ? part.sessionID : "";
|
|
1012
|
+
if (sessionID === "") return null;
|
|
1013
|
+
return {
|
|
1014
|
+
sessionID,
|
|
1015
|
+
activity: {
|
|
1016
|
+
tool: typeof part.tool === "string" && part.tool !== "" ? part.tool : "tool",
|
|
1017
|
+
summary: summarizeToolInput(part.state?.input).replace(/\s+/g, " ").trim().slice(0, 48),
|
|
1018
|
+
at: now
|
|
1019
|
+
}
|
|
1020
|
+
};
|
|
1021
|
+
}
|
|
1022
|
+
/** Record an activity sample (bounded map, oldest dropped). */
|
|
1023
|
+
function trackToolActivity(map, sessionID, activity) {
|
|
1024
|
+
if (sessionID === "") return;
|
|
1025
|
+
if (map.size >= MAX_TOOL_ACTIVITY_ENTRIES) {
|
|
1026
|
+
const oldest = map.keys().next().value;
|
|
1027
|
+
if (oldest !== void 0) map.delete(oldest);
|
|
1028
|
+
}
|
|
1029
|
+
map.set(sessionID, activity);
|
|
1030
|
+
}
|
|
1031
|
+
/** Latest live activity for a child session, or null when absent/stale. */
|
|
1032
|
+
function latestToolActivityFor(map, sessionID, now = Date.now(), ttlMs = TOOL_ACTIVITY_TTL_MS) {
|
|
1033
|
+
if (!sessionID) return null;
|
|
1034
|
+
const hit = map.get(sessionID);
|
|
1035
|
+
if (hit === void 0) return null;
|
|
1036
|
+
if (now - hit.at > ttlMs) return null;
|
|
1037
|
+
return hit;
|
|
1038
|
+
}
|
|
964
1039
|
/** Merge the immediate tool-event channel into the child-session channel.
|
|
965
1040
|
*
|
|
966
1041
|
* Children remain the durable source, while live entries make a delegation
|
|
@@ -1023,10 +1098,12 @@ const DELEGATE_TASKID_PATTERN = /\(task\s+([a-z0-9_]+)\)/i;
|
|
|
1023
1098
|
const READ_ALIAS_PATTERN = /^[a-z]{2,8}-\d+$/i;
|
|
1024
1099
|
/** Extract the tool name + args from a `message.part.updated` part and
|
|
1025
1100
|
* reduce it to what the panel needs. Returns null for anything that is
|
|
1026
|
-
* not a pantheon delegation tool part
|
|
1101
|
+
* not a pantheon delegation tool part, the native `task` subagent tool
|
|
1102
|
+
* (same parentID === caller mechanism — its children render `nat:`),
|
|
1103
|
+
* or is missing its callID. */
|
|
1027
1104
|
function parseDelegationToolPart(part, now = Date.now()) {
|
|
1028
1105
|
if (part.type !== "tool") return null;
|
|
1029
|
-
if (part.tool !== "pantheon_delegate" && part.tool !== "pantheon_delegation_read") return null;
|
|
1106
|
+
if (part.tool !== "pantheon_delegate" && part.tool !== "pantheon_delegation_read" && part.tool !== "task") return null;
|
|
1030
1107
|
const callID = part.callID;
|
|
1031
1108
|
if (callID === void 0 || callID === "") return null;
|
|
1032
1109
|
const sessionID = part.sessionID ?? "";
|
|
@@ -1058,8 +1135,8 @@ function parseDelegationToolPart(part, now = Date.now()) {
|
|
|
1058
1135
|
endAt
|
|
1059
1136
|
};
|
|
1060
1137
|
}
|
|
1061
|
-
const agent = typeof input.agent === "string" ? input.agent : "agent";
|
|
1062
|
-
const description = typeof input.description === "string" ? input.description : "";
|
|
1138
|
+
const agent = typeof input.agent === "string" ? input.agent : typeof input.subagent_type === "string" ? input.subagent_type : "agent";
|
|
1139
|
+
const description = typeof input.description === "string" ? input.description : typeof input.prompt === "string" ? input.prompt.slice(0, 120) : "";
|
|
1063
1140
|
let alias = null;
|
|
1064
1141
|
let taskID = null;
|
|
1065
1142
|
if (status === "completed") {
|
|
@@ -1071,7 +1148,7 @@ function parseDelegationToolPart(part, now = Date.now()) {
|
|
|
1071
1148
|
callID,
|
|
1072
1149
|
partID: part.id ?? "",
|
|
1073
1150
|
sessionID,
|
|
1074
|
-
tool: "pantheon_delegate",
|
|
1151
|
+
tool: part.tool === "task" ? "task" : "pantheon_delegate",
|
|
1075
1152
|
agent,
|
|
1076
1153
|
description,
|
|
1077
1154
|
status,
|
|
@@ -1120,7 +1197,7 @@ function reduceDelegationToolPart(map, part, now = Date.now()) {
|
|
|
1120
1197
|
callID: parsed.callID,
|
|
1121
1198
|
partID: parsed.partID,
|
|
1122
1199
|
sessionID: parsed.sessionID,
|
|
1123
|
-
tool:
|
|
1200
|
+
tool: parsed.tool,
|
|
1124
1201
|
agent: parsed.agent ?? "agent",
|
|
1125
1202
|
description: parsed.description,
|
|
1126
1203
|
alias: existing?.alias ?? null,
|
|
@@ -1137,7 +1214,7 @@ function reduceDelegationToolPart(map, part, now = Date.now()) {
|
|
|
1137
1214
|
callID: parsed.callID,
|
|
1138
1215
|
partID: parsed.partID,
|
|
1139
1216
|
sessionID: parsed.sessionID,
|
|
1140
|
-
tool:
|
|
1217
|
+
tool: parsed.tool,
|
|
1141
1218
|
agent: parsed.agent ?? "agent",
|
|
1142
1219
|
description: parsed.description,
|
|
1143
1220
|
alias: parsed.alias,
|
|
@@ -1182,11 +1259,14 @@ function removeDelegationEntry(map, partIDOrCallID) {
|
|
|
1182
1259
|
}
|
|
1183
1260
|
return false;
|
|
1184
1261
|
}
|
|
1185
|
-
/** Collect pantheon delegation tool parts from a session's messages.
|
|
1262
|
+
/** Collect pantheon delegation + native task tool parts from a session's messages.
|
|
1186
1263
|
* Messages may carry their parts inline (duck-typed `msg.parts`); when
|
|
1187
1264
|
* they don't, the optional `getParts(messageID)` callback is used (the TUI
|
|
1188
|
-
* SDK exposes `api.state.part(messageID)`).
|
|
1189
|
-
*
|
|
1265
|
+
* SDK exposes `api.state.part(messageID)`). The native `task` tool spawns a
|
|
1266
|
+
* child session with parentID = caller — the same mechanism as
|
|
1267
|
+
* pantheon_delegate — so its parts feed the live-map as the native signal
|
|
1268
|
+
* (rows render `nat:` via the children channel). Pure w.r.t. I/O — used
|
|
1269
|
+
* by the mount re-scan to re-seed the live map after compaction/attach. */
|
|
1190
1270
|
function collectDelegationToolParts(messages, getParts) {
|
|
1191
1271
|
const out = [];
|
|
1192
1272
|
for (const msg of messages ?? []) {
|
|
@@ -1196,7 +1276,7 @@ function collectDelegationToolParts(messages, getParts) {
|
|
|
1196
1276
|
if (!parts) continue;
|
|
1197
1277
|
for (const raw of parts) {
|
|
1198
1278
|
const part = raw;
|
|
1199
|
-
if (part?.type === "tool" && (part.tool === "pantheon_delegate" || part.tool === "pantheon_delegation_read")) out.push(part);
|
|
1279
|
+
if (part?.type === "tool" && (part.tool === "pantheon_delegate" || part.tool === "pantheon_delegation_read" || part.tool === "task")) out.push(part);
|
|
1200
1280
|
}
|
|
1201
1281
|
}
|
|
1202
1282
|
return out;
|
|
@@ -1309,14 +1389,102 @@ function buildChildrenPath(id) {
|
|
|
1309
1389
|
* correct it as soon as terminal data exists). */
|
|
1310
1390
|
function childStatusToState(status) {
|
|
1311
1391
|
if (status === "idle") return "completed";
|
|
1392
|
+
if (status === "retry") return "retry";
|
|
1312
1393
|
return "running";
|
|
1313
1394
|
}
|
|
1314
|
-
/**
|
|
1315
|
-
* (
|
|
1316
|
-
*
|
|
1317
|
-
*
|
|
1395
|
+
/** Short row prefix for a delegation entry (one of the two visual channels
|
|
1396
|
+
* that split native task() work from pantheon_delegate jobs — the other is
|
|
1397
|
+
* {@link delegationIcon}):
|
|
1398
|
+
*
|
|
1399
|
+
* - `nat:<agent>` — a native task() child (source 'children-only', no board
|
|
1400
|
+
* report). The child session carries no board alias, so the agent IS the
|
|
1401
|
+
* identity.
|
|
1402
|
+
* - `pan:<alias>` — a pantheon_delegate board row (`pan:apo-1`), the same
|
|
1403
|
+
* alias the manager prints in pantheon_delegation_list.
|
|
1404
|
+
*
|
|
1405
|
+
* Short prefixes keep the narrow sidebar readable (the old
|
|
1406
|
+
* `pan:apo-1`/`nat:` tags ate the row width). */
|
|
1318
1407
|
function delegationTag(entry) {
|
|
1319
|
-
return entry.source === "children-only" ?
|
|
1408
|
+
return entry.source === "children-only" ? `nat:${entry.agent}` : `pan:${entry.alias}`;
|
|
1409
|
+
}
|
|
1410
|
+
/** Row glyph: hollow diamond `◇` for native task() children (info color,
|
|
1411
|
+
* outline) vs filled diamond `◆` for pantheon_delegate rows (state color).
|
|
1412
|
+
* Shape + color are independent channels, so the split stays legible even
|
|
1413
|
+
* without color. */
|
|
1414
|
+
function delegationIcon(entry) {
|
|
1415
|
+
return entry.source === "children-only" ? "◇" : "◆";
|
|
1416
|
+
}
|
|
1417
|
+
/** Row identity after the status marker + glyph. Pantheon rows append the
|
|
1418
|
+
* agent (`pan:apo-1 apollo`); native rows already carry it inside the tag
|
|
1419
|
+
* (`nat:apollo`) and must not duplicate it. */
|
|
1420
|
+
function formatDelegationIdentity(entry) {
|
|
1421
|
+
return entry.source === "children-only" ? delegationTag(entry) : `${delegationTag(entry)} ${entry.agent}`;
|
|
1422
|
+
}
|
|
1423
|
+
/** Max description width on the row detail line — the old 180-char slice
|
|
1424
|
+
* wrapped the sidebar; 44 keeps one readable line. */
|
|
1425
|
+
const DELEGATION_DESCRIPTION_MAX = 44;
|
|
1426
|
+
/** Lazily-built grapheme segmenter. `Intl.Segmenter` keeps ZWJ emoji families
|
|
1427
|
+
* (and skin-tone/variation sequences) intact; `Array.from` (code points) is
|
|
1428
|
+
* the fallback for runtimes without it. */
|
|
1429
|
+
let graphemeSegmenter;
|
|
1430
|
+
/** Split `text` into display graphemes so truncation never cuts a multi-unit
|
|
1431
|
+
* emoji in half (surrogate pair → mojibake). */
|
|
1432
|
+
function splitGraphemes(text) {
|
|
1433
|
+
if (typeof Intl !== "undefined" && typeof Intl.Segmenter === "function") {
|
|
1434
|
+
graphemeSegmenter ??= new Intl.Segmenter("pt", { granularity: "grapheme" });
|
|
1435
|
+
return Array.from(graphemeSegmenter.segment(text), (s) => s.segment);
|
|
1436
|
+
}
|
|
1437
|
+
return Array.from(text);
|
|
1438
|
+
}
|
|
1439
|
+
/** Truncate a description to `max` graphemes appending `…` when cut. Exact
|
|
1440
|
+
* `max`-length text is left untouched. Grapheme-granular, so an emoji made of
|
|
1441
|
+
* several code points is never split into mojibake at the boundary. Pure. */
|
|
1442
|
+
function truncateDelegationDescription(text, max = 44) {
|
|
1443
|
+
const graphemes = splitGraphemes(text);
|
|
1444
|
+
if (graphemes.length <= max) return text;
|
|
1445
|
+
return `${graphemes.slice(0, Math.max(0, max - 1)).join("")}\u2026`;
|
|
1446
|
+
}
|
|
1447
|
+
/** Fixed elapsed-time box: right-aligned to `width` (default 8) so elapsed
|
|
1448
|
+
* values line up across rows, e.g. ` 12s`. A label that already fills
|
|
1449
|
+
* the box is returned untouched. Pure. */
|
|
1450
|
+
const DELEGATION_ELAPSED_WIDTH = 8;
|
|
1451
|
+
function formatDelegationElapsed(entry, now, width = 8) {
|
|
1452
|
+
const label = delegationElapsed(entry, now);
|
|
1453
|
+
if (label.length >= width) return label;
|
|
1454
|
+
return `${" ".repeat(width - label.length)}${label}`;
|
|
1455
|
+
}
|
|
1456
|
+
/** First row line: `<marker><glyph> <identity>`. The marker already carries
|
|
1457
|
+
* its trailing space. Pure — the row renders the returned string verbatim. */
|
|
1458
|
+
function formatDelegationRow(entry, marker) {
|
|
1459
|
+
return `${marker}${delegationIcon(entry)} ${formatDelegationIdentity(entry)}`;
|
|
1460
|
+
}
|
|
1461
|
+
/** Header summary: `(N active · M done · nat:K pan:M)`. Active counts
|
|
1462
|
+
* running/retry AND display-only stale-running (a stale row is still a live
|
|
1463
|
+
* job — it must never read as done). Pure. */
|
|
1464
|
+
function formatDelegationHeader(entries) {
|
|
1465
|
+
let active = 0;
|
|
1466
|
+
for (const e of entries) if (e.state === "running" || e.state === "retry" || e.state === "stale-running") active++;
|
|
1467
|
+
const done = entries.length - active;
|
|
1468
|
+
const counts = countDelegationSources(entries);
|
|
1469
|
+
return `(${active} active \u00b7 ${done} done \u00b7 nat:${counts.native} pan:${counts.pantheon})`;
|
|
1470
|
+
}
|
|
1471
|
+
/** Split a display list into native task() rows vs pantheon_delegate rows.
|
|
1472
|
+
* Native = source 'children-only' (no board report); everything else counts
|
|
1473
|
+
* as pantheon. Pure — powers the header breakdown + the hooks.log line. */
|
|
1474
|
+
function countDelegationSources(entries) {
|
|
1475
|
+
let native = 0;
|
|
1476
|
+
for (const e of entries) if (e.source === "children-only") native++;
|
|
1477
|
+
return {
|
|
1478
|
+
native,
|
|
1479
|
+
pantheon: entries.length - native,
|
|
1480
|
+
total: entries.length
|
|
1481
|
+
};
|
|
1482
|
+
}
|
|
1483
|
+
/** Diagnostic hooks.log line for a panel re-fetch, with the children
|
|
1484
|
+
* breakdown (pantheon = children WITH a board report, native = children
|
|
1485
|
+
* WITHOUT one). Pure — the View logs the returned string verbatim. */
|
|
1486
|
+
function formatPanelLogLine(children, pantheon, native, md, events) {
|
|
1487
|
+
return `panel: children=${children}(pantheon=${pantheon} native=${native}) md=${md} events=${events}`;
|
|
1320
1488
|
}
|
|
1321
1489
|
/** Turn child sessions (PRIMARY) enriched with md reports into the display
|
|
1322
1490
|
* list. One entry per child id (duplicates across re-fetches collapse).
|
|
@@ -1326,10 +1494,14 @@ function delegationTag(entry) {
|
|
|
1326
1494
|
* itself (fallback 'agent'), state derived from its status, startedAt from
|
|
1327
1495
|
* time.created. A report-less child is a NATIVE task() child (every
|
|
1328
1496
|
* child of the current session — pantheon_delegate OR the native `task()`
|
|
1329
|
-
* tool — carries parentID = caller), so it gets source 'children-only'
|
|
1330
|
-
* and the `
|
|
1497
|
+
* tool — carries parentID = caller), so it gets source 'children-only',
|
|
1498
|
+
* the internal alias 'native-task' and the `nat:` tag instead of a
|
|
1499
|
+
* board alias. The 'task nativa' description fallback keeps the row
|
|
1500
|
+
* non-empty when the child carries no title.
|
|
1331
1501
|
* Terminal md state wins over the derived state; a running md defers to
|
|
1332
|
-
* the child's live status.
|
|
1502
|
+
* the child's live status. A running child is NEVER archived — it always
|
|
1503
|
+
* lands in the active split (splitDelegationList active = running/retry).
|
|
1504
|
+
* Sorted running-first (compareDelegationEntries).
|
|
1333
1505
|
* Pure — no I/O. */
|
|
1334
1506
|
function childrenToDelegationEntries(children, md, now = Date.now()) {
|
|
1335
1507
|
const byTaskID = /* @__PURE__ */ new Map();
|
|
@@ -1342,7 +1514,7 @@ function childrenToDelegationEntries(children, md, now = Date.now()) {
|
|
|
1342
1514
|
const mdEntry = byTaskID.get(child.id);
|
|
1343
1515
|
const state = mdEntry !== void 0 && mdEntry.state !== "running" ? mdEntry.state : childStatusToState(child.status);
|
|
1344
1516
|
out.push({
|
|
1345
|
-
alias: mdEntry?.alias ?? "task",
|
|
1517
|
+
alias: mdEntry?.alias ?? "native-task",
|
|
1346
1518
|
sessionID: mdEntry?.sessionID ?? "",
|
|
1347
1519
|
taskID: child.id,
|
|
1348
1520
|
agent: mdEntry?.agent ?? child.agent ?? "agent",
|
|
@@ -1350,7 +1522,7 @@ function childrenToDelegationEntries(children, md, now = Date.now()) {
|
|
|
1350
1522
|
startedAt: mdEntry?.startedAt ?? child.time?.created ?? now,
|
|
1351
1523
|
updatedAt: mdEntry?.updatedAt ?? (state === "running" || state === "stale-running" ? null : child.time?.updated ?? null),
|
|
1352
1524
|
timedOut: mdEntry?.timedOut ?? false,
|
|
1353
|
-
description: mdEntry !== void 0 && mdEntry.description !== "" ? mdEntry.description : child.title
|
|
1525
|
+
description: mdEntry !== void 0 && mdEntry.description !== "" ? mdEntry.description : child.title !== void 0 && child.title !== "" ? child.title : "task nativa",
|
|
1354
1526
|
source: mdEntry !== void 0 ? "md" : "children-only"
|
|
1355
1527
|
});
|
|
1356
1528
|
}
|
|
@@ -1393,7 +1565,11 @@ function createTuiLogger(projectRoot, module = "pantheon-tui") {
|
|
|
1393
1565
|
await mkdir(dirname(logPath), { recursive: true });
|
|
1394
1566
|
const stamp = (/* @__PURE__ */ new Date()).toISOString();
|
|
1395
1567
|
await appendFile(logPath, `${lines.map((l) => `[${stamp}] [${module}] ${l}`).join("\n")}\n`, "utf8");
|
|
1396
|
-
} catch {
|
|
1568
|
+
} catch (err) {
|
|
1569
|
+
if (echo) try {
|
|
1570
|
+
process.stderr.write(`[${module}] file-log failed: ${formatArg(err)}\n`);
|
|
1571
|
+
} catch {}
|
|
1572
|
+
}
|
|
1397
1573
|
})();
|
|
1398
1574
|
if (echo) for (const line of lines) console.log(`[${module}] ${line}`);
|
|
1399
1575
|
};
|
|
@@ -1429,6 +1605,7 @@ function DelegationRow(props) {
|
|
|
1429
1605
|
const t = theme();
|
|
1430
1606
|
switch (props.job.state) {
|
|
1431
1607
|
case "running": return t.warning;
|
|
1608
|
+
case "retry": return t.warning;
|
|
1432
1609
|
case "stale-running": return t.error;
|
|
1433
1610
|
case "completed": return t.success;
|
|
1434
1611
|
case "error": return t.error;
|
|
@@ -1437,6 +1614,7 @@ function DelegationRow(props) {
|
|
|
1437
1614
|
});
|
|
1438
1615
|
const marker = createMemo(() => {
|
|
1439
1616
|
if (props.job.state === "running") return `${delegationSpinnerFrame(props.animationNow)} `;
|
|
1617
|
+
if (props.job.state === "retry") return "⟳ ";
|
|
1440
1618
|
if (props.job.state === "stale-running") return "⚠ ";
|
|
1441
1619
|
switch (props.job.state) {
|
|
1442
1620
|
case "completed": return "✓ ";
|
|
@@ -1445,38 +1623,55 @@ function DelegationRow(props) {
|
|
|
1445
1623
|
}
|
|
1446
1624
|
});
|
|
1447
1625
|
const tagColor = createMemo(() => props.job.source === "children-only" ? theme().info : color());
|
|
1448
|
-
const
|
|
1449
|
-
|
|
1450
|
-
|
|
1451
|
-
});
|
|
1626
|
+
const description = createMemo(() => truncateDelegationDescription(props.job.description));
|
|
1627
|
+
const elapsed = createMemo(() => formatDelegationElapsed(props.job, props.now));
|
|
1628
|
+
const activity = createMemo(() => latestToolActivityFor(latestToolActivity, props.job.taskID, props.now));
|
|
1452
1629
|
const open = () => {
|
|
1453
1630
|
navigateToDelegationSession(props.api.route, props.job.taskID);
|
|
1454
1631
|
};
|
|
1455
1632
|
return (() => {
|
|
1456
|
-
var _el$13 = createElement("box"), _el$14 = createElement("box"), _el$15 = createElement("text"), _el$16 = createElement("
|
|
1633
|
+
var _el$13 = createElement("box"), _el$14 = createElement("box"), _el$15 = createElement("text"), _el$16 = createElement("box"), _el$18 = createElement("text");
|
|
1457
1634
|
insertNode(_el$13, _el$14);
|
|
1458
|
-
insertNode(_el$13, _el$
|
|
1635
|
+
insertNode(_el$13, _el$16);
|
|
1459
1636
|
setProp(_el$13, "onMouseDown", open);
|
|
1460
1637
|
insertNode(_el$14, _el$15);
|
|
1461
|
-
insertNode(_el$14, _el$16);
|
|
1462
|
-
insertNode(_el$14, _el$17);
|
|
1463
1638
|
setProp(_el$14, "flexDirection", "row");
|
|
1464
|
-
insert(_el$15, marker);
|
|
1465
|
-
|
|
1466
|
-
|
|
1467
|
-
insert(_el$
|
|
1639
|
+
insert(_el$15, () => formatDelegationRow(props.job, marker()));
|
|
1640
|
+
insertNode(_el$16, _el$18);
|
|
1641
|
+
setProp(_el$16, "flexDirection", "row");
|
|
1642
|
+
insert(_el$16, createComponent(Show, {
|
|
1643
|
+
get when() {
|
|
1644
|
+
return description() !== "";
|
|
1645
|
+
},
|
|
1646
|
+
get children() {
|
|
1647
|
+
var _el$17 = createElement("text");
|
|
1648
|
+
insert(_el$17, description);
|
|
1649
|
+
effect((_$p) => setProp(_el$17, "fg", theme().textMuted, _$p));
|
|
1650
|
+
return _el$17;
|
|
1651
|
+
}
|
|
1652
|
+
}), _el$18);
|
|
1653
|
+
insert(_el$18, elapsed);
|
|
1654
|
+
insert(_el$13, createComponent(Show, {
|
|
1655
|
+
get when() {
|
|
1656
|
+
return activity();
|
|
1657
|
+
},
|
|
1658
|
+
children: (a) => (() => {
|
|
1659
|
+
var _el$19 = createElement("text");
|
|
1660
|
+
insert(_el$19, () => ` \u21b3 ${truncateDelegationDescription(`${a().tool}${a().summary !== "" ? ` ${a().summary}` : ""}`)}`);
|
|
1661
|
+
effect((_$p) => setProp(_el$19, "fg", theme().textMuted, _$p));
|
|
1662
|
+
return _el$19;
|
|
1663
|
+
})()
|
|
1664
|
+
}), null);
|
|
1468
1665
|
effect((_p$) => {
|
|
1469
|
-
var _v$5 =
|
|
1666
|
+
var _v$5 = tagColor(), _v$6 = description() !== "" ? "space-between" : "flex-end", _v$7 = theme().textMuted;
|
|
1470
1667
|
_v$5 !== _p$.e && (_p$.e = setProp(_el$15, "fg", _v$5, _p$.e));
|
|
1471
|
-
_v$6 !== _p$.t && (_p$.t = setProp(_el$16, "
|
|
1472
|
-
_v$7 !== _p$.a && (_p$.a = setProp(_el$
|
|
1473
|
-
_v$8 !== _p$.o && (_p$.o = setProp(_el$18, "fg", _v$8, _p$.o));
|
|
1668
|
+
_v$6 !== _p$.t && (_p$.t = setProp(_el$16, "justifyContent", _v$6, _p$.t));
|
|
1669
|
+
_v$7 !== _p$.a && (_p$.a = setProp(_el$18, "fg", _v$7, _p$.a));
|
|
1474
1670
|
return _p$;
|
|
1475
1671
|
}, {
|
|
1476
1672
|
e: void 0,
|
|
1477
1673
|
t: void 0,
|
|
1478
|
-
a: void 0
|
|
1479
|
-
o: void 0
|
|
1674
|
+
a: void 0
|
|
1480
1675
|
});
|
|
1481
1676
|
return _el$13;
|
|
1482
1677
|
})();
|
|
@@ -1558,7 +1753,7 @@ function View(props) {
|
|
|
1558
1753
|
});
|
|
1559
1754
|
if (sessionID === null) {
|
|
1560
1755
|
setChildDelegations(md);
|
|
1561
|
-
panelLog.info(
|
|
1756
|
+
panelLog.info(`${formatPanelLogLine(0, 0, 0, md.length, eventRefreshCount)} (no sessionID — history shown)`);
|
|
1562
1757
|
return;
|
|
1563
1758
|
}
|
|
1564
1759
|
let children = [];
|
|
@@ -1585,14 +1780,23 @@ function View(props) {
|
|
|
1585
1780
|
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);
|
|
1586
1781
|
const liveEntries = [...props.liveStore.map.values()].filter((entry) => entry.sessionID === sessionID);
|
|
1587
1782
|
setChildDelegations(mergeChildDelegationSources(childEntries, liveEntries));
|
|
1588
|
-
|
|
1783
|
+
const counts = countDelegationSources(childEntries);
|
|
1784
|
+
panelLog.info(formatPanelLogLine(children.length, counts.pantheon, counts.native, md.length, eventRefreshCount));
|
|
1589
1785
|
} finally {
|
|
1590
1786
|
delegationsInflight = null;
|
|
1591
1787
|
}
|
|
1592
1788
|
})();
|
|
1593
1789
|
return delegationsInflight;
|
|
1594
1790
|
};
|
|
1595
|
-
const
|
|
1791
|
+
const delegationSplit = createMemo(() => splitDelegationList(childDelegations()));
|
|
1792
|
+
const visibleDelegations = createMemo(() => [...delegationSplit().active, ...delegationSplit().recent]);
|
|
1793
|
+
const delegationHeader = createMemo(() => formatDelegationHeader(childDelegations()));
|
|
1794
|
+
const [archivedPage, setArchivedPage] = createSignal(archivedUiState.page);
|
|
1795
|
+
const clampArchivedPage = (page, pages) => {
|
|
1796
|
+
const clamped = Math.max(0, Math.min(page, Math.max(0, pages - 1)));
|
|
1797
|
+
archivedUiState.page = clamped;
|
|
1798
|
+
setArchivedPage(clamped);
|
|
1799
|
+
};
|
|
1596
1800
|
onMount(() => {
|
|
1597
1801
|
const cleanup = [];
|
|
1598
1802
|
try {
|
|
@@ -1621,7 +1825,7 @@ function View(props) {
|
|
|
1621
1825
|
refreshDelegations();
|
|
1622
1826
|
}, 1e3);
|
|
1623
1827
|
cleanup.push(() => clearInterval(poll));
|
|
1624
|
-
const animation = setInterval(() => setAnimationNow(Date.now()),
|
|
1828
|
+
const animation = setInterval(() => setAnimationNow(Date.now()), 1e3);
|
|
1625
1829
|
cleanup.push(() => clearInterval(animation));
|
|
1626
1830
|
try {
|
|
1627
1831
|
const sdk = props.api.state?.session;
|
|
@@ -1641,78 +1845,78 @@ function View(props) {
|
|
|
1641
1845
|
}));
|
|
1642
1846
|
});
|
|
1643
1847
|
const HR = () => (() => {
|
|
1644
|
-
var _el$
|
|
1645
|
-
insertNode(_el$
|
|
1646
|
-
effect((_$p) => setProp(_el$
|
|
1647
|
-
return _el$
|
|
1848
|
+
var _el$20 = createElement("text");
|
|
1849
|
+
insertNode(_el$20, createTextNode(`────────────────────────────`));
|
|
1850
|
+
effect((_$p) => setProp(_el$20, "fg", theme().textMuted, _$p));
|
|
1851
|
+
return _el$20;
|
|
1648
1852
|
})();
|
|
1649
1853
|
return (() => {
|
|
1650
|
-
var _el$
|
|
1651
|
-
insertNode(_el$
|
|
1652
|
-
insertNode(_el$
|
|
1653
|
-
insertNode(_el$
|
|
1654
|
-
setProp(_el$
|
|
1655
|
-
setProp(_el$
|
|
1656
|
-
setProp(_el$
|
|
1657
|
-
insert(_el$
|
|
1658
|
-
insert(_el$
|
|
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");
|
|
1855
|
+
insertNode(_el$22, _el$23);
|
|
1856
|
+
insertNode(_el$22, _el$24);
|
|
1857
|
+
insertNode(_el$22, _el$28);
|
|
1858
|
+
setProp(_el$22, "flexDirection", "column");
|
|
1859
|
+
setProp(_el$22, "width", "100%");
|
|
1860
|
+
setProp(_el$23, "attributes", 1);
|
|
1861
|
+
insert(_el$23, () => `Pantheon${props.version ? ` v${props.version}` : ""}`);
|
|
1862
|
+
insert(_el$22, createComponent(Show, {
|
|
1659
1863
|
get when() {
|
|
1660
1864
|
return branch();
|
|
1661
1865
|
},
|
|
1662
1866
|
children: (b) => (() => {
|
|
1663
|
-
var _el$
|
|
1664
|
-
insert(_el$
|
|
1665
|
-
effect((_$p) => setProp(_el$
|
|
1666
|
-
return _el$
|
|
1867
|
+
var _el$32 = createElement("text");
|
|
1868
|
+
insert(_el$32, b);
|
|
1869
|
+
effect((_$p) => setProp(_el$32, "fg", theme().textMuted, _$p));
|
|
1870
|
+
return _el$32;
|
|
1667
1871
|
})()
|
|
1668
|
-
}), _el$
|
|
1669
|
-
insert(_el$
|
|
1872
|
+
}), _el$24);
|
|
1873
|
+
insert(_el$22, createComponent(Show, {
|
|
1670
1874
|
get when() {
|
|
1671
1875
|
return preset().name;
|
|
1672
1876
|
},
|
|
1673
1877
|
get fallback() {
|
|
1674
1878
|
return (() => {
|
|
1675
|
-
var _el$
|
|
1676
|
-
insertNode(_el$
|
|
1677
|
-
setProp(_el$
|
|
1678
|
-
setProp(_el$
|
|
1679
|
-
insertNode(_el$
|
|
1680
|
-
effect((_$p) => setProp(_el$
|
|
1681
|
-
return _el$
|
|
1879
|
+
var _el$33 = createElement("box"), _el$34 = createElement("text");
|
|
1880
|
+
insertNode(_el$33, _el$34);
|
|
1881
|
+
setProp(_el$33, "flexDirection", "row");
|
|
1882
|
+
setProp(_el$33, "gap", 1);
|
|
1883
|
+
insertNode(_el$34, createTextNode(`Preset: default`));
|
|
1884
|
+
effect((_$p) => setProp(_el$34, "fg", theme().textMuted, _$p));
|
|
1885
|
+
return _el$33;
|
|
1682
1886
|
})();
|
|
1683
1887
|
},
|
|
1684
1888
|
children: (name) => (() => {
|
|
1685
|
-
var _el$
|
|
1686
|
-
insertNode(_el$
|
|
1687
|
-
insertNode(_el$
|
|
1688
|
-
insertNode(_el$
|
|
1689
|
-
setProp(_el$
|
|
1690
|
-
setProp(_el$
|
|
1691
|
-
insertNode(_el$
|
|
1692
|
-
insert(_el$
|
|
1693
|
-
insert(_el$
|
|
1889
|
+
var _el$36 = createElement("box"), _el$37 = createElement("text"), _el$39 = createElement("text"), _el$40 = createElement("text");
|
|
1890
|
+
insertNode(_el$36, _el$37);
|
|
1891
|
+
insertNode(_el$36, _el$39);
|
|
1892
|
+
insertNode(_el$36, _el$40);
|
|
1893
|
+
setProp(_el$36, "flexDirection", "row");
|
|
1894
|
+
setProp(_el$36, "gap", 1);
|
|
1895
|
+
insertNode(_el$37, createTextNode(`⚡ Preset:`));
|
|
1896
|
+
insert(_el$39, name);
|
|
1897
|
+
insert(_el$40, () => `(${preset().source ?? ""})`);
|
|
1694
1898
|
effect((_p$) => {
|
|
1695
|
-
var _v$
|
|
1696
|
-
_v$
|
|
1697
|
-
_v$
|
|
1698
|
-
_v$
|
|
1899
|
+
var _v$11 = theme().textMuted, _v$12 = theme().accent, _v$13 = theme().textMuted;
|
|
1900
|
+
_v$11 !== _p$.e && (_p$.e = setProp(_el$37, "fg", _v$11, _p$.e));
|
|
1901
|
+
_v$12 !== _p$.t && (_p$.t = setProp(_el$39, "fg", _v$12, _p$.t));
|
|
1902
|
+
_v$13 !== _p$.a && (_p$.a = setProp(_el$40, "fg", _v$13, _p$.a));
|
|
1699
1903
|
return _p$;
|
|
1700
1904
|
}, {
|
|
1701
1905
|
e: void 0,
|
|
1702
1906
|
t: void 0,
|
|
1703
1907
|
a: void 0
|
|
1704
1908
|
});
|
|
1705
|
-
return _el$
|
|
1909
|
+
return _el$36;
|
|
1706
1910
|
})()
|
|
1707
|
-
}), _el$
|
|
1708
|
-
insert(_el$
|
|
1709
|
-
insertNode(_el$
|
|
1710
|
-
insertNode(_el$
|
|
1711
|
-
setProp(_el$
|
|
1712
|
-
setProp(_el$
|
|
1713
|
-
insert(_el$
|
|
1714
|
-
insert(_el$
|
|
1715
|
-
insert(_el$
|
|
1911
|
+
}), _el$24);
|
|
1912
|
+
insert(_el$22, createComponent(HR, {}), _el$24);
|
|
1913
|
+
insertNode(_el$24, _el$25);
|
|
1914
|
+
insertNode(_el$24, _el$26);
|
|
1915
|
+
setProp(_el$24, "onMouseDown", () => setShowSessions((x) => !x));
|
|
1916
|
+
setProp(_el$25, "attributes", 1);
|
|
1917
|
+
insert(_el$25, () => `${showSessions() ? "▼" : "▶"} Sessions`);
|
|
1918
|
+
insert(_el$26, () => ` (${String(totalSessions())})`);
|
|
1919
|
+
insert(_el$22, createComponent(Show, {
|
|
1716
1920
|
get when() {
|
|
1717
1921
|
return showSessions();
|
|
1718
1922
|
},
|
|
@@ -1723,19 +1927,19 @@ function View(props) {
|
|
|
1723
1927
|
},
|
|
1724
1928
|
get fallback() {
|
|
1725
1929
|
return (() => {
|
|
1726
|
-
var _el$
|
|
1727
|
-
insertNode(_el$
|
|
1728
|
-
setProp(_el$
|
|
1729
|
-
insertNode(_el$
|
|
1730
|
-
effect((_$p) => setProp(_el$
|
|
1731
|
-
return _el$
|
|
1930
|
+
var _el$41 = createElement("box"), _el$42 = createElement("text");
|
|
1931
|
+
insertNode(_el$41, _el$42);
|
|
1932
|
+
setProp(_el$41, "marginLeft", 1);
|
|
1933
|
+
insertNode(_el$42, createTextNode(`No recent sessions`));
|
|
1934
|
+
effect((_$p) => setProp(_el$42, "fg", theme().textMuted, _$p));
|
|
1935
|
+
return _el$41;
|
|
1732
1936
|
})();
|
|
1733
1937
|
},
|
|
1734
1938
|
get children() {
|
|
1735
|
-
var _el$
|
|
1736
|
-
setProp(_el$
|
|
1737
|
-
setProp(_el$
|
|
1738
|
-
insert(_el$
|
|
1939
|
+
var _el$27 = createElement("box");
|
|
1940
|
+
setProp(_el$27, "marginLeft", 1);
|
|
1941
|
+
setProp(_el$27, "flexDirection", "column");
|
|
1942
|
+
insert(_el$27, createComponent(For, {
|
|
1739
1943
|
get each() {
|
|
1740
1944
|
return recentSessions();
|
|
1741
1945
|
},
|
|
@@ -1746,18 +1950,18 @@ function View(props) {
|
|
|
1746
1950
|
session: ses
|
|
1747
1951
|
})
|
|
1748
1952
|
}));
|
|
1749
|
-
return _el$
|
|
1953
|
+
return _el$27;
|
|
1750
1954
|
}
|
|
1751
1955
|
});
|
|
1752
1956
|
}
|
|
1753
|
-
}), _el$
|
|
1754
|
-
insertNode(_el$
|
|
1755
|
-
insertNode(_el$
|
|
1756
|
-
setProp(_el$
|
|
1757
|
-
setProp(_el$
|
|
1758
|
-
insert(_el$
|
|
1759
|
-
insert(_el$
|
|
1760
|
-
insert(_el$
|
|
1957
|
+
}), _el$28);
|
|
1958
|
+
insertNode(_el$28, _el$29);
|
|
1959
|
+
insertNode(_el$28, _el$30);
|
|
1960
|
+
setProp(_el$28, "onMouseDown", () => setShowDelegations((x) => !x));
|
|
1961
|
+
setProp(_el$29, "attributes", 1);
|
|
1962
|
+
insert(_el$29, () => `${showDelegations() ? "▼" : "▶"} Delegations`);
|
|
1963
|
+
insert(_el$30, () => ` ${delegationHeader()}`);
|
|
1964
|
+
insert(_el$22, createComponent(Show, {
|
|
1761
1965
|
get when() {
|
|
1762
1966
|
return showDelegations();
|
|
1763
1967
|
},
|
|
@@ -1768,19 +1972,19 @@ function View(props) {
|
|
|
1768
1972
|
},
|
|
1769
1973
|
get fallback() {
|
|
1770
1974
|
return (() => {
|
|
1771
|
-
var _el$
|
|
1772
|
-
insertNode(_el$
|
|
1773
|
-
setProp(_el$
|
|
1774
|
-
insertNode(_el$
|
|
1775
|
-
effect((_$p) => setProp(_el$
|
|
1776
|
-
return _el$
|
|
1975
|
+
var _el$44 = createElement("box"), _el$45 = createElement("text");
|
|
1976
|
+
insertNode(_el$44, _el$45);
|
|
1977
|
+
setProp(_el$44, "marginLeft", 1);
|
|
1978
|
+
insertNode(_el$45, createTextNode(`No delegations`));
|
|
1979
|
+
effect((_$p) => setProp(_el$45, "fg", theme().textMuted, _$p));
|
|
1980
|
+
return _el$44;
|
|
1777
1981
|
})();
|
|
1778
1982
|
},
|
|
1779
1983
|
get children() {
|
|
1780
|
-
var _el$
|
|
1781
|
-
setProp(_el$
|
|
1782
|
-
setProp(_el$
|
|
1783
|
-
insert(_el$
|
|
1984
|
+
var _el$31 = createElement("box");
|
|
1985
|
+
setProp(_el$31, "marginLeft", 1);
|
|
1986
|
+
setProp(_el$31, "flexDirection", "column");
|
|
1987
|
+
insert(_el$31, createComponent(For, {
|
|
1784
1988
|
get each() {
|
|
1785
1989
|
return visibleDelegations();
|
|
1786
1990
|
},
|
|
@@ -1796,19 +2000,79 @@ function View(props) {
|
|
|
1796
2000
|
return animationNow();
|
|
1797
2001
|
}
|
|
1798
2002
|
})
|
|
1799
|
-
}));
|
|
1800
|
-
|
|
2003
|
+
}), null);
|
|
2004
|
+
insert(_el$31, createComponent(Show, {
|
|
2005
|
+
get when() {
|
|
2006
|
+
return delegationSplit().archived.length > 0;
|
|
2007
|
+
},
|
|
2008
|
+
get children() {
|
|
2009
|
+
return (() => {
|
|
2010
|
+
const archived = delegationSplit().archived;
|
|
2011
|
+
const pageSize = 8;
|
|
2012
|
+
const pages = Math.ceil(archived.length / pageSize);
|
|
2013
|
+
const page = Math.min(archivedPage(), pages - 1);
|
|
2014
|
+
const slice = archived.slice(page * pageSize, page * pageSize + pageSize);
|
|
2015
|
+
return (() => {
|
|
2016
|
+
var _el$47 = createElement("box"), _el$48 = createElement("box"), _el$49 = createElement("text"), _el$51 = createElement("text"), _el$52 = createElement("text"), _el$53 = createElement("text");
|
|
2017
|
+
insertNode(_el$47, _el$48);
|
|
2018
|
+
setProp(_el$47, "flexDirection", "column");
|
|
2019
|
+
insertNode(_el$48, _el$49);
|
|
2020
|
+
insertNode(_el$48, _el$51);
|
|
2021
|
+
insertNode(_el$48, _el$52);
|
|
2022
|
+
insertNode(_el$48, _el$53);
|
|
2023
|
+
setProp(_el$48, "flexDirection", "row");
|
|
2024
|
+
setProp(_el$48, "marginLeft", 0);
|
|
2025
|
+
insertNode(_el$49, createTextNode(`‹ `));
|
|
2026
|
+
setProp(_el$49, "onMouseDown", () => clampArchivedPage(page - 1, pages));
|
|
2027
|
+
insert(_el$51, () => `Archived (${archived.length}) `);
|
|
2028
|
+
insert(_el$52, `${page + 1}/${pages}`);
|
|
2029
|
+
insertNode(_el$53, createTextNode(` ›`));
|
|
2030
|
+
setProp(_el$53, "onMouseDown", () => clampArchivedPage(page + 1, pages));
|
|
2031
|
+
insert(_el$47, createComponent(For, {
|
|
2032
|
+
each: slice,
|
|
2033
|
+
children: (job) => createComponent(DelegationRow, {
|
|
2034
|
+
get api() {
|
|
2035
|
+
return props.api;
|
|
2036
|
+
},
|
|
2037
|
+
job,
|
|
2038
|
+
get now() {
|
|
2039
|
+
return now();
|
|
2040
|
+
},
|
|
2041
|
+
get animationNow() {
|
|
2042
|
+
return animationNow();
|
|
2043
|
+
}
|
|
2044
|
+
})
|
|
2045
|
+
}), null);
|
|
2046
|
+
effect((_p$) => {
|
|
2047
|
+
var _v$14 = theme().textMuted, _v$15 = theme().textMuted, _v$16 = theme().textMuted, _v$17 = theme().textMuted;
|
|
2048
|
+
_v$14 !== _p$.e && (_p$.e = setProp(_el$49, "fg", _v$14, _p$.e));
|
|
2049
|
+
_v$15 !== _p$.t && (_p$.t = setProp(_el$51, "fg", _v$15, _p$.t));
|
|
2050
|
+
_v$16 !== _p$.a && (_p$.a = setProp(_el$52, "fg", _v$16, _p$.a));
|
|
2051
|
+
_v$17 !== _p$.o && (_p$.o = setProp(_el$53, "fg", _v$17, _p$.o));
|
|
2052
|
+
return _p$;
|
|
2053
|
+
}, {
|
|
2054
|
+
e: void 0,
|
|
2055
|
+
t: void 0,
|
|
2056
|
+
a: void 0,
|
|
2057
|
+
o: void 0
|
|
2058
|
+
});
|
|
2059
|
+
return _el$47;
|
|
2060
|
+
})();
|
|
2061
|
+
})();
|
|
2062
|
+
}
|
|
2063
|
+
}), null);
|
|
2064
|
+
return _el$31;
|
|
1801
2065
|
}
|
|
1802
2066
|
});
|
|
1803
2067
|
}
|
|
1804
2068
|
}), null);
|
|
1805
2069
|
effect((_p$) => {
|
|
1806
|
-
var _v$
|
|
1807
|
-
_v$
|
|
1808
|
-
_v$
|
|
1809
|
-
_v$
|
|
1810
|
-
_v$
|
|
1811
|
-
_v$
|
|
2070
|
+
var _v$8 = theme().accent, _v$9 = theme().text, _v$0 = theme().textMuted, _v$1 = theme().text, _v$10 = theme().textMuted;
|
|
2071
|
+
_v$8 !== _p$.e && (_p$.e = setProp(_el$23, "fg", _v$8, _p$.e));
|
|
2072
|
+
_v$9 !== _p$.t && (_p$.t = setProp(_el$25, "fg", _v$9, _p$.t));
|
|
2073
|
+
_v$0 !== _p$.a && (_p$.a = setProp(_el$26, "fg", _v$0, _p$.a));
|
|
2074
|
+
_v$1 !== _p$.o && (_p$.o = setProp(_el$29, "fg", _v$1, _p$.o));
|
|
2075
|
+
_v$10 !== _p$.i && (_p$.i = setProp(_el$30, "fg", _v$10, _p$.i));
|
|
1812
2076
|
return _p$;
|
|
1813
2077
|
}, {
|
|
1814
2078
|
e: void 0,
|
|
@@ -1817,7 +2081,7 @@ function View(props) {
|
|
|
1817
2081
|
o: void 0,
|
|
1818
2082
|
i: void 0
|
|
1819
2083
|
});
|
|
1820
|
-
return _el$
|
|
2084
|
+
return _el$22;
|
|
1821
2085
|
})();
|
|
1822
2086
|
}
|
|
1823
2087
|
const tui = (api, _options, _meta) => {
|
|
@@ -1837,6 +2101,8 @@ const tui = (api, _options, _meta) => {
|
|
|
1837
2101
|
const props = event?.properties ?? {};
|
|
1838
2102
|
const part = props.part ?? props.info?.part;
|
|
1839
2103
|
if (part === void 0) return;
|
|
2104
|
+
const sample = extractToolActivity(part);
|
|
2105
|
+
if (sample !== null) trackToolActivity(latestToolActivity, sample.sessionID, sample.activity);
|
|
1840
2106
|
if (reduceDelegationToolPart(liveStore.map, part)) liveStore.bump();
|
|
1841
2107
|
}));
|
|
1842
2108
|
} catch {}
|
|
@@ -1871,9 +2137,10 @@ const tui = (api, _options, _meta) => {
|
|
|
1871
2137
|
};
|
|
1872
2138
|
const plugin = {
|
|
1873
2139
|
id: "pantheon.tui",
|
|
1874
|
-
tui
|
|
2140
|
+
tui,
|
|
2141
|
+
setup: async () => {}
|
|
1875
2142
|
};
|
|
1876
2143
|
//#endregion
|
|
1877
|
-
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 };
|
|
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 };
|
|
1878
2145
|
|
|
1879
2146
|
//# sourceMappingURL=tui.js.map
|