@wrongstack/tui 0.7.2 → 0.7.4
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 +232 -12
- 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 {
|
|
@@ -2893,10 +3037,9 @@ function reducer(state, action) {
|
|
|
2893
3037
|
case "fleetUsage": {
|
|
2894
3038
|
const cur = state.fleet[action.id];
|
|
2895
3039
|
if (!cur) return state;
|
|
2896
|
-
const cost = cur.cost;
|
|
2897
3040
|
return {
|
|
2898
3041
|
...state,
|
|
2899
|
-
fleet: { ...state.fleet, [action.id]: { ...cur,
|
|
3042
|
+
fleet: { ...state.fleet, [action.id]: { ...cur, lastEventAt: Date.now() } }
|
|
2900
3043
|
};
|
|
2901
3044
|
}
|
|
2902
3045
|
case "fleetDone": {
|
|
@@ -2965,6 +3108,9 @@ function reducer(state, action) {
|
|
|
2965
3108
|
case "toggleMonitor": {
|
|
2966
3109
|
return { ...state, monitorOpen: !state.monitorOpen };
|
|
2967
3110
|
}
|
|
3111
|
+
case "toggleAgentsMonitor": {
|
|
3112
|
+
return { ...state, agentsMonitorOpen: !state.agentsMonitorOpen };
|
|
3113
|
+
}
|
|
2968
3114
|
case "checkpointReceived": {
|
|
2969
3115
|
const existing = state.checkpoints.find((c) => c.promptIndex === action.cp.promptIndex);
|
|
2970
3116
|
if (existing) return state;
|
|
@@ -3125,6 +3271,7 @@ function App({
|
|
|
3125
3271
|
buffer: "",
|
|
3126
3272
|
cursor: 0,
|
|
3127
3273
|
placeholders: [],
|
|
3274
|
+
placeholderContents: [],
|
|
3128
3275
|
streamingText: "",
|
|
3129
3276
|
toolStream: null,
|
|
3130
3277
|
status: "idle",
|
|
@@ -3155,6 +3302,7 @@ function App({
|
|
|
3155
3302
|
fleetTokens: { input: 0, output: 0 },
|
|
3156
3303
|
streamFleet: true,
|
|
3157
3304
|
monitorOpen: false,
|
|
3305
|
+
agentsMonitorOpen: false,
|
|
3158
3306
|
checkpoints: [],
|
|
3159
3307
|
rewindOverlay: null,
|
|
3160
3308
|
eternalStage: null,
|
|
@@ -3196,6 +3344,10 @@ function App({
|
|
|
3196
3344
|
draftRef.current = { buffer: "", cursor: 0 };
|
|
3197
3345
|
dispatch({ type: "clearInput" });
|
|
3198
3346
|
};
|
|
3347
|
+
const clearPlaceholdersOnly = () => {
|
|
3348
|
+
draftRef.current = { buffer: "", cursor: 0 };
|
|
3349
|
+
dispatch({ type: "clearPlaceholdersOnly" });
|
|
3350
|
+
};
|
|
3199
3351
|
const startedAtRef = useRef(Date.now());
|
|
3200
3352
|
const [nowTick, setNowTick] = React2.useState(Date.now());
|
|
3201
3353
|
useEffect(() => {
|
|
@@ -3634,6 +3786,20 @@ function App({
|
|
|
3634
3786
|
slashRegistry.unregister("rewind");
|
|
3635
3787
|
};
|
|
3636
3788
|
}, [slashRegistry, handleRewindTo]);
|
|
3789
|
+
useEffect(() => {
|
|
3790
|
+
const cmd = {
|
|
3791
|
+
name: "agents",
|
|
3792
|
+
description: "Toggle the agents monitor overlay.",
|
|
3793
|
+
async run() {
|
|
3794
|
+
dispatch({ type: "toggleAgentsMonitor" });
|
|
3795
|
+
return { message: void 0 };
|
|
3796
|
+
}
|
|
3797
|
+
};
|
|
3798
|
+
slashRegistry.register(cmd);
|
|
3799
|
+
return () => {
|
|
3800
|
+
slashRegistry.unregister("agents");
|
|
3801
|
+
};
|
|
3802
|
+
}, [slashRegistry]);
|
|
3637
3803
|
useEffect(() => {
|
|
3638
3804
|
if (!getPickableProviders || !switchProviderAndModel) return;
|
|
3639
3805
|
const cmd = {
|
|
@@ -3651,6 +3817,23 @@ function App({
|
|
|
3651
3817
|
slashRegistry.unregister("model");
|
|
3652
3818
|
};
|
|
3653
3819
|
}, [slashRegistry, getPickableProviders, switchProviderAndModel]);
|
|
3820
|
+
useEffect(() => {
|
|
3821
|
+
const cmd = {
|
|
3822
|
+
name: "agents",
|
|
3823
|
+
description: "Open or close the agents monitor overlay.",
|
|
3824
|
+
async run(args) {
|
|
3825
|
+
if (args.trim().toLowerCase() === "monitor") {
|
|
3826
|
+
dispatch({ type: "toggleAgentsMonitor" });
|
|
3827
|
+
return { message: "Agents monitor toggled." };
|
|
3828
|
+
}
|
|
3829
|
+
return { message: "Usage: /agents monitor" };
|
|
3830
|
+
}
|
|
3831
|
+
};
|
|
3832
|
+
slashRegistry.register(cmd);
|
|
3833
|
+
return () => {
|
|
3834
|
+
slashRegistry.unregister("agents");
|
|
3835
|
+
};
|
|
3836
|
+
}, [slashRegistry]);
|
|
3654
3837
|
useEffect(() => {
|
|
3655
3838
|
if (!switchAutonomy) return;
|
|
3656
3839
|
const cmd = {
|
|
@@ -4307,13 +4490,25 @@ function App({
|
|
|
4307
4490
|
process.off("SIGINT", onSigint);
|
|
4308
4491
|
};
|
|
4309
4492
|
}, [director, getEternalEngine, getParallelEngine, switchAutonomy, onExit, exit]);
|
|
4493
|
+
const truncatePastePreview = (text, lines) => {
|
|
4494
|
+
const all = text.split("\n");
|
|
4495
|
+
if (all.length <= lines) return text;
|
|
4496
|
+
const head = all.slice(0, lines).join("\n");
|
|
4497
|
+
return `${head}
|
|
4498
|
+
... (${all.length - lines} more lines)`;
|
|
4499
|
+
};
|
|
4310
4500
|
const commitPaste = async (full) => {
|
|
4311
4501
|
const builder = builderRef.current;
|
|
4312
4502
|
if (!builder || !full) return;
|
|
4313
4503
|
if (builder.wouldCollapse(full) || full.includes("\n")) {
|
|
4314
4504
|
const lineCount = full.split("\n").length;
|
|
4315
4505
|
const ph = await builder.appendPaste(full);
|
|
4316
|
-
|
|
4506
|
+
const preview = truncatePastePreview(full, 6);
|
|
4507
|
+
dispatch({
|
|
4508
|
+
type: "addPlaceholder",
|
|
4509
|
+
ph: `${ph ?? "[pasted]"} (${lineCount} lines)`,
|
|
4510
|
+
content: preview
|
|
4511
|
+
});
|
|
4317
4512
|
return;
|
|
4318
4513
|
}
|
|
4319
4514
|
const { buffer, cursor } = draftRef.current;
|
|
@@ -4534,10 +4729,18 @@ function App({
|
|
|
4534
4729
|
dispatch({ type: "toggleMonitor" });
|
|
4535
4730
|
return;
|
|
4536
4731
|
}
|
|
4732
|
+
if (key.ctrl && key.shift && input === "M") {
|
|
4733
|
+
dispatch({ type: "toggleAgentsMonitor" });
|
|
4734
|
+
return;
|
|
4735
|
+
}
|
|
4537
4736
|
if (key.escape && state.monitorOpen) {
|
|
4538
4737
|
dispatch({ type: "toggleMonitor" });
|
|
4539
4738
|
return;
|
|
4540
4739
|
}
|
|
4740
|
+
if (key.escape && state.agentsMonitorOpen) {
|
|
4741
|
+
dispatch({ type: "toggleAgentsMonitor" });
|
|
4742
|
+
return;
|
|
4743
|
+
}
|
|
4541
4744
|
if (isEnter) {
|
|
4542
4745
|
const now = Date.now();
|
|
4543
4746
|
if (now - lastEnterAtRef.current < 50) return;
|
|
@@ -4929,18 +5132,26 @@ User message:
|
|
|
4929
5132
|
}
|
|
4930
5133
|
if (steering) dispatch({ type: "steerConsume" });
|
|
4931
5134
|
const displayText = trimmed ? steering ? `\u21AF ${trimmed}` : trimmed : "(attachments only)";
|
|
5135
|
+
const pasteParts = [];
|
|
5136
|
+
for (let i = 0; i < state.placeholders.length; i++) {
|
|
5137
|
+
const label = state.placeholders[i];
|
|
5138
|
+
const content = state.placeholderContents[i] ?? "";
|
|
5139
|
+
pasteParts.push(label);
|
|
5140
|
+
if (content) pasteParts.push(` ${content.split("\n").slice(0, 6).join("\n ")}`);
|
|
5141
|
+
}
|
|
5142
|
+
const pasteContent = pasteParts.length > 0 ? pasteParts.join("\n") : void 0;
|
|
4932
5143
|
pushSubmittedHistory();
|
|
4933
|
-
|
|
5144
|
+
clearPlaceholdersOnly();
|
|
4934
5145
|
const blocks = await builder.submit();
|
|
4935
5146
|
if (state.status !== "idle") {
|
|
4936
5147
|
dispatch({
|
|
4937
5148
|
type: "addEntry",
|
|
4938
|
-
entry: { kind: "user", text: displayText, queued: true }
|
|
5149
|
+
entry: { kind: "user", text: displayText, queued: true, pasteContent }
|
|
4939
5150
|
});
|
|
4940
5151
|
dispatch({ type: "enqueue", item: { displayText, blocks } });
|
|
4941
5152
|
return;
|
|
4942
5153
|
}
|
|
4943
|
-
dispatch({ type: "addEntry", entry: { kind: "user", text: displayText } });
|
|
5154
|
+
dispatch({ type: "addEntry", entry: { kind: "user", text: displayText, pasteContent } });
|
|
4944
5155
|
await runBlocks(blocks);
|
|
4945
5156
|
};
|
|
4946
5157
|
const bootInjectedRef = useRef(false);
|
|
@@ -5089,6 +5300,15 @@ User message:
|
|
|
5089
5300
|
goalSummary: state.goalSummary
|
|
5090
5301
|
}
|
|
5091
5302
|
),
|
|
5303
|
+
state.agentsMonitorOpen ? /* @__PURE__ */ jsx(
|
|
5304
|
+
AgentsMonitor,
|
|
5305
|
+
{
|
|
5306
|
+
entries: state.fleet,
|
|
5307
|
+
totalCost: state.fleetCost,
|
|
5308
|
+
totalTokens: state.fleetTokens,
|
|
5309
|
+
nowTick
|
|
5310
|
+
}
|
|
5311
|
+
) : null,
|
|
5092
5312
|
state.monitorOpen ? /* @__PURE__ */ jsx(
|
|
5093
5313
|
FleetMonitor,
|
|
5094
5314
|
{
|