@wrongstack/tui 0.272.1 → 0.273.0
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/dist/index.d.ts +5 -0
- package/dist/index.js +1308 -211
- package/dist/index.js.map +1 -1
- package/package.json +4 -4
package/dist/index.js
CHANGED
|
@@ -786,37 +786,9 @@ function StatusBar({
|
|
|
786
786
|
mailbox.lastSubject.length > 40 ? `${mailbox.lastSubject.slice(0, 37)}\u2026` : mailbox.lastSubject
|
|
787
787
|
] })
|
|
788
788
|
] }) : null,
|
|
789
|
-
fleetAgents && fleetAgents.length > 0 ? fleetAgents.map((a, i) => (
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" }),
|
|
793
|
-
" ",
|
|
794
|
-
/* @__PURE__ */ jsx(Text, { color: a.color, bold: true, children: a.label }),
|
|
795
|
-
/* @__PURE__ */ jsx(Text, { dimColor: true, children: " " }),
|
|
796
|
-
/* @__PURE__ */ jsx(Text, { dimColor: !a.running, ...a.running ? { color: "yellow" } : {}, children: a.running ? "\u25B6" : "\xB7" }),
|
|
797
|
-
/* @__PURE__ */ jsx(Text, { dimColor: true, children: " " }),
|
|
798
|
-
/* @__PURE__ */ jsx(Text, { dimColor: true, children: fmtElapsed(a.elapsedMs) }),
|
|
799
|
-
/* @__PURE__ */ jsx(Text, { dimColor: true, children: " \xB7 " }),
|
|
800
|
-
/* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
801
|
-
a.toolCalls,
|
|
802
|
-
"t"
|
|
803
|
-
] }),
|
|
804
|
-
a.tool ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
805
|
-
/* @__PURE__ */ jsx(Text, { dimColor: true, children: " \xB7 " }),
|
|
806
|
-
/* @__PURE__ */ jsx(Text, { color: "cyan", children: a.tool })
|
|
807
|
-
] }) : null,
|
|
808
|
-
a.extensions && a.extensions > 0 ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
809
|
-
/* @__PURE__ */ jsx(Text, { dimColor: true, children: " \xB7 " }),
|
|
810
|
-
/* @__PURE__ */ jsxs(Text, { color: "yellow", children: [
|
|
811
|
-
"\u26A1\xD7",
|
|
812
|
-
a.extensions
|
|
813
|
-
] })
|
|
814
|
-
] }) : null
|
|
815
|
-
] }, i)
|
|
816
|
-
)) : null
|
|
817
|
-
] }) : fleetAgents && fleetAgents.length > 0 ? /* @__PURE__ */ jsx(Box, { flexDirection: "row", gap: 2, children: fleetAgents.map((a, i) => (
|
|
818
|
-
// biome-ignore lint/suspicious/noArrayIndexKey: agent list is stable per render
|
|
819
|
-
/* @__PURE__ */ jsxs(Text, { children: [
|
|
789
|
+
fleetAgents && fleetAgents.length > 0 ? fleetAgents.map((a, i) => /* @__PURE__ */ jsxs(Text, { children: [
|
|
790
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" }),
|
|
791
|
+
" ",
|
|
820
792
|
/* @__PURE__ */ jsx(Text, { color: a.color, bold: true, children: a.label }),
|
|
821
793
|
/* @__PURE__ */ jsx(Text, { dimColor: true, children: " " }),
|
|
822
794
|
/* @__PURE__ */ jsx(Text, { dimColor: !a.running, ...a.running ? { color: "yellow" } : {}, children: a.running ? "\u25B6" : "\xB7" }),
|
|
@@ -838,8 +810,30 @@ function StatusBar({
|
|
|
838
810
|
a.extensions
|
|
839
811
|
] })
|
|
840
812
|
] }) : null
|
|
841
|
-
] }, i)
|
|
842
|
-
|
|
813
|
+
] }, i)) : null
|
|
814
|
+
] }) : fleetAgents && fleetAgents.length > 0 ? /* @__PURE__ */ jsx(Box, { flexDirection: "row", gap: 2, children: fleetAgents.map((a, i) => /* @__PURE__ */ jsxs(Text, { children: [
|
|
815
|
+
/* @__PURE__ */ jsx(Text, { color: a.color, bold: true, children: a.label }),
|
|
816
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: " " }),
|
|
817
|
+
/* @__PURE__ */ jsx(Text, { dimColor: !a.running, ...a.running ? { color: "yellow" } : {}, children: a.running ? "\u25B6" : "\xB7" }),
|
|
818
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: " " }),
|
|
819
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: fmtElapsed(a.elapsedMs) }),
|
|
820
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: " \xB7 " }),
|
|
821
|
+
/* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
822
|
+
a.toolCalls,
|
|
823
|
+
"t"
|
|
824
|
+
] }),
|
|
825
|
+
a.tool ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
826
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: " \xB7 " }),
|
|
827
|
+
/* @__PURE__ */ jsx(Text, { color: "cyan", children: a.tool })
|
|
828
|
+
] }) : null,
|
|
829
|
+
a.extensions && a.extensions > 0 ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
830
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: " \xB7 " }),
|
|
831
|
+
/* @__PURE__ */ jsxs(Text, { color: "yellow", children: [
|
|
832
|
+
"\u26A1\xD7",
|
|
833
|
+
a.extensions
|
|
834
|
+
] })
|
|
835
|
+
] }) : null
|
|
836
|
+
] }, i)) }) : /* @__PURE__ */ jsx(Box, { height: 1, children: /* @__PURE__ */ jsx(Text, { children: " " }) })
|
|
843
837
|
]
|
|
844
838
|
}
|
|
845
839
|
);
|
|
@@ -981,10 +975,7 @@ var WAVE_COLORS = [
|
|
|
981
975
|
// flamingo
|
|
982
976
|
];
|
|
983
977
|
function WaveText({ text, phase }) {
|
|
984
|
-
return /* @__PURE__ */ jsx(Text, { bold: true, children: Array.from(text).map((ch, i) => (
|
|
985
|
-
// biome-ignore lint/suspicious/noArrayIndexKey: glyph order is positional and re-rendered each tick
|
|
986
|
-
/* @__PURE__ */ jsx(Text, { color: WAVE_COLORS[(i + phase) % WAVE_COLORS.length] ?? "#ffffff", children: ch }, i)
|
|
987
|
-
)) });
|
|
978
|
+
return /* @__PURE__ */ jsx(Text, { bold: true, children: Array.from(text).map((ch, i) => /* @__PURE__ */ jsx(Text, { color: WAVE_COLORS[(i + phase) % WAVE_COLORS.length] ?? "#ffffff", children: ch }, i)) });
|
|
988
979
|
}
|
|
989
980
|
var FILLED = "\u2588";
|
|
990
981
|
var EMPTY = "\u2591";
|
|
@@ -1183,14 +1174,11 @@ function FleetMonitor({
|
|
|
1183
1174
|
/* @__PURE__ */ jsx(Text, { bold: true, color: VERDICT_COLOR[collabSession.overallVerdict] ?? "white", children: collabSession.overallVerdict })
|
|
1184
1175
|
] }) : null
|
|
1185
1176
|
] }),
|
|
1186
|
-
collabSession.timeline.length > 0 ? /* @__PURE__ */ jsx(Box, { flexDirection: "column", marginTop: 0, children: collabSession.timeline.slice(0, 6).map((ev, i) => (
|
|
1187
|
-
|
|
1188
|
-
/* @__PURE__ */
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
/* @__PURE__ */ jsx(Text, { dimColor: true, children: ev.text })
|
|
1192
|
-
] }, i)
|
|
1193
|
-
)) }) : null
|
|
1177
|
+
collabSession.timeline.length > 0 ? /* @__PURE__ */ jsx(Box, { flexDirection: "column", marginTop: 0, children: collabSession.timeline.slice(0, 6).map((ev, i) => /* @__PURE__ */ jsxs(Box, { flexDirection: "row", gap: 1, children: [
|
|
1178
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: `${fmtElapsed(Math.max(0, nowTick - ev.at))} ago`.padEnd(10) }),
|
|
1179
|
+
/* @__PURE__ */ jsx(Text, { ...ev.color ? { color: ev.color } : {}, children: ev.icon }),
|
|
1180
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: ev.text })
|
|
1181
|
+
] }, i)) }) : null
|
|
1194
1182
|
] }) : null,
|
|
1195
1183
|
/* @__PURE__ */ jsxs(Box, { flexDirection: "row", gap: 1, children: [
|
|
1196
1184
|
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "concurrency" }),
|
|
@@ -1248,14 +1236,11 @@ function FleetMonitor({
|
|
|
1248
1236
|
] }) : null,
|
|
1249
1237
|
timeline.length > 0 ? /* @__PURE__ */ jsxs(Box, { flexDirection: "column", marginTop: 1, children: [
|
|
1250
1238
|
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "timeline" }),
|
|
1251
|
-
timeline.map((ev, i) => (
|
|
1252
|
-
|
|
1253
|
-
/* @__PURE__ */
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
/* @__PURE__ */ jsx(Text, { dimColor: true, children: ev.text })
|
|
1257
|
-
] }, i)
|
|
1258
|
-
))
|
|
1239
|
+
timeline.map((ev, i) => /* @__PURE__ */ jsxs(Box, { flexDirection: "row", gap: 1, children: [
|
|
1240
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: `${fmtElapsed(Math.max(0, nowTick - ev.at))} ago`.padEnd(10) }),
|
|
1241
|
+
/* @__PURE__ */ jsx(Text, { color: ev.color, children: ev.icon }),
|
|
1242
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: ev.text })
|
|
1243
|
+
] }, i))
|
|
1259
1244
|
] }) : null
|
|
1260
1245
|
] });
|
|
1261
1246
|
}
|
|
@@ -1570,10 +1555,7 @@ function AgentDetail({
|
|
|
1570
1555
|
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "recent" }),
|
|
1571
1556
|
entry.recentTools.slice(-4).map((tool, i) => {
|
|
1572
1557
|
const visual = getToolVisual(tool.name);
|
|
1573
|
-
return (
|
|
1574
|
-
// biome-ignore lint/suspicious/noArrayIndexKey: recent tool entries do not carry stable ids.
|
|
1575
|
-
/* @__PURE__ */ jsx(Text, { color: tool.ok === false ? "red" : visual.color, children: `\u2039${visual.glyph} ${formatRecentToolChip(tool)}\u203A` }, `${tool.name}-${tool.at}-${i}`)
|
|
1576
|
-
);
|
|
1558
|
+
return /* @__PURE__ */ jsx(Text, { color: tool.ok === false ? "red" : visual.color, children: `\u2039${visual.glyph} ${formatRecentToolChip(tool)}\u203A` }, `${tool.name}-${tool.at}-${i}`);
|
|
1577
1559
|
})
|
|
1578
1560
|
] }) : null,
|
|
1579
1561
|
entry.status === "running" && streamTail ? /* @__PURE__ */ jsx(Box, { children: /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
@@ -1853,10 +1835,7 @@ function BrainDecisionPrompt({
|
|
|
1853
1835
|
/* @__PURE__ */ jsx(Text, { color: "white", children: question }),
|
|
1854
1836
|
ctx.length > 0 ? /* @__PURE__ */ jsxs(Box, { flexDirection: "column", marginTop: 1, children: [
|
|
1855
1837
|
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "Context:" }),
|
|
1856
|
-
ctx.map((line, index) => (
|
|
1857
|
-
// biome-ignore lint/suspicious/noArrayIndexKey: context lines are static for this prompt render
|
|
1858
|
-
/* @__PURE__ */ jsx(Text, { dimColor: true, children: line }, index)
|
|
1859
|
-
))
|
|
1838
|
+
ctx.map((line, index) => /* @__PURE__ */ jsx(Text, { dimColor: true, children: line }, index))
|
|
1860
1839
|
] }) : null,
|
|
1861
1840
|
options.length > 0 ? /* @__PURE__ */ jsxs(Box, { flexDirection: "column", marginTop: 1, children: [
|
|
1862
1841
|
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "Options:" }),
|
|
@@ -3507,10 +3486,7 @@ function MarkdownView({
|
|
|
3507
3486
|
/[\u2500-\u257F]/.test(qContent) ? (
|
|
3508
3487
|
// Box-drawing characters inside blockquotes also need transparent
|
|
3509
3488
|
// background to avoid inheriting the message panel background.
|
|
3510
|
-
/* @__PURE__ */ jsx(Box, { flexDirection: "row", backgroundColor: "transparent", children: [...qContent].slice(0, (contentWidth ?? termWidth) - 2).map((ch, ci) => (
|
|
3511
|
-
/* biome-ignore lint/suspicious/noArrayIndexKey: characters are not reorderable */
|
|
3512
|
-
/* @__PURE__ */ jsx(Text, { dimColor: true, children: ch }, ci)
|
|
3513
|
-
)) })
|
|
3489
|
+
/* @__PURE__ */ jsx(Box, { flexDirection: "row", backgroundColor: "transparent", children: [...qContent].slice(0, (contentWidth ?? termWidth) - 2).map((ch, ci) => /* @__PURE__ */ jsx(Text, { dimColor: true, children: ch }, ci)) })
|
|
3514
3490
|
) : /* @__PURE__ */ jsx(InlineLine, { tokens: parseInline(qContent), dim: true })
|
|
3515
3491
|
] }, `q${key++}`)
|
|
3516
3492
|
);
|
|
@@ -3540,10 +3516,7 @@ function MarkdownView({
|
|
|
3540
3516
|
const maxW = contentWidth ?? termWidth;
|
|
3541
3517
|
const chars = [...line].slice(0, maxW);
|
|
3542
3518
|
rows.push(
|
|
3543
|
-
/* @__PURE__ */ jsx(Box, { width: maxW, backgroundColor: "transparent", flexDirection: "row", children: chars.map((ch, ci) => (
|
|
3544
|
-
/* biome-ignore lint/suspicious/noArrayIndexKey: characters are not reorderable */
|
|
3545
|
-
/* @__PURE__ */ jsx(Text, { children: ch }, ci)
|
|
3546
|
-
)) }, `bx${key++}`)
|
|
3519
|
+
/* @__PURE__ */ jsx(Box, { width: maxW, backgroundColor: "transparent", flexDirection: "row", children: chars.map((ch, ci) => /* @__PURE__ */ jsx(Text, { children: ch }, ci)) }, `bx${key++}`)
|
|
3547
3520
|
);
|
|
3548
3521
|
continue;
|
|
3549
3522
|
}
|
|
@@ -3633,6 +3606,19 @@ function formatMatchHit(hit) {
|
|
|
3633
3606
|
return void 0;
|
|
3634
3607
|
}
|
|
3635
3608
|
var ARG_BUDGET = 60;
|
|
3609
|
+
function stringArrayOf(v) {
|
|
3610
|
+
return Array.isArray(v) ? v.filter((item) => typeof item === "string") : void 0;
|
|
3611
|
+
}
|
|
3612
|
+
function fileScopeSummary(files, fallback) {
|
|
3613
|
+
const list = stringArrayOf(files);
|
|
3614
|
+
if (list && list.length > 0) {
|
|
3615
|
+
const first = list[0] ?? "";
|
|
3616
|
+
const more = list.length > 1 ? ` (+${list.length - 1})` : "";
|
|
3617
|
+
return first ? `${shortenPath(first, 42)}${more}` : `${list.length} files`;
|
|
3618
|
+
}
|
|
3619
|
+
const scalar = typeof files === "string" ? files : fallback;
|
|
3620
|
+
return scalar ? shortenPath(scalar, 44) : "";
|
|
3621
|
+
}
|
|
3636
3622
|
function formatToolArgs(toolName, input) {
|
|
3637
3623
|
if (!input || typeof input !== "object") return "";
|
|
3638
3624
|
const obj = input;
|
|
@@ -3641,13 +3627,18 @@ function formatToolArgs(toolName, input) {
|
|
|
3641
3627
|
case "write":
|
|
3642
3628
|
case "edit":
|
|
3643
3629
|
case "patch":
|
|
3644
|
-
case "document":
|
|
3645
3630
|
case "list_dir":
|
|
3646
3631
|
case "ls":
|
|
3647
3632
|
case "tree": {
|
|
3648
3633
|
const p = stringOf(obj["path"]) ?? stringOf(obj["file"]);
|
|
3649
3634
|
return p ? shortenPath(p, ARG_BUDGET) : "";
|
|
3650
3635
|
}
|
|
3636
|
+
case "document": {
|
|
3637
|
+
const target = stringOf(obj["target"]) ?? "all";
|
|
3638
|
+
const scope = fileScopeSummary(obj["files"], stringOf(obj["path"]));
|
|
3639
|
+
const style = stringOf(obj["style"]);
|
|
3640
|
+
return [target, scope, style].filter(Boolean).join(" \xB7 ");
|
|
3641
|
+
}
|
|
3651
3642
|
case "grep":
|
|
3652
3643
|
case "search":
|
|
3653
3644
|
case "replace": {
|
|
@@ -3663,12 +3654,19 @@ function formatToolArgs(toolName, input) {
|
|
|
3663
3654
|
}
|
|
3664
3655
|
case "bash":
|
|
3665
3656
|
case "shell":
|
|
3666
|
-
case "exec":
|
|
3667
3657
|
case "install":
|
|
3668
3658
|
case "git": {
|
|
3669
3659
|
const cmd = stringOf(obj["command"]) ?? stringOf(obj["args"]);
|
|
3670
3660
|
return cmd ? truncMid(cmd, ARG_BUDGET) : "";
|
|
3671
3661
|
}
|
|
3662
|
+
case "exec": {
|
|
3663
|
+
const command = stringOf(obj["command"]);
|
|
3664
|
+
const args = stringArrayOf(obj["args"]) ?? [];
|
|
3665
|
+
const cwd = stringOf(obj["cwd"]);
|
|
3666
|
+
const cmd = [command, ...args].filter(Boolean).join(" ");
|
|
3667
|
+
const head = cmd ? truncMid(cmd, cwd ? 44 : ARG_BUDGET) : "";
|
|
3668
|
+
return cwd ? `${head} in ${shortenPath(cwd, 14)}` : head;
|
|
3669
|
+
}
|
|
3672
3670
|
case "diff": {
|
|
3673
3671
|
const files = Array.isArray(obj["files"]) ? obj["files"] : void 0;
|
|
3674
3672
|
if (files && files.length > 0) {
|
|
@@ -3690,6 +3688,19 @@ function formatToolArgs(toolName, input) {
|
|
|
3690
3688
|
if (Array.isArray(list)) return `${list.length} item${list.length === 1 ? "" : "s"}`;
|
|
3691
3689
|
return "";
|
|
3692
3690
|
}
|
|
3691
|
+
case "plan": {
|
|
3692
|
+
const action = stringOf(obj["action"]) ?? "show";
|
|
3693
|
+
const target = stringOf(obj["target"]) ?? stringOf(obj["title"]) ?? stringOf(obj["template"]) ?? "";
|
|
3694
|
+
const scope = stringOf(obj["scope"]);
|
|
3695
|
+
return [action, target ? truncMid(target, 34) : "", scope].filter(Boolean).join(" \xB7 ");
|
|
3696
|
+
}
|
|
3697
|
+
case "task": {
|
|
3698
|
+
const action = stringOf(obj["action"]) ?? "show";
|
|
3699
|
+
const task = obj["task"] && typeof obj["task"] === "object" ? obj["task"] : void 0;
|
|
3700
|
+
const target = stringOf(obj["target"]) ?? stringOf(obj["id"]) ?? stringOf(task?.["title"]) ?? (Array.isArray(obj["tasks"]) ? `${obj["tasks"].length} tasks` : "");
|
|
3701
|
+
const status = stringOf(obj["status"]);
|
|
3702
|
+
return [action, target ? truncMid(target, 32) : "", status].filter(Boolean).join(" \xB7 ");
|
|
3703
|
+
}
|
|
3693
3704
|
case "lint":
|
|
3694
3705
|
case "format":
|
|
3695
3706
|
case "typecheck":
|
|
@@ -3717,19 +3728,79 @@ function formatToolArgs(toolName, input) {
|
|
|
3717
3728
|
if (tmpl && name) return `${tmpl} \u2192 ${truncMid(name, ARG_BUDGET - tmpl.length - 4)}`;
|
|
3718
3729
|
return name ?? tmpl ?? "";
|
|
3719
3730
|
}
|
|
3720
|
-
case "remember":
|
|
3721
|
-
|
|
3731
|
+
case "remember": {
|
|
3732
|
+
const scope = stringOf(obj["scope"]);
|
|
3733
|
+
const type = stringOf(obj["type"]);
|
|
3734
|
+
const text = stringOf(obj["text"]);
|
|
3735
|
+
return [scope, type, text ? truncMid(text, 34) : ""].filter(Boolean).join(" \xB7 ");
|
|
3736
|
+
}
|
|
3737
|
+
case "forget": {
|
|
3738
|
+
const query = stringOf(obj["query"]);
|
|
3739
|
+
const scope = stringOf(obj["scope"]);
|
|
3740
|
+
return [query ? `"${truncMid(query, 36)}"` : "", scope].filter(Boolean).join(" \xB7 ");
|
|
3741
|
+
}
|
|
3742
|
+
case "search_memory":
|
|
3743
|
+
case "find_related_memories": {
|
|
3744
|
+
const query = stringOf(obj["query"]) ?? stringOf(obj["text"]);
|
|
3745
|
+
const scope = stringOf(obj["scope"]);
|
|
3746
|
+
return [query ? `"${truncMid(query, 36)}"` : "", scope].filter(Boolean).join(" \xB7 ");
|
|
3747
|
+
}
|
|
3722
3748
|
case "memory": {
|
|
3723
3749
|
const key = stringOf(obj["key"]) ?? stringOf(obj["name"]);
|
|
3724
3750
|
return key ? truncMid(key, ARG_BUDGET) : "";
|
|
3725
3751
|
}
|
|
3726
3752
|
case "mode": {
|
|
3753
|
+
const action = stringOf(obj["action"]);
|
|
3727
3754
|
const m = stringOf(obj["mode"]) ?? stringOf(obj["name"]);
|
|
3728
|
-
return m
|
|
3755
|
+
return [action, m].filter(Boolean).join(" \xB7 ");
|
|
3729
3756
|
}
|
|
3730
3757
|
case "logs": {
|
|
3731
3758
|
const target = stringOf(obj["target"]) ?? stringOf(obj["service"]) ?? stringOf(obj["path"]);
|
|
3732
|
-
|
|
3759
|
+
const filter = stringOf(obj["filter"]);
|
|
3760
|
+
const since = stringOf(obj["since"]);
|
|
3761
|
+
const lines = typeof obj["lines"] === "number" ? `${obj["lines"]} lines` : "";
|
|
3762
|
+
return [target ? shortenPath(target, 34) : "", filter ? `/${truncMid(filter, 16)}/` : "", since, lines].filter(Boolean).join(" \xB7 ");
|
|
3763
|
+
}
|
|
3764
|
+
case "tool_help": {
|
|
3765
|
+
const tool = stringOf(obj["tool"]) ?? "all";
|
|
3766
|
+
const format = stringOf(obj["format"]);
|
|
3767
|
+
return [tool, format].filter(Boolean).join(" \xB7 ");
|
|
3768
|
+
}
|
|
3769
|
+
case "tool_search": {
|
|
3770
|
+
const query = stringOf(obj["query"]);
|
|
3771
|
+
const tags = stringArrayOf(obj["tags"]);
|
|
3772
|
+
const filters = [
|
|
3773
|
+
query ? `"${truncMid(query, 28)}"` : "",
|
|
3774
|
+
tags && tags.length > 0 ? tags.join(",") : "",
|
|
3775
|
+
stringOf(obj["permission"]),
|
|
3776
|
+
typeof obj["mutating"] === "boolean" ? obj["mutating"] ? "mutating" : "read-only" : ""
|
|
3777
|
+
].filter(Boolean);
|
|
3778
|
+
return filters.join(" \xB7 ");
|
|
3779
|
+
}
|
|
3780
|
+
case "tool_use": {
|
|
3781
|
+
const tool = stringOf(obj["tool"]);
|
|
3782
|
+
return tool ? `call ${tool}` : "";
|
|
3783
|
+
}
|
|
3784
|
+
case "batch_tool_use": {
|
|
3785
|
+
const calls = Array.isArray(obj["calls"]) ? obj["calls"] : [];
|
|
3786
|
+
const mode = obj["parallel"] === false ? "sequential" : "parallel";
|
|
3787
|
+
return `${calls.length} call${calls.length === 1 ? "" : "s"} \xB7 ${mode}`;
|
|
3788
|
+
}
|
|
3789
|
+
case "codebase-index": {
|
|
3790
|
+
const langs = stringArrayOf(obj["langs"]);
|
|
3791
|
+
const force = obj["force"] === true ? "force" : "";
|
|
3792
|
+
return [force, langs && langs.length > 0 ? langs.join(",") : "incremental"].filter(Boolean).join(" \xB7 ");
|
|
3793
|
+
}
|
|
3794
|
+
case "codebase-search": {
|
|
3795
|
+
const query = stringOf(obj["query"]);
|
|
3796
|
+
const filters = [stringOf(obj["kind"]), stringOf(obj["lang"]), stringOf(obj["file"]) ? `in ${shortenPath(String(obj["file"]), 24)}` : ""].filter(Boolean).join(" \xB7 ");
|
|
3797
|
+
return [query ? `"${truncMid(query, 30)}"` : "", filters].filter(Boolean).join(" \xB7 ");
|
|
3798
|
+
}
|
|
3799
|
+
case "codebase-stats":
|
|
3800
|
+
return "index health";
|
|
3801
|
+
case "set_working_dir": {
|
|
3802
|
+
const p = stringOf(obj["path"]);
|
|
3803
|
+
return p ? shortenPath(p, ARG_BUDGET) : "current";
|
|
3733
3804
|
}
|
|
3734
3805
|
}
|
|
3735
3806
|
for (const key of ["path", "file", "url", "name", "query", "pattern", "command"]) {
|
|
@@ -4102,6 +4173,716 @@ function formatToolOutput(toolName, output, ok, _outputBytes, outputLines) {
|
|
|
4102
4173
|
const collapsed = text.replace(/\s+/g, " ").trim();
|
|
4103
4174
|
return [truncMid(collapsed, GENERIC_BUDGET)];
|
|
4104
4175
|
}
|
|
4176
|
+
var VISUAL_MAX_LINES = 7;
|
|
4177
|
+
var VISUAL_TEXT_BUDGET = 92;
|
|
4178
|
+
function formatToolVisualOutput(toolName, output, ok, input) {
|
|
4179
|
+
if (!output) return void 0;
|
|
4180
|
+
const text = output.trim();
|
|
4181
|
+
if (!text) return void 0;
|
|
4182
|
+
if (toolName === "read") return visualRead(text);
|
|
4183
|
+
if (toolName === "grep" || toolName === "search") return visualSearch(toolName, text);
|
|
4184
|
+
if (toolName === "glob") return visualPathList(toolName, text);
|
|
4185
|
+
if (toolName === "tree") return visualTree(text);
|
|
4186
|
+
if (toolName === "bash" || toolName === "shell" || toolName === "git" || toolName === "exec" || toolName === "install") {
|
|
4187
|
+
return visualCommand(toolName, text, ok);
|
|
4188
|
+
}
|
|
4189
|
+
if (toolName === "test" || toolName === "lint" || toolName === "typecheck" || toolName === "format") {
|
|
4190
|
+
return visualVerifier(toolName, text, ok);
|
|
4191
|
+
}
|
|
4192
|
+
if (toolName === "fetch" || toolName === "webfetch" || toolName === "web_fetch") {
|
|
4193
|
+
return visualFetch(text);
|
|
4194
|
+
}
|
|
4195
|
+
if (toolName === "json") return visualJson(text);
|
|
4196
|
+
if (toolName === "outdated") return visualOutdated(text);
|
|
4197
|
+
if (toolName === "audit") return visualAudit(text);
|
|
4198
|
+
if (toolName === "scaffold") return visualScaffold(text);
|
|
4199
|
+
if (toolName === "todo") return visualTodo(text);
|
|
4200
|
+
if (toolName === "task" || toolName === "plan") return visualWorkBoard(toolName, text, ok);
|
|
4201
|
+
if (toolName === "remember" || toolName === "forget" || toolName === "search_memory" || toolName === "find_related_memories") {
|
|
4202
|
+
return visualMemory(toolName, text, ok);
|
|
4203
|
+
}
|
|
4204
|
+
if (toolName === "logs") return visualLogs(text);
|
|
4205
|
+
if (toolName === "document") return visualDocument(text);
|
|
4206
|
+
if (toolName === "tool_help" || toolName === "tool_search") return visualToolCatalog(toolName, text);
|
|
4207
|
+
if (toolName === "tool_use" || toolName === "batch_tool_use") return visualMetaExecution(toolName, text, ok);
|
|
4208
|
+
if (toolName === "codebase-index" || toolName === "codebase-search" || toolName === "codebase-stats") {
|
|
4209
|
+
return visualCodebase(toolName, text, ok);
|
|
4210
|
+
}
|
|
4211
|
+
if (toolName === "set_working_dir") return visualWorkingDir(text, ok);
|
|
4212
|
+
if (toolName === "mode") return visualMode(text, ok);
|
|
4213
|
+
return void 0;
|
|
4214
|
+
}
|
|
4215
|
+
function ToolOutputLines({ lines, hasFollowingBlock }) {
|
|
4216
|
+
return /* @__PURE__ */ jsx(Fragment, { children: lines.map((line, i) => {
|
|
4217
|
+
const branch = i === lines.length - 1 && !hasFollowingBlock ? " \u2514\u2500 " : " \u251C\u2500 ";
|
|
4218
|
+
const color = colorForVisualKind(line.kind);
|
|
4219
|
+
return /* @__PURE__ */ jsxs(Text, { children: [
|
|
4220
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: branch }),
|
|
4221
|
+
line.marker ? /* @__PURE__ */ jsx(Text, { color, bold: true, children: line.marker }) : null,
|
|
4222
|
+
line.path ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
4223
|
+
/* @__PURE__ */ jsx(Text, { color: "cyan", children: shortenPath(line.path, 56) }),
|
|
4224
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: " " })
|
|
4225
|
+
] }) : null,
|
|
4226
|
+
line.lineNo ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
4227
|
+
/* @__PURE__ */ jsx(Text, { color: "yellow", children: String(line.lineNo).padStart(4, " ") }),
|
|
4228
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: " \u2502 " })
|
|
4229
|
+
] }) : null,
|
|
4230
|
+
/* @__PURE__ */ jsx(Text, { color, dimColor: line.kind === "meta" || line.kind === "stdout", children: truncMid(line.text, VISUAL_TEXT_BUDGET) })
|
|
4231
|
+
] }, `${line.kind}-${i}`);
|
|
4232
|
+
}) });
|
|
4233
|
+
}
|
|
4234
|
+
function colorForVisualKind(kind) {
|
|
4235
|
+
switch (kind) {
|
|
4236
|
+
case "ok":
|
|
4237
|
+
return "green";
|
|
4238
|
+
case "warn":
|
|
4239
|
+
return "yellow";
|
|
4240
|
+
case "error":
|
|
4241
|
+
case "stderr":
|
|
4242
|
+
return "red";
|
|
4243
|
+
case "path":
|
|
4244
|
+
case "match":
|
|
4245
|
+
return "cyan";
|
|
4246
|
+
case "code":
|
|
4247
|
+
return "white";
|
|
4248
|
+
case "stdout":
|
|
4249
|
+
case "meta":
|
|
4250
|
+
return void 0;
|
|
4251
|
+
}
|
|
4252
|
+
}
|
|
4253
|
+
function visualRead(text) {
|
|
4254
|
+
const lines = bodyLines(text);
|
|
4255
|
+
const numbered = lines.map((line) => line.match(/^\s*(\d+)→(.*)$/)).filter((match) => Boolean(match?.[1]));
|
|
4256
|
+
if (numbered.length === 0) {
|
|
4257
|
+
const first = firstNonEmpty(lines.join("\n"));
|
|
4258
|
+
return first ? [{ kind: "meta", text: first }] : void 0;
|
|
4259
|
+
}
|
|
4260
|
+
const rows = numbered.slice(0, 5).map((match) => ({
|
|
4261
|
+
kind: "code",
|
|
4262
|
+
lineNo: match[1],
|
|
4263
|
+
text: match[2] ?? ""
|
|
4264
|
+
}));
|
|
4265
|
+
if (numbered.length > rows.length) {
|
|
4266
|
+
rows.push({ kind: "meta", text: `${numbered.length - rows.length} more read line(s)` });
|
|
4267
|
+
}
|
|
4268
|
+
return rows;
|
|
4269
|
+
}
|
|
4270
|
+
function visualSearch(toolName, text) {
|
|
4271
|
+
const json = tryParseJson(text);
|
|
4272
|
+
if (json && typeof json === "object") {
|
|
4273
|
+
const obj = json;
|
|
4274
|
+
const matches = Array.isArray(obj["matches"]) ? obj["matches"] : Array.isArray(obj["results"]) ? obj["results"] : [];
|
|
4275
|
+
return visualSearchMatches(matches, numOf(obj["count"]) ?? matches.length);
|
|
4276
|
+
}
|
|
4277
|
+
const lines = bodyLines(text);
|
|
4278
|
+
if (lines.length === 0 || lines[0] === "(no matches)") return void 0;
|
|
4279
|
+
const rows = [];
|
|
4280
|
+
let currentPath;
|
|
4281
|
+
let consumed = 0;
|
|
4282
|
+
for (const line of lines) {
|
|
4283
|
+
if (consumed >= VISUAL_MAX_LINES) break;
|
|
4284
|
+
const fileHeader = line.match(/^(.+?) \((\d+) match\(es\), showing \d+\)$/);
|
|
4285
|
+
if (fileHeader?.[1]) {
|
|
4286
|
+
currentPath = fileHeader[1];
|
|
4287
|
+
rows.push({ kind: "path", path: currentPath, text: `${fileHeader[2] ?? "?"} match(es)` });
|
|
4288
|
+
consumed++;
|
|
4289
|
+
continue;
|
|
4290
|
+
}
|
|
4291
|
+
const direct = line.match(/^(.+?):(\d+):(.*)$/);
|
|
4292
|
+
const grouped = line.match(/^(\d+):(.*)$/);
|
|
4293
|
+
if (direct?.[1] && direct[2]) {
|
|
4294
|
+
rows.push({ kind: "match", path: direct[1], lineNo: direct[2], text: direct[3] ?? "" });
|
|
4295
|
+
consumed++;
|
|
4296
|
+
} else if (grouped?.[1]) {
|
|
4297
|
+
rows.push({ kind: "match", path: currentPath, lineNo: grouped[1], text: grouped[2] ?? "" });
|
|
4298
|
+
consumed++;
|
|
4299
|
+
} else if (line.trim() && !line.startsWith(`${toolName}:`)) {
|
|
4300
|
+
rows.push({ kind: "meta", text: line.trim() });
|
|
4301
|
+
consumed++;
|
|
4302
|
+
}
|
|
4303
|
+
}
|
|
4304
|
+
if (lines.length > consumed) rows.push({ kind: "meta", text: `${lines.length - consumed} more result line(s)` });
|
|
4305
|
+
return rows.length > 0 ? rows : void 0;
|
|
4306
|
+
}
|
|
4307
|
+
function visualSearchMatches(matches, count) {
|
|
4308
|
+
if (count === 0) return [{ kind: "ok", marker: "ok ", text: "no matches" }];
|
|
4309
|
+
const rows = [];
|
|
4310
|
+
for (const match of matches.slice(0, VISUAL_MAX_LINES)) {
|
|
4311
|
+
const hit = parseMatchHit(match);
|
|
4312
|
+
if (hit) rows.push({ kind: "match", path: hit.path, lineNo: hit.line, text: hit.text });
|
|
4313
|
+
}
|
|
4314
|
+
if (rows.length === 0) return count > 0 ? [{ kind: "meta", text: `${count} result${count === 1 ? "" : "s"}` }] : void 0;
|
|
4315
|
+
if (count > rows.length) rows.push({ kind: "meta", text: `${count - rows.length} more result(s)` });
|
|
4316
|
+
return rows;
|
|
4317
|
+
}
|
|
4318
|
+
function parseMatchHit(hit) {
|
|
4319
|
+
if (typeof hit === "string") {
|
|
4320
|
+
const m = hit.match(/^(.+?):(\d+):(.*)$/);
|
|
4321
|
+
return m?.[1] && m[2] ? { path: m[1], line: m[2], text: m[3] ?? "" } : { text: hit };
|
|
4322
|
+
}
|
|
4323
|
+
if (hit && typeof hit === "object") {
|
|
4324
|
+
const o = hit;
|
|
4325
|
+
const path7 = stringOf(o["file"]) ?? stringOf(o["path"]) ?? stringOf(o["url"]);
|
|
4326
|
+
const line = numOf(o["line"]) ?? numOf(o["lineNumber"]);
|
|
4327
|
+
const title = stringOf(o["title"]);
|
|
4328
|
+
const snippet2 = stringOf(o["snippet"]);
|
|
4329
|
+
const text = stringOf(o["text"]) ?? stringOf(o["match"]) ?? stringOf(o["preview"]) ?? [title, snippet2].filter(Boolean).join(" \u2014 ");
|
|
4330
|
+
return { path: path7, line: line === void 0 ? void 0 : String(line), text };
|
|
4331
|
+
}
|
|
4332
|
+
return void 0;
|
|
4333
|
+
}
|
|
4334
|
+
function visualPathList(toolName, text) {
|
|
4335
|
+
const json = tryParseJson(text);
|
|
4336
|
+
const files = json && typeof json === "object" && Array.isArray(json["files"]) ? json["files"].filter((v) => typeof v === "string") : bodyLines(text).filter((line) => line.trim() && !line.startsWith(`${toolName}:`));
|
|
4337
|
+
if (files.length === 0) return void 0;
|
|
4338
|
+
const rows = files.slice(0, VISUAL_MAX_LINES).map((file) => ({
|
|
4339
|
+
kind: "path",
|
|
4340
|
+
path: file,
|
|
4341
|
+
text: ""
|
|
4342
|
+
}));
|
|
4343
|
+
if (files.length > rows.length) rows.push({ kind: "meta", text: `${files.length - rows.length} more path(s)` });
|
|
4344
|
+
return rows;
|
|
4345
|
+
}
|
|
4346
|
+
function visualTree(text) {
|
|
4347
|
+
const lines = bodyLines(text).filter((line) => line.trim());
|
|
4348
|
+
if (lines.length === 0) return void 0;
|
|
4349
|
+
const rows = lines.slice(0, VISUAL_MAX_LINES).map((line) => ({
|
|
4350
|
+
kind: line.includes("\u2500\u2500") || line.includes("|--") ? "path" : "meta",
|
|
4351
|
+
text: line
|
|
4352
|
+
}));
|
|
4353
|
+
if (lines.length > rows.length) rows.push({ kind: "meta", text: `${lines.length - rows.length} more tree line(s)` });
|
|
4354
|
+
return rows;
|
|
4355
|
+
}
|
|
4356
|
+
function visualCommand(toolName, text, ok) {
|
|
4357
|
+
const json = tryParseJson(text);
|
|
4358
|
+
if (json && typeof json === "object") {
|
|
4359
|
+
const obj = json;
|
|
4360
|
+
return commandRows({
|
|
4361
|
+
exit: numOf(obj["exit_code"]) ?? numOf(obj["exitCode"]),
|
|
4362
|
+
timedOut: obj["timed_out"] === true || obj["timedOut"] === true,
|
|
4363
|
+
stdout: stringOf(obj["stdout"]) ?? stringOf(obj["output"]),
|
|
4364
|
+
stderr: stringOf(obj["stderr"]) ?? stringOf(obj["error"]),
|
|
4365
|
+
ok
|
|
4366
|
+
});
|
|
4367
|
+
}
|
|
4368
|
+
const header = parseHeaderLine(text);
|
|
4369
|
+
const sections = parseNamedSections(text);
|
|
4370
|
+
return commandRows({
|
|
4371
|
+
exit: numberFromParsedField(header.fields, "exit_code") ?? numberFromParsedField(header.fields, "exitCode"),
|
|
4372
|
+
timedOut: header.fields["timed_out"] === "true" || header.fields["timedOut"] === "true",
|
|
4373
|
+
stdout: sections.get("stdout") ?? sections.get("output"),
|
|
4374
|
+
stderr: sections.get("stderr") ?? sections.get("error"),
|
|
4375
|
+
ok,
|
|
4376
|
+
label: toolName
|
|
4377
|
+
});
|
|
4378
|
+
}
|
|
4379
|
+
function commandRows(opts) {
|
|
4380
|
+
const rows = [];
|
|
4381
|
+
const statusKind = opts.timedOut ? "warn" : opts.ok && (opts.exit ?? 0) === 0 ? "ok" : "error";
|
|
4382
|
+
const status = opts.timedOut ? "timed out" : opts.exit !== void 0 ? `exit ${opts.exit}` : opts.ok ? "completed" : "failed";
|
|
4383
|
+
rows.push({ kind: statusKind, marker: statusKind === "ok" ? "ok " : statusKind === "warn" ? "! " : "x ", text: opts.label ? `${opts.label} ${status}` : status });
|
|
4384
|
+
appendOutputPreview(rows, opts.stdout, "stdout");
|
|
4385
|
+
appendOutputPreview(rows, opts.stderr, "stderr");
|
|
4386
|
+
return rows.length > 0 ? rows.slice(0, VISUAL_MAX_LINES) : void 0;
|
|
4387
|
+
}
|
|
4388
|
+
function visualVerifier(toolName, text, ok) {
|
|
4389
|
+
const json = tryParseJson(text);
|
|
4390
|
+
if (json && typeof json === "object") {
|
|
4391
|
+
const obj = json;
|
|
4392
|
+
const errors = numOf(obj["errors"]) ?? numOf(obj["failed"]) ?? 0;
|
|
4393
|
+
const warnings = numOf(obj["warnings"]) ?? 0;
|
|
4394
|
+
const changed2 = numOf(obj["files_changed"]) ?? 0;
|
|
4395
|
+
const statusKind2 = !ok || errors > 0 ? "error" : changed2 > 0 ? "warn" : "ok";
|
|
4396
|
+
const parts = [
|
|
4397
|
+
toolName,
|
|
4398
|
+
errors > 0 ? `${errors} error${errors === 1 ? "" : "s"}` : void 0,
|
|
4399
|
+
warnings > 0 ? `${warnings} warning${warnings === 1 ? "" : "s"}` : void 0,
|
|
4400
|
+
changed2 > 0 ? `${changed2} changed` : void 0,
|
|
4401
|
+
toolName === "test" ? `${numOf(obj["passed"]) ?? 0}/${numOf(obj["tests_run"]) ?? 0} passed` : void 0
|
|
4402
|
+
].filter(Boolean);
|
|
4403
|
+
return [{ kind: statusKind2, marker: statusKind2 === "ok" ? "ok " : statusKind2 === "warn" ? "! " : "x ", text: parts.join(" \xB7 ") || toolName }];
|
|
4404
|
+
}
|
|
4405
|
+
const header = parseHeaderLine(text);
|
|
4406
|
+
const sections = parseNamedSections(text);
|
|
4407
|
+
const report = sections.get("report") ?? "";
|
|
4408
|
+
const errorContext = sections.get("error_context");
|
|
4409
|
+
const fields = { ...header.fields, ...parseKeyValueLines(report) };
|
|
4410
|
+
const status = fields["status"];
|
|
4411
|
+
const errorCount = numberFromParsedField(fields, "errors") ?? numberFromParsedField(fields, "failed") ?? 0;
|
|
4412
|
+
const warningCount = numberFromParsedField(fields, "warnings") ?? 0;
|
|
4413
|
+
const changed = numberFromParsedField(fields, "files_changed") ?? 0;
|
|
4414
|
+
const statusKind = !ok || errorContext || errorCount > 0 ? "error" : status === "changed" || changed > 0 ? "warn" : "ok";
|
|
4415
|
+
const rows = [{
|
|
4416
|
+
kind: statusKind,
|
|
4417
|
+
marker: statusKind === "ok" ? "ok " : statusKind === "warn" ? "! " : "x ",
|
|
4418
|
+
text: [
|
|
4419
|
+
toolName,
|
|
4420
|
+
status ? `status=${status}` : void 0,
|
|
4421
|
+
errorCount > 0 ? `${errorCount} error${errorCount === 1 ? "" : "s"}` : void 0,
|
|
4422
|
+
warningCount > 0 ? `${warningCount} warning${warningCount === 1 ? "" : "s"}` : void 0,
|
|
4423
|
+
changed > 0 ? `${changed} changed` : void 0
|
|
4424
|
+
].filter(Boolean).join(" \xB7 ")
|
|
4425
|
+
}];
|
|
4426
|
+
appendOutputPreview(rows, errorContext, "stderr");
|
|
4427
|
+
return rows.slice(0, VISUAL_MAX_LINES);
|
|
4428
|
+
}
|
|
4429
|
+
function visualFetch(text) {
|
|
4430
|
+
const json = tryParseJson(text);
|
|
4431
|
+
if (json && typeof json === "object") {
|
|
4432
|
+
const obj = json;
|
|
4433
|
+
const status = numOf(obj["status"]);
|
|
4434
|
+
const ct = stringOf(obj["content_type"]);
|
|
4435
|
+
const content = stringOf(obj["content"]);
|
|
4436
|
+
return fetchRows(status, ct, content);
|
|
4437
|
+
}
|
|
4438
|
+
const header = parseHeaderLine(text);
|
|
4439
|
+
return fetchRows(
|
|
4440
|
+
numberFromParsedField(header.fields, "status"),
|
|
4441
|
+
header.fields["content_type"],
|
|
4442
|
+
bodyLines(text).join("\n")
|
|
4443
|
+
);
|
|
4444
|
+
}
|
|
4445
|
+
function fetchRows(status, contentType, content) {
|
|
4446
|
+
const kind = status === void 0 ? "meta" : status >= 200 && status < 300 ? "ok" : status >= 300 && status < 400 ? "warn" : "error";
|
|
4447
|
+
const rows = [{
|
|
4448
|
+
kind,
|
|
4449
|
+
marker: kind === "ok" ? "ok " : kind === "warn" ? "! " : kind === "error" ? "x " : void 0,
|
|
4450
|
+
text: [status !== void 0 ? `HTTP ${status}` : "HTTP", contentType?.split(";")[0]].filter(Boolean).join(" \xB7 ")
|
|
4451
|
+
}];
|
|
4452
|
+
const preview = firstNonEmpty(content ?? "");
|
|
4453
|
+
if (preview) rows.push({ kind: "stdout", text: preview });
|
|
4454
|
+
return rows;
|
|
4455
|
+
}
|
|
4456
|
+
function visualJson(text) {
|
|
4457
|
+
const json = tryParseJson(text);
|
|
4458
|
+
if (!json || typeof json !== "object" || Array.isArray(json)) return void 0;
|
|
4459
|
+
const obj = json;
|
|
4460
|
+
const err = stringOf(obj["error"]);
|
|
4461
|
+
if (err) return [{ kind: "error", marker: "x ", text: err }];
|
|
4462
|
+
const type = stringOf(obj["type"]);
|
|
4463
|
+
const keys = Array.isArray(obj["keys"]) ? obj["keys"].length : void 0;
|
|
4464
|
+
return [{ kind: "ok", marker: "ok ", text: [type ?? "json", keys !== void 0 ? `${keys} key${keys === 1 ? "" : "s"}` : void 0].filter(Boolean).join(" \xB7 ") }];
|
|
4465
|
+
}
|
|
4466
|
+
function visualOutdated(text) {
|
|
4467
|
+
const lines = bodyLines(text).filter((line) => line.trim() && !line.startsWith("outdated"));
|
|
4468
|
+
if (lines.length === 0) return void 0;
|
|
4469
|
+
return lines.slice(0, VISUAL_MAX_LINES).map((line) => ({ kind: "warn", marker: "! ", text: line }));
|
|
4470
|
+
}
|
|
4471
|
+
function visualAudit(text) {
|
|
4472
|
+
const lines = bodyLines(text).filter((line) => line.trim() && !line.startsWith("audit"));
|
|
4473
|
+
if (lines.length === 0) return void 0;
|
|
4474
|
+
return lines.slice(0, VISUAL_MAX_LINES).map((line) => ({
|
|
4475
|
+
kind: /^critical|^high/i.test(line) ? "error" : /^moderate|^medium/i.test(line) ? "warn" : "meta",
|
|
4476
|
+
marker: /^critical|^high/i.test(line) ? "x " : /^moderate|^medium/i.test(line) ? "! " : void 0,
|
|
4477
|
+
text: line
|
|
4478
|
+
}));
|
|
4479
|
+
}
|
|
4480
|
+
function visualScaffold(text) {
|
|
4481
|
+
const json = tryParseJson(text);
|
|
4482
|
+
if (!json || typeof json !== "object") return void 0;
|
|
4483
|
+
const obj = json;
|
|
4484
|
+
const created = Array.isArray(obj["created"]) ? obj["created"] : [];
|
|
4485
|
+
const skipped = Array.isArray(obj["skipped"]) ? obj["skipped"] : [];
|
|
4486
|
+
const rows = [];
|
|
4487
|
+
for (const file of created.slice(0, 5)) {
|
|
4488
|
+
if (typeof file === "string") rows.push({ kind: "ok", marker: "+ ", path: file, text: "" });
|
|
4489
|
+
}
|
|
4490
|
+
if (skipped.length > 0) rows.push({ kind: "warn", marker: "! ", text: `${skipped.length} skipped` });
|
|
4491
|
+
return rows.length > 0 ? rows : void 0;
|
|
4492
|
+
}
|
|
4493
|
+
function visualTodo(text) {
|
|
4494
|
+
const json = tryParseJson(text);
|
|
4495
|
+
const fields = json && typeof json === "object" && !Array.isArray(json) ? recordToStringFields(json) : parseHeaderLine(text).fields;
|
|
4496
|
+
const count = numberFromParsedField(fields, "count") ?? 0;
|
|
4497
|
+
const inProgress = numberFromParsedField(fields, "in_progress") ?? 0;
|
|
4498
|
+
return [{
|
|
4499
|
+
kind: count > 0 ? "ok" : "meta",
|
|
4500
|
+
marker: count > 0 ? "ok " : void 0,
|
|
4501
|
+
text: `${count} todo${count === 1 ? "" : "s"}${inProgress > 0 ? ` \xB7 ${inProgress} in progress` : ""}`
|
|
4502
|
+
}];
|
|
4503
|
+
}
|
|
4504
|
+
function visualWorkBoard(toolName, text, ok) {
|
|
4505
|
+
const json = tryParseJson(text);
|
|
4506
|
+
if (json && typeof json === "object" && !Array.isArray(json)) {
|
|
4507
|
+
const obj = json;
|
|
4508
|
+
const rows2 = boardSummaryRows(toolName, recordToStringFields(obj), ok);
|
|
4509
|
+
appendBoardPreview(rows2, stringOf(obj["message"]));
|
|
4510
|
+
appendBoardPreview(rows2, stringOf(obj["plan"]));
|
|
4511
|
+
const todos = Array.isArray(obj["todos"]) ? obj["todos"] : [];
|
|
4512
|
+
for (const todo of todos.slice(0, 3)) {
|
|
4513
|
+
if (todo && typeof todo === "object") {
|
|
4514
|
+
const o = todo;
|
|
4515
|
+
rows2.push({ kind: "path", marker: "+ ", text: stringOf(o["content"]) ?? stringOf(o["id"]) ?? "todo" });
|
|
4516
|
+
}
|
|
4517
|
+
}
|
|
4518
|
+
return rows2.slice(0, VISUAL_MAX_LINES);
|
|
4519
|
+
}
|
|
4520
|
+
const header = parseHeaderLine(text);
|
|
4521
|
+
const sections = parseNamedSections(text);
|
|
4522
|
+
const rows = boardSummaryRows(toolName, header.fields, ok);
|
|
4523
|
+
appendBoardPreview(rows, sections.get("message") ?? sections.get("plan") ?? bodyLines(text).join("\n"));
|
|
4524
|
+
return rows.slice(0, VISUAL_MAX_LINES);
|
|
4525
|
+
}
|
|
4526
|
+
function boardSummaryRows(toolName, fields, ok) {
|
|
4527
|
+
const success = fields["ok"] !== "false" && ok;
|
|
4528
|
+
const count = numberFromParsedField(fields, "count");
|
|
4529
|
+
const open = numberFromParsedField(fields, "open");
|
|
4530
|
+
const completed = numberFromParsedField(fields, "completed");
|
|
4531
|
+
const inProgress = numberFromParsedField(fields, "inProgress") ?? numberFromParsedField(fields, "in_progress");
|
|
4532
|
+
const parts = [
|
|
4533
|
+
toolName,
|
|
4534
|
+
count !== void 0 ? `${count} item${count === 1 ? "" : "s"}` : void 0,
|
|
4535
|
+
open !== void 0 ? `${open} open` : void 0,
|
|
4536
|
+
completed !== void 0 ? `${completed} done` : void 0,
|
|
4537
|
+
inProgress !== void 0 && inProgress > 0 ? `${inProgress} in progress` : void 0
|
|
4538
|
+
].filter(Boolean);
|
|
4539
|
+
return [{
|
|
4540
|
+
kind: success ? "ok" : "error",
|
|
4541
|
+
marker: success ? "ok " : "x ",
|
|
4542
|
+
text: parts.join(" \xB7 ") || toolName
|
|
4543
|
+
}];
|
|
4544
|
+
}
|
|
4545
|
+
function appendBoardPreview(rows, text) {
|
|
4546
|
+
if (!text) return;
|
|
4547
|
+
const lines = text.split(/\r?\n/).map((line) => line.replace(/^[\s│├└─>*-]+/, "").trim()).filter((line) => line && !line.startsWith("{") && !line.startsWith("["));
|
|
4548
|
+
for (const line of lines.slice(0, 4)) {
|
|
4549
|
+
rows.push({ kind: line.includes("failed") || line.includes("not configured") ? "error" : "meta", text: line });
|
|
4550
|
+
}
|
|
4551
|
+
}
|
|
4552
|
+
function visualMemory(toolName, text, ok) {
|
|
4553
|
+
const json = tryParseJson(text);
|
|
4554
|
+
if (json && typeof json === "object" && !Array.isArray(json)) {
|
|
4555
|
+
const obj = json;
|
|
4556
|
+
if (toolName === "search_memory" || toolName === "find_related_memories") {
|
|
4557
|
+
return memoryResultRows(Array.isArray(obj["results"]) ? obj["results"] : []);
|
|
4558
|
+
}
|
|
4559
|
+
const fields = recordToStringFields(obj);
|
|
4560
|
+
return [memoryStatusRow(toolName, fields, ok)];
|
|
4561
|
+
}
|
|
4562
|
+
const header = parseHeaderLine(text);
|
|
4563
|
+
if (toolName === "search_memory" || toolName === "find_related_memories") {
|
|
4564
|
+
return memoryResultRows(bodyLines(text));
|
|
4565
|
+
}
|
|
4566
|
+
return [memoryStatusRow(toolName, header.fields, ok)];
|
|
4567
|
+
}
|
|
4568
|
+
function memoryStatusRow(toolName, fields, ok) {
|
|
4569
|
+
const scope = fields["scope"];
|
|
4570
|
+
const removed = numberFromParsedField(fields, "removed");
|
|
4571
|
+
const text = toolName === "forget" ? `${removed ?? 0} removed${scope ? ` \xB7 ${scope}` : ""}` : `${toolName}${scope ? ` \xB7 ${scope}` : ""}`;
|
|
4572
|
+
return { kind: ok ? "ok" : "error", marker: ok ? "ok " : "x ", text };
|
|
4573
|
+
}
|
|
4574
|
+
function memoryResultRows(results) {
|
|
4575
|
+
if (results.length === 0) return [{ kind: "meta", text: "no memories" }];
|
|
4576
|
+
const rows = [];
|
|
4577
|
+
for (const result of results.slice(0, VISUAL_MAX_LINES)) {
|
|
4578
|
+
if (typeof result === "string") {
|
|
4579
|
+
const parsed = tryParseJson(result);
|
|
4580
|
+
if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
|
|
4581
|
+
const o = parsed;
|
|
4582
|
+
rows.push({ kind: "meta", marker: tagMarker(stringOf(o["priority"])), text: memoryText(o) });
|
|
4583
|
+
} else {
|
|
4584
|
+
rows.push({ kind: "meta", text: result });
|
|
4585
|
+
}
|
|
4586
|
+
} else if (result && typeof result === "object") {
|
|
4587
|
+
const o = result;
|
|
4588
|
+
rows.push({ kind: "meta", marker: tagMarker(stringOf(o["priority"])), text: memoryText(o) });
|
|
4589
|
+
}
|
|
4590
|
+
}
|
|
4591
|
+
if (results.length > rows.length) rows.push({ kind: "meta", text: `${results.length - rows.length} more memory result(s)` });
|
|
4592
|
+
return rows;
|
|
4593
|
+
}
|
|
4594
|
+
function memoryText(o) {
|
|
4595
|
+
const type = stringOf(o["type"]);
|
|
4596
|
+
const scope = stringOf(o["scope"]);
|
|
4597
|
+
const text = stringOf(o["text"]) ?? "";
|
|
4598
|
+
return [type ? `[${type}]` : void 0, scope, text].filter(Boolean).join(" ");
|
|
4599
|
+
}
|
|
4600
|
+
function tagMarker(priority) {
|
|
4601
|
+
if (priority === "critical" || priority === "high") return "! ";
|
|
4602
|
+
return void 0;
|
|
4603
|
+
}
|
|
4604
|
+
function visualLogs(text) {
|
|
4605
|
+
const json = tryParseJson(text);
|
|
4606
|
+
if (json && typeof json === "object" && !Array.isArray(json)) {
|
|
4607
|
+
const obj = json;
|
|
4608
|
+
const rows2 = [{
|
|
4609
|
+
kind: "meta",
|
|
4610
|
+
text: `${stringOf(obj["source"]) ?? "logs"} \xB7 ${numOf(obj["total"]) ?? 0} entries${obj["truncated"] === true ? " \xB7 truncated" : ""}`
|
|
4611
|
+
}];
|
|
4612
|
+
const entries = Array.isArray(obj["entries"]) ? obj["entries"] : [];
|
|
4613
|
+
appendLogEntries(rows2, entries);
|
|
4614
|
+
return rows2;
|
|
4615
|
+
}
|
|
4616
|
+
const header = parseHeaderLine(text);
|
|
4617
|
+
const rows = [{ kind: "meta", text: `${header.label}${header.fields["total"] ? ` \xB7 ${header.fields["total"]} entries` : ""}` }];
|
|
4618
|
+
appendLogEntries(rows, bodyLines(text));
|
|
4619
|
+
return rows.slice(0, VISUAL_MAX_LINES);
|
|
4620
|
+
}
|
|
4621
|
+
function appendLogEntries(rows, entries) {
|
|
4622
|
+
for (const entry of entries.slice(0, 5)) {
|
|
4623
|
+
if (typeof entry === "string") {
|
|
4624
|
+
rows.push(logLine(entry));
|
|
4625
|
+
} else if (entry && typeof entry === "object") {
|
|
4626
|
+
const o = entry;
|
|
4627
|
+
rows.push(logLine([stringOf(o["timestamp"]), stringOf(o["level"]), stringOf(o["source"]), stringOf(o["message"])].filter(Boolean).join(" ")));
|
|
4628
|
+
}
|
|
4629
|
+
}
|
|
4630
|
+
if (entries.length > 5) rows.push({ kind: "meta", text: `${entries.length - 5} more log line(s)` });
|
|
4631
|
+
}
|
|
4632
|
+
function logLine(line) {
|
|
4633
|
+
const kind = /\b(error|fatal|panic)\b/i.test(line) ? "error" : /\b(warn|warning)\b/i.test(line) ? "warn" : "stdout";
|
|
4634
|
+
return { kind, marker: kind === "error" ? "x " : kind === "warn" ? "! " : void 0, text: line };
|
|
4635
|
+
}
|
|
4636
|
+
function visualDocument(text) {
|
|
4637
|
+
const json = tryParseJson(text);
|
|
4638
|
+
const rows = [];
|
|
4639
|
+
if (json && typeof json === "object" && !Array.isArray(json)) {
|
|
4640
|
+
const obj = json;
|
|
4641
|
+
rows.push({
|
|
4642
|
+
kind: "ok",
|
|
4643
|
+
marker: "ok ",
|
|
4644
|
+
text: `${numOf(obj["items_documented"]) ?? 0} documented \xB7 ${numOf(obj["files_processed"]) ?? 0} files \xB7 ${stringOf(obj["style"]) ?? "style"}`
|
|
4645
|
+
});
|
|
4646
|
+
appendDocumentResults(rows, Array.isArray(obj["results"]) ? obj["results"] : []);
|
|
4647
|
+
return rows.slice(0, VISUAL_MAX_LINES);
|
|
4648
|
+
}
|
|
4649
|
+
const header = parseHeaderLine(text);
|
|
4650
|
+
rows.push({
|
|
4651
|
+
kind: "ok",
|
|
4652
|
+
marker: "ok ",
|
|
4653
|
+
text: `${header.fields["items_documented"] ?? "0"} documented \xB7 ${header.fields["files_processed"] ?? "0"} files`
|
|
4654
|
+
});
|
|
4655
|
+
appendDocumentResults(rows, bodyLines(text));
|
|
4656
|
+
return rows.slice(0, VISUAL_MAX_LINES);
|
|
4657
|
+
}
|
|
4658
|
+
function appendDocumentResults(rows, results) {
|
|
4659
|
+
for (const result of results.slice(0, 5)) {
|
|
4660
|
+
const obj = typeof result === "string" ? tryParseJson(result) : result;
|
|
4661
|
+
if (obj && typeof obj === "object" && !Array.isArray(obj)) {
|
|
4662
|
+
const o = obj;
|
|
4663
|
+
const status = stringOf(o["status"]) ?? "item";
|
|
4664
|
+
rows.push({
|
|
4665
|
+
kind: status === "error" ? "error" : status === "skipped" ? "warn" : "path",
|
|
4666
|
+
marker: status === "error" ? "x " : status === "skipped" ? "! " : "+ ",
|
|
4667
|
+
path: stringOf(o["path"]),
|
|
4668
|
+
text: stringOf(o["name"]) ?? stringOf(o["signature"]) ?? status
|
|
4669
|
+
});
|
|
4670
|
+
} else if (typeof result === "string" && result.trim()) {
|
|
4671
|
+
rows.push({ kind: "meta", text: result.trim() });
|
|
4672
|
+
}
|
|
4673
|
+
}
|
|
4674
|
+
}
|
|
4675
|
+
function visualToolCatalog(toolName, text) {
|
|
4676
|
+
const json = tryParseJson(text);
|
|
4677
|
+
const rows = [];
|
|
4678
|
+
if (json && typeof json === "object" && !Array.isArray(json)) {
|
|
4679
|
+
const obj = json;
|
|
4680
|
+
const total = numOf(obj["total"]) ?? 0;
|
|
4681
|
+
rows.push({ kind: total > 0 ? "ok" : "warn", marker: total > 0 ? "ok " : "! ", text: `${toolName} \xB7 ${total} result${total === 1 ? "" : "s"}` });
|
|
4682
|
+
const tools = Array.isArray(obj["tools"]) ? obj["tools"] : [];
|
|
4683
|
+
for (const tool of tools.slice(0, 5)) {
|
|
4684
|
+
if (tool && typeof tool === "object") {
|
|
4685
|
+
const o = tool;
|
|
4686
|
+
rows.push({
|
|
4687
|
+
kind: o["mutating"] === true ? "warn" : "path",
|
|
4688
|
+
marker: o["mutating"] === true ? "! " : void 0,
|
|
4689
|
+
text: [stringOf(o["name"]), stringOf(o["permission"]), stringOf(o["description"])].filter(Boolean).join(" \xB7 ")
|
|
4690
|
+
});
|
|
4691
|
+
}
|
|
4692
|
+
}
|
|
4693
|
+
return rows.slice(0, VISUAL_MAX_LINES);
|
|
4694
|
+
}
|
|
4695
|
+
const header = parseHeaderLine(text);
|
|
4696
|
+
return [{ kind: "meta", text: header.label || toolName }];
|
|
4697
|
+
}
|
|
4698
|
+
function visualMetaExecution(toolName, text, ok) {
|
|
4699
|
+
const json = tryParseJson(text);
|
|
4700
|
+
if (!json || typeof json !== "object" || Array.isArray(json)) {
|
|
4701
|
+
const header = parseHeaderLine(text);
|
|
4702
|
+
return [{ kind: ok ? "ok" : "error", marker: ok ? "ok " : "x ", text: header.label || toolName }];
|
|
4703
|
+
}
|
|
4704
|
+
const obj = json;
|
|
4705
|
+
if (toolName === "tool_use") {
|
|
4706
|
+
const success = obj["success"] !== false && ok;
|
|
4707
|
+
const target = stringOf(obj["tool"]) ?? "tool";
|
|
4708
|
+
return [{
|
|
4709
|
+
kind: success ? "ok" : "error",
|
|
4710
|
+
marker: success ? "ok " : "x ",
|
|
4711
|
+
text: `${target} \xB7 ${numOf(obj["executionMs"]) ?? 0}ms${success ? "" : ` \xB7 ${stringOf(obj["error"]) ?? "failed"}`}`
|
|
4712
|
+
}];
|
|
4713
|
+
}
|
|
4714
|
+
const total = numOf(obj["total"]) ?? 0;
|
|
4715
|
+
const succeeded = numOf(obj["succeeded"]) ?? 0;
|
|
4716
|
+
const failed = numOf(obj["failed"]) ?? 0;
|
|
4717
|
+
const rows = [{
|
|
4718
|
+
kind: failed > 0 || !ok ? "error" : "ok",
|
|
4719
|
+
marker: failed > 0 || !ok ? "x " : "ok ",
|
|
4720
|
+
text: `${succeeded}/${total} succeeded${failed > 0 ? ` \xB7 ${failed} failed` : ""}`
|
|
4721
|
+
}];
|
|
4722
|
+
const results = Array.isArray(obj["results"]) ? obj["results"] : [];
|
|
4723
|
+
for (const result of results.slice(0, 5)) {
|
|
4724
|
+
if (result && typeof result === "object") {
|
|
4725
|
+
const r = result;
|
|
4726
|
+
const success = r["success"] !== false;
|
|
4727
|
+
rows.push({
|
|
4728
|
+
kind: success ? "ok" : "error",
|
|
4729
|
+
marker: success ? "ok " : "x ",
|
|
4730
|
+
text: `${stringOf(r["tool"]) ?? "tool"} \xB7 ${numOf(r["executionMs"]) ?? 0}ms${success ? "" : ` \xB7 ${stringOf(r["error"]) ?? "failed"}`}`
|
|
4731
|
+
});
|
|
4732
|
+
}
|
|
4733
|
+
}
|
|
4734
|
+
return rows.slice(0, VISUAL_MAX_LINES);
|
|
4735
|
+
}
|
|
4736
|
+
function visualCodebase(toolName, text, ok) {
|
|
4737
|
+
const json = tryParseJson(text);
|
|
4738
|
+
if (!json || typeof json !== "object" || Array.isArray(json)) {
|
|
4739
|
+
const header = parseHeaderLine(text);
|
|
4740
|
+
return [{ kind: ok ? "ok" : "warn", marker: ok ? "ok " : "! ", text: header.label || toolName }];
|
|
4741
|
+
}
|
|
4742
|
+
const obj = json;
|
|
4743
|
+
if (toolName === "codebase-search") {
|
|
4744
|
+
const status2 = stringOf(obj["indexStatus"]);
|
|
4745
|
+
const total = numOf(obj["total"]) ?? 0;
|
|
4746
|
+
const rows = [{
|
|
4747
|
+
kind: status2 ? "warn" : "ok",
|
|
4748
|
+
marker: status2 ? "! " : "ok ",
|
|
4749
|
+
text: status2 ?? `${total} symbol result${total === 1 ? "" : "s"} for "${stringOf(obj["query"]) ?? ""}"`
|
|
4750
|
+
}];
|
|
4751
|
+
const results = Array.isArray(obj["results"]) ? obj["results"] : [];
|
|
4752
|
+
for (const result of results.slice(0, 5)) {
|
|
4753
|
+
if (result && typeof result === "object") {
|
|
4754
|
+
const r = result;
|
|
4755
|
+
rows.push({
|
|
4756
|
+
kind: "match",
|
|
4757
|
+
path: stringOf(r["file"]),
|
|
4758
|
+
lineNo: numOf(r["line"])?.toString(),
|
|
4759
|
+
text: [stringOf(r["kind"]), stringOf(r["name"]), stringOf(r["signature"])].filter(Boolean).join(" \xB7 ")
|
|
4760
|
+
});
|
|
4761
|
+
}
|
|
4762
|
+
}
|
|
4763
|
+
return rows.slice(0, VISUAL_MAX_LINES);
|
|
4764
|
+
}
|
|
4765
|
+
if (toolName === "codebase-index") {
|
|
4766
|
+
const errors = Array.isArray(obj["errors"]) ? obj["errors"] : [];
|
|
4767
|
+
return [{
|
|
4768
|
+
kind: errors.length > 0 || !ok ? "error" : stringOf(obj["note"]) ? "warn" : "ok",
|
|
4769
|
+
marker: errors.length > 0 || !ok ? "x " : stringOf(obj["note"]) ? "! " : "ok ",
|
|
4770
|
+
text: stringOf(obj["note"]) ?? `${numOf(obj["filesIndexed"]) ?? 0} files \xB7 ${numOf(obj["symbolsIndexed"]) ?? 0} symbols \xB7 ${fmtDuration(numOf(obj["durationMs"]) ?? 0)}`
|
|
4771
|
+
}];
|
|
4772
|
+
}
|
|
4773
|
+
const status = stringOf(obj["indexStatus"]);
|
|
4774
|
+
return [{
|
|
4775
|
+
kind: status ? "warn" : "ok",
|
|
4776
|
+
marker: status ? "! " : "ok ",
|
|
4777
|
+
text: status ?? `${numOf(obj["totalSymbols"]) ?? 0} symbols \xB7 ${numOf(obj["totalFiles"]) ?? 0} files \xB7 ${fmtBytes(numOf(obj["sizeBytes"]) ?? 0)}`
|
|
4778
|
+
}];
|
|
4779
|
+
}
|
|
4780
|
+
function visualWorkingDir(text, ok) {
|
|
4781
|
+
const json = tryParseJson(text);
|
|
4782
|
+
const obj = json && typeof json === "object" && !Array.isArray(json) ? json : void 0;
|
|
4783
|
+
if (!obj) return void 0;
|
|
4784
|
+
const err = stringOf(obj["error"]);
|
|
4785
|
+
return [{
|
|
4786
|
+
kind: err || !ok ? "error" : "ok",
|
|
4787
|
+
marker: err || !ok ? "x " : "ok ",
|
|
4788
|
+
path: stringOf(obj["current"]),
|
|
4789
|
+
text: err ?? stringOf(obj["message"]) ?? "working directory"
|
|
4790
|
+
}];
|
|
4791
|
+
}
|
|
4792
|
+
function visualMode(text, ok) {
|
|
4793
|
+
const json = tryParseJson(text);
|
|
4794
|
+
const obj = json && typeof json === "object" && !Array.isArray(json) ? json : void 0;
|
|
4795
|
+
if (!obj) return void 0;
|
|
4796
|
+
if (Array.isArray(obj["modes"])) {
|
|
4797
|
+
const modes = obj["modes"];
|
|
4798
|
+
const rows = [{ kind: "ok", marker: "ok ", text: `${modes.length} mode${modes.length === 1 ? "" : "s"}` }];
|
|
4799
|
+
for (const mode of modes.slice(0, 5)) {
|
|
4800
|
+
if (mode && typeof mode === "object") {
|
|
4801
|
+
const m = mode;
|
|
4802
|
+
rows.push({ kind: "path", text: [stringOf(m["id"]), stringOf(m["name"]), stringOf(m["description"])].filter(Boolean).join(" \xB7 ") });
|
|
4803
|
+
}
|
|
4804
|
+
}
|
|
4805
|
+
return rows;
|
|
4806
|
+
}
|
|
4807
|
+
const success = obj["success"] !== false && ok;
|
|
4808
|
+
return [{
|
|
4809
|
+
kind: success ? "ok" : "error",
|
|
4810
|
+
marker: success ? "ok " : "x ",
|
|
4811
|
+
text: [stringOf(obj["action"]) ?? "mode", stringOf(obj["currentMode"]), stringOf(obj["message"])].filter(Boolean).join(" \xB7 ")
|
|
4812
|
+
}];
|
|
4813
|
+
}
|
|
4814
|
+
function recordToStringFields(obj) {
|
|
4815
|
+
const out = {};
|
|
4816
|
+
for (const [key, value] of Object.entries(obj)) {
|
|
4817
|
+
if (value === void 0 || value === null) continue;
|
|
4818
|
+
if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
|
|
4819
|
+
out[key] = String(value);
|
|
4820
|
+
}
|
|
4821
|
+
}
|
|
4822
|
+
return out;
|
|
4823
|
+
}
|
|
4824
|
+
function appendOutputPreview(rows, output, kind) {
|
|
4825
|
+
if (!output) return;
|
|
4826
|
+
const lines = output.split(/\r?\n/).filter((line) => line.trim());
|
|
4827
|
+
for (const line of lines.slice(0, 3)) rows.push({ kind, text: line.trim() });
|
|
4828
|
+
if (lines.length > 3) rows.push({ kind: "meta", text: `${lines.length - 3} more ${kind} line(s)` });
|
|
4829
|
+
}
|
|
4830
|
+
function bodyLines(text) {
|
|
4831
|
+
const lines = text.replace(/\r/g, "").split("\n");
|
|
4832
|
+
if (lines.length > 0 && /^[^\n]+(?:\s+\([^)]*\))?$/.test(lines[0] ?? "")) {
|
|
4833
|
+
return lines.slice(1);
|
|
4834
|
+
}
|
|
4835
|
+
return lines;
|
|
4836
|
+
}
|
|
4837
|
+
function parseHeaderLine(text) {
|
|
4838
|
+
const first = text.split(/\r?\n/, 1)[0] ?? "";
|
|
4839
|
+
const match = first.match(/^(.+?)(?: \((.*)\))?$/);
|
|
4840
|
+
const label = match?.[1] ?? first;
|
|
4841
|
+
const rawFields = match?.[2] ?? "";
|
|
4842
|
+
return { label, fields: parseInlineFields(rawFields) };
|
|
4843
|
+
}
|
|
4844
|
+
function parseInlineFields(raw) {
|
|
4845
|
+
const fields = {};
|
|
4846
|
+
for (const match of raw.matchAll(/([A-Za-z_][A-Za-z0-9_]*)=([^ ]+)/g)) {
|
|
4847
|
+
if (match[1] && match[2]) fields[match[1]] = match[2];
|
|
4848
|
+
}
|
|
4849
|
+
return fields;
|
|
4850
|
+
}
|
|
4851
|
+
function parseNamedSections(text) {
|
|
4852
|
+
const sections = /* @__PURE__ */ new Map();
|
|
4853
|
+
const lines = text.replace(/\r/g, "").split("\n");
|
|
4854
|
+
let current;
|
|
4855
|
+
const buf = [];
|
|
4856
|
+
const flush = () => {
|
|
4857
|
+
if (current) sections.set(current, buf.join("\n").trim());
|
|
4858
|
+
buf.length = 0;
|
|
4859
|
+
};
|
|
4860
|
+
for (const line of lines.slice(1)) {
|
|
4861
|
+
const m = line.match(/^([a-z_]+):$/);
|
|
4862
|
+
if (m?.[1]) {
|
|
4863
|
+
flush();
|
|
4864
|
+
current = m[1];
|
|
4865
|
+
continue;
|
|
4866
|
+
}
|
|
4867
|
+
if (current) buf.push(line);
|
|
4868
|
+
}
|
|
4869
|
+
flush();
|
|
4870
|
+
return sections;
|
|
4871
|
+
}
|
|
4872
|
+
function parseKeyValueLines(text) {
|
|
4873
|
+
const out = {};
|
|
4874
|
+
for (const line of text.split(/\r?\n/)) {
|
|
4875
|
+
const m = line.match(/^([A-Za-z_][A-Za-z0-9_]*)=(.*)$/);
|
|
4876
|
+
if (m?.[1]) out[m[1]] = m[2] ?? "";
|
|
4877
|
+
}
|
|
4878
|
+
return out;
|
|
4879
|
+
}
|
|
4880
|
+
function numberFromParsedField(fields, key) {
|
|
4881
|
+
const raw = fields[key];
|
|
4882
|
+
if (raw === void 0) return void 0;
|
|
4883
|
+
const n = Number.parseInt(raw, 10);
|
|
4884
|
+
return Number.isFinite(n) ? n : void 0;
|
|
4885
|
+
}
|
|
4105
4886
|
var MAX_STREAM_DISPLAY_CHARS = 480;
|
|
4106
4887
|
var MAX_STREAM_LINES = 8;
|
|
4107
4888
|
function streamBoxRows(text, maxLines, contentWidth) {
|
|
@@ -4146,10 +4927,7 @@ var ToolStreamBox = React5.memo(function ToolStreamBox2({
|
|
|
4146
4927
|
/* @__PURE__ */ jsx(Text, { dimColor: true, children: ` \u23F1 ${fmtDuration(elapsedMs)}` }),
|
|
4147
4928
|
hidden > 0 ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: ` (${totalLines} lines, showing last ${MAX_STREAM_LINES})` }) : null
|
|
4148
4929
|
] }),
|
|
4149
|
-
/* @__PURE__ */ jsx(Box, { flexDirection: "column", marginLeft: 2, children: rows.map((r, i) => (
|
|
4150
|
-
// biome-ignore lint/suspicious/noArrayIndexKey: fixed-height block, index is the row
|
|
4151
|
-
/* @__PURE__ */ jsx(Text, { dimColor: true, italic: Boolean(r.italic), children: r.text || " " }, i)
|
|
4152
|
-
)) })
|
|
4930
|
+
/* @__PURE__ */ jsx(Box, { flexDirection: "column", marginLeft: 2, children: rows.map((r, i) => /* @__PURE__ */ jsx(Text, { dimColor: true, italic: Boolean(r.italic), children: r.text || " " }, i)) })
|
|
4153
4931
|
] });
|
|
4154
4932
|
});
|
|
4155
4933
|
function tailForDisplay(text, maxChars) {
|
|
@@ -4162,7 +4940,7 @@ function tailForDisplay(text, maxChars) {
|
|
|
4162
4940
|
return `\u2026 ${text.slice(cut)}`;
|
|
4163
4941
|
}
|
|
4164
4942
|
var MAX_CODE_LINES = 80;
|
|
4165
|
-
var DIFF_MAX_LINES =
|
|
4943
|
+
var DIFF_MAX_LINES = 12;
|
|
4166
4944
|
function CodeBlock({
|
|
4167
4945
|
code,
|
|
4168
4946
|
lang,
|
|
@@ -4194,58 +4972,83 @@ function CodeBlock({
|
|
|
4194
4972
|
paddingX: 1,
|
|
4195
4973
|
children: [
|
|
4196
4974
|
lang !== "plain" ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: lang }) : null,
|
|
4197
|
-
rows.map((tokens, i) => (
|
|
4198
|
-
|
|
4199
|
-
/* @__PURE__ */
|
|
4200
|
-
|
|
4201
|
-
|
|
4202
|
-
|
|
4203
|
-
|
|
4204
|
-
|
|
4205
|
-
|
|
4206
|
-
|
|
4207
|
-
|
|
4208
|
-
|
|
4209
|
-
|
|
4210
|
-
))
|
|
4211
|
-
] }, i)
|
|
4212
|
-
)),
|
|
4975
|
+
rows.map((tokens, i) => /* @__PURE__ */ jsxs(Text, { children: [
|
|
4976
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: `${String(i + 1).padStart(gutterW, " ")} ` }),
|
|
4977
|
+
tokens.length === 0 ? " " : tokens.map((t, j) => /* @__PURE__ */ jsx(
|
|
4978
|
+
Text,
|
|
4979
|
+
{
|
|
4980
|
+
dimColor: Boolean(t.dim),
|
|
4981
|
+
bold: Boolean(t.bold),
|
|
4982
|
+
...t.color ? { color: t.color } : {},
|
|
4983
|
+
children: t.text
|
|
4984
|
+
},
|
|
4985
|
+
j
|
|
4986
|
+
))
|
|
4987
|
+
] }, i)),
|
|
4213
4988
|
hidden > 0 ? /* @__PURE__ */ jsx(Text, { dimColor: true, italic: true, children: `\u2026 +${hidden} more line${hidden === 1 ? "" : "s"}` }) : null
|
|
4214
4989
|
]
|
|
4215
4990
|
}
|
|
4216
4991
|
);
|
|
4217
4992
|
}
|
|
4218
|
-
function DiffBlock({
|
|
4993
|
+
function DiffBlock({
|
|
4994
|
+
rows,
|
|
4995
|
+
hidden,
|
|
4996
|
+
hiddenAdded = 0,
|
|
4997
|
+
hiddenRemoved = 0
|
|
4998
|
+
}) {
|
|
4219
4999
|
let gutterWidth = 1;
|
|
4220
5000
|
for (const r of rows) {
|
|
4221
|
-
const n
|
|
4222
|
-
|
|
4223
|
-
|
|
4224
|
-
|
|
5001
|
+
for (const n of [r.oldLine, r.newLine]) {
|
|
5002
|
+
if (typeof n === "number") {
|
|
5003
|
+
const w = String(n).length;
|
|
5004
|
+
if (w > gutterWidth) gutterWidth = w;
|
|
5005
|
+
}
|
|
4225
5006
|
}
|
|
4226
5007
|
}
|
|
4227
5008
|
const blank = " ".repeat(gutterWidth);
|
|
5009
|
+
const gutterPad = `${blank} ${blank}`;
|
|
5010
|
+
const footerStats = [
|
|
5011
|
+
hiddenAdded > 0 ? `+${hiddenAdded}` : "",
|
|
5012
|
+
hiddenRemoved > 0 ? `-${hiddenRemoved}` : ""
|
|
5013
|
+
].filter(Boolean);
|
|
5014
|
+
const markerFor = (kind) => {
|
|
5015
|
+
if (kind === "add") return "+";
|
|
5016
|
+
if (kind === "del") return "-";
|
|
5017
|
+
return " ";
|
|
5018
|
+
};
|
|
5019
|
+
const textForDisplay = (row) => {
|
|
5020
|
+
if ((row.kind === "add" || row.kind === "del" || row.kind === "ctx") && row.text.length > 0) {
|
|
5021
|
+
return row.text.slice(1) || " ";
|
|
5022
|
+
}
|
|
5023
|
+
return row.text || " ";
|
|
5024
|
+
};
|
|
4228
5025
|
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", marginLeft: 4, marginTop: 0, children: [
|
|
4229
5026
|
rows.map((row, i) => {
|
|
4230
5027
|
const key = i;
|
|
4231
5028
|
if (row.kind === "hunk") {
|
|
4232
|
-
return /* @__PURE__ */ jsx(Text, { color: "cyan", dimColor: true, children: row.text }, key);
|
|
5029
|
+
return /* @__PURE__ */ jsx(Text, { color: "cyan", dimColor: true, children: `${gutterPad} ${row.text}` }, key);
|
|
4233
5030
|
}
|
|
4234
5031
|
if (row.kind === "meta") {
|
|
4235
|
-
return /* @__PURE__ */ jsx(Text, { dimColor: true, children: `${
|
|
5032
|
+
return /* @__PURE__ */ jsx(Text, { dimColor: true, children: `${gutterPad} ${row.text}` }, key);
|
|
4236
5033
|
}
|
|
4237
|
-
const
|
|
4238
|
-
const
|
|
5034
|
+
const oldLn = typeof row.oldLine === "number" ? String(row.oldLine).padStart(gutterWidth, " ") : blank;
|
|
5035
|
+
const newLn = typeof row.newLine === "number" ? String(row.newLine).padStart(gutterWidth, " ") : blank;
|
|
4239
5036
|
if (row.kind === "ctx") {
|
|
4240
|
-
return /* @__PURE__ */ jsx(Text, { dimColor: true, children: `${
|
|
5037
|
+
return /* @__PURE__ */ jsx(Text, { dimColor: true, children: `${oldLn} ${newLn} ${textForDisplay(row)}` }, key);
|
|
4241
5038
|
}
|
|
4242
5039
|
const bg = row.kind === "add" ? theme.diffAddBg : theme.diffDelBg;
|
|
5040
|
+
const lineColor = row.kind === "add" ? theme.success : theme.error;
|
|
5041
|
+
const marker = markerFor(row.kind);
|
|
4243
5042
|
return /* @__PURE__ */ jsxs(Text, { children: [
|
|
4244
|
-
/* @__PURE__ */ jsx(Text, { dimColor:
|
|
4245
|
-
/* @__PURE__ */ jsx(Text, {
|
|
5043
|
+
/* @__PURE__ */ jsx(Text, { color: row.kind === "del" ? lineColor : void 0, dimColor: row.kind !== "del", children: oldLn }),
|
|
5044
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: " " }),
|
|
5045
|
+
/* @__PURE__ */ jsx(Text, { color: row.kind === "add" ? lineColor : void 0, dimColor: row.kind !== "add", children: newLn }),
|
|
5046
|
+
/* @__PURE__ */ jsx(Text, { children: " " }),
|
|
5047
|
+
/* @__PURE__ */ jsx(Text, { color: lineColor, bold: true, children: marker }),
|
|
5048
|
+
/* @__PURE__ */ jsx(Text, { backgroundColor: bg, color: "black", children: textForDisplay(row) })
|
|
4246
5049
|
] }, key);
|
|
4247
5050
|
}),
|
|
4248
|
-
hidden > 0 ? /* @__PURE__ */ jsx(Text, { dimColor: true, italic: true, children: `${
|
|
5051
|
+
hidden > 0 ? /* @__PURE__ */ jsx(Text, { dimColor: true, italic: true, children: `${gutterPad} \u2026 ${hidden} more line${hidden === 1 ? "" : "s"}${footerStats.length > 0 ? ` (${footerStats.join(" ")})` : ""}` }) : null
|
|
4249
5052
|
] });
|
|
4250
5053
|
}
|
|
4251
5054
|
function parseUnifiedDiff(diff, maxLines) {
|
|
@@ -4284,19 +5087,35 @@ function parseUnifiedDiff(diff, maxLines) {
|
|
|
4284
5087
|
oldLn++;
|
|
4285
5088
|
newLn++;
|
|
4286
5089
|
}
|
|
4287
|
-
|
|
4288
|
-
|
|
4289
|
-
|
|
5090
|
+
const added = all.filter((row) => row.kind === "add").length;
|
|
5091
|
+
const removed = all.filter((row) => row.kind === "del").length;
|
|
5092
|
+
if (all.length === 0) {
|
|
5093
|
+
return { rows: [], hidden: 0, added: 0, removed: 0, hiddenAdded: 0, hiddenRemoved: 0 };
|
|
5094
|
+
}
|
|
5095
|
+
if (all.length <= maxLines) {
|
|
5096
|
+
return { rows: all, hidden: 0, added, removed, hiddenAdded: 0, hiddenRemoved: 0 };
|
|
5097
|
+
}
|
|
5098
|
+
const rows = all.slice(0, maxLines);
|
|
5099
|
+
const hiddenRows = all.slice(maxLines);
|
|
5100
|
+
return {
|
|
5101
|
+
rows,
|
|
5102
|
+
hidden: hiddenRows.length,
|
|
5103
|
+
added,
|
|
5104
|
+
removed,
|
|
5105
|
+
hiddenAdded: hiddenRows.filter((row) => row.kind === "add").length,
|
|
5106
|
+
hiddenRemoved: hiddenRows.filter((row) => row.kind === "del").length
|
|
5107
|
+
};
|
|
4290
5108
|
}
|
|
4291
|
-
function extractDiffPreview(toolName, output) {
|
|
5109
|
+
function extractDiffPreview(toolName, output, input) {
|
|
4292
5110
|
if (!output) return void 0;
|
|
4293
5111
|
const text = output.trim();
|
|
4294
5112
|
if (!text) return void 0;
|
|
4295
5113
|
let diff;
|
|
4296
|
-
if (toolName === "edit" || toolName === "diff") {
|
|
5114
|
+
if (toolName === "edit" || toolName === "diff" || toolName === "write") {
|
|
4297
5115
|
const parsed = tryParseJson(text);
|
|
4298
5116
|
if (parsed && typeof parsed === "object") {
|
|
4299
|
-
|
|
5117
|
+
const obj = parsed;
|
|
5118
|
+
diff = toolName === "write" && obj["created"] === true ? newFileDiffFromWriteInput(obj, input) ?? stringOf(obj["diff"]) : stringOf(obj["diff"]);
|
|
4300
5119
|
}
|
|
4301
5120
|
} else if (toolName === "patch") {
|
|
4302
5121
|
const parsed = tryParseJson(text);
|
|
@@ -4305,9 +5124,32 @@ function extractDiffPreview(toolName, output) {
|
|
|
4305
5124
|
} else if (text.includes("@@") || text.startsWith("---")) {
|
|
4306
5125
|
diff = text;
|
|
4307
5126
|
}
|
|
5127
|
+
} else if (toolName === "replace") {
|
|
5128
|
+
const parsed = tryParseJson(text);
|
|
5129
|
+
if (parsed && typeof parsed === "object") {
|
|
5130
|
+
diff = collectReplaceDiffs(parsed);
|
|
5131
|
+
}
|
|
4308
5132
|
}
|
|
4309
|
-
if (!diff
|
|
4310
|
-
|
|
5133
|
+
if (!diff?.trim() || diff.startsWith("(no-op")) return void 0;
|
|
5134
|
+
const preview = parseUnifiedDiff(diff, DIFF_MAX_LINES);
|
|
5135
|
+
return preview.rows.length > 0 ? preview : void 0;
|
|
5136
|
+
}
|
|
5137
|
+
function collectReplaceDiffs(obj) {
|
|
5138
|
+
const results = Array.isArray(obj["results"]) ? obj["results"] : [];
|
|
5139
|
+
const diffs = results.map(
|
|
5140
|
+
(result) => result && typeof result === "object" ? stringOf(result["diff"]) : void 0
|
|
5141
|
+
).filter((diff) => Boolean(diff?.trim()));
|
|
5142
|
+
return diffs.length > 0 ? diffs.join("\n") : void 0;
|
|
5143
|
+
}
|
|
5144
|
+
function newFileDiffFromWriteInput(output, input) {
|
|
5145
|
+
if (!input || typeof input !== "object") return void 0;
|
|
5146
|
+
const obj = input;
|
|
5147
|
+
const content = stringOf(obj["content"]);
|
|
5148
|
+
if (content === void 0) return void 0;
|
|
5149
|
+
const path7 = stringOf(output["path"]) ?? stringOf(obj["path"]) ?? "new file";
|
|
5150
|
+
const lines = content === "" ? [] : content.replace(/\n$/, "").split("\n");
|
|
5151
|
+
const header = [`+++ ${path7}`, `@@ -0,0 +1,${lines.length} @@`];
|
|
5152
|
+
return [...header, ...lines.map((line) => `+${line}`)].join("\n");
|
|
4311
5153
|
}
|
|
4312
5154
|
var MESSAGE_PANEL_CHROME_WIDTH = 2;
|
|
4313
5155
|
function assistantContentWidth(termWidth) {
|
|
@@ -4354,20 +5196,14 @@ function AssistantBody({
|
|
|
4354
5196
|
const segments = splitFencedBlocks(text);
|
|
4355
5197
|
const inner = contentWidth ?? termWidth;
|
|
4356
5198
|
return /* @__PURE__ */ jsx(Box, { flexDirection: "column", children: segments.map(
|
|
4357
|
-
(seg, i) => seg.type === "code" ? (
|
|
4358
|
-
|
|
4359
|
-
|
|
4360
|
-
|
|
4361
|
-
|
|
4362
|
-
|
|
4363
|
-
|
|
4364
|
-
|
|
4365
|
-
text: seg.text,
|
|
4366
|
-
termWidth: inner,
|
|
4367
|
-
tableWidth: termWidth - MESSAGE_PANEL_CHROME_WIDTH
|
|
4368
|
-
},
|
|
4369
|
-
i
|
|
4370
|
-
)
|
|
5199
|
+
(seg, i) => seg.type === "code" ? /* @__PURE__ */ jsx(CodeBlock, { code: seg.text, lang: seg.lang ?? "plain", contentWidth: inner }, i) : /* @__PURE__ */ jsx(
|
|
5200
|
+
MarkdownView,
|
|
5201
|
+
{
|
|
5202
|
+
text: seg.text,
|
|
5203
|
+
termWidth: inner,
|
|
5204
|
+
tableWidth: termWidth - MESSAGE_PANEL_CHROME_WIDTH
|
|
5205
|
+
},
|
|
5206
|
+
i
|
|
4371
5207
|
)
|
|
4372
5208
|
) });
|
|
4373
5209
|
}
|
|
@@ -4403,10 +5239,7 @@ function AssistantTail({
|
|
|
4403
5239
|
/* @__PURE__ */ jsx(Text, { bold: true, color: theme.assistant, children: "ASSISTANT" }),
|
|
4404
5240
|
/* @__PURE__ */ jsx(Text, { dimColor: true, children: " (streaming\u2026)" })
|
|
4405
5241
|
] }),
|
|
4406
|
-
/* @__PURE__ */ jsx(Box, { flexDirection: "column", children: rows.map((r, i) => (
|
|
4407
|
-
// biome-ignore lint/suspicious/noArrayIndexKey: fixed-height block, index is the row
|
|
4408
|
-
/* @__PURE__ */ jsx(Text, { color: "white", children: r || " " }, i)
|
|
4409
|
-
)) })
|
|
5242
|
+
/* @__PURE__ */ jsx(Box, { flexDirection: "column", children: rows.map((r, i) => /* @__PURE__ */ jsx(Text, { color: "white", children: r || " " }, i)) })
|
|
4410
5243
|
]
|
|
4411
5244
|
}
|
|
4412
5245
|
);
|
|
@@ -4706,7 +5539,8 @@ var Entry = React5.memo(function Entry2({
|
|
|
4706
5539
|
entry.outputBytes,
|
|
4707
5540
|
entry.outputLines
|
|
4708
5541
|
);
|
|
4709
|
-
const
|
|
5542
|
+
const visualLines = formatToolVisualOutput(entry.name, entry.output, entry.ok, entry.input);
|
|
5543
|
+
const diff = entry.ok ? extractDiffPreview(entry.name, entry.output, entry.input) : void 0;
|
|
4710
5544
|
const sizeChip = (() => {
|
|
4711
5545
|
if (!entry.ok) return "";
|
|
4712
5546
|
const parts = [];
|
|
@@ -4733,21 +5567,26 @@ var Entry = React5.memo(function Entry2({
|
|
|
4733
5567
|
/* @__PURE__ */ jsx(Text, { dimColor: true, children: ` \xB7 ${fmtDuration(entry.durationMs)}` }),
|
|
4734
5568
|
sizeChip ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: ` \xB7 ${sizeChip}` }) : null
|
|
4735
5569
|
] }),
|
|
4736
|
-
outLines.map((line, i) => (
|
|
4737
|
-
|
|
4738
|
-
/* @__PURE__ */
|
|
4739
|
-
|
|
4740
|
-
|
|
4741
|
-
|
|
4742
|
-
{
|
|
4743
|
-
|
|
4744
|
-
|
|
4745
|
-
|
|
4746
|
-
|
|
4747
|
-
|
|
4748
|
-
|
|
4749
|
-
|
|
4750
|
-
|
|
5570
|
+
visualLines ? /* @__PURE__ */ jsx(ToolOutputLines, { lines: visualLines, hasFollowingBlock: Boolean(diff) }) : outLines.map((line, i) => /* @__PURE__ */ jsxs(Text, { children: [
|
|
5571
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: i === outLines.length - 1 && !diff ? " \u2514\u2500 " : " \u251C\u2500 " }),
|
|
5572
|
+
/* @__PURE__ */ jsx(
|
|
5573
|
+
Text,
|
|
5574
|
+
{
|
|
5575
|
+
dimColor: entry.ok && !line.startsWith("!"),
|
|
5576
|
+
...!entry.ok || line.startsWith("!") ? { color: "red" } : {},
|
|
5577
|
+
children: line
|
|
5578
|
+
}
|
|
5579
|
+
)
|
|
5580
|
+
] }, i)),
|
|
5581
|
+
diff ? /* @__PURE__ */ jsx(
|
|
5582
|
+
DiffBlock,
|
|
5583
|
+
{
|
|
5584
|
+
rows: diff.rows,
|
|
5585
|
+
hidden: diff.hidden,
|
|
5586
|
+
hiddenAdded: diff.hiddenAdded,
|
|
5587
|
+
hiddenRemoved: diff.hiddenRemoved
|
|
5588
|
+
}
|
|
5589
|
+
) : null
|
|
4751
5590
|
] });
|
|
4752
5591
|
}
|
|
4753
5592
|
case "info": {
|
|
@@ -4851,13 +5690,10 @@ var Entry = React5.memo(function Entry2({
|
|
|
4851
5690
|
/* @__PURE__ */ jsx(Text, { dimColor: true, children: entry.detail })
|
|
4852
5691
|
] }) : null
|
|
4853
5692
|
] }),
|
|
4854
|
-
lines.slice(1).map((line, i) => (
|
|
4855
|
-
|
|
4856
|
-
/* @__PURE__ */
|
|
4857
|
-
|
|
4858
|
-
/* @__PURE__ */ jsx(Text, { children: line })
|
|
4859
|
-
] }, i)
|
|
4860
|
-
))
|
|
5693
|
+
lines.slice(1).map((line, i) => /* @__PURE__ */ jsxs(Text, { children: [
|
|
5694
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: " " }),
|
|
5695
|
+
/* @__PURE__ */ jsx(Text, { children: line })
|
|
5696
|
+
] }, i))
|
|
4861
5697
|
] });
|
|
4862
5698
|
}
|
|
4863
5699
|
}
|
|
@@ -5507,13 +6343,7 @@ var Input = memo(function Input2({
|
|
|
5507
6343
|
}
|
|
5508
6344
|
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", children: [
|
|
5509
6345
|
rows.map(
|
|
5510
|
-
(row, i) => row.length === 0 ? (
|
|
5511
|
-
// biome-ignore lint/suspicious/noArrayIndexKey: rows are positional and re-laid out every render
|
|
5512
|
-
/* @__PURE__ */ jsx(Text, { children: " " }, i)
|
|
5513
|
-
) : (
|
|
5514
|
-
// biome-ignore lint/suspicious/noArrayIndexKey: rows are positional and re-laid out every render
|
|
5515
|
-
/* @__PURE__ */ jsx(Text, { children: renderRow2(row, `r${i}`, promptColor) }, i)
|
|
5516
|
-
)
|
|
6346
|
+
(row, i) => row.length === 0 ? /* @__PURE__ */ jsx(Text, { children: " " }, i) : /* @__PURE__ */ jsx(Text, { children: renderRow2(row, `r${i}`, promptColor) }, i)
|
|
5517
6347
|
),
|
|
5518
6348
|
hint ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: hint }) : null
|
|
5519
6349
|
] });
|
|
@@ -5673,30 +6503,172 @@ function PhaseMonitor({
|
|
|
5673
6503
|
const isRunning = runningPhaseIds.includes(phaseKey);
|
|
5674
6504
|
const elapsed = phase.startedAt ? fmtElapsed2(nowTick - phase.startedAt) : "\u2014";
|
|
5675
6505
|
const progress = phase.totalTasks > 0 ? `${phase.completedTasks}/${phase.totalTasks}` : "\u2014";
|
|
5676
|
-
return /* @__PURE__ */
|
|
5677
|
-
/* @__PURE__ */
|
|
5678
|
-
|
|
5679
|
-
|
|
5680
|
-
/* @__PURE__ */ jsx(Text, { color: s2.color, children: s2.label }),
|
|
5681
|
-
isRunning ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
5682
|
-
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "\xB7" }),
|
|
5683
|
-
/* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
5684
|
-
"elapsed ",
|
|
5685
|
-
elapsed
|
|
5686
|
-
] })
|
|
5687
|
-
] }) : null,
|
|
5688
|
-
phase.totalTasks > 0 && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
6506
|
+
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", marginTop: 1, children: [
|
|
6507
|
+
/* @__PURE__ */ jsxs(Box, { flexDirection: "row", gap: 1, children: [
|
|
6508
|
+
/* @__PURE__ */ jsx(Text, { color: s2.color, bold: true, children: s2.icon }),
|
|
6509
|
+
/* @__PURE__ */ jsx(Text, { bold: true, children: phase.name }),
|
|
5689
6510
|
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "\xB7" }),
|
|
5690
|
-
/* @__PURE__ */
|
|
5691
|
-
|
|
5692
|
-
|
|
6511
|
+
/* @__PURE__ */ jsx(Text, { color: s2.color, children: s2.label }),
|
|
6512
|
+
isRunning ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
6513
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "\xB7" }),
|
|
6514
|
+
/* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
6515
|
+
"elapsed ",
|
|
6516
|
+
elapsed
|
|
6517
|
+
] })
|
|
6518
|
+
] }) : null,
|
|
6519
|
+
phase.totalTasks > 0 && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
6520
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "\xB7" }),
|
|
6521
|
+
/* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
6522
|
+
"tasks ",
|
|
6523
|
+
progress
|
|
6524
|
+
] })
|
|
5693
6525
|
] })
|
|
5694
|
-
] })
|
|
5695
|
-
|
|
6526
|
+
] }),
|
|
6527
|
+
(phase.activeTasks ?? []).map((t) => /* @__PURE__ */ jsxs(Box, { flexDirection: "row", gap: 1, marginLeft: 2, children: [
|
|
6528
|
+
/* @__PURE__ */ jsx(Text, { color: "yellow", children: "\u25CF" }),
|
|
6529
|
+
/* @__PURE__ */ jsx(Text, { color: "cyan", children: t.agent ?? "agent" }),
|
|
6530
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2192" }),
|
|
6531
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: t.title || "(task)" })
|
|
6532
|
+
] }, t.taskId))
|
|
6533
|
+
] }, phaseKey);
|
|
5696
6534
|
}),
|
|
5697
6535
|
/* @__PURE__ */ jsx(Box, { marginTop: 1, children: /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2191/\u2193 navigate phases" }) })
|
|
5698
6536
|
] });
|
|
5699
6537
|
}
|
|
6538
|
+
var STATUS3 = {
|
|
6539
|
+
pending: { icon: "\u25CB", color: "gray" },
|
|
6540
|
+
queued: { icon: "\u25D4", color: "cyan" },
|
|
6541
|
+
in_progress: { icon: "\u25B6", color: "yellow" },
|
|
6542
|
+
blocked: { icon: "\u2298", color: "magenta" },
|
|
6543
|
+
review: { icon: "\u25C6", color: "blue" },
|
|
6544
|
+
failed: { icon: "\u2717", color: "red" },
|
|
6545
|
+
completed: { icon: "\u2713", color: "green" },
|
|
6546
|
+
cancelled: { icon: "\u229D", color: "gray" }
|
|
6547
|
+
};
|
|
6548
|
+
var RUN_STATUS = {
|
|
6549
|
+
running: "yellow",
|
|
6550
|
+
paused: "magenta",
|
|
6551
|
+
completed: "green",
|
|
6552
|
+
failed: "red",
|
|
6553
|
+
deadlocked: "red",
|
|
6554
|
+
idle: "gray"
|
|
6555
|
+
};
|
|
6556
|
+
var PRIORITY = {
|
|
6557
|
+
critical: "red",
|
|
6558
|
+
high: "yellow",
|
|
6559
|
+
medium: "cyan",
|
|
6560
|
+
low: "gray"
|
|
6561
|
+
};
|
|
6562
|
+
var FEED_KIND = {
|
|
6563
|
+
started: { icon: "\u25B6", color: "yellow" },
|
|
6564
|
+
completed: { icon: "\u2713", color: "green" },
|
|
6565
|
+
failed: { icon: "\u2717", color: "red" },
|
|
6566
|
+
retrying: { icon: "\u21BB", color: "yellow" },
|
|
6567
|
+
wave: { icon: "\u224B", color: "magenta" },
|
|
6568
|
+
deadlock: { icon: "\u26A0", color: "red" },
|
|
6569
|
+
verification_failed: { icon: "\u26CA", color: "red" },
|
|
6570
|
+
conflict: { icon: "\u2442", color: "yellow" },
|
|
6571
|
+
split: { icon: "\u22D4", color: "cyan" },
|
|
6572
|
+
supervisor: { icon: "\u2726", color: "magenta" }
|
|
6573
|
+
};
|
|
6574
|
+
function clip(s2, n) {
|
|
6575
|
+
return s2.length > n ? `${s2.slice(0, n - 1)}\u2026` : s2;
|
|
6576
|
+
}
|
|
6577
|
+
function TaskCard({ task }) {
|
|
6578
|
+
const st2 = STATUS3[task.displayStatus] ?? { icon: "?", color: "white" };
|
|
6579
|
+
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", marginBottom: 1, width: 26, children: [
|
|
6580
|
+
/* @__PURE__ */ jsxs(Box, { flexDirection: "row", gap: 1, children: [
|
|
6581
|
+
/* @__PURE__ */ jsx(Text, { color: st2.color, bold: true, children: st2.icon }),
|
|
6582
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: task.shortId }),
|
|
6583
|
+
/* @__PURE__ */ jsx(Text, { color: PRIORITY[task.priority] ?? "gray", children: task.priority[0]?.toUpperCase() })
|
|
6584
|
+
] }),
|
|
6585
|
+
/* @__PURE__ */ jsx(Text, { wrap: "truncate-end", children: clip(task.title, 24) }),
|
|
6586
|
+
task.deps.length > 0 ? /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
6587
|
+
"\u2190 ",
|
|
6588
|
+
clip(task.deps.join(", "), 22)
|
|
6589
|
+
] }) : null,
|
|
6590
|
+
task.agentName ? /* @__PURE__ */ jsxs(Box, { flexDirection: "row", gap: 1, children: [
|
|
6591
|
+
/* @__PURE__ */ jsx(Text, { color: task.displayStatus === "in_progress" ? "yellow" : "gray", children: "\u25CF" }),
|
|
6592
|
+
/* @__PURE__ */ jsx(Text, { color: "cyan", children: clip(task.agentName, 14) }),
|
|
6593
|
+
task.retries > 0 ? /* @__PURE__ */ jsxs(Text, { color: "red", children: [
|
|
6594
|
+
"\u21BB",
|
|
6595
|
+
task.retries
|
|
6596
|
+
] }) : null
|
|
6597
|
+
] }) : null,
|
|
6598
|
+
task.worktreeBranch ? /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
6599
|
+
"\u2325 ",
|
|
6600
|
+
clip(task.worktreeBranch, 22)
|
|
6601
|
+
] }) : null
|
|
6602
|
+
] });
|
|
6603
|
+
}
|
|
6604
|
+
function SddBoardOverlay({
|
|
6605
|
+
snapshot
|
|
6606
|
+
}) {
|
|
6607
|
+
const byShort = new Map(snapshot.tasks.map((t) => [t.shortId, t]));
|
|
6608
|
+
const p = snapshot.progress;
|
|
6609
|
+
const chains = snapshot.diagnostics?.deadlockChains ?? [];
|
|
6610
|
+
const recentFeed = (snapshot.feed ?? []).slice(0, 6);
|
|
6611
|
+
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", borderStyle: "round", borderColor: "cyan", paddingX: 1, children: [
|
|
6612
|
+
/* @__PURE__ */ jsxs(Box, { flexDirection: "row", gap: 1, marginBottom: 1, children: [
|
|
6613
|
+
/* @__PURE__ */ jsx(Text, { bold: true, color: "cyan", children: "SDD BOARD" }),
|
|
6614
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" }),
|
|
6615
|
+
/* @__PURE__ */ jsx(Text, { bold: true, children: clip(snapshot.title, 32) }),
|
|
6616
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" }),
|
|
6617
|
+
/* @__PURE__ */ jsx(Text, { color: RUN_STATUS[snapshot.status] ?? "white", children: snapshot.status }),
|
|
6618
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" }),
|
|
6619
|
+
/* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
6620
|
+
"wave ",
|
|
6621
|
+
snapshot.wave + 1
|
|
6622
|
+
] }),
|
|
6623
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" }),
|
|
6624
|
+
/* @__PURE__ */ jsxs(Text, { color: "green", children: [
|
|
6625
|
+
"\u2713",
|
|
6626
|
+
p.completed
|
|
6627
|
+
] }),
|
|
6628
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "/" }),
|
|
6629
|
+
/* @__PURE__ */ jsx(Text, { children: p.total }),
|
|
6630
|
+
/* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
6631
|
+
"(",
|
|
6632
|
+
p.percentComplete,
|
|
6633
|
+
"%)"
|
|
6634
|
+
] }),
|
|
6635
|
+
p.inProgress > 0 ? /* @__PURE__ */ jsxs(Text, { color: "yellow", children: [
|
|
6636
|
+
"\u25B6",
|
|
6637
|
+
p.inProgress
|
|
6638
|
+
] }) : null,
|
|
6639
|
+
p.failed > 0 ? /* @__PURE__ */ jsxs(Text, { color: "red", children: [
|
|
6640
|
+
"\u2717",
|
|
6641
|
+
p.failed
|
|
6642
|
+
] }) : null,
|
|
6643
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502 Ctrl+B close \xB7 c clean wt \xB7 z rollback" })
|
|
6644
|
+
] }),
|
|
6645
|
+
chains.length > 0 ? /* @__PURE__ */ jsxs(Box, { flexDirection: "column", marginBottom: 1, children: [
|
|
6646
|
+
/* @__PURE__ */ jsx(Text, { color: "red", bold: true, children: "\u26A0 Deadlock \u2014 blocked by failed tasks:" }),
|
|
6647
|
+
chains.map((c) => /* @__PURE__ */ jsxs(Text, { color: "red", children: [
|
|
6648
|
+
" ",
|
|
6649
|
+
c.blocked,
|
|
6650
|
+
" \u2190 ",
|
|
6651
|
+
c.blockedBy.join(", ")
|
|
6652
|
+
] }, c.blocked))
|
|
6653
|
+
] }) : null,
|
|
6654
|
+
snapshot.tasks.length === 0 ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: "No active SDD run. Start one with /sdd execute." }) : /* @__PURE__ */ jsx(Box, { flexDirection: "row", gap: 2, children: snapshot.columns.map((col) => /* @__PURE__ */ jsxs(Box, { flexDirection: "column", marginRight: 1, children: [
|
|
6655
|
+
/* @__PURE__ */ jsx(Text, { bold: true, color: "cyan", children: col.label }),
|
|
6656
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2500".repeat(12) }),
|
|
6657
|
+
col.taskIds.map((sid) => byShort.get(sid)).filter((t) => Boolean(t)).map((t) => /* @__PURE__ */ jsx(TaskCard, { task: t }, t.id))
|
|
6658
|
+
] }, col.label)) }),
|
|
6659
|
+
recentFeed.length > 0 ? /* @__PURE__ */ jsxs(Box, { flexDirection: "column", marginTop: 1, children: [
|
|
6660
|
+
/* @__PURE__ */ jsx(Text, { bold: true, color: "cyan", children: "Recent activity" }),
|
|
6661
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2500".repeat(12) }),
|
|
6662
|
+
recentFeed.map((f, i) => {
|
|
6663
|
+
const k = FEED_KIND[f.kind] ?? FEED_KIND.started;
|
|
6664
|
+
return /* @__PURE__ */ jsxs(Box, { flexDirection: "row", gap: 1, children: [
|
|
6665
|
+
/* @__PURE__ */ jsx(Text, { color: k?.color ?? "white", children: k?.icon ?? "\u2022" }),
|
|
6666
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: clip(f.text, 70) })
|
|
6667
|
+
] }, `${f.ts}-${i}`);
|
|
6668
|
+
})
|
|
6669
|
+
] }) : null
|
|
6670
|
+
] });
|
|
6671
|
+
}
|
|
5700
6672
|
var fmtElapsed3 = (ms) => {
|
|
5701
6673
|
const s2 = Math.floor(ms / 1e3);
|
|
5702
6674
|
const m = Math.floor(s2 / 60);
|
|
@@ -5705,7 +6677,7 @@ var fmtElapsed3 = (ms) => {
|
|
|
5705
6677
|
if (m > 0) return `${m}:${String(s2 % 60).padStart(2, "0")}`;
|
|
5706
6678
|
return `${s2}s`;
|
|
5707
6679
|
};
|
|
5708
|
-
var
|
|
6680
|
+
var STATUS4 = {
|
|
5709
6681
|
pending: { icon: "\u25CB", color: "gray" },
|
|
5710
6682
|
ready: { icon: "\u25D0", color: "cyan" },
|
|
5711
6683
|
running: { icon: "\u25CF", color: "yellow" },
|
|
@@ -5715,7 +6687,7 @@ var STATUS3 = {
|
|
|
5715
6687
|
skipped: { icon: "\u2298", color: "gray" }
|
|
5716
6688
|
};
|
|
5717
6689
|
function s(entry) {
|
|
5718
|
-
return
|
|
6690
|
+
return STATUS4[entry] ?? { icon: "?", color: "white" };
|
|
5719
6691
|
}
|
|
5720
6692
|
function PhasePanel({ phases, nowTick }) {
|
|
5721
6693
|
const list = Object.values(phases);
|
|
@@ -6033,7 +7005,7 @@ function GoalPanel({
|
|
|
6033
7005
|
/* @__PURE__ */ jsx(Box, { marginTop: 1, children: coordinatorRunning ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
6034
7006
|
/* @__PURE__ */ jsx(Text, { color: "green", children: "\u25CF Coordinator running " }),
|
|
6035
7007
|
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "[S] Stop coordinator" })
|
|
6036
|
-
] }) : /* @__PURE__ */ jsx(
|
|
7008
|
+
] }) : /* @__PURE__ */ jsx(Text, { dimColor: true, children: "[C] Start coordinator" }) })
|
|
6037
7009
|
] });
|
|
6038
7010
|
}
|
|
6039
7011
|
const displayGoal = goal.refinedGoal || goal.goal;
|
|
@@ -6071,15 +7043,12 @@ function GoalPanel({
|
|
|
6071
7043
|
] }) }),
|
|
6072
7044
|
goal.deliverables.map((d, i) => {
|
|
6073
7045
|
const done = /^\[[x✓]\]|✅|\(done\)/i.test(d);
|
|
6074
|
-
return (
|
|
6075
|
-
|
|
6076
|
-
|
|
6077
|
-
|
|
6078
|
-
|
|
6079
|
-
|
|
6080
|
-
d
|
|
6081
|
-
] }) }, i)
|
|
6082
|
-
);
|
|
7046
|
+
return /* @__PURE__ */ jsx(Box, { children: /* @__PURE__ */ jsxs(Text, { ...done ? { color: "green" } : {}, dimColor: !done, children: [
|
|
7047
|
+
" ",
|
|
7048
|
+
done ? "\u2713" : "\u25CB",
|
|
7049
|
+
" ",
|
|
7050
|
+
d
|
|
7051
|
+
] }) }, i);
|
|
6083
7052
|
})
|
|
6084
7053
|
] }),
|
|
6085
7054
|
/* @__PURE__ */ jsxs(Box, { flexDirection: "column", marginBottom: 1, children: [
|
|
@@ -6103,7 +7072,7 @@ function GoalPanel({
|
|
|
6103
7072
|
/* @__PURE__ */ jsx(Box, { marginTop: 1, children: coordinatorRunning ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
6104
7073
|
/* @__PURE__ */ jsx(Text, { color: "green", children: "\u25CF Coordinator running " }),
|
|
6105
7074
|
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "[S] Stop coordinator" })
|
|
6106
|
-
] }) : /* @__PURE__ */ jsx(
|
|
7075
|
+
] }) : /* @__PURE__ */ jsx(Text, { dimColor: true, children: "[C] Start coordinator" }) })
|
|
6107
7076
|
] })
|
|
6108
7077
|
] });
|
|
6109
7078
|
}
|
|
@@ -7187,13 +8156,10 @@ function hintsFor(ctx) {
|
|
|
7187
8156
|
}
|
|
7188
8157
|
function KeyHintBar({ context }) {
|
|
7189
8158
|
const hints = hintsFor(context);
|
|
7190
|
-
return /* @__PURE__ */ jsx(Box, { flexDirection: "row", paddingX: 1, children: hints.map((h, i) => (
|
|
7191
|
-
|
|
7192
|
-
/* @__PURE__ */
|
|
7193
|
-
|
|
7194
|
-
/* @__PURE__ */ jsx(Text, { dimColor: true, children: ` ${h.label}` })
|
|
7195
|
-
] }, i)
|
|
7196
|
-
)) });
|
|
8159
|
+
return /* @__PURE__ */ jsx(Box, { flexDirection: "row", paddingX: 1, children: hints.map((h, i) => /* @__PURE__ */ jsxs(Box, { flexDirection: "row", marginRight: 2, children: [
|
|
8160
|
+
/* @__PURE__ */ jsx(Text, { color: h.discovery ? theme.monitor.agents : theme.accent, children: h.key }),
|
|
8161
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: ` ${h.label}` })
|
|
8162
|
+
] }, i)) });
|
|
7197
8163
|
}
|
|
7198
8164
|
function TodosMonitor({ todos }) {
|
|
7199
8165
|
const { stdout } = useStdout();
|
|
@@ -7426,7 +8392,7 @@ var fmtElapsed6 = (ms) => {
|
|
|
7426
8392
|
if (m > 0) return `${m}:${String(s2 % 60).padStart(2, "0")}`;
|
|
7427
8393
|
return `${s2}s`;
|
|
7428
8394
|
};
|
|
7429
|
-
var
|
|
8395
|
+
var STATUS5 = {
|
|
7430
8396
|
allocating: { icon: "\u25CB", color: "gray" },
|
|
7431
8397
|
active: { icon: "\u25CF", color: "yellow" },
|
|
7432
8398
|
committing: { icon: "\u25D0", color: "cyan" },
|
|
@@ -7436,7 +8402,7 @@ var STATUS4 = {
|
|
|
7436
8402
|
failed: { icon: "\u2717", color: "red" }
|
|
7437
8403
|
};
|
|
7438
8404
|
function st(status) {
|
|
7439
|
-
return
|
|
8405
|
+
return STATUS5[status] ?? { icon: "?", color: "white" };
|
|
7440
8406
|
}
|
|
7441
8407
|
function WorktreePanel({
|
|
7442
8408
|
worktrees,
|
|
@@ -8399,6 +9365,46 @@ function useAutoPhaseEvents(subscribeAutoPhase, dispatch, stateRef) {
|
|
|
8399
9365
|
});
|
|
8400
9366
|
break;
|
|
8401
9367
|
}
|
|
9368
|
+
case "phase.taskStarted": {
|
|
9369
|
+
const p = payload;
|
|
9370
|
+
dispatch({
|
|
9371
|
+
type: "autoPhaseTaskActive",
|
|
9372
|
+
phaseId: p.phaseId,
|
|
9373
|
+
taskId: p.taskId,
|
|
9374
|
+
title: p.taskTitle,
|
|
9375
|
+
agent: p.agentName,
|
|
9376
|
+
active: true
|
|
9377
|
+
});
|
|
9378
|
+
break;
|
|
9379
|
+
}
|
|
9380
|
+
case "phase.taskAssigned": {
|
|
9381
|
+
const p = payload;
|
|
9382
|
+
const active = stateRef.current.autoPhase?.phases[p.phaseId]?.activeTasks?.find(
|
|
9383
|
+
(t) => t.taskId === p.taskId
|
|
9384
|
+
);
|
|
9385
|
+
if (active) {
|
|
9386
|
+
dispatch({
|
|
9387
|
+
type: "autoPhaseTaskActive",
|
|
9388
|
+
phaseId: p.phaseId,
|
|
9389
|
+
taskId: p.taskId,
|
|
9390
|
+
title: active.title,
|
|
9391
|
+
agent: p.agentName,
|
|
9392
|
+
active: true
|
|
9393
|
+
});
|
|
9394
|
+
}
|
|
9395
|
+
break;
|
|
9396
|
+
}
|
|
9397
|
+
case "phase.taskFailed": {
|
|
9398
|
+
const p = payload;
|
|
9399
|
+
dispatch({
|
|
9400
|
+
type: "autoPhaseTaskActive",
|
|
9401
|
+
phaseId: p.phaseId,
|
|
9402
|
+
taskId: p.taskId,
|
|
9403
|
+
title: "",
|
|
9404
|
+
active: false
|
|
9405
|
+
});
|
|
9406
|
+
break;
|
|
9407
|
+
}
|
|
8402
9408
|
case "phase.taskCompleted": {
|
|
8403
9409
|
const p = payload;
|
|
8404
9410
|
const existing = stateRef.current.autoPhase?.phases[p.phaseId];
|
|
@@ -8412,6 +9418,13 @@ function useAutoPhaseEvents(subscribeAutoPhase, dispatch, stateRef) {
|
|
|
8412
9418
|
totalTasks: existing.totalTasks
|
|
8413
9419
|
});
|
|
8414
9420
|
}
|
|
9421
|
+
dispatch({
|
|
9422
|
+
type: "autoPhaseTaskActive",
|
|
9423
|
+
phaseId: p.phaseId,
|
|
9424
|
+
taskId: p.taskId,
|
|
9425
|
+
title: "",
|
|
9426
|
+
active: false
|
|
9427
|
+
});
|
|
8415
9428
|
break;
|
|
8416
9429
|
}
|
|
8417
9430
|
case "autonomous.tick": {
|
|
@@ -8430,6 +9443,11 @@ function useAutoPhaseEvents(subscribeAutoPhase, dispatch, stateRef) {
|
|
|
8430
9443
|
dispatch({ type: "autoPhaseReset" });
|
|
8431
9444
|
break;
|
|
8432
9445
|
}
|
|
9446
|
+
case "sdd.board.snapshot": {
|
|
9447
|
+
const p = payload;
|
|
9448
|
+
if (p.snapshot) dispatch({ type: "sddBoardSnapshot", snapshot: p.snapshot });
|
|
9449
|
+
break;
|
|
9450
|
+
}
|
|
8433
9451
|
case "worktree.allocated": {
|
|
8434
9452
|
const p = payload;
|
|
8435
9453
|
dispatch({
|
|
@@ -8764,6 +9782,7 @@ function closePanels(state) {
|
|
|
8764
9782
|
projectPicker: { ...state.projectPicker, open: false },
|
|
8765
9783
|
fKeyPicker: { ...state.fKeyPicker, open: false },
|
|
8766
9784
|
autoPhase: state.autoPhase ? { ...state.autoPhase, monitorOpen: false } : state.autoPhase,
|
|
9785
|
+
sddBoard: state.sddBoard ? { ...state.sddBoard, monitorOpen: false } : state.sddBoard,
|
|
8767
9786
|
worktreeMonitorOpen: false,
|
|
8768
9787
|
coordinator: { ...state.coordinator, monitorOpen: false }
|
|
8769
9788
|
};
|
|
@@ -9905,12 +10924,31 @@ function reducer(state, action) {
|
|
|
9905
10924
|
status: action.status,
|
|
9906
10925
|
completedTasks: action.completedTasks,
|
|
9907
10926
|
totalTasks: action.totalTasks,
|
|
9908
|
-
startedAt: action.startedAt
|
|
10927
|
+
startedAt: action.startedAt,
|
|
10928
|
+
// Preserve the live worker list across status/count updates.
|
|
10929
|
+
activeTasks: existing.phases[action.phaseId]?.activeTasks
|
|
9909
10930
|
}
|
|
9910
10931
|
}
|
|
9911
10932
|
}
|
|
9912
10933
|
};
|
|
9913
10934
|
}
|
|
10935
|
+
case "autoPhaseTaskActive": {
|
|
10936
|
+
if (!state.autoPhase) return state;
|
|
10937
|
+
const phase = state.autoPhase.phases[action.phaseId];
|
|
10938
|
+
if (!phase) return state;
|
|
10939
|
+
const without = (phase.activeTasks ?? []).filter((t) => t.taskId !== action.taskId);
|
|
10940
|
+
const activeTasks = action.active ? [...without, { taskId: action.taskId, title: action.title, agent: action.agent }] : without;
|
|
10941
|
+
return {
|
|
10942
|
+
...state,
|
|
10943
|
+
autoPhase: {
|
|
10944
|
+
...state.autoPhase,
|
|
10945
|
+
phases: {
|
|
10946
|
+
...state.autoPhase.phases,
|
|
10947
|
+
[action.phaseId]: { ...phase, activeTasks }
|
|
10948
|
+
}
|
|
10949
|
+
}
|
|
10950
|
+
};
|
|
10951
|
+
}
|
|
9914
10952
|
case "autoPhaseRunningPhases": {
|
|
9915
10953
|
if (!state.autoPhase) return state;
|
|
9916
10954
|
return {
|
|
@@ -9937,6 +10975,22 @@ function reducer(state, action) {
|
|
|
9937
10975
|
case "autoPhaseReset": {
|
|
9938
10976
|
return { ...state, autoPhase: null };
|
|
9939
10977
|
}
|
|
10978
|
+
case "sddBoardSnapshot": {
|
|
10979
|
+
const monitorOpen = state.sddBoard?.monitorOpen ?? false;
|
|
10980
|
+
return { ...state, sddBoard: { snapshot: action.snapshot, monitorOpen } };
|
|
10981
|
+
}
|
|
10982
|
+
case "toggleSddBoardMonitor": {
|
|
10983
|
+
if (!state.sddBoard) return state;
|
|
10984
|
+
const opening = !state.sddBoard.monitorOpen;
|
|
10985
|
+
return opening ? {
|
|
10986
|
+
...state,
|
|
10987
|
+
...closePanels(state),
|
|
10988
|
+
sddBoard: { ...state.sddBoard, monitorOpen: true }
|
|
10989
|
+
} : {
|
|
10990
|
+
...state,
|
|
10991
|
+
sddBoard: { ...state.sddBoard, monitorOpen: false }
|
|
10992
|
+
};
|
|
10993
|
+
}
|
|
9940
10994
|
case "worktreeUpsert": {
|
|
9941
10995
|
const prev = state.worktrees[action.handleId];
|
|
9942
10996
|
const merged = {
|
|
@@ -10369,6 +11423,7 @@ function App({
|
|
|
10369
11423
|
getAutonomy,
|
|
10370
11424
|
getEternalEngine,
|
|
10371
11425
|
getParallelEngine,
|
|
11426
|
+
getSddRun,
|
|
10372
11427
|
subscribeEternalIteration,
|
|
10373
11428
|
subscribeEternalStage,
|
|
10374
11429
|
subscribeAutoPhase,
|
|
@@ -10627,6 +11682,7 @@ function App({
|
|
|
10627
11682
|
eternalStage: null,
|
|
10628
11683
|
goalSummary: null,
|
|
10629
11684
|
autoPhase: null,
|
|
11685
|
+
sddBoard: null,
|
|
10630
11686
|
worktrees: {},
|
|
10631
11687
|
worktreeMonitorOpen: false,
|
|
10632
11688
|
coordinator: {
|
|
@@ -10893,7 +11949,7 @@ function App({
|
|
|
10893
11949
|
readGitInfo(agent.ctx.cwd).then((info) => {
|
|
10894
11950
|
if (cancelled) return;
|
|
10895
11951
|
setGitInfo(info);
|
|
10896
|
-
if (info
|
|
11952
|
+
if (info?.branch) {
|
|
10897
11953
|
const prev = prevBranchRef.current;
|
|
10898
11954
|
if (prev !== null && prev !== info.branch) {
|
|
10899
11955
|
const msg = {
|
|
@@ -12395,9 +13451,12 @@ function App({
|
|
|
12395
13451
|
(e) => e.status === "running"
|
|
12396
13452
|
).length;
|
|
12397
13453
|
const autonomyRunning = eternalLoopRunningRef.current || parallelLoopRunningRef.current || getEternalEngine?.()?.currentState === "running" || getParallelEngine?.()?.currentState === "running";
|
|
12398
|
-
|
|
13454
|
+
const sddRun = getSddRun?.();
|
|
13455
|
+
const sddRunning = sddRun?.isRunning() ?? false;
|
|
13456
|
+
if (autonomyRunning || fleetRunning > 0 || sddRunning) {
|
|
12399
13457
|
getEternalEngine?.()?.stop();
|
|
12400
13458
|
getParallelEngine?.()?.stop();
|
|
13459
|
+
if (sddRunning) sddRun?.stop();
|
|
12401
13460
|
if (autonomyRunning) switchAutonomy?.("off");
|
|
12402
13461
|
if (director) {
|
|
12403
13462
|
const cap = new Promise((resolve) => {
|
|
@@ -12409,6 +13468,7 @@ function App({
|
|
|
12409
13468
|
const killed2 = getProcessRegistry().killAll();
|
|
12410
13469
|
const bits = [];
|
|
12411
13470
|
if (autonomyRunning) bits.push("autonomy stopped");
|
|
13471
|
+
if (sddRunning) bits.push("SDD run stopped");
|
|
12412
13472
|
if (fleetRunning > 0)
|
|
12413
13473
|
bits.push(`${fleetRunning} agent${fleetRunning === 1 ? "" : "s"} terminated`);
|
|
12414
13474
|
if (killed2.length > 0)
|
|
@@ -12434,7 +13494,7 @@ function App({
|
|
|
12434
13494
|
return () => {
|
|
12435
13495
|
process.off("SIGINT", onSigint);
|
|
12436
13496
|
};
|
|
12437
|
-
}, [director, getEternalEngine, getParallelEngine, switchAutonomy, onExit, exit]);
|
|
13497
|
+
}, [director, getEternalEngine, getParallelEngine, getSddRun, switchAutonomy, onExit, exit]);
|
|
12438
13498
|
const commitPaste = async (full) => {
|
|
12439
13499
|
const builder = builderRef.current;
|
|
12440
13500
|
if (!builder || !full) return;
|
|
@@ -13120,6 +14180,42 @@ function App({
|
|
|
13120
14180
|
toggleWorktreeOverlay();
|
|
13121
14181
|
return;
|
|
13122
14182
|
}
|
|
14183
|
+
if (key.ctrl && input === "b") {
|
|
14184
|
+
dispatch({ type: "toggleSddBoardMonitor" });
|
|
14185
|
+
return;
|
|
14186
|
+
}
|
|
14187
|
+
if (state.sddBoard?.monitorOpen && !key.ctrl && !key.meta) {
|
|
14188
|
+
if (input === "c") {
|
|
14189
|
+
const run = getSddRun?.();
|
|
14190
|
+
if (run) {
|
|
14191
|
+
void run.cleanupWorktrees().then((n) => {
|
|
14192
|
+
dispatch({
|
|
14193
|
+
type: "addEntry",
|
|
14194
|
+
entry: {
|
|
14195
|
+
kind: n > 0 ? "info" : "warn",
|
|
14196
|
+
text: n > 0 ? `Cleaned ${n} SDD worktree${n === 1 ? "" : "s"}.` : "No SDD worktrees to clean (stop the run first if it is live)."
|
|
14197
|
+
}
|
|
14198
|
+
});
|
|
14199
|
+
});
|
|
14200
|
+
}
|
|
14201
|
+
return;
|
|
14202
|
+
}
|
|
14203
|
+
if (input === "z") {
|
|
14204
|
+
const run = getSddRun?.();
|
|
14205
|
+
if (run) {
|
|
14206
|
+
void run.rollback().then((r) => {
|
|
14207
|
+
dispatch({
|
|
14208
|
+
type: "addEntry",
|
|
14209
|
+
entry: {
|
|
14210
|
+
kind: r.ok ? "info" : "warn",
|
|
14211
|
+
text: r.ok ? r.reverted > 0 ? `Rolled back ${r.reverted} run commit${r.reverted === 1 ? "" : "s"} (revert commits added).` : "Nothing to roll back." : `Rollback failed: ${r.reason ?? "unknown error"}`
|
|
14212
|
+
}
|
|
14213
|
+
});
|
|
14214
|
+
});
|
|
14215
|
+
}
|
|
14216
|
+
return;
|
|
14217
|
+
}
|
|
14218
|
+
}
|
|
13123
14219
|
if (key.fn === 5) {
|
|
13124
14220
|
if (state.planPanelOpen) {
|
|
13125
14221
|
dispatch({ type: "togglePlanPanel" });
|
|
@@ -13270,7 +14366,7 @@ function App({
|
|
|
13270
14366
|
featureMemory: cfg.featureMemory ?? true,
|
|
13271
14367
|
featureSkills: cfg.featureSkills ?? true,
|
|
13272
14368
|
featureModelsRegistry: cfg.featureModelsRegistry ?? true,
|
|
13273
|
-
tokenSavingTier: cfg.
|
|
14369
|
+
tokenSavingTier: cfg.featureTokenSaving ?? "off",
|
|
13274
14370
|
allowOutsideProjectRoot: cfg.allowOutsideProjectRoot ?? true,
|
|
13275
14371
|
contextAutoCompact: cfg.contextAutoCompact ?? true,
|
|
13276
14372
|
contextStrategy: cfg.contextStrategy ?? "hybrid",
|
|
@@ -14573,7 +15669,7 @@ User message:
|
|
|
14573
15669
|
elapsedMs: state.autoPhase.elapsedMs,
|
|
14574
15670
|
nowTick
|
|
14575
15671
|
}
|
|
14576
|
-
) : state.worktreeMonitorOpen ? /* @__PURE__ */ jsx(
|
|
15672
|
+
) : state.sddBoard?.monitorOpen ? /* @__PURE__ */ jsx(SddBoardOverlay, { snapshot: state.sddBoard.snapshot }) : state.worktreeMonitorOpen ? /* @__PURE__ */ jsx(
|
|
14577
15673
|
WorktreeMonitor,
|
|
14578
15674
|
{
|
|
14579
15675
|
worktrees: state.worktrees,
|
|
@@ -14992,6 +16088,7 @@ async function runTui(opts) {
|
|
|
14992
16088
|
getAutonomy: opts.getAutonomy,
|
|
14993
16089
|
getEternalEngine: opts.getEternalEngine,
|
|
14994
16090
|
getParallelEngine: opts.getParallelEngine,
|
|
16091
|
+
getSddRun: opts.getSddRun,
|
|
14995
16092
|
subscribeEternalIteration: opts.subscribeEternalIteration,
|
|
14996
16093
|
subscribeEternalStage: opts.subscribeEternalStage,
|
|
14997
16094
|
subscribeAutoPhase: opts.subscribeAutoPhase,
|