@wrongstack/tui 0.306.2 → 0.306.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js
CHANGED
|
@@ -291,9 +291,9 @@ var init_connections_health = __esm({
|
|
|
291
291
|
});
|
|
292
292
|
|
|
293
293
|
// src/app.tsx
|
|
294
|
-
import * as
|
|
294
|
+
import * as path9 from "node:path";
|
|
295
295
|
import { applyRewindToConversation, DefaultSessionRewinder } from "@wrongstack/core/storage";
|
|
296
|
-
import React9, { useCallback as
|
|
296
|
+
import React9, { useCallback as useCallback26, useEffect as useEffect68, useRef as useRef39 } from "react";
|
|
297
297
|
|
|
298
298
|
// src/hooks/use-terminal-size.ts
|
|
299
299
|
import { onResize } from "@wrongstack/core/utils";
|
|
@@ -1553,6 +1553,7 @@ function RightSidebar({ width, maxHeight, focused = false, children }) {
|
|
|
1553
1553
|
|
|
1554
1554
|
// src/ui-contracts.ts
|
|
1555
1555
|
var SIDEBAR_MISSION_ROWS = 8;
|
|
1556
|
+
var SETTINGS_PICKER_MAX_HEIGHT = 24;
|
|
1556
1557
|
var PANEL_POSITION_FIELD_START = 46;
|
|
1557
1558
|
var SIDEBAR_PANEL_LIMIT = 6;
|
|
1558
1559
|
var SIDEBAR_TWIN_MAX_WRAP_LINES = 10;
|
|
@@ -8063,10 +8064,10 @@ function MailboxPanel({
|
|
|
8063
8064
|
messages,
|
|
8064
8065
|
agents,
|
|
8065
8066
|
unreadCount,
|
|
8066
|
-
open
|
|
8067
|
+
open: open2
|
|
8067
8068
|
}) {
|
|
8068
8069
|
const { columns: termWidth } = useTerminalSize({ fallbackColumns: 90 });
|
|
8069
|
-
if (!
|
|
8070
|
+
if (!open2) return null;
|
|
8070
8071
|
const showMessages = messages.slice(0, 6);
|
|
8071
8072
|
const showAgents = agents.slice(0, 8);
|
|
8072
8073
|
const maxSubjectLen = Math.max(15, Math.min(30, termWidth - 55));
|
|
@@ -8412,10 +8413,10 @@ function PlanPanel({
|
|
|
8412
8413
|
setSelected((value) => Math.min(Math.max(0, items.length - 1), value + 1));
|
|
8413
8414
|
}
|
|
8414
8415
|
});
|
|
8415
|
-
const
|
|
8416
|
+
const open2 = items.filter((i) => i.status === "open");
|
|
8416
8417
|
const inProgress = items.filter((i) => i.status === "in_progress");
|
|
8417
8418
|
const done = items.filter((i) => i.status === "done");
|
|
8418
|
-
const ordered = useMemo5(() => [...inProgress, ...
|
|
8419
|
+
const ordered = useMemo5(() => [...inProgress, ...open2, ...done], [inProgress, open2, done]);
|
|
8419
8420
|
useEffect11(() => {
|
|
8420
8421
|
setSelected((value) => Math.min(Math.max(0, ordered.length - 1), value));
|
|
8421
8422
|
}, [ordered.length]);
|
|
@@ -8468,7 +8469,7 @@ function PlanPanel({
|
|
|
8468
8469
|
] }),
|
|
8469
8470
|
/* @__PURE__ */ jsxs19(Text, { color: theme.textMuted, children: [
|
|
8470
8471
|
" \u25CB ",
|
|
8471
|
-
|
|
8472
|
+
open2.length
|
|
8472
8473
|
] }),
|
|
8473
8474
|
updatedAt && size.columns >= 105 ? /* @__PURE__ */ jsxs19(Text, { color: theme.textMuted, children: [
|
|
8474
8475
|
" updated ",
|
|
@@ -11787,8 +11788,8 @@ function detectLang(fenceInfo) {
|
|
|
11787
11788
|
const tag = fenceInfo.trim().toLowerCase().split(/\s+/)[0] ?? "";
|
|
11788
11789
|
return LANG_ALIASES[tag] ?? "plain";
|
|
11789
11790
|
}
|
|
11790
|
-
function langFromPath(
|
|
11791
|
-
const m = /\.([A-Za-z0-9]+)$/.exec(
|
|
11791
|
+
function langFromPath(path12) {
|
|
11792
|
+
const m = /\.([A-Za-z0-9]+)$/.exec(path12.trim());
|
|
11792
11793
|
const ext = m?.[1]?.toLowerCase() ?? "";
|
|
11793
11794
|
return LANG_ALIASES[ext] ?? "plain";
|
|
11794
11795
|
}
|
|
@@ -12239,13 +12240,13 @@ function visualWorkBoard(toolName, text, ok) {
|
|
|
12239
12240
|
function boardSummaryRows(toolName, fields, ok) {
|
|
12240
12241
|
const success = fields["ok"] !== "false" && ok;
|
|
12241
12242
|
const count = numberFromParsedField(fields, "count");
|
|
12242
|
-
const
|
|
12243
|
+
const open2 = numberFromParsedField(fields, "open");
|
|
12243
12244
|
const completed = numberFromParsedField(fields, "completed");
|
|
12244
12245
|
const inProgress = numberFromParsedField(fields, "inProgress") ?? numberFromParsedField(fields, "in_progress");
|
|
12245
12246
|
const parts = [
|
|
12246
12247
|
toolName,
|
|
12247
12248
|
count !== void 0 ? `${count} item${count === 1 ? "" : "s"}` : void 0,
|
|
12248
|
-
|
|
12249
|
+
open2 !== void 0 ? `${open2} open` : void 0,
|
|
12249
12250
|
completed !== void 0 ? `${completed} done` : void 0,
|
|
12250
12251
|
inProgress !== void 0 && inProgress > 0 ? `${inProgress} in progress` : void 0
|
|
12251
12252
|
].filter(Boolean);
|
|
@@ -13079,19 +13080,19 @@ function formatToolArgs(toolName, input) {
|
|
|
13079
13080
|
case "codebase-stats":
|
|
13080
13081
|
return "index health";
|
|
13081
13082
|
case "lsp_diagnostics": {
|
|
13082
|
-
const
|
|
13083
|
+
const path12 = stringOf(obj["path"]);
|
|
13083
13084
|
const severity = stringArrayOf(obj["severity"]) ?? stringArrayOf(obj["severities"]);
|
|
13084
|
-
return [
|
|
13085
|
+
return [path12 ? shortenPath(path12, 40) : "workspace", severity?.join("+")].filter(Boolean).join(" \xB7 ");
|
|
13085
13086
|
}
|
|
13086
13087
|
case "lsp_definition":
|
|
13087
13088
|
case "lsp_completion":
|
|
13088
13089
|
case "lsp_rename": {
|
|
13089
|
-
const
|
|
13090
|
+
const path12 = stringOf(obj["path"]) ?? stringOf(obj["file"]);
|
|
13090
13091
|
const line = numOf(obj["line"]);
|
|
13091
13092
|
const character = numOf(obj["character"]);
|
|
13092
13093
|
const position = line !== void 0 ? `L${line}:${character ?? 1}` : "";
|
|
13093
13094
|
const rename = toolName === "lsp_rename" ? stringOf(obj["new_name"]) : void 0;
|
|
13094
|
-
return [
|
|
13095
|
+
return [path12 ? shortenPath(path12, 38) : "", position, rename ? `\u2192 ${rename}` : ""].filter(Boolean).join(" \xB7 ");
|
|
13095
13096
|
}
|
|
13096
13097
|
case "set_working_dir": {
|
|
13097
13098
|
const p = stringOf(obj["path"]);
|
|
@@ -13534,19 +13535,19 @@ function visualEdit(toolName, text, ok) {
|
|
|
13534
13535
|
const parsed = tryParseJson(text);
|
|
13535
13536
|
if (parsed && typeof parsed === "object") {
|
|
13536
13537
|
const obj = parsed;
|
|
13537
|
-
const
|
|
13538
|
+
const path12 = typeof obj["path"] === "string" ? obj["path"] : void 0;
|
|
13538
13539
|
const replacements = typeof obj["replacements"] === "number" ? obj["replacements"] : void 0;
|
|
13539
13540
|
const bytes = typeof obj["bytes"] === "number" ? obj["bytes"] : void 0;
|
|
13540
13541
|
const created = obj["created"] === true;
|
|
13541
13542
|
const files = Array.isArray(obj["files"]) ? obj["files"] : void 0;
|
|
13542
13543
|
const results = Array.isArray(obj["results"]) ? obj["results"] : void 0;
|
|
13543
|
-
if (toolName === "edit" &&
|
|
13544
|
+
if (toolName === "edit" && path12 !== void 0) {
|
|
13544
13545
|
const repText = replacements !== void 0 ? `${replacements} replacement${replacements === 1 ? "" : "s"}` : void 0;
|
|
13545
|
-
rows.push({ kind: "ok", text: "", marker: "edit ", path:
|
|
13546
|
+
rows.push({ kind: "ok", text: "", marker: "edit ", path: path12 });
|
|
13546
13547
|
if (repText) rows.push({ kind: "meta", text: repText });
|
|
13547
|
-
} else if (toolName === "write" &&
|
|
13548
|
+
} else if (toolName === "write" && path12 !== void 0) {
|
|
13548
13549
|
const sizeText = bytes !== void 0 ? `${bytes} bytes` : created ? "new file" : "updated";
|
|
13549
|
-
rows.push({ kind: "ok", text: "", marker: "write ", path:
|
|
13550
|
+
rows.push({ kind: "ok", text: "", marker: "write ", path: path12 });
|
|
13550
13551
|
rows.push({ kind: "meta", text: sizeText });
|
|
13551
13552
|
} else if ((toolName === "diff" || toolName === "patch") && files && files.length > 0) {
|
|
13552
13553
|
rows.push({
|
|
@@ -13569,8 +13570,8 @@ function visualEdit(toolName, text, ok) {
|
|
|
13569
13570
|
marker: "replace ",
|
|
13570
13571
|
text: `${results.length} replacement${results.length === 1 ? "" : "s"} across ${fileCount} file${fileCount === 1 ? "" : "s"}`
|
|
13571
13572
|
});
|
|
13572
|
-
} else if (
|
|
13573
|
-
rows.push({ kind: "ok", text: "", marker: `${toolName} `, path:
|
|
13573
|
+
} else if (path12 !== void 0) {
|
|
13574
|
+
rows.push({ kind: "ok", text: "", marker: `${toolName} `, path: path12 });
|
|
13574
13575
|
} else {
|
|
13575
13576
|
return void 0;
|
|
13576
13577
|
}
|
|
@@ -13664,12 +13665,12 @@ function parseMatchHit(hit) {
|
|
|
13664
13665
|
}
|
|
13665
13666
|
if (hit && typeof hit === "object") {
|
|
13666
13667
|
const o = hit;
|
|
13667
|
-
const
|
|
13668
|
+
const path12 = stringOf(o["file"]) ?? stringOf(o["path"]) ?? stringOf(o["url"]);
|
|
13668
13669
|
const line = numOf(o["line"]) ?? numOf(o["lineNumber"]);
|
|
13669
13670
|
const title = stringOf(o["title"]);
|
|
13670
13671
|
const snippet2 = stringOf(o["snippet"]);
|
|
13671
13672
|
const text = stringOf(o["text"]) ?? stringOf(o["match"]) ?? stringOf(o["preview"]) ?? [title, snippet2].filter(Boolean).join(" \u2014 ");
|
|
13672
|
-
return { path:
|
|
13673
|
+
return { path: path12, line: line === void 0 ? void 0 : String(line), text };
|
|
13673
13674
|
}
|
|
13674
13675
|
return void 0;
|
|
13675
13676
|
}
|
|
@@ -13767,8 +13768,8 @@ function splitReplaceDiffs(obj) {
|
|
|
13767
13768
|
const record = result;
|
|
13768
13769
|
const diff = stringOf(record["diff"]);
|
|
13769
13770
|
if (!diff?.trim()) continue;
|
|
13770
|
-
const
|
|
13771
|
-
items.push(
|
|
13771
|
+
const path12 = stringOf(record["path"]);
|
|
13772
|
+
items.push(path12 ? { path: path12, diff } : { diff });
|
|
13772
13773
|
}
|
|
13773
13774
|
return items;
|
|
13774
13775
|
}
|
|
@@ -13843,8 +13844,8 @@ function collectMultiFileDiffItems(toolName, output, _input) {
|
|
|
13843
13844
|
if (!diffText?.trim()) return void 0;
|
|
13844
13845
|
const blocks = splitGitStyleDiff(diffText);
|
|
13845
13846
|
if (blocks.length === 0) {
|
|
13846
|
-
const
|
|
13847
|
-
return [{ path:
|
|
13847
|
+
const path12 = explicitFiles[0] ?? extractPatchHeaderPath(diffText);
|
|
13848
|
+
return [{ path: path12, diff: diffText }];
|
|
13848
13849
|
}
|
|
13849
13850
|
return blocks.map((block, idx) => ({
|
|
13850
13851
|
path: explicitFiles[idx] ?? block.path,
|
|
@@ -13878,9 +13879,9 @@ function newFileDiffFromWriteInput(output, input) {
|
|
|
13878
13879
|
const obj = input;
|
|
13879
13880
|
const content = stringOf(obj["content"]);
|
|
13880
13881
|
if (content === void 0) return void 0;
|
|
13881
|
-
const
|
|
13882
|
+
const path12 = stringOf(output["path"]) ?? stringOf(obj["path"]) ?? "new file";
|
|
13882
13883
|
const lines = content === "" ? [] : content.replace(/\n$/, "").split("\n");
|
|
13883
|
-
const header = [`+++ ${
|
|
13884
|
+
const header = [`+++ ${path12}`, `@@ -0,0 +1,${lines.length} @@`];
|
|
13884
13885
|
return [...header, ...lines.map((line) => `+${line}`)].join("\n");
|
|
13885
13886
|
}
|
|
13886
13887
|
function splitGitStyleDiff(diff) {
|
|
@@ -13920,8 +13921,8 @@ function splitGitStyleDiff(diff) {
|
|
|
13920
13921
|
}
|
|
13921
13922
|
flush();
|
|
13922
13923
|
if (blocks.length === 1 && !blocks[0].path) {
|
|
13923
|
-
const
|
|
13924
|
-
if (
|
|
13924
|
+
const path12 = extractPatchHeaderPath(blocks[0].diff);
|
|
13925
|
+
if (path12) blocks[0] = { path: path12, diff: blocks[0].diff };
|
|
13925
13926
|
}
|
|
13926
13927
|
return blocks;
|
|
13927
13928
|
}
|
|
@@ -13942,8 +13943,8 @@ function parseDiffGitPath(line) {
|
|
|
13942
13943
|
function extractPatchHeaderPath(diffText) {
|
|
13943
13944
|
for (const line of diffText.split("\n")) {
|
|
13944
13945
|
if (line.startsWith("+++ ")) {
|
|
13945
|
-
const
|
|
13946
|
-
const cleaned =
|
|
13946
|
+
const path12 = line.slice(4).trim();
|
|
13947
|
+
const cleaned = path12.replace(/^b\//, "").split(" ")[0].trim();
|
|
13947
13948
|
return cleaned || void 0;
|
|
13948
13949
|
}
|
|
13949
13950
|
}
|
|
@@ -14075,13 +14076,13 @@ function formatMultiDiffSummary(summary, threshold = MULTI_DIFF_SUMMARY_THRESHOL
|
|
|
14075
14076
|
return parts.join(" \xB7 ");
|
|
14076
14077
|
}
|
|
14077
14078
|
function DiffFileBlock({
|
|
14078
|
-
path:
|
|
14079
|
+
path: path12,
|
|
14079
14080
|
preview,
|
|
14080
14081
|
useColor = true,
|
|
14081
14082
|
contentWidth
|
|
14082
14083
|
}) {
|
|
14083
14084
|
return /* @__PURE__ */ jsxs37(Box, { flexDirection: "column", marginTop: 1, children: [
|
|
14084
|
-
/* @__PURE__ */ jsx38(Text, { dimColor: true, italic: true, children:
|
|
14085
|
+
/* @__PURE__ */ jsx38(Text, { dimColor: true, italic: true, children: path12 }),
|
|
14085
14086
|
/* @__PURE__ */ jsx38(
|
|
14086
14087
|
DiffBlock,
|
|
14087
14088
|
{
|
|
@@ -14092,7 +14093,7 @@ function DiffFileBlock({
|
|
|
14092
14093
|
hiddenAdded: preview.hiddenAdded,
|
|
14093
14094
|
hiddenRemoved: preview.hiddenRemoved,
|
|
14094
14095
|
useColor,
|
|
14095
|
-
lang: langFromPath(
|
|
14096
|
+
lang: langFromPath(path12),
|
|
14096
14097
|
contentWidth
|
|
14097
14098
|
}
|
|
14098
14099
|
)
|
|
@@ -14367,7 +14368,7 @@ function renderDiffLine(line) {
|
|
|
14367
14368
|
"\n"
|
|
14368
14369
|
] }, line);
|
|
14369
14370
|
}
|
|
14370
|
-
function renderDiff(diff,
|
|
14371
|
+
function renderDiff(diff, path12) {
|
|
14371
14372
|
const preview = parseUnifiedDiff(diff, CONFIRM_DIFF_MAX_LINES);
|
|
14372
14373
|
if (preview.rows.length > 0) {
|
|
14373
14374
|
return /* @__PURE__ */ jsx39(
|
|
@@ -14380,7 +14381,7 @@ function renderDiff(diff, path10) {
|
|
|
14380
14381
|
hiddenAdded: preview.hiddenAdded,
|
|
14381
14382
|
hiddenRemoved: preview.hiddenRemoved,
|
|
14382
14383
|
useColor: theme.supportsBackground,
|
|
14383
|
-
lang: langFromPath(
|
|
14384
|
+
lang: langFromPath(path12 ?? "")
|
|
14384
14385
|
}
|
|
14385
14386
|
);
|
|
14386
14387
|
}
|
|
@@ -15501,8 +15502,8 @@ function FilePicker({ query, matches, selected }) {
|
|
|
15501
15502
|
] }, m))
|
|
15502
15503
|
] });
|
|
15503
15504
|
}
|
|
15504
|
-
function highlight(
|
|
15505
|
-
return
|
|
15505
|
+
function highlight(path12, _query) {
|
|
15506
|
+
return path12;
|
|
15506
15507
|
}
|
|
15507
15508
|
|
|
15508
15509
|
// src/components/help-panel.tsx
|
|
@@ -19774,15 +19775,15 @@ var Entry = React4.memo(function Entry2({
|
|
|
19774
19775
|
const outObj = outJson && typeof outJson === "object" ? outJson : void 0;
|
|
19775
19776
|
const created = name === "write" && (outObj?.["created"] === true || /^[^\n]*\bcreated=true\b/.test(outputForFormatting));
|
|
19776
19777
|
const verb = created ? "Write" : "Update";
|
|
19777
|
-
const
|
|
19778
|
+
const path12 = stringOf(inputObj?.["path"]) ?? stringOf(outObj?.["path"]);
|
|
19778
19779
|
const agg = multiDiffs2 ? summarizeMultiFileDiffs(multiDiffs2) : void 0;
|
|
19779
|
-
const target = multiDiffs2 ? agg?.fileCount === 1 ? multiDiffs2[0].path : `${agg?.fileCount ?? multiDiffs2.length} files` :
|
|
19780
|
+
const target = multiDiffs2 ? agg?.fileCount === 1 ? multiDiffs2[0].path : `${agg?.fileCount ?? multiDiffs2.length} files` : path12 ?? "file";
|
|
19780
19781
|
return {
|
|
19781
19782
|
verb,
|
|
19782
19783
|
target,
|
|
19783
19784
|
added: agg ? agg.added : diff2?.added ?? 0,
|
|
19784
19785
|
removed: agg ? agg.removed : diff2?.removed ?? 0,
|
|
19785
|
-
lang: langFromPath(multiDiffs2 ? "" :
|
|
19786
|
+
lang: langFromPath(multiDiffs2 ? "" : path12 ?? "")
|
|
19786
19787
|
};
|
|
19787
19788
|
})();
|
|
19788
19789
|
return {
|
|
@@ -22479,7 +22480,10 @@ function SettingsPicker({
|
|
|
22479
22480
|
const bottomChromeRows = statuslineMode === "detailed" ? 5 : 2;
|
|
22480
22481
|
const BORDER_ROWS = 2;
|
|
22481
22482
|
const BASE_CHROME_ROWS = contentWidth < 64 ? 4 : 3;
|
|
22482
|
-
const pickerHeight = Math.
|
|
22483
|
+
const pickerHeight = Math.min(
|
|
22484
|
+
SETTINGS_PICKER_MAX_HEIGHT,
|
|
22485
|
+
Math.max(BORDER_ROWS, termRows - INPUT_ROWS - bottomChromeRows)
|
|
22486
|
+
);
|
|
22483
22487
|
const innerHeight = pickerHeight - BORDER_ROWS;
|
|
22484
22488
|
const totalFields = fieldRowIndex.length;
|
|
22485
22489
|
const sectionFieldStarts = deriveSettingsSectionFieldStarts(fieldRowIndex);
|
|
@@ -32094,7 +32098,7 @@ var LayoutStore = class {
|
|
|
32094
32098
|
const filePath = path2.join(this.sessionDataDir, LAYOUT_FILENAME);
|
|
32095
32099
|
let raw;
|
|
32096
32100
|
try {
|
|
32097
|
-
raw = await import("node:fs/promises").then((
|
|
32101
|
+
raw = await import("node:fs/promises").then((fs6) => fs6.readFile(filePath, "utf8"));
|
|
32098
32102
|
} catch {
|
|
32099
32103
|
return 0;
|
|
32100
32104
|
}
|
|
@@ -32133,12 +32137,12 @@ var LayoutStore = class {
|
|
|
32133
32137
|
};
|
|
32134
32138
|
const filePath = path2.join(this.sessionDataDir, LAYOUT_FILENAME);
|
|
32135
32139
|
try {
|
|
32136
|
-
const
|
|
32140
|
+
const fs6 = await import("node:fs/promises");
|
|
32137
32141
|
const dir = path2.dirname(filePath);
|
|
32138
|
-
await
|
|
32142
|
+
await fs6.mkdir(dir, { recursive: true });
|
|
32139
32143
|
const tmp = path2.join(dir, `.${path2.basename(filePath)}.${Date.now().toString(36)}.tmp`);
|
|
32140
|
-
await
|
|
32141
|
-
await
|
|
32144
|
+
await fs6.writeFile(tmp, JSON.stringify(snapshot, null, 2), "utf8");
|
|
32145
|
+
await fs6.rename(tmp, filePath);
|
|
32142
32146
|
} catch {
|
|
32143
32147
|
}
|
|
32144
32148
|
}
|
|
@@ -32228,7 +32232,7 @@ var OAUTH_TITLE = {
|
|
|
32228
32232
|
copilot: "Sign in with GitHub Copilot"
|
|
32229
32233
|
};
|
|
32230
32234
|
function useAuthPanel(opts) {
|
|
32231
|
-
const { authHost, stateRef, dispatch, open } = opts;
|
|
32235
|
+
const { authHost, stateRef, dispatch, open: open2 } = opts;
|
|
32232
32236
|
const flowAbortRef = useRef11(null);
|
|
32233
32237
|
const standaloneSecretRef = useRef11(false);
|
|
32234
32238
|
const promptRef = useRef11(null);
|
|
@@ -32249,8 +32253,8 @@ function useAuthPanel(opts) {
|
|
|
32249
32253
|
};
|
|
32250
32254
|
}, [abortLiveFlow]);
|
|
32251
32255
|
useEffect28(() => {
|
|
32252
|
-
if (!
|
|
32253
|
-
}, [
|
|
32256
|
+
if (!open2) abortLiveFlow();
|
|
32257
|
+
}, [open2, abortLiveFlow]);
|
|
32254
32258
|
const reloadProviders = useCallback7(async () => {
|
|
32255
32259
|
if (!authHost || !mountedRef.current) return;
|
|
32256
32260
|
try {
|
|
@@ -34952,6 +34956,45 @@ function renderList2() {
|
|
|
34952
34956
|
return lines.join("\n");
|
|
34953
34957
|
}
|
|
34954
34958
|
|
|
34959
|
+
// src/slash-command-lifecycle.ts
|
|
34960
|
+
function registerSlashCommandLifecycle(registry, command, options = {}) {
|
|
34961
|
+
const owner = options.owner ?? "core";
|
|
34962
|
+
const displaced = /* @__PURE__ */ new Map();
|
|
34963
|
+
for (const key of [command.name, ...command.aliases ?? []]) {
|
|
34964
|
+
const previous = registry.get(key);
|
|
34965
|
+
const previousOwner = registry.ownerOf(key);
|
|
34966
|
+
if (previous && previousOwner && previous !== command && !displaced.has(previous)) {
|
|
34967
|
+
displaced.set(previous, { command: previous, owner: previousOwner });
|
|
34968
|
+
}
|
|
34969
|
+
}
|
|
34970
|
+
registry.register(command, owner, { official: options.official });
|
|
34971
|
+
const namespacedName = owner === "core" ? null : `${owner}:${command.name}`;
|
|
34972
|
+
let cleaned = false;
|
|
34973
|
+
return () => {
|
|
34974
|
+
if (cleaned) return;
|
|
34975
|
+
cleaned = true;
|
|
34976
|
+
const ownsBareName = registry.get(command.name) === command;
|
|
34977
|
+
const ownsNamespace = namespacedName !== null && registry.get(namespacedName) === command;
|
|
34978
|
+
if (ownsBareName) registry.unregister(command.name);
|
|
34979
|
+
else if (ownsNamespace && namespacedName) registry.unregister(namespacedName);
|
|
34980
|
+
else return;
|
|
34981
|
+
for (const registration of displaced.values()) {
|
|
34982
|
+
const keys = [registration.command.name, ...registration.command.aliases ?? []];
|
|
34983
|
+
if (keys.some((key) => {
|
|
34984
|
+
const current = registry.get(key);
|
|
34985
|
+
return current !== void 0 && current !== registration.command;
|
|
34986
|
+
})) {
|
|
34987
|
+
continue;
|
|
34988
|
+
}
|
|
34989
|
+
registry.register(
|
|
34990
|
+
registration.command,
|
|
34991
|
+
registration.owner,
|
|
34992
|
+
registration.owner === "core" ? void 0 : { official: true }
|
|
34993
|
+
);
|
|
34994
|
+
}
|
|
34995
|
+
};
|
|
34996
|
+
}
|
|
34997
|
+
|
|
34955
34998
|
// src/steering-preamble.ts
|
|
34956
34999
|
function buildSteeringPreamble(snapshot, newDirection) {
|
|
34957
35000
|
const lines = ["[STEERING \u2014 I pressed Esc to interrupt you mid-task on purpose.", ""];
|
|
@@ -35012,67 +35055,69 @@ function useCoreTuiCommands({
|
|
|
35012
35055
|
const stdout = { columns: terminalWidth };
|
|
35013
35056
|
const getCronJobs = useMemo10(() => createCronJobsGetter(agent), [agent]);
|
|
35014
35057
|
useEffect33(() => {
|
|
35015
|
-
|
|
35016
|
-
|
|
35017
|
-
|
|
35058
|
+
const cleanups = [];
|
|
35059
|
+
cleanups.push(registerSlashCommandLifecycle(slashRegistry, createKillSlashCommand()));
|
|
35060
|
+
cleanups.push(registerSlashCommandLifecycle(slashRegistry, createPsSlashCommand()));
|
|
35061
|
+
cleanups.push(
|
|
35062
|
+
registerSlashCommandLifecycle(slashRegistry, createCronSlashCommand({ getCronJobs }))
|
|
35063
|
+
);
|
|
35018
35064
|
if (memoryStore) {
|
|
35019
|
-
|
|
35065
|
+
cleanups.push(
|
|
35066
|
+
registerSlashCommandLifecycle(
|
|
35067
|
+
slashRegistry,
|
|
35068
|
+
createMemorySlashCommand({ memoryStore })
|
|
35069
|
+
)
|
|
35070
|
+
);
|
|
35020
35071
|
}
|
|
35021
|
-
|
|
35022
|
-
|
|
35023
|
-
|
|
35024
|
-
|
|
35025
|
-
|
|
35026
|
-
|
|
35027
|
-
|
|
35028
|
-
|
|
35029
|
-
|
|
35030
|
-
|
|
35031
|
-
|
|
35032
|
-
|
|
35033
|
-
|
|
35034
|
-
|
|
35035
|
-
|
|
35036
|
-
|
|
35037
|
-
memoryPending: memories.filter((memory) => memory.state === "injected").length,
|
|
35038
|
-
memoryLeft: memories.filter((memory) => memory.state === "exited").length
|
|
35039
|
-
};
|
|
35040
|
-
}
|
|
35041
|
-
});
|
|
35042
|
-
contextPanelCmd.__panelWrapper = true;
|
|
35043
|
-
slashRegistry.register(contextPanelCmd);
|
|
35072
|
+
const existingContext = slashRegistry.get("context");
|
|
35073
|
+
const contextPanelCmd = createContextSlashCommand({
|
|
35074
|
+
onPanelOpen,
|
|
35075
|
+
fallback: existingContext,
|
|
35076
|
+
getSummary: () => {
|
|
35077
|
+
const leader = stateRef.current.leader;
|
|
35078
|
+
const memories = Object.values(memoryContextMonitorRef.current.memories);
|
|
35079
|
+
return {
|
|
35080
|
+
contextPct: leader.ctxPct,
|
|
35081
|
+
contextTokens: leader.ctxTokens,
|
|
35082
|
+
contextMaxTokens: leader.ctxMaxTokens,
|
|
35083
|
+
memoryTotal: memoryRecordTotalRef.current,
|
|
35084
|
+
memoryCtx: memories.filter((memory) => memory.state === "active").length,
|
|
35085
|
+
memoryPending: memories.filter((memory) => memory.state === "injected").length,
|
|
35086
|
+
memoryLeft: memories.filter((memory) => memory.state === "exited").length
|
|
35087
|
+
};
|
|
35044
35088
|
}
|
|
35045
|
-
}
|
|
35046
|
-
|
|
35047
|
-
|
|
35048
|
-
|
|
35049
|
-
|
|
35050
|
-
createKanbanSlashCommand({
|
|
35051
|
-
projectRoot: agent.ctx.projectRoot,
|
|
35052
|
-
sessionId: agent.ctx.session?.id ?? null,
|
|
35053
|
-
onPanelOpen,
|
|
35054
|
-
// Goal → Kanban bridge & `/kanban use <boardId>` both arrive here.
|
|
35055
|
-
// We capture a `focusedBoardId` and pass it down as `initialBoardId`
|
|
35056
|
-
// so the panel lands on the requested board rather than defaulting
|
|
35057
|
-
// to the session-tag fallback.
|
|
35058
|
-
onBoardFocus: boardFocusRef.current ? boardFocusRef.current : {
|
|
35059
|
-
current: (boardId) => {
|
|
35060
|
-
setFocusedBoardId(boardId);
|
|
35061
|
-
return true;
|
|
35062
|
-
}
|
|
35063
|
-
},
|
|
35064
|
-
terminalWidth: stdout.columns ?? 80
|
|
35089
|
+
});
|
|
35090
|
+
cleanups.push(
|
|
35091
|
+
registerSlashCommandLifecycle(slashRegistry, contextPanelCmd, {
|
|
35092
|
+
owner: "tui",
|
|
35093
|
+
official: true
|
|
35065
35094
|
})
|
|
35066
35095
|
);
|
|
35096
|
+
cleanups.push(
|
|
35097
|
+
registerSlashCommandLifecycle(
|
|
35098
|
+
slashRegistry,
|
|
35099
|
+
createConnectionsSlashCommand({ onPanelOpen })
|
|
35100
|
+
)
|
|
35101
|
+
);
|
|
35102
|
+
cleanups.push(
|
|
35103
|
+
registerSlashCommandLifecycle(
|
|
35104
|
+
slashRegistry,
|
|
35105
|
+
createKanbanSlashCommand({
|
|
35106
|
+
projectRoot: agent.ctx.projectRoot,
|
|
35107
|
+
sessionId: agent.ctx.session?.id ?? null,
|
|
35108
|
+
onPanelOpen,
|
|
35109
|
+
onBoardFocus: boardFocusRef.current ? boardFocusRef.current : {
|
|
35110
|
+
current: (boardId) => {
|
|
35111
|
+
setFocusedBoardId(boardId);
|
|
35112
|
+
return true;
|
|
35113
|
+
}
|
|
35114
|
+
},
|
|
35115
|
+
terminalWidth: stdout.columns ?? 80
|
|
35116
|
+
})
|
|
35117
|
+
)
|
|
35118
|
+
);
|
|
35067
35119
|
return () => {
|
|
35068
|
-
|
|
35069
|
-
slashRegistry.unregister("ps");
|
|
35070
|
-
slashRegistry.unregister("cron");
|
|
35071
|
-
if (memoryStore) {
|
|
35072
|
-
slashRegistry.unregister("memory");
|
|
35073
|
-
}
|
|
35074
|
-
slashRegistry.unregister("context");
|
|
35075
|
-
slashRegistry.unregister("kanban");
|
|
35120
|
+
for (const cleanup of cleanups.reverse()) cleanup();
|
|
35076
35121
|
};
|
|
35077
35122
|
}, [
|
|
35078
35123
|
slashRegistry,
|
|
@@ -35143,10 +35188,7 @@ function useCoreTuiCommands({
|
|
|
35143
35188
|
};
|
|
35144
35189
|
}
|
|
35145
35190
|
};
|
|
35146
|
-
slashRegistry
|
|
35147
|
-
return () => {
|
|
35148
|
-
slashRegistry.unregister("steer");
|
|
35149
|
-
};
|
|
35191
|
+
return registerSlashCommandLifecycle(slashRegistry, cmd);
|
|
35150
35192
|
}, [slashRegistry, director, runSteerSequence]);
|
|
35151
35193
|
useEffect33(() => {
|
|
35152
35194
|
const cmd = {
|
|
@@ -35180,29 +35222,29 @@ function useCoreTuiCommands({
|
|
|
35180
35222
|
return {};
|
|
35181
35223
|
}
|
|
35182
35224
|
};
|
|
35183
|
-
slashRegistry
|
|
35184
|
-
return () => {
|
|
35185
|
-
slashRegistry.unregister("rewind");
|
|
35186
|
-
};
|
|
35225
|
+
return registerSlashCommandLifecycle(slashRegistry, cmd);
|
|
35187
35226
|
}, [slashRegistry, handleRewindTo]);
|
|
35188
35227
|
useEffect33(() => {
|
|
35228
|
+
const original = slashRegistry.get("agents");
|
|
35189
35229
|
const cmd = {
|
|
35190
35230
|
name: "agents",
|
|
35191
|
-
description: "Toggle the agents monitor overlay.",
|
|
35192
|
-
|
|
35231
|
+
description: original?.description ?? "Toggle the agents monitor overlay.",
|
|
35232
|
+
argsHint: original?.argsHint,
|
|
35233
|
+
help: original?.help,
|
|
35234
|
+
async run(args, ctx) {
|
|
35193
35235
|
const arg = args.trim().toLowerCase();
|
|
35194
35236
|
if (!arg || arg === "monitor") {
|
|
35195
35237
|
dispatch({ type: "toggleAgentsMonitor" });
|
|
35196
35238
|
return { message: void 0 };
|
|
35197
35239
|
}
|
|
35198
|
-
return { message:
|
|
35240
|
+
return original?.run(args, ctx) ?? { message: "/agents is unavailable." };
|
|
35199
35241
|
}
|
|
35200
35242
|
};
|
|
35201
|
-
slashRegistry
|
|
35202
|
-
|
|
35203
|
-
|
|
35204
|
-
};
|
|
35205
|
-
}, [slashRegistry]);
|
|
35243
|
+
return registerSlashCommandLifecycle(slashRegistry, cmd, {
|
|
35244
|
+
owner: "tui",
|
|
35245
|
+
official: true
|
|
35246
|
+
});
|
|
35247
|
+
}, [slashRegistry, dispatch]);
|
|
35206
35248
|
return { getCronJobs, runSteerSequence };
|
|
35207
35249
|
}
|
|
35208
35250
|
|
|
@@ -35983,6 +36025,7 @@ async function searchFiles(root, query, limit = 8) {
|
|
|
35983
36025
|
}
|
|
35984
36026
|
|
|
35985
36027
|
// src/hooks/use-file-search.ts
|
|
36028
|
+
var FILE_SEARCH_DEBOUNCE_MS = 150;
|
|
35986
36029
|
function detectAtToken(buffer, cursor) {
|
|
35987
36030
|
let i = cursor - 1;
|
|
35988
36031
|
while (i >= 0) {
|
|
@@ -36006,22 +36049,34 @@ function useFileSearch(options) {
|
|
|
36006
36049
|
if (state.picker.open) dispatch({ type: "pickerClose" });
|
|
36007
36050
|
return;
|
|
36008
36051
|
}
|
|
36009
|
-
|
|
36052
|
+
const justOpened = !state.picker.open;
|
|
36053
|
+
if (justOpened || state.picker.query !== detected.query) {
|
|
36010
36054
|
dispatch({ type: "pickerOpen", query: detected.query });
|
|
36011
36055
|
}
|
|
36012
36056
|
let cancelled = false;
|
|
36013
|
-
|
|
36014
|
-
|
|
36015
|
-
|
|
36016
|
-
|
|
36017
|
-
|
|
36057
|
+
const run = () => {
|
|
36058
|
+
searchFiles(projectRoot, detected.query, 8).then((matches) => {
|
|
36059
|
+
if (!cancelled) {
|
|
36060
|
+
dispatch({ type: "pickerSetMatches", query: detected.query, matches });
|
|
36061
|
+
}
|
|
36062
|
+
}).catch(() => void 0);
|
|
36063
|
+
};
|
|
36064
|
+
if (justOpened) {
|
|
36065
|
+
run();
|
|
36066
|
+
return () => {
|
|
36067
|
+
cancelled = true;
|
|
36068
|
+
};
|
|
36069
|
+
}
|
|
36070
|
+
const timer = setTimeout(run, FILE_SEARCH_DEBOUNCE_MS);
|
|
36071
|
+
timer.unref?.();
|
|
36018
36072
|
return () => {
|
|
36019
36073
|
cancelled = true;
|
|
36074
|
+
clearTimeout(timer);
|
|
36020
36075
|
};
|
|
36021
36076
|
}, [state.buffer, state.cursor, projectRoot]);
|
|
36022
36077
|
const acceptPickerSelection = async () => {
|
|
36023
|
-
const { open, matches, selected } = state.picker;
|
|
36024
|
-
if (!
|
|
36078
|
+
const { open: open2, matches, selected } = state.picker;
|
|
36079
|
+
if (!open2 || matches.length === 0) return;
|
|
36025
36080
|
const picked = matches[selected];
|
|
36026
36081
|
if (!picked) return;
|
|
36027
36082
|
const builder = builderRef.current;
|
|
@@ -36034,10 +36089,10 @@ function useFileSearch(options) {
|
|
|
36034
36089
|
}
|
|
36035
36090
|
const absPath = path4.isAbsolute(picked) ? picked : path4.join(projectRoot, picked);
|
|
36036
36091
|
try {
|
|
36037
|
-
const
|
|
36092
|
+
const stat4 = await fs3.stat(absPath);
|
|
36038
36093
|
let data;
|
|
36039
|
-
if (
|
|
36040
|
-
data = fileReadContract(picked,
|
|
36094
|
+
if (stat4.size > TEXT_FILE_ATTACHMENT_INLINE_MAX_BYTES) {
|
|
36095
|
+
data = fileReadContract(picked, stat4.size);
|
|
36041
36096
|
} else {
|
|
36042
36097
|
const inline = await fs3.readFile(absPath, "utf8");
|
|
36043
36098
|
const bytes = Buffer.byteLength(inline, "utf8");
|
|
@@ -36255,11 +36310,252 @@ function useHelpPanel(dispatch, slashRegistry) {
|
|
|
36255
36310
|
return { openHelpPanel };
|
|
36256
36311
|
}
|
|
36257
36312
|
|
|
36313
|
+
// src/hooks/use-history-archive.ts
|
|
36314
|
+
import * as fsp2 from "node:fs/promises";
|
|
36315
|
+
import * as path6 from "node:path";
|
|
36316
|
+
import { useCallback as useCallback14, useEffect as useEffect39, useRef as useRef20, useState as useState27 } from "react";
|
|
36317
|
+
|
|
36318
|
+
// src/history-archive.ts
|
|
36319
|
+
import * as fsp from "node:fs/promises";
|
|
36320
|
+
import * as path5 from "node:path";
|
|
36321
|
+
var ARCHIVE_PAGE_SIZE = 100;
|
|
36322
|
+
var HistoryArchive = class {
|
|
36323
|
+
filePath;
|
|
36324
|
+
handle = null;
|
|
36325
|
+
closed = false;
|
|
36326
|
+
/** Byte-offset index: index → { offset, length }. Built on first load. */
|
|
36327
|
+
index = null;
|
|
36328
|
+
/** Total entries written so far (monotonic counter). */
|
|
36329
|
+
// ── Write serialisation ──────────────────────────────────────────────
|
|
36330
|
+
writeChain = Promise.resolve();
|
|
36331
|
+
drainToken = null;
|
|
36332
|
+
constructor(sessionDir) {
|
|
36333
|
+
this.filePath = path5.join(sessionDir, "history-archive.jsonl");
|
|
36334
|
+
}
|
|
36335
|
+
/**
|
|
36336
|
+
* Append an entry to the archive. Fire-and-forget: the write is queued
|
|
36337
|
+
* on an internal promise chain so callers never block. Returns immediately.
|
|
36338
|
+
*/
|
|
36339
|
+
append(entry) {
|
|
36340
|
+
if (this.closed) return;
|
|
36341
|
+
const line = JSON.stringify(entry) + "\n";
|
|
36342
|
+
this.enqueueWrite(line);
|
|
36343
|
+
}
|
|
36344
|
+
/**
|
|
36345
|
+
* Load a range of entries by index. Indices are 0-based and sequential
|
|
36346
|
+
* across the entire file (index 0 = oldest archived entry).
|
|
36347
|
+
*
|
|
36348
|
+
* Returns the loaded entries in chronological order (oldest first).
|
|
36349
|
+
* When the range exceeds the available data, returns whatever fits.
|
|
36350
|
+
*/
|
|
36351
|
+
async loadRange(startIndex, count) {
|
|
36352
|
+
if (this.closed || count <= 0) return [];
|
|
36353
|
+
await this.buildIndex();
|
|
36354
|
+
if (!this.index) return [];
|
|
36355
|
+
const clampedStart = Math.max(0, startIndex);
|
|
36356
|
+
const clampedEnd = Math.min(clampedStart + count, this.index.length);
|
|
36357
|
+
if (clampedStart >= clampedEnd) return [];
|
|
36358
|
+
const handle = await this.ensureOpen();
|
|
36359
|
+
const slice = this.index.slice(clampedStart, clampedEnd);
|
|
36360
|
+
const entries = [];
|
|
36361
|
+
for (const slot of slice) {
|
|
36362
|
+
const buf = Buffer.allocUnsafe(slot.length);
|
|
36363
|
+
await handle.read(buf, 0, slot.length, slot.offset);
|
|
36364
|
+
const text = buf.toString("utf8").trim();
|
|
36365
|
+
if (!text) continue;
|
|
36366
|
+
try {
|
|
36367
|
+
const parsed = JSON.parse(text);
|
|
36368
|
+
entries.push(parsed);
|
|
36369
|
+
} catch {
|
|
36370
|
+
}
|
|
36371
|
+
}
|
|
36372
|
+
return entries;
|
|
36373
|
+
}
|
|
36374
|
+
/** How many entries are archived on disk. */
|
|
36375
|
+
get archivedCount() {
|
|
36376
|
+
return this.index?.length ?? 0;
|
|
36377
|
+
}
|
|
36378
|
+
/**
|
|
36379
|
+
* Close the file handle and release resources. Idempotent.
|
|
36380
|
+
* The write chain is drained before closing so no in-flight write
|
|
36381
|
+
* is lost.
|
|
36382
|
+
*/
|
|
36383
|
+
async close() {
|
|
36384
|
+
if (this.closed) return;
|
|
36385
|
+
this.closed = true;
|
|
36386
|
+
await this.writeChain;
|
|
36387
|
+
if (this.handle) {
|
|
36388
|
+
try {
|
|
36389
|
+
await this.handle.close();
|
|
36390
|
+
} catch {
|
|
36391
|
+
}
|
|
36392
|
+
this.handle = null;
|
|
36393
|
+
}
|
|
36394
|
+
}
|
|
36395
|
+
// ── Internals ────────────────────────────────────────────────────────
|
|
36396
|
+
async ensureOpen() {
|
|
36397
|
+
if (this.handle) return this.handle;
|
|
36398
|
+
await fsp.mkdir(path5.dirname(this.filePath), { recursive: true });
|
|
36399
|
+
this.handle = await fsp.open(this.filePath, "a+", 384);
|
|
36400
|
+
return this.handle;
|
|
36401
|
+
}
|
|
36402
|
+
/**
|
|
36403
|
+
* Build the byte-offset index by scanning the archive file.
|
|
36404
|
+
* Rebuilds when `this.index` is null (first use or after rotation).
|
|
36405
|
+
* The index is cached for the lifetime of the archive object.
|
|
36406
|
+
*/
|
|
36407
|
+
async buildIndex() {
|
|
36408
|
+
if (this.index !== null) return;
|
|
36409
|
+
const handle = await this.ensureOpen();
|
|
36410
|
+
const stat4 = await handle.stat();
|
|
36411
|
+
if (stat4.size === 0) {
|
|
36412
|
+
this.index = [];
|
|
36413
|
+
return;
|
|
36414
|
+
}
|
|
36415
|
+
const buf = Buffer.allocUnsafe(stat4.size);
|
|
36416
|
+
await handle.read(buf, 0, stat4.size, 0);
|
|
36417
|
+
const text = buf.toString("utf8");
|
|
36418
|
+
const lines = text.split("\n");
|
|
36419
|
+
const idx = [];
|
|
36420
|
+
let offset = 0;
|
|
36421
|
+
for (let i = 0; i < lines.length; i++) {
|
|
36422
|
+
const line = lines[i];
|
|
36423
|
+
const lineBytes = Buffer.byteLength(line, "utf8") + 1;
|
|
36424
|
+
if (line.trim().length === 0) {
|
|
36425
|
+
offset += lineBytes;
|
|
36426
|
+
continue;
|
|
36427
|
+
}
|
|
36428
|
+
idx.push({ index: idx.length, offset, length: lineBytes });
|
|
36429
|
+
offset += lineBytes;
|
|
36430
|
+
}
|
|
36431
|
+
this.index = idx;
|
|
36432
|
+
}
|
|
36433
|
+
/** Serialise writes through a FIFO promise chain with fresh-token coalescing. */
|
|
36434
|
+
enqueueWrite(line) {
|
|
36435
|
+
if (this.drainToken) {
|
|
36436
|
+
this.drainToken.buffer.push(line);
|
|
36437
|
+
return;
|
|
36438
|
+
}
|
|
36439
|
+
let resolve;
|
|
36440
|
+
const promise = new Promise((r) => {
|
|
36441
|
+
resolve = r;
|
|
36442
|
+
});
|
|
36443
|
+
this.drainToken = { buffer: [line], promise, resolve };
|
|
36444
|
+
const doWrite = async () => {
|
|
36445
|
+
const token = this.drainToken;
|
|
36446
|
+
this.drainToken = null;
|
|
36447
|
+
try {
|
|
36448
|
+
const batch = token.buffer.join("");
|
|
36449
|
+
const handle = await this.ensureOpen();
|
|
36450
|
+
await handle.appendFile(batch, "utf8");
|
|
36451
|
+
this.index = null;
|
|
36452
|
+
} catch {
|
|
36453
|
+
} finally {
|
|
36454
|
+
token.resolve();
|
|
36455
|
+
}
|
|
36456
|
+
};
|
|
36457
|
+
this.writeChain = this.writeChain.then(doWrite, doWrite);
|
|
36458
|
+
}
|
|
36459
|
+
};
|
|
36460
|
+
function historyArchivePath(sessionDir) {
|
|
36461
|
+
return path5.join(sessionDir, "history-archive.jsonl");
|
|
36462
|
+
}
|
|
36463
|
+
|
|
36464
|
+
// src/hooks/use-history-archive.ts
|
|
36465
|
+
function useHistoryArchive({
|
|
36466
|
+
entries,
|
|
36467
|
+
dispatch,
|
|
36468
|
+
sessionsDir,
|
|
36469
|
+
sessionId
|
|
36470
|
+
}) {
|
|
36471
|
+
const archiveRef = useRef20(null);
|
|
36472
|
+
const lastArchivedIdRef = useRef20(-1);
|
|
36473
|
+
const appendedCountRef = useRef20(0);
|
|
36474
|
+
const nextLoadEndRef = useRef20(null);
|
|
36475
|
+
const loadingRef = useRef20(false);
|
|
36476
|
+
const entriesRef = useRef20(entries);
|
|
36477
|
+
entriesRef.current = entries;
|
|
36478
|
+
const [archiveGeneration, setArchiveGeneration] = useState27(0);
|
|
36479
|
+
useEffect39(() => {
|
|
36480
|
+
if (!sessionsDir || !sessionId) return;
|
|
36481
|
+
let disposed = false;
|
|
36482
|
+
let created = null;
|
|
36483
|
+
const directory = path6.join(sessionsDir, sessionId);
|
|
36484
|
+
void (async () => {
|
|
36485
|
+
try {
|
|
36486
|
+
await fsp2.rm(historyArchivePath(directory), { force: true });
|
|
36487
|
+
} catch {
|
|
36488
|
+
return;
|
|
36489
|
+
}
|
|
36490
|
+
if (disposed) return;
|
|
36491
|
+
created = new HistoryArchive(directory);
|
|
36492
|
+
archiveRef.current = created;
|
|
36493
|
+
setArchiveGeneration((generation) => generation + 1);
|
|
36494
|
+
})();
|
|
36495
|
+
return () => {
|
|
36496
|
+
disposed = true;
|
|
36497
|
+
archiveRef.current = null;
|
|
36498
|
+
lastArchivedIdRef.current = -1;
|
|
36499
|
+
appendedCountRef.current = 0;
|
|
36500
|
+
nextLoadEndRef.current = null;
|
|
36501
|
+
void created?.close();
|
|
36502
|
+
};
|
|
36503
|
+
}, [sessionsDir, sessionId]);
|
|
36504
|
+
useEffect39(() => {
|
|
36505
|
+
const archive = archiveRef.current;
|
|
36506
|
+
if (!archive) return;
|
|
36507
|
+
const since = lastArchivedIdRef.current;
|
|
36508
|
+
let highest = since;
|
|
36509
|
+
let appended = 0;
|
|
36510
|
+
for (const entry of entries) {
|
|
36511
|
+
if (entry.id <= since) continue;
|
|
36512
|
+
archive.append(entry);
|
|
36513
|
+
appended++;
|
|
36514
|
+
if (entry.id > highest) highest = entry.id;
|
|
36515
|
+
}
|
|
36516
|
+
if (appended === 0) return;
|
|
36517
|
+
lastArchivedIdRef.current = highest;
|
|
36518
|
+
appendedCountRef.current += appended;
|
|
36519
|
+
}, [entries, archiveGeneration]);
|
|
36520
|
+
const onRequestOlderEntries = useCallback14(() => {
|
|
36521
|
+
if (loadingRef.current) return;
|
|
36522
|
+
const settleEmpty = () => {
|
|
36523
|
+
dispatch({ type: "startArchiveLoad" });
|
|
36524
|
+
dispatch({ type: "archiveLoaded", entries: [] });
|
|
36525
|
+
};
|
|
36526
|
+
const archive = archiveRef.current;
|
|
36527
|
+
if (!archive) {
|
|
36528
|
+
settleEmpty();
|
|
36529
|
+
return;
|
|
36530
|
+
}
|
|
36531
|
+
if (nextLoadEndRef.current === null) {
|
|
36532
|
+
nextLoadEndRef.current = Math.max(0, appendedCountRef.current - entriesRef.current.length);
|
|
36533
|
+
}
|
|
36534
|
+
const end = nextLoadEndRef.current;
|
|
36535
|
+
if (end <= 0) {
|
|
36536
|
+
settleEmpty();
|
|
36537
|
+
return;
|
|
36538
|
+
}
|
|
36539
|
+
const start = Math.max(0, end - ARCHIVE_PAGE_SIZE);
|
|
36540
|
+
loadingRef.current = true;
|
|
36541
|
+
dispatch({ type: "startArchiveLoad" });
|
|
36542
|
+
void archive.loadRange(start, end - start).then((loaded) => {
|
|
36543
|
+
nextLoadEndRef.current = start;
|
|
36544
|
+
dispatch({ type: "archiveLoaded", entries: loaded });
|
|
36545
|
+
}).catch(() => {
|
|
36546
|
+
dispatch({ type: "archiveLoaded", entries: [] });
|
|
36547
|
+
}).finally(() => {
|
|
36548
|
+
loadingRef.current = false;
|
|
36549
|
+
});
|
|
36550
|
+
}, [dispatch]);
|
|
36551
|
+
return { onRequestOlderEntries };
|
|
36552
|
+
}
|
|
36553
|
+
|
|
36258
36554
|
// src/hooks/use-history-copy-notice.ts
|
|
36259
|
-
import { useCallback as
|
|
36555
|
+
import { useCallback as useCallback15, useEffect as useEffect40, useRef as useRef21 } from "react";
|
|
36260
36556
|
function useHistoryCopyNotice(dispatch) {
|
|
36261
|
-
const copiedHintTimerRef =
|
|
36262
|
-
const onHistoryCopy =
|
|
36557
|
+
const copiedHintTimerRef = useRef21(null);
|
|
36558
|
+
const onHistoryCopy = useCallback15(
|
|
36263
36559
|
(entryId) => {
|
|
36264
36560
|
dispatch({ type: "copiedNotice", text: "\u2713 Copied", entryId });
|
|
36265
36561
|
if (copiedHintTimerRef.current) clearTimeout(copiedHintTimerRef.current);
|
|
@@ -36270,7 +36566,7 @@ function useHistoryCopyNotice(dispatch) {
|
|
|
36270
36566
|
},
|
|
36271
36567
|
[dispatch]
|
|
36272
36568
|
);
|
|
36273
|
-
|
|
36569
|
+
useEffect40(
|
|
36274
36570
|
() => () => {
|
|
36275
36571
|
if (copiedHintTimerRef.current) clearTimeout(copiedHintTimerRef.current);
|
|
36276
36572
|
},
|
|
@@ -36280,15 +36576,15 @@ function useHistoryCopyNotice(dispatch) {
|
|
|
36280
36576
|
}
|
|
36281
36577
|
|
|
36282
36578
|
// src/hooks/use-history-viewport-sync.ts
|
|
36283
|
-
import { useEffect as
|
|
36579
|
+
import { useEffect as useEffect41, useLayoutEffect as useLayoutEffect2, useRef as useRef22, useState as useState28 } from "react";
|
|
36284
36580
|
function useHistoryViewportSync(input) {
|
|
36285
36581
|
const { stdoutRows, viewportRows, setViewportRows } = input;
|
|
36286
|
-
const bottomRegionRef =
|
|
36287
|
-
const statusBarWrapRef =
|
|
36288
|
-
const belowStatusBarRef =
|
|
36289
|
-
const [termRows, setTermRows] =
|
|
36290
|
-
const [statusBarRows, setStatusBarRows] =
|
|
36291
|
-
|
|
36582
|
+
const bottomRegionRef = useRef22(null);
|
|
36583
|
+
const statusBarWrapRef = useRef22(null);
|
|
36584
|
+
const belowStatusBarRef = useRef22(null);
|
|
36585
|
+
const [termRows, setTermRows] = useState28(stdoutRows ?? 24);
|
|
36586
|
+
const [statusBarRows, setStatusBarRows] = useState28(2);
|
|
36587
|
+
useEffect41(() => {
|
|
36292
36588
|
const handleResize = () => setTermRows(process.stdout.rows ?? 24);
|
|
36293
36589
|
process.stdout.prependListener("resize", handleResize);
|
|
36294
36590
|
return () => {
|
|
@@ -36316,7 +36612,7 @@ function useHistoryViewportSync(input) {
|
|
|
36316
36612
|
|
|
36317
36613
|
// src/hooks/use-initial-prompt.ts
|
|
36318
36614
|
import { buildGoalPreamble } from "@wrongstack/core/execution";
|
|
36319
|
-
import { useEffect as
|
|
36615
|
+
import { useEffect as useEffect42, useRef as useRef23 } from "react";
|
|
36320
36616
|
function useInitialPrompt({
|
|
36321
36617
|
initialGoal,
|
|
36322
36618
|
initialAsk,
|
|
@@ -36324,8 +36620,8 @@ function useInitialPrompt({
|
|
|
36324
36620
|
runBlocksRef,
|
|
36325
36621
|
dispatch
|
|
36326
36622
|
}) {
|
|
36327
|
-
const bootInjectedRef =
|
|
36328
|
-
|
|
36623
|
+
const bootInjectedRef = useRef23(false);
|
|
36624
|
+
useEffect42(() => {
|
|
36329
36625
|
if (bootInjectedRef.current) return;
|
|
36330
36626
|
const goal = initialGoal?.trim();
|
|
36331
36627
|
const ask = initialAsk?.trim();
|
|
@@ -36372,7 +36668,7 @@ function useInitialPrompt({
|
|
|
36372
36668
|
import { DefaultSecretScrubber } from "@wrongstack/core/security";
|
|
36373
36669
|
import { INPUT_HISTORY_DEFAULT_MAX, InputHistoryStore } from "@wrongstack/core/storage";
|
|
36374
36670
|
import { resolveWstackPaths as resolveWstackPaths3 } from "@wrongstack/core/utils";
|
|
36375
|
-
import { useEffect as
|
|
36671
|
+
import { useEffect as useEffect43, useMemo as useMemo12, useRef as useRef24 } from "react";
|
|
36376
36672
|
function useInputHistoryPersistence({
|
|
36377
36673
|
projectRoot,
|
|
36378
36674
|
inputHistory,
|
|
@@ -36383,10 +36679,10 @@ function useInputHistoryPersistence({
|
|
|
36383
36679
|
const file = resolveWstackPaths3({ projectRoot }).projectInputHistory;
|
|
36384
36680
|
return new InputHistoryStore(file, new DefaultSecretScrubber(), INPUT_HISTORY_DEFAULT_MAX);
|
|
36385
36681
|
}, [projectRoot]);
|
|
36386
|
-
const inputHistoryLoadedRef =
|
|
36387
|
-
const inputHistorySaveTimerRef =
|
|
36388
|
-
const inputHistoryLastSavedRef =
|
|
36389
|
-
|
|
36682
|
+
const inputHistoryLoadedRef = useRef24(false);
|
|
36683
|
+
const inputHistorySaveTimerRef = useRef24(void 0);
|
|
36684
|
+
const inputHistoryLastSavedRef = useRef24("");
|
|
36685
|
+
useEffect43(() => {
|
|
36390
36686
|
if (!inputHistoryStore) return;
|
|
36391
36687
|
let cancelled = false;
|
|
36392
36688
|
inputHistoryStore.load().then((entries) => {
|
|
@@ -36402,7 +36698,7 @@ function useInputHistoryPersistence({
|
|
|
36402
36698
|
cancelled = true;
|
|
36403
36699
|
};
|
|
36404
36700
|
}, [inputHistoryStore, dispatch]);
|
|
36405
|
-
|
|
36701
|
+
useEffect43(() => {
|
|
36406
36702
|
if (!inputHistoryStore || !inputHistoryLoadedRef.current) return;
|
|
36407
36703
|
const snapshot = JSON.stringify(inputHistory);
|
|
36408
36704
|
if (snapshot === inputHistoryLastSavedRef.current) return;
|
|
@@ -36421,9 +36717,9 @@ function useInputHistoryPersistence({
|
|
|
36421
36717
|
// src/hooks/use-interrupt-ladder.ts
|
|
36422
36718
|
import { getProcessRegistry as getProcessRegistry8 } from "@wrongstack/tools";
|
|
36423
36719
|
import {
|
|
36424
|
-
useCallback as
|
|
36425
|
-
useEffect as
|
|
36426
|
-
useRef as
|
|
36720
|
+
useCallback as useCallback16,
|
|
36721
|
+
useEffect as useEffect44,
|
|
36722
|
+
useRef as useRef25
|
|
36427
36723
|
} from "react";
|
|
36428
36724
|
var INTERRUPT_PRESS_WINDOW_MS = 2e3;
|
|
36429
36725
|
function useInterruptLadder({
|
|
@@ -36444,9 +36740,9 @@ function useInterruptLadder({
|
|
|
36444
36740
|
getSddRun,
|
|
36445
36741
|
confirmExitRef
|
|
36446
36742
|
}) {
|
|
36447
|
-
const interruptsSyncRef =
|
|
36448
|
-
const lastPressAtRef =
|
|
36449
|
-
const runInterruptLadder =
|
|
36743
|
+
const interruptsSyncRef = useRef25(0);
|
|
36744
|
+
const lastPressAtRef = useRef25(0);
|
|
36745
|
+
const runInterruptLadder = useCallback16(() => {
|
|
36450
36746
|
const current = stateRef.current;
|
|
36451
36747
|
const now = Date.now();
|
|
36452
36748
|
if (interruptsSyncRef.current > 0 && current.status === "idle" && now - lastPressAtRef.current > INTERRUPT_PRESS_WINDOW_MS) {
|
|
@@ -36621,7 +36917,7 @@ function useInterruptLadder({
|
|
|
36621
36917
|
onExit,
|
|
36622
36918
|
exit
|
|
36623
36919
|
]);
|
|
36624
|
-
|
|
36920
|
+
useEffect44(() => {
|
|
36625
36921
|
process.on("SIGINT", runInterruptLadder);
|
|
36626
36922
|
return () => {
|
|
36627
36923
|
process.off("SIGINT", runInterruptLadder);
|
|
@@ -36631,10 +36927,10 @@ function useInterruptLadder({
|
|
|
36631
36927
|
}
|
|
36632
36928
|
|
|
36633
36929
|
// src/hooks/use-kanban-board-focus.ts
|
|
36634
|
-
import { useRef as
|
|
36930
|
+
import { useRef as useRef26, useState as useState29 } from "react";
|
|
36635
36931
|
function useKanbanBoardFocus() {
|
|
36636
|
-
const [focusedBoardId, setFocusedBoardId] =
|
|
36637
|
-
const boardFocusRef =
|
|
36932
|
+
const [focusedBoardId, setFocusedBoardId] = useState29(null);
|
|
36933
|
+
const boardFocusRef = useRef26(null);
|
|
36638
36934
|
if (!boardFocusRef.current) {
|
|
36639
36935
|
boardFocusRef.current = {
|
|
36640
36936
|
current: (boardId) => {
|
|
@@ -36647,7 +36943,7 @@ function useKanbanBoardFocus() {
|
|
|
36647
36943
|
}
|
|
36648
36944
|
|
|
36649
36945
|
// src/hooks/use-live-settings-state.ts
|
|
36650
|
-
import { useEffect as
|
|
36946
|
+
import { useEffect as useEffect45, useRef as useRef27 } from "react";
|
|
36651
36947
|
function useLiveSettingsState({
|
|
36652
36948
|
getSettings,
|
|
36653
36949
|
titleController,
|
|
@@ -36658,12 +36954,12 @@ function useLiveSettingsState({
|
|
|
36658
36954
|
const liveStatuslineMode = liveSettings?.statuslineMode ?? DEFAULT_STATUSLINE_MODE;
|
|
36659
36955
|
const liveAnimationStyle = liveSettings?.animationStyle ?? "rainbow";
|
|
36660
36956
|
const liveThinkingWord = liveSettings?.thinkingWord ?? "thinking";
|
|
36661
|
-
const chimeRef =
|
|
36957
|
+
const chimeRef = useRef27(chime);
|
|
36662
36958
|
chimeRef.current = liveSettings?.chime ?? chime;
|
|
36663
|
-
const confirmExitRef =
|
|
36959
|
+
const confirmExitRef = useRef27(confirmExit);
|
|
36664
36960
|
confirmExitRef.current = liveSettings?.confirmExit ?? confirmExit;
|
|
36665
36961
|
const liveTitleAnimation = liveSettings?.titleAnimation;
|
|
36666
|
-
|
|
36962
|
+
useEffect45(() => {
|
|
36667
36963
|
if (!titleController) return;
|
|
36668
36964
|
titleController.setEnabled(liveTitleAnimation !== false);
|
|
36669
36965
|
}, [titleController, liveTitleAnimation]);
|
|
@@ -36678,10 +36974,10 @@ function useLiveSettingsState({
|
|
|
36678
36974
|
}
|
|
36679
36975
|
|
|
36680
36976
|
// src/hooks/use-live-todos.ts
|
|
36681
|
-
import { useEffect as
|
|
36977
|
+
import { useEffect as useEffect46, useState as useState30 } from "react";
|
|
36682
36978
|
function useLiveTodos(context) {
|
|
36683
|
-
const [todos, setTodos] =
|
|
36684
|
-
|
|
36979
|
+
const [todos, setTodos] = useState30(() => [...context.todos]);
|
|
36980
|
+
useEffect46(() => {
|
|
36685
36981
|
setTodos([...context.todos]);
|
|
36686
36982
|
return context.state.onChange((change) => {
|
|
36687
36983
|
if (change.kind === "todos_replaced") setTodos([...change.todos]);
|
|
@@ -36691,17 +36987,17 @@ function useLiveTodos(context) {
|
|
|
36691
36987
|
}
|
|
36692
36988
|
|
|
36693
36989
|
// src/hooks/use-mailbox-view-model.ts
|
|
36694
|
-
import { useEffect as
|
|
36990
|
+
import { useEffect as useEffect47, useState as useState31 } from "react";
|
|
36695
36991
|
function useMailboxViewModel(events) {
|
|
36696
|
-
const [mailboxStatus, setMailboxStatus] =
|
|
36992
|
+
const [mailboxStatus, setMailboxStatus] = useState31({
|
|
36697
36993
|
unread: 0,
|
|
36698
36994
|
onlineAgents: 0,
|
|
36699
36995
|
onlineClients: { tui: 0, webui: 0, repl: 0 }
|
|
36700
36996
|
});
|
|
36701
|
-
const [mailboxPanelOpen, setMailboxPanelOpen] =
|
|
36702
|
-
const [mailboxMessages, setMailboxMessages] =
|
|
36703
|
-
const [mailboxAgents, setMailboxAgents] =
|
|
36704
|
-
|
|
36997
|
+
const [mailboxPanelOpen, setMailboxPanelOpen] = useState31(false);
|
|
36998
|
+
const [mailboxMessages, setMailboxMessages] = useState31([]);
|
|
36999
|
+
const [mailboxAgents, setMailboxAgents] = useState31([]);
|
|
37000
|
+
useEffect47(() => {
|
|
36705
37001
|
const AGENT_ONLINE_TTL_MS = 12e4;
|
|
36706
37002
|
const lastSeen = /* @__PURE__ */ new Map();
|
|
36707
37003
|
const unsubUnread = events.onPattern("mailbox.unread_count", (_event, payload) => {
|
|
@@ -36763,7 +37059,7 @@ function useMailboxViewModel(events) {
|
|
|
36763
37059
|
unsubSnapshot();
|
|
36764
37060
|
};
|
|
36765
37061
|
}, [events]);
|
|
36766
|
-
|
|
37062
|
+
useEffect47(() => {
|
|
36767
37063
|
const unsubMessage = events.onPattern("mailbox.received", (_event, payload) => {
|
|
36768
37064
|
const data = payload;
|
|
36769
37065
|
if (!data?.messageId) return;
|
|
@@ -36864,7 +37160,7 @@ function useMailboxViewModel(events) {
|
|
|
36864
37160
|
}
|
|
36865
37161
|
|
|
36866
37162
|
// src/hooks/use-mode-picker.ts
|
|
36867
|
-
import { useCallback as
|
|
37163
|
+
import { useCallback as useCallback17 } from "react";
|
|
36868
37164
|
function buildModePickerOptions(result) {
|
|
36869
37165
|
return toModeOptions(result.modes, result.activeId);
|
|
36870
37166
|
}
|
|
@@ -36872,7 +37168,7 @@ function useModePicker({
|
|
|
36872
37168
|
dispatch,
|
|
36873
37169
|
getModes
|
|
36874
37170
|
}) {
|
|
36875
|
-
const openModePicker =
|
|
37171
|
+
const openModePicker = useCallback17(async () => {
|
|
36876
37172
|
if (!getModes) return;
|
|
36877
37173
|
const result = await getModes();
|
|
36878
37174
|
const options = buildModePickerOptions(result);
|
|
@@ -36914,11 +37210,11 @@ function useModelPickRequest(opts) {
|
|
|
36914
37210
|
}
|
|
36915
37211
|
|
|
36916
37212
|
// src/hooks/use-mouse-tracking.ts
|
|
36917
|
-
import { useEffect as
|
|
37213
|
+
import { useEffect as useEffect48, useRef as useRef28, useState as useState32 } from "react";
|
|
36918
37214
|
function useMouseTracking(input) {
|
|
36919
37215
|
const { initialMouseMode, initialNativeMouse, overlayOpen, protocol, stdout } = input;
|
|
36920
|
-
const [mouseMode, setMouseMode] =
|
|
36921
|
-
const [nativeMouse, setNativeMouse] =
|
|
37216
|
+
const [mouseMode, setMouseMode] = useState32(initialMouseMode);
|
|
37217
|
+
const [nativeMouse, setNativeMouse] = useState32(initialNativeMouse ?? false);
|
|
36922
37218
|
const mouseTrackingOn = shouldEnableMouseTracking({
|
|
36923
37219
|
fullMode: mouseMode,
|
|
36924
37220
|
overlayOpen,
|
|
@@ -36927,8 +37223,8 @@ function useMouseTracking(input) {
|
|
|
36927
37223
|
protocol
|
|
36928
37224
|
});
|
|
36929
37225
|
const mouseTrackingSequence = mouseTrackingOn ? mouseMode ? MOUSE_DRAG_ON : MOUSE_CLICK_ON : MOUSE_OFF;
|
|
36930
|
-
const mouseWrittenRef =
|
|
36931
|
-
|
|
37226
|
+
const mouseWrittenRef = useRef28(null);
|
|
37227
|
+
useEffect48(() => {
|
|
36932
37228
|
if (mouseWrittenRef.current === mouseTrackingSequence) return;
|
|
36933
37229
|
mouseWrittenRef.current = mouseTrackingSequence;
|
|
36934
37230
|
try {
|
|
@@ -36936,7 +37232,7 @@ function useMouseTracking(input) {
|
|
|
36936
37232
|
} catch {
|
|
36937
37233
|
}
|
|
36938
37234
|
}, [mouseTrackingSequence, stdout]);
|
|
36939
|
-
|
|
37235
|
+
useEffect48(
|
|
36940
37236
|
() => () => {
|
|
36941
37237
|
const wasTracking = mouseWrittenRef.current !== null && mouseWrittenRef.current !== MOUSE_OFF;
|
|
36942
37238
|
mouseWrittenRef.current = null;
|
|
@@ -36963,10 +37259,10 @@ import {
|
|
|
36963
37259
|
} from "@wrongstack/tools/auto-proceed-loop-guard";
|
|
36964
37260
|
import { todoTool } from "@wrongstack/tools/todo";
|
|
36965
37261
|
import {
|
|
36966
|
-
useCallback as
|
|
36967
|
-
useEffect as
|
|
36968
|
-
useRef as
|
|
36969
|
-
useState as
|
|
37262
|
+
useCallback as useCallback18,
|
|
37263
|
+
useEffect as useEffect49,
|
|
37264
|
+
useRef as useRef29,
|
|
37265
|
+
useState as useState33
|
|
36970
37266
|
} from "react";
|
|
36971
37267
|
async function commitTodoTransition(agent, todos) {
|
|
36972
37268
|
if (!agent?.ctx?.state) return null;
|
|
@@ -37011,27 +37307,27 @@ function useNextStepsAutoSubmit({
|
|
|
37011
37307
|
clearDraft,
|
|
37012
37308
|
runBlocksRef
|
|
37013
37309
|
}) {
|
|
37014
|
-
const [nextStepsAutoSubmitCountdown, setNextStepsAutoSubmitCountdown] =
|
|
37310
|
+
const [nextStepsAutoSubmitCountdown, setNextStepsAutoSubmitCountdown] = useState33(
|
|
37015
37311
|
null
|
|
37016
37312
|
);
|
|
37017
|
-
const [nextStepsAutoSubmitLabel, setNextStepsAutoSubmitLabel] =
|
|
37018
|
-
const nextStepsAutoSubmitSuggestionRef =
|
|
37019
|
-
const nextStepsAutoSubmitSourceRef =
|
|
37020
|
-
const nextStepsAutoSubmitTodoIdRef =
|
|
37021
|
-
const nextStepsAutoSubmitTodosRef =
|
|
37022
|
-
const nextStepsAutoSubmitTimerRef =
|
|
37023
|
-
const autoSubmitStreakRef =
|
|
37024
|
-
const autoSubmitCapWarnedRef =
|
|
37025
|
-
const autoSubmitLoopGuardRef =
|
|
37026
|
-
const continuationAttemptTrackerRef =
|
|
37027
|
-
const [nextStepsRecheck, setNextStepsRecheck] =
|
|
37028
|
-
|
|
37313
|
+
const [nextStepsAutoSubmitLabel, setNextStepsAutoSubmitLabel] = useState33(null);
|
|
37314
|
+
const nextStepsAutoSubmitSuggestionRef = useRef29(null);
|
|
37315
|
+
const nextStepsAutoSubmitSourceRef = useRef29(null);
|
|
37316
|
+
const nextStepsAutoSubmitTodoIdRef = useRef29(null);
|
|
37317
|
+
const nextStepsAutoSubmitTodosRef = useRef29([]);
|
|
37318
|
+
const nextStepsAutoSubmitTimerRef = useRef29(void 0);
|
|
37319
|
+
const autoSubmitStreakRef = useRef29(0);
|
|
37320
|
+
const autoSubmitCapWarnedRef = useRef29(false);
|
|
37321
|
+
const autoSubmitLoopGuardRef = useRef29(createAutoProceedLoopGuard());
|
|
37322
|
+
const continuationAttemptTrackerRef = useRef29(createContinuationAttemptTracker());
|
|
37323
|
+
const [nextStepsRecheck, setNextStepsRecheck] = useState33(0);
|
|
37324
|
+
useEffect49(() => {
|
|
37029
37325
|
autoSubmitStreakRef.current = 0;
|
|
37030
37326
|
autoSubmitCapWarnedRef.current = false;
|
|
37031
37327
|
autoSubmitLoopGuardRef.current.reset();
|
|
37032
37328
|
continuationAttemptTrackerRef.current.reset();
|
|
37033
37329
|
}, [autonomyLive]);
|
|
37034
|
-
|
|
37330
|
+
useEffect49(() => {
|
|
37035
37331
|
const liveAutonomy = getAutonomy?.() ?? autonomyLive;
|
|
37036
37332
|
if (state.status !== "idle" || liveAutonomy !== "auto") {
|
|
37037
37333
|
clearInterval(nextStepsAutoSubmitTimerRef.current);
|
|
@@ -37265,7 +37561,7 @@ ${GROUNDED_NO_PROGRESS_STEER}` : suggestion;
|
|
|
37265
37561
|
autonomyNextPrompt,
|
|
37266
37562
|
dispatch
|
|
37267
37563
|
]);
|
|
37268
|
-
const cancelNextStepsCountdown =
|
|
37564
|
+
const cancelNextStepsCountdown = useCallback18(() => {
|
|
37269
37565
|
if (nextStepsAutoSubmitTimerRef.current == null) return;
|
|
37270
37566
|
clearInterval(nextStepsAutoSubmitTimerRef.current);
|
|
37271
37567
|
nextStepsAutoSubmitTimerRef.current = void 0;
|
|
@@ -37291,7 +37587,7 @@ ${GROUNDED_NO_PROGRESS_STEER}` : suggestion;
|
|
|
37291
37587
|
|
|
37292
37588
|
// src/hooks/use-panel-controllers.ts
|
|
37293
37589
|
import { toErrorMessage as toErrorMessage6 } from "@wrongstack/core/utils";
|
|
37294
|
-
import React8, { useEffect as
|
|
37590
|
+
import React8, { useEffect as useEffect50 } from "react";
|
|
37295
37591
|
|
|
37296
37592
|
// src/on-panel-open.ts
|
|
37297
37593
|
function createPanelOpenDispatcher(deps) {
|
|
@@ -37425,7 +37721,7 @@ function usePanelControllers({
|
|
|
37425
37721
|
dispatch({ type: "sessionsPanelBusy", on: false });
|
|
37426
37722
|
}
|
|
37427
37723
|
}, [getLiveSessions]);
|
|
37428
|
-
|
|
37724
|
+
useEffect50(() => {
|
|
37429
37725
|
if (!onPanelOpen) return;
|
|
37430
37726
|
const dispatcher = createPanelOpenDispatcher({
|
|
37431
37727
|
dispatch,
|
|
@@ -37452,7 +37748,7 @@ function usePanelControllers({
|
|
|
37452
37748
|
openShadowPanel,
|
|
37453
37749
|
openHelpPanel
|
|
37454
37750
|
]);
|
|
37455
|
-
|
|
37751
|
+
useEffect50(() => {
|
|
37456
37752
|
if (!state.sessionsPanelOpen || !getLiveSessions) return void 0;
|
|
37457
37753
|
const t = setInterval(() => {
|
|
37458
37754
|
void loadLiveSessions();
|
|
@@ -37532,7 +37828,7 @@ function usePanelControllers({
|
|
|
37532
37828
|
if (!getPluginItems) return;
|
|
37533
37829
|
dispatch({ type: "pluginPickerSetItems", items: getPluginItems() });
|
|
37534
37830
|
}, [getPluginItems]);
|
|
37535
|
-
|
|
37831
|
+
useEffect50(() => {
|
|
37536
37832
|
if (!state.pluginPicker.open) return;
|
|
37537
37833
|
refreshPluginPicker();
|
|
37538
37834
|
}, [state.pluginPicker.open, refreshPluginPicker]);
|
|
@@ -37564,7 +37860,7 @@ function usePanelControllers({
|
|
|
37564
37860
|
if (!getMcpServers) return;
|
|
37565
37861
|
dispatch({ type: "mcpPickerSetItems", items: getMcpServers() });
|
|
37566
37862
|
}, [getMcpServers]);
|
|
37567
|
-
|
|
37863
|
+
useEffect50(() => {
|
|
37568
37864
|
if (!state.mcpPicker.open) return;
|
|
37569
37865
|
refreshMcpPicker();
|
|
37570
37866
|
}, [state.mcpPicker.open, refreshMcpPicker]);
|
|
@@ -37608,7 +37904,7 @@ function usePanelControllers({
|
|
|
37608
37904
|
dispatch({ type: "toolsPickerSetItems", items });
|
|
37609
37905
|
setLiveToolCount(items.filter((item) => item.enabled).length);
|
|
37610
37906
|
}, [getToolsItems]);
|
|
37611
|
-
|
|
37907
|
+
useEffect50(() => {
|
|
37612
37908
|
if (!state.toolsPicker.open) return;
|
|
37613
37909
|
refreshToolsPicker();
|
|
37614
37910
|
}, [state.toolsPicker.open, refreshToolsPicker]);
|
|
@@ -37644,7 +37940,7 @@ function usePanelControllers({
|
|
|
37644
37940
|
}
|
|
37645
37941
|
|
|
37646
37942
|
// src/hooks/use-paste-handling.ts
|
|
37647
|
-
import { useRef as
|
|
37943
|
+
import { useRef as useRef30 } from "react";
|
|
37648
37944
|
import { toErrorMessage as toErrorMessage7 } from "@wrongstack/core/utils";
|
|
37649
37945
|
|
|
37650
37946
|
// src/input-validation/limits.ts
|
|
@@ -37689,8 +37985,8 @@ function usePasteHandling({
|
|
|
37689
37985
|
setDraft,
|
|
37690
37986
|
tokenPreviewsRef
|
|
37691
37987
|
}) {
|
|
37692
|
-
const pasteAccumRef =
|
|
37693
|
-
const pasteFlushTimerRef =
|
|
37988
|
+
const pasteAccumRef = useRef30(null);
|
|
37989
|
+
const pasteFlushTimerRef = useRef30(null);
|
|
37694
37990
|
const commitPaste = async (full) => {
|
|
37695
37991
|
const builder = builderRef.current;
|
|
37696
37992
|
if (!builder || !full) return;
|
|
@@ -37781,11 +38077,11 @@ function usePasteHandling({
|
|
|
37781
38077
|
|
|
37782
38078
|
// src/hooks/use-prompt-picker.ts
|
|
37783
38079
|
import { createRequire } from "node:module";
|
|
37784
|
-
import * as
|
|
38080
|
+
import * as path7 from "node:path";
|
|
37785
38081
|
import { DefaultPromptLoader } from "@wrongstack/core/execution";
|
|
37786
38082
|
import { PromptUsageStore } from "@wrongstack/core/storage";
|
|
37787
38083
|
import { resolveWstackPaths as resolveWstackPaths4 } from "@wrongstack/core/utils";
|
|
37788
|
-
import { useCallback as
|
|
38084
|
+
import { useCallback as useCallback19, useRef as useRef31 } from "react";
|
|
37789
38085
|
function buildPromptPickerPayload(all, recentSlugs) {
|
|
37790
38086
|
const entries = all.map((e) => ({
|
|
37791
38087
|
slug: e.slug,
|
|
@@ -37806,15 +38102,15 @@ function buildPromptPickerPayload(all, recentSlugs) {
|
|
|
37806
38102
|
return { all: entries, categories, recentSlugs };
|
|
37807
38103
|
}
|
|
37808
38104
|
function usePromptPicker({ projectRoot, dispatch }) {
|
|
37809
|
-
const promptLoaderRef =
|
|
37810
|
-
const promptUsageRef =
|
|
37811
|
-
const getPromptLoader =
|
|
38105
|
+
const promptLoaderRef = useRef31(null);
|
|
38106
|
+
const promptUsageRef = useRef31(null);
|
|
38107
|
+
const getPromptLoader = useCallback19(() => {
|
|
37812
38108
|
if (!promptLoaderRef.current && projectRoot) {
|
|
37813
38109
|
let bundledDir;
|
|
37814
38110
|
try {
|
|
37815
38111
|
const req = createRequire(import.meta.url);
|
|
37816
|
-
bundledDir =
|
|
37817
|
-
|
|
38112
|
+
bundledDir = path7.join(
|
|
38113
|
+
path7.dirname(req.resolve("@wrongstack/core/package.json")),
|
|
37818
38114
|
"data",
|
|
37819
38115
|
"prompts"
|
|
37820
38116
|
);
|
|
@@ -37827,7 +38123,7 @@ function usePromptPicker({ projectRoot, dispatch }) {
|
|
|
37827
38123
|
}
|
|
37828
38124
|
return promptLoaderRef.current;
|
|
37829
38125
|
}, [projectRoot]);
|
|
37830
|
-
const openPromptPicker =
|
|
38126
|
+
const openPromptPicker = useCallback19(async () => {
|
|
37831
38127
|
const loader = getPromptLoader();
|
|
37832
38128
|
if (!loader) return;
|
|
37833
38129
|
loader.invalidateCache();
|
|
@@ -37836,7 +38132,7 @@ function usePromptPicker({ projectRoot, dispatch }) {
|
|
|
37836
38132
|
const payload = buildPromptPickerPayload(all, recentSlugs);
|
|
37837
38133
|
dispatch({ type: "promptPickerOpen", ...payload });
|
|
37838
38134
|
}, [dispatch, getPromptLoader]);
|
|
37839
|
-
const setPromptFavorite =
|
|
38135
|
+
const setPromptFavorite = useCallback19(
|
|
37840
38136
|
async (slug, favorite) => {
|
|
37841
38137
|
const loader = getPromptLoader();
|
|
37842
38138
|
if (!loader) return;
|
|
@@ -37852,7 +38148,7 @@ function usePromptPicker({ projectRoot, dispatch }) {
|
|
|
37852
38148
|
import { tuiStreamFlushMs } from "@wrongstack/core/utils";
|
|
37853
38149
|
import { DEFAULT_MIN_IMPORTANCE as DEFAULT_MIN_IMPORTANCE2, DEFAULT_MIN_SCORE as DEFAULT_MIN_SCORE2, MIN_RELATION_STRENGTH as MIN_RELATION_STRENGTH2 } from "@wrongstack/sage";
|
|
37854
38150
|
import { isFinalTurnStopReason as isFinalTurnStopReason2 } from "@wrongstack/tools/next-steps";
|
|
37855
|
-
import { useEffect as
|
|
38151
|
+
import { useEffect as useEffect51 } from "react";
|
|
37856
38152
|
|
|
37857
38153
|
// src/memory-lifecycle-entry.ts
|
|
37858
38154
|
function memoryLifecycleEntry(event, payload) {
|
|
@@ -38052,7 +38348,7 @@ function useProviderEventBridge({
|
|
|
38052
38348
|
assistantCommittedThisRunRef,
|
|
38053
38349
|
setMemoryContextMonitor
|
|
38054
38350
|
}) {
|
|
38055
|
-
|
|
38351
|
+
useEffect51(() => {
|
|
38056
38352
|
const FLUSH_MS2 = tuiStreamFlushMs();
|
|
38057
38353
|
let pendingToolStream = null;
|
|
38058
38354
|
const pendingSageStats = /* @__PURE__ */ new Map();
|
|
@@ -38426,7 +38722,7 @@ function useProviderEventBridge({
|
|
|
38426
38722
|
}
|
|
38427
38723
|
|
|
38428
38724
|
// src/hooks/use-queue-manager.ts
|
|
38429
|
-
import { useEffect as
|
|
38725
|
+
import { useEffect as useEffect52, useRef as useRef32 } from "react";
|
|
38430
38726
|
|
|
38431
38727
|
// src/queue-slash.ts
|
|
38432
38728
|
var USAGE5 = "Usage:\n /queue \u2014 list pending messages\n /queue list \u2014 same as /queue\n /queue clear \u2014 drop all pending messages\n /queue delete N M\u2026 \u2014 drop messages at 1-based positions\n /queue picker on|off \u2014 toggle the mid-run send-mode picker (queue/btw/steer)\n /queue picker \u2014 show whether the picker is on";
|
|
@@ -38533,8 +38829,8 @@ function useQueueManager({
|
|
|
38533
38829
|
saveSettings,
|
|
38534
38830
|
midRunSendPickerRef
|
|
38535
38831
|
}) {
|
|
38536
|
-
const persistState =
|
|
38537
|
-
|
|
38832
|
+
const persistState = useRef32({ running: false, pending: null });
|
|
38833
|
+
useEffect52(() => {
|
|
38538
38834
|
if (!queueStore) return;
|
|
38539
38835
|
let cancelled = false;
|
|
38540
38836
|
queueStore.read().then((items) => {
|
|
@@ -38561,7 +38857,7 @@ function useQueueManager({
|
|
|
38561
38857
|
cancelled = true;
|
|
38562
38858
|
};
|
|
38563
38859
|
}, [queueStore]);
|
|
38564
|
-
|
|
38860
|
+
useEffect52(() => {
|
|
38565
38861
|
if (!queueStore) return;
|
|
38566
38862
|
const raw = stateRef.current.queue.map(
|
|
38567
38863
|
({
|
|
@@ -38590,10 +38886,10 @@ function useQueueManager({
|
|
|
38590
38886
|
}
|
|
38591
38887
|
})();
|
|
38592
38888
|
}, [stateRef.current.queue, queueStore, stateRef]);
|
|
38593
|
-
|
|
38889
|
+
useEffect52(() => {
|
|
38594
38890
|
onQueueChange?.(stateRef.current.queue.map((q) => q.displayText));
|
|
38595
38891
|
}, [stateRef.current.queue, onQueueChange, stateRef]);
|
|
38596
|
-
|
|
38892
|
+
useEffect52(() => {
|
|
38597
38893
|
const cmd = createQueueSlashCommand({
|
|
38598
38894
|
getQueue: () => stateRef.current.queue,
|
|
38599
38895
|
clear: () => dispatch({ type: "queueClear" }),
|
|
@@ -38616,7 +38912,7 @@ function useQueueManager({
|
|
|
38616
38912
|
}
|
|
38617
38913
|
|
|
38618
38914
|
// src/hooks/use-session-interrupt-controller.ts
|
|
38619
|
-
import { useEffect as
|
|
38915
|
+
import { useEffect as useEffect53 } from "react";
|
|
38620
38916
|
function useSessionInterruptController({
|
|
38621
38917
|
interruptController,
|
|
38622
38918
|
dispatch,
|
|
@@ -38638,7 +38934,7 @@ function useSessionInterruptController({
|
|
|
38638
38934
|
getSddRun,
|
|
38639
38935
|
switchAutonomy
|
|
38640
38936
|
}) {
|
|
38641
|
-
|
|
38937
|
+
useEffect53(() => {
|
|
38642
38938
|
if (!interruptController) return;
|
|
38643
38939
|
let pendingClearResolve = null;
|
|
38644
38940
|
let pendingSlashResolve = null;
|
|
@@ -38765,15 +39061,15 @@ function useSessionInterruptController({
|
|
|
38765
39061
|
}
|
|
38766
39062
|
|
|
38767
39063
|
// src/hooks/use-settings-auto-save.ts
|
|
38768
|
-
import { useEffect as
|
|
39064
|
+
import { useEffect as useEffect54, useRef as useRef33 } from "react";
|
|
38769
39065
|
function useSettingsAutoSave(state, saveSettings, dispatch) {
|
|
38770
|
-
const settingsAutoSaveGateRef =
|
|
38771
|
-
|
|
39066
|
+
const settingsAutoSaveGateRef = useRef33(true);
|
|
39067
|
+
useEffect54(() => {
|
|
38772
39068
|
if (state.settingsPicker.open) {
|
|
38773
39069
|
settingsAutoSaveGateRef.current = true;
|
|
38774
39070
|
}
|
|
38775
39071
|
}, [state.settingsPicker.open]);
|
|
38776
|
-
|
|
39072
|
+
useEffect54(() => {
|
|
38777
39073
|
const sp = state.settingsPicker;
|
|
38778
39074
|
const save = saveSettings;
|
|
38779
39075
|
if (!sp.open || !save) return;
|
|
@@ -38889,15 +39185,15 @@ function useSettingsAutoSave(state, saveSettings, dispatch) {
|
|
|
38889
39185
|
}
|
|
38890
39186
|
|
|
38891
39187
|
// src/hooks/use-shadow-panel.ts
|
|
38892
|
-
import { useCallback as
|
|
39188
|
+
import { useCallback as useCallback20 } from "react";
|
|
38893
39189
|
import { toErrorMessage as toErrorMessage8 } from "@wrongstack/core/utils";
|
|
38894
39190
|
function useShadowPanel(dispatch, host) {
|
|
38895
39191
|
const { getShadowData, onShadowStart, onShadowStop } = host;
|
|
38896
|
-
const openShadowPanel =
|
|
39192
|
+
const openShadowPanel = useCallback20(() => {
|
|
38897
39193
|
if (!getShadowData) return;
|
|
38898
39194
|
dispatch({ type: "shadowOpen", shadow: getShadowData() });
|
|
38899
39195
|
}, [dispatch, getShadowData]);
|
|
38900
|
-
const handleShadowStart =
|
|
39196
|
+
const handleShadowStart = useCallback20(async () => {
|
|
38901
39197
|
if (!onShadowStart) return;
|
|
38902
39198
|
dispatch({ type: "shadowHint", text: "Starting Shadow Agent\u2026" });
|
|
38903
39199
|
try {
|
|
@@ -38911,7 +39207,7 @@ function useShadowPanel(dispatch, host) {
|
|
|
38911
39207
|
dispatch({ type: "shadowHint", text: `Failed to start: ${toErrorMessage8(error)}` });
|
|
38912
39208
|
}
|
|
38913
39209
|
}, [dispatch, getShadowData, onShadowStart]);
|
|
38914
|
-
const handleShadowStop =
|
|
39210
|
+
const handleShadowStop = useCallback20(async () => {
|
|
38915
39211
|
if (!onShadowStop) return;
|
|
38916
39212
|
dispatch({ type: "shadowHint", text: "Stopping Shadow Agent\u2026" });
|
|
38917
39213
|
try {
|
|
@@ -38929,14 +39225,14 @@ function useShadowPanel(dispatch, host) {
|
|
|
38929
39225
|
}
|
|
38930
39226
|
|
|
38931
39227
|
// src/hooks/use-slash-picker.ts
|
|
38932
|
-
import { useCallback as
|
|
39228
|
+
import { useCallback as useCallback21, useEffect as useEffect55 } from "react";
|
|
38933
39229
|
function useSlashPicker({
|
|
38934
39230
|
state,
|
|
38935
39231
|
slashRegistry,
|
|
38936
39232
|
dispatch,
|
|
38937
39233
|
setDraft
|
|
38938
39234
|
}) {
|
|
38939
|
-
|
|
39235
|
+
useEffect55(() => {
|
|
38940
39236
|
const trimmed = state.buffer.trimStart();
|
|
38941
39237
|
if (!trimmed.startsWith("/") || /\s/.test(trimmed)) {
|
|
38942
39238
|
if (state.slashPicker.open) dispatch({ type: "slashPickerClose" });
|
|
@@ -38948,9 +39244,9 @@ function useSlashPicker({
|
|
|
38948
39244
|
dispatch({ type: "slashPickerOpen", query, matches });
|
|
38949
39245
|
}
|
|
38950
39246
|
}, [state.buffer, state.slashPicker.open, state.slashPicker.query, slashRegistry, dispatch]);
|
|
38951
|
-
return
|
|
38952
|
-
const { open, matches, selected } = state.slashPicker;
|
|
38953
|
-
if (!
|
|
39247
|
+
return useCallback21(() => {
|
|
39248
|
+
const { open: open2, matches, selected } = state.slashPicker;
|
|
39249
|
+
if (!open2 || matches.length === 0) return;
|
|
38954
39250
|
const picked = matches[selected];
|
|
38955
39251
|
if (!picked) return;
|
|
38956
39252
|
const command = picked.argsHint !== void 0 ? `/${picked.name} ` : `/${picked.name}`;
|
|
@@ -38960,11 +39256,11 @@ function useSlashPicker({
|
|
|
38960
39256
|
}
|
|
38961
39257
|
|
|
38962
39258
|
// src/hooks/use-stable-key-handler.ts
|
|
38963
|
-
import { useCallback as
|
|
39259
|
+
import { useCallback as useCallback22, useRef as useRef34 } from "react";
|
|
38964
39260
|
function useStableKeyHandler(handleKey) {
|
|
38965
|
-
const handleKeyRef =
|
|
39261
|
+
const handleKeyRef = useRef34(null);
|
|
38966
39262
|
handleKeyRef.current = handleKey;
|
|
38967
|
-
return
|
|
39263
|
+
return useCallback22((input, key) => {
|
|
38968
39264
|
handleKeyRef.current?.(input, key)?.catch(() => {
|
|
38969
39265
|
});
|
|
38970
39266
|
return Promise.resolve();
|
|
@@ -38974,7 +39270,7 @@ function useStableKeyHandler(handleKey) {
|
|
|
38974
39270
|
// src/hooks/use-statusbar-view-model.ts
|
|
38975
39271
|
import * as fs4 from "node:fs/promises";
|
|
38976
39272
|
import { getContextBreakdown } from "@wrongstack/core/utils";
|
|
38977
|
-
import { useEffect as
|
|
39273
|
+
import { useEffect as useEffect56, useMemo as useMemo13, useState as useState34 } from "react";
|
|
38978
39274
|
|
|
38979
39275
|
// src/context-fill.ts
|
|
38980
39276
|
function resolveContextFill(inputs) {
|
|
@@ -39107,8 +39403,8 @@ function useStatusbarViewModel({
|
|
|
39107
39403
|
const planHidden = hiddenItems.includes("plan");
|
|
39108
39404
|
const taskHidden = hiddenItems.includes("tasks");
|
|
39109
39405
|
const planPath = agent.ctx.meta["plan.path"];
|
|
39110
|
-
const [planCounts, setPlanCounts] =
|
|
39111
|
-
|
|
39406
|
+
const [planCounts, setPlanCounts] = useState34(null);
|
|
39407
|
+
useEffect56(() => {
|
|
39112
39408
|
if (planHidden) return;
|
|
39113
39409
|
if (typeof planPath !== "string" || !planPath) {
|
|
39114
39410
|
setPlanCounts(null);
|
|
@@ -39118,8 +39414,8 @@ function useStatusbarViewModel({
|
|
|
39118
39414
|
let lastFingerprint = "";
|
|
39119
39415
|
const poll = async () => {
|
|
39120
39416
|
try {
|
|
39121
|
-
const
|
|
39122
|
-
const fingerprint = `${
|
|
39417
|
+
const stat4 = await fs4.stat(planPath);
|
|
39418
|
+
const fingerprint = `${stat4.mtimeMs}:${stat4.size}`;
|
|
39123
39419
|
if (fingerprint === lastFingerprint) return;
|
|
39124
39420
|
const data = await fs4.readFile(planPath, "utf8");
|
|
39125
39421
|
const parsed = JSON.parse(data);
|
|
@@ -39129,15 +39425,15 @@ function useStatusbarViewModel({
|
|
|
39129
39425
|
setPlanCounts((previous) => previous === null ? previous : null);
|
|
39130
39426
|
return;
|
|
39131
39427
|
}
|
|
39132
|
-
let
|
|
39428
|
+
let open2 = 0;
|
|
39133
39429
|
let inProgress = 0;
|
|
39134
39430
|
let done = 0;
|
|
39135
39431
|
for (const item of parsed.items) {
|
|
39136
39432
|
if (item?.status === "done") done++;
|
|
39137
39433
|
else if (item?.status === "in_progress") inProgress++;
|
|
39138
|
-
else
|
|
39434
|
+
else open2++;
|
|
39139
39435
|
}
|
|
39140
|
-
const next =
|
|
39436
|
+
const next = open2 + inProgress + done > 0 ? { open: open2, inProgress, done } : null;
|
|
39141
39437
|
setPlanCounts((previous) => samePlanCounts(previous, next) ? previous : next);
|
|
39142
39438
|
} catch {
|
|
39143
39439
|
if (!cancelled) {
|
|
@@ -39154,8 +39450,8 @@ function useStatusbarViewModel({
|
|
|
39154
39450
|
};
|
|
39155
39451
|
}, [planPath, planHidden]);
|
|
39156
39452
|
const taskPath = agent.ctx.meta["task.path"];
|
|
39157
|
-
const [taskCounts, setTaskCounts] =
|
|
39158
|
-
|
|
39453
|
+
const [taskCounts, setTaskCounts] = useState34(null);
|
|
39454
|
+
useEffect56(() => {
|
|
39159
39455
|
if (taskHidden) return;
|
|
39160
39456
|
if (typeof taskPath !== "string" || !taskPath) {
|
|
39161
39457
|
setTaskCounts(null);
|
|
@@ -39165,8 +39461,8 @@ function useStatusbarViewModel({
|
|
|
39165
39461
|
let lastFingerprint = "";
|
|
39166
39462
|
const poll = async () => {
|
|
39167
39463
|
try {
|
|
39168
|
-
const
|
|
39169
|
-
const fingerprint = `${
|
|
39464
|
+
const stat4 = await fs4.stat(taskPath);
|
|
39465
|
+
const fingerprint = `${stat4.mtimeMs}:${stat4.size}`;
|
|
39170
39466
|
if (fingerprint === lastFingerprint) return;
|
|
39171
39467
|
const data = await fs4.readFile(taskPath, "utf8");
|
|
39172
39468
|
const parsed = JSON.parse(data);
|
|
@@ -39225,7 +39521,7 @@ function useStatusbarViewModel({
|
|
|
39225
39521
|
}
|
|
39226
39522
|
|
|
39227
39523
|
// src/hooks/use-statusline-hidden-sync.ts
|
|
39228
|
-
import { useEffect as
|
|
39524
|
+
import { useEffect as useEffect57 } from "react";
|
|
39229
39525
|
function statuslineHiddenDiffers(hookHidden, pickerHidden) {
|
|
39230
39526
|
const currentHidden = new Set(hookHidden);
|
|
39231
39527
|
const pickerHiddenSet = new Set(pickerHidden);
|
|
@@ -39237,7 +39533,7 @@ function useStatuslineHiddenSync({
|
|
|
39237
39533
|
hiddenItems,
|
|
39238
39534
|
setHiddenItems
|
|
39239
39535
|
}) {
|
|
39240
|
-
|
|
39536
|
+
useEffect57(() => {
|
|
39241
39537
|
if (!pickerOpen) return;
|
|
39242
39538
|
if (statuslineHiddenDiffers(hiddenItems, pickerHidden)) {
|
|
39243
39539
|
setHiddenItems([...pickerHidden]);
|
|
@@ -39246,7 +39542,7 @@ function useStatuslineHiddenSync({
|
|
|
39246
39542
|
}
|
|
39247
39543
|
|
|
39248
39544
|
// src/hooks/use-stream-chip-expiration.ts
|
|
39249
|
-
import { useEffect as
|
|
39545
|
+
import { useEffect as useEffect58, useRef as useRef35 } from "react";
|
|
39250
39546
|
function computeStreamChipActions(input) {
|
|
39251
39547
|
const actions = [];
|
|
39252
39548
|
const visible = new Set(input.visibleChipKeys);
|
|
@@ -39271,9 +39567,9 @@ function useStreamChipExpiration({
|
|
|
39271
39567
|
visibleChips,
|
|
39272
39568
|
dispatch
|
|
39273
39569
|
}) {
|
|
39274
|
-
const prevBrainPromptRef =
|
|
39275
|
-
const prevEnhanceRef =
|
|
39276
|
-
|
|
39570
|
+
const prevBrainPromptRef = useRef35(brainPrompt);
|
|
39571
|
+
const prevEnhanceRef = useRef35(enhance);
|
|
39572
|
+
useEffect58(() => {
|
|
39277
39573
|
const actions = computeStreamChipActions({
|
|
39278
39574
|
brainPromptNow: !!brainPrompt,
|
|
39279
39575
|
brainPromptPrev: !!prevBrainPromptRef.current,
|
|
@@ -39285,7 +39581,7 @@ function useStreamChipExpiration({
|
|
|
39285
39581
|
prevBrainPromptRef.current = brainPrompt;
|
|
39286
39582
|
prevEnhanceRef.current = enhance;
|
|
39287
39583
|
}, [brainPrompt, enhance, visibleChips, dispatch]);
|
|
39288
|
-
|
|
39584
|
+
useEffect58(() => {
|
|
39289
39585
|
const interval = setInterval(() => {
|
|
39290
39586
|
const expired = computeExpiredChipKeys(visibleChips, Date.now());
|
|
39291
39587
|
for (const key of expired) {
|
|
@@ -39297,9 +39593,9 @@ function useStreamChipExpiration({
|
|
|
39297
39593
|
}
|
|
39298
39594
|
|
|
39299
39595
|
// src/hooks/use-theme-state.ts
|
|
39300
|
-
import { useEffect as
|
|
39596
|
+
import { useEffect as useEffect59 } from "react";
|
|
39301
39597
|
function useThemeState({ configStore }) {
|
|
39302
|
-
|
|
39598
|
+
useEffect59(() => {
|
|
39303
39599
|
if (!configStore) return;
|
|
39304
39600
|
const initial = configStore.get().themePreset;
|
|
39305
39601
|
if (initial && initial !== getActiveThemeName()) {
|
|
@@ -39318,10 +39614,11 @@ function useThemeState({ configStore }) {
|
|
|
39318
39614
|
}
|
|
39319
39615
|
|
|
39320
39616
|
// src/hooks/use-tui-activity.ts
|
|
39617
|
+
import * as fs5 from "node:fs/promises";
|
|
39321
39618
|
import * as os from "node:os";
|
|
39322
39619
|
import { loadGoal } from "@wrongstack/core/storage";
|
|
39323
39620
|
import { resolveWstackPaths as resolveWstackPaths5 } from "@wrongstack/core/utils";
|
|
39324
|
-
import { useCallback as
|
|
39621
|
+
import { useCallback as useCallback23, useEffect as useEffect60, useMemo as useMemo14, useRef as useRef36, useState as useState35 } from "react";
|
|
39325
39622
|
|
|
39326
39623
|
// src/heap-watchdog.ts
|
|
39327
39624
|
import {
|
|
@@ -39332,6 +39629,7 @@ import {
|
|
|
39332
39629
|
} from "@wrongstack/core/utils";
|
|
39333
39630
|
|
|
39334
39631
|
// src/hooks/use-tui-activity.ts
|
|
39632
|
+
var GOAL_FILE_MISSING = "missing";
|
|
39335
39633
|
function attachmentsSize(store) {
|
|
39336
39634
|
const items = store.items;
|
|
39337
39635
|
return items?.size ?? 0;
|
|
@@ -39365,10 +39663,10 @@ function useTuiActivity({
|
|
|
39365
39663
|
builderRef
|
|
39366
39664
|
}) {
|
|
39367
39665
|
recordTuiAppRender();
|
|
39368
|
-
const [rolledThinkingWord, setRolledThinkingWord] =
|
|
39666
|
+
const [rolledThinkingWord, setRolledThinkingWord] = useState35(() => pickRandomTuiThinkingWord());
|
|
39369
39667
|
const thinkingWorking = status === "running" || status === "streaming";
|
|
39370
|
-
const prevThinkingWorkingRef =
|
|
39371
|
-
|
|
39668
|
+
const prevThinkingWorkingRef = useRef36(false);
|
|
39669
|
+
useEffect60(() => {
|
|
39372
39670
|
if (thinkingWorking && !prevThinkingWorkingRef.current) {
|
|
39373
39671
|
setRolledThinkingWord((previous) => pickRandomTuiThinkingWord(previous));
|
|
39374
39672
|
}
|
|
@@ -39379,16 +39677,16 @@ function useTuiActivity({
|
|
|
39379
39677
|
() => Object.values(fleet).filter((entry) => entry.status === "running").length,
|
|
39380
39678
|
[fleet]
|
|
39381
39679
|
);
|
|
39382
|
-
const startedAtRef =
|
|
39383
|
-
const [nowTick, setNowTick] =
|
|
39384
|
-
|
|
39680
|
+
const startedAtRef = useRef36(Date.now());
|
|
39681
|
+
const [nowTick, setNowTick] = useState35(Date.now());
|
|
39682
|
+
useEffect60(() => {
|
|
39385
39683
|
const timer = setInterval(() => setNowTick(Date.now()), 1e4);
|
|
39386
39684
|
return () => clearInterval(timer);
|
|
39387
39685
|
}, []);
|
|
39388
|
-
const [workingTimeBase, setWorkingTimeBase] =
|
|
39389
|
-
const workingStartRef =
|
|
39390
|
-
const prevStatusRef =
|
|
39391
|
-
|
|
39686
|
+
const [workingTimeBase, setWorkingTimeBase] = useState35(0);
|
|
39687
|
+
const workingStartRef = useRef36(null);
|
|
39688
|
+
const prevStatusRef = useRef36(status);
|
|
39689
|
+
useEffect60(() => {
|
|
39392
39690
|
if (prevStatusRef.current === status) return;
|
|
39393
39691
|
const wasWorking = prevStatusRef.current === "running" || prevStatusRef.current === "streaming";
|
|
39394
39692
|
const isWorking = status === "running" || status === "streaming";
|
|
@@ -39401,10 +39699,10 @@ function useTuiActivity({
|
|
|
39401
39699
|
}
|
|
39402
39700
|
prevStatusRef.current = status;
|
|
39403
39701
|
}, [status]);
|
|
39404
|
-
const [fleetWorkingBase, setFleetWorkingBase] =
|
|
39405
|
-
const fleetWorkingStartRef =
|
|
39406
|
-
const prevFleetRunningRef =
|
|
39407
|
-
|
|
39702
|
+
const [fleetWorkingBase, setFleetWorkingBase] = useState35(0);
|
|
39703
|
+
const fleetWorkingStartRef = useRef36(null);
|
|
39704
|
+
const prevFleetRunningRef = useRef36(0);
|
|
39705
|
+
useEffect60(() => {
|
|
39408
39706
|
const running = fleetRunningCount;
|
|
39409
39707
|
if (prevFleetRunningRef.current === running) return;
|
|
39410
39708
|
const wasRunning = prevFleetRunningRef.current > 0;
|
|
@@ -39427,16 +39725,16 @@ function useTuiActivity({
|
|
|
39427
39725
|
const timingNow = Date.now();
|
|
39428
39726
|
const workingTimeMs = workingStartRef.current === null ? workingTimeBase : workingTimeBase + (timingNow - workingStartRef.current);
|
|
39429
39727
|
const fleetWorkingTimeMs = fleetWorkingStartRef.current === null ? fleetWorkingBase : fleetWorkingBase + (timingNow - fleetWorkingStartRef.current);
|
|
39430
|
-
const rssHistoryRef =
|
|
39431
|
-
const heapHistoryRef =
|
|
39728
|
+
const rssHistoryRef = useRef36([]);
|
|
39729
|
+
const heapHistoryRef = useRef36([]);
|
|
39432
39730
|
const processMemory = useMemo14(() => {
|
|
39433
39731
|
const sample = takeHeapSample();
|
|
39434
39732
|
pushMetricHistory(rssHistoryRef.current, Math.min(1, sample.rss / TOTAL_MEM));
|
|
39435
39733
|
pushMetricHistory(heapHistoryRef.current, Math.min(1, sample.load));
|
|
39436
39734
|
return sample;
|
|
39437
39735
|
}, [nowTick]);
|
|
39438
|
-
const cpuPrevRef =
|
|
39439
|
-
const cpuHistoryRef =
|
|
39736
|
+
const cpuPrevRef = useRef36(null);
|
|
39737
|
+
const cpuHistoryRef = useRef36([]);
|
|
39440
39738
|
const cpuPercent = useMemo14(() => {
|
|
39441
39739
|
const now = process.hrtime.bigint();
|
|
39442
39740
|
const cpuNow = process.cpuUsage();
|
|
@@ -39450,7 +39748,7 @@ function useTuiActivity({
|
|
|
39450
39748
|
pushMetricHistory(cpuHistoryRef.current, pct / 100);
|
|
39451
39749
|
return pct;
|
|
39452
39750
|
}, [nowTick]);
|
|
39453
|
-
|
|
39751
|
+
useEffect60(() => {
|
|
39454
39752
|
const stopHeapWatchdog = startSharedHeapWatchdog({
|
|
39455
39753
|
collectStats: () => {
|
|
39456
39754
|
const currentState = stateRef.current;
|
|
@@ -39494,13 +39792,27 @@ function useTuiActivity({
|
|
|
39494
39792
|
void stopHeapWatchdog();
|
|
39495
39793
|
};
|
|
39496
39794
|
}, [agentContext, dispatch, stateRef, attachments, builderRef]);
|
|
39497
|
-
const goalSummaryFingerprintRef =
|
|
39498
|
-
const goalSummaryGenerationRef =
|
|
39499
|
-
const
|
|
39795
|
+
const goalSummaryFingerprintRef = useRef36(void 0);
|
|
39796
|
+
const goalSummaryGenerationRef = useRef36(0);
|
|
39797
|
+
const goalStatFingerprintRef = useRef36(void 0);
|
|
39798
|
+
const refreshGoalSummary = useCallback23(() => {
|
|
39500
39799
|
const generation = ++goalSummaryGenerationRef.current;
|
|
39501
39800
|
if (!projectRoot) return;
|
|
39502
39801
|
const goalPath = resolveWstackPaths5({ projectRoot }).projectGoal;
|
|
39503
|
-
|
|
39802
|
+
fs5.stat(goalPath).then(
|
|
39803
|
+
(stat4) => {
|
|
39804
|
+
const statFingerprint = `${stat4.mtimeMs}:${stat4.size}`;
|
|
39805
|
+
if (statFingerprint === goalStatFingerprintRef.current) return void 0;
|
|
39806
|
+
goalStatFingerprintRef.current = statFingerprint;
|
|
39807
|
+
return loadGoal(goalPath);
|
|
39808
|
+
},
|
|
39809
|
+
() => {
|
|
39810
|
+
if (goalStatFingerprintRef.current === GOAL_FILE_MISSING) return void 0;
|
|
39811
|
+
goalStatFingerprintRef.current = GOAL_FILE_MISSING;
|
|
39812
|
+
return null;
|
|
39813
|
+
}
|
|
39814
|
+
).then((goal) => {
|
|
39815
|
+
if (goal === void 0) return;
|
|
39504
39816
|
if (generation !== goalSummaryGenerationRef.current) return;
|
|
39505
39817
|
if (!goal) {
|
|
39506
39818
|
if (goalSummaryFingerprintRef.current === "null") return;
|
|
@@ -39531,7 +39843,7 @@ function useTuiActivity({
|
|
|
39531
39843
|
}).catch(() => {
|
|
39532
39844
|
});
|
|
39533
39845
|
}, [dispatch, projectRoot]);
|
|
39534
|
-
|
|
39846
|
+
useEffect60(() => {
|
|
39535
39847
|
refreshGoalSummary();
|
|
39536
39848
|
}, [nowTick, refreshGoalSummary]);
|
|
39537
39849
|
const enhanceDots = enhanceBusy ? timingFrame % 36 : 0;
|
|
@@ -39554,7 +39866,7 @@ function useTuiActivity({
|
|
|
39554
39866
|
}
|
|
39555
39867
|
|
|
39556
39868
|
// src/hooks/use-tui-controllers.ts
|
|
39557
|
-
import { useEffect as
|
|
39869
|
+
import { useEffect as useEffect61 } from "react";
|
|
39558
39870
|
function useTuiControllers({
|
|
39559
39871
|
dispatch,
|
|
39560
39872
|
fleetChat,
|
|
@@ -39564,7 +39876,7 @@ function useTuiControllers({
|
|
|
39564
39876
|
enhanceController,
|
|
39565
39877
|
agentsMonitorController
|
|
39566
39878
|
}) {
|
|
39567
|
-
|
|
39879
|
+
useEffect61(() => {
|
|
39568
39880
|
if (!fleetStreamController) return;
|
|
39569
39881
|
fleetStreamController.mode = fleetChat;
|
|
39570
39882
|
fleetStreamController.setMode = (mode) => {
|
|
@@ -39576,12 +39888,12 @@ function useTuiControllers({
|
|
|
39576
39888
|
};
|
|
39577
39889
|
};
|
|
39578
39890
|
}, [dispatch, fleetStreamController, fleetChat]);
|
|
39579
|
-
|
|
39891
|
+
useEffect61(() => {
|
|
39580
39892
|
if (fleetStreamController) {
|
|
39581
39893
|
fleetStreamController.mode = fleetChat;
|
|
39582
39894
|
}
|
|
39583
39895
|
}, [fleetStreamController, fleetChat]);
|
|
39584
|
-
|
|
39896
|
+
useEffect61(() => {
|
|
39585
39897
|
if (!enhanceController) return;
|
|
39586
39898
|
enhanceController.enabled = enhanceEnabled;
|
|
39587
39899
|
enhanceController.setEnabled = (enabled) => {
|
|
@@ -39593,7 +39905,7 @@ function useTuiControllers({
|
|
|
39593
39905
|
};
|
|
39594
39906
|
};
|
|
39595
39907
|
}, [dispatch, enhanceController, enhanceEnabled]);
|
|
39596
|
-
|
|
39908
|
+
useEffect61(() => {
|
|
39597
39909
|
if (!agentsMonitorController) return;
|
|
39598
39910
|
agentsMonitorController.visible = agentsMonitorOpen;
|
|
39599
39911
|
agentsMonitorController.setVisible = (visible) => {
|
|
@@ -39607,28 +39919,28 @@ function useTuiControllers({
|
|
|
39607
39919
|
};
|
|
39608
39920
|
};
|
|
39609
39921
|
}, [agentsMonitorController, agentsMonitorOpen, dispatch]);
|
|
39610
|
-
|
|
39922
|
+
useEffect61(() => {
|
|
39611
39923
|
if (agentsMonitorController) agentsMonitorController.visible = agentsMonitorOpen;
|
|
39612
39924
|
}, [agentsMonitorController, agentsMonitorOpen]);
|
|
39613
39925
|
}
|
|
39614
39926
|
|
|
39615
39927
|
// src/hooks/use-tui-environment-state.ts
|
|
39616
39928
|
import { getIndexState as getIndexState2, getProcessRegistry as getProcessRegistry9, onIndexStateChange } from "@wrongstack/tools";
|
|
39617
|
-
import { useEffect as
|
|
39929
|
+
import { useEffect as useEffect62, useRef as useRef37, useState as useState37 } from "react";
|
|
39618
39930
|
|
|
39619
39931
|
// src/hooks/use-statusline-state.ts
|
|
39620
|
-
import { useState as
|
|
39932
|
+
import { useState as useState36 } from "react";
|
|
39621
39933
|
function useStatuslineState(opts) {
|
|
39622
|
-
const [liveModel, setLiveModel] =
|
|
39623
|
-
const [liveProvider, setLiveProvider] =
|
|
39624
|
-
const [activeMaxContext, setActiveMaxContext] =
|
|
39625
|
-
const [yoloLive, setYoloLive] =
|
|
39626
|
-
const [autonomyLive, setAutonomyLive] =
|
|
39627
|
-
const [liveModeLabel, setLiveModeLabel] =
|
|
39628
|
-
const [hiddenItems, setHiddenItems] =
|
|
39934
|
+
const [liveModel, setLiveModel] = useState36(opts.model);
|
|
39935
|
+
const [liveProvider, setLiveProvider] = useState36(opts.provider ?? "agent");
|
|
39936
|
+
const [activeMaxContext, setActiveMaxContext] = useState36(opts.effectiveMaxContext);
|
|
39937
|
+
const [yoloLive, setYoloLive] = useState36(opts.yolo);
|
|
39938
|
+
const [autonomyLive, setAutonomyLive] = useState36(opts.getAutonomy?.() ?? "off");
|
|
39939
|
+
const [liveModeLabel, setLiveModeLabel] = useState36(opts.modeLabel ?? "");
|
|
39940
|
+
const [hiddenItems, setHiddenItems] = useState36(
|
|
39629
39941
|
Array.isArray(opts.statuslineHiddenItems) ? [...opts.statuslineHiddenItems] : [...opts.statuslineHiddenItems]
|
|
39630
39942
|
);
|
|
39631
|
-
const [sessionCount, setSessionCount] =
|
|
39943
|
+
const [sessionCount, setSessionCount] = useState36(0);
|
|
39632
39944
|
return {
|
|
39633
39945
|
liveModel,
|
|
39634
39946
|
setLiveModel,
|
|
@@ -39665,14 +39977,14 @@ function useTuiEnvironmentState({
|
|
|
39665
39977
|
setStatuslineHiddenItems,
|
|
39666
39978
|
saveStatuslineHiddenItems
|
|
39667
39979
|
}) {
|
|
39668
|
-
const [memoryContextMonitor, setMemoryContextMonitor] =
|
|
39669
|
-
const [memoryRecordTotal, setMemoryRecordTotal] =
|
|
39670
|
-
const memoryContextMonitorRef =
|
|
39980
|
+
const [memoryContextMonitor, setMemoryContextMonitor] = useState37(emptyMemoryContextMonitor);
|
|
39981
|
+
const [memoryRecordTotal, setMemoryRecordTotal] = useState37();
|
|
39982
|
+
const memoryContextMonitorRef = useRef37(memoryContextMonitor);
|
|
39671
39983
|
memoryContextMonitorRef.current = memoryContextMonitor;
|
|
39672
|
-
const memoryRecordTotalRef =
|
|
39984
|
+
const memoryRecordTotalRef = useRef37(memoryRecordTotal);
|
|
39673
39985
|
memoryRecordTotalRef.current = memoryRecordTotal;
|
|
39674
39986
|
const activeMemoryInContext = activeMemoryContextCount(memoryContextMonitor);
|
|
39675
|
-
|
|
39987
|
+
useEffect62(() => {
|
|
39676
39988
|
let cancelled = false;
|
|
39677
39989
|
const refreshTotal = async () => {
|
|
39678
39990
|
try {
|
|
@@ -39698,19 +40010,19 @@ function useTuiEnvironmentState({
|
|
|
39698
40010
|
modeLabel,
|
|
39699
40011
|
statuslineHiddenItems
|
|
39700
40012
|
});
|
|
39701
|
-
const hiddenItemsRef =
|
|
40013
|
+
const hiddenItemsRef = useRef37(statusline.hiddenItems);
|
|
39702
40014
|
hiddenItemsRef.current = statusline.hiddenItems;
|
|
39703
|
-
const [liveToolCount, setLiveToolCount] =
|
|
39704
|
-
|
|
39705
|
-
const [indexState, setIndexState] =
|
|
39706
|
-
|
|
40015
|
+
const [liveToolCount, setLiveToolCount] = useState37(toolCount);
|
|
40016
|
+
useEffect62(() => setLiveToolCount(toolCount), [toolCount]);
|
|
40017
|
+
const [indexState, setIndexState] = useState37(() => getIndexState2());
|
|
40018
|
+
useEffect62(() => {
|
|
39707
40019
|
setIndexState(getIndexState2());
|
|
39708
40020
|
return onIndexStateChange(setIndexState);
|
|
39709
40021
|
}, []);
|
|
39710
|
-
const [breakerCountdown, setBreakerCountdown] =
|
|
40022
|
+
const [breakerCountdown, setBreakerCountdown] = useState37(
|
|
39711
40023
|
() => getProcessRegistry9().getBreakerCountdown()
|
|
39712
40024
|
);
|
|
39713
|
-
|
|
40025
|
+
useEffect62(() => {
|
|
39714
40026
|
const settings = getSettings?.();
|
|
39715
40027
|
if (settings) {
|
|
39716
40028
|
getProcessRegistry9().setBreakerConfig({
|
|
@@ -39721,7 +40033,7 @@ function useTuiEnvironmentState({
|
|
|
39721
40033
|
return getProcessRegistry9().onBreakerCountdownChange(setBreakerCountdown);
|
|
39722
40034
|
}, [getSettings]);
|
|
39723
40035
|
const breakerArmed = breakerCountdown !== null;
|
|
39724
|
-
|
|
40036
|
+
useEffect62(() => {
|
|
39725
40037
|
if (!breakerArmed) return;
|
|
39726
40038
|
const timer = setInterval(
|
|
39727
40039
|
() => setBreakerCountdown(getProcessRegistry9().getBreakerCountdown()),
|
|
@@ -39729,10 +40041,10 @@ function useTuiEnvironmentState({
|
|
|
39729
40041
|
);
|
|
39730
40042
|
return () => clearInterval(timer);
|
|
39731
40043
|
}, [breakerArmed]);
|
|
39732
|
-
|
|
40044
|
+
useEffect62(() => {
|
|
39733
40045
|
statusline.setHiddenItems([...statuslineHiddenItems]);
|
|
39734
40046
|
}, [statuslineHiddenItems, statusline.setHiddenItems]);
|
|
39735
|
-
|
|
40047
|
+
useEffect62(() => {
|
|
39736
40048
|
setStatuslineHiddenItems(statusline.hiddenItems);
|
|
39737
40049
|
saveStatuslineHiddenItems(statusline.hiddenItems).catch?.((error) => {
|
|
39738
40050
|
console.error(
|
|
@@ -39762,13 +40074,13 @@ function useTuiEnvironmentState({
|
|
|
39762
40074
|
}
|
|
39763
40075
|
|
|
39764
40076
|
// src/hooks/use-tui-event-bridge.ts
|
|
39765
|
-
import { useCallback as
|
|
40077
|
+
import { useCallback as useCallback25, useEffect as useEffect65 } from "react";
|
|
39766
40078
|
|
|
39767
40079
|
// src/hooks/use-brain-events.ts
|
|
39768
|
-
import { useEffect as
|
|
40080
|
+
import { useEffect as useEffect63 } from "react";
|
|
39769
40081
|
var MONITOR_INTERVENTION_GRACE_MS = 5e3;
|
|
39770
40082
|
function useBrainEvents(events, dispatch, getSessionId) {
|
|
39771
|
-
|
|
40083
|
+
useEffect63(() => {
|
|
39772
40084
|
const isCurrentSession2 = (sessionId) => {
|
|
39773
40085
|
const current = getSessionId?.();
|
|
39774
40086
|
return !sessionId || !current || sessionId === current;
|
|
@@ -39938,7 +40250,7 @@ function useBrainEvents(events, dispatch, getSessionId) {
|
|
|
39938
40250
|
|
|
39939
40251
|
// src/hooks/use-subagent-events.ts
|
|
39940
40252
|
import { expectDefined as expectDefined5 } from "@wrongstack/core/utils";
|
|
39941
|
-
import { useCallback as
|
|
40253
|
+
import { useCallback as useCallback24, useEffect as useEffect64, useRef as useRef38 } from "react";
|
|
39942
40254
|
var STREAM_COLORS2 = ["cyan", "magenta", "yellow", "green", "blue"];
|
|
39943
40255
|
function providerContextLimitHistoryEntry(event) {
|
|
39944
40256
|
if (event.source !== "provider" || event.decreased !== true || typeof event.previousMaxContext !== "number" || event.previousMaxContext <= event.maxContext) {
|
|
@@ -39981,21 +40293,21 @@ function labelFor2(labelsRef, id, name) {
|
|
|
39981
40293
|
return v;
|
|
39982
40294
|
}
|
|
39983
40295
|
function useSubagentEvents(events, dispatch, setActiveMaxContext, getSessionId, getChatMode, sessionGenerationRef) {
|
|
39984
|
-
const labelsRef =
|
|
39985
|
-
const ctxDispatchRef =
|
|
40296
|
+
const labelsRef = useRef38(/* @__PURE__ */ new Map());
|
|
40297
|
+
const ctxDispatchRef = useRef38(
|
|
39986
40298
|
/* @__PURE__ */ new Map()
|
|
39987
40299
|
);
|
|
39988
|
-
const leaderCtxDispatchRef =
|
|
39989
|
-
const leaderCtxFlushRef =
|
|
39990
|
-
const latestLeaderCtxPctRef =
|
|
39991
|
-
const ctxFlushRef =
|
|
40300
|
+
const leaderCtxDispatchRef = useRef38(void 0);
|
|
40301
|
+
const leaderCtxFlushRef = useRef38(void 0);
|
|
40302
|
+
const latestLeaderCtxPctRef = useRef38(void 0);
|
|
40303
|
+
const ctxFlushRef = useRef38(/* @__PURE__ */ new Map());
|
|
39992
40304
|
const gate = useFleetGenerationGate(sessionGenerationRef);
|
|
39993
|
-
const lbl =
|
|
40305
|
+
const lbl = useCallback24(
|
|
39994
40306
|
(id, name) => labelFor2(labelsRef, id, name),
|
|
39995
40307
|
[]
|
|
39996
40308
|
// labelsRef is a stable ref
|
|
39997
40309
|
);
|
|
39998
|
-
|
|
40310
|
+
useEffect64(() => {
|
|
39999
40311
|
const seen = /* @__PURE__ */ new Set();
|
|
40000
40312
|
const isCurrentSession2 = (sessionId) => {
|
|
40001
40313
|
const current = getSessionId?.();
|
|
@@ -40333,14 +40645,14 @@ function useTuiEventBridge({
|
|
|
40333
40645
|
onClearHistory,
|
|
40334
40646
|
sessionGenerationRef
|
|
40335
40647
|
}) {
|
|
40336
|
-
const getChatMode =
|
|
40648
|
+
const getChatMode = useCallback25(() => stateRef.current.fleetChat, [stateRef]);
|
|
40337
40649
|
useSubagentEvents(events, dispatch, setActiveMaxContext, getSessionId, getChatMode, sessionGenerationRef);
|
|
40338
40650
|
useSessionEvents(events, dispatch, onClearHistory, getSessionId);
|
|
40339
40651
|
useBrainEvents(events, dispatch, getSessionId);
|
|
40340
40652
|
useGoalEvents(subscribeGoal, dispatch, stateRef, getSessionId);
|
|
40341
40653
|
}
|
|
40342
40654
|
function useSessionEvents(events, dispatch, onClearHistory, getSessionId) {
|
|
40343
|
-
|
|
40655
|
+
useEffect65(() => {
|
|
40344
40656
|
const isCurrentSession2 = (sessionId) => {
|
|
40345
40657
|
const current = getSessionId?.();
|
|
40346
40658
|
return !sessionId || !current || sessionId === current;
|
|
@@ -40371,7 +40683,7 @@ function useSessionEvents(events, dispatch, onClearHistory, getSessionId) {
|
|
|
40371
40683
|
}, [events, dispatch, onClearHistory, getSessionId]);
|
|
40372
40684
|
}
|
|
40373
40685
|
function useGoalEvents(subscribeGoal, dispatch, stateRef, getSessionId) {
|
|
40374
|
-
|
|
40686
|
+
useEffect65(() => {
|
|
40375
40687
|
if (!subscribeGoal) return;
|
|
40376
40688
|
const isCurrentSession2 = (sessionId) => {
|
|
40377
40689
|
const current = getSessionId?.();
|
|
@@ -40594,10 +40906,7 @@ import {
|
|
|
40594
40906
|
} from "@wrongstack/core/design";
|
|
40595
40907
|
import { SKILL_LIMITS, stripFrontmatter } from "@wrongstack/core/skills";
|
|
40596
40908
|
import { toErrorMessage as toErrorMessage9 } from "@wrongstack/core/utils";
|
|
40597
|
-
import {
|
|
40598
|
-
useEffect as useEffect65,
|
|
40599
|
-
useRef as useRef38
|
|
40600
|
-
} from "react";
|
|
40909
|
+
import { useEffect as useEffect66 } from "react";
|
|
40601
40910
|
function useTuiSlashCommands({
|
|
40602
40911
|
slashRegistry,
|
|
40603
40912
|
skillLoader,
|
|
@@ -40621,17 +40930,7 @@ function useTuiSlashCommands({
|
|
|
40621
40930
|
listSessions,
|
|
40622
40931
|
openPromptPicker
|
|
40623
40932
|
}) {
|
|
40624
|
-
|
|
40625
|
-
new Map(
|
|
40626
|
-
["fallback", "profile", "provider-status", "memory", "worktree", "git"].map(
|
|
40627
|
-
(name) => [name, slashRegistry.get(name)]
|
|
40628
|
-
)
|
|
40629
|
-
)
|
|
40630
|
-
);
|
|
40631
|
-
const panelOriginalsRef = useRef38(
|
|
40632
|
-
new Map(["cron", "prompts"].map((name) => [name, slashRegistry.get(name)]))
|
|
40633
|
-
);
|
|
40634
|
-
useEffect65(() => {
|
|
40933
|
+
useEffect66(() => {
|
|
40635
40934
|
if (!getPickableProviders || !switchProviderAndModel) return;
|
|
40636
40935
|
const cmd = {
|
|
40637
40936
|
name: "model",
|
|
@@ -40642,12 +40941,12 @@ function useTuiSlashCommands({
|
|
|
40642
40941
|
return { message: void 0 };
|
|
40643
40942
|
}
|
|
40644
40943
|
};
|
|
40645
|
-
slashRegistry
|
|
40646
|
-
|
|
40647
|
-
|
|
40648
|
-
};
|
|
40944
|
+
return registerSlashCommandLifecycle(slashRegistry, cmd, {
|
|
40945
|
+
owner: "tui",
|
|
40946
|
+
official: true
|
|
40947
|
+
});
|
|
40649
40948
|
}, [slashRegistry, getPickableProviders, switchProviderAndModel, openModelPicker]);
|
|
40650
|
-
|
|
40949
|
+
useEffect66(() => {
|
|
40651
40950
|
const cmd = {
|
|
40652
40951
|
name: "f",
|
|
40653
40952
|
description: "Open F-key panel picker. Arrow keys to navigate, Enter to open, Esc to close.",
|
|
@@ -40656,12 +40955,12 @@ function useTuiSlashCommands({
|
|
|
40656
40955
|
return { message: void 0 };
|
|
40657
40956
|
}
|
|
40658
40957
|
};
|
|
40659
|
-
slashRegistry
|
|
40660
|
-
|
|
40661
|
-
|
|
40662
|
-
};
|
|
40958
|
+
return registerSlashCommandLifecycle(slashRegistry, cmd, {
|
|
40959
|
+
owner: "tui",
|
|
40960
|
+
official: true
|
|
40961
|
+
});
|
|
40663
40962
|
}, [slashRegistry, openFKeyPicker]);
|
|
40664
|
-
|
|
40963
|
+
useEffect66(() => {
|
|
40665
40964
|
const cmd = {
|
|
40666
40965
|
name: "design",
|
|
40667
40966
|
description: "Design Studio: /design (picker) | <kit> [stack] | off | foundations | set <k=v> | tune <k=v> | swap <kit> | materialize [stack] [path] | verify.",
|
|
@@ -40758,7 +41057,7 @@ ${menu}` };
|
|
|
40758
41057
|
kitId: active.kit,
|
|
40759
41058
|
outPath
|
|
40760
41059
|
});
|
|
40761
|
-
const
|
|
41060
|
+
const fsp3 = await import("node:fs/promises");
|
|
40762
41061
|
const nodePath = await import("node:path");
|
|
40763
41062
|
const { resolveMaterializeTarget } = await import("@wrongstack/core/design");
|
|
40764
41063
|
let abs;
|
|
@@ -40768,8 +41067,8 @@ ${menu}` };
|
|
|
40768
41067
|
return { message: e.message };
|
|
40769
41068
|
}
|
|
40770
41069
|
try {
|
|
40771
|
-
await
|
|
40772
|
-
await
|
|
41070
|
+
await fsp3.mkdir(nodePath.dirname(abs), { recursive: true });
|
|
41071
|
+
await fsp3.writeFile(abs, result.content);
|
|
40773
41072
|
} catch (e) {
|
|
40774
41073
|
return { message: `Failed to write ${result.path}: ${e.message}` };
|
|
40775
41074
|
}
|
|
@@ -40788,12 +41087,12 @@ ${menu}` };
|
|
|
40788
41087
|
return { runText: `design use ${kit.id}${stack ? ` --stack ${stack}` : ""}` };
|
|
40789
41088
|
}
|
|
40790
41089
|
};
|
|
40791
|
-
slashRegistry
|
|
40792
|
-
|
|
40793
|
-
|
|
40794
|
-
};
|
|
41090
|
+
return registerSlashCommandLifecycle(slashRegistry, cmd, {
|
|
41091
|
+
owner: "tui",
|
|
41092
|
+
official: true
|
|
41093
|
+
});
|
|
40795
41094
|
}, [slashRegistry, projectRoot, agent]);
|
|
40796
|
-
|
|
41095
|
+
useEffect66(() => {
|
|
40797
41096
|
if (!getSettings || !saveSettings) return;
|
|
40798
41097
|
const cmd = {
|
|
40799
41098
|
name: "settings",
|
|
@@ -40895,12 +41194,12 @@ Available chords:
|
|
|
40895
41194
|
return { message: void 0 };
|
|
40896
41195
|
}
|
|
40897
41196
|
};
|
|
40898
|
-
slashRegistry
|
|
40899
|
-
|
|
40900
|
-
|
|
40901
|
-
};
|
|
41197
|
+
return registerSlashCommandLifecycle(slashRegistry, cmd, {
|
|
41198
|
+
owner: "tui",
|
|
41199
|
+
official: true
|
|
41200
|
+
});
|
|
40902
41201
|
}, [slashRegistry, getSettings, saveSettings, openSettings, dispatch]);
|
|
40903
|
-
|
|
41202
|
+
useEffect66(() => {
|
|
40904
41203
|
const cmd = {
|
|
40905
41204
|
name: "settings-get",
|
|
40906
41205
|
aliases: ["config-get", "get"],
|
|
@@ -40927,12 +41226,12 @@ Available chords:
|
|
|
40927
41226
|
return { message: `${result.label}: ${result.displayValue}` };
|
|
40928
41227
|
}
|
|
40929
41228
|
};
|
|
40930
|
-
slashRegistry
|
|
40931
|
-
|
|
40932
|
-
|
|
40933
|
-
};
|
|
41229
|
+
return registerSlashCommandLifecycle(slashRegistry, cmd, {
|
|
41230
|
+
owner: "tui",
|
|
41231
|
+
official: true
|
|
41232
|
+
});
|
|
40934
41233
|
}, [slashRegistry, state.settingsPicker]);
|
|
40935
|
-
|
|
41234
|
+
useEffect66(() => {
|
|
40936
41235
|
const cmd = {
|
|
40937
41236
|
name: "statusline",
|
|
40938
41237
|
aliases: ["sl"],
|
|
@@ -40980,12 +41279,12 @@ Available chords:
|
|
|
40980
41279
|
return { message: void 0 };
|
|
40981
41280
|
}
|
|
40982
41281
|
};
|
|
40983
|
-
slashRegistry
|
|
40984
|
-
|
|
40985
|
-
|
|
40986
|
-
};
|
|
41282
|
+
return registerSlashCommandLifecycle(slashRegistry, cmd, {
|
|
41283
|
+
owner: "tui",
|
|
41284
|
+
official: true
|
|
41285
|
+
});
|
|
40987
41286
|
}, [slashRegistry, openStatuslinePicker, setHiddenItems]);
|
|
40988
|
-
|
|
41287
|
+
useEffect66(() => {
|
|
40989
41288
|
const cmd = {
|
|
40990
41289
|
name: "mailbox",
|
|
40991
41290
|
aliases: ["inbox", "mail"],
|
|
@@ -40995,12 +41294,12 @@ Available chords:
|
|
|
40995
41294
|
return { message: void 0 };
|
|
40996
41295
|
}
|
|
40997
41296
|
};
|
|
40998
|
-
slashRegistry
|
|
40999
|
-
|
|
41000
|
-
|
|
41001
|
-
};
|
|
41297
|
+
return registerSlashCommandLifecycle(slashRegistry, cmd, {
|
|
41298
|
+
owner: "tui",
|
|
41299
|
+
official: true
|
|
41300
|
+
});
|
|
41002
41301
|
}, [slashRegistry]);
|
|
41003
|
-
|
|
41302
|
+
useEffect66(() => {
|
|
41004
41303
|
if (!switchAutonomy) return;
|
|
41005
41304
|
const cmd = {
|
|
41006
41305
|
name: "autonomy",
|
|
@@ -41011,12 +41310,12 @@ Available chords:
|
|
|
41011
41310
|
return { message: void 0 };
|
|
41012
41311
|
}
|
|
41013
41312
|
};
|
|
41014
|
-
slashRegistry
|
|
41015
|
-
|
|
41016
|
-
|
|
41017
|
-
};
|
|
41313
|
+
return registerSlashCommandLifecycle(slashRegistry, cmd, {
|
|
41314
|
+
owner: "tui",
|
|
41315
|
+
official: true
|
|
41316
|
+
});
|
|
41018
41317
|
}, [slashRegistry, switchAutonomy]);
|
|
41019
|
-
|
|
41318
|
+
useEffect66(() => {
|
|
41020
41319
|
if (!skillLoader) return;
|
|
41021
41320
|
const cmd = {
|
|
41022
41321
|
name: "skill",
|
|
@@ -41045,72 +41344,78 @@ Available chords:
|
|
|
41045
41344
|
}
|
|
41046
41345
|
}
|
|
41047
41346
|
};
|
|
41048
|
-
slashRegistry
|
|
41049
|
-
|
|
41050
|
-
|
|
41051
|
-
};
|
|
41347
|
+
return registerSlashCommandLifecycle(slashRegistry, cmd, {
|
|
41348
|
+
owner: "tui",
|
|
41349
|
+
official: true
|
|
41350
|
+
});
|
|
41052
41351
|
}, [slashRegistry, skillLoader, dispatch]);
|
|
41053
|
-
|
|
41352
|
+
useEffect66(() => {
|
|
41054
41353
|
if (!getResourceMenu) return;
|
|
41055
41354
|
const names = ["fallback", "profile", "provider-status", "memory", "worktree", "git"];
|
|
41355
|
+
const cleanups = [];
|
|
41056
41356
|
for (const name of names) {
|
|
41057
|
-
const original =
|
|
41058
|
-
|
|
41059
|
-
|
|
41060
|
-
|
|
41061
|
-
|
|
41062
|
-
|
|
41063
|
-
|
|
41064
|
-
|
|
41065
|
-
|
|
41066
|
-
|
|
41067
|
-
|
|
41068
|
-
|
|
41069
|
-
|
|
41070
|
-
|
|
41071
|
-
|
|
41072
|
-
|
|
41357
|
+
const original = slashRegistry.get(name);
|
|
41358
|
+
cleanups.push(
|
|
41359
|
+
registerSlashCommandLifecycle(
|
|
41360
|
+
slashRegistry,
|
|
41361
|
+
{
|
|
41362
|
+
name,
|
|
41363
|
+
description: original?.description ?? `Browse ${name} state interactively.`,
|
|
41364
|
+
argsHint: original?.argsHint,
|
|
41365
|
+
help: original?.help,
|
|
41366
|
+
async run(args, ctx) {
|
|
41367
|
+
if (args.trim())
|
|
41368
|
+
return original?.run(args, ctx) ?? { message: `/${name} is unavailable.` };
|
|
41369
|
+
try {
|
|
41370
|
+
const snapshot = await getResourceMenu(name);
|
|
41371
|
+
dispatch({ type: "resourceMenuOpen", snapshot });
|
|
41372
|
+
return { message: void 0 };
|
|
41373
|
+
} catch (err) {
|
|
41374
|
+
return { message: `Could not load ${name}: ${toErrorMessage9(err)}` };
|
|
41375
|
+
}
|
|
41073
41376
|
}
|
|
41074
|
-
}
|
|
41075
|
-
|
|
41076
|
-
|
|
41077
|
-
{ official: true }
|
|
41377
|
+
},
|
|
41378
|
+
{ owner: "tui", official: true }
|
|
41379
|
+
)
|
|
41078
41380
|
);
|
|
41079
41381
|
}
|
|
41080
41382
|
return () => {
|
|
41081
|
-
for (const
|
|
41383
|
+
for (const cleanup of [...cleanups].reverse()) cleanup();
|
|
41082
41384
|
};
|
|
41083
41385
|
}, [slashRegistry, getResourceMenu, dispatch]);
|
|
41084
|
-
|
|
41386
|
+
useEffect66(() => {
|
|
41085
41387
|
const definitions = [
|
|
41086
41388
|
{ name: "cron", open: () => dispatch({ type: "toggleCronMonitor" }) },
|
|
41087
41389
|
{ name: "prompts", open: () => void openPromptPicker() }
|
|
41088
41390
|
];
|
|
41391
|
+
const cleanups = [];
|
|
41089
41392
|
for (const definition of definitions) {
|
|
41090
|
-
const original =
|
|
41091
|
-
|
|
41092
|
-
|
|
41093
|
-
|
|
41094
|
-
|
|
41095
|
-
|
|
41096
|
-
|
|
41097
|
-
|
|
41098
|
-
|
|
41099
|
-
|
|
41393
|
+
const original = slashRegistry.get(definition.name);
|
|
41394
|
+
cleanups.push(
|
|
41395
|
+
registerSlashCommandLifecycle(
|
|
41396
|
+
slashRegistry,
|
|
41397
|
+
{
|
|
41398
|
+
name: definition.name,
|
|
41399
|
+
description: original?.description ?? `Open the ${definition.name} browser.`,
|
|
41400
|
+
argsHint: original?.argsHint,
|
|
41401
|
+
help: original?.help,
|
|
41402
|
+
async run(args, ctx) {
|
|
41403
|
+
if (args.trim()) {
|
|
41404
|
+
return original?.run(args, ctx) ?? { message: `/${definition.name} is unavailable.` };
|
|
41405
|
+
}
|
|
41406
|
+
definition.open();
|
|
41407
|
+
return { message: void 0 };
|
|
41100
41408
|
}
|
|
41101
|
-
|
|
41102
|
-
|
|
41103
|
-
|
|
41104
|
-
},
|
|
41105
|
-
"tui",
|
|
41106
|
-
{ official: true }
|
|
41409
|
+
},
|
|
41410
|
+
{ owner: "tui", official: true }
|
|
41411
|
+
)
|
|
41107
41412
|
);
|
|
41108
41413
|
}
|
|
41109
41414
|
return () => {
|
|
41110
|
-
for (const
|
|
41415
|
+
for (const cleanup of [...cleanups].reverse()) cleanup();
|
|
41111
41416
|
};
|
|
41112
41417
|
}, [slashRegistry, dispatch, openPromptPicker]);
|
|
41113
|
-
|
|
41418
|
+
useEffect66(() => {
|
|
41114
41419
|
const cmd = {
|
|
41115
41420
|
name: "theme",
|
|
41116
41421
|
description: "Pick a TUI color theme preset interactively (picker).",
|
|
@@ -41137,12 +41442,12 @@ Available chords:
|
|
|
41137
41442
|
return { message: void 0 };
|
|
41138
41443
|
}
|
|
41139
41444
|
};
|
|
41140
|
-
slashRegistry
|
|
41141
|
-
|
|
41142
|
-
|
|
41143
|
-
};
|
|
41445
|
+
return registerSlashCommandLifecycle(slashRegistry, cmd, {
|
|
41446
|
+
owner: "tui",
|
|
41447
|
+
official: true
|
|
41448
|
+
});
|
|
41144
41449
|
}, [slashRegistry, dispatch]);
|
|
41145
|
-
|
|
41450
|
+
useEffect66(() => {
|
|
41146
41451
|
const cmd = {
|
|
41147
41452
|
name: "resume",
|
|
41148
41453
|
aliases: ["load"],
|
|
@@ -41165,28 +41470,28 @@ Available chords:
|
|
|
41165
41470
|
return { message: void 0 };
|
|
41166
41471
|
}
|
|
41167
41472
|
};
|
|
41168
|
-
slashRegistry
|
|
41169
|
-
|
|
41170
|
-
|
|
41171
|
-
};
|
|
41473
|
+
return registerSlashCommandLifecycle(slashRegistry, cmd, {
|
|
41474
|
+
owner: "tui",
|
|
41475
|
+
official: true
|
|
41476
|
+
});
|
|
41172
41477
|
}, [slashRegistry, listSessions]);
|
|
41173
41478
|
}
|
|
41174
41479
|
|
|
41175
41480
|
// src/hooks/use-working-dir-chip.ts
|
|
41176
|
-
import * as
|
|
41177
|
-
import { useEffect as
|
|
41481
|
+
import * as path8 from "node:path";
|
|
41482
|
+
import { useEffect as useEffect67, useState as useState38 } from "react";
|
|
41178
41483
|
function formatWorkingDirChip(workingDir, projectRoot) {
|
|
41179
41484
|
if (!workingDir || workingDir === projectRoot) return void 0;
|
|
41180
|
-
const impl = workingDir.includes("\\") || projectRoot.includes("\\") ?
|
|
41485
|
+
const impl = workingDir.includes("\\") || projectRoot.includes("\\") ? path8.win32 : path8;
|
|
41181
41486
|
const rel = impl.relative(projectRoot, workingDir) || ".";
|
|
41182
41487
|
if (rel === ".") return void 0;
|
|
41183
41488
|
return rel.replaceAll(impl.sep, "/");
|
|
41184
41489
|
}
|
|
41185
41490
|
function useWorkingDirChip(ctx, projectRoot) {
|
|
41186
|
-
const [workingDirChip, setWorkingDirChip] =
|
|
41491
|
+
const [workingDirChip, setWorkingDirChip] = useState38(
|
|
41187
41492
|
() => formatWorkingDirChip(ctx.workingDir, projectRoot)
|
|
41188
41493
|
);
|
|
41189
|
-
|
|
41494
|
+
useEffect67(() => {
|
|
41190
41495
|
setWorkingDirChip(formatWorkingDirChip(ctx.workingDir, projectRoot));
|
|
41191
41496
|
return ctx.onWorkingDirChanged((newDir) => {
|
|
41192
41497
|
setWorkingDirChip(formatWorkingDirChip(newDir, projectRoot));
|
|
@@ -43518,14 +43823,16 @@ function App(props) {
|
|
|
43518
43823
|
sessionsDir
|
|
43519
43824
|
});
|
|
43520
43825
|
const historyScrollRef = useRef39(null);
|
|
43521
|
-
const onScrollInfo =
|
|
43826
|
+
const onScrollInfo = useCallback26(
|
|
43522
43827
|
(info) => dispatch({ type: "setHistoryScrolled", scrolled: info.scrolled }),
|
|
43523
43828
|
[dispatch]
|
|
43524
43829
|
);
|
|
43525
|
-
const onRequestOlderEntries =
|
|
43526
|
-
|
|
43527
|
-
|
|
43528
|
-
|
|
43830
|
+
const { onRequestOlderEntries } = useHistoryArchive({
|
|
43831
|
+
entries: state.entries,
|
|
43832
|
+
dispatch,
|
|
43833
|
+
sessionsDir,
|
|
43834
|
+
sessionId: agent.ctx.session?.id
|
|
43835
|
+
});
|
|
43529
43836
|
const onHistoryCopy = useHistoryCopyNotice(dispatch);
|
|
43530
43837
|
const { focusedBoardId, setFocusedBoardId, boardFocusRef } = useKanbanBoardFocus();
|
|
43531
43838
|
useInputHistoryPersistence({
|
|
@@ -43593,8 +43900,8 @@ function App(props) {
|
|
|
43593
43900
|
submitRef
|
|
43594
43901
|
} = useAppRuntimeRefs(attachments, state);
|
|
43595
43902
|
const projectName = React9.useMemo(() => {
|
|
43596
|
-
const base =
|
|
43597
|
-
return base && base !==
|
|
43903
|
+
const base = path9.basename(projectRoot);
|
|
43904
|
+
return base && base !== path9.sep ? base : void 0;
|
|
43598
43905
|
}, [projectRoot]);
|
|
43599
43906
|
const workingDirChip = useWorkingDirChip(agent.ctx, projectRoot);
|
|
43600
43907
|
const {
|
|
@@ -43613,7 +43920,7 @@ function App(props) {
|
|
|
43613
43920
|
liveSettings,
|
|
43614
43921
|
mailbox.mailboxPanelOpen
|
|
43615
43922
|
);
|
|
43616
|
-
|
|
43923
|
+
useEffect68(() => {
|
|
43617
43924
|
titleController?.setModel(liveModel);
|
|
43618
43925
|
}, [titleController, liveModel]);
|
|
43619
43926
|
const activity = useTuiActivity({
|
|
@@ -43629,11 +43936,11 @@ function App(props) {
|
|
|
43629
43936
|
builderRef
|
|
43630
43937
|
});
|
|
43631
43938
|
const { displayThinkingWord, refreshGoalSummary } = activity;
|
|
43632
|
-
const liveDirector =
|
|
43939
|
+
const liveDirector = useCallback26(
|
|
43633
43940
|
() => getDirector?.() ?? director,
|
|
43634
43941
|
[getDirector, director]
|
|
43635
43942
|
);
|
|
43636
|
-
const clearPendingConfirms =
|
|
43943
|
+
const clearPendingConfirms = useCallback26(() => {
|
|
43637
43944
|
const queue = stateRef.current.confirmQueue;
|
|
43638
43945
|
if (queue.length === 0) return;
|
|
43639
43946
|
for (const c of queue) {
|
|
@@ -43650,7 +43957,7 @@ function App(props) {
|
|
|
43650
43957
|
dispatch,
|
|
43651
43958
|
open: state.authPanel.open
|
|
43652
43959
|
});
|
|
43653
|
-
|
|
43960
|
+
useEffect68(() => {
|
|
43654
43961
|
if (!secretInputController) return;
|
|
43655
43962
|
const previousSecret = secretInputController.readSecret;
|
|
43656
43963
|
const previousText = secretInputController.readText;
|
|
@@ -43662,13 +43969,13 @@ function App(props) {
|
|
|
43662
43969
|
else delete secretInputController.readText;
|
|
43663
43970
|
};
|
|
43664
43971
|
}, [secretInputController, authPanelController.readSecret, authPanelController.readText]);
|
|
43665
|
-
const statuslineHiddenForPicker =
|
|
43972
|
+
const statuslineHiddenForPicker = useCallback26(() => {
|
|
43666
43973
|
return mergeStatuslineHiddenItems(
|
|
43667
43974
|
hiddenItemsRef.current,
|
|
43668
43975
|
stateRef.current.statuslinePicker.hiddenItems
|
|
43669
43976
|
);
|
|
43670
43977
|
}, []);
|
|
43671
|
-
const openStatuslinePicker =
|
|
43978
|
+
const openStatuslinePicker = useCallback26(
|
|
43672
43979
|
(field) => {
|
|
43673
43980
|
if (field !== void 0) {
|
|
43674
43981
|
dispatch({ type: "statuslineFieldSet", field });
|
|
@@ -43746,7 +44053,7 @@ function App(props) {
|
|
|
43746
44053
|
dispatch({ type: "clearInput" });
|
|
43747
44054
|
};
|
|
43748
44055
|
const staleGuardRef = useRef39(JSON.stringify({ a: "", y: false, m: "", model: "", provider: "" }));
|
|
43749
|
-
|
|
44056
|
+
useEffect68(() => {
|
|
43750
44057
|
const poll = () => {
|
|
43751
44058
|
const a = getAutonomy?.() ?? "off";
|
|
43752
44059
|
const y = getYolo?.() ?? false;
|
|
@@ -43962,8 +44269,8 @@ function App(props) {
|
|
|
43962
44269
|
saveSettings,
|
|
43963
44270
|
midRunSendPickerRef
|
|
43964
44271
|
});
|
|
43965
|
-
const getActiveSessionId =
|
|
43966
|
-
const getLeaderTranscript =
|
|
44272
|
+
const getActiveSessionId = useCallback26(() => agent.ctx.session.id, [agent]);
|
|
44273
|
+
const getLeaderTranscript = useCallback26(
|
|
43967
44274
|
() => leaderTimelineFromEntries(stateRef.current.entries),
|
|
43968
44275
|
[stateRef]
|
|
43969
44276
|
);
|
|
@@ -44032,7 +44339,7 @@ function App(props) {
|
|
|
44032
44339
|
setDraft,
|
|
44033
44340
|
tokenPreviewsRef
|
|
44034
44341
|
});
|
|
44035
|
-
const onThemePickerEnter =
|
|
44342
|
+
const onThemePickerEnter = useCallback26(() => {
|
|
44036
44343
|
const preset = THEME_OPTIONS[Math.max(0, state.themePicker.selected)];
|
|
44037
44344
|
const presetName = preset?.id;
|
|
44038
44345
|
if (!presetName) return;
|
|
@@ -44373,7 +44680,7 @@ import {
|
|
|
44373
44680
|
// src/run-tui.ts
|
|
44374
44681
|
import { createWriteStream } from "node:fs";
|
|
44375
44682
|
import { tmpdir } from "node:os";
|
|
44376
|
-
import { join as
|
|
44683
|
+
import { join as join8 } from "node:path";
|
|
44377
44684
|
import { detectTerminal, TerminalLifecycle, writeErr } from "@wrongstack/core/utils";
|
|
44378
44685
|
import { getProcessRegistry as getProcessRegistry10 } from "@wrongstack/tools";
|
|
44379
44686
|
import { render } from "ink";
|
|
@@ -44381,7 +44688,7 @@ import React10 from "react";
|
|
|
44381
44688
|
|
|
44382
44689
|
// src/run-tui-client-registration.ts
|
|
44383
44690
|
import { randomUUID } from "node:crypto";
|
|
44384
|
-
import * as
|
|
44691
|
+
import * as path10 from "node:path";
|
|
44385
44692
|
import { RemoteMailbox, resolveProjectDir } from "@wrongstack/core/coordination";
|
|
44386
44693
|
import {
|
|
44387
44694
|
createHqPublisherFromEnv,
|
|
@@ -44480,7 +44787,7 @@ function createRunTuiClientRegistration(opts) {
|
|
|
44480
44787
|
await mailbox.registerClient({
|
|
44481
44788
|
clientId,
|
|
44482
44789
|
sessionId: opts.getSessionId?.() ?? opts.projectRoot,
|
|
44483
|
-
name: `TUI [${
|
|
44790
|
+
name: `TUI [${path10.basename(opts.projectRoot)}]`,
|
|
44484
44791
|
source: "tui",
|
|
44485
44792
|
pid: process.pid
|
|
44486
44793
|
});
|
|
@@ -44498,7 +44805,7 @@ function createRunTuiClientRegistration(opts) {
|
|
|
44498
44805
|
tuiHqPublisher = createHqPublisherFromEnv({
|
|
44499
44806
|
clientKind: "tui",
|
|
44500
44807
|
projectRoot: opts.projectRoot,
|
|
44501
|
-
projectName:
|
|
44808
|
+
projectName: path10.basename(opts.projectRoot),
|
|
44502
44809
|
appConfig: opts.appConfig
|
|
44503
44810
|
});
|
|
44504
44811
|
tuiHqPublisher?.connect();
|
|
@@ -44511,7 +44818,7 @@ function createRunTuiClientRegistration(opts) {
|
|
|
44511
44818
|
events: opts.events,
|
|
44512
44819
|
sessionId: tuiSessionId,
|
|
44513
44820
|
projectRoot: opts.projectRoot,
|
|
44514
|
-
projectName:
|
|
44821
|
+
projectName: path10.basename(opts.projectRoot)
|
|
44515
44822
|
})
|
|
44516
44823
|
);
|
|
44517
44824
|
} catch {
|
|
@@ -44640,7 +44947,7 @@ function createRunTuiClientRegistration(opts) {
|
|
|
44640
44947
|
}
|
|
44641
44948
|
|
|
44642
44949
|
// src/run-tui-title-controller.ts
|
|
44643
|
-
import * as
|
|
44950
|
+
import * as path11 from "node:path";
|
|
44644
44951
|
|
|
44645
44952
|
// src/terminal-title.ts
|
|
44646
44953
|
var SPINNER = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
|
|
@@ -44720,7 +45027,7 @@ function createRunTuiTitleController(opts) {
|
|
|
44720
45027
|
stdout: opts.stdout,
|
|
44721
45028
|
events: opts.events,
|
|
44722
45029
|
model: currentModel,
|
|
44723
|
-
appName: opts.projectRoot ?
|
|
45030
|
+
appName: opts.projectRoot ? path11.basename(opts.projectRoot) : void 0
|
|
44724
45031
|
});
|
|
44725
45032
|
};
|
|
44726
45033
|
const stop = () => {
|
|
@@ -44810,7 +45117,7 @@ async function runTui(opts) {
|
|
|
44810
45117
|
const traceEnv = process.env["WRONGSTACK_TUI_TRACE"];
|
|
44811
45118
|
let restoreTrace = null;
|
|
44812
45119
|
if (traceEnv && traceEnv !== "0") {
|
|
44813
|
-
const tracePath = traceEnv === "1" ?
|
|
45120
|
+
const tracePath = traceEnv === "1" ? join8(tmpdir(), `wstack-tui-trace-${process.pid}.bin`) : traceEnv;
|
|
44814
45121
|
try {
|
|
44815
45122
|
const stream = createWriteStream(tracePath);
|
|
44816
45123
|
const realWrite = stdout.write.bind(stdout);
|