pantheon-opencode 1.5.0-beta.1 → 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/manifest.json +21 -0
- package/CHANGELOG.md +1026 -0
- package/README.md +171 -16
- package/README.pt-BR.md +99 -13
- package/bin/pantheon-init.mjs +178 -21
- package/package.json +23 -14
- 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/doctor.mjs +178 -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 +116 -27
- package/src/plugins/tui/dist/tui.d.ts.map +1 -1
- package/src/plugins/tui/dist/tui.js +414 -150
- package/src/plugins/tui/dist/tui.js.map +1 -1
- package/src/plugins/tui/dist/tui.tsx +447 -84
- package/src/plugins/tui/package-lock.json +2 -2
- package/src/plugins/tui/package.json +1 -1
- package/src/plugins/tui/src/index.tsx +447 -84
- 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.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,16 +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
|
-
*
|
|
1318
|
-
*
|
|
1319
|
-
*
|
|
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). */
|
|
1320
1407
|
function delegationTag(entry) {
|
|
1321
|
-
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}`;
|
|
1322
1488
|
}
|
|
1323
1489
|
/** Turn child sessions (PRIMARY) enriched with md reports into the display
|
|
1324
1490
|
* list. One entry per child id (duplicates across re-fetches collapse).
|
|
@@ -1328,10 +1494,14 @@ function delegationTag(entry) {
|
|
|
1328
1494
|
* itself (fallback 'agent'), state derived from its status, startedAt from
|
|
1329
1495
|
* time.created. A report-less child is a NATIVE task() child (every
|
|
1330
1496
|
* 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 `
|
|
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.
|
|
1333
1501
|
* Terminal md state wins over the derived state; a running md defers to
|
|
1334
|
-
* 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).
|
|
1335
1505
|
* Pure — no I/O. */
|
|
1336
1506
|
function childrenToDelegationEntries(children, md, now = Date.now()) {
|
|
1337
1507
|
const byTaskID = /* @__PURE__ */ new Map();
|
|
@@ -1344,7 +1514,7 @@ function childrenToDelegationEntries(children, md, now = Date.now()) {
|
|
|
1344
1514
|
const mdEntry = byTaskID.get(child.id);
|
|
1345
1515
|
const state = mdEntry !== void 0 && mdEntry.state !== "running" ? mdEntry.state : childStatusToState(child.status);
|
|
1346
1516
|
out.push({
|
|
1347
|
-
alias: mdEntry?.alias ?? "task",
|
|
1517
|
+
alias: mdEntry?.alias ?? "native-task",
|
|
1348
1518
|
sessionID: mdEntry?.sessionID ?? "",
|
|
1349
1519
|
taskID: child.id,
|
|
1350
1520
|
agent: mdEntry?.agent ?? child.agent ?? "agent",
|
|
@@ -1352,7 +1522,7 @@ function childrenToDelegationEntries(children, md, now = Date.now()) {
|
|
|
1352
1522
|
startedAt: mdEntry?.startedAt ?? child.time?.created ?? now,
|
|
1353
1523
|
updatedAt: mdEntry?.updatedAt ?? (state === "running" || state === "stale-running" ? null : child.time?.updated ?? null),
|
|
1354
1524
|
timedOut: mdEntry?.timedOut ?? false,
|
|
1355
|
-
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",
|
|
1356
1526
|
source: mdEntry !== void 0 ? "md" : "children-only"
|
|
1357
1527
|
});
|
|
1358
1528
|
}
|
|
@@ -1395,7 +1565,11 @@ function createTuiLogger(projectRoot, module = "pantheon-tui") {
|
|
|
1395
1565
|
await mkdir(dirname(logPath), { recursive: true });
|
|
1396
1566
|
const stamp = (/* @__PURE__ */ new Date()).toISOString();
|
|
1397
1567
|
await appendFile(logPath, `${lines.map((l) => `[${stamp}] [${module}] ${l}`).join("\n")}\n`, "utf8");
|
|
1398
|
-
} catch {
|
|
1568
|
+
} catch (err) {
|
|
1569
|
+
if (echo) try {
|
|
1570
|
+
process.stderr.write(`[${module}] file-log failed: ${formatArg(err)}\n`);
|
|
1571
|
+
} catch {}
|
|
1572
|
+
}
|
|
1399
1573
|
})();
|
|
1400
1574
|
if (echo) for (const line of lines) console.log(`[${module}] ${line}`);
|
|
1401
1575
|
};
|
|
@@ -1431,6 +1605,7 @@ function DelegationRow(props) {
|
|
|
1431
1605
|
const t = theme();
|
|
1432
1606
|
switch (props.job.state) {
|
|
1433
1607
|
case "running": return t.warning;
|
|
1608
|
+
case "retry": return t.warning;
|
|
1434
1609
|
case "stale-running": return t.error;
|
|
1435
1610
|
case "completed": return t.success;
|
|
1436
1611
|
case "error": return t.error;
|
|
@@ -1439,6 +1614,7 @@ function DelegationRow(props) {
|
|
|
1439
1614
|
});
|
|
1440
1615
|
const marker = createMemo(() => {
|
|
1441
1616
|
if (props.job.state === "running") return `${delegationSpinnerFrame(props.animationNow)} `;
|
|
1617
|
+
if (props.job.state === "retry") return "⟳ ";
|
|
1442
1618
|
if (props.job.state === "stale-running") return "⚠ ";
|
|
1443
1619
|
switch (props.job.state) {
|
|
1444
1620
|
case "completed": return "✓ ";
|
|
@@ -1447,38 +1623,55 @@ function DelegationRow(props) {
|
|
|
1447
1623
|
}
|
|
1448
1624
|
});
|
|
1449
1625
|
const tagColor = createMemo(() => props.job.source === "children-only" ? theme().info : color());
|
|
1450
|
-
const
|
|
1451
|
-
|
|
1452
|
-
|
|
1453
|
-
});
|
|
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));
|
|
1454
1629
|
const open = () => {
|
|
1455
1630
|
navigateToDelegationSession(props.api.route, props.job.taskID);
|
|
1456
1631
|
};
|
|
1457
1632
|
return (() => {
|
|
1458
|
-
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");
|
|
1459
1634
|
insertNode(_el$13, _el$14);
|
|
1460
|
-
insertNode(_el$13, _el$
|
|
1635
|
+
insertNode(_el$13, _el$16);
|
|
1461
1636
|
setProp(_el$13, "onMouseDown", open);
|
|
1462
1637
|
insertNode(_el$14, _el$15);
|
|
1463
|
-
insertNode(_el$14, _el$16);
|
|
1464
|
-
insertNode(_el$14, _el$17);
|
|
1465
1638
|
setProp(_el$14, "flexDirection", "row");
|
|
1466
|
-
insert(_el$15, marker);
|
|
1467
|
-
|
|
1468
|
-
|
|
1469
|
-
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);
|
|
1470
1665
|
effect((_p$) => {
|
|
1471
|
-
var _v$5 =
|
|
1666
|
+
var _v$5 = tagColor(), _v$6 = description() !== "" ? "space-between" : "flex-end", _v$7 = theme().textMuted;
|
|
1472
1667
|
_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));
|
|
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));
|
|
1476
1670
|
return _p$;
|
|
1477
1671
|
}, {
|
|
1478
1672
|
e: void 0,
|
|
1479
1673
|
t: void 0,
|
|
1480
|
-
a: void 0
|
|
1481
|
-
o: void 0
|
|
1674
|
+
a: void 0
|
|
1482
1675
|
});
|
|
1483
1676
|
return _el$13;
|
|
1484
1677
|
})();
|
|
@@ -1560,7 +1753,7 @@ function View(props) {
|
|
|
1560
1753
|
});
|
|
1561
1754
|
if (sessionID === null) {
|
|
1562
1755
|
setChildDelegations(md);
|
|
1563
|
-
panelLog.info(
|
|
1756
|
+
panelLog.info(`${formatPanelLogLine(0, 0, 0, md.length, eventRefreshCount)} (no sessionID — history shown)`);
|
|
1564
1757
|
return;
|
|
1565
1758
|
}
|
|
1566
1759
|
let children = [];
|
|
@@ -1587,14 +1780,23 @@ function View(props) {
|
|
|
1587
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);
|
|
1588
1781
|
const liveEntries = [...props.liveStore.map.values()].filter((entry) => entry.sessionID === sessionID);
|
|
1589
1782
|
setChildDelegations(mergeChildDelegationSources(childEntries, liveEntries));
|
|
1590
|
-
|
|
1783
|
+
const counts = countDelegationSources(childEntries);
|
|
1784
|
+
panelLog.info(formatPanelLogLine(children.length, counts.pantheon, counts.native, md.length, eventRefreshCount));
|
|
1591
1785
|
} finally {
|
|
1592
1786
|
delegationsInflight = null;
|
|
1593
1787
|
}
|
|
1594
1788
|
})();
|
|
1595
1789
|
return delegationsInflight;
|
|
1596
1790
|
};
|
|
1597
|
-
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
|
+
};
|
|
1598
1800
|
onMount(() => {
|
|
1599
1801
|
const cleanup = [];
|
|
1600
1802
|
try {
|
|
@@ -1623,7 +1825,7 @@ function View(props) {
|
|
|
1623
1825
|
refreshDelegations();
|
|
1624
1826
|
}, 1e3);
|
|
1625
1827
|
cleanup.push(() => clearInterval(poll));
|
|
1626
|
-
const animation = setInterval(() => setAnimationNow(Date.now()),
|
|
1828
|
+
const animation = setInterval(() => setAnimationNow(Date.now()), 1e3);
|
|
1627
1829
|
cleanup.push(() => clearInterval(animation));
|
|
1628
1830
|
try {
|
|
1629
1831
|
const sdk = props.api.state?.session;
|
|
@@ -1643,78 +1845,78 @@ function View(props) {
|
|
|
1643
1845
|
}));
|
|
1644
1846
|
});
|
|
1645
1847
|
const HR = () => (() => {
|
|
1646
|
-
var _el$
|
|
1647
|
-
insertNode(_el$
|
|
1648
|
-
effect((_$p) => setProp(_el$
|
|
1649
|
-
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;
|
|
1650
1852
|
})();
|
|
1651
1853
|
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$
|
|
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, {
|
|
1661
1863
|
get when() {
|
|
1662
1864
|
return branch();
|
|
1663
1865
|
},
|
|
1664
1866
|
children: (b) => (() => {
|
|
1665
|
-
var _el$
|
|
1666
|
-
insert(_el$
|
|
1667
|
-
effect((_$p) => setProp(_el$
|
|
1668
|
-
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;
|
|
1669
1871
|
})()
|
|
1670
|
-
}), _el$
|
|
1671
|
-
insert(_el$
|
|
1872
|
+
}), _el$24);
|
|
1873
|
+
insert(_el$22, createComponent(Show, {
|
|
1672
1874
|
get when() {
|
|
1673
1875
|
return preset().name;
|
|
1674
1876
|
},
|
|
1675
1877
|
get fallback() {
|
|
1676
1878
|
return (() => {
|
|
1677
|
-
var _el$
|
|
1678
|
-
insertNode(_el$
|
|
1679
|
-
setProp(_el$
|
|
1680
|
-
setProp(_el$
|
|
1681
|
-
insertNode(_el$
|
|
1682
|
-
effect((_$p) => setProp(_el$
|
|
1683
|
-
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;
|
|
1684
1886
|
})();
|
|
1685
1887
|
},
|
|
1686
1888
|
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$
|
|
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 ?? ""})`);
|
|
1696
1898
|
effect((_p$) => {
|
|
1697
|
-
var _v$
|
|
1698
|
-
_v$
|
|
1699
|
-
_v$
|
|
1700
|
-
_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));
|
|
1701
1903
|
return _p$;
|
|
1702
1904
|
}, {
|
|
1703
1905
|
e: void 0,
|
|
1704
1906
|
t: void 0,
|
|
1705
1907
|
a: void 0
|
|
1706
1908
|
});
|
|
1707
|
-
return _el$
|
|
1909
|
+
return _el$36;
|
|
1708
1910
|
})()
|
|
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$
|
|
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, {
|
|
1718
1920
|
get when() {
|
|
1719
1921
|
return showSessions();
|
|
1720
1922
|
},
|
|
@@ -1725,19 +1927,19 @@ function View(props) {
|
|
|
1725
1927
|
},
|
|
1726
1928
|
get fallback() {
|
|
1727
1929
|
return (() => {
|
|
1728
|
-
var _el$
|
|
1729
|
-
insertNode(_el$
|
|
1730
|
-
setProp(_el$
|
|
1731
|
-
insertNode(_el$
|
|
1732
|
-
effect((_$p) => setProp(_el$
|
|
1733
|
-
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;
|
|
1734
1936
|
})();
|
|
1735
1937
|
},
|
|
1736
1938
|
get children() {
|
|
1737
|
-
var _el$
|
|
1738
|
-
setProp(_el$
|
|
1739
|
-
setProp(_el$
|
|
1740
|
-
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, {
|
|
1741
1943
|
get each() {
|
|
1742
1944
|
return recentSessions();
|
|
1743
1945
|
},
|
|
@@ -1748,18 +1950,18 @@ function View(props) {
|
|
|
1748
1950
|
session: ses
|
|
1749
1951
|
})
|
|
1750
1952
|
}));
|
|
1751
|
-
return _el$
|
|
1953
|
+
return _el$27;
|
|
1752
1954
|
}
|
|
1753
1955
|
});
|
|
1754
1956
|
}
|
|
1755
|
-
}), _el$
|
|
1756
|
-
insertNode(_el$
|
|
1757
|
-
insertNode(_el$
|
|
1758
|
-
setProp(_el$
|
|
1759
|
-
setProp(_el$
|
|
1760
|
-
insert(_el$
|
|
1761
|
-
insert(_el$
|
|
1762
|
-
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, {
|
|
1763
1965
|
get when() {
|
|
1764
1966
|
return showDelegations();
|
|
1765
1967
|
},
|
|
@@ -1770,19 +1972,19 @@ function View(props) {
|
|
|
1770
1972
|
},
|
|
1771
1973
|
get fallback() {
|
|
1772
1974
|
return (() => {
|
|
1773
|
-
var _el$
|
|
1774
|
-
insertNode(_el$
|
|
1775
|
-
setProp(_el$
|
|
1776
|
-
insertNode(_el$
|
|
1777
|
-
effect((_$p) => setProp(_el$
|
|
1778
|
-
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;
|
|
1779
1981
|
})();
|
|
1780
1982
|
},
|
|
1781
1983
|
get children() {
|
|
1782
|
-
var _el$
|
|
1783
|
-
setProp(_el$
|
|
1784
|
-
setProp(_el$
|
|
1785
|
-
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, {
|
|
1786
1988
|
get each() {
|
|
1787
1989
|
return visibleDelegations();
|
|
1788
1990
|
},
|
|
@@ -1798,19 +2000,79 @@ function View(props) {
|
|
|
1798
2000
|
return animationNow();
|
|
1799
2001
|
}
|
|
1800
2002
|
})
|
|
1801
|
-
}));
|
|
1802
|
-
|
|
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;
|
|
1803
2065
|
}
|
|
1804
2066
|
});
|
|
1805
2067
|
}
|
|
1806
2068
|
}), null);
|
|
1807
2069
|
effect((_p$) => {
|
|
1808
|
-
var _v$
|
|
1809
|
-
_v$
|
|
1810
|
-
_v$
|
|
1811
|
-
_v$
|
|
1812
|
-
_v$
|
|
1813
|
-
_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));
|
|
1814
2076
|
return _p$;
|
|
1815
2077
|
}, {
|
|
1816
2078
|
e: void 0,
|
|
@@ -1819,7 +2081,7 @@ function View(props) {
|
|
|
1819
2081
|
o: void 0,
|
|
1820
2082
|
i: void 0
|
|
1821
2083
|
});
|
|
1822
|
-
return _el$
|
|
2084
|
+
return _el$22;
|
|
1823
2085
|
})();
|
|
1824
2086
|
}
|
|
1825
2087
|
const tui = (api, _options, _meta) => {
|
|
@@ -1839,6 +2101,8 @@ const tui = (api, _options, _meta) => {
|
|
|
1839
2101
|
const props = event?.properties ?? {};
|
|
1840
2102
|
const part = props.part ?? props.info?.part;
|
|
1841
2103
|
if (part === void 0) return;
|
|
2104
|
+
const sample = extractToolActivity(part);
|
|
2105
|
+
if (sample !== null) trackToolActivity(latestToolActivity, sample.sessionID, sample.activity);
|
|
1842
2106
|
if (reduceDelegationToolPart(liveStore.map, part)) liveStore.bump();
|
|
1843
2107
|
}));
|
|
1844
2108
|
} catch {}
|
|
@@ -1877,6 +2141,6 @@ const plugin = {
|
|
|
1877
2141
|
setup: async () => {}
|
|
1878
2142
|
};
|
|
1879
2143
|
//#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 };
|
|
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 };
|
|
1881
2145
|
|
|
1882
2146
|
//# sourceMappingURL=tui.js.map
|