@wrongstack/tui 0.148.0 → 0.155.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.js +81 -29
- package/dist/index.js.map +1 -1
- package/package.json +4 -4
package/dist/index.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
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
|
|
4
|
+
import * as path3 from 'path';
|
|
5
|
+
import React5, { useState, useEffect, useMemo, memo, useRef, useCallback, useReducer } from 'react';
|
|
5
6
|
import * as fs2 from 'fs/promises';
|
|
6
|
-
import * as path2 from 'path';
|
|
7
7
|
import { routeImagesForModel } from '@wrongstack/runtime/vision';
|
|
8
8
|
import { getIndexState, onIndexStateChange, getProcessRegistry } from '@wrongstack/tools';
|
|
9
9
|
import { readClipboardImage } from '@wrongstack/runtime/clipboard';
|
|
@@ -1467,8 +1467,8 @@ function FilePicker({ query, matches, selected }) {
|
|
|
1467
1467
|
] }, m))
|
|
1468
1468
|
] });
|
|
1469
1469
|
}
|
|
1470
|
-
function highlight(
|
|
1471
|
-
return
|
|
1470
|
+
function highlight(path5, _query) {
|
|
1471
|
+
return path5;
|
|
1472
1472
|
}
|
|
1473
1473
|
function FleetPanel({
|
|
1474
1474
|
entries,
|
|
@@ -1607,7 +1607,7 @@ function HelpOverlay() {
|
|
|
1607
1607
|
const keyWidth = Math.max(...sections.flatMap((s2) => s2.entries.map((e) => e.keys.length)), 0);
|
|
1608
1608
|
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", borderStyle: "round", borderColor: theme.accent, paddingX: 1, children: [
|
|
1609
1609
|
/* @__PURE__ */ jsxs(Box, { flexDirection: "row", gap: 1, children: [
|
|
1610
|
-
/* @__PURE__ */ jsx(Text, { bold: true, color: theme.accent, children: "
|
|
1610
|
+
/* @__PURE__ */ jsx(Text, { bold: true, color: theme.accent, children: "Keyboard shortcuts" }),
|
|
1611
1611
|
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "\xB7 Esc to close" })
|
|
1612
1612
|
] }),
|
|
1613
1613
|
sections.map((sec) => /* @__PURE__ */ jsxs(Box, { flexDirection: "column", marginTop: 1, children: [
|
|
@@ -3408,10 +3408,11 @@ function Banner({
|
|
|
3408
3408
|
entry
|
|
3409
3409
|
}) {
|
|
3410
3410
|
const cwdShort = shortenPath(entry.cwd, 48);
|
|
3411
|
+
const projectLabel = path3.basename(entry.cwd);
|
|
3411
3412
|
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", borderStyle: "round", borderColor: "magenta", paddingX: 2, paddingY: 0, children: [
|
|
3412
3413
|
/* @__PURE__ */ jsxs(Text, { children: [
|
|
3413
3414
|
/* @__PURE__ */ jsx(Text, { color: "magenta", bold: true, children: " \u259F\u259B " }),
|
|
3414
|
-
/* @__PURE__ */ jsx(Text, { color: "magenta", bold: true, children:
|
|
3415
|
+
/* @__PURE__ */ jsx(Text, { color: "magenta", bold: true, children: projectLabel }),
|
|
3415
3416
|
/* @__PURE__ */ jsx(Text, { dimColor: true, children: " v" }),
|
|
3416
3417
|
/* @__PURE__ */ jsx(Text, { children: entry.version })
|
|
3417
3418
|
] }),
|
|
@@ -3443,6 +3444,20 @@ function Banner({
|
|
|
3443
3444
|
] })
|
|
3444
3445
|
] });
|
|
3445
3446
|
}
|
|
3447
|
+
var NEXT_STEPS_RE = /💡\s*Next steps?\s*\n+((?:\d+\.\s+.+\n?)+)/i;
|
|
3448
|
+
function parseNextSteps(content) {
|
|
3449
|
+
const match = NEXT_STEPS_RE.exec(content);
|
|
3450
|
+
if (!match?.[1]) return { steps: [], stripped: content };
|
|
3451
|
+
const block = match[1];
|
|
3452
|
+
const steps = [];
|
|
3453
|
+
const lines = block.split("\n").filter(Boolean);
|
|
3454
|
+
for (const line of lines) {
|
|
3455
|
+
const m = /^(\d+)\.\s+(.+)$/.exec(line.trim());
|
|
3456
|
+
if (m) steps.push({ index: Number.parseInt(m[1], 10), text: m[2].trim() });
|
|
3457
|
+
}
|
|
3458
|
+
const stripped = content.replace(NEXT_STEPS_RE, "").replace(/\n{3,}/g, "\n\n").trim();
|
|
3459
|
+
return { steps: steps.slice(0, 6), stripped };
|
|
3460
|
+
}
|
|
3446
3461
|
function brainStatusStyle(status) {
|
|
3447
3462
|
switch (status) {
|
|
3448
3463
|
case "thinking":
|
|
@@ -3471,6 +3486,10 @@ var Entry = React5.memo(function Entry2({
|
|
|
3471
3486
|
entry,
|
|
3472
3487
|
termWidth
|
|
3473
3488
|
}) {
|
|
3489
|
+
const nextSteps = useMemo(() => {
|
|
3490
|
+
if (entry.kind !== "assistant") return { steps: [], stripped: "" };
|
|
3491
|
+
return parseNextSteps(entry.text);
|
|
3492
|
+
}, [entry.kind, entry.text]);
|
|
3474
3493
|
switch (entry.kind) {
|
|
3475
3494
|
case "user":
|
|
3476
3495
|
return /* @__PURE__ */ jsx(
|
|
@@ -3499,24 +3518,52 @@ var Entry = React5.memo(function Entry2({
|
|
|
3499
3518
|
);
|
|
3500
3519
|
case "assistant": {
|
|
3501
3520
|
const contentWidth = assistantContentWidth(termWidth);
|
|
3502
|
-
|
|
3503
|
-
|
|
3504
|
-
|
|
3505
|
-
|
|
3506
|
-
|
|
3507
|
-
|
|
3508
|
-
|
|
3509
|
-
|
|
3510
|
-
|
|
3511
|
-
|
|
3512
|
-
|
|
3513
|
-
|
|
3514
|
-
|
|
3515
|
-
|
|
3516
|
-
|
|
3517
|
-
|
|
3518
|
-
|
|
3519
|
-
|
|
3521
|
+
const { steps, stripped } = nextSteps;
|
|
3522
|
+
const hasNext = steps.length > 0;
|
|
3523
|
+
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", children: [
|
|
3524
|
+
/* @__PURE__ */ jsxs(
|
|
3525
|
+
Box,
|
|
3526
|
+
{
|
|
3527
|
+
flexDirection: "column",
|
|
3528
|
+
marginX: MESSAGE_PANEL_MARGIN,
|
|
3529
|
+
marginY: 1,
|
|
3530
|
+
borderStyle: "single",
|
|
3531
|
+
borderTop: false,
|
|
3532
|
+
borderRight: false,
|
|
3533
|
+
borderBottom: hasNext ? false : void 0,
|
|
3534
|
+
borderColor: theme.assistant,
|
|
3535
|
+
paddingLeft: 1,
|
|
3536
|
+
children: [
|
|
3537
|
+
/* @__PURE__ */ jsx(Box, { flexDirection: "row", children: /* @__PURE__ */ jsx(Text, { bold: true, color: theme.assistant, children: "ASSISTANT" }) }),
|
|
3538
|
+
/* @__PURE__ */ jsx(AssistantBody, { text: stripped, termWidth, contentWidth })
|
|
3539
|
+
]
|
|
3540
|
+
}
|
|
3541
|
+
),
|
|
3542
|
+
hasNext && /* @__PURE__ */ jsxs(
|
|
3543
|
+
Box,
|
|
3544
|
+
{
|
|
3545
|
+
flexDirection: "column",
|
|
3546
|
+
marginX: MESSAGE_PANEL_MARGIN,
|
|
3547
|
+
marginY: 1,
|
|
3548
|
+
borderStyle: "single",
|
|
3549
|
+
borderTop: false,
|
|
3550
|
+
borderRight: false,
|
|
3551
|
+
borderBottom: false,
|
|
3552
|
+
borderColor: theme.accent,
|
|
3553
|
+
paddingLeft: 1,
|
|
3554
|
+
children: [
|
|
3555
|
+
/* @__PURE__ */ jsxs(Box, { flexDirection: "row", children: [
|
|
3556
|
+
/* @__PURE__ */ jsx(Text, { bold: true, color: theme.accent, children: "\u{1F4A1} NEXT STEPS " }),
|
|
3557
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "(use /next 1, /next 1 2 3 to select)" })
|
|
3558
|
+
] }),
|
|
3559
|
+
steps.map((s2) => /* @__PURE__ */ jsx(Box, { flexDirection: "row", marginTop: 0, children: /* @__PURE__ */ jsxs(Text, { children: [
|
|
3560
|
+
/* @__PURE__ */ jsx(Text, { bold: true, color: theme.accent, children: ` ${s2.index}. ` }),
|
|
3561
|
+
/* @__PURE__ */ jsx(Text, { children: s2.text })
|
|
3562
|
+
] }) }, s2.index))
|
|
3563
|
+
]
|
|
3564
|
+
}
|
|
3565
|
+
)
|
|
3566
|
+
] });
|
|
3520
3567
|
}
|
|
3521
3568
|
case "tool": {
|
|
3522
3569
|
const argSummary = formatToolArgs(entry.name, entry.input);
|
|
@@ -5177,7 +5224,7 @@ async function loadIndex(root) {
|
|
|
5177
5224
|
async function walk(root, rel, depth, out) {
|
|
5178
5225
|
if (out.length >= MAX_FILES_INDEXED) return;
|
|
5179
5226
|
if (depth > MAX_DEPTH) return;
|
|
5180
|
-
const dir = rel ?
|
|
5227
|
+
const dir = rel ? path3.join(root, rel) : root;
|
|
5181
5228
|
let entries;
|
|
5182
5229
|
try {
|
|
5183
5230
|
entries = await fs2.readdir(dir, { withFileTypes: true });
|
|
@@ -7652,8 +7699,8 @@ function App({
|
|
|
7652
7699
|
const lastEnterAtRef = useRef(0);
|
|
7653
7700
|
const tokenPreviewsRef = useRef(/* @__PURE__ */ new Map());
|
|
7654
7701
|
const projectName = React5.useMemo(() => {
|
|
7655
|
-
const base =
|
|
7656
|
-
return base && base !==
|
|
7702
|
+
const base = path3.basename(projectRoot);
|
|
7703
|
+
return base && base !== path3.sep ? base : void 0;
|
|
7657
7704
|
}, [projectRoot]);
|
|
7658
7705
|
const chimeRef = useRef(chime);
|
|
7659
7706
|
chimeRef.current = chime;
|
|
@@ -8059,7 +8106,7 @@ function App({
|
|
|
8059
8106
|
dispatch({ type: "pickerClose" });
|
|
8060
8107
|
return;
|
|
8061
8108
|
}
|
|
8062
|
-
const absPath =
|
|
8109
|
+
const absPath = path3.isAbsolute(picked) ? picked : path3.join(projectRoot, picked);
|
|
8063
8110
|
try {
|
|
8064
8111
|
const data = await fs2.readFile(absPath, "utf8");
|
|
8065
8112
|
const token = await builder.registerFile({
|
|
@@ -10330,7 +10377,12 @@ async function runTui(opts) {
|
|
|
10330
10377
|
stdout.write(BRACKETED_PASTE_ON);
|
|
10331
10378
|
stdout.write("\x1B[2J\x1B[H");
|
|
10332
10379
|
const inkStdin = stdin;
|
|
10333
|
-
const stopTitle = opts.titleAnimation !== false ? startTerminalTitle({
|
|
10380
|
+
const stopTitle = opts.titleAnimation !== false ? startTerminalTitle({
|
|
10381
|
+
stdout,
|
|
10382
|
+
events: opts.events,
|
|
10383
|
+
model: opts.model,
|
|
10384
|
+
appName: opts.projectRoot ? path3.basename(opts.projectRoot) : void 0
|
|
10385
|
+
}) : (() => {
|
|
10334
10386
|
});
|
|
10335
10387
|
const swallowSignals = ["SIGTSTP", "SIGQUIT", "SIGTTIN", "SIGTTOU"];
|
|
10336
10388
|
const swallow = () => {
|