@wrongstack/tui 0.260.0 → 0.265.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.d.ts +36 -3
- package/dist/index.js +1018 -138
- package/dist/index.js.map +1 -1
- package/package.json +4 -4
package/dist/index.js
CHANGED
|
@@ -1,15 +1,16 @@
|
|
|
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';
|
|
1
|
+
import { writeErr, resolveProjectDir, wstackGlobalRoot, GlobalMailbox, resolveWstackPaths, loadGoal, InputBuilder, DefaultSessionRewinder, writeOut, formatTodosList, buildGoalPreamble, expectDefined as expectDefined$1, projectSlug, 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
4
|
import { randomUUID } from 'crypto';
|
|
5
|
-
import * as
|
|
5
|
+
import * as path5 from 'path';
|
|
6
6
|
import React5, { forwardRef, useState, useEffect, useMemo, memo, useRef, useCallback, useReducer, useLayoutEffect } from 'react';
|
|
7
|
-
import * as
|
|
7
|
+
import * as fs3 from 'fs/promises';
|
|
8
|
+
import { expectDefined, toErrorMessage, resolveWstackPaths as resolveWstackPaths$1 } from '@wrongstack/core/utils';
|
|
8
9
|
import { routeImagesForModel } from '@wrongstack/runtime/vision';
|
|
9
10
|
import { getIndexState, onIndexStateChange, getProcessRegistry } from '@wrongstack/tools';
|
|
10
11
|
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
11
|
-
import { readClipboardImage } from '@wrongstack/runtime/clipboard';
|
|
12
|
-
import {
|
|
12
|
+
import { readClipboardText, readClipboardImage } from '@wrongstack/runtime/clipboard';
|
|
13
|
+
import { getToolIcon, TOOL_ICON_CONFIG } from '@wrongstack/tools/tool-icons';
|
|
13
14
|
import * as v8 from 'v8';
|
|
14
15
|
import { spawn } from 'child_process';
|
|
15
16
|
|
|
@@ -160,11 +161,13 @@ function StatusBar({
|
|
|
160
161
|
workingDir,
|
|
161
162
|
processCount,
|
|
162
163
|
context,
|
|
164
|
+
contextStrategy,
|
|
163
165
|
hiddenItems,
|
|
164
166
|
events,
|
|
165
167
|
eternalStage,
|
|
166
168
|
goalSummary,
|
|
167
169
|
indexState,
|
|
170
|
+
breakerCountdown,
|
|
168
171
|
modeLabel,
|
|
169
172
|
debugStreamStats,
|
|
170
173
|
enhanceCountdown,
|
|
@@ -273,7 +276,12 @@ function StatusBar({
|
|
|
273
276
|
"ctx ",
|
|
274
277
|
renderMeter(clampedRatio, 8),
|
|
275
278
|
" ",
|
|
276
|
-
pctText
|
|
279
|
+
pctText,
|
|
280
|
+
contextStrategy ? /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
281
|
+
" [",
|
|
282
|
+
contextStrategy,
|
|
283
|
+
"]"
|
|
284
|
+
] }) : null
|
|
277
285
|
] });
|
|
278
286
|
})()
|
|
279
287
|
] }) : null,
|
|
@@ -334,7 +342,21 @@ function StatusBar({
|
|
|
334
342
|
] }) : indexState?.circuit?.state === "open" ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
335
343
|
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" }),
|
|
336
344
|
/* @__PURE__ */ jsx(Text, { color: "red", children: "\u2699 index paused (/reindex)" })
|
|
337
|
-
] }) : null
|
|
345
|
+
] }) : null,
|
|
346
|
+
breakerCountdown ? (() => {
|
|
347
|
+
const secs = Math.ceil(breakerCountdown.remainingMs / 1e3);
|
|
348
|
+
const ratio = breakerCountdown.totalMs > 0 ? breakerCountdown.remainingMs / breakerCountdown.totalMs : 0;
|
|
349
|
+
const c = secs > 20 ? "green" : secs > 10 ? "yellow" : "red";
|
|
350
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
351
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" }),
|
|
352
|
+
/* @__PURE__ */ jsxs(Text, { color: c, bold: true, children: [
|
|
353
|
+
"\u26A1 kill/reset in ",
|
|
354
|
+
secs,
|
|
355
|
+
"s",
|
|
356
|
+
ratio <= 0.25 ? "!" : ""
|
|
357
|
+
] })
|
|
358
|
+
] });
|
|
359
|
+
})() : null
|
|
338
360
|
] })
|
|
339
361
|
) }),
|
|
340
362
|
hasSecondLine ? /* @__PURE__ */ jsxs(Box, { flexDirection: "row", gap: 2, children: [
|
|
@@ -485,6 +507,11 @@ function StatusBar({
|
|
|
485
507
|
plan.done > 0 ? /* @__PURE__ */ jsxs(Text, { color: "green", children: [
|
|
486
508
|
"\u2713",
|
|
487
509
|
plan.done
|
|
510
|
+
] }) : null,
|
|
511
|
+
plan.scope ? /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
512
|
+
" [",
|
|
513
|
+
plan.scope,
|
|
514
|
+
"]"
|
|
488
515
|
] }) : null
|
|
489
516
|
] })
|
|
490
517
|
] }) : null,
|
|
@@ -515,6 +542,11 @@ function StatusBar({
|
|
|
515
542
|
tasks.failed > 0 ? /* @__PURE__ */ jsxs(Text, { color: "red", children: [
|
|
516
543
|
"\u2717",
|
|
517
544
|
tasks.failed
|
|
545
|
+
] }) : null,
|
|
546
|
+
tasks.scope ? /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
547
|
+
" [",
|
|
548
|
+
tasks.scope,
|
|
549
|
+
"]"
|
|
518
550
|
] }) : null
|
|
519
551
|
] })
|
|
520
552
|
] }) : null,
|
|
@@ -594,7 +626,8 @@ function StatusBar({
|
|
|
594
626
|
] }),
|
|
595
627
|
/* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
596
628
|
" ",
|
|
597
|
-
nextStepsAutoSubmitLabel ? formatSuggestionLabel(nextStepsAutoSubmitLabel) : ""
|
|
629
|
+
nextStepsAutoSubmitLabel ? formatSuggestionLabel(nextStepsAutoSubmitLabel) : "",
|
|
630
|
+
" \xB7 \u21E5 edit"
|
|
598
631
|
] })
|
|
599
632
|
] }) : null
|
|
600
633
|
] }) : /* @__PURE__ */ jsx(Box, { height: 1, children: /* @__PURE__ */ jsx(Text, { children: " " }) }),
|
|
@@ -1758,8 +1791,8 @@ function FilePicker({ query, matches, selected }) {
|
|
|
1758
1791
|
] }, m))
|
|
1759
1792
|
] });
|
|
1760
1793
|
}
|
|
1761
|
-
function highlight(
|
|
1762
|
-
return
|
|
1794
|
+
function highlight(path7, _query) {
|
|
1795
|
+
return path7;
|
|
1763
1796
|
}
|
|
1764
1797
|
function FleetPanel({
|
|
1765
1798
|
entries,
|
|
@@ -1923,6 +1956,36 @@ function MailboxPanel({
|
|
|
1923
1956
|
/* @__PURE__ */ jsx(Box, { marginTop: 1, children: /* @__PURE__ */ jsx(Text, { dimColor: true, children: "/mailbox \u2014 Esc to close" }) })
|
|
1924
1957
|
] });
|
|
1925
1958
|
}
|
|
1959
|
+
var TOOL_GLYPHS = {
|
|
1960
|
+
file: "\u25A4",
|
|
1961
|
+
edit: "\u270E",
|
|
1962
|
+
search: "\u2315",
|
|
1963
|
+
folder: "\u25A3",
|
|
1964
|
+
terminal: "\u25B8",
|
|
1965
|
+
web: "\u25C8",
|
|
1966
|
+
git: "\u2387",
|
|
1967
|
+
tree: "\u2630",
|
|
1968
|
+
code: "\u2699",
|
|
1969
|
+
test: "\u2697",
|
|
1970
|
+
package: "\u2B22",
|
|
1971
|
+
document: "\u2637",
|
|
1972
|
+
scaffold: "\u2731",
|
|
1973
|
+
todo: "\u2610",
|
|
1974
|
+
plan: "\u2756",
|
|
1975
|
+
task: "\u25AA",
|
|
1976
|
+
meta: "\u274F",
|
|
1977
|
+
index: "\u229B",
|
|
1978
|
+
json: "\u2317",
|
|
1979
|
+
diff: "\u2206",
|
|
1980
|
+
logs: "\u2261",
|
|
1981
|
+
settings: "\u2699",
|
|
1982
|
+
brain: "\u2726",
|
|
1983
|
+
fallback: "\u2022"
|
|
1984
|
+
};
|
|
1985
|
+
function getToolVisual(name) {
|
|
1986
|
+
const id = getToolIcon(name);
|
|
1987
|
+
return { glyph: TOOL_GLYPHS[id], color: TOOL_ICON_CONFIG[id].color };
|
|
1988
|
+
}
|
|
1926
1989
|
function helpSections() {
|
|
1927
1990
|
const nav = [];
|
|
1928
1991
|
nav.push(
|
|
@@ -1969,31 +2032,133 @@ function helpSections() {
|
|
|
1969
2032
|
{ keys: "/settings", desc: "autonomy defaults (also Ctrl+S)" },
|
|
1970
2033
|
{ keys: "/clear", desc: "clear the conversation" }
|
|
1971
2034
|
]
|
|
2035
|
+
},
|
|
2036
|
+
{
|
|
2037
|
+
title: "Tool Colors",
|
|
2038
|
+
entries: toolColorLegend()
|
|
1972
2039
|
}
|
|
1973
2040
|
];
|
|
1974
2041
|
}
|
|
2042
|
+
function toolColorLegend() {
|
|
2043
|
+
const tools = [
|
|
2044
|
+
// File operations (most common)
|
|
2045
|
+
{ name: "read/write", tool: "read", desc: "file I/O" },
|
|
2046
|
+
{ name: "write", tool: "write", desc: "create file" },
|
|
2047
|
+
{ name: "edit", tool: "edit", desc: "edit file" },
|
|
2048
|
+
{ name: "patch", tool: "patch", desc: "diff/patch" },
|
|
2049
|
+
// Search
|
|
2050
|
+
{ name: "search", tool: "grep", desc: "search" },
|
|
2051
|
+
{ name: "glob", tool: "glob", desc: "glob/pattern" },
|
|
2052
|
+
// Shell & web
|
|
2053
|
+
{ name: "terminal", tool: "bash", desc: "shell" },
|
|
2054
|
+
{ name: "web", tool: "fetch", desc: "web" },
|
|
2055
|
+
// Navigation & tree
|
|
2056
|
+
{ name: "folder", tool: "ls", desc: "navigate" },
|
|
2057
|
+
{ name: "tree", tool: "tree", desc: "tree view" },
|
|
2058
|
+
// VCS
|
|
2059
|
+
{ name: "git", tool: "git", desc: "git" },
|
|
2060
|
+
// Code quality
|
|
2061
|
+
{ name: "lint", tool: "lint", desc: "lint" },
|
|
2062
|
+
{ name: "format", tool: "format", desc: "format" },
|
|
2063
|
+
{ name: "typecheck", tool: "typecheck", desc: "typecheck" },
|
|
2064
|
+
// Testing & packages
|
|
2065
|
+
{ name: "test", tool: "test", desc: "test" },
|
|
2066
|
+
{ name: "package", tool: "install", desc: "packages" },
|
|
2067
|
+
{ name: "audit", tool: "audit", desc: "audit" },
|
|
2068
|
+
// Planning & tracking
|
|
2069
|
+
{ name: "todo", tool: "todo", desc: "todos" },
|
|
2070
|
+
{ name: "plan", tool: "plan", desc: "planning" },
|
|
2071
|
+
{ name: "task", tool: "task", desc: "tasks" },
|
|
2072
|
+
// Docs & scaffolding
|
|
2073
|
+
{ name: "document", tool: "document", desc: "docs" },
|
|
2074
|
+
{ name: "scaffold", tool: "scaffold", desc: "scaffold" },
|
|
2075
|
+
// Data & logs
|
|
2076
|
+
{ name: "json", tool: "json", desc: "JSON" },
|
|
2077
|
+
{ name: "logs", tool: "logs", desc: "logs" },
|
|
2078
|
+
// Memory & meta
|
|
2079
|
+
{ name: "brain", tool: "remember", desc: "memory" },
|
|
2080
|
+
{ name: "tool_use", tool: "tool_use", desc: "tool chain" }
|
|
2081
|
+
];
|
|
2082
|
+
return tools.map(({ name, tool, desc }) => {
|
|
2083
|
+
const { glyph, color } = getToolVisual(tool);
|
|
2084
|
+
return {
|
|
2085
|
+
keys: `${glyph} ${name}`,
|
|
2086
|
+
desc: `${desc} (${color})`
|
|
2087
|
+
};
|
|
2088
|
+
});
|
|
2089
|
+
}
|
|
2090
|
+
function splitIntoColumns(entries) {
|
|
2091
|
+
const left = [];
|
|
2092
|
+
const right = [];
|
|
2093
|
+
for (const entry of entries) {
|
|
2094
|
+
if (left.length <= right.length) {
|
|
2095
|
+
left.push(entry);
|
|
2096
|
+
} else {
|
|
2097
|
+
right.push(entry);
|
|
2098
|
+
}
|
|
2099
|
+
}
|
|
2100
|
+
return [left, right];
|
|
2101
|
+
}
|
|
1975
2102
|
function HelpOverlay() {
|
|
1976
2103
|
const sections = helpSections();
|
|
1977
|
-
const
|
|
2104
|
+
const otherSections = sections.filter((s2) => s2.title !== "Tool Colors");
|
|
2105
|
+
const otherKeyWidth = Math.max(
|
|
2106
|
+
...otherSections.flatMap((s2) => s2.entries.map((e) => e.keys.length)),
|
|
2107
|
+
0
|
|
2108
|
+
);
|
|
2109
|
+
const toolSection = sections.find((s2) => s2.title === "Tool Colors");
|
|
2110
|
+
const toolKeyWidth = toolSection ? Math.max(...toolSection.entries.map((e) => e.keys.length), 0) : 0;
|
|
1978
2111
|
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", borderStyle: "round", borderColor: theme.accent, paddingX: 1, children: [
|
|
1979
2112
|
/* @__PURE__ */ jsxs(Box, { flexDirection: "row", gap: 1, children: [
|
|
1980
2113
|
/* @__PURE__ */ jsx(Text, { bold: true, color: theme.accent, children: "Keyboard shortcuts" }),
|
|
1981
2114
|
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "\xB7 Esc to close" })
|
|
1982
2115
|
] }),
|
|
1983
|
-
sections.map((sec) =>
|
|
1984
|
-
|
|
1985
|
-
|
|
1986
|
-
Box,
|
|
1987
|
-
|
|
1988
|
-
flexDirection: "row",
|
|
1989
|
-
|
|
1990
|
-
|
|
1991
|
-
|
|
1992
|
-
|
|
1993
|
-
|
|
1994
|
-
|
|
1995
|
-
|
|
1996
|
-
|
|
2116
|
+
sections.map((sec) => {
|
|
2117
|
+
if (sec.title === "Tool Colors") {
|
|
2118
|
+
const [leftCol, rightCol] = splitIntoColumns(sec.entries);
|
|
2119
|
+
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", marginTop: 1, children: [
|
|
2120
|
+
/* @__PURE__ */ jsx(Text, { bold: true, color: theme.brand, children: sec.title }),
|
|
2121
|
+
/* @__PURE__ */ jsxs(Box, { flexDirection: "row", gap: 2, children: [
|
|
2122
|
+
/* @__PURE__ */ jsx(Box, { flexDirection: "column", children: leftCol.map((e, i) => /* @__PURE__ */ jsxs(
|
|
2123
|
+
Box,
|
|
2124
|
+
{
|
|
2125
|
+
flexDirection: "row",
|
|
2126
|
+
children: [
|
|
2127
|
+
/* @__PURE__ */ jsx(Text, { color: theme.accent, children: e.keys.padEnd(toolKeyWidth + 2) }),
|
|
2128
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: e.desc })
|
|
2129
|
+
]
|
|
2130
|
+
},
|
|
2131
|
+
i
|
|
2132
|
+
)) }),
|
|
2133
|
+
/* @__PURE__ */ jsx(Box, { flexDirection: "column", children: rightCol.map((e, i) => /* @__PURE__ */ jsxs(
|
|
2134
|
+
Box,
|
|
2135
|
+
{
|
|
2136
|
+
flexDirection: "row",
|
|
2137
|
+
children: [
|
|
2138
|
+
/* @__PURE__ */ jsx(Text, { color: theme.accent, children: e.keys.padEnd(toolKeyWidth + 2) }),
|
|
2139
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: e.desc })
|
|
2140
|
+
]
|
|
2141
|
+
},
|
|
2142
|
+
i
|
|
2143
|
+
)) })
|
|
2144
|
+
] })
|
|
2145
|
+
] }, sec.title);
|
|
2146
|
+
}
|
|
2147
|
+
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", marginTop: 1, children: [
|
|
2148
|
+
/* @__PURE__ */ jsx(Text, { bold: true, color: theme.brand, children: sec.title }),
|
|
2149
|
+
sec.entries.map((e, i) => /* @__PURE__ */ jsxs(
|
|
2150
|
+
Box,
|
|
2151
|
+
{
|
|
2152
|
+
flexDirection: "row",
|
|
2153
|
+
children: [
|
|
2154
|
+
/* @__PURE__ */ jsx(Text, { color: theme.accent, children: e.keys.padEnd(otherKeyWidth + 2) }),
|
|
2155
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: e.desc })
|
|
2156
|
+
]
|
|
2157
|
+
},
|
|
2158
|
+
i
|
|
2159
|
+
))
|
|
2160
|
+
] }, sec.title);
|
|
2161
|
+
})
|
|
1997
2162
|
] });
|
|
1998
2163
|
}
|
|
1999
2164
|
|
|
@@ -3518,6 +3683,7 @@ var ToolStreamBox = React5.memo(function ToolStreamBox2({
|
|
|
3518
3683
|
startedAt,
|
|
3519
3684
|
termWidth
|
|
3520
3685
|
}) {
|
|
3686
|
+
const { glyph, color } = getToolVisual(name);
|
|
3521
3687
|
const [tick, setTick] = useState(0);
|
|
3522
3688
|
useEffect(() => {
|
|
3523
3689
|
const t = setInterval(() => setTick((n) => n + 1), 500);
|
|
@@ -3530,8 +3696,11 @@ var ToolStreamBox = React5.memo(function ToolStreamBox2({
|
|
|
3530
3696
|
const rows = streamBoxRows(text, MAX_STREAM_LINES, contentWidth);
|
|
3531
3697
|
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", marginTop: 0, children: [
|
|
3532
3698
|
/* @__PURE__ */ jsxs(Box, { flexDirection: "row", children: [
|
|
3533
|
-
/* @__PURE__ */
|
|
3534
|
-
|
|
3699
|
+
/* @__PURE__ */ jsxs(Text, { color, children: [
|
|
3700
|
+
glyph,
|
|
3701
|
+
" "
|
|
3702
|
+
] }),
|
|
3703
|
+
/* @__PURE__ */ jsx(Text, { bold: true, color, children: name }),
|
|
3535
3704
|
/* @__PURE__ */ jsx(Text, { dimColor: true, children: ` \u23F1 ${fmtDuration(elapsedMs)}` }),
|
|
3536
3705
|
hidden > 0 ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: ` (${totalLines} lines, showing last ${MAX_STREAM_LINES})` }) : null
|
|
3537
3706
|
] }),
|
|
@@ -3804,7 +3973,7 @@ function Banner({
|
|
|
3804
3973
|
entry
|
|
3805
3974
|
}) {
|
|
3806
3975
|
const cwdShort = shortenPath(entry.cwd, 48);
|
|
3807
|
-
const projectLabel =
|
|
3976
|
+
const projectLabel = path5.basename(entry.cwd);
|
|
3808
3977
|
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", borderStyle: "round", borderColor: "magenta", paddingX: 2, paddingY: 0, children: [
|
|
3809
3978
|
/* @__PURE__ */ jsxs(Text, { children: [
|
|
3810
3979
|
/* @__PURE__ */ jsx(Text, { color: "magenta", bold: true, children: " \u259F\u259B " }),
|
|
@@ -3922,13 +4091,14 @@ function parseWithHeading(content, strict) {
|
|
|
3922
4091
|
if (steps.length === 0) {
|
|
3923
4092
|
return { steps: [], texts: [], stripped: content, autoTexts: [] };
|
|
3924
4093
|
}
|
|
3925
|
-
|
|
4094
|
+
const headingWasXmlTag = headingMatch[0].startsWith("<");
|
|
4095
|
+
if (strict && headingWasXmlTag && !afterHeading.includes("</next_steps>")) {
|
|
3926
4096
|
return { steps: [], texts: [], stripped: content, autoTexts: [] };
|
|
3927
4097
|
}
|
|
3928
4098
|
const texts = steps.map((s2) => s2.text);
|
|
3929
4099
|
const autoTexts = steps.filter((s2) => s2.auto).map((s2) => s2.text);
|
|
3930
4100
|
const blockStart = headingMatch.index;
|
|
3931
|
-
const blockEnd =
|
|
4101
|
+
const blockEnd = headingMatch[0].length + findBlockEnd(afterHeading, steps.length);
|
|
3932
4102
|
const stripped = (content.slice(0, blockStart) + content.slice(blockStart + blockEnd)).replace(/\n{3,}/g, "\n\n").trim();
|
|
3933
4103
|
return { steps, texts, stripped, autoTexts };
|
|
3934
4104
|
}
|
|
@@ -3937,24 +4107,26 @@ function buildPermissiveHeadingRe() {
|
|
|
3937
4107
|
return new RegExp(variants, "i");
|
|
3938
4108
|
}
|
|
3939
4109
|
function findBlockEnd(afterHeading, stepCount) {
|
|
4110
|
+
const closeIdx = afterHeading.indexOf("</next_steps>");
|
|
4111
|
+
if (closeIdx !== -1) {
|
|
4112
|
+
let end = closeIdx + "</next_steps>".length;
|
|
4113
|
+
if (afterHeading[end] === "\n") end += 1;
|
|
4114
|
+
return end;
|
|
4115
|
+
}
|
|
3940
4116
|
const lines = afterHeading.split("\n");
|
|
3941
4117
|
let consumed = 0;
|
|
3942
4118
|
let found = 0;
|
|
3943
4119
|
for (const rawLine of lines) {
|
|
3944
4120
|
const line = rawLine.trim();
|
|
3945
|
-
if (line
|
|
3946
|
-
consumed += rawLine.length + 1;
|
|
3947
|
-
break;
|
|
3948
|
-
}
|
|
3949
|
-
if (!line) {
|
|
3950
|
-
consumed += rawLine.length + 1;
|
|
3951
|
-
continue;
|
|
3952
|
-
}
|
|
4121
|
+
if (!line) break;
|
|
3953
4122
|
const m = ITEM_RE.exec(line);
|
|
3954
4123
|
if (!m) break;
|
|
3955
4124
|
consumed += rawLine.length + 1;
|
|
3956
4125
|
found++;
|
|
3957
|
-
if (found >= stepCount)
|
|
4126
|
+
if (found >= stepCount) {
|
|
4127
|
+
consumed -= 1;
|
|
4128
|
+
break;
|
|
4129
|
+
}
|
|
3958
4130
|
}
|
|
3959
4131
|
return consumed;
|
|
3960
4132
|
}
|
|
@@ -4083,6 +4255,7 @@ var Entry = React5.memo(function Entry2({
|
|
|
4083
4255
|
] });
|
|
4084
4256
|
}
|
|
4085
4257
|
case "tool": {
|
|
4258
|
+
const { glyph, color } = getToolVisual(entry.name);
|
|
4086
4259
|
const argSummary = formatToolArgs(entry.name, entry.input);
|
|
4087
4260
|
const outLines = formatToolOutput(
|
|
4088
4261
|
entry.name,
|
|
@@ -4108,9 +4281,9 @@ var Entry = React5.memo(function Entry2({
|
|
|
4108
4281
|
})();
|
|
4109
4282
|
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", children: [
|
|
4110
4283
|
/* @__PURE__ */ jsxs(Text, { children: [
|
|
4111
|
-
/* @__PURE__ */ jsx(Text, { color
|
|
4112
|
-
" ",
|
|
4113
|
-
/* @__PURE__ */ jsx(Text, { bold: true, color
|
|
4284
|
+
/* @__PURE__ */ jsx(Text, { color, children: glyph }),
|
|
4285
|
+
/* @__PURE__ */ jsx(Text, { children: " " }),
|
|
4286
|
+
/* @__PURE__ */ jsx(Text, { bold: true, color, children: entry.name }),
|
|
4114
4287
|
argSummary ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
4115
4288
|
/* @__PURE__ */ jsx(Text, { children: " " }),
|
|
4116
4289
|
/* @__PURE__ */ jsx(Text, { dimColor: true, children: argSummary })
|
|
@@ -4377,7 +4550,7 @@ function ScrollableHistory({
|
|
|
4377
4550
|
}
|
|
4378
4551
|
var MB = 1024 * 1024;
|
|
4379
4552
|
function defaultHeapLogPath() {
|
|
4380
|
-
return
|
|
4553
|
+
return path5.join(wstackGlobalRoot(), "logs", "heap.jsonl");
|
|
4381
4554
|
}
|
|
4382
4555
|
function takeHeapSample() {
|
|
4383
4556
|
const m = process.memoryUsage();
|
|
@@ -4407,10 +4580,10 @@ function startHeapWatchdog(opts = {}) {
|
|
|
4407
4580
|
const append = (line) => {
|
|
4408
4581
|
writeChain = writeChain.then(async () => {
|
|
4409
4582
|
if (!dirReady) {
|
|
4410
|
-
await
|
|
4583
|
+
await fs3.mkdir(path5.dirname(logPath), { recursive: true });
|
|
4411
4584
|
dirReady = true;
|
|
4412
4585
|
}
|
|
4413
|
-
await
|
|
4586
|
+
await fs3.appendFile(logPath, `${line}
|
|
4414
4587
|
`, "utf8");
|
|
4415
4588
|
}).catch(() => void 0);
|
|
4416
4589
|
};
|
|
@@ -4583,6 +4756,52 @@ function layoutInputRows(prompt, value, cursor, width) {
|
|
|
4583
4756
|
if (row.length > 0 || rows.length === 0) rows.push(row);
|
|
4584
4757
|
return rows;
|
|
4585
4758
|
}
|
|
4759
|
+
function inputIndexAtRowCol(prompt, value, width, row, col) {
|
|
4760
|
+
const w = Math.max(1, Math.floor(width));
|
|
4761
|
+
const flat = [];
|
|
4762
|
+
for (let i = 0; i < prompt.length; i++) flat.push({ ch: prompt[i], buf: -1 });
|
|
4763
|
+
for (let i = 0; i < value.length; i++) flat.push({ ch: value[i], buf: i });
|
|
4764
|
+
const rows = [];
|
|
4765
|
+
const starts = [];
|
|
4766
|
+
let cur = [];
|
|
4767
|
+
let curStart = 0;
|
|
4768
|
+
for (const cell of flat) {
|
|
4769
|
+
if (cell.ch === "\n") {
|
|
4770
|
+
rows.push(cur);
|
|
4771
|
+
starts.push(curStart);
|
|
4772
|
+
cur = [];
|
|
4773
|
+
curStart = cell.buf + 1;
|
|
4774
|
+
continue;
|
|
4775
|
+
}
|
|
4776
|
+
if (cur.length === 0 && cell.buf >= 0) curStart = cell.buf;
|
|
4777
|
+
cur.push({ buf: cell.buf });
|
|
4778
|
+
if (cur.length >= w) {
|
|
4779
|
+
rows.push(cur);
|
|
4780
|
+
starts.push(curStart);
|
|
4781
|
+
cur = [];
|
|
4782
|
+
curStart = -1;
|
|
4783
|
+
}
|
|
4784
|
+
}
|
|
4785
|
+
if (cur.length > 0 || rows.length === 0) {
|
|
4786
|
+
rows.push(cur);
|
|
4787
|
+
starts.push(curStart);
|
|
4788
|
+
}
|
|
4789
|
+
const clamp = (n) => Math.max(0, Math.min(value.length, n));
|
|
4790
|
+
if (row < 0) return 0;
|
|
4791
|
+
if (row >= rows.length) return value.length;
|
|
4792
|
+
const r = rows[row];
|
|
4793
|
+
const c = Math.max(0, col);
|
|
4794
|
+
if (c < r.length) {
|
|
4795
|
+
const b = r[c].buf;
|
|
4796
|
+
return b < 0 ? 0 : clamp(b);
|
|
4797
|
+
}
|
|
4798
|
+
for (let k = r.length - 1; k >= 0; k--) {
|
|
4799
|
+
const b = r[k].buf;
|
|
4800
|
+
if (b >= 0) return clamp(b + 1);
|
|
4801
|
+
}
|
|
4802
|
+
const start = starts[row];
|
|
4803
|
+
return clamp(start !== void 0 && start >= 0 ? start : value.length);
|
|
4804
|
+
}
|
|
4586
4805
|
|
|
4587
4806
|
// src/mouse.ts
|
|
4588
4807
|
var ESC = String.fromCharCode(27);
|
|
@@ -4936,12 +5155,8 @@ function PhaseMonitor({
|
|
|
4936
5155
|
phases,
|
|
4937
5156
|
runningPhaseIds,
|
|
4938
5157
|
elapsedMs,
|
|
4939
|
-
nowTick
|
|
4940
|
-
onClose
|
|
5158
|
+
nowTick
|
|
4941
5159
|
}) {
|
|
4942
|
-
useInput((_, key) => {
|
|
4943
|
-
if (key.escape) onClose();
|
|
4944
|
-
});
|
|
4945
5160
|
const phaseList = Object.values(phases);
|
|
4946
5161
|
const running = phaseList.filter(
|
|
4947
5162
|
(p) => runningPhaseIds.includes(Object.keys(phases).find((k) => phases[k] === p) ?? "")
|
|
@@ -4973,7 +5188,7 @@ function PhaseMonitor({
|
|
|
4973
5188
|
failed.length
|
|
4974
5189
|
] })
|
|
4975
5190
|
] }) : null,
|
|
4976
|
-
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502 Ctrl+P
|
|
5191
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502 Ctrl+P to close" })
|
|
4977
5192
|
] }),
|
|
4978
5193
|
phaseList.length === 0 ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: "No phases active. Use /autophase start [title] to begin." }) : phaseList.map((phase, i) => {
|
|
4979
5194
|
const s2 = fmtPhase(phase.status);
|
|
@@ -5002,7 +5217,7 @@ function PhaseMonitor({
|
|
|
5002
5217
|
] })
|
|
5003
5218
|
] }) }, phaseKey);
|
|
5004
5219
|
}),
|
|
5005
|
-
/* @__PURE__ */ jsx(Box, { marginTop: 1, children: /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2191/\u2193 navigate phases
|
|
5220
|
+
/* @__PURE__ */ jsx(Box, { marginTop: 1, children: /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2191/\u2193 navigate phases" }) })
|
|
5006
5221
|
] });
|
|
5007
5222
|
}
|
|
5008
5223
|
var fmtElapsed3 = (ms) => {
|
|
@@ -5183,7 +5398,7 @@ function QueuePanel({ items }) {
|
|
|
5183
5398
|
"+",
|
|
5184
5399
|
overflow
|
|
5185
5400
|
] }) : null,
|
|
5186
|
-
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502 F7
|
|
5401
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502 F7 to close" })
|
|
5187
5402
|
] }) }),
|
|
5188
5403
|
items.length === 0 ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: "No queued messages" }) : /* @__PURE__ */ jsxs(Box, { flexDirection: "column", children: [
|
|
5189
5404
|
visible.map((item, i) => /* @__PURE__ */ jsxs(Box, { flexDirection: "row", flexShrink: 0, children: [
|
|
@@ -5259,7 +5474,7 @@ function ProcessListMonitor() {
|
|
|
5259
5474
|
breakerState,
|
|
5260
5475
|
b.state !== "closed" ? ` fail=${b.consecutiveFailures}/5 slow=${b.slowCallsInWindow}/3` : ""
|
|
5261
5476
|
] }),
|
|
5262
|
-
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502 F8
|
|
5477
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502 F8 to close" })
|
|
5263
5478
|
] }),
|
|
5264
5479
|
all.length === 0 ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: "No active processes. Bash/exec spawns appear here." }) : null,
|
|
5265
5480
|
all.map((p, i) => {
|
|
@@ -5288,7 +5503,25 @@ function ProcessListMonitor() {
|
|
|
5288
5503
|
] })
|
|
5289
5504
|
] });
|
|
5290
5505
|
}
|
|
5291
|
-
function GoalPanel({
|
|
5506
|
+
function GoalPanel({
|
|
5507
|
+
goal,
|
|
5508
|
+
onCoordinatorStart,
|
|
5509
|
+
onCoordinatorStop,
|
|
5510
|
+
coordinatorRunning
|
|
5511
|
+
}) {
|
|
5512
|
+
useInput((input) => {
|
|
5513
|
+
if (input === "c" || input === "C") {
|
|
5514
|
+
if (onCoordinatorStart && goal) {
|
|
5515
|
+
const goalText = goal.refinedGoal || goal.goal;
|
|
5516
|
+
onCoordinatorStart(goalText);
|
|
5517
|
+
}
|
|
5518
|
+
}
|
|
5519
|
+
if (input === "S") {
|
|
5520
|
+
if (onCoordinatorStop) {
|
|
5521
|
+
onCoordinatorStop();
|
|
5522
|
+
}
|
|
5523
|
+
}
|
|
5524
|
+
});
|
|
5292
5525
|
if (!goal) {
|
|
5293
5526
|
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", padding: 1, children: [
|
|
5294
5527
|
/* @__PURE__ */ jsx(Box, { marginBottom: 1, children: /* @__PURE__ */ jsx(Text, { bold: true, color: theme.accent, children: "\u{1F3AF} Goal" }) }),
|
|
@@ -5300,7 +5533,11 @@ function GoalPanel({ goal }) {
|
|
|
5300
5533
|
] }),
|
|
5301
5534
|
/* @__PURE__ */ jsx(Text, { dimColor: true, children: " to create one." })
|
|
5302
5535
|
] }),
|
|
5303
|
-
/* @__PURE__ */ jsx(Box, { marginTop: 1, children: /* @__PURE__ */ jsx(Text, { dimColor: true, children: "Press F9
|
|
5536
|
+
/* @__PURE__ */ jsx(Box, { marginTop: 1, children: /* @__PURE__ */ jsx(Text, { dimColor: true, children: "Press F9 to close." }) }),
|
|
5537
|
+
/* @__PURE__ */ jsx(Box, { marginTop: 1, children: coordinatorRunning ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
5538
|
+
/* @__PURE__ */ jsx(Text, { color: "green", children: "\u25CF Coordinator running " }),
|
|
5539
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "[S] Stop coordinator" })
|
|
5540
|
+
] }) : /* @__PURE__ */ jsx(Fragment, { children: /* @__PURE__ */ jsx(Text, { dimColor: true, children: "[C] Start coordinator" }) }) })
|
|
5304
5541
|
] });
|
|
5305
5542
|
}
|
|
5306
5543
|
const displayGoal = goal.refinedGoal || goal.goal;
|
|
@@ -5366,7 +5603,11 @@ function GoalPanel({ goal }) {
|
|
|
5366
5603
|
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "Last task: " }),
|
|
5367
5604
|
/* @__PURE__ */ jsx(Text, { children: goal.lastTask.length > 50 ? goal.lastTask.slice(0, 47) + "\u2026" : goal.lastTask })
|
|
5368
5605
|
] }),
|
|
5369
|
-
/* @__PURE__ */ jsx(Box, { marginTop: 1, children: /* @__PURE__ */ jsx(Text, { dimColor: true, children: "Press F9
|
|
5606
|
+
/* @__PURE__ */ jsx(Box, { marginTop: 1, children: /* @__PURE__ */ jsx(Text, { dimColor: true, children: "Press F9 to close." }) }),
|
|
5607
|
+
/* @__PURE__ */ jsx(Box, { marginTop: 1, children: coordinatorRunning ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
5608
|
+
/* @__PURE__ */ jsx(Text, { color: "green", children: "\u25CF Coordinator running " }),
|
|
5609
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "[S] Stop coordinator" })
|
|
5610
|
+
] }) : /* @__PURE__ */ jsx(Fragment, { children: /* @__PURE__ */ jsx(Text, { dimColor: true, children: "[C] Start coordinator" }) }) })
|
|
5370
5611
|
] })
|
|
5371
5612
|
] });
|
|
5372
5613
|
}
|
|
@@ -5391,6 +5632,261 @@ function renderProgressBar(progress, trend) {
|
|
|
5391
5632
|
] })
|
|
5392
5633
|
] });
|
|
5393
5634
|
}
|
|
5635
|
+
var STATUS_COLOR = {
|
|
5636
|
+
open: "gray",
|
|
5637
|
+
in_progress: "yellow",
|
|
5638
|
+
done: "green"
|
|
5639
|
+
};
|
|
5640
|
+
var STATUS_ICON = {
|
|
5641
|
+
open: "\u25CB",
|
|
5642
|
+
in_progress: "\u25D0",
|
|
5643
|
+
done: "\u2713"
|
|
5644
|
+
};
|
|
5645
|
+
function planFilePath(projectRoot, sessionId, scope) {
|
|
5646
|
+
const base = resolveWstackPaths$1({ projectRoot }).projectSessions;
|
|
5647
|
+
if (scope === "project") {
|
|
5648
|
+
return path5.join(base, "backlog.plan.json");
|
|
5649
|
+
}
|
|
5650
|
+
if (sessionId) {
|
|
5651
|
+
return path5.join(base, `${sessionId}.plan.json`);
|
|
5652
|
+
}
|
|
5653
|
+
return path5.join(base, "backlog.plan.json");
|
|
5654
|
+
}
|
|
5655
|
+
function PlanPanel({ projectRoot, sessionId, onClose: _onClose }) {
|
|
5656
|
+
const [items, setItems] = useState([]);
|
|
5657
|
+
const [title, setTitle2] = useState(void 0);
|
|
5658
|
+
const [scope, setScope] = useState("session");
|
|
5659
|
+
const [loading, setLoading] = useState(true);
|
|
5660
|
+
const [error, setError] = useState(null);
|
|
5661
|
+
async function load(scope_) {
|
|
5662
|
+
setLoading(true);
|
|
5663
|
+
setError(null);
|
|
5664
|
+
try {
|
|
5665
|
+
const filePath = planFilePath(projectRoot, sessionId, scope_);
|
|
5666
|
+
let content;
|
|
5667
|
+
try {
|
|
5668
|
+
content = await fs3.readFile(filePath, "utf-8");
|
|
5669
|
+
} catch {
|
|
5670
|
+
setItems([]);
|
|
5671
|
+
setTitle2(void 0);
|
|
5672
|
+
setScope(scope_);
|
|
5673
|
+
setLoading(false);
|
|
5674
|
+
return;
|
|
5675
|
+
}
|
|
5676
|
+
const parsed = JSON.parse(content);
|
|
5677
|
+
setItems(parsed.items ?? []);
|
|
5678
|
+
setTitle2(parsed.title);
|
|
5679
|
+
setScope(scope_);
|
|
5680
|
+
} catch (err) {
|
|
5681
|
+
setError(err instanceof Error ? err.message : String(err));
|
|
5682
|
+
} finally {
|
|
5683
|
+
setLoading(false);
|
|
5684
|
+
}
|
|
5685
|
+
}
|
|
5686
|
+
useEffect(() => {
|
|
5687
|
+
void load("session");
|
|
5688
|
+
}, []);
|
|
5689
|
+
async function handleScopeSwitch(newScope) {
|
|
5690
|
+
await load(newScope);
|
|
5691
|
+
}
|
|
5692
|
+
useInput((input) => {
|
|
5693
|
+
if (input === "s" || input === "S") {
|
|
5694
|
+
void handleScopeSwitch(scope === "session" ? "project" : "session");
|
|
5695
|
+
}
|
|
5696
|
+
});
|
|
5697
|
+
const open = items.filter((i) => i.status === "open");
|
|
5698
|
+
const inProgress = items.filter((i) => i.status === "in_progress");
|
|
5699
|
+
const done = items.filter((i) => i.status === "done");
|
|
5700
|
+
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", borderStyle: "round", borderColor: "cyan", paddingX: 1, children: [
|
|
5701
|
+
/* @__PURE__ */ jsxs(Box, { flexDirection: "row", gap: 1, marginBottom: 1, children: [
|
|
5702
|
+
/* @__PURE__ */ jsx(Text, { bold: true, color: "cyan", children: "\u{1F4CB} PLAN" }),
|
|
5703
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" }),
|
|
5704
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: scope === "session" ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: "session-scoped" }) : /* @__PURE__ */ jsx(Text, { color: "yellow", children: "project-scoped" }) }),
|
|
5705
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" }),
|
|
5706
|
+
/* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
5707
|
+
items.length,
|
|
5708
|
+
" item",
|
|
5709
|
+
items.length !== 1 ? "s" : ""
|
|
5710
|
+
] }),
|
|
5711
|
+
title ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
5712
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502" }),
|
|
5713
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: title })
|
|
5714
|
+
] }) : null,
|
|
5715
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502 F5/Esc to close" })
|
|
5716
|
+
] }),
|
|
5717
|
+
loading ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: "Loading plan..." }) : error ? /* @__PURE__ */ jsxs(Text, { color: "red", children: [
|
|
5718
|
+
"Error: ",
|
|
5719
|
+
error
|
|
5720
|
+
] }) : items.length === 0 ? /* @__PURE__ */ jsxs(Box, { flexDirection: "column", gap: 0, children: [
|
|
5721
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "No plan items yet." }),
|
|
5722
|
+
/* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
5723
|
+
"Use ",
|
|
5724
|
+
/* @__PURE__ */ jsx(Text, { color: theme.accent, children: "/plan add <title>" }),
|
|
5725
|
+
" to create one."
|
|
5726
|
+
] })
|
|
5727
|
+
] }) : /* @__PURE__ */ jsxs(Box, { flexDirection: "column", gap: 0, children: [
|
|
5728
|
+
inProgress.length > 0 && /* @__PURE__ */ jsxs(Box, { flexDirection: "column", marginBottom: 1, children: [
|
|
5729
|
+
/* @__PURE__ */ jsxs(Text, { color: "yellow", bold: true, children: [
|
|
5730
|
+
"In Progress (",
|
|
5731
|
+
inProgress.length,
|
|
5732
|
+
")"
|
|
5733
|
+
] }),
|
|
5734
|
+
inProgress.map((item) => /* @__PURE__ */ jsx(PlanRow, { item }, item.id))
|
|
5735
|
+
] }),
|
|
5736
|
+
open.length > 0 && /* @__PURE__ */ jsxs(Box, { flexDirection: "column", marginBottom: 1, children: [
|
|
5737
|
+
/* @__PURE__ */ jsxs(Text, { dimColor: true, bold: true, children: [
|
|
5738
|
+
"Open (",
|
|
5739
|
+
open.length,
|
|
5740
|
+
")"
|
|
5741
|
+
] }),
|
|
5742
|
+
open.map((item) => /* @__PURE__ */ jsx(PlanRow, { item }, item.id))
|
|
5743
|
+
] }),
|
|
5744
|
+
done.length > 0 && /* @__PURE__ */ jsxs(Box, { flexDirection: "column", children: [
|
|
5745
|
+
/* @__PURE__ */ jsxs(Text, { color: "green", bold: true, children: [
|
|
5746
|
+
"Done (",
|
|
5747
|
+
done.length,
|
|
5748
|
+
")"
|
|
5749
|
+
] }),
|
|
5750
|
+
done.map((item) => /* @__PURE__ */ jsx(PlanRow, { item }, item.id))
|
|
5751
|
+
] })
|
|
5752
|
+
] }),
|
|
5753
|
+
/* @__PURE__ */ jsx(Box, { marginTop: 1, children: /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
5754
|
+
"[",
|
|
5755
|
+
/* @__PURE__ */ jsx(Text, { color: "cyan", children: "S" }),
|
|
5756
|
+
"] Switch scope to",
|
|
5757
|
+
" ",
|
|
5758
|
+
scope === "session" ? /* @__PURE__ */ jsx(Text, { color: "yellow", children: "project" }) : /* @__PURE__ */ jsx(Text, { color: "cyan", children: "session" }),
|
|
5759
|
+
" ",
|
|
5760
|
+
"\xB7 Use ",
|
|
5761
|
+
/* @__PURE__ */ jsx(Text, { color: theme.accent, children: "/plan add" }),
|
|
5762
|
+
" to add items \xB7",
|
|
5763
|
+
" ",
|
|
5764
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "F5/Esc to close" })
|
|
5765
|
+
] }) })
|
|
5766
|
+
] });
|
|
5767
|
+
}
|
|
5768
|
+
function PlanRow({ item }) {
|
|
5769
|
+
const icon = STATUS_ICON[item.status] ?? "?";
|
|
5770
|
+
const color = STATUS_COLOR[item.status] ?? "white";
|
|
5771
|
+
return /* @__PURE__ */ jsxs(Box, { flexDirection: "row", gap: 1, children: [
|
|
5772
|
+
/* @__PURE__ */ jsx(Text, { color, children: icon }),
|
|
5773
|
+
/* @__PURE__ */ jsx(Text, { color, children: item.title }),
|
|
5774
|
+
item.details ? /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
5775
|
+
" \u2014 ",
|
|
5776
|
+
item.details.slice(0, 60),
|
|
5777
|
+
item.details.length > 60 ? "\u2026" : ""
|
|
5778
|
+
] }) : null
|
|
5779
|
+
] });
|
|
5780
|
+
}
|
|
5781
|
+
var KIND_COLOR = {
|
|
5782
|
+
goal: "cyan",
|
|
5783
|
+
task: "yellow",
|
|
5784
|
+
knowledge: "green",
|
|
5785
|
+
consensus: "magenta",
|
|
5786
|
+
deadlock: "red"
|
|
5787
|
+
};
|
|
5788
|
+
function fmtElapsed4(at, nowTick) {
|
|
5789
|
+
const s2 = Math.floor((nowTick - at) / 1e3);
|
|
5790
|
+
if (s2 < 60) return `${s2}s ago`;
|
|
5791
|
+
const m = Math.floor(s2 / 60);
|
|
5792
|
+
if (m < 60) return `${m}m ago`;
|
|
5793
|
+
return `${Math.floor(m / 60)}h ago`;
|
|
5794
|
+
}
|
|
5795
|
+
function GoalRow({
|
|
5796
|
+
goal
|
|
5797
|
+
}) {
|
|
5798
|
+
const statusColor = {
|
|
5799
|
+
active: "green",
|
|
5800
|
+
paused: "yellow",
|
|
5801
|
+
completed: "gray",
|
|
5802
|
+
failed: "red"
|
|
5803
|
+
};
|
|
5804
|
+
const color = statusColor[goal.status] ?? "gray";
|
|
5805
|
+
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", paddingLeft: 2, marginBottom: 1, children: [
|
|
5806
|
+
/* @__PURE__ */ jsx(Box, { children: /* @__PURE__ */ jsxs(Text, { color, bold: true, children: [
|
|
5807
|
+
goal.status === "active" ? "\u25B6" : goal.status === "paused" ? "\u23F8" : goal.status === "completed" ? "\u2713" : "\u2717",
|
|
5808
|
+
" ",
|
|
5809
|
+
goal.title || "(unnamed goal)"
|
|
5810
|
+
] }) }),
|
|
5811
|
+
goal.tasks.length > 0 && /* @__PURE__ */ jsx(Box, { flexDirection: "column", paddingLeft: 2, children: goal.tasks.map((task) => {
|
|
5812
|
+
const taskColor = {
|
|
5813
|
+
pending: "gray",
|
|
5814
|
+
running: "yellow",
|
|
5815
|
+
done: "green",
|
|
5816
|
+
failed: "red"
|
|
5817
|
+
};
|
|
5818
|
+
return /* @__PURE__ */ jsx(Box, { children: /* @__PURE__ */ jsxs(Text, { color: taskColor[task.status] ?? "gray", children: [
|
|
5819
|
+
task.status === "pending" ? "\u25CB" : task.status === "running" ? "\u25B6" : task.status === "done" ? "\u2713" : "\u2717",
|
|
5820
|
+
" ",
|
|
5821
|
+
task.title,
|
|
5822
|
+
task.assignedTo ? /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
5823
|
+
" \u2192 ",
|
|
5824
|
+
task.assignedTo
|
|
5825
|
+
] }) : null
|
|
5826
|
+
] }) }, task.id);
|
|
5827
|
+
}) }),
|
|
5828
|
+
goal.participants.length > 0 && /* @__PURE__ */ jsx(Box, { paddingLeft: 2, children: /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
5829
|
+
"participants: ",
|
|
5830
|
+
goal.participants.join(", ")
|
|
5831
|
+
] }) })
|
|
5832
|
+
] }, goal.id);
|
|
5833
|
+
}
|
|
5834
|
+
function CoordinatorPanel({
|
|
5835
|
+
coordinator,
|
|
5836
|
+
nowTick,
|
|
5837
|
+
onClose
|
|
5838
|
+
}) {
|
|
5839
|
+
const handleInput = useCallback(
|
|
5840
|
+
(input, _key) => {
|
|
5841
|
+
if (input === "q" || input === "Q" || input === "\x1B") {
|
|
5842
|
+
onClose();
|
|
5843
|
+
}
|
|
5844
|
+
},
|
|
5845
|
+
[onClose]
|
|
5846
|
+
);
|
|
5847
|
+
useInput(handleInput);
|
|
5848
|
+
const { goals, timeline, knowledgeCount, healthy } = coordinator;
|
|
5849
|
+
return /* @__PURE__ */ jsxs(
|
|
5850
|
+
Box,
|
|
5851
|
+
{
|
|
5852
|
+
flexDirection: "column",
|
|
5853
|
+
borderStyle: "round",
|
|
5854
|
+
borderColor: "cyan",
|
|
5855
|
+
paddingX: 1,
|
|
5856
|
+
height: Math.min(30, Math.max(10, goals.length * 4 + timeline.length + 8)),
|
|
5857
|
+
width: 80,
|
|
5858
|
+
children: [
|
|
5859
|
+
/* @__PURE__ */ jsxs(Box, { borderStyle: "bold", borderColor: "cyan", paddingX: 1, marginBottom: 1, children: [
|
|
5860
|
+
/* @__PURE__ */ jsx(Text, { bold: true, color: "cyan", children: "\u{1F916} AutonomousCoordinator" }),
|
|
5861
|
+
/* @__PURE__ */ jsx(Box, { flexGrow: 1 }),
|
|
5862
|
+
/* @__PURE__ */ jsx(Text, { dimColor: !healthy, color: healthy ? "green" : "red", children: healthy ? "\u25CF connected" : "\u25CB disconnected" }),
|
|
5863
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: " \xB7 q/esc to close" })
|
|
5864
|
+
] }),
|
|
5865
|
+
goals.length > 0 && /* @__PURE__ */ jsxs(Box, { flexDirection: "column", marginBottom: 1, children: [
|
|
5866
|
+
/* @__PURE__ */ jsxs(Text, { bold: true, children: [
|
|
5867
|
+
"Goals (",
|
|
5868
|
+
goals.length,
|
|
5869
|
+
")"
|
|
5870
|
+
] }),
|
|
5871
|
+
goals.map((goal) => /* @__PURE__ */ jsx(GoalRow, { goal }, goal.id))
|
|
5872
|
+
] }),
|
|
5873
|
+
/* @__PURE__ */ jsxs(Box, { marginBottom: 1, children: [
|
|
5874
|
+
/* @__PURE__ */ jsx(Text, { bold: true, children: "Knowledge " }),
|
|
5875
|
+
/* @__PURE__ */ jsx(Text, { color: "green", children: knowledgeCount }),
|
|
5876
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: " shared facts" })
|
|
5877
|
+
] }),
|
|
5878
|
+
/* @__PURE__ */ jsxs(Box, { flexDirection: "column", flexGrow: 1, children: [
|
|
5879
|
+
/* @__PURE__ */ jsx(Text, { bold: true, children: "Activity" }),
|
|
5880
|
+
timeline.length === 0 ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: " No activity yet" }) : timeline.slice(0, 10).map((entry, i) => /* @__PURE__ */ jsxs(Box, { alignItems: "flex-start", children: [
|
|
5881
|
+
/* @__PURE__ */ jsx(Text, { color: KIND_COLOR[entry.kind] ?? "gray", dimColor: i > 2, children: entry.icon }),
|
|
5882
|
+
/* @__PURE__ */ jsx(Box, { flexGrow: 1, marginLeft: 1, children: /* @__PURE__ */ jsx(Text, { dimColor: i > 2, children: entry.text }) }),
|
|
5883
|
+
/* @__PURE__ */ jsx(Box, { marginLeft: 1, children: /* @__PURE__ */ jsx(Text, { dimColor: true, children: fmtElapsed4(entry.at, nowTick) }) })
|
|
5884
|
+
] }, i))
|
|
5885
|
+
] })
|
|
5886
|
+
]
|
|
5887
|
+
}
|
|
5888
|
+
);
|
|
5889
|
+
}
|
|
5394
5890
|
function ResumePicker({
|
|
5395
5891
|
sessions,
|
|
5396
5892
|
selected,
|
|
@@ -5498,7 +5994,7 @@ function SessionsPanel({
|
|
|
5498
5994
|
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", borderStyle: "round", borderColor: "cyan", paddingX: 1, flexShrink: 0, children: [
|
|
5499
5995
|
/* @__PURE__ */ jsxs(Box, { flexDirection: "row", gap: 1, children: [
|
|
5500
5996
|
/* @__PURE__ */ jsx(Text, { bold: true, color: "cyan", children: "\u29C9 Sessions" }),
|
|
5501
|
-
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "\xB7 F10
|
|
5997
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "\xB7 F10 to close" }),
|
|
5502
5998
|
busy && /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\xB7 loading\u2026" })
|
|
5503
5999
|
] }),
|
|
5504
6000
|
resumeConfirm ? /* @__PURE__ */ jsxs(Box, { marginY: 1, borderStyle: "single", borderColor: "yellow", paddingX: 1, children: [
|
|
@@ -5594,6 +6090,14 @@ var MAX_ITERATIONS_PRESETS = [100, 200, 500, 1e3, 0];
|
|
|
5594
6090
|
var AUTO_PROCEED_MAX_PRESETS = [10, 25, 50, 100, 250, 0];
|
|
5595
6091
|
var ENHANCE_DELAY_PRESETS = [3e4, 45e3, 6e4, 9e4, 12e4];
|
|
5596
6092
|
var ENHANCE_LANGUAGES = ["original", "english"];
|
|
6093
|
+
var TOKEN_SAVING_TIERS = ["off", "minimal", "light", "medium", "aggressive"];
|
|
6094
|
+
var TOKEN_SAVING_TIER_DESCS = {
|
|
6095
|
+
off: "All tools enabled (full prompt)",
|
|
6096
|
+
minimal: "~3\u20134k tokens \u2014 core tools only",
|
|
6097
|
+
light: "~2\u20133k tokens \u2014 core + patterns",
|
|
6098
|
+
medium: "~1.5\u20132k tokens \u2014 most tools enabled",
|
|
6099
|
+
aggressive: "~4\u20135k tokens \u2014 trimmed prompt"
|
|
6100
|
+
};
|
|
5597
6101
|
function formatSettingsDelay(ms) {
|
|
5598
6102
|
if (ms === 0) return "disabled";
|
|
5599
6103
|
if (ms >= 6e4) return `${Math.round(ms / 6e4)}m`;
|
|
@@ -5611,7 +6115,7 @@ var MODE_DESC = {
|
|
|
5611
6115
|
suggest: "Shows next-step suggestions after each turn",
|
|
5612
6116
|
auto: "Self-driving \u2014 agent continues automatically"
|
|
5613
6117
|
};
|
|
5614
|
-
var SETTINGS_FIELD_COUNT =
|
|
6118
|
+
var SETTINGS_FIELD_COUNT = 27;
|
|
5615
6119
|
var CONFIG_SCOPES = ["global", "project"];
|
|
5616
6120
|
function SettingsPicker({
|
|
5617
6121
|
field,
|
|
@@ -5628,7 +6132,8 @@ function SettingsPicker({
|
|
|
5628
6132
|
featureMemory,
|
|
5629
6133
|
featureSkills,
|
|
5630
6134
|
featureModelsRegistry,
|
|
5631
|
-
|
|
6135
|
+
tokenSavingTier,
|
|
6136
|
+
allowOutsideProjectRoot,
|
|
5632
6137
|
contextAutoCompact,
|
|
5633
6138
|
contextStrategy,
|
|
5634
6139
|
logLevel,
|
|
@@ -5714,8 +6219,13 @@ function SettingsPicker({
|
|
|
5714
6219
|
},
|
|
5715
6220
|
{
|
|
5716
6221
|
label: "Token-saving mode",
|
|
5717
|
-
value:
|
|
5718
|
-
detail:
|
|
6222
|
+
value: tokenSavingTier,
|
|
6223
|
+
detail: TOKEN_SAVING_TIER_DESCS[tokenSavingTier]
|
|
6224
|
+
},
|
|
6225
|
+
{
|
|
6226
|
+
label: "Allow outside project",
|
|
6227
|
+
value: boolVal(allowOutsideProjectRoot),
|
|
6228
|
+
detail: "Allow tools to access paths outside project root"
|
|
5719
6229
|
},
|
|
5720
6230
|
// ── Context ──
|
|
5721
6231
|
{ section: "Context" },
|
|
@@ -5822,7 +6332,7 @@ function SettingsPicker({
|
|
|
5822
6332
|
};
|
|
5823
6333
|
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", borderStyle: "round", borderColor: "yellow", paddingX: 1, children: [
|
|
5824
6334
|
/* @__PURE__ */ jsx(Text, { color: "cyan", bold: true, children: "\u2501\u2501 Settings \u2501\u2501" }),
|
|
5825
|
-
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2191/\u2193 field \xB7 \u2190/\u2192 change (instant
|
|
6335
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2191/\u2193 field \xB7 \u2190/\u2192 change (instant apply) \xB7 F5 to close" }),
|
|
5826
6336
|
hasAbove ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: ` \u2191 ${windowStart} field${windowStart === 1 ? "" : "s"} above` }) : null,
|
|
5827
6337
|
rows.map((row, i) => {
|
|
5828
6338
|
const fieldAtRow = fieldRowIndex.indexOf(i);
|
|
@@ -6072,7 +6582,7 @@ function TodosMonitor({ todos }) {
|
|
|
6072
6582
|
done
|
|
6073
6583
|
] })
|
|
6074
6584
|
] }) : null,
|
|
6075
|
-
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502 F6
|
|
6585
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502 F6 to close" })
|
|
6076
6586
|
] }),
|
|
6077
6587
|
todos.length === 0 ? /* @__PURE__ */ jsx(Box, { marginY: 1, children: /* @__PURE__ */ jsx(Text, { dimColor: true, children: "No todos. The agent will create them as it plans work." }) }) : twoCols ? (
|
|
6078
6588
|
/* Two-column layout: split the list in half, render side-by-side.
|
|
@@ -6087,7 +6597,7 @@ function TodosMonitor({ todos }) {
|
|
|
6087
6597
|
)
|
|
6088
6598
|
] });
|
|
6089
6599
|
}
|
|
6090
|
-
var
|
|
6600
|
+
var fmtElapsed5 = (ms) => {
|
|
6091
6601
|
const s2 = Math.floor(ms / 1e3);
|
|
6092
6602
|
const m = Math.floor(s2 / 60);
|
|
6093
6603
|
const h = Math.floor(m / 60);
|
|
@@ -6114,7 +6624,7 @@ function WorktreeMonitor({
|
|
|
6114
6624
|
onClose
|
|
6115
6625
|
}) {
|
|
6116
6626
|
useInput((input, key) => {
|
|
6117
|
-
if (key.
|
|
6627
|
+
if (key.ctrl && input === "w") onClose();
|
|
6118
6628
|
});
|
|
6119
6629
|
const TERMINAL_TTL_MS = 5 * 6e4;
|
|
6120
6630
|
const list = Object.values(worktrees);
|
|
@@ -6151,12 +6661,12 @@ function WorktreeMonitor({
|
|
|
6151
6661
|
failed
|
|
6152
6662
|
] })
|
|
6153
6663
|
] }) : null,
|
|
6154
|
-
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502 Ctrl+T / F4
|
|
6664
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2502 Ctrl+T / F4 to close" })
|
|
6155
6665
|
] }),
|
|
6156
6666
|
recent.length === 0 ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: "No worktrees. They appear when AutoPhase runs with isolation on." }) : recent.map((w) => {
|
|
6157
6667
|
const s2 = fmt(w.status);
|
|
6158
6668
|
const short = w.branch.replace(/^wstack\/ap\//, "");
|
|
6159
|
-
const elapsed = w.allocatedAt ?
|
|
6669
|
+
const elapsed = w.allocatedAt ? fmtElapsed5(nowTick - w.allocatedAt) : "\u2014";
|
|
6160
6670
|
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", marginTop: 1, children: [
|
|
6161
6671
|
/* @__PURE__ */ jsxs(Box, { flexDirection: "row", gap: 1, children: [
|
|
6162
6672
|
/* @__PURE__ */ jsx(Text, { color: s2.color, bold: true, children: s2.icon }),
|
|
@@ -6201,12 +6711,12 @@ function WorktreeMonitor({
|
|
|
6201
6711
|
] }, w.branch);
|
|
6202
6712
|
}),
|
|
6203
6713
|
/* @__PURE__ */ jsxs(Box, { marginTop: 1, children: [
|
|
6204
|
-
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "
|
|
6714
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "Ctrl+T to close \xB7 merge conflicts with /worktree merge <branch>" }),
|
|
6205
6715
|
staleTerminal > 0 ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: ` \xB7 ${staleTerminal} terminal pruned` }) : null
|
|
6206
6716
|
] })
|
|
6207
6717
|
] });
|
|
6208
6718
|
}
|
|
6209
|
-
var
|
|
6719
|
+
var fmtElapsed6 = (ms) => {
|
|
6210
6720
|
const s2 = Math.floor(ms / 1e3);
|
|
6211
6721
|
const m = Math.floor(s2 / 60);
|
|
6212
6722
|
const h = Math.floor(m / 60);
|
|
@@ -6272,7 +6782,7 @@ function WorktreePanel({
|
|
|
6272
6782
|
list.map((w) => {
|
|
6273
6783
|
const s2 = st(w.status);
|
|
6274
6784
|
const conflict = w.status === "needs-review";
|
|
6275
|
-
const elapsed = w.allocatedAt ?
|
|
6785
|
+
const elapsed = w.allocatedAt ? fmtElapsed6(nowTick - w.allocatedAt) : "";
|
|
6276
6786
|
return /* @__PURE__ */ jsxs(Box, { flexDirection: "row", gap: 1, children: [
|
|
6277
6787
|
/* @__PURE__ */ jsx(Text, { color: s2.color, children: s2.icon }),
|
|
6278
6788
|
/* @__PURE__ */ jsx(Text, { children: w.branch.replace(/^wstack\/ap\//, "").slice(0, 18).padEnd(18) }),
|
|
@@ -6327,10 +6837,10 @@ async function loadIndex(root) {
|
|
|
6327
6837
|
async function walk(root, rel, depth, out) {
|
|
6328
6838
|
if (out.length >= MAX_FILES_INDEXED) return;
|
|
6329
6839
|
if (depth > MAX_DEPTH) return;
|
|
6330
|
-
const dir = rel ?
|
|
6840
|
+
const dir = rel ? path5.join(root, rel) : root;
|
|
6331
6841
|
let entries;
|
|
6332
6842
|
try {
|
|
6333
|
-
entries = await
|
|
6843
|
+
entries = await fs3.readdir(dir, { withFileTypes: true });
|
|
6334
6844
|
} catch {
|
|
6335
6845
|
return;
|
|
6336
6846
|
}
|
|
@@ -6817,6 +7327,21 @@ function handleCollabDone(event, dispatch, stateRef) {
|
|
|
6817
7327
|
verdict: payload.report.overallVerdict ?? "needs_revision"
|
|
6818
7328
|
});
|
|
6819
7329
|
}
|
|
7330
|
+
function useAutonomousCoordinator(subscribeCoordinatorEvents, dispatch) {
|
|
7331
|
+
const dispatchRef = useRef(dispatch);
|
|
7332
|
+
dispatchRef.current = dispatch;
|
|
7333
|
+
const handler = useCallback((event) => {
|
|
7334
|
+
dispatchRef.current({
|
|
7335
|
+
type: "coordinatorEvent",
|
|
7336
|
+
event
|
|
7337
|
+
});
|
|
7338
|
+
}, []);
|
|
7339
|
+
useEffect(() => {
|
|
7340
|
+
if (!subscribeCoordinatorEvents) return;
|
|
7341
|
+
const unsubscribe = subscribeCoordinatorEvents(handler);
|
|
7342
|
+
return unsubscribe;
|
|
7343
|
+
}, [subscribeCoordinatorEvents, handler]);
|
|
7344
|
+
}
|
|
6820
7345
|
function useStatuslineState(opts) {
|
|
6821
7346
|
const [liveModel, setLiveModel] = useState(opts.model);
|
|
6822
7347
|
const [liveProvider, setLiveProvider] = useState(opts.provider ?? "agent");
|
|
@@ -7568,11 +8093,17 @@ function reducer(state, action) {
|
|
|
7568
8093
|
const banner = state.entries.find((e) => e.kind === "banner");
|
|
7569
8094
|
return {
|
|
7570
8095
|
...state,
|
|
7571
|
-
entries: banner ? [banner] :
|
|
8096
|
+
entries: banner ? [banner] : [],
|
|
7572
8097
|
queue: [],
|
|
7573
8098
|
nextQueueId: 1,
|
|
7574
8099
|
scrollOffset: 0,
|
|
7575
8100
|
pendingNewLines: 0,
|
|
8101
|
+
// Bump the generation so <Static> remounts — without this, Ink's
|
|
8102
|
+
// already-written index exceeds the new (shorter) array and the
|
|
8103
|
+
// committed entries stay on screen even though `state.entries` no
|
|
8104
|
+
// longer references them. /clear would otherwise appear to do
|
|
8105
|
+
// nothing to the visible chat history.
|
|
8106
|
+
historyGen: state.historyGen + 1,
|
|
7576
8107
|
// Reset fleet state on /clear so old subagent entries don't
|
|
7577
8108
|
// cause the LiveActivityStrip to render stale spacers, and
|
|
7578
8109
|
// the fleet cost/tokens chips show zero.
|
|
@@ -7913,7 +8444,8 @@ function reducer(state, action) {
|
|
|
7913
8444
|
featureMemory: action.featureMemory,
|
|
7914
8445
|
featureSkills: action.featureSkills,
|
|
7915
8446
|
featureModelsRegistry: action.featureModelsRegistry,
|
|
7916
|
-
|
|
8447
|
+
tokenSavingTier: action.tokenSavingTier,
|
|
8448
|
+
allowOutsideProjectRoot: action.allowOutsideProjectRoot,
|
|
7917
8449
|
contextAutoCompact: action.contextAutoCompact,
|
|
7918
8450
|
contextStrategy: action.contextStrategy,
|
|
7919
8451
|
logLevel: action.logLevel,
|
|
@@ -7948,6 +8480,7 @@ function reducer(state, action) {
|
|
|
7948
8480
|
case "settingsValueChange": {
|
|
7949
8481
|
const sp = state.settingsPicker;
|
|
7950
8482
|
const f = sp.field;
|
|
8483
|
+
const bootHint = "\u21BB Takes effect next session";
|
|
7951
8484
|
if (f === 0) {
|
|
7952
8485
|
const i = SETTINGS_MODES.indexOf(sp.mode);
|
|
7953
8486
|
const base = i < 0 ? 0 : i;
|
|
@@ -7966,59 +8499,65 @@ function reducer(state, action) {
|
|
|
7966
8499
|
if (f === 5) return { ...state, settingsPicker: { ...sp, chime: !sp.chime, hint: void 0 } };
|
|
7967
8500
|
if (f === 6) return { ...state, settingsPicker: { ...sp, confirmExit: !sp.confirmExit, hint: void 0 } };
|
|
7968
8501
|
if (f === 7) return { ...state, settingsPicker: { ...sp, nextPrediction: !sp.nextPrediction, hint: void 0 } };
|
|
7969
|
-
if (f === 8) return { ...state, settingsPicker: { ...sp, featureMcp: !sp.featureMcp, hint:
|
|
7970
|
-
if (f === 9) return { ...state, settingsPicker: { ...sp, featurePlugins: !sp.featurePlugins, hint:
|
|
7971
|
-
if (f === 10) return { ...state, settingsPicker: { ...sp, featureMemory: !sp.featureMemory, hint:
|
|
7972
|
-
if (f === 11) return { ...state, settingsPicker: { ...sp, featureSkills: !sp.featureSkills, hint:
|
|
7973
|
-
if (f === 12) return { ...state, settingsPicker: { ...sp, featureModelsRegistry: !sp.featureModelsRegistry, hint:
|
|
7974
|
-
if (f === 13)
|
|
7975
|
-
|
|
7976
|
-
|
|
8502
|
+
if (f === 8) return { ...state, settingsPicker: { ...sp, featureMcp: !sp.featureMcp, hint: bootHint } };
|
|
8503
|
+
if (f === 9) return { ...state, settingsPicker: { ...sp, featurePlugins: !sp.featurePlugins, hint: bootHint } };
|
|
8504
|
+
if (f === 10) return { ...state, settingsPicker: { ...sp, featureMemory: !sp.featureMemory, hint: bootHint } };
|
|
8505
|
+
if (f === 11) return { ...state, settingsPicker: { ...sp, featureSkills: !sp.featureSkills, hint: bootHint } };
|
|
8506
|
+
if (f === 12) return { ...state, settingsPicker: { ...sp, featureModelsRegistry: !sp.featureModelsRegistry, hint: bootHint } };
|
|
8507
|
+
if (f === 13) {
|
|
8508
|
+
const i = TOKEN_SAVING_TIERS.indexOf(sp.tokenSavingTier);
|
|
8509
|
+
const base = i < 0 ? 0 : i;
|
|
8510
|
+
const next = (base + action.delta + TOKEN_SAVING_TIERS.length) % TOKEN_SAVING_TIERS.length;
|
|
8511
|
+
return { ...state, settingsPicker: { ...sp, tokenSavingTier: TOKEN_SAVING_TIERS[next] ?? "off", hint: bootHint } };
|
|
8512
|
+
}
|
|
8513
|
+
if (f === 14) return { ...state, settingsPicker: { ...sp, allowOutsideProjectRoot: !sp.allowOutsideProjectRoot, hint: void 0 } };
|
|
8514
|
+
if (f === 15) return { ...state, settingsPicker: { ...sp, contextAutoCompact: !sp.contextAutoCompact, hint: void 0 } };
|
|
8515
|
+
if (f === 16) {
|
|
7977
8516
|
const i = COMPACTOR_STRATEGIES.indexOf(sp.contextStrategy);
|
|
7978
8517
|
const base = i < 0 ? 0 : i;
|
|
7979
8518
|
const next = (base + action.delta + COMPACTOR_STRATEGIES.length) % COMPACTOR_STRATEGIES.length;
|
|
7980
|
-
return { ...state, settingsPicker: { ...sp, contextStrategy: expectDefined$1(COMPACTOR_STRATEGIES[next]), hint:
|
|
8519
|
+
return { ...state, settingsPicker: { ...sp, contextStrategy: expectDefined$1(COMPACTOR_STRATEGIES[next]), hint: bootHint } };
|
|
7981
8520
|
}
|
|
7982
|
-
if (f ===
|
|
8521
|
+
if (f === 17) {
|
|
7983
8522
|
const i = LOG_LEVELS.indexOf(sp.logLevel);
|
|
7984
8523
|
const base = i < 0 ? 0 : i;
|
|
7985
8524
|
const next = (base + action.delta + LOG_LEVELS.length) % LOG_LEVELS.length;
|
|
7986
8525
|
return { ...state, settingsPicker: { ...sp, logLevel: expectDefined$1(LOG_LEVELS[next]), hint: void 0 } };
|
|
7987
8526
|
}
|
|
7988
|
-
if (f ===
|
|
8527
|
+
if (f === 18) {
|
|
7989
8528
|
const i = AUDIT_LEVELS.indexOf(sp.auditLevel);
|
|
7990
8529
|
const base = i < 0 ? 0 : i;
|
|
7991
8530
|
const next = (base + action.delta + AUDIT_LEVELS.length) % AUDIT_LEVELS.length;
|
|
7992
8531
|
return { ...state, settingsPicker: { ...sp, auditLevel: expectDefined$1(AUDIT_LEVELS[next]), hint: void 0 } };
|
|
7993
8532
|
}
|
|
7994
|
-
if (f ===
|
|
7995
|
-
if (f ===
|
|
8533
|
+
if (f === 19) return { ...state, settingsPicker: { ...sp, indexOnStart: !sp.indexOnStart, hint: bootHint } };
|
|
8534
|
+
if (f === 20) {
|
|
7996
8535
|
const j = MAX_ITERATIONS_PRESETS.indexOf(sp.maxIterations);
|
|
7997
8536
|
const base = j < 0 ? 0 : j;
|
|
7998
8537
|
const next = (base + action.delta + MAX_ITERATIONS_PRESETS.length) % MAX_ITERATIONS_PRESETS.length;
|
|
7999
8538
|
return { ...state, settingsPicker: { ...sp, maxIterations: expectDefined$1(MAX_ITERATIONS_PRESETS[next]), hint: void 0 } };
|
|
8000
8539
|
}
|
|
8001
|
-
if (f ===
|
|
8540
|
+
if (f === 21) {
|
|
8002
8541
|
const aj = AUTO_PROCEED_MAX_PRESETS.indexOf(sp.autoProceedMaxIterations);
|
|
8003
8542
|
const abase = aj < 0 ? 0 : aj;
|
|
8004
8543
|
const anext = (abase + action.delta + AUTO_PROCEED_MAX_PRESETS.length) % AUTO_PROCEED_MAX_PRESETS.length;
|
|
8005
8544
|
return { ...state, settingsPicker: { ...sp, autoProceedMaxIterations: expectDefined$1(AUTO_PROCEED_MAX_PRESETS[anext]), hint: void 0 } };
|
|
8006
8545
|
}
|
|
8007
|
-
if (f ===
|
|
8546
|
+
if (f === 22) {
|
|
8008
8547
|
const ej = ENHANCE_DELAY_PRESETS.indexOf(sp.enhanceDelayMs);
|
|
8009
8548
|
const ebase = ej < 0 ? 0 : ej;
|
|
8010
8549
|
const enext = (ebase + action.delta + ENHANCE_DELAY_PRESETS.length) % ENHANCE_DELAY_PRESETS.length;
|
|
8011
8550
|
return { ...state, settingsPicker: { ...sp, enhanceDelayMs: expectDefined$1(ENHANCE_DELAY_PRESETS[enext]), hint: void 0 } };
|
|
8012
8551
|
}
|
|
8013
|
-
if (f ===
|
|
8014
|
-
if (f ===
|
|
8552
|
+
if (f === 23) return { ...state, settingsPicker: { ...sp, enhanceEnabled: !sp.enhanceEnabled, hint: void 0 } };
|
|
8553
|
+
if (f === 24) {
|
|
8015
8554
|
const i = ENHANCE_LANGUAGES.indexOf(sp.enhanceLanguage);
|
|
8016
8555
|
const base = i < 0 ? 0 : i;
|
|
8017
8556
|
const next = (base + action.delta + ENHANCE_LANGUAGES.length) % ENHANCE_LANGUAGES.length;
|
|
8018
8557
|
return { ...state, settingsPicker: { ...sp, enhanceLanguage: expectDefined$1(ENHANCE_LANGUAGES[next]), hint: void 0 } };
|
|
8019
8558
|
}
|
|
8020
|
-
if (f ===
|
|
8021
|
-
if (f ===
|
|
8559
|
+
if (f === 25) return { ...state, settingsPicker: { ...sp, debugStream: !sp.debugStream, hint: void 0 } };
|
|
8560
|
+
if (f === 26) {
|
|
8022
8561
|
const i = CONFIG_SCOPES.indexOf(sp.configScope);
|
|
8023
8562
|
const base = i < 0 ? 0 : i;
|
|
8024
8563
|
const next = (base + action.delta + CONFIG_SCOPES.length) % CONFIG_SCOPES.length;
|
|
@@ -8429,6 +8968,10 @@ function reducer(state, action) {
|
|
|
8429
8968
|
const opening = !state.processListOpen;
|
|
8430
8969
|
return opening ? { ...state, processListOpen: true, monitorOpen: false, agentsMonitorOpen: false, helpOpen: false, todosMonitorOpen: false, queuePanelOpen: false, goalPanelOpen: false } : { ...state, processListOpen: false };
|
|
8431
8970
|
}
|
|
8971
|
+
case "togglePlanPanel": {
|
|
8972
|
+
const opening = !state.planPanelOpen;
|
|
8973
|
+
return opening ? { ...state, planPanelOpen: true, monitorOpen: false, agentsMonitorOpen: false, helpOpen: false, todosMonitorOpen: false, queuePanelOpen: false, processListOpen: false, goalPanelOpen: false } : { ...state, planPanelOpen: false };
|
|
8974
|
+
}
|
|
8432
8975
|
case "toggleGoalPanel": {
|
|
8433
8976
|
const opening = !state.goalPanelOpen;
|
|
8434
8977
|
return opening ? { ...state, goalPanelOpen: true, monitorOpen: false, agentsMonitorOpen: false, helpOpen: false, todosMonitorOpen: false, queuePanelOpen: false, processListOpen: false } : { ...state, goalPanelOpen: false };
|
|
@@ -8749,9 +9292,10 @@ function reducer(state, action) {
|
|
|
8749
9292
|
return { ...state, sessionsPanelOpen: !state.sessionsPanelOpen };
|
|
8750
9293
|
}
|
|
8751
9294
|
case "sessionsPanelSet": {
|
|
9295
|
+
const sessions = Array.isArray(action.sessions) ? action.sessions : [];
|
|
8752
9296
|
return {
|
|
8753
9297
|
...state,
|
|
8754
|
-
sessionsPanel: { sessions
|
|
9298
|
+
sessionsPanel: { sessions, busy: false, selected: sessions.length > 0 ? 0 : -1 }
|
|
8755
9299
|
};
|
|
8756
9300
|
}
|
|
8757
9301
|
case "sessionsPanelMove": {
|
|
@@ -8786,6 +9330,81 @@ function reducer(state, action) {
|
|
|
8786
9330
|
if (state.countdown === null) return state;
|
|
8787
9331
|
return { ...state, countdown: null };
|
|
8788
9332
|
}
|
|
9333
|
+
// --- AutonomousCoordinator ---
|
|
9334
|
+
case "coordinatorEvent": {
|
|
9335
|
+
const { event } = action;
|
|
9336
|
+
const now = Date.now();
|
|
9337
|
+
let kind;
|
|
9338
|
+
let icon;
|
|
9339
|
+
switch (event.type) {
|
|
9340
|
+
case "goal:added":
|
|
9341
|
+
kind = "goal";
|
|
9342
|
+
icon = "\u{1F3AF}";
|
|
9343
|
+
break;
|
|
9344
|
+
case "goal:completed":
|
|
9345
|
+
kind = "goal";
|
|
9346
|
+
icon = "\u2705";
|
|
9347
|
+
break;
|
|
9348
|
+
case "goal:failed":
|
|
9349
|
+
kind = "goal";
|
|
9350
|
+
icon = "\u274C";
|
|
9351
|
+
break;
|
|
9352
|
+
case "task:ready":
|
|
9353
|
+
kind = "task";
|
|
9354
|
+
icon = "\u26A1";
|
|
9355
|
+
break;
|
|
9356
|
+
case "task:completed":
|
|
9357
|
+
kind = "task";
|
|
9358
|
+
icon = "\u2713";
|
|
9359
|
+
break;
|
|
9360
|
+
case "knowledge:added":
|
|
9361
|
+
kind = "knowledge";
|
|
9362
|
+
icon = "\u{1F4A1}";
|
|
9363
|
+
break;
|
|
9364
|
+
case "consensus:reached":
|
|
9365
|
+
kind = "consensus";
|
|
9366
|
+
icon = "\u{1F91D}";
|
|
9367
|
+
break;
|
|
9368
|
+
case "deadlock:detected":
|
|
9369
|
+
kind = "deadlock";
|
|
9370
|
+
icon = "\u26A0\uFE0F";
|
|
9371
|
+
break;
|
|
9372
|
+
default:
|
|
9373
|
+
kind = "goal";
|
|
9374
|
+
icon = "\u2022";
|
|
9375
|
+
break;
|
|
9376
|
+
}
|
|
9377
|
+
const timelineEntry = {
|
|
9378
|
+
at: now,
|
|
9379
|
+
kind,
|
|
9380
|
+
icon,
|
|
9381
|
+
text: event.text ?? event.type
|
|
9382
|
+
};
|
|
9383
|
+
return {
|
|
9384
|
+
...state,
|
|
9385
|
+
coordinator: {
|
|
9386
|
+
...state.coordinator,
|
|
9387
|
+
healthy: true,
|
|
9388
|
+
knowledgeCount: event.type === "knowledge:added" ? state.coordinator.knowledgeCount + 1 : state.coordinator.knowledgeCount,
|
|
9389
|
+
timeline: [timelineEntry, ...state.coordinator.timeline].slice(0, 50)
|
|
9390
|
+
}
|
|
9391
|
+
};
|
|
9392
|
+
}
|
|
9393
|
+
case "toggleCoordinatorMonitor": {
|
|
9394
|
+
const opening = !state.coordinator.monitorOpen;
|
|
9395
|
+
return opening ? {
|
|
9396
|
+
...state,
|
|
9397
|
+
coordinator: { ...state.coordinator, monitorOpen: true },
|
|
9398
|
+
// Close other monitors when opening coordinator
|
|
9399
|
+
monitorOpen: false,
|
|
9400
|
+
agentsMonitorOpen: false,
|
|
9401
|
+
helpOpen: false,
|
|
9402
|
+
todosMonitorOpen: false,
|
|
9403
|
+
queuePanelOpen: false,
|
|
9404
|
+
processListOpen: false,
|
|
9405
|
+
goalPanelOpen: false
|
|
9406
|
+
} : { ...state, coordinator: { ...state.coordinator, monitorOpen: false } };
|
|
9407
|
+
}
|
|
8789
9408
|
}
|
|
8790
9409
|
}
|
|
8791
9410
|
var INPUT_PROMPT = "\u203A ";
|
|
@@ -8840,6 +9459,7 @@ function App({
|
|
|
8840
9459
|
yolo = false,
|
|
8841
9460
|
chime = false,
|
|
8842
9461
|
confirmExit = true,
|
|
9462
|
+
titleController,
|
|
8843
9463
|
mouse = false,
|
|
8844
9464
|
enhanceEnabled = true,
|
|
8845
9465
|
enhanceController,
|
|
@@ -8895,7 +9515,12 @@ function App({
|
|
|
8895
9515
|
requestExit,
|
|
8896
9516
|
getLiveSessions,
|
|
8897
9517
|
onSwitchToSession,
|
|
8898
|
-
initialAgentsMonitorOpen
|
|
9518
|
+
initialAgentsMonitorOpen,
|
|
9519
|
+
subscribeCoordinatorEvents,
|
|
9520
|
+
onCoordinatorStart,
|
|
9521
|
+
onCoordinatorStop,
|
|
9522
|
+
coordinatorRunning = false,
|
|
9523
|
+
clientId
|
|
8899
9524
|
}) {
|
|
8900
9525
|
const { exit } = useApp();
|
|
8901
9526
|
const { stdout } = useStdout();
|
|
@@ -8931,6 +9556,28 @@ function App({
|
|
|
8931
9556
|
setIndexState(getIndexState());
|
|
8932
9557
|
return onIndexStateChange((next) => setIndexState(next));
|
|
8933
9558
|
}, []);
|
|
9559
|
+
const [breakerCountdown, setBreakerCountdown] = useState(
|
|
9560
|
+
() => getProcessRegistry().getBreakerCountdown()
|
|
9561
|
+
);
|
|
9562
|
+
useEffect(() => {
|
|
9563
|
+
const s2 = getSettings?.();
|
|
9564
|
+
if (s2) {
|
|
9565
|
+
getProcessRegistry().setBreakerConfig({
|
|
9566
|
+
enabled: s2.breakerEnabled ?? false,
|
|
9567
|
+
autoKillResetMs: s2.breakerAutoKillResetMs ?? 6e4
|
|
9568
|
+
});
|
|
9569
|
+
}
|
|
9570
|
+
return getProcessRegistry().onBreakerCountdownChange((snap) => setBreakerCountdown(snap));
|
|
9571
|
+
}, [getSettings]);
|
|
9572
|
+
const breakerArmed = breakerCountdown !== null;
|
|
9573
|
+
useEffect(() => {
|
|
9574
|
+
if (!breakerArmed) return;
|
|
9575
|
+
const t = setInterval(
|
|
9576
|
+
() => setBreakerCountdown(getProcessRegistry().getBreakerCountdown()),
|
|
9577
|
+
1e3
|
|
9578
|
+
);
|
|
9579
|
+
return () => clearInterval(t);
|
|
9580
|
+
}, [breakerArmed]);
|
|
8934
9581
|
useEffect(() => {
|
|
8935
9582
|
setHiddenItems([...statuslineHiddenItems]);
|
|
8936
9583
|
}, [statuslineHiddenItems]);
|
|
@@ -9028,7 +9675,7 @@ function App({
|
|
|
9028
9675
|
},
|
|
9029
9676
|
autonomyPicker: { open: false, options: [], selected: 0 },
|
|
9030
9677
|
resumePicker: { open: false, sessions: [], selected: 0, busy: false, hint: void 0, error: void 0 },
|
|
9031
|
-
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,
|
|
9678
|
+
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, tokenSavingTier: "off", allowOutsideProjectRoot: 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" },
|
|
9032
9679
|
projectPicker: { open: false, allItems: [], items: [], selected: 0, filter: "", hint: void 0 },
|
|
9033
9680
|
confirmQueue: [],
|
|
9034
9681
|
enhance: null,
|
|
@@ -9056,6 +9703,7 @@ function App({
|
|
|
9056
9703
|
todosMonitorOpen: false,
|
|
9057
9704
|
queuePanelOpen: false,
|
|
9058
9705
|
processListOpen: false,
|
|
9706
|
+
planPanelOpen: false,
|
|
9059
9707
|
goalPanelOpen: false,
|
|
9060
9708
|
sessionsPanelOpen: false,
|
|
9061
9709
|
sessionsPanel: { sessions: [], busy: false, selected: -1 },
|
|
@@ -9068,6 +9716,13 @@ function App({
|
|
|
9068
9716
|
autoPhase: null,
|
|
9069
9717
|
worktrees: {},
|
|
9070
9718
|
worktreeMonitorOpen: false,
|
|
9719
|
+
coordinator: {
|
|
9720
|
+
goals: [],
|
|
9721
|
+
timeline: [],
|
|
9722
|
+
knowledgeCount: 0,
|
|
9723
|
+
monitorOpen: false,
|
|
9724
|
+
healthy: false
|
|
9725
|
+
},
|
|
9071
9726
|
scrollOffset: 0,
|
|
9072
9727
|
totalLines: 0,
|
|
9073
9728
|
viewportRows: 0,
|
|
@@ -9075,6 +9730,7 @@ function App({
|
|
|
9075
9730
|
debugStreamStats: null,
|
|
9076
9731
|
countdown: null
|
|
9077
9732
|
});
|
|
9733
|
+
useAutonomousCoordinator(subscribeCoordinatorEvents, dispatch);
|
|
9078
9734
|
const builderRef = useRef(null);
|
|
9079
9735
|
if (builderRef.current === null) {
|
|
9080
9736
|
builderRef.current = new InputBuilder({ store: attachments });
|
|
@@ -9087,27 +9743,33 @@ function App({
|
|
|
9087
9743
|
const lastEnterAtRef = useRef(0);
|
|
9088
9744
|
const tokenPreviewsRef = useRef(/* @__PURE__ */ new Map());
|
|
9089
9745
|
const projectName = React5.useMemo(() => {
|
|
9090
|
-
const base =
|
|
9091
|
-
return base && base !==
|
|
9746
|
+
const base = path5.basename(projectRoot);
|
|
9747
|
+
return base && base !== path5.sep ? base : void 0;
|
|
9092
9748
|
}, [projectRoot]);
|
|
9093
9749
|
const [workingDirChip, setWorkingDirChip] = React5.useState(() => {
|
|
9094
9750
|
const ctx = agent.ctx;
|
|
9095
9751
|
if (ctx.workingDir && ctx.workingDir !== projectRoot) {
|
|
9096
|
-
return
|
|
9752
|
+
return path5.relative(projectRoot, ctx.workingDir) || ".";
|
|
9097
9753
|
}
|
|
9098
9754
|
return void 0;
|
|
9099
9755
|
});
|
|
9100
9756
|
React5.useEffect(() => {
|
|
9101
9757
|
const ctx = agent.ctx;
|
|
9102
9758
|
return ctx.onWorkingDirChanged((newDir) => {
|
|
9103
|
-
const rel =
|
|
9759
|
+
const rel = path5.relative(projectRoot, newDir) || ".";
|
|
9104
9760
|
setWorkingDirChip(rel === "." ? void 0 : rel);
|
|
9105
9761
|
});
|
|
9106
9762
|
}, [agent.ctx, projectRoot]);
|
|
9763
|
+
const liveSettings = getSettings?.();
|
|
9107
9764
|
const chimeRef = useRef(chime);
|
|
9108
|
-
chimeRef.current = chime;
|
|
9765
|
+
chimeRef.current = liveSettings?.chime ?? chime;
|
|
9109
9766
|
const confirmExitRef = useRef(confirmExit);
|
|
9110
|
-
confirmExitRef.current = confirmExit;
|
|
9767
|
+
confirmExitRef.current = liveSettings?.confirmExit ?? confirmExit;
|
|
9768
|
+
const liveTitleAnimation = liveSettings?.titleAnimation;
|
|
9769
|
+
useEffect(() => {
|
|
9770
|
+
if (!titleController) return;
|
|
9771
|
+
titleController.setEnabled(liveTitleAnimation !== false);
|
|
9772
|
+
}, [titleController, liveTitleAnimation]);
|
|
9111
9773
|
const streamingTextRef = useRef("");
|
|
9112
9774
|
const pendingDeltaRef = useRef("");
|
|
9113
9775
|
const flushTimerRef = useRef(null);
|
|
@@ -9491,7 +10153,7 @@ function App({
|
|
|
9491
10153
|
let cancelled = false;
|
|
9492
10154
|
const poll = async () => {
|
|
9493
10155
|
try {
|
|
9494
|
-
const data = await
|
|
10156
|
+
const data = await fs3.readFile(planPath, "utf8");
|
|
9495
10157
|
const parsed = JSON.parse(data);
|
|
9496
10158
|
if (cancelled) return;
|
|
9497
10159
|
if (!Array.isArray(parsed.items)) {
|
|
@@ -9525,7 +10187,7 @@ function App({
|
|
|
9525
10187
|
let cancelled = false;
|
|
9526
10188
|
const poll = async () => {
|
|
9527
10189
|
try {
|
|
9528
|
-
const data = await
|
|
10190
|
+
const data = await fs3.readFile(taskPath, "utf8");
|
|
9529
10191
|
const parsed = JSON.parse(data);
|
|
9530
10192
|
if (cancelled) return;
|
|
9531
10193
|
if (!Array.isArray(parsed.tasks)) {
|
|
@@ -9575,7 +10237,7 @@ function App({
|
|
|
9575
10237
|
}
|
|
9576
10238
|
}, []);
|
|
9577
10239
|
React5.useLayoutEffect(() => {
|
|
9578
|
-
const anyOpenNow = state.picker.open || state.slashPicker.open || state.modelPicker.open || state.autonomyPicker.open || state.resumePicker.open || state.settingsPicker.open || state.enhanceBusy || state.enhance != null || state.escConfirm != null || state.confirmQueue.length > 0;
|
|
10240
|
+
const anyOpenNow = state.picker.open || state.slashPicker.open || state.modelPicker.open || state.autonomyPicker.open || state.resumePicker.open || state.settingsPicker.open || state.enhanceBusy || state.enhance != null || state.coordinator.monitorOpen || state.escConfirm != null || state.confirmQueue.length > 0;
|
|
9579
10241
|
const overlayClosed = prevAnyOverlayOpen.current && !anyOpenNow;
|
|
9580
10242
|
const newEntryCommitted = state.entries.length > prevEntriesCount.current;
|
|
9581
10243
|
const curToolStreamLen = state.toolStream?.text.length ?? 0;
|
|
@@ -9594,6 +10256,7 @@ function App({
|
|
|
9594
10256
|
state.settingsPicker.open,
|
|
9595
10257
|
state.enhanceBusy,
|
|
9596
10258
|
state.enhance,
|
|
10259
|
+
state.coordinator.monitorOpen,
|
|
9597
10260
|
state.escConfirm,
|
|
9598
10261
|
state.confirmQueue.length,
|
|
9599
10262
|
state.entries.length,
|
|
@@ -9618,7 +10281,8 @@ function App({
|
|
|
9618
10281
|
queue: stateRef.current.queuePanelOpen,
|
|
9619
10282
|
processList: stateRef.current.processListOpen,
|
|
9620
10283
|
goalPanel: stateRef.current.goalPanelOpen,
|
|
9621
|
-
sessionsPanel: stateRef.current.sessionsPanelOpen
|
|
10284
|
+
sessionsPanel: stateRef.current.sessionsPanelOpen,
|
|
10285
|
+
coordinator: stateRef.current.coordinator.monitorOpen
|
|
9622
10286
|
};
|
|
9623
10287
|
if (stateRef.current.settingsPicker.open) dispatch({ type: "settingsClose" });
|
|
9624
10288
|
if (stateRef.current.projectPicker.open) dispatch({ type: "projectPickerClose" });
|
|
@@ -9635,6 +10299,7 @@ function App({
|
|
|
9635
10299
|
if (stateRef.current.todosMonitorOpen) dispatch({ type: "toggleTodosMonitor" });
|
|
9636
10300
|
if (stateRef.current.queuePanelOpen) dispatch({ type: "toggleQueuePanel" });
|
|
9637
10301
|
if (stateRef.current.processListOpen) dispatch({ type: "toggleProcessList" });
|
|
10302
|
+
if (stateRef.current.planPanelOpen) dispatch({ type: "togglePlanPanel" });
|
|
9638
10303
|
if (stateRef.current.goalPanelOpen) dispatch({ type: "toggleGoalPanel" });
|
|
9639
10304
|
if (stateRef.current.sessionsPanelOpen) dispatch({ type: "toggleSessionsPanel" });
|
|
9640
10305
|
eraseLiveRegion();
|
|
@@ -9660,7 +10325,8 @@ function App({
|
|
|
9660
10325
|
featureMemory: sp.featureMemory,
|
|
9661
10326
|
featureSkills: sp.featureSkills,
|
|
9662
10327
|
featureModelsRegistry: sp.featureModelsRegistry,
|
|
9663
|
-
|
|
10328
|
+
tokenSavingTier: sp.tokenSavingTier,
|
|
10329
|
+
allowOutsideProjectRoot: sp.allowOutsideProjectRoot,
|
|
9664
10330
|
contextAutoCompact: sp.contextAutoCompact,
|
|
9665
10331
|
contextStrategy: sp.contextStrategy,
|
|
9666
10332
|
logLevel: sp.logLevel,
|
|
@@ -9688,6 +10354,7 @@ function App({
|
|
|
9688
10354
|
if (prev.processList) dispatch({ type: "toggleProcessList" });
|
|
9689
10355
|
if (prev.goalPanel) dispatch({ type: "toggleGoalPanel" });
|
|
9690
10356
|
if (prev.sessionsPanel) dispatch({ type: "toggleSessionsPanel" });
|
|
10357
|
+
if (prev.coordinator) dispatch({ type: "toggleCoordinatorMonitor" });
|
|
9691
10358
|
preResizePanelsRef.current = null;
|
|
9692
10359
|
resizeRestoreTimerRef.current = null;
|
|
9693
10360
|
}, 300);
|
|
@@ -9781,7 +10448,28 @@ function App({
|
|
|
9781
10448
|
type: "addEntry",
|
|
9782
10449
|
entry: {
|
|
9783
10450
|
kind: "error",
|
|
9784
|
-
text: `Clipboard image error: ${
|
|
10451
|
+
text: `Clipboard image error: ${toErrorMessage(err)}`
|
|
10452
|
+
}
|
|
10453
|
+
});
|
|
10454
|
+
}
|
|
10455
|
+
};
|
|
10456
|
+
const pasteClipboardText = async () => {
|
|
10457
|
+
try {
|
|
10458
|
+
const text = await readClipboardText();
|
|
10459
|
+
if (!text) {
|
|
10460
|
+
dispatch({
|
|
10461
|
+
type: "addEntry",
|
|
10462
|
+
entry: { kind: "info", text: "No text on the clipboard." }
|
|
10463
|
+
});
|
|
10464
|
+
return;
|
|
10465
|
+
}
|
|
10466
|
+
await commitPaste(text);
|
|
10467
|
+
} catch (err) {
|
|
10468
|
+
dispatch({
|
|
10469
|
+
type: "addEntry",
|
|
10470
|
+
entry: {
|
|
10471
|
+
kind: "error",
|
|
10472
|
+
text: `Clipboard error: ${toErrorMessage(err)}`
|
|
9785
10473
|
}
|
|
9786
10474
|
});
|
|
9787
10475
|
}
|
|
@@ -9799,9 +10487,9 @@ function App({
|
|
|
9799
10487
|
dispatch({ type: "pickerClose" });
|
|
9800
10488
|
return;
|
|
9801
10489
|
}
|
|
9802
|
-
const absPath =
|
|
10490
|
+
const absPath = path5.isAbsolute(picked) ? picked : path5.join(projectRoot, picked);
|
|
9803
10491
|
try {
|
|
9804
|
-
const data = await
|
|
10492
|
+
const data = await fs3.readFile(absPath, "utf8");
|
|
9805
10493
|
const token = await builder.registerFile({
|
|
9806
10494
|
kind: "file",
|
|
9807
10495
|
data,
|
|
@@ -9818,7 +10506,7 @@ function App({
|
|
|
9818
10506
|
type: "addEntry",
|
|
9819
10507
|
entry: {
|
|
9820
10508
|
kind: "error",
|
|
9821
|
-
text: `Attach failed: ${
|
|
10509
|
+
text: `Attach failed: ${toErrorMessage(err)}`
|
|
9822
10510
|
}
|
|
9823
10511
|
});
|
|
9824
10512
|
dispatch({ type: "pickerClose" });
|
|
@@ -10004,7 +10692,10 @@ function App({
|
|
|
10004
10692
|
dispatch({ type: "projectPickerOpen", items });
|
|
10005
10693
|
}, [getProjectPickerItems]);
|
|
10006
10694
|
const loadLiveSessions = React5.useCallback(async () => {
|
|
10007
|
-
if (!getLiveSessions)
|
|
10695
|
+
if (!getLiveSessions) {
|
|
10696
|
+
dispatch({ type: "sessionsPanelSet", sessions: [] });
|
|
10697
|
+
return;
|
|
10698
|
+
}
|
|
10008
10699
|
dispatch({ type: "sessionsPanelBusy", on: true });
|
|
10009
10700
|
try {
|
|
10010
10701
|
const sessions = await getLiveSessions();
|
|
@@ -10038,7 +10729,8 @@ function App({
|
|
|
10038
10729
|
featureMemory: s2.featureMemory ?? true,
|
|
10039
10730
|
featureSkills: s2.featureSkills ?? true,
|
|
10040
10731
|
featureModelsRegistry: s2.featureModelsRegistry ?? true,
|
|
10041
|
-
|
|
10732
|
+
tokenSavingTier: s2.featureTokenSaving ?? "off",
|
|
10733
|
+
allowOutsideProjectRoot: s2.allowOutsideProjectRoot ?? true,
|
|
10042
10734
|
contextAutoCompact: s2.contextAutoCompact ?? true,
|
|
10043
10735
|
contextStrategy: s2.contextStrategy ?? "hybrid",
|
|
10044
10736
|
logLevel: s2.logLevel ?? "info",
|
|
@@ -10173,7 +10865,8 @@ function App({
|
|
|
10173
10865
|
featureMemory: sp.featureMemory,
|
|
10174
10866
|
featureSkills: sp.featureSkills,
|
|
10175
10867
|
featureModelsRegistry: sp.featureModelsRegistry,
|
|
10176
|
-
featureTokenSaving: sp.
|
|
10868
|
+
featureTokenSaving: sp.tokenSavingTier,
|
|
10869
|
+
allowOutsideProjectRoot: sp.allowOutsideProjectRoot,
|
|
10177
10870
|
contextAutoCompact: sp.contextAutoCompact,
|
|
10178
10871
|
contextStrategy: sp.contextStrategy,
|
|
10179
10872
|
logLevel: sp.logLevel,
|
|
@@ -10204,6 +10897,8 @@ function App({
|
|
|
10204
10897
|
state.settingsPicker.featureMemory,
|
|
10205
10898
|
state.settingsPicker.featureSkills,
|
|
10206
10899
|
state.settingsPicker.featureModelsRegistry,
|
|
10900
|
+
state.settingsPicker.tokenSavingTier,
|
|
10901
|
+
state.settingsPicker.allowOutsideProjectRoot,
|
|
10207
10902
|
state.settingsPicker.contextAutoCompact,
|
|
10208
10903
|
state.settingsPicker.contextStrategy,
|
|
10209
10904
|
state.settingsPicker.logLevel,
|
|
@@ -10212,6 +10907,9 @@ function App({
|
|
|
10212
10907
|
state.settingsPicker.maxIterations,
|
|
10213
10908
|
state.settingsPicker.autoProceedMaxIterations,
|
|
10214
10909
|
state.settingsPicker.enhanceDelayMs,
|
|
10910
|
+
state.settingsPicker.enhanceEnabled,
|
|
10911
|
+
state.settingsPicker.enhanceLanguage,
|
|
10912
|
+
state.settingsPicker.debugStream,
|
|
10215
10913
|
saveSettings
|
|
10216
10914
|
]);
|
|
10217
10915
|
useEffect(() => {
|
|
@@ -10294,7 +10992,7 @@ function App({
|
|
|
10294
10992
|
dispatch({ type: "resumePickerOpen", sessions });
|
|
10295
10993
|
} catch (err) {
|
|
10296
10994
|
return {
|
|
10297
|
-
message:
|
|
10995
|
+
message: toErrorMessage(err)
|
|
10298
10996
|
};
|
|
10299
10997
|
}
|
|
10300
10998
|
return { message: void 0 };
|
|
@@ -10474,6 +11172,47 @@ function App({
|
|
|
10474
11172
|
if (flushTimerRef.current) clearTimeout(flushTimerRef.current);
|
|
10475
11173
|
};
|
|
10476
11174
|
}, [events, agent.ctx.todos]);
|
|
11175
|
+
useEffect(() => {
|
|
11176
|
+
if (!clientId || !events) return;
|
|
11177
|
+
let toolCalls = 0;
|
|
11178
|
+
const emitStatus = () => {
|
|
11179
|
+
const usage = tokenCounter?.total();
|
|
11180
|
+
const cost = tokenCounter?.estimateCost();
|
|
11181
|
+
const mode = getAutonomy?.() ?? "off";
|
|
11182
|
+
events.emit("client.status", {
|
|
11183
|
+
clientType: "tui",
|
|
11184
|
+
clientId,
|
|
11185
|
+
projectHash: agent.ctx.projectRoot ? projectSlug(agent.ctx.projectRoot) : "unknown",
|
|
11186
|
+
agentCount: 1,
|
|
11187
|
+
// TUI is a single leader agent
|
|
11188
|
+
model: agent.ctx.model,
|
|
11189
|
+
mode,
|
|
11190
|
+
toolCalls,
|
|
11191
|
+
inputTokens: usage?.input ?? 0,
|
|
11192
|
+
outputTokens: usage?.output ?? 0,
|
|
11193
|
+
cacheTokens: (usage?.cacheRead ?? 0) + (usage?.cacheWrite ?? 0),
|
|
11194
|
+
costUsd: cost?.total ?? 0,
|
|
11195
|
+
timestamp: Date.now(),
|
|
11196
|
+
projectSlug: agent.ctx.projectRoot ? projectSlug(agent.ctx.projectRoot) : "unknown"
|
|
11197
|
+
});
|
|
11198
|
+
};
|
|
11199
|
+
const offTool = events.on("tool.executed", () => {
|
|
11200
|
+
toolCalls++;
|
|
11201
|
+
emitStatus();
|
|
11202
|
+
});
|
|
11203
|
+
const offProviderResp = events.on("provider.response", () => {
|
|
11204
|
+
emitStatus();
|
|
11205
|
+
});
|
|
11206
|
+
const offIterCompleted = events.on("iteration.completed", () => {
|
|
11207
|
+
emitStatus();
|
|
11208
|
+
});
|
|
11209
|
+
emitStatus();
|
|
11210
|
+
return () => {
|
|
11211
|
+
offTool();
|
|
11212
|
+
offProviderResp();
|
|
11213
|
+
offIterCompleted();
|
|
11214
|
+
};
|
|
11215
|
+
}, [events, clientId, tokenCounter, getAutonomy, agent.ctx.model, agent.ctx.projectRoot]);
|
|
10477
11216
|
useEffect(() => {
|
|
10478
11217
|
if (!registerDebugStreamCallback) return;
|
|
10479
11218
|
let cancelled = false;
|
|
@@ -10897,7 +11636,7 @@ function App({
|
|
|
10897
11636
|
}).catch((err) => {
|
|
10898
11637
|
dispatch({
|
|
10899
11638
|
type: "resumePickerError",
|
|
10900
|
-
text:
|
|
11639
|
+
text: toErrorMessage(err)
|
|
10901
11640
|
});
|
|
10902
11641
|
});
|
|
10903
11642
|
return;
|
|
@@ -11294,6 +12033,21 @@ function App({
|
|
|
11294
12033
|
toggleWorktreeOverlay();
|
|
11295
12034
|
return;
|
|
11296
12035
|
}
|
|
12036
|
+
if (key.fn === 5) {
|
|
12037
|
+
if (state.planPanelOpen) {
|
|
12038
|
+
dispatch({ type: "togglePlanPanel" });
|
|
12039
|
+
} else {
|
|
12040
|
+
if (state.agentsMonitorOpen) dispatch({ type: "toggleAgentsMonitor" });
|
|
12041
|
+
if (state.monitorOpen) dispatch({ type: "toggleMonitor" });
|
|
12042
|
+
if (state.worktreeMonitorOpen) dispatch({ type: "worktreeMonitorToggle" });
|
|
12043
|
+
if (state.todosMonitorOpen) dispatch({ type: "toggleTodosMonitor" });
|
|
12044
|
+
if (state.autoPhase?.monitorOpen) dispatch({ type: "autoPhaseMonitorToggle" });
|
|
12045
|
+
if (state.settingsPicker.open) dispatch({ type: "settingsClose" });
|
|
12046
|
+
if (state.helpOpen) dispatch({ type: "toggleHelp" });
|
|
12047
|
+
dispatch({ type: "togglePlanPanel" });
|
|
12048
|
+
}
|
|
12049
|
+
return;
|
|
12050
|
+
}
|
|
11297
12051
|
if (key.fn === 6) {
|
|
11298
12052
|
toggleTodosOverlay();
|
|
11299
12053
|
return;
|
|
@@ -11346,7 +12100,7 @@ function App({
|
|
|
11346
12100
|
}
|
|
11347
12101
|
return;
|
|
11348
12102
|
}
|
|
11349
|
-
if (key.fn === 10) {
|
|
12103
|
+
if (key.fn === 10 || key.escape && state.sessionsPanelOpen) {
|
|
11350
12104
|
if (state.sessionsPanelOpen) {
|
|
11351
12105
|
dispatch({ type: "toggleSessionsPanel" });
|
|
11352
12106
|
} else {
|
|
@@ -11365,6 +12119,10 @@ function App({
|
|
|
11365
12119
|
}
|
|
11366
12120
|
return;
|
|
11367
12121
|
}
|
|
12122
|
+
if (key.fn === 11 || input === "\x1B" && state.coordinator.monitorOpen) {
|
|
12123
|
+
dispatch({ type: "toggleCoordinatorMonitor" });
|
|
12124
|
+
return;
|
|
12125
|
+
}
|
|
11368
12126
|
if (key.ctrl && input === "s") {
|
|
11369
12127
|
if (state.settingsPicker.open) {
|
|
11370
12128
|
dispatch({ type: "settingsClose" });
|
|
@@ -11392,7 +12150,8 @@ function App({
|
|
|
11392
12150
|
featureMemory: cfg.featureMemory ?? true,
|
|
11393
12151
|
featureSkills: cfg.featureSkills ?? true,
|
|
11394
12152
|
featureModelsRegistry: cfg.featureModelsRegistry ?? true,
|
|
11395
|
-
|
|
12153
|
+
tokenSavingTier: cfg.featureTokenSaving ?? "off",
|
|
12154
|
+
allowOutsideProjectRoot: cfg.allowOutsideProjectRoot ?? true,
|
|
11396
12155
|
contextAutoCompact: cfg.contextAutoCompact ?? true,
|
|
11397
12156
|
contextStrategy: cfg.contextStrategy ?? "hybrid",
|
|
11398
12157
|
logLevel: cfg.logLevel ?? "info",
|
|
@@ -11442,10 +12201,18 @@ function App({
|
|
|
11442
12201
|
dispatch({ type: "toggleGoalPanel" });
|
|
11443
12202
|
return;
|
|
11444
12203
|
}
|
|
12204
|
+
if (state.helpOpen) {
|
|
12205
|
+
dispatch({ type: "toggleHelp" });
|
|
12206
|
+
return;
|
|
12207
|
+
}
|
|
11445
12208
|
if (state.sessionsPanelOpen) {
|
|
11446
12209
|
dispatch({ type: "toggleSessionsPanel" });
|
|
11447
12210
|
return;
|
|
11448
12211
|
}
|
|
12212
|
+
if (state.coordinator.monitorOpen) {
|
|
12213
|
+
dispatch({ type: "toggleCoordinatorMonitor" });
|
|
12214
|
+
return;
|
|
12215
|
+
}
|
|
11449
12216
|
}
|
|
11450
12217
|
if (state.processListOpen) {
|
|
11451
12218
|
return;
|
|
@@ -11468,6 +12235,17 @@ function App({
|
|
|
11468
12235
|
return;
|
|
11469
12236
|
}
|
|
11470
12237
|
const { buffer, cursor } = draftRef.current;
|
|
12238
|
+
if (key.tab && nextStepsAutoSubmitTimerRef.current != null) {
|
|
12239
|
+
const pending = nextStepsAutoSubmitSuggestionRef.current ?? nextStepsAutoSubmitLabel ?? "";
|
|
12240
|
+
clearInterval(nextStepsAutoSubmitTimerRef.current);
|
|
12241
|
+
nextStepsAutoSubmitTimerRef.current = void 0;
|
|
12242
|
+
setNextStepsAutoSubmitCountdown(null);
|
|
12243
|
+
setNextStepsAutoSubmitLabel(null);
|
|
12244
|
+
nextStepsAutoSubmitSuggestionRef.current = null;
|
|
12245
|
+
const text = pending.trim();
|
|
12246
|
+
if (text) setDraft(text, text.length);
|
|
12247
|
+
return;
|
|
12248
|
+
}
|
|
11471
12249
|
if (key.backspace) {
|
|
11472
12250
|
if (key.ctrl) {
|
|
11473
12251
|
if (cursor === 0) return;
|
|
@@ -11555,7 +12333,58 @@ function App({
|
|
|
11555
12333
|
setDraft(buffer, buffer.length);
|
|
11556
12334
|
return;
|
|
11557
12335
|
}
|
|
11558
|
-
|
|
12336
|
+
if (key.upArrow || key.downArrow || key.pageUp || key.pageDown) {
|
|
12337
|
+
const width = stdout?.columns ?? 80;
|
|
12338
|
+
const rows = layoutInputRows(INPUT_PROMPT, buffer, cursor, width);
|
|
12339
|
+
if (rows.length <= 1) ; else {
|
|
12340
|
+
let row = 0, col = 0, offset = 0;
|
|
12341
|
+
outer: for (let r = 0; r < rows.length; r++) {
|
|
12342
|
+
const cells = rows[r];
|
|
12343
|
+
for (let c = 0; c < cells.length; c++) {
|
|
12344
|
+
if (offset === cursor) {
|
|
12345
|
+
row = r;
|
|
12346
|
+
col = c;
|
|
12347
|
+
break outer;
|
|
12348
|
+
}
|
|
12349
|
+
offset++;
|
|
12350
|
+
}
|
|
12351
|
+
if (cells.length < width) offset++;
|
|
12352
|
+
}
|
|
12353
|
+
if (key.upArrow) {
|
|
12354
|
+
if (row > 0) {
|
|
12355
|
+
const prevRowLen = rows[row - 1].filter((cell) => !cell.prompt && !cell.chip).length;
|
|
12356
|
+
const targetCol = Math.min(col, prevRowLen);
|
|
12357
|
+
const target = inputIndexAtRowCol(INPUT_PROMPT, buffer, width, row - 1, targetCol);
|
|
12358
|
+
setDraft(buffer, target);
|
|
12359
|
+
return;
|
|
12360
|
+
}
|
|
12361
|
+
return;
|
|
12362
|
+
}
|
|
12363
|
+
if (key.downArrow) {
|
|
12364
|
+
if (row < rows.length - 1) {
|
|
12365
|
+
const nextRowLen = rows[row + 1].filter((cell) => !cell.prompt && !cell.chip).length;
|
|
12366
|
+
const targetCol = Math.min(col, nextRowLen);
|
|
12367
|
+
const target = inputIndexAtRowCol(INPUT_PROMPT, buffer, width, row + 1, targetCol);
|
|
12368
|
+
setDraft(buffer, target);
|
|
12369
|
+
return;
|
|
12370
|
+
}
|
|
12371
|
+
return;
|
|
12372
|
+
}
|
|
12373
|
+
if (key.pageUp || key.pageDown) {
|
|
12374
|
+
const pageSize = Math.max(1, Math.floor((stdout?.rows ?? 24) / 2));
|
|
12375
|
+
const delta = key.pageUp ? -pageSize : pageSize;
|
|
12376
|
+
const targetRow = Math.max(0, Math.min(rows.length - 1, row + delta));
|
|
12377
|
+
if (targetRow !== row) {
|
|
12378
|
+
const targetRowLen = rows[targetRow].filter((cell) => !cell.prompt && !cell.chip).length;
|
|
12379
|
+
const targetCol = Math.min(col, targetRowLen);
|
|
12380
|
+
const target = inputIndexAtRowCol(INPUT_PROMPT, buffer, width, targetRow, targetCol);
|
|
12381
|
+
setDraft(buffer, target);
|
|
12382
|
+
}
|
|
12383
|
+
return;
|
|
12384
|
+
}
|
|
12385
|
+
}
|
|
12386
|
+
}
|
|
12387
|
+
const overlayOpen = state.monitorOpen || state.agentsMonitorOpen || state.worktreeMonitorOpen || state.todosMonitorOpen || state.queuePanelOpen || state.processListOpen || state.goalPanelOpen || state.sessionsPanelOpen || state.coordinator.monitorOpen || state.helpOpen || (state.autoPhase?.monitorOpen ?? false) || state.rewindOverlay !== null;
|
|
11559
12388
|
if (mouseMode && !overlayOpen) {
|
|
11560
12389
|
if (key.mouse?.kind === "wheel") {
|
|
11561
12390
|
if (key.mouse.shift) dispatch({ type: "scrollPage", dir: key.mouse.wheel > 0 ? "up" : "down" });
|
|
@@ -11684,6 +12513,10 @@ function App({
|
|
|
11684
12513
|
setDraft(next2, cursor);
|
|
11685
12514
|
return;
|
|
11686
12515
|
}
|
|
12516
|
+
if (key.ctrl) {
|
|
12517
|
+
await pasteClipboardText();
|
|
12518
|
+
return;
|
|
12519
|
+
}
|
|
11687
12520
|
if (key.meta && input === "v") {
|
|
11688
12521
|
await pasteClipboardImage();
|
|
11689
12522
|
return;
|
|
@@ -11807,7 +12640,7 @@ function App({
|
|
|
11807
12640
|
} catch (err) {
|
|
11808
12641
|
dispatch({
|
|
11809
12642
|
type: "addEntry",
|
|
11810
|
-
entry: { kind: "error", text:
|
|
12643
|
+
entry: { kind: "error", text: toErrorMessage(err) }
|
|
11811
12644
|
});
|
|
11812
12645
|
} finally {
|
|
11813
12646
|
activeCtrlRef.current = null;
|
|
@@ -11849,7 +12682,7 @@ function App({
|
|
|
11849
12682
|
type: "addEntry",
|
|
11850
12683
|
entry: {
|
|
11851
12684
|
kind: "error",
|
|
11852
|
-
text: `[eternal] ${
|
|
12685
|
+
text: `[eternal] ${toErrorMessage(err)}`
|
|
11853
12686
|
}
|
|
11854
12687
|
});
|
|
11855
12688
|
}
|
|
@@ -11885,7 +12718,7 @@ function App({
|
|
|
11885
12718
|
type: "addEntry",
|
|
11886
12719
|
entry: {
|
|
11887
12720
|
kind: "error",
|
|
11888
|
-
text: `[parallel] ${
|
|
12721
|
+
text: `[parallel] ${toErrorMessage(err)}`
|
|
11889
12722
|
}
|
|
11890
12723
|
});
|
|
11891
12724
|
}
|
|
@@ -12047,7 +12880,7 @@ ${content}
|
|
|
12047
12880
|
} catch (err) {
|
|
12048
12881
|
dispatch({
|
|
12049
12882
|
type: "addEntry",
|
|
12050
|
-
entry: { kind: "error", text:
|
|
12883
|
+
entry: { kind: "error", text: toErrorMessage(err) }
|
|
12051
12884
|
});
|
|
12052
12885
|
}
|
|
12053
12886
|
return;
|
|
@@ -12326,7 +13159,8 @@ User message:
|
|
|
12326
13159
|
featureMemory: state.settingsPicker.featureMemory,
|
|
12327
13160
|
featureSkills: state.settingsPicker.featureSkills,
|
|
12328
13161
|
featureModelsRegistry: state.settingsPicker.featureModelsRegistry,
|
|
12329
|
-
|
|
13162
|
+
tokenSavingTier: state.settingsPicker.tokenSavingTier,
|
|
13163
|
+
allowOutsideProjectRoot: state.settingsPicker.allowOutsideProjectRoot,
|
|
12330
13164
|
contextAutoCompact: state.settingsPicker.contextAutoCompact,
|
|
12331
13165
|
contextStrategy: state.settingsPicker.contextStrategy,
|
|
12332
13166
|
logLevel: state.settingsPicker.logLevel,
|
|
@@ -12361,6 +13195,14 @@ User message:
|
|
|
12361
13195
|
currentSessionId: agent.ctx.session?.id
|
|
12362
13196
|
}
|
|
12363
13197
|
) : null,
|
|
13198
|
+
state.coordinator.monitorOpen ? /* @__PURE__ */ jsx(
|
|
13199
|
+
CoordinatorPanel,
|
|
13200
|
+
{
|
|
13201
|
+
coordinator: state.coordinator,
|
|
13202
|
+
nowTick,
|
|
13203
|
+
onClose: () => dispatch({ type: "toggleCoordinatorMonitor" })
|
|
13204
|
+
}
|
|
13205
|
+
) : null,
|
|
12364
13206
|
state.rewindOverlay ? (() => {
|
|
12365
13207
|
const overlay = state.rewindOverlay;
|
|
12366
13208
|
return /* @__PURE__ */ jsx(
|
|
@@ -12491,6 +13333,7 @@ User message:
|
|
|
12491
13333
|
fleet: fleetCounts,
|
|
12492
13334
|
git: gitInfo,
|
|
12493
13335
|
context: contextWindow,
|
|
13336
|
+
contextStrategy: getSettings ? getSettings().contextStrategy : void 0,
|
|
12494
13337
|
brain: state.brain,
|
|
12495
13338
|
projectName,
|
|
12496
13339
|
workingDir: workingDirChip,
|
|
@@ -12501,6 +13344,7 @@ User message:
|
|
|
12501
13344
|
eternalStage: state.eternalStage,
|
|
12502
13345
|
goalSummary: state.goalSummary,
|
|
12503
13346
|
indexState,
|
|
13347
|
+
breakerCountdown,
|
|
12504
13348
|
modeLabel: liveModeLabel || void 0,
|
|
12505
13349
|
debugStreamStats: state.debugStreamStats,
|
|
12506
13350
|
enhanceCountdown,
|
|
@@ -12509,7 +13353,7 @@ User message:
|
|
|
12509
13353
|
autoProceedCountdown: state.countdown?.remainingSeconds ?? null,
|
|
12510
13354
|
sessionCount,
|
|
12511
13355
|
mailbox: mailboxStatus,
|
|
12512
|
-
tokenSavingMode: getSettings ? getSettings().featureTokenSaving : tokenSavingMode,
|
|
13356
|
+
tokenSavingMode: getSettings ? getSettings().featureTokenSaving !== "off" : tokenSavingMode,
|
|
12513
13357
|
toolCount
|
|
12514
13358
|
}
|
|
12515
13359
|
) }),
|
|
@@ -12539,8 +13383,7 @@ User message:
|
|
|
12539
13383
|
phases: state.autoPhase.phases,
|
|
12540
13384
|
runningPhaseIds: state.autoPhase.runningPhaseIds,
|
|
12541
13385
|
elapsedMs: state.autoPhase.elapsedMs,
|
|
12542
|
-
nowTick
|
|
12543
|
-
onClose: () => dispatch({ type: "autoPhaseMonitorToggle" })
|
|
13386
|
+
nowTick
|
|
12544
13387
|
}
|
|
12545
13388
|
) : state.worktreeMonitorOpen ? /* @__PURE__ */ jsx(
|
|
12546
13389
|
WorktreeMonitor,
|
|
@@ -12580,7 +13423,23 @@ User message:
|
|
|
12580
13423
|
Object.keys(state.worktrees).length > 0 && !state.worktreeMonitorOpen && !state.monitorOpen ? /* @__PURE__ */ jsx(WorktreePanel, { worktrees: state.worktrees, nowTick }) : null,
|
|
12581
13424
|
state.queuePanelOpen ? /* @__PURE__ */ jsx(QueuePanel, { items: state.queue }) : null,
|
|
12582
13425
|
state.processListOpen ? /* @__PURE__ */ jsx(ProcessListMonitor, {}) : null,
|
|
12583
|
-
state.
|
|
13426
|
+
state.planPanelOpen ? /* @__PURE__ */ jsx(
|
|
13427
|
+
PlanPanel,
|
|
13428
|
+
{
|
|
13429
|
+
projectRoot,
|
|
13430
|
+
sessionId: agent.ctx.session?.id ?? null,
|
|
13431
|
+
onClose: () => dispatch({ type: "togglePlanPanel" })
|
|
13432
|
+
}
|
|
13433
|
+
) : null,
|
|
13434
|
+
state.goalPanelOpen ? /* @__PURE__ */ jsx(
|
|
13435
|
+
GoalPanel,
|
|
13436
|
+
{
|
|
13437
|
+
goal: state.goalSummary,
|
|
13438
|
+
onCoordinatorStart: onCoordinatorStart ?? void 0,
|
|
13439
|
+
onCoordinatorStop: onCoordinatorStop ?? void 0,
|
|
13440
|
+
coordinatorRunning
|
|
13441
|
+
}
|
|
13442
|
+
) : null,
|
|
12584
13443
|
(() => {
|
|
12585
13444
|
const anyMonitorOpen = state.agentsMonitorOpen || (state.autoPhase?.monitorOpen ?? false) || state.worktreeMonitorOpen || state.todosMonitorOpen || state.monitorOpen || state.processListOpen || state.queuePanelOpen || state.goalPanelOpen;
|
|
12586
13445
|
let nextPanelHint;
|
|
@@ -12756,13 +13615,30 @@ async function runTui(opts) {
|
|
|
12756
13615
|
const mouseEnabled = opts.mouse ?? opts.getSettings?.().mouseMode ?? process.env.WRONGSTACK_MOUSE === "1";
|
|
12757
13616
|
stdout.write("\x1B[2J\x1B[H");
|
|
12758
13617
|
const inkStdin = stdin;
|
|
12759
|
-
|
|
12760
|
-
|
|
12761
|
-
|
|
12762
|
-
|
|
12763
|
-
|
|
12764
|
-
|
|
12765
|
-
|
|
13618
|
+
let titleStop = null;
|
|
13619
|
+
const startTitle = () => {
|
|
13620
|
+
if (titleStop) return;
|
|
13621
|
+
titleStop = startTerminalTitle({
|
|
13622
|
+
stdout,
|
|
13623
|
+
events: opts.events,
|
|
13624
|
+
model: opts.model,
|
|
13625
|
+
appName: opts.projectRoot ? path5.basename(opts.projectRoot) : void 0
|
|
13626
|
+
});
|
|
13627
|
+
};
|
|
13628
|
+
const stopTitle = () => {
|
|
13629
|
+
try {
|
|
13630
|
+
titleStop?.();
|
|
13631
|
+
} catch {
|
|
13632
|
+
}
|
|
13633
|
+
titleStop = null;
|
|
13634
|
+
};
|
|
13635
|
+
const titleController = {
|
|
13636
|
+
setEnabled(on) {
|
|
13637
|
+
if (on) startTitle();
|
|
13638
|
+
else stopTitle();
|
|
13639
|
+
}
|
|
13640
|
+
};
|
|
13641
|
+
if (opts.titleAnimation !== false) startTitle();
|
|
12766
13642
|
const swallowSignals = ["SIGTSTP", "SIGQUIT", "SIGTTIN", "SIGTTOU"];
|
|
12767
13643
|
const swallow = () => {
|
|
12768
13644
|
};
|
|
@@ -12816,7 +13692,7 @@ async function runTui(opts) {
|
|
|
12816
13692
|
await mailbox.registerClient({
|
|
12817
13693
|
clientId,
|
|
12818
13694
|
sessionId: opts.projectRoot,
|
|
12819
|
-
name: `TUI [${
|
|
13695
|
+
name: `TUI [${path5.basename(opts.projectRoot)}]`,
|
|
12820
13696
|
source: "tui",
|
|
12821
13697
|
pid: process.pid
|
|
12822
13698
|
});
|
|
@@ -12941,6 +13817,7 @@ async function runTui(opts) {
|
|
|
12941
13817
|
setSuggestions: opts.setSuggestions,
|
|
12942
13818
|
chime: opts.chime,
|
|
12943
13819
|
confirmExit: opts.confirmExit,
|
|
13820
|
+
titleController,
|
|
12944
13821
|
mouse: mouseEnabled,
|
|
12945
13822
|
modeLabel: opts.modeLabel,
|
|
12946
13823
|
tokenSavingMode: opts.tokenSavingMode,
|
|
@@ -12957,7 +13834,10 @@ async function runTui(opts) {
|
|
|
12957
13834
|
requestExit: opts.requestExit,
|
|
12958
13835
|
getLiveSessions: opts.getLiveSessions,
|
|
12959
13836
|
onSwitchToSession: opts.onSwitchToSession,
|
|
12960
|
-
initialAgentsMonitorOpen: opts.initialAgentsMonitorOpen
|
|
13837
|
+
initialAgentsMonitorOpen: opts.initialAgentsMonitorOpen,
|
|
13838
|
+
subscribeCoordinatorEvents: opts.subscribeCoordinatorEvents,
|
|
13839
|
+
onCoordinatorStart: opts.onCoordinatorStart,
|
|
13840
|
+
onCoordinatorStop: opts.onCoordinatorStop
|
|
12961
13841
|
}),
|
|
12962
13842
|
{ exitOnCtrlC: false, stdin: inkStdin }
|
|
12963
13843
|
);
|