@wrongstack/tui 0.250.0 → 0.255.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 +2 -2
- package/dist/index.js +131 -7
- package/dist/index.js.map +1 -1
- package/package.json +5 -5
package/dist/index.d.ts
CHANGED
|
@@ -338,8 +338,8 @@ interface RunTuiOptions {
|
|
|
338
338
|
* visible bar without a round-trip. The initial value is loaded from
|
|
339
339
|
* the config file before App mounts.
|
|
340
340
|
*/
|
|
341
|
-
statuslineHiddenItems: Array<'todos' | 'plan' | 'fleet' | 'git' | 'elapsed' | 'context' | 'cost'>;
|
|
342
|
-
setStatuslineHiddenItems: (items: Array<'todos' | 'plan' | 'fleet' | 'git' | 'elapsed' | 'context' | 'cost'>) => void;
|
|
341
|
+
statuslineHiddenItems: Array<'todos' | 'plan' | 'tasks' | 'fleet' | 'git' | 'elapsed' | 'context' | 'cost'>;
|
|
342
|
+
setStatuslineHiddenItems: (items: Array<'todos' | 'plan' | 'tasks' | 'fleet' | 'git' | 'elapsed' | 'context' | 'cost'>) => void;
|
|
343
343
|
/**
|
|
344
344
|
* Controller for the agents monitor overlay. App installs a dispatch-backed
|
|
345
345
|
* setter on mount so the `/agents on|off` slash command can toggle the
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import { writeErr, resolveWstackPaths, loadGoal, InputBuilder, DefaultSessionRewinder, writeOut, formatTodosList, buildGoalPreamble, expectDefined as expectDefined$1,
|
|
1
|
+
import { writeErr, resolveProjectDir, wstackGlobalRoot, GlobalMailbox, resolveWstackPaths, loadGoal, InputBuilder, DefaultSessionRewinder, writeOut, formatTodosList, buildGoalPreamble, expectDefined as expectDefined$1, shouldEnhance, enhanceUserPrompt, recentTextTurns, normalizedEqual, buildChildEnv } from '@wrongstack/core';
|
|
2
2
|
export { buildGoalPreamble } from '@wrongstack/core';
|
|
3
3
|
import { Box as Box$1, useInput, useStdin, useStdout, Text as Text$1, render, useApp, measureElement, Static } from 'ink';
|
|
4
|
+
import { randomUUID } from 'crypto';
|
|
4
5
|
import * as path4 from 'path';
|
|
5
6
|
import React5, { forwardRef, useState, useEffect, useMemo, memo, useRef, useCallback, useReducer, useLayoutEffect } from 'react';
|
|
6
7
|
import * as fs2 from 'fs/promises';
|
|
@@ -86,6 +87,27 @@ var Box = forwardRef(function Box2({ borderColor, backgroundColor, ...rest }, re
|
|
|
86
87
|
}
|
|
87
88
|
);
|
|
88
89
|
});
|
|
90
|
+
function useTokenCounterRefresh(tokenCounter, events) {
|
|
91
|
+
const [data, setData] = useState(
|
|
92
|
+
() => tokenCounter ? {
|
|
93
|
+
usage: tokenCounter.total(),
|
|
94
|
+
cost: tokenCounter.estimateCost(),
|
|
95
|
+
cacheStats: tokenCounter.cacheStats()
|
|
96
|
+
} : void 0
|
|
97
|
+
);
|
|
98
|
+
useEffect(() => {
|
|
99
|
+
if (!tokenCounter || !events) return;
|
|
100
|
+
const off = events.on("token.accounted", () => {
|
|
101
|
+
setData({
|
|
102
|
+
usage: tokenCounter.total(),
|
|
103
|
+
cost: tokenCounter.estimateCost(),
|
|
104
|
+
cacheStats: tokenCounter.cacheStats()
|
|
105
|
+
});
|
|
106
|
+
});
|
|
107
|
+
return off;
|
|
108
|
+
}, [tokenCounter, events]);
|
|
109
|
+
return data;
|
|
110
|
+
}
|
|
89
111
|
var MODE_ICONS = {
|
|
90
112
|
teach: "\u{1F9D1}\u200D\u{1F3EB}",
|
|
91
113
|
brief: "\u26A1",
|
|
@@ -131,6 +153,7 @@ function StatusBar({
|
|
|
131
153
|
processCount,
|
|
132
154
|
context,
|
|
133
155
|
hiddenItems,
|
|
156
|
+
events,
|
|
134
157
|
eternalStage,
|
|
135
158
|
goalSummary,
|
|
136
159
|
indexState,
|
|
@@ -155,9 +178,10 @@ function StatusBar({
|
|
|
155
178
|
const isCompact = termWidth < COMPACT_THRESHOLD;
|
|
156
179
|
const isComfortable = termWidth >= COMFORTABLE_THRESHOLD;
|
|
157
180
|
const hiddenSet = new Set(hiddenItems);
|
|
158
|
-
const
|
|
159
|
-
const
|
|
160
|
-
const
|
|
181
|
+
const tokenData = useTokenCounterRefresh(tokenCounter, events);
|
|
182
|
+
const usage = tokenData?.usage;
|
|
183
|
+
const cost = tokenData?.cost;
|
|
184
|
+
const cache2 = tokenData?.cacheStats;
|
|
161
185
|
const [elapsedMs, setElapsedMs] = useState(startedAt ? Date.now() - startedAt : 0);
|
|
162
186
|
useEffect(() => {
|
|
163
187
|
if (startedAt == null) return;
|
|
@@ -555,7 +579,22 @@ function StatusBar({
|
|
|
555
579
|
/* @__PURE__ */ jsxs(Text, { color: "cyan", children: [
|
|
556
580
|
"\u{1F465} ",
|
|
557
581
|
mailbox.onlineAgents,
|
|
558
|
-
"
|
|
582
|
+
" agent",
|
|
583
|
+
mailbox.onlineAgents === 1 ? "" : "s",
|
|
584
|
+
mailbox.onlineClients.tui + mailbox.onlineClients.webui + mailbox.onlineClients.repl > 0 ? /* @__PURE__ */ jsxs(Text, { color: "green", children: [
|
|
585
|
+
mailbox.onlineClients.tui > 0 ? /* @__PURE__ */ jsxs(Text, { color: "green", children: [
|
|
586
|
+
" \xB7 \u{1F5A5} TUI",
|
|
587
|
+
mailbox.onlineClients.tui > 1 ? `\xD7${mailbox.onlineClients.tui}` : ""
|
|
588
|
+
] }) : null,
|
|
589
|
+
mailbox.onlineClients.webui > 0 ? /* @__PURE__ */ jsxs(Text, { color: "green", children: [
|
|
590
|
+
" \xB7 \u{1F310} WebUI",
|
|
591
|
+
mailbox.onlineClients.webui > 1 ? `\xD7${mailbox.onlineClients.webui}` : ""
|
|
592
|
+
] }) : null,
|
|
593
|
+
mailbox.onlineClients.repl > 0 ? /* @__PURE__ */ jsxs(Text, { color: "green", children: [
|
|
594
|
+
" \xB7 \u2328 REPL",
|
|
595
|
+
mailbox.onlineClients.repl > 1 ? `\xD7${mailbox.onlineClients.repl}` : ""
|
|
596
|
+
] }) : null
|
|
597
|
+
] }) : null
|
|
559
598
|
] }),
|
|
560
599
|
mailbox.lastSubject ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
561
600
|
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" }),
|
|
@@ -4308,6 +4347,15 @@ function startHeapWatchdog(opts = {}) {
|
|
|
4308
4347
|
}).catch(() => void 0);
|
|
4309
4348
|
};
|
|
4310
4349
|
const tick = () => {
|
|
4350
|
+
let userTimings = 0;
|
|
4351
|
+
try {
|
|
4352
|
+
userTimings = performance.getEntriesByType("mark").length + performance.getEntriesByType("measure").length;
|
|
4353
|
+
if (userTimings > 0) {
|
|
4354
|
+
performance.clearMarks();
|
|
4355
|
+
performance.clearMeasures();
|
|
4356
|
+
}
|
|
4357
|
+
} catch {
|
|
4358
|
+
}
|
|
4311
4359
|
const s2 = takeHeapSample();
|
|
4312
4360
|
if (s2.load >= criticalAt && criticalArmed) {
|
|
4313
4361
|
criticalArmed = false;
|
|
@@ -4336,7 +4384,7 @@ function startHeapWatchdog(opts = {}) {
|
|
|
4336
4384
|
extras = opts.collectStats?.() ?? {};
|
|
4337
4385
|
} catch {
|
|
4338
4386
|
}
|
|
4339
|
-
append(JSON.stringify({ pid: process.pid, ...s2, ...extras }));
|
|
4387
|
+
append(JSON.stringify({ pid: process.pid, ...s2, userTimings, ...extras }));
|
|
4340
4388
|
}
|
|
4341
4389
|
};
|
|
4342
4390
|
const timer = setInterval(tick, sampleEveryMs);
|
|
@@ -6931,6 +6979,7 @@ function useSessionEvents(events, dispatch, onClearHistory) {
|
|
|
6931
6979
|
const offRewound = events.on("session.rewound", () => {
|
|
6932
6980
|
dispatch({ type: "sessionRewound", toPromptIndex: 0 });
|
|
6933
6981
|
dispatch({ type: "clearHistory" });
|
|
6982
|
+
dispatch({ type: "resetContextChip" });
|
|
6934
6983
|
onClearHistory?.(dispatch);
|
|
6935
6984
|
});
|
|
6936
6985
|
return () => {
|
|
@@ -9148,7 +9197,8 @@ function App({
|
|
|
9148
9197
|
}, [getLiveSessions]);
|
|
9149
9198
|
const [mailboxStatus, setMailboxStatus] = useState({
|
|
9150
9199
|
unread: 0,
|
|
9151
|
-
onlineAgents: 0
|
|
9200
|
+
onlineAgents: 0,
|
|
9201
|
+
onlineClients: { tui: 0, webui: 0, repl: 0 }
|
|
9152
9202
|
});
|
|
9153
9203
|
useEffect(() => {
|
|
9154
9204
|
const seenAgents = /* @__PURE__ */ new Set();
|
|
@@ -9174,11 +9224,25 @@ function App({
|
|
|
9174
9224
|
if (p?.agentId) seenAgents.add(p.agentId);
|
|
9175
9225
|
setMailboxStatus((prev) => ({ ...prev, onlineAgents: seenAgents.size }));
|
|
9176
9226
|
});
|
|
9227
|
+
const unsub5 = events.onPattern("mailbox.sync_clients", (_e, payload) => {
|
|
9228
|
+
const p = payload;
|
|
9229
|
+
if (p) {
|
|
9230
|
+
setMailboxStatus((prev) => ({
|
|
9231
|
+
...prev,
|
|
9232
|
+
onlineClients: {
|
|
9233
|
+
tui: p.tui ?? 0,
|
|
9234
|
+
webui: p.webui ?? 0,
|
|
9235
|
+
repl: p.repl ?? 0
|
|
9236
|
+
}
|
|
9237
|
+
}));
|
|
9238
|
+
}
|
|
9239
|
+
});
|
|
9177
9240
|
return () => {
|
|
9178
9241
|
unsub1();
|
|
9179
9242
|
unsub2();
|
|
9180
9243
|
unsub3();
|
|
9181
9244
|
unsub4();
|
|
9245
|
+
unsub5();
|
|
9182
9246
|
};
|
|
9183
9247
|
}, [events]);
|
|
9184
9248
|
const [mailboxPanelOpen, setMailboxPanelOpen] = useState(false);
|
|
@@ -12248,6 +12312,7 @@ User message:
|
|
|
12248
12312
|
subagentCount: Object.keys(state.fleet).length,
|
|
12249
12313
|
processCount: getProcessRegistry().activeCount,
|
|
12250
12314
|
hiddenItems,
|
|
12315
|
+
events,
|
|
12251
12316
|
eternalStage: state.eternalStage,
|
|
12252
12317
|
goalSummary: state.goalSummary,
|
|
12253
12318
|
indexState,
|
|
@@ -12523,6 +12588,7 @@ async function runTui(opts) {
|
|
|
12523
12588
|
const cleanup = () => {
|
|
12524
12589
|
if (cleaned) return;
|
|
12525
12590
|
cleaned = true;
|
|
12591
|
+
unregisterTuiClient();
|
|
12526
12592
|
unsilenceTerminal();
|
|
12527
12593
|
try {
|
|
12528
12594
|
stopTitle();
|
|
@@ -12549,6 +12615,64 @@ async function runTui(opts) {
|
|
|
12549
12615
|
}
|
|
12550
12616
|
process.off("exit", exitHandler);
|
|
12551
12617
|
};
|
|
12618
|
+
let clientHeartbeatTimer = null;
|
|
12619
|
+
let clientSyncTimer = null;
|
|
12620
|
+
const CLIENT_HEARTBEAT_MS = 15e3;
|
|
12621
|
+
const CLIENT_SYNC_MS = 3e4;
|
|
12622
|
+
const registerTuiClient = async () => {
|
|
12623
|
+
if (!opts.projectRoot) return null;
|
|
12624
|
+
try {
|
|
12625
|
+
const projectDir = resolveProjectDir(opts.projectRoot, wstackGlobalRoot());
|
|
12626
|
+
const mailbox = new GlobalMailbox(projectDir, opts.events);
|
|
12627
|
+
const clientId = `tui@${randomUUID().slice(0, 8)}`;
|
|
12628
|
+
await mailbox.registerClient({
|
|
12629
|
+
clientId,
|
|
12630
|
+
sessionId: opts.projectRoot,
|
|
12631
|
+
name: `TUI [${path4.basename(opts.projectRoot)}]`,
|
|
12632
|
+
source: "tui",
|
|
12633
|
+
pid: process.pid
|
|
12634
|
+
});
|
|
12635
|
+
clientHeartbeatTimer = setInterval(() => {
|
|
12636
|
+
mailbox.clientHeartbeat({ clientId }).catch(() => {
|
|
12637
|
+
});
|
|
12638
|
+
}, CLIENT_HEARTBEAT_MS);
|
|
12639
|
+
clientHeartbeatTimer.unref();
|
|
12640
|
+
const syncClients = async () => {
|
|
12641
|
+
try {
|
|
12642
|
+
const statuses = await mailbox.getClientStatuses();
|
|
12643
|
+
const counts = { tui: 0, webui: 0, repl: 0 };
|
|
12644
|
+
for (const s2 of statuses) {
|
|
12645
|
+
if (s2.online && s2.source in counts) {
|
|
12646
|
+
counts[s2.source]++;
|
|
12647
|
+
}
|
|
12648
|
+
}
|
|
12649
|
+
opts.events.emitCustom("mailbox.sync_clients", counts);
|
|
12650
|
+
} catch {
|
|
12651
|
+
}
|
|
12652
|
+
};
|
|
12653
|
+
setTimeout(() => {
|
|
12654
|
+
void syncClients();
|
|
12655
|
+
}, 5e3);
|
|
12656
|
+
clientSyncTimer = setInterval(() => {
|
|
12657
|
+
void syncClients();
|
|
12658
|
+
}, CLIENT_SYNC_MS);
|
|
12659
|
+
clientSyncTimer.unref();
|
|
12660
|
+
return clientId;
|
|
12661
|
+
} catch {
|
|
12662
|
+
return null;
|
|
12663
|
+
}
|
|
12664
|
+
};
|
|
12665
|
+
const unregisterTuiClient = () => {
|
|
12666
|
+
if (clientHeartbeatTimer) {
|
|
12667
|
+
clearInterval(clientHeartbeatTimer);
|
|
12668
|
+
clientHeartbeatTimer = null;
|
|
12669
|
+
}
|
|
12670
|
+
if (clientSyncTimer) {
|
|
12671
|
+
clearInterval(clientSyncTimer);
|
|
12672
|
+
clientSyncTimer = null;
|
|
12673
|
+
}
|
|
12674
|
+
};
|
|
12675
|
+
registerTuiClient();
|
|
12552
12676
|
return new Promise((resolve) => {
|
|
12553
12677
|
let exitCode = 0;
|
|
12554
12678
|
let hardExitTimer = null;
|