@wrongstack/tui 0.104.0 → 0.109.1
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 +74 -55
- package/dist/index.js.map +1 -1
- package/package.json +4 -4
package/dist/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { expectDefined, writeErr, InputBuilder, DefaultSessionRewinder, writeOut, formatTodosList, buildGoalPreamble, shouldEnhance, enhanceUserPrompt, recentTextTurns, normalizedEqual, buildChildEnv } from '@wrongstack/core';
|
|
1
|
+
import { expectDefined, writeErr, resolveWstackPaths, loadGoal, InputBuilder, DefaultSessionRewinder, writeOut, formatTodosList, buildGoalPreamble, shouldEnhance, enhanceUserPrompt, recentTextTurns, normalizedEqual, buildChildEnv } from '@wrongstack/core';
|
|
2
2
|
export { buildGoalPreamble } from '@wrongstack/core';
|
|
3
3
|
import { Box, Text, useInput, useStdin, useStdout, render, useApp, Static } from 'ink';
|
|
4
|
-
import React6, { useState, useEffect, memo, useReducer, useRef, useMemo
|
|
4
|
+
import React6, { useState, useEffect, memo, useCallback, useReducer, useRef, useMemo } from 'react';
|
|
5
5
|
import * as fs2 from 'fs/promises';
|
|
6
6
|
import * as path2 from 'path';
|
|
7
7
|
import { routeImagesForModel } from '@wrongstack/runtime/vision';
|
|
@@ -913,10 +913,10 @@ function AgentsMonitor({
|
|
|
913
913
|
const live = useMemo(() => selectLiveAgents(all, nowTick), [all, nowTick]);
|
|
914
914
|
const [selectedIndex, setSelectedIndex] = useState(0);
|
|
915
915
|
const safeIndex = Math.min(selectedIndex, Math.max(0, live.length - 1));
|
|
916
|
-
useInput((
|
|
917
|
-
if (key.upArrow
|
|
916
|
+
useInput((_input, key) => {
|
|
917
|
+
if (key.upArrow) {
|
|
918
918
|
setSelectedIndex((prev) => Math.max(0, prev - 1));
|
|
919
|
-
} else if (key.downArrow
|
|
919
|
+
} else if (key.downArrow) {
|
|
920
920
|
setSelectedIndex((prev) => Math.min(live.length - 1, prev + 1));
|
|
921
921
|
}
|
|
922
922
|
});
|
|
@@ -2065,9 +2065,8 @@ function computeWidths(allRows, cols, maxWidth, sepWidths) {
|
|
|
2065
2065
|
for (let c = 0; c < cols; c++) {
|
|
2066
2066
|
const cell = row[c] ?? "";
|
|
2067
2067
|
const stripped = stripInlineMarkers(cell);
|
|
2068
|
-
const w = longestWord(stripped);
|
|
2069
2068
|
const total = strWidth(stripped);
|
|
2070
|
-
natural[c] = Math.max(expectDefined$1(natural[c]),
|
|
2069
|
+
natural[c] = Math.max(expectDefined$1(natural[c]), total);
|
|
2071
2070
|
}
|
|
2072
2071
|
}
|
|
2073
2072
|
if (sepWidths) {
|
|
@@ -2200,19 +2199,16 @@ function strWidth(s2) {
|
|
|
2200
2199
|
i += cpLen;
|
|
2201
2200
|
continue;
|
|
2202
2201
|
}
|
|
2202
|
+
if (code >= 9472 && code <= 9599) {
|
|
2203
|
+
width += 1;
|
|
2204
|
+
i += cpLen;
|
|
2205
|
+
continue;
|
|
2206
|
+
}
|
|
2203
2207
|
width += 1;
|
|
2204
2208
|
i += cpLen;
|
|
2205
2209
|
}
|
|
2206
2210
|
return width;
|
|
2207
2211
|
}
|
|
2208
|
-
function longestWord(s2) {
|
|
2209
|
-
let max = 0;
|
|
2210
|
-
for (const w of s2.split(/\s+/)) {
|
|
2211
|
-
const visualWidth = strWidth(w);
|
|
2212
|
-
if (visualWidth > max) max = visualWidth;
|
|
2213
|
-
}
|
|
2214
|
-
return max;
|
|
2215
|
-
}
|
|
2216
2212
|
function border(left, mid, right, widths) {
|
|
2217
2213
|
return left + widths.map((w) => "\u2500".repeat(w + 2)).join(mid) + right;
|
|
2218
2214
|
}
|
|
@@ -2220,13 +2216,12 @@ function stripInlineMarkers(text) {
|
|
|
2220
2216
|
return text.replace(/\*\*(.+?)\*\*/g, "$1").replace(/(?<!\*)\*(?!\*)(.+?)(?<!\*)\*(?!\*)/g, "$1").replace(/`(.+?)`/g, "$1").replace(/~~(.+?)~~/g, "$1");
|
|
2221
2217
|
}
|
|
2222
2218
|
var ANSI_BOLD = "\x1B[1m";
|
|
2223
|
-
var ANSI_RESET = "\x1B[22m";
|
|
2224
2219
|
var ANSI_DIM = "\x1B[2m";
|
|
2225
2220
|
var ANSI_CYAN = "\x1B[36m";
|
|
2226
2221
|
var ANSI_STRIKE = "\x1B[9m";
|
|
2227
2222
|
var ANSI_RESET_ALL = "\x1B[0m";
|
|
2228
2223
|
function applyInlineAnsi(text) {
|
|
2229
|
-
return text.replace(/\*\*(.+?)\*\*/g, `${ANSI_BOLD}$1${
|
|
2224
|
+
return text.replace(/\*\*(.+?)\*\*/g, `${ANSI_BOLD}$1${ANSI_RESET_ALL}`).replace(/(?<!\*)\*(?!\*)(.+?)(?<!\*)\*(?!\*)/g, `${ANSI_DIM}$1${ANSI_RESET_ALL}`).replace(/`(.+?)`/g, `${ANSI_CYAN}$1${ANSI_RESET_ALL}`).replace(/~~(.+?)~~/g, `${ANSI_STRIKE}$1${ANSI_RESET_ALL}`);
|
|
2230
2225
|
}
|
|
2231
2226
|
function renderRow(cells, widths, aligns) {
|
|
2232
2227
|
const styled = cells.map((c) => applyInlineAnsi(c));
|
|
@@ -2239,7 +2234,7 @@ function renderRow(cells, widths, aligns) {
|
|
|
2239
2234
|
for (let c = 0; c < widths.length; c++) {
|
|
2240
2235
|
const w = widths[c] ?? MIN_COL_WIDTH;
|
|
2241
2236
|
const text = wrapped[c]?.[line] ?? "";
|
|
2242
|
-
parts.push(padCell(text, w, aligns[c] ?? "left"));
|
|
2237
|
+
parts.push(padCell(text, w, aligns[c] ?? "left") + ANSI_RESET_ALL);
|
|
2243
2238
|
}
|
|
2244
2239
|
out.push("\u2502 " + parts.join(" \u2502 ") + " \u2502");
|
|
2245
2240
|
}
|
|
@@ -3089,7 +3084,8 @@ function CodeBlock({
|
|
|
3089
3084
|
const hidden = Math.max(0, lines.length - MAX_CODE_LINES);
|
|
3090
3085
|
if (hidden > 0) lines = lines.slice(0, MAX_CODE_LINES);
|
|
3091
3086
|
const gutterW = String(lines.length).length;
|
|
3092
|
-
const
|
|
3087
|
+
const boxWidth = Math.max(22, contentWidth - 2);
|
|
3088
|
+
const maxW = Math.max(20, Math.min(boxWidth - 4 - gutterW - 1, 120));
|
|
3093
3089
|
let carry = {};
|
|
3094
3090
|
const rows = lines.map((raw) => {
|
|
3095
3091
|
const display = raw.length > maxW ? `${raw.slice(0, maxW - 1)}\u2026` : raw;
|
|
@@ -3101,6 +3097,8 @@ function CodeBlock({
|
|
|
3101
3097
|
Box,
|
|
3102
3098
|
{
|
|
3103
3099
|
flexDirection: "column",
|
|
3100
|
+
width: boxWidth,
|
|
3101
|
+
flexShrink: 0,
|
|
3104
3102
|
marginLeft: 2,
|
|
3105
3103
|
marginY: 0,
|
|
3106
3104
|
borderStyle: "round",
|
|
@@ -3224,6 +3222,10 @@ function extractDiffPreview(toolName, output) {
|
|
|
3224
3222
|
return parseUnifiedDiff(diff, DIFF_MAX_LINES);
|
|
3225
3223
|
}
|
|
3226
3224
|
var MESSAGE_PANEL_CHROME_WIDTH = 2;
|
|
3225
|
+
var MESSAGE_PANEL_MARGIN = 2;
|
|
3226
|
+
function assistantContentWidth(termWidth) {
|
|
3227
|
+
return Math.max(20, termWidth - MESSAGE_PANEL_CHROME_WIDTH - MESSAGE_PANEL_MARGIN * 2);
|
|
3228
|
+
}
|
|
3227
3229
|
function splitFencedBlocks(text) {
|
|
3228
3230
|
const lines = text.split("\n");
|
|
3229
3231
|
const segs = [];
|
|
@@ -3377,9 +3379,6 @@ function brainRiskColor(risk) {
|
|
|
3377
3379
|
return "red";
|
|
3378
3380
|
}
|
|
3379
3381
|
}
|
|
3380
|
-
function assistantContentWidth(termWidth) {
|
|
3381
|
-
return Math.max(20, termWidth - MESSAGE_PANEL_CHROME_WIDTH);
|
|
3382
|
-
}
|
|
3383
3382
|
var Entry = React6.memo(function Entry2({
|
|
3384
3383
|
entry,
|
|
3385
3384
|
termWidth
|
|
@@ -3389,6 +3388,7 @@ var Entry = React6.memo(function Entry2({
|
|
|
3389
3388
|
return /* @__PURE__ */ jsx(
|
|
3390
3389
|
Box,
|
|
3391
3390
|
{
|
|
3391
|
+
marginX: MESSAGE_PANEL_MARGIN,
|
|
3392
3392
|
borderStyle: "single",
|
|
3393
3393
|
borderTop: false,
|
|
3394
3394
|
borderRight: false,
|
|
@@ -3415,6 +3415,7 @@ var Entry = React6.memo(function Entry2({
|
|
|
3415
3415
|
Box,
|
|
3416
3416
|
{
|
|
3417
3417
|
flexDirection: "column",
|
|
3418
|
+
marginX: MESSAGE_PANEL_MARGIN,
|
|
3418
3419
|
marginY: 1,
|
|
3419
3420
|
borderStyle: "single",
|
|
3420
3421
|
borderTop: false,
|
|
@@ -3488,6 +3489,7 @@ var Entry = React6.memo(function Entry2({
|
|
|
3488
3489
|
return /* @__PURE__ */ jsx(
|
|
3489
3490
|
Box,
|
|
3490
3491
|
{
|
|
3492
|
+
marginX: MESSAGE_PANEL_MARGIN,
|
|
3491
3493
|
borderStyle: "single",
|
|
3492
3494
|
borderTop: false,
|
|
3493
3495
|
borderRight: false,
|
|
@@ -3501,6 +3503,7 @@ var Entry = React6.memo(function Entry2({
|
|
|
3501
3503
|
return /* @__PURE__ */ jsx(
|
|
3502
3504
|
Box,
|
|
3503
3505
|
{
|
|
3506
|
+
marginX: MESSAGE_PANEL_MARGIN,
|
|
3504
3507
|
borderStyle: "single",
|
|
3505
3508
|
borderTop: false,
|
|
3506
3509
|
borderRight: false,
|
|
@@ -3519,6 +3522,7 @@ var Entry = React6.memo(function Entry2({
|
|
|
3519
3522
|
Box,
|
|
3520
3523
|
{
|
|
3521
3524
|
flexDirection: "column",
|
|
3525
|
+
marginX: MESSAGE_PANEL_MARGIN,
|
|
3522
3526
|
marginY: 1,
|
|
3523
3527
|
borderStyle: "single",
|
|
3524
3528
|
borderTop: false,
|
|
@@ -3799,6 +3803,8 @@ var Input = memo(function Input2({
|
|
|
3799
3803
|
cursor,
|
|
3800
3804
|
disabled,
|
|
3801
3805
|
hint,
|
|
3806
|
+
hidden,
|
|
3807
|
+
placeholderHeight,
|
|
3802
3808
|
onKey
|
|
3803
3809
|
}) {
|
|
3804
3810
|
useInput((input, key) => {
|
|
@@ -3854,6 +3860,9 @@ var Input = memo(function Input2({
|
|
|
3854
3860
|
}, [stdout]);
|
|
3855
3861
|
const promptColor = disabled ? "red" : "cyan";
|
|
3856
3862
|
const rows = layoutInputRows(prompt, value, cursor, cols);
|
|
3863
|
+
if (hidden) {
|
|
3864
|
+
return /* @__PURE__ */ jsx(Box, { height: Math.max(1, placeholderHeight ?? rows.length) });
|
|
3865
|
+
}
|
|
3857
3866
|
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", children: [
|
|
3858
3867
|
rows.map(
|
|
3859
3868
|
(row, i) => row.length === 0 ? (
|
|
@@ -3922,8 +3931,8 @@ var LiveActivityStrip = React6.memo(function LiveActivityStrip2({
|
|
|
3922
3931
|
}) {
|
|
3923
3932
|
const { stdout } = useStdout();
|
|
3924
3933
|
const width = Math.max(10, (stdout?.columns ?? 80) - 2);
|
|
3925
|
-
|
|
3926
|
-
const rows = activityStripRows(entries, Date.now(), maxRows, width);
|
|
3934
|
+
const hasEntries = Object.keys(entries).length > 0;
|
|
3935
|
+
const rows = hasEntries ? activityStripRows(entries, Date.now(), maxRows, width) : new Array(maxRows).fill("");
|
|
3927
3936
|
return /* @__PURE__ */ jsx(Box, { flexDirection: "column", paddingX: 1, children: rows.map((text, slot) => (
|
|
3928
3937
|
// biome-ignore lint/suspicious/noArrayIndexKey: fixed-height slots, index IS the identity
|
|
3929
3938
|
/* @__PURE__ */ jsx(Box, { height: 1, children: text === "" ? /* @__PURE__ */ jsx(Text, { children: " " }) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
@@ -7310,6 +7319,7 @@ function App({
|
|
|
7310
7319
|
getModeLabel
|
|
7311
7320
|
}) {
|
|
7312
7321
|
const { exit } = useApp();
|
|
7322
|
+
const { stdout } = useStdout();
|
|
7313
7323
|
const [liveModel, setLiveModel] = useState(model);
|
|
7314
7324
|
const [liveProvider, setLiveProvider] = useState(provider ?? "agent");
|
|
7315
7325
|
const [activeMaxContext, setActiveMaxContext] = useState(effectiveMaxContext);
|
|
@@ -7329,32 +7339,33 @@ function App({
|
|
|
7329
7339
|
setStatuslineHiddenItems(hiddenItems);
|
|
7330
7340
|
}, [setStatuslineHiddenItems, hiddenItems]);
|
|
7331
7341
|
const projectRoot = agent.ctx.projectRoot;
|
|
7332
|
-
|
|
7342
|
+
const refreshGoalSummary = useCallback(() => {
|
|
7333
7343
|
if (!projectRoot) return;
|
|
7334
|
-
const goalPath =
|
|
7335
|
-
|
|
7336
|
-
|
|
7337
|
-
|
|
7338
|
-
|
|
7339
|
-
|
|
7340
|
-
|
|
7341
|
-
|
|
7342
|
-
|
|
7343
|
-
|
|
7344
|
-
|
|
7345
|
-
|
|
7346
|
-
|
|
7347
|
-
|
|
7348
|
-
|
|
7349
|
-
|
|
7350
|
-
|
|
7351
|
-
|
|
7352
|
-
|
|
7353
|
-
});
|
|
7354
|
-
}
|
|
7344
|
+
const goalPath = resolveWstackPaths({ projectRoot }).projectGoal;
|
|
7345
|
+
loadGoal(goalPath).then((goal) => {
|
|
7346
|
+
if (!goal) return;
|
|
7347
|
+
const lastEntry = goal.journal?.[goal.journal.length - 1];
|
|
7348
|
+
dispatch({
|
|
7349
|
+
type: "goalSummary",
|
|
7350
|
+
summary: {
|
|
7351
|
+
goal: goal.goal,
|
|
7352
|
+
refinedGoal: goal.refinedGoal,
|
|
7353
|
+
goalState: goal.goalState ?? "active",
|
|
7354
|
+
iterations: goal.iterations,
|
|
7355
|
+
progress: goal.progress,
|
|
7356
|
+
progressNote: goal.progressNote,
|
|
7357
|
+
progressTrend: goal.progressTrend,
|
|
7358
|
+
deliverables: goal.deliverables,
|
|
7359
|
+
lastTask: lastEntry?.task,
|
|
7360
|
+
lastStatus: lastEntry?.status
|
|
7361
|
+
}
|
|
7362
|
+
});
|
|
7355
7363
|
}).catch(() => {
|
|
7356
7364
|
});
|
|
7357
7365
|
}, [projectRoot]);
|
|
7366
|
+
useEffect(() => {
|
|
7367
|
+
refreshGoalSummary();
|
|
7368
|
+
}, [refreshGoalSummary]);
|
|
7358
7369
|
const restoredEntries = (() => {
|
|
7359
7370
|
const msgs = agent.ctx.messages;
|
|
7360
7371
|
if (!msgs || msgs.length === 0) return [];
|
|
@@ -7504,6 +7515,9 @@ function App({
|
|
|
7504
7515
|
const t = setInterval(() => setNowTick(Date.now()), 1e4);
|
|
7505
7516
|
return () => clearInterval(t);
|
|
7506
7517
|
}, []);
|
|
7518
|
+
useEffect(() => {
|
|
7519
|
+
if (state.goalPanelOpen) refreshGoalSummary();
|
|
7520
|
+
}, [state.goalPanelOpen, nowTick, refreshGoalSummary]);
|
|
7507
7521
|
const [enhanceDots, setEnhanceDots] = useState(0);
|
|
7508
7522
|
useEffect(() => {
|
|
7509
7523
|
if (!state.enhanceBusy) return;
|
|
@@ -8979,18 +8993,10 @@ function App({
|
|
|
8979
8993
|
dispatch({ type: "toggleMonitor" });
|
|
8980
8994
|
return;
|
|
8981
8995
|
}
|
|
8982
|
-
if (state.worktreeMonitorOpen) {
|
|
8983
|
-
dispatch({ type: "worktreeMonitorToggle" });
|
|
8984
|
-
return;
|
|
8985
|
-
}
|
|
8986
8996
|
if (state.todosMonitorOpen) {
|
|
8987
8997
|
dispatch({ type: "toggleTodosMonitor" });
|
|
8988
8998
|
return;
|
|
8989
8999
|
}
|
|
8990
|
-
if (state.autoPhase?.monitorOpen) {
|
|
8991
|
-
dispatch({ type: "autoPhaseMonitorToggle" });
|
|
8992
|
-
return;
|
|
8993
|
-
}
|
|
8994
9000
|
if (state.settingsPicker.open) {
|
|
8995
9001
|
dispatch({ type: "settingsClose" });
|
|
8996
9002
|
return;
|
|
@@ -9008,6 +9014,9 @@ function App({
|
|
|
9008
9014
|
return;
|
|
9009
9015
|
}
|
|
9010
9016
|
}
|
|
9017
|
+
if (state.processListOpen) {
|
|
9018
|
+
return;
|
|
9019
|
+
}
|
|
9011
9020
|
if (input === "?" && !key.ctrl && !key.meta && draftRef.current.buffer === "" && !state.slashPicker.open && !state.picker.open && !state.modelPicker.open && !state.autonomyPicker.open && !state.settingsPicker.open && !state.rewindOverlay && !state.monitorOpen && !state.agentsMonitorOpen && !state.worktreeMonitorOpen && !state.todosMonitorOpen && !state.autoPhase?.monitorOpen) {
|
|
9012
9021
|
dispatch({ type: "toggleHelp" });
|
|
9013
9022
|
return;
|
|
@@ -9601,6 +9610,14 @@ User message:
|
|
|
9601
9610
|
return "";
|
|
9602
9611
|
}, [state.buffer, state.status, state.picker.open]);
|
|
9603
9612
|
const enhanceActive = state.enhanceBusy || state.enhance != null;
|
|
9613
|
+
const inputCellRows = layoutInputRows(
|
|
9614
|
+
INPUT_PROMPT,
|
|
9615
|
+
state.buffer,
|
|
9616
|
+
state.cursor,
|
|
9617
|
+
stdout?.columns ?? 80
|
|
9618
|
+
);
|
|
9619
|
+
const inputHeight = Math.max(1, inputCellRows.length);
|
|
9620
|
+
const hideInput = enhanceActive || state.helpOpen || state.processListOpen;
|
|
9604
9621
|
return /* @__PURE__ */ jsx(Box, { flexDirection: "column", children: /* @__PURE__ */ jsxs(Box, { flexDirection: "column", flexGrow: 1, flexShrink: 0, children: [
|
|
9605
9622
|
/* @__PURE__ */ jsx(
|
|
9606
9623
|
History,
|
|
@@ -9612,12 +9629,14 @@ User message:
|
|
|
9612
9629
|
),
|
|
9613
9630
|
/* @__PURE__ */ jsxs(Box, { flexDirection: "column", flexShrink: 0, children: [
|
|
9614
9631
|
/* @__PURE__ */ jsx(LiveActivityStrip, { entries: state.fleet, nowTick }),
|
|
9615
|
-
|
|
9632
|
+
/* @__PURE__ */ jsx(
|
|
9616
9633
|
Input,
|
|
9617
9634
|
{
|
|
9618
9635
|
prompt: INPUT_PROMPT,
|
|
9619
9636
|
value: state.buffer,
|
|
9620
9637
|
cursor: state.cursor,
|
|
9638
|
+
hidden: hideInput,
|
|
9639
|
+
placeholderHeight: inputHeight,
|
|
9621
9640
|
disabled: state.status === "aborting" && !state.steeringPending || state.confirmQueue.length > 0,
|
|
9622
9641
|
hint: inputHint,
|
|
9623
9642
|
onKey: stableOnKey
|