mindweave 2.4.2 → 2.4.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/cli/App.js +55 -5
- package/dist/cli/App.js.map +1 -1
- package/dist/cli/blockSpacing.js +22 -1
- package/dist/cli/blockSpacing.js.map +1 -1
- package/dist/cli/components/ApprovalBox.js +16 -4
- package/dist/cli/components/ApprovalBox.js.map +1 -1
- package/dist/cli/components/BlockView.js +1 -1
- package/dist/cli/components/BlockView.js.map +1 -1
- package/dist/cli/components/ToolLine.js +12 -3
- package/dist/cli/components/ToolLine.js.map +1 -1
- package/dist/cli/framebuffer/writer.js +20 -3
- package/dist/cli/framebuffer/writer.js.map +1 -1
- package/dist/cli/toolDisplay.js +4 -1
- package/dist/cli/toolDisplay.js.map +1 -1
- package/dist/cli/transcript.js +1 -0
- package/dist/cli/transcript.js.map +1 -1
- package/dist/dynamo/engine.js +15 -0
- package/dist/dynamo/engine.js.map +1 -1
- package/dist/dynamo/prompt.js +1 -0
- package/dist/dynamo/prompt.js.map +1 -1
- package/dist/tools/askUser.js +26 -3
- package/dist/tools/askUser.js.map +1 -1
- package/dist/tools/backgroundShells.js +112 -7
- package/dist/tools/backgroundShells.js.map +1 -1
- package/dist/tools/shellTools.js +8 -1
- package/dist/tools/shellTools.js.map +1 -1
- package/package.json +74 -74
package/dist/cli/App.js
CHANGED
|
@@ -74,6 +74,7 @@ import { currentInstall, requestRestart, runUpdate } from "./updateRunner.js";
|
|
|
74
74
|
import { enableMouse, readMouse, readWheel } from "./mouse.js";
|
|
75
75
|
import { applySelection, ctrlCShouldCopy, isEmpty, selectionText } from "./selection.js";
|
|
76
76
|
import { latestScreen, repaintOverlay, setFrameOverlay } from "./framebuffer/overlay.js";
|
|
77
|
+
import { requestFullRepaint } from "./framebuffer/writer.js";
|
|
77
78
|
import { copyToClipboard } from "./clipboard.js";
|
|
78
79
|
import { chatLayout, reflowScroll } from "./chatAnchor.js";
|
|
79
80
|
import { growFill, INLINE_LIVE_RESERVE, NO_FILL } from "./startupFill.js";
|
|
@@ -651,6 +652,14 @@ export function App({ resumeSessionId, initialScreen }) {
|
|
|
651
652
|
// nothing else on screen would tell them their dev server had fallen over.
|
|
652
653
|
if (kind === "ready")
|
|
653
654
|
continue;
|
|
655
|
+
// The watchdog flagged a running shell as stuck — a prompt it is blocked on, or a
|
|
656
|
+
// long silence on a command that should be working. Worth a line: otherwise it sits
|
|
657
|
+
// invisible until it times out.
|
|
658
|
+
if (kind === "stalled") {
|
|
659
|
+
const why = sh.stallReason === "prompt" ? "waiting for input?" : "no output for a while — stuck?";
|
|
660
|
+
addTool(`shell #${sh.id} (${clipCmd(sh.command)}) ${why}`, { error: true });
|
|
661
|
+
continue;
|
|
662
|
+
}
|
|
654
663
|
if (sh.status === "killed" && sh.stoppedBy === "user")
|
|
655
664
|
continue;
|
|
656
665
|
const verb = sh.status === "killed" ? "killed" : `finished — exit ${sh.exitCode}`;
|
|
@@ -666,7 +675,7 @@ export function App({ resumeSessionId, initialScreen }) {
|
|
|
666
675
|
note(notice);
|
|
667
676
|
}
|
|
668
677
|
function attachApproval(s) {
|
|
669
|
-
s.toolContext.requestApproval = (q, o, detail, title) => askApproval.current(q, o, detail, title);
|
|
678
|
+
s.toolContext.requestApproval = (q, o, detail, title, freeText) => askApproval.current(q, o, detail, title, freeText);
|
|
670
679
|
// Same stop Esc performs. A tool reaches for this when the USER has said, by
|
|
671
680
|
// dismissing a question, that the work should not carry on without them.
|
|
672
681
|
s.toolContext.interrupt = () => abortRef.current?.abort();
|
|
@@ -978,6 +987,11 @@ export function App({ resumeSessionId, initialScreen }) {
|
|
|
978
987
|
// scrolled back down before the view moved at all. A flick or two past the top bought
|
|
979
988
|
// a second of a wheel that did nothing, which reads as the app having frozen.
|
|
980
989
|
const scrollBy = useCallback((lines) => {
|
|
990
|
+
// Repaint the whole next frame. A scroll can move a row out from under the
|
|
991
|
+
// framebuffer's model (see requestFullRepaint), which is what left a transcript row
|
|
992
|
+
// stranded on the pinned banner; a scroll already redraws almost every visible row, so
|
|
993
|
+
// redrawing the stable ones on top is nearly free and stops that.
|
|
994
|
+
requestFullRepaint();
|
|
981
995
|
setScrollUp((s) => Math.max(0, Math.min(maxScrollRef.current, s + lines)));
|
|
982
996
|
}, []);
|
|
983
997
|
/**
|
|
@@ -1030,10 +1044,14 @@ export function App({ resumeSessionId, initialScreen }) {
|
|
|
1030
1044
|
// back (see scrollPill.ts) names ctrl+End, so this is the half that makes the
|
|
1031
1045
|
// chip true. CTRL is what keeps them off the input: plain End and Home belong to
|
|
1032
1046
|
// the caret, whether or not the input claims them yet.
|
|
1033
|
-
else if (key.end && key.ctrl)
|
|
1047
|
+
else if (key.end && key.ctrl) {
|
|
1048
|
+
requestFullRepaint();
|
|
1034
1049
|
setScrollUp(0);
|
|
1035
|
-
|
|
1050
|
+
}
|
|
1051
|
+
else if (key.home && key.ctrl) {
|
|
1052
|
+
requestFullRepaint();
|
|
1036
1053
|
setScrollUp(maxScrollRef.current);
|
|
1054
|
+
}
|
|
1037
1055
|
}, { isActive: ready && overlay === null });
|
|
1038
1056
|
// Leaving the reading view when it reaches the bottom needs no effect of its own:
|
|
1039
1057
|
// `reading` is `scrollUp > 0`, so landing on zero — the wheel, the keys, ctrl+End, or
|
|
@@ -1307,6 +1325,7 @@ export function App({ resumeSessionId, initialScreen }) {
|
|
|
1307
1325
|
const hit = pillHit.current;
|
|
1308
1326
|
if (hit && hitsPill(hit, event.x, event.y)) {
|
|
1309
1327
|
clearSelection();
|
|
1328
|
+
requestFullRepaint();
|
|
1310
1329
|
setScrollUp(0);
|
|
1311
1330
|
continue;
|
|
1312
1331
|
}
|
|
@@ -1522,6 +1541,11 @@ export function App({ resumeSessionId, initialScreen }) {
|
|
|
1522
1541
|
const wait = revealWait({ flush: flush.current });
|
|
1523
1542
|
pumpTimer.current = setTimeout(() => {
|
|
1524
1543
|
pumpTimer.current = null;
|
|
1544
|
+
// A revealed block shifts the transcript, which can move a row out from under the
|
|
1545
|
+
// framebuffer's model and strand it on the pinned banner (see requestFullRepaint).
|
|
1546
|
+
// Set BEFORE the dispatch, so the very frame that shows the new block redraws the
|
|
1547
|
+
// banner too rather than leaving a stray row on it until the next paint.
|
|
1548
|
+
requestFullRepaint();
|
|
1525
1549
|
reveal();
|
|
1526
1550
|
lastRevealAt.current = Date.now();
|
|
1527
1551
|
pump();
|
|
@@ -1534,8 +1558,12 @@ export function App({ resumeSessionId, initialScreen }) {
|
|
|
1534
1558
|
const a = revealQ.current.shift();
|
|
1535
1559
|
if (a.type === "token")
|
|
1536
1560
|
applySilent(a);
|
|
1537
|
-
else
|
|
1561
|
+
else {
|
|
1562
|
+
// An in-place resolve grows a row into its result, shifting everything below it —
|
|
1563
|
+
// the same de-sync risk a reveal carries, so heal the banner on the same frame.
|
|
1564
|
+
requestFullRepaint();
|
|
1538
1565
|
dispatch(a);
|
|
1566
|
+
}
|
|
1539
1567
|
// A group stays open once shown; anything that isn't part of it (a
|
|
1540
1568
|
// standalone tool, narration, a sub-agent) closes it, mirroring exactly
|
|
1541
1569
|
// what the transcript reducer's own closeToolGroup does on the same actions.
|
|
@@ -3764,11 +3792,33 @@ export function mcpDetail(server, blocked = 0) {
|
|
|
3764
3792
|
* The port comes from the process's own startup line (see detectPort), so it is
|
|
3765
3793
|
* shown only when the server actually said where it is listening. */
|
|
3766
3794
|
function BackgroundBar({ shells }) {
|
|
3795
|
+
// Tick once a second while anything runs, so the elapsed clock beside each command
|
|
3796
|
+
// actually moves — that motion is the whole point: it says the command is still
|
|
3797
|
+
// working, not wedged. The interval is torn down the moment nothing is running.
|
|
3798
|
+
const [, setTick] = useState(0);
|
|
3799
|
+
useEffect(() => {
|
|
3800
|
+
if (shells.length === 0)
|
|
3801
|
+
return;
|
|
3802
|
+
const id = setInterval(() => setTick((t) => t + 1), 1000);
|
|
3803
|
+
return () => clearInterval(id);
|
|
3804
|
+
}, [shells.length]);
|
|
3767
3805
|
if (shells.length === 0)
|
|
3768
3806
|
return null;
|
|
3769
|
-
const
|
|
3807
|
+
const now = Date.now();
|
|
3808
|
+
const cmds = shells
|
|
3809
|
+
.map((s) => `$ ${clipCmd(s.command)}${s.port ? ` (${s.port})` : ""} ${bgClock(now - s.startedAt)}`)
|
|
3810
|
+
.join(" • ");
|
|
3770
3811
|
return (_jsxs(Box, { children: [_jsx(Text, { color: "yellow", children: "[BG] " }), _jsx(Text, { dimColor: true, wrap: "truncate-end", children: `${shells.length} running: ${cmds}` })] }));
|
|
3771
3812
|
}
|
|
3813
|
+
/** Elapsed for the background bar: whole seconds under a minute, `1m 20s` past it. */
|
|
3814
|
+
function bgClock(ms) {
|
|
3815
|
+
const seconds = Math.max(0, Math.round(ms / 1000));
|
|
3816
|
+
if (seconds < 60)
|
|
3817
|
+
return `${seconds}s`;
|
|
3818
|
+
const m = Math.floor(seconds / 60);
|
|
3819
|
+
const s = seconds % 60;
|
|
3820
|
+
return s === 0 ? `${m}m` : `${m}m ${s}s`;
|
|
3821
|
+
}
|
|
3772
3822
|
// One short, useful line rendered inside the input box (see PromptInput's
|
|
3773
3823
|
// `tip` prop) — picked once per session, not rewritten every render. The
|
|
3774
3824
|
// mode/model/thinking readout already lives in the header, so this slot is
|