@wrongstack/tui 0.7.2 → 0.7.3
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.js +231 -10
- package/dist/index.js.map +1 -1
- package/package.json +4 -4
package/dist/index.js
CHANGED
|
@@ -847,6 +847,133 @@ function FleetMonitor({
|
|
|
847
847
|
] }) : null
|
|
848
848
|
] });
|
|
849
849
|
}
|
|
850
|
+
var STATUS2 = {
|
|
851
|
+
idle: { icon: "\u25CB", color: "gray" },
|
|
852
|
+
running: { icon: "\u25B6", color: "yellow" },
|
|
853
|
+
success: { icon: "\u2713", color: "green" },
|
|
854
|
+
failed: { icon: "\u2717", color: "red" },
|
|
855
|
+
timeout: { icon: "\u23F1", color: "yellow" },
|
|
856
|
+
stopped: { icon: "\u2298", color: "gray" }
|
|
857
|
+
};
|
|
858
|
+
function fmtTokens2(n) {
|
|
859
|
+
if (n < 1e3) return String(n);
|
|
860
|
+
if (n < 1e6) return `${(n / 1e3).toFixed(1)}k`;
|
|
861
|
+
return `${(n / 1e6).toFixed(1)}M`;
|
|
862
|
+
}
|
|
863
|
+
function AgentsMonitor({
|
|
864
|
+
entries,
|
|
865
|
+
totalCost,
|
|
866
|
+
totalTokens,
|
|
867
|
+
nowTick
|
|
868
|
+
}) {
|
|
869
|
+
const all = Object.values(entries);
|
|
870
|
+
const running = all.filter((e) => e.status === "running");
|
|
871
|
+
const done = all.filter((e) => e.status === "success").length;
|
|
872
|
+
const failed = all.filter((e) => e.status === "failed" || e.status === "timeout").length;
|
|
873
|
+
const maxTools = Math.max(1, ...all.map((e) => e.toolCalls));
|
|
874
|
+
const ordered = [...all].sort((a, b) => {
|
|
875
|
+
const ra = a.status === "running" ? 0 : a.status === "idle" ? 1 : 2;
|
|
876
|
+
const rb = b.status === "running" ? 0 : b.status === "idle" ? 1 : 2;
|
|
877
|
+
if (ra !== rb) return ra - rb;
|
|
878
|
+
return a.startedAt - b.startedAt;
|
|
879
|
+
});
|
|
880
|
+
const shown = ordered.slice(0, 20);
|
|
881
|
+
const events = [];
|
|
882
|
+
for (const e of all) {
|
|
883
|
+
events.push({ at: e.startedAt, icon: "\u25CF", color: "cyan", text: `${e.name} spawned` });
|
|
884
|
+
if (e.status !== "running" && e.status !== "idle") {
|
|
885
|
+
const s = STATUS2[e.status];
|
|
886
|
+
events.push({
|
|
887
|
+
at: e.lastEventAt,
|
|
888
|
+
icon: s.icon,
|
|
889
|
+
color: s.color,
|
|
890
|
+
text: `${e.name} ${e.status} (${e.toolCalls}t)`
|
|
891
|
+
});
|
|
892
|
+
}
|
|
893
|
+
if (e.budgetWarning) {
|
|
894
|
+
events.push({
|
|
895
|
+
at: e.budgetWarning.at,
|
|
896
|
+
icon: "\u26A1",
|
|
897
|
+
color: "yellow",
|
|
898
|
+
text: `${e.name} ${e.budgetWarning.kind} ${e.budgetWarning.used}/${e.budgetWarning.limit} \u2014 extending`
|
|
899
|
+
});
|
|
900
|
+
}
|
|
901
|
+
}
|
|
902
|
+
events.sort((a, b) => b.at - a.at);
|
|
903
|
+
const timeline = events.slice(0, 6);
|
|
904
|
+
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", borderStyle: "round", borderColor: "magenta", paddingX: 1, children: [
|
|
905
|
+
/* @__PURE__ */ jsxs(Box, { flexDirection: "row", gap: 1, children: [
|
|
906
|
+
/* @__PURE__ */ jsx(Text, { bold: true, color: "magenta", children: "AGENTS MONITOR" }),
|
|
907
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" }),
|
|
908
|
+
/* @__PURE__ */ jsxs(Text, { color: "yellow", children: [
|
|
909
|
+
"\u25B6",
|
|
910
|
+
running.length
|
|
911
|
+
] }),
|
|
912
|
+
/* @__PURE__ */ jsxs(Text, { color: "green", children: [
|
|
913
|
+
"\u2713",
|
|
914
|
+
done
|
|
915
|
+
] }),
|
|
916
|
+
failed > 0 ? /* @__PURE__ */ jsxs(Text, { color: "red", children: [
|
|
917
|
+
"\u2717",
|
|
918
|
+
failed
|
|
919
|
+
] }) : null,
|
|
920
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "\xB7 Ctrl+Shift+M to close" })
|
|
921
|
+
] }),
|
|
922
|
+
/* @__PURE__ */ jsxs(Box, { flexDirection: "row", gap: 1, children: [
|
|
923
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "agents" }),
|
|
924
|
+
/* @__PURE__ */ jsx(Text, { color: "magenta", children: all.length }),
|
|
925
|
+
totalTokens ? /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
926
|
+
fmtTokens2(totalTokens.input),
|
|
927
|
+
"\u2191 ",
|
|
928
|
+
fmtTokens2(totalTokens.output),
|
|
929
|
+
"\u2193"
|
|
930
|
+
] }) : null,
|
|
931
|
+
/* @__PURE__ */ jsx(Text, { color: "green", children: ` $${totalCost.toFixed(3)}` })
|
|
932
|
+
] }),
|
|
933
|
+
shown.length === 0 ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: "No subagents yet \u2014 spawn with /spawn or /fleet dispatch." }) : null,
|
|
934
|
+
shown.map((e) => {
|
|
935
|
+
const s = STATUS2[e.status];
|
|
936
|
+
const elapsed = e.status === "running" ? fmtElapsed(Math.max(0, nowTick - e.startedAt)) : e.status;
|
|
937
|
+
const spark = sparkline(bucketActivity(e.recentTools, nowTick));
|
|
938
|
+
const tool = e.currentTool?.name ?? e.recentTools[e.recentTools.length - 1]?.name ?? "";
|
|
939
|
+
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", children: [
|
|
940
|
+
/* @__PURE__ */ jsxs(Box, { flexDirection: "row", gap: 1, children: [
|
|
941
|
+
/* @__PURE__ */ jsx(Text, { color: s.color, bold: true, children: s.icon }),
|
|
942
|
+
/* @__PURE__ */ jsx(Text, { bold: true, children: e.name.padEnd(14).slice(0, 14) }),
|
|
943
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: elapsed.padEnd(8).slice(0, 8) }),
|
|
944
|
+
/* @__PURE__ */ jsx(Text, { color: "cyan", children: renderProgress(e.toolCalls / maxTools, 10) }),
|
|
945
|
+
/* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
946
|
+
"L",
|
|
947
|
+
e.iterations,
|
|
948
|
+
" ",
|
|
949
|
+
e.toolCalls,
|
|
950
|
+
"t"
|
|
951
|
+
] }),
|
|
952
|
+
e.extensions && e.extensions > 0 ? /* @__PURE__ */ jsxs(Text, { color: "yellow", children: [
|
|
953
|
+
"\u26A1\xD7",
|
|
954
|
+
e.extensions
|
|
955
|
+
] }) : null
|
|
956
|
+
] }),
|
|
957
|
+
/* @__PURE__ */ jsxs(Box, { flexDirection: "row", gap: 1, children: [
|
|
958
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: " " }),
|
|
959
|
+
/* @__PURE__ */ jsx(Text, { color: "green", children: spark }),
|
|
960
|
+
tool ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: tool }) : null
|
|
961
|
+
] })
|
|
962
|
+
] }, e.id);
|
|
963
|
+
}),
|
|
964
|
+
timeline.length > 0 ? /* @__PURE__ */ jsxs(Box, { flexDirection: "column", marginTop: 1, children: [
|
|
965
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "timeline" }),
|
|
966
|
+
timeline.map((ev, i) => (
|
|
967
|
+
// biome-ignore lint/suspicious/noArrayIndexKey: timeline is rebuilt per render
|
|
968
|
+
/* @__PURE__ */ jsxs(Box, { flexDirection: "row", gap: 1, children: [
|
|
969
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: `${fmtElapsed(Math.max(0, nowTick - ev.at))} ago`.padEnd(10) }),
|
|
970
|
+
/* @__PURE__ */ jsx(Text, { color: ev.color, children: ev.icon }),
|
|
971
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: ev.text })
|
|
972
|
+
] }, i)
|
|
973
|
+
))
|
|
974
|
+
] }) : null
|
|
975
|
+
] });
|
|
976
|
+
}
|
|
850
977
|
|
|
851
978
|
// src/markdown-table.ts
|
|
852
979
|
function renderMarkdownTables(text, maxWidth) {
|
|
@@ -1136,10 +1263,16 @@ function Entry({
|
|
|
1136
1263
|
switch (entry.kind) {
|
|
1137
1264
|
case "user":
|
|
1138
1265
|
return /* @__PURE__ */ jsxs(Text, { children: [
|
|
1139
|
-
/* @__PURE__ */ jsx(Text, {
|
|
1140
|
-
|
|
1141
|
-
/* @__PURE__ */ jsx(Text, { dimColor:
|
|
1142
|
-
entry.
|
|
1266
|
+
/* @__PURE__ */ jsx(Text, { bold: true, color: "yellow", children: "USER: " }),
|
|
1267
|
+
/* @__PURE__ */ jsx(Text, { color: "white", children: entry.text }),
|
|
1268
|
+
entry.queued ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: " (queued)" }) : null,
|
|
1269
|
+
entry.pasteContent ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
1270
|
+
entry.text ? "\n" : null,
|
|
1271
|
+
/* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
1272
|
+
" \u21B3 ",
|
|
1273
|
+
entry.pasteContent
|
|
1274
|
+
] })
|
|
1275
|
+
] }) : null
|
|
1143
1276
|
] });
|
|
1144
1277
|
case "assistant":
|
|
1145
1278
|
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", marginY: 1, children: [
|
|
@@ -2501,20 +2634,31 @@ function reducer(state, action) {
|
|
|
2501
2634
|
case "setBuffer":
|
|
2502
2635
|
return { ...state, buffer: action.buffer, cursor: action.cursor };
|
|
2503
2636
|
case "addPlaceholder":
|
|
2504
|
-
return {
|
|
2637
|
+
return {
|
|
2638
|
+
...state,
|
|
2639
|
+
placeholders: [...state.placeholders, action.ph],
|
|
2640
|
+
placeholderContents: [...state.placeholderContents, action.content ?? ""]
|
|
2641
|
+
};
|
|
2505
2642
|
case "removeLastPlaceholder":
|
|
2506
2643
|
if (state.placeholders.length === 0) return state;
|
|
2507
|
-
return {
|
|
2644
|
+
return {
|
|
2645
|
+
...state,
|
|
2646
|
+
placeholders: state.placeholders.slice(0, -1),
|
|
2647
|
+
placeholderContents: state.placeholderContents.slice(0, -1)
|
|
2648
|
+
};
|
|
2508
2649
|
case "clearInput":
|
|
2509
2650
|
return {
|
|
2510
2651
|
...state,
|
|
2511
2652
|
buffer: "",
|
|
2512
2653
|
cursor: 0,
|
|
2513
2654
|
placeholders: [],
|
|
2655
|
+
placeholderContents: [],
|
|
2514
2656
|
historyIndex: 0,
|
|
2515
2657
|
picker: { open: false, query: "", matches: [], selected: 0 },
|
|
2516
2658
|
slashPicker: { open: false, query: "", matches: [], selected: 0 }
|
|
2517
2659
|
};
|
|
2660
|
+
case "clearPlaceholdersOnly":
|
|
2661
|
+
return { ...state, placeholders: [], placeholderContents: [] };
|
|
2518
2662
|
case "clearHistory": {
|
|
2519
2663
|
const last = state.entries[state.entries.length - 1];
|
|
2520
2664
|
return {
|
|
@@ -2965,6 +3109,9 @@ function reducer(state, action) {
|
|
|
2965
3109
|
case "toggleMonitor": {
|
|
2966
3110
|
return { ...state, monitorOpen: !state.monitorOpen };
|
|
2967
3111
|
}
|
|
3112
|
+
case "toggleAgentsMonitor": {
|
|
3113
|
+
return { ...state, agentsMonitorOpen: !state.agentsMonitorOpen };
|
|
3114
|
+
}
|
|
2968
3115
|
case "checkpointReceived": {
|
|
2969
3116
|
const existing = state.checkpoints.find((c) => c.promptIndex === action.cp.promptIndex);
|
|
2970
3117
|
if (existing) return state;
|
|
@@ -3125,6 +3272,7 @@ function App({
|
|
|
3125
3272
|
buffer: "",
|
|
3126
3273
|
cursor: 0,
|
|
3127
3274
|
placeholders: [],
|
|
3275
|
+
placeholderContents: [],
|
|
3128
3276
|
streamingText: "",
|
|
3129
3277
|
toolStream: null,
|
|
3130
3278
|
status: "idle",
|
|
@@ -3155,6 +3303,7 @@ function App({
|
|
|
3155
3303
|
fleetTokens: { input: 0, output: 0 },
|
|
3156
3304
|
streamFleet: true,
|
|
3157
3305
|
monitorOpen: false,
|
|
3306
|
+
agentsMonitorOpen: false,
|
|
3158
3307
|
checkpoints: [],
|
|
3159
3308
|
rewindOverlay: null,
|
|
3160
3309
|
eternalStage: null,
|
|
@@ -3196,6 +3345,10 @@ function App({
|
|
|
3196
3345
|
draftRef.current = { buffer: "", cursor: 0 };
|
|
3197
3346
|
dispatch({ type: "clearInput" });
|
|
3198
3347
|
};
|
|
3348
|
+
const clearPlaceholdersOnly = () => {
|
|
3349
|
+
draftRef.current = { buffer: "", cursor: 0 };
|
|
3350
|
+
dispatch({ type: "clearPlaceholdersOnly" });
|
|
3351
|
+
};
|
|
3199
3352
|
const startedAtRef = useRef(Date.now());
|
|
3200
3353
|
const [nowTick, setNowTick] = React2.useState(Date.now());
|
|
3201
3354
|
useEffect(() => {
|
|
@@ -3634,6 +3787,20 @@ function App({
|
|
|
3634
3787
|
slashRegistry.unregister("rewind");
|
|
3635
3788
|
};
|
|
3636
3789
|
}, [slashRegistry, handleRewindTo]);
|
|
3790
|
+
useEffect(() => {
|
|
3791
|
+
const cmd = {
|
|
3792
|
+
name: "agents",
|
|
3793
|
+
description: "Toggle the agents monitor overlay.",
|
|
3794
|
+
async run() {
|
|
3795
|
+
dispatch({ type: "toggleAgentsMonitor" });
|
|
3796
|
+
return { message: void 0 };
|
|
3797
|
+
}
|
|
3798
|
+
};
|
|
3799
|
+
slashRegistry.register(cmd);
|
|
3800
|
+
return () => {
|
|
3801
|
+
slashRegistry.unregister("agents");
|
|
3802
|
+
};
|
|
3803
|
+
}, [slashRegistry]);
|
|
3637
3804
|
useEffect(() => {
|
|
3638
3805
|
if (!getPickableProviders || !switchProviderAndModel) return;
|
|
3639
3806
|
const cmd = {
|
|
@@ -3651,6 +3818,23 @@ function App({
|
|
|
3651
3818
|
slashRegistry.unregister("model");
|
|
3652
3819
|
};
|
|
3653
3820
|
}, [slashRegistry, getPickableProviders, switchProviderAndModel]);
|
|
3821
|
+
useEffect(() => {
|
|
3822
|
+
const cmd = {
|
|
3823
|
+
name: "agents",
|
|
3824
|
+
description: "Open or close the agents monitor overlay.",
|
|
3825
|
+
async run(args) {
|
|
3826
|
+
if (args.trim().toLowerCase() === "monitor") {
|
|
3827
|
+
dispatch({ type: "toggleAgentsMonitor" });
|
|
3828
|
+
return { message: "Agents monitor toggled." };
|
|
3829
|
+
}
|
|
3830
|
+
return { message: "Usage: /agents monitor" };
|
|
3831
|
+
}
|
|
3832
|
+
};
|
|
3833
|
+
slashRegistry.register(cmd);
|
|
3834
|
+
return () => {
|
|
3835
|
+
slashRegistry.unregister("agents");
|
|
3836
|
+
};
|
|
3837
|
+
}, [slashRegistry]);
|
|
3654
3838
|
useEffect(() => {
|
|
3655
3839
|
if (!switchAutonomy) return;
|
|
3656
3840
|
const cmd = {
|
|
@@ -4307,13 +4491,25 @@ function App({
|
|
|
4307
4491
|
process.off("SIGINT", onSigint);
|
|
4308
4492
|
};
|
|
4309
4493
|
}, [director, getEternalEngine, getParallelEngine, switchAutonomy, onExit, exit]);
|
|
4494
|
+
const truncatePastePreview = (text, lines) => {
|
|
4495
|
+
const all = text.split("\n");
|
|
4496
|
+
if (all.length <= lines) return text;
|
|
4497
|
+
const head = all.slice(0, lines).join("\n");
|
|
4498
|
+
return `${head}
|
|
4499
|
+
... (${all.length - lines} more lines)`;
|
|
4500
|
+
};
|
|
4310
4501
|
const commitPaste = async (full) => {
|
|
4311
4502
|
const builder = builderRef.current;
|
|
4312
4503
|
if (!builder || !full) return;
|
|
4313
4504
|
if (builder.wouldCollapse(full) || full.includes("\n")) {
|
|
4314
4505
|
const lineCount = full.split("\n").length;
|
|
4315
4506
|
const ph = await builder.appendPaste(full);
|
|
4316
|
-
|
|
4507
|
+
const preview = truncatePastePreview(full, 6);
|
|
4508
|
+
dispatch({
|
|
4509
|
+
type: "addPlaceholder",
|
|
4510
|
+
ph: `${ph ?? "[pasted]"} (${lineCount} lines)`,
|
|
4511
|
+
content: preview
|
|
4512
|
+
});
|
|
4317
4513
|
return;
|
|
4318
4514
|
}
|
|
4319
4515
|
const { buffer, cursor } = draftRef.current;
|
|
@@ -4534,10 +4730,18 @@ function App({
|
|
|
4534
4730
|
dispatch({ type: "toggleMonitor" });
|
|
4535
4731
|
return;
|
|
4536
4732
|
}
|
|
4733
|
+
if (key.ctrl && key.shift && input === "M") {
|
|
4734
|
+
dispatch({ type: "toggleAgentsMonitor" });
|
|
4735
|
+
return;
|
|
4736
|
+
}
|
|
4537
4737
|
if (key.escape && state.monitorOpen) {
|
|
4538
4738
|
dispatch({ type: "toggleMonitor" });
|
|
4539
4739
|
return;
|
|
4540
4740
|
}
|
|
4741
|
+
if (key.escape && state.agentsMonitorOpen) {
|
|
4742
|
+
dispatch({ type: "toggleAgentsMonitor" });
|
|
4743
|
+
return;
|
|
4744
|
+
}
|
|
4541
4745
|
if (isEnter) {
|
|
4542
4746
|
const now = Date.now();
|
|
4543
4747
|
if (now - lastEnterAtRef.current < 50) return;
|
|
@@ -4929,18 +5133,26 @@ User message:
|
|
|
4929
5133
|
}
|
|
4930
5134
|
if (steering) dispatch({ type: "steerConsume" });
|
|
4931
5135
|
const displayText = trimmed ? steering ? `\u21AF ${trimmed}` : trimmed : "(attachments only)";
|
|
5136
|
+
const pasteParts = [];
|
|
5137
|
+
for (let i = 0; i < state.placeholders.length; i++) {
|
|
5138
|
+
const label = state.placeholders[i];
|
|
5139
|
+
const content = state.placeholderContents[i] ?? "";
|
|
5140
|
+
pasteParts.push(label);
|
|
5141
|
+
if (content) pasteParts.push(` ${content.split("\n").slice(0, 6).join("\n ")}`);
|
|
5142
|
+
}
|
|
5143
|
+
const pasteContent = pasteParts.length > 0 ? pasteParts.join("\n") : void 0;
|
|
4932
5144
|
pushSubmittedHistory();
|
|
4933
|
-
|
|
5145
|
+
clearPlaceholdersOnly();
|
|
4934
5146
|
const blocks = await builder.submit();
|
|
4935
5147
|
if (state.status !== "idle") {
|
|
4936
5148
|
dispatch({
|
|
4937
5149
|
type: "addEntry",
|
|
4938
|
-
entry: { kind: "user", text: displayText, queued: true }
|
|
5150
|
+
entry: { kind: "user", text: displayText, queued: true, pasteContent }
|
|
4939
5151
|
});
|
|
4940
5152
|
dispatch({ type: "enqueue", item: { displayText, blocks } });
|
|
4941
5153
|
return;
|
|
4942
5154
|
}
|
|
4943
|
-
dispatch({ type: "addEntry", entry: { kind: "user", text: displayText } });
|
|
5155
|
+
dispatch({ type: "addEntry", entry: { kind: "user", text: displayText, pasteContent } });
|
|
4944
5156
|
await runBlocks(blocks);
|
|
4945
5157
|
};
|
|
4946
5158
|
const bootInjectedRef = useRef(false);
|
|
@@ -5089,6 +5301,15 @@ User message:
|
|
|
5089
5301
|
goalSummary: state.goalSummary
|
|
5090
5302
|
}
|
|
5091
5303
|
),
|
|
5304
|
+
state.agentsMonitorOpen ? /* @__PURE__ */ jsx(
|
|
5305
|
+
AgentsMonitor,
|
|
5306
|
+
{
|
|
5307
|
+
entries: state.fleet,
|
|
5308
|
+
totalCost: state.fleetCost,
|
|
5309
|
+
totalTokens: state.fleetTokens,
|
|
5310
|
+
nowTick
|
|
5311
|
+
}
|
|
5312
|
+
) : null,
|
|
5092
5313
|
state.monitorOpen ? /* @__PURE__ */ jsx(
|
|
5093
5314
|
FleetMonitor,
|
|
5094
5315
|
{
|