@wrongstack/tui 0.250.0 → 0.256.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 +28 -9
- package/dist/index.js +280 -42
- package/dist/index.js.map +1 -1
- package/package.json +6 -5
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,
|
|
@@ -140,7 +163,9 @@ function StatusBar({
|
|
|
140
163
|
nextStepsAutoSubmitCountdown,
|
|
141
164
|
autoProceedCountdown,
|
|
142
165
|
sessionCount,
|
|
143
|
-
mailbox
|
|
166
|
+
mailbox,
|
|
167
|
+
tokenSavingMode,
|
|
168
|
+
toolCount
|
|
144
169
|
}) {
|
|
145
170
|
const { stdout } = useStdout();
|
|
146
171
|
const [termWidth, setTermWidth] = useState(stdout?.columns ?? 90);
|
|
@@ -155,9 +180,10 @@ function StatusBar({
|
|
|
155
180
|
const isCompact = termWidth < COMPACT_THRESHOLD;
|
|
156
181
|
const isComfortable = termWidth >= COMFORTABLE_THRESHOLD;
|
|
157
182
|
const hiddenSet = new Set(hiddenItems);
|
|
158
|
-
const
|
|
159
|
-
const
|
|
160
|
-
const
|
|
183
|
+
const tokenData = useTokenCounterRefresh(tokenCounter, events);
|
|
184
|
+
const usage = tokenData?.usage;
|
|
185
|
+
const cost = tokenData?.cost;
|
|
186
|
+
const cache2 = tokenData?.cacheStats;
|
|
161
187
|
const [elapsedMs, setElapsedMs] = useState(startedAt ? Date.now() - startedAt : 0);
|
|
162
188
|
useEffect(() => {
|
|
163
189
|
if (startedAt == null) return;
|
|
@@ -178,7 +204,7 @@ function StatusBar({
|
|
|
178
204
|
const statePrefix = state === "idle" || state === "aborting" ? "\u25CF" : spinner;
|
|
179
205
|
const thinking = state === "running" || state === "streaming";
|
|
180
206
|
const hasAutoProceed = autoProceedCountdown != null && autoProceedCountdown > 0;
|
|
181
|
-
const hasSecondLine = yolo || autonomy && autonomy !== "off" || startedAt != null || git !== null && git !== void 0 || projectName !== void 0 && projectName.length > 0 || workingDir !== void 0 && workingDir.length > 0 || goalSummary !== null && goalSummary !== void 0 || !!modeLabel || hasAutoProceed;
|
|
207
|
+
const hasSecondLine = yolo || autonomy && autonomy !== "off" || startedAt != null || git !== null && git !== void 0 || projectName !== void 0 && projectName.length > 0 || workingDir !== void 0 && workingDir.length > 0 || goalSummary !== null && goalSummary !== void 0 || !!modeLabel || hasAutoProceed || tokenSavingMode || typeof toolCount === "number" && toolCount > 0;
|
|
182
208
|
const fleetHasActivity = fleet && (fleet.running > 0 || fleet.idle > 0 || fleet.pending > 0 || fleet.completed > 0) || subagentCount > 0;
|
|
183
209
|
const hasBrainActivity = !!brain && brain.state !== "idle";
|
|
184
210
|
const hasDebugStream = !!debugStreamStats;
|
|
@@ -399,6 +425,19 @@ function StatusBar({
|
|
|
399
425
|
" session",
|
|
400
426
|
sessionCount === 1 ? "" : "s"
|
|
401
427
|
] })
|
|
428
|
+
] }) : null,
|
|
429
|
+
toolCount != null ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
430
|
+
yolo || startedAt != null || projectName || workingDir || git || sessionCount ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" }) : null,
|
|
431
|
+
/* @__PURE__ */ jsxs(Text, { color: "cyan", children: [
|
|
432
|
+
"\u{1F527} ",
|
|
433
|
+
toolCount,
|
|
434
|
+
" tool",
|
|
435
|
+
toolCount === 1 ? "" : "s"
|
|
436
|
+
] })
|
|
437
|
+
] }) : null,
|
|
438
|
+
tokenSavingMode ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
439
|
+
yolo || startedAt != null || projectName || workingDir || git || sessionCount || toolCount ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" }) : null,
|
|
440
|
+
/* @__PURE__ */ jsx(Text, { color: "yellow", bold: true, children: "\u{1F4BE} save" })
|
|
402
441
|
] }) : null
|
|
403
442
|
] }) : /* @__PURE__ */ jsx(Box, { height: 1, children: /* @__PURE__ */ jsx(Text, { children: " " }) }),
|
|
404
443
|
hasThirdLine ? /* @__PURE__ */ jsxs(Box, { flexDirection: "row", gap: 2, children: [
|
|
@@ -555,7 +594,22 @@ function StatusBar({
|
|
|
555
594
|
/* @__PURE__ */ jsxs(Text, { color: "cyan", children: [
|
|
556
595
|
"\u{1F465} ",
|
|
557
596
|
mailbox.onlineAgents,
|
|
558
|
-
"
|
|
597
|
+
" agent",
|
|
598
|
+
mailbox.onlineAgents === 1 ? "" : "s",
|
|
599
|
+
mailbox.onlineClients.tui + mailbox.onlineClients.webui + mailbox.onlineClients.repl > 0 ? /* @__PURE__ */ jsxs(Text, { color: "green", children: [
|
|
600
|
+
mailbox.onlineClients.tui > 0 ? /* @__PURE__ */ jsxs(Text, { color: "green", children: [
|
|
601
|
+
" \xB7 \u{1F5A5} TUI",
|
|
602
|
+
mailbox.onlineClients.tui > 1 ? `\xD7${mailbox.onlineClients.tui}` : ""
|
|
603
|
+
] }) : null,
|
|
604
|
+
mailbox.onlineClients.webui > 0 ? /* @__PURE__ */ jsxs(Text, { color: "green", children: [
|
|
605
|
+
" \xB7 \u{1F310} WebUI",
|
|
606
|
+
mailbox.onlineClients.webui > 1 ? `\xD7${mailbox.onlineClients.webui}` : ""
|
|
607
|
+
] }) : null,
|
|
608
|
+
mailbox.onlineClients.repl > 0 ? /* @__PURE__ */ jsxs(Text, { color: "green", children: [
|
|
609
|
+
" \xB7 \u2328 REPL",
|
|
610
|
+
mailbox.onlineClients.repl > 1 ? `\xD7${mailbox.onlineClients.repl}` : ""
|
|
611
|
+
] }) : null
|
|
612
|
+
] }) : null
|
|
559
613
|
] }),
|
|
560
614
|
mailbox.lastSubject ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
561
615
|
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" }),
|
|
@@ -2807,7 +2861,7 @@ function MarkdownView({
|
|
|
2807
2861
|
const tableEnd = detectTable(lines, i);
|
|
2808
2862
|
if (tableEnd > i) {
|
|
2809
2863
|
rows.push(
|
|
2810
|
-
/* @__PURE__ */ jsx(Text, { children: renderTable(lines.slice(i, tableEnd), tableBudget) }, `t${key++}`)
|
|
2864
|
+
/* @__PURE__ */ jsx(Box, { width: tableBudget, backgroundColor: "transparent", children: /* @__PURE__ */ jsx(Text, { children: renderTable(lines.slice(i, tableEnd), tableBudget) }) }, `t${key++}`)
|
|
2811
2865
|
);
|
|
2812
2866
|
i = tableEnd;
|
|
2813
2867
|
continue;
|
|
@@ -2827,10 +2881,14 @@ function MarkdownView({
|
|
|
2827
2881
|
rows.push(
|
|
2828
2882
|
/* @__PURE__ */ jsxs(Box, { flexDirection: "row", children: [
|
|
2829
2883
|
/* @__PURE__ */ jsx(Text, { dimColor: true, children: " " }),
|
|
2830
|
-
/[\u2500-\u257F]/.test(qContent) ?
|
|
2831
|
-
|
|
2832
|
-
|
|
2833
|
-
|
|
2884
|
+
/[\u2500-\u257F]/.test(qContent) ? (
|
|
2885
|
+
// Box-drawing characters inside blockquotes also need transparent
|
|
2886
|
+
// background to avoid inheriting the message panel background.
|
|
2887
|
+
/* @__PURE__ */ jsx(Box, { flexDirection: "row", backgroundColor: "transparent", children: [...qContent].slice(0, (contentWidth ?? termWidth) - 2).map((ch, ci) => (
|
|
2888
|
+
/* biome-ignore lint/suspicious/noArrayIndexKey: characters are not reorderable */
|
|
2889
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: ch }, ci)
|
|
2890
|
+
)) })
|
|
2891
|
+
) : /* @__PURE__ */ jsx(InlineLine, { tokens: parseInline(qContent), dim: true })
|
|
2834
2892
|
] }, `q${key++}`)
|
|
2835
2893
|
);
|
|
2836
2894
|
continue;
|
|
@@ -2859,7 +2917,7 @@ function MarkdownView({
|
|
|
2859
2917
|
const maxW = contentWidth ?? termWidth;
|
|
2860
2918
|
const chars = [...line].slice(0, maxW);
|
|
2861
2919
|
rows.push(
|
|
2862
|
-
/* @__PURE__ */ jsx(Box, { flexDirection: "row", children: chars.map((ch, ci) => (
|
|
2920
|
+
/* @__PURE__ */ jsx(Box, { width: maxW, backgroundColor: "transparent", flexDirection: "row", children: chars.map((ch, ci) => (
|
|
2863
2921
|
/* biome-ignore lint/suspicious/noArrayIndexKey: characters are not reorderable */
|
|
2864
2922
|
/* @__PURE__ */ jsx(Text, { children: ch }, ci)
|
|
2865
2923
|
)) }, `bx${key++}`)
|
|
@@ -3761,11 +3819,12 @@ function Banner({
|
|
|
3761
3819
|
}
|
|
3762
3820
|
|
|
3763
3821
|
// src/components/suggestions.ts
|
|
3764
|
-
var STRICT_HEADING_RE =
|
|
3822
|
+
var STRICT_HEADING_RE = /(?:💡\s*Next steps?|<next_steps>)\s*\n+/i;
|
|
3765
3823
|
var PERMISSIVE_HEADING_PATTERNS = [
|
|
3766
3824
|
{ re: /💡\s*Next steps?\s*\n+/i, label: "emoji" },
|
|
3767
3825
|
{ re: /##?\s*Next steps?\s*\n+/i, label: "markdown" },
|
|
3768
|
-
{ re: /\n{1,2}Next steps?\s*\n+/i, label: "plain" }
|
|
3826
|
+
{ re: /\n{1,2}Next steps?\s*\n+/i, label: "plain" },
|
|
3827
|
+
{ re: /<next_steps>\s*\n+/i, label: "xml-tag" }
|
|
3769
3828
|
];
|
|
3770
3829
|
var ITEM_RE = /^(?:(\d+)[.)]\s*|[-*•]\s*)(.+)$/;
|
|
3771
3830
|
var MAX_STEPS = 6;
|
|
@@ -3849,6 +3908,10 @@ function findBlockEnd(afterHeading, stepCount) {
|
|
|
3849
3908
|
let found = 0;
|
|
3850
3909
|
for (const rawLine of lines) {
|
|
3851
3910
|
const line = rawLine.trim();
|
|
3911
|
+
if (line === "</next_steps>") {
|
|
3912
|
+
consumed += rawLine.length + 1;
|
|
3913
|
+
break;
|
|
3914
|
+
}
|
|
3852
3915
|
if (!line) {
|
|
3853
3916
|
consumed += rawLine.length + 1;
|
|
3854
3917
|
continue;
|
|
@@ -3913,6 +3976,7 @@ var Entry = React5.memo(function Entry2({
|
|
|
3913
3976
|
borderRight: false,
|
|
3914
3977
|
borderBottom: false,
|
|
3915
3978
|
borderColor: theme.user,
|
|
3979
|
+
backgroundColor: "#1e1e2e",
|
|
3916
3980
|
paddingLeft: 1,
|
|
3917
3981
|
children: /* @__PURE__ */ jsxs(Text, { children: [
|
|
3918
3982
|
/* @__PURE__ */ jsx(Text, { bold: true, color: theme.user, children: "USER " }),
|
|
@@ -3942,8 +4006,9 @@ var Entry = React5.memo(function Entry2({
|
|
|
3942
4006
|
borderStyle: "single",
|
|
3943
4007
|
borderTop: false,
|
|
3944
4008
|
borderRight: false,
|
|
3945
|
-
borderBottom:
|
|
4009
|
+
borderBottom: false,
|
|
3946
4010
|
borderColor: theme.assistant,
|
|
4011
|
+
backgroundColor: "#1e1e2e",
|
|
3947
4012
|
paddingLeft: 1,
|
|
3948
4013
|
children: [
|
|
3949
4014
|
/* @__PURE__ */ jsx(Box, { flexDirection: "row", children: /* @__PURE__ */ jsx(Text, { bold: true, color: theme.assistant, children: "ASSISTANT" }) }),
|
|
@@ -4308,6 +4373,15 @@ function startHeapWatchdog(opts = {}) {
|
|
|
4308
4373
|
}).catch(() => void 0);
|
|
4309
4374
|
};
|
|
4310
4375
|
const tick = () => {
|
|
4376
|
+
let userTimings = 0;
|
|
4377
|
+
try {
|
|
4378
|
+
userTimings = performance.getEntriesByType("mark").length + performance.getEntriesByType("measure").length;
|
|
4379
|
+
if (userTimings > 0) {
|
|
4380
|
+
performance.clearMarks();
|
|
4381
|
+
performance.clearMeasures();
|
|
4382
|
+
}
|
|
4383
|
+
} catch {
|
|
4384
|
+
}
|
|
4311
4385
|
const s2 = takeHeapSample();
|
|
4312
4386
|
if (s2.load >= criticalAt && criticalArmed) {
|
|
4313
4387
|
criticalArmed = false;
|
|
@@ -4336,7 +4410,7 @@ function startHeapWatchdog(opts = {}) {
|
|
|
4336
4410
|
extras = opts.collectStats?.() ?? {};
|
|
4337
4411
|
} catch {
|
|
4338
4412
|
}
|
|
4339
|
-
append(JSON.stringify({ pid: process.pid, ...s2, ...extras }));
|
|
4413
|
+
append(JSON.stringify({ pid: process.pid, ...s2, userTimings, ...extras }));
|
|
4340
4414
|
}
|
|
4341
4415
|
};
|
|
4342
4416
|
const timer = setInterval(tick, sampleEveryMs);
|
|
@@ -5495,7 +5569,7 @@ var MODE_DESC = {
|
|
|
5495
5569
|
suggest: "Shows next-step suggestions after each turn",
|
|
5496
5570
|
auto: "Self-driving \u2014 agent continues automatically"
|
|
5497
5571
|
};
|
|
5498
|
-
var SETTINGS_FIELD_COUNT =
|
|
5572
|
+
var SETTINGS_FIELD_COUNT = 26;
|
|
5499
5573
|
var CONFIG_SCOPES = ["global", "project"];
|
|
5500
5574
|
function SettingsPicker({
|
|
5501
5575
|
field,
|
|
@@ -5512,6 +5586,7 @@ function SettingsPicker({
|
|
|
5512
5586
|
featureMemory,
|
|
5513
5587
|
featureSkills,
|
|
5514
5588
|
featureModelsRegistry,
|
|
5589
|
+
featureTokenSaving,
|
|
5515
5590
|
contextAutoCompact,
|
|
5516
5591
|
contextStrategy,
|
|
5517
5592
|
logLevel,
|
|
@@ -5595,6 +5670,11 @@ function SettingsPicker({
|
|
|
5595
5670
|
value: boolVal(featureModelsRegistry),
|
|
5596
5671
|
detail: "Fetch models.dev catalog at startup"
|
|
5597
5672
|
},
|
|
5673
|
+
{
|
|
5674
|
+
label: "Token-saving mode",
|
|
5675
|
+
value: boolVal(featureTokenSaving),
|
|
5676
|
+
detail: "Omit non-essential tools and trim system prompt to save tokens"
|
|
5677
|
+
},
|
|
5598
5678
|
// ── Context ──
|
|
5599
5679
|
{ section: "Context" },
|
|
5600
5680
|
{
|
|
@@ -6695,6 +6775,36 @@ function handleCollabDone(event, dispatch, stateRef) {
|
|
|
6695
6775
|
verdict: payload.report.overallVerdict ?? "needs_revision"
|
|
6696
6776
|
});
|
|
6697
6777
|
}
|
|
6778
|
+
function useStatuslineState(opts) {
|
|
6779
|
+
const [liveModel, setLiveModel] = useState(opts.model);
|
|
6780
|
+
const [liveProvider, setLiveProvider] = useState(opts.provider ?? "agent");
|
|
6781
|
+
const [activeMaxContext, setActiveMaxContext] = useState(opts.effectiveMaxContext);
|
|
6782
|
+
const [yoloLive, setYoloLive] = useState(opts.yolo);
|
|
6783
|
+
const [autonomyLive, setAutonomyLive] = useState(opts.getAutonomy?.() ?? "off");
|
|
6784
|
+
const [liveModeLabel, setLiveModeLabel] = useState(opts.modeLabel ?? "");
|
|
6785
|
+
const [hiddenItems, setHiddenItems] = useState(
|
|
6786
|
+
Array.isArray(opts.statuslineHiddenItems) ? [...opts.statuslineHiddenItems] : [...opts.statuslineHiddenItems]
|
|
6787
|
+
);
|
|
6788
|
+
const [sessionCount, setSessionCount] = useState(0);
|
|
6789
|
+
return {
|
|
6790
|
+
liveModel,
|
|
6791
|
+
setLiveModel,
|
|
6792
|
+
liveProvider,
|
|
6793
|
+
setLiveProvider,
|
|
6794
|
+
activeMaxContext,
|
|
6795
|
+
setActiveMaxContext,
|
|
6796
|
+
yoloLive,
|
|
6797
|
+
setYoloLive,
|
|
6798
|
+
autonomyLive,
|
|
6799
|
+
setAutonomyLive,
|
|
6800
|
+
liveModeLabel,
|
|
6801
|
+
setLiveModeLabel,
|
|
6802
|
+
hiddenItems,
|
|
6803
|
+
setHiddenItems,
|
|
6804
|
+
sessionCount,
|
|
6805
|
+
setSessionCount
|
|
6806
|
+
};
|
|
6807
|
+
}
|
|
6698
6808
|
function useTuiControllers({
|
|
6699
6809
|
dispatch,
|
|
6700
6810
|
streamFleet,
|
|
@@ -6931,6 +7041,7 @@ function useSessionEvents(events, dispatch, onClearHistory) {
|
|
|
6931
7041
|
const offRewound = events.on("session.rewound", () => {
|
|
6932
7042
|
dispatch({ type: "sessionRewound", toPromptIndex: 0 });
|
|
6933
7043
|
dispatch({ type: "clearHistory" });
|
|
7044
|
+
dispatch({ type: "resetContextChip" });
|
|
6934
7045
|
onClearHistory?.(dispatch);
|
|
6935
7046
|
});
|
|
6936
7047
|
return () => {
|
|
@@ -7760,6 +7871,7 @@ function reducer(state, action) {
|
|
|
7760
7871
|
featureMemory: action.featureMemory,
|
|
7761
7872
|
featureSkills: action.featureSkills,
|
|
7762
7873
|
featureModelsRegistry: action.featureModelsRegistry,
|
|
7874
|
+
featureTokenSaving: action.featureTokenSaving,
|
|
7763
7875
|
contextAutoCompact: action.contextAutoCompact,
|
|
7764
7876
|
contextStrategy: action.contextStrategy,
|
|
7765
7877
|
logLevel: action.logLevel,
|
|
@@ -7817,53 +7929,54 @@ function reducer(state, action) {
|
|
|
7817
7929
|
if (f === 10) return { ...state, settingsPicker: { ...sp, featureMemory: !sp.featureMemory, hint: void 0 } };
|
|
7818
7930
|
if (f === 11) return { ...state, settingsPicker: { ...sp, featureSkills: !sp.featureSkills, hint: void 0 } };
|
|
7819
7931
|
if (f === 12) return { ...state, settingsPicker: { ...sp, featureModelsRegistry: !sp.featureModelsRegistry, hint: void 0 } };
|
|
7820
|
-
if (f === 13) return { ...state, settingsPicker: { ...sp,
|
|
7821
|
-
if (f === 14) {
|
|
7932
|
+
if (f === 13) return { ...state, settingsPicker: { ...sp, featureTokenSaving: !sp.featureTokenSaving, hint: void 0 } };
|
|
7933
|
+
if (f === 14) return { ...state, settingsPicker: { ...sp, contextAutoCompact: !sp.contextAutoCompact, hint: void 0 } };
|
|
7934
|
+
if (f === 15) {
|
|
7822
7935
|
const i = COMPACTOR_STRATEGIES.indexOf(sp.contextStrategy);
|
|
7823
7936
|
const base = i < 0 ? 0 : i;
|
|
7824
7937
|
const next = (base + action.delta + COMPACTOR_STRATEGIES.length) % COMPACTOR_STRATEGIES.length;
|
|
7825
7938
|
return { ...state, settingsPicker: { ...sp, contextStrategy: expectDefined$1(COMPACTOR_STRATEGIES[next]), hint: void 0 } };
|
|
7826
7939
|
}
|
|
7827
|
-
if (f ===
|
|
7940
|
+
if (f === 16) {
|
|
7828
7941
|
const i = LOG_LEVELS.indexOf(sp.logLevel);
|
|
7829
7942
|
const base = i < 0 ? 0 : i;
|
|
7830
7943
|
const next = (base + action.delta + LOG_LEVELS.length) % LOG_LEVELS.length;
|
|
7831
7944
|
return { ...state, settingsPicker: { ...sp, logLevel: expectDefined$1(LOG_LEVELS[next]), hint: void 0 } };
|
|
7832
7945
|
}
|
|
7833
|
-
if (f ===
|
|
7946
|
+
if (f === 17) {
|
|
7834
7947
|
const i = AUDIT_LEVELS.indexOf(sp.auditLevel);
|
|
7835
7948
|
const base = i < 0 ? 0 : i;
|
|
7836
7949
|
const next = (base + action.delta + AUDIT_LEVELS.length) % AUDIT_LEVELS.length;
|
|
7837
7950
|
return { ...state, settingsPicker: { ...sp, auditLevel: expectDefined$1(AUDIT_LEVELS[next]), hint: void 0 } };
|
|
7838
7951
|
}
|
|
7839
|
-
if (f ===
|
|
7840
|
-
if (f ===
|
|
7952
|
+
if (f === 18) return { ...state, settingsPicker: { ...sp, indexOnStart: !sp.indexOnStart, hint: void 0 } };
|
|
7953
|
+
if (f === 19) {
|
|
7841
7954
|
const j = MAX_ITERATIONS_PRESETS.indexOf(sp.maxIterations);
|
|
7842
7955
|
const base = j < 0 ? 0 : j;
|
|
7843
7956
|
const next = (base + action.delta + MAX_ITERATIONS_PRESETS.length) % MAX_ITERATIONS_PRESETS.length;
|
|
7844
7957
|
return { ...state, settingsPicker: { ...sp, maxIterations: expectDefined$1(MAX_ITERATIONS_PRESETS[next]), hint: void 0 } };
|
|
7845
7958
|
}
|
|
7846
|
-
if (f ===
|
|
7959
|
+
if (f === 20) {
|
|
7847
7960
|
const aj = AUTO_PROCEED_MAX_PRESETS.indexOf(sp.autoProceedMaxIterations);
|
|
7848
7961
|
const abase = aj < 0 ? 0 : aj;
|
|
7849
7962
|
const anext = (abase + action.delta + AUTO_PROCEED_MAX_PRESETS.length) % AUTO_PROCEED_MAX_PRESETS.length;
|
|
7850
7963
|
return { ...state, settingsPicker: { ...sp, autoProceedMaxIterations: expectDefined$1(AUTO_PROCEED_MAX_PRESETS[anext]), hint: void 0 } };
|
|
7851
7964
|
}
|
|
7852
|
-
if (f ===
|
|
7965
|
+
if (f === 21) {
|
|
7853
7966
|
const ej = ENHANCE_DELAY_PRESETS.indexOf(sp.enhanceDelayMs);
|
|
7854
7967
|
const ebase = ej < 0 ? 0 : ej;
|
|
7855
7968
|
const enext = (ebase + action.delta + ENHANCE_DELAY_PRESETS.length) % ENHANCE_DELAY_PRESETS.length;
|
|
7856
7969
|
return { ...state, settingsPicker: { ...sp, enhanceDelayMs: expectDefined$1(ENHANCE_DELAY_PRESETS[enext]), hint: void 0 } };
|
|
7857
7970
|
}
|
|
7858
|
-
if (f ===
|
|
7859
|
-
if (f ===
|
|
7971
|
+
if (f === 22) return { ...state, settingsPicker: { ...sp, enhanceEnabled: !sp.enhanceEnabled, hint: void 0 } };
|
|
7972
|
+
if (f === 23) {
|
|
7860
7973
|
const i = ENHANCE_LANGUAGES.indexOf(sp.enhanceLanguage);
|
|
7861
7974
|
const base = i < 0 ? 0 : i;
|
|
7862
7975
|
const next = (base + action.delta + ENHANCE_LANGUAGES.length) % ENHANCE_LANGUAGES.length;
|
|
7863
7976
|
return { ...state, settingsPicker: { ...sp, enhanceLanguage: expectDefined$1(ENHANCE_LANGUAGES[next]), hint: void 0 } };
|
|
7864
7977
|
}
|
|
7865
|
-
if (f ===
|
|
7866
|
-
if (f ===
|
|
7978
|
+
if (f === 24) return { ...state, settingsPicker: { ...sp, debugStream: !sp.debugStream, hint: void 0 } };
|
|
7979
|
+
if (f === 25) {
|
|
7867
7980
|
const i = CONFIG_SCOPES.indexOf(sp.configScope);
|
|
7868
7981
|
const base = i < 0 ? 0 : i;
|
|
7869
7982
|
const next = (base + action.delta + CONFIG_SCOPES.length) % CONFIG_SCOPES.length;
|
|
@@ -8702,6 +8815,8 @@ function App({
|
|
|
8702
8815
|
provider,
|
|
8703
8816
|
family,
|
|
8704
8817
|
keyTail,
|
|
8818
|
+
tokenSavingMode,
|
|
8819
|
+
toolCount,
|
|
8705
8820
|
getPickableProviders,
|
|
8706
8821
|
switchProviderAndModel,
|
|
8707
8822
|
getSettings,
|
|
@@ -8719,6 +8834,7 @@ function App({
|
|
|
8719
8834
|
listSessions,
|
|
8720
8835
|
onResumeSession,
|
|
8721
8836
|
fleetStreamController,
|
|
8837
|
+
interruptController,
|
|
8722
8838
|
statuslineHiddenItems,
|
|
8723
8839
|
setStatuslineHiddenItems,
|
|
8724
8840
|
agentsMonitorController,
|
|
@@ -8739,14 +8855,32 @@ function App({
|
|
|
8739
8855
|
}) {
|
|
8740
8856
|
const { exit } = useApp();
|
|
8741
8857
|
const { stdout } = useStdout();
|
|
8742
|
-
const
|
|
8743
|
-
|
|
8744
|
-
|
|
8745
|
-
|
|
8746
|
-
|
|
8747
|
-
|
|
8748
|
-
|
|
8749
|
-
|
|
8858
|
+
const {
|
|
8859
|
+
liveModel,
|
|
8860
|
+
setLiveModel,
|
|
8861
|
+
liveProvider,
|
|
8862
|
+
setLiveProvider,
|
|
8863
|
+
activeMaxContext,
|
|
8864
|
+
setActiveMaxContext,
|
|
8865
|
+
yoloLive,
|
|
8866
|
+
setYoloLive,
|
|
8867
|
+
autonomyLive,
|
|
8868
|
+
setAutonomyLive,
|
|
8869
|
+
liveModeLabel,
|
|
8870
|
+
setLiveModeLabel,
|
|
8871
|
+
hiddenItems,
|
|
8872
|
+
setHiddenItems,
|
|
8873
|
+
sessionCount,
|
|
8874
|
+
setSessionCount
|
|
8875
|
+
} = useStatuslineState({
|
|
8876
|
+
model,
|
|
8877
|
+
provider,
|
|
8878
|
+
effectiveMaxContext,
|
|
8879
|
+
yolo,
|
|
8880
|
+
getAutonomy,
|
|
8881
|
+
modeLabel,
|
|
8882
|
+
statuslineHiddenItems
|
|
8883
|
+
});
|
|
8750
8884
|
const prevBranchRef = useRef(null);
|
|
8751
8885
|
const [indexState, setIndexState] = useState(() => getIndexState());
|
|
8752
8886
|
useEffect(() => {
|
|
@@ -8754,7 +8888,7 @@ function App({
|
|
|
8754
8888
|
return onIndexStateChange((next) => setIndexState(next));
|
|
8755
8889
|
}, []);
|
|
8756
8890
|
useEffect(() => {
|
|
8757
|
-
setHiddenItems(statuslineHiddenItems);
|
|
8891
|
+
setHiddenItems([...statuslineHiddenItems]);
|
|
8758
8892
|
}, [statuslineHiddenItems]);
|
|
8759
8893
|
useEffect(() => {
|
|
8760
8894
|
setStatuslineHiddenItems(hiddenItems);
|
|
@@ -8850,7 +8984,7 @@ function App({
|
|
|
8850
8984
|
},
|
|
8851
8985
|
autonomyPicker: { open: false, options: [], selected: 0 },
|
|
8852
8986
|
resumePicker: { open: false, sessions: [], selected: 0, busy: false, hint: void 0, error: void 0 },
|
|
8853
|
-
settingsPicker: { open: false, field: 0, mode: "off", delayMs: 0, titleAnimation: true, yolo: false, streamFleet: true, chime: false, confirmExit: true, nextPrediction: false, featureMcp: true, featurePlugins: true, featureMemory: true, featureSkills: true, featureModelsRegistry: true, contextAutoCompact: true, contextStrategy: "hybrid", logLevel: "info", auditLevel: "standard", indexOnStart: true, maxIterations: 500, autoProceedMaxIterations: 50, enhanceDelayMs: 6e4, enhanceEnabled: true, enhanceLanguage: "original", debugStream: false, configScope: "global" },
|
|
8987
|
+
settingsPicker: { open: false, field: 0, mode: "off", delayMs: 0, titleAnimation: true, yolo: false, streamFleet: true, chime: false, confirmExit: true, nextPrediction: false, featureMcp: true, featurePlugins: true, featureMemory: true, featureSkills: true, featureModelsRegistry: true, featureTokenSaving: false, contextAutoCompact: true, contextStrategy: "hybrid", logLevel: "info", auditLevel: "standard", indexOnStart: true, maxIterations: 500, autoProceedMaxIterations: 50, enhanceDelayMs: 6e4, enhanceEnabled: true, enhanceLanguage: "original", debugStream: false, configScope: "global" },
|
|
8854
8988
|
projectPicker: { open: false, allItems: [], items: [], selected: 0, filter: "", hint: void 0 },
|
|
8855
8989
|
confirmQueue: [],
|
|
8856
8990
|
enhance: null,
|
|
@@ -9148,7 +9282,8 @@ function App({
|
|
|
9148
9282
|
}, [getLiveSessions]);
|
|
9149
9283
|
const [mailboxStatus, setMailboxStatus] = useState({
|
|
9150
9284
|
unread: 0,
|
|
9151
|
-
onlineAgents: 0
|
|
9285
|
+
onlineAgents: 0,
|
|
9286
|
+
onlineClients: { tui: 0, webui: 0, repl: 0 }
|
|
9152
9287
|
});
|
|
9153
9288
|
useEffect(() => {
|
|
9154
9289
|
const seenAgents = /* @__PURE__ */ new Set();
|
|
@@ -9174,11 +9309,25 @@ function App({
|
|
|
9174
9309
|
if (p?.agentId) seenAgents.add(p.agentId);
|
|
9175
9310
|
setMailboxStatus((prev) => ({ ...prev, onlineAgents: seenAgents.size }));
|
|
9176
9311
|
});
|
|
9312
|
+
const unsub5 = events.onPattern("mailbox.sync_clients", (_e, payload) => {
|
|
9313
|
+
const p = payload;
|
|
9314
|
+
if (p) {
|
|
9315
|
+
setMailboxStatus((prev) => ({
|
|
9316
|
+
...prev,
|
|
9317
|
+
onlineClients: {
|
|
9318
|
+
tui: p.tui ?? 0,
|
|
9319
|
+
webui: p.webui ?? 0,
|
|
9320
|
+
repl: p.repl ?? 0
|
|
9321
|
+
}
|
|
9322
|
+
}));
|
|
9323
|
+
}
|
|
9324
|
+
});
|
|
9177
9325
|
return () => {
|
|
9178
9326
|
unsub1();
|
|
9179
9327
|
unsub2();
|
|
9180
9328
|
unsub3();
|
|
9181
9329
|
unsub4();
|
|
9330
|
+
unsub5();
|
|
9182
9331
|
};
|
|
9183
9332
|
}, [events]);
|
|
9184
9333
|
const [mailboxPanelOpen, setMailboxPanelOpen] = useState(false);
|
|
@@ -9467,6 +9616,7 @@ function App({
|
|
|
9467
9616
|
featureMemory: sp.featureMemory,
|
|
9468
9617
|
featureSkills: sp.featureSkills,
|
|
9469
9618
|
featureModelsRegistry: sp.featureModelsRegistry,
|
|
9619
|
+
featureTokenSaving: sp.featureTokenSaving,
|
|
9470
9620
|
contextAutoCompact: sp.contextAutoCompact,
|
|
9471
9621
|
contextStrategy: sp.contextStrategy,
|
|
9472
9622
|
logLevel: sp.logLevel,
|
|
@@ -9844,6 +9994,7 @@ function App({
|
|
|
9844
9994
|
featureMemory: s2.featureMemory ?? true,
|
|
9845
9995
|
featureSkills: s2.featureSkills ?? true,
|
|
9846
9996
|
featureModelsRegistry: s2.featureModelsRegistry ?? true,
|
|
9997
|
+
featureTokenSaving: s2.featureTokenSaving ?? false,
|
|
9847
9998
|
contextAutoCompact: s2.contextAutoCompact ?? true,
|
|
9848
9999
|
contextStrategy: s2.contextStrategy ?? "hybrid",
|
|
9849
10000
|
logLevel: s2.logLevel ?? "info",
|
|
@@ -9961,6 +10112,7 @@ function App({
|
|
|
9961
10112
|
featureMemory: sp.featureMemory,
|
|
9962
10113
|
featureSkills: sp.featureSkills,
|
|
9963
10114
|
featureModelsRegistry: sp.featureModelsRegistry,
|
|
10115
|
+
featureTokenSaving: sp.featureTokenSaving,
|
|
9964
10116
|
contextAutoCompact: sp.contextAutoCompact,
|
|
9965
10117
|
contextStrategy: sp.contextStrategy,
|
|
9966
10118
|
logLevel: sp.logLevel,
|
|
@@ -10170,6 +10322,15 @@ function App({
|
|
|
10170
10322
|
entry: { kind: "error", text: e.description }
|
|
10171
10323
|
});
|
|
10172
10324
|
});
|
|
10325
|
+
const offFallback = events.on("provider.fallback", (e) => {
|
|
10326
|
+
dispatch({
|
|
10327
|
+
type: "addEntry",
|
|
10328
|
+
entry: {
|
|
10329
|
+
kind: "warn",
|
|
10330
|
+
text: `\u21BB rate-limited (${e.status}) \u2014 switched to ${e.to.providerId}/${e.to.model}`
|
|
10331
|
+
}
|
|
10332
|
+
});
|
|
10333
|
+
});
|
|
10173
10334
|
const offProvResp = events.on("provider.response", () => {
|
|
10174
10335
|
const text = streamingTextRef.current;
|
|
10175
10336
|
streamingTextRef.current = "";
|
|
@@ -10243,6 +10404,7 @@ function App({
|
|
|
10243
10404
|
offTool();
|
|
10244
10405
|
offRetry();
|
|
10245
10406
|
offProvErr();
|
|
10407
|
+
offFallback();
|
|
10246
10408
|
offProvResp();
|
|
10247
10409
|
offConfirmNeeded();
|
|
10248
10410
|
offTrustPersisted();
|
|
@@ -10304,6 +10466,15 @@ function App({
|
|
|
10304
10466
|
enhanceController,
|
|
10305
10467
|
agentsMonitorController
|
|
10306
10468
|
});
|
|
10469
|
+
useEffect(() => {
|
|
10470
|
+
if (!interruptController) return;
|
|
10471
|
+
interruptController.abortLeader = () => {
|
|
10472
|
+
if (stateRef.current.status === "idle") return false;
|
|
10473
|
+
activeCtrlRef.current?.abort("user interrupt (/interrupt)");
|
|
10474
|
+
dispatch({ type: "status", status: "aborting" });
|
|
10475
|
+
return true;
|
|
10476
|
+
};
|
|
10477
|
+
}, [interruptController, dispatch, stateRef]);
|
|
10307
10478
|
const lastEscAtRef = useRef(0);
|
|
10308
10479
|
const ESC_DOUBLE_PRESS_MS = 1e3;
|
|
10309
10480
|
useDirectorFleetBridge({
|
|
@@ -11159,6 +11330,7 @@ function App({
|
|
|
11159
11330
|
featureMemory: cfg.featureMemory ?? true,
|
|
11160
11331
|
featureSkills: cfg.featureSkills ?? true,
|
|
11161
11332
|
featureModelsRegistry: cfg.featureModelsRegistry ?? true,
|
|
11333
|
+
featureTokenSaving: cfg.featureTokenSaving ?? false,
|
|
11162
11334
|
contextAutoCompact: cfg.contextAutoCompact ?? true,
|
|
11163
11335
|
contextStrategy: cfg.contextStrategy ?? "hybrid",
|
|
11164
11336
|
logLevel: cfg.logLevel ?? "info",
|
|
@@ -12078,6 +12250,7 @@ User message:
|
|
|
12078
12250
|
featureMemory: state.settingsPicker.featureMemory,
|
|
12079
12251
|
featureSkills: state.settingsPicker.featureSkills,
|
|
12080
12252
|
featureModelsRegistry: state.settingsPicker.featureModelsRegistry,
|
|
12253
|
+
featureTokenSaving: state.settingsPicker.featureTokenSaving,
|
|
12081
12254
|
contextAutoCompact: state.settingsPicker.contextAutoCompact,
|
|
12082
12255
|
contextStrategy: state.settingsPicker.contextStrategy,
|
|
12083
12256
|
logLevel: state.settingsPicker.logLevel,
|
|
@@ -12248,6 +12421,7 @@ User message:
|
|
|
12248
12421
|
subagentCount: Object.keys(state.fleet).length,
|
|
12249
12422
|
processCount: getProcessRegistry().activeCount,
|
|
12250
12423
|
hiddenItems,
|
|
12424
|
+
events,
|
|
12251
12425
|
eternalStage: state.eternalStage,
|
|
12252
12426
|
goalSummary: state.goalSummary,
|
|
12253
12427
|
indexState,
|
|
@@ -12257,7 +12431,9 @@ User message:
|
|
|
12257
12431
|
nextStepsAutoSubmitCountdown,
|
|
12258
12432
|
autoProceedCountdown: state.countdown?.remainingSeconds ?? null,
|
|
12259
12433
|
sessionCount,
|
|
12260
|
-
mailbox: mailboxStatus
|
|
12434
|
+
mailbox: mailboxStatus,
|
|
12435
|
+
tokenSavingMode: getSettings ? getSettings().featureTokenSaving : tokenSavingMode,
|
|
12436
|
+
toolCount
|
|
12261
12437
|
}
|
|
12262
12438
|
) }),
|
|
12263
12439
|
/* @__PURE__ */ jsx(
|
|
@@ -12523,6 +12699,7 @@ async function runTui(opts) {
|
|
|
12523
12699
|
const cleanup = () => {
|
|
12524
12700
|
if (cleaned) return;
|
|
12525
12701
|
cleaned = true;
|
|
12702
|
+
unregisterTuiClient();
|
|
12526
12703
|
unsilenceTerminal();
|
|
12527
12704
|
try {
|
|
12528
12705
|
stopTitle();
|
|
@@ -12549,6 +12726,64 @@ async function runTui(opts) {
|
|
|
12549
12726
|
}
|
|
12550
12727
|
process.off("exit", exitHandler);
|
|
12551
12728
|
};
|
|
12729
|
+
let clientHeartbeatTimer = null;
|
|
12730
|
+
let clientSyncTimer = null;
|
|
12731
|
+
const CLIENT_HEARTBEAT_MS = 15e3;
|
|
12732
|
+
const CLIENT_SYNC_MS = 3e4;
|
|
12733
|
+
const registerTuiClient = async () => {
|
|
12734
|
+
if (!opts.projectRoot) return null;
|
|
12735
|
+
try {
|
|
12736
|
+
const projectDir = resolveProjectDir(opts.projectRoot, wstackGlobalRoot());
|
|
12737
|
+
const mailbox = new GlobalMailbox(projectDir, opts.events);
|
|
12738
|
+
const clientId = `tui@${randomUUID().slice(0, 8)}`;
|
|
12739
|
+
await mailbox.registerClient({
|
|
12740
|
+
clientId,
|
|
12741
|
+
sessionId: opts.projectRoot,
|
|
12742
|
+
name: `TUI [${path4.basename(opts.projectRoot)}]`,
|
|
12743
|
+
source: "tui",
|
|
12744
|
+
pid: process.pid
|
|
12745
|
+
});
|
|
12746
|
+
clientHeartbeatTimer = setInterval(() => {
|
|
12747
|
+
mailbox.clientHeartbeat({ clientId }).catch(() => {
|
|
12748
|
+
});
|
|
12749
|
+
}, CLIENT_HEARTBEAT_MS);
|
|
12750
|
+
clientHeartbeatTimer.unref();
|
|
12751
|
+
const syncClients = async () => {
|
|
12752
|
+
try {
|
|
12753
|
+
const statuses = await mailbox.getClientStatuses();
|
|
12754
|
+
const counts = { tui: 0, webui: 0, repl: 0 };
|
|
12755
|
+
for (const s2 of statuses) {
|
|
12756
|
+
if (s2.online && s2.source in counts) {
|
|
12757
|
+
counts[s2.source]++;
|
|
12758
|
+
}
|
|
12759
|
+
}
|
|
12760
|
+
opts.events.emitCustom("mailbox.sync_clients", counts);
|
|
12761
|
+
} catch {
|
|
12762
|
+
}
|
|
12763
|
+
};
|
|
12764
|
+
setTimeout(() => {
|
|
12765
|
+
void syncClients();
|
|
12766
|
+
}, 5e3);
|
|
12767
|
+
clientSyncTimer = setInterval(() => {
|
|
12768
|
+
void syncClients();
|
|
12769
|
+
}, CLIENT_SYNC_MS);
|
|
12770
|
+
clientSyncTimer.unref();
|
|
12771
|
+
return clientId;
|
|
12772
|
+
} catch {
|
|
12773
|
+
return null;
|
|
12774
|
+
}
|
|
12775
|
+
};
|
|
12776
|
+
const unregisterTuiClient = () => {
|
|
12777
|
+
if (clientHeartbeatTimer) {
|
|
12778
|
+
clearInterval(clientHeartbeatTimer);
|
|
12779
|
+
clientHeartbeatTimer = null;
|
|
12780
|
+
}
|
|
12781
|
+
if (clientSyncTimer) {
|
|
12782
|
+
clearInterval(clientSyncTimer);
|
|
12783
|
+
clientSyncTimer = null;
|
|
12784
|
+
}
|
|
12785
|
+
};
|
|
12786
|
+
registerTuiClient();
|
|
12552
12787
|
return new Promise((resolve) => {
|
|
12553
12788
|
let exitCode = 0;
|
|
12554
12789
|
let hardExitTimer = null;
|
|
@@ -12607,6 +12842,7 @@ async function runTui(opts) {
|
|
|
12607
12842
|
fleetRoster: opts.fleetRoster,
|
|
12608
12843
|
onClearHistory: opts.onClearHistory ? (dispatch) => opts.onClearHistory?.(dispatch) : void 0,
|
|
12609
12844
|
fleetStreamController: opts.fleetStreamController,
|
|
12845
|
+
interruptController: opts.interruptController,
|
|
12610
12846
|
enhanceController: opts.enhanceController,
|
|
12611
12847
|
enhanceEnabled: opts.enhanceController?.enabled ?? true,
|
|
12612
12848
|
statuslineHiddenItems: opts.statuslineHiddenItems,
|
|
@@ -12626,6 +12862,8 @@ async function runTui(opts) {
|
|
|
12626
12862
|
confirmExit: opts.confirmExit,
|
|
12627
12863
|
mouse: mouseEnabled,
|
|
12628
12864
|
modeLabel: opts.modeLabel,
|
|
12865
|
+
tokenSavingMode: opts.tokenSavingMode,
|
|
12866
|
+
toolCount: opts.toolCount,
|
|
12629
12867
|
getModeLabel: opts.getModeLabel,
|
|
12630
12868
|
registerDebugStreamCallback: opts.registerDebugStreamCallback,
|
|
12631
12869
|
restoreDebugStreamCallback: opts.restoreDebugStreamCallback,
|