@wrongstack/tui 0.282.0 → 0.282.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/dist/index.d.ts +14 -18
- package/dist/index.js +638 -508
- package/dist/index.js.map +1 -1
- package/package.json +4 -4
package/dist/index.js
CHANGED
|
@@ -1,11 +1,10 @@
|
|
|
1
|
-
import { hasOpenTodos, writeErr, resolveProjectDir, wstackGlobalRoot, createHqPublisherFromEnv, startFleetTelemetryBridge, startBrainTelemetryBridge, startWorktreeTelemetryBridge, startToolTelemetryBridge, startCostTelemetryBridge, GlobalMailbox, resolveWstackPaths, loadGoal,
|
|
1
|
+
import { hasOpenTodos, writeErr, resolveProjectDir, wstackGlobalRoot, createHqPublisherFromEnv, startFleetTelemetryBridge, startBrainTelemetryBridge, startWorktreeTelemetryBridge, startToolTelemetryBridge, startCostTelemetryBridge, GlobalMailbox, resolveWstackPaths, loadGoal, InputBuilder, DefaultSessionRewinder, writeOut, formatTodosList, buildGoalPreamble, expectDefined as expectDefined$1, InputHistoryStore, DefaultSecretScrubber, INPUT_HISTORY_DEFAULT_MAX, DefaultPromptLoader, PromptUsageStore, getDesignKitLoader, clearActiveKit, clearPersistedActiveKit, recordOverrides, setDesignOverrides, loadActiveKit, isDesignStack, materializeTokens, applyTokenOverrides, setActiveKit, projectSlug, shouldEnhance, enhanceUserPrompt, recentTextTurns, normalizedEqual, setBtwNote, listBoards, getBoard, createBoard, addTask, buildChildEnv, removeTask, moveTask, updateTask, duplicateBoard, copyTaskToBoard, transferTaskToBoard } from '@wrongstack/core';
|
|
2
2
|
export { buildGoalPreamble } from '@wrongstack/core';
|
|
3
3
|
import { Box as Box$1, useStdout, Static, useInput, useStdin, measureElement, Text as Text$1, render, useApp } from 'ink';
|
|
4
4
|
import { randomUUID } from 'crypto';
|
|
5
|
-
import * as
|
|
5
|
+
import * as path9 from 'path';
|
|
6
6
|
import React5, { forwardRef, useState, useEffect, useMemo, memo, useRef, useLayoutEffect, useCallback, useReducer, isValidElement, Fragment as Fragment$1 } from 'react';
|
|
7
7
|
import * as fsp from 'fs/promises';
|
|
8
|
-
import { createRequire } from 'module';
|
|
9
8
|
import { expectDefined, toErrorMessage, resolveWstackPaths as resolveWstackPaths$1, sessionScopedPath } from '@wrongstack/core/utils';
|
|
10
9
|
import { routeImagesForModel } from '@wrongstack/runtime/vision';
|
|
11
10
|
import { getIndexState, onIndexStateChange, getProcessRegistry } from '@wrongstack/tools';
|
|
@@ -14,6 +13,7 @@ import { getToolIcon, TOOL_ICON_CONFIG } from '@wrongstack/tools/tool-icons';
|
|
|
14
13
|
import { spawn } from 'child_process';
|
|
15
14
|
import * as v8 from 'v8';
|
|
16
15
|
import { readClipboardText, readClipboardImage } from '@wrongstack/runtime/clipboard';
|
|
16
|
+
import { createRequire } from 'module';
|
|
17
17
|
|
|
18
18
|
// src/run-tui.ts
|
|
19
19
|
|
|
@@ -4156,6 +4156,36 @@ function StatusBar({
|
|
|
4156
4156
|
return () => clearInterval(t);
|
|
4157
4157
|
}, [state]);
|
|
4158
4158
|
const spinner = expectDefined$1(SPINNER_FRAMES[spinnerIdx]);
|
|
4159
|
+
const TODOS_CLEAR_DELAY_MS = 3e3;
|
|
4160
|
+
const [todosCleared, setTodosCleared] = useState(false);
|
|
4161
|
+
const todosClearTimerRef = useRef(null);
|
|
4162
|
+
useEffect(() => {
|
|
4163
|
+
const hasActive = todos && (todos.pending > 0 || todos.inProgress > 0);
|
|
4164
|
+
if (hasActive) {
|
|
4165
|
+
if (todosClearTimerRef.current) {
|
|
4166
|
+
clearTimeout(todosClearTimerRef.current);
|
|
4167
|
+
todosClearTimerRef.current = null;
|
|
4168
|
+
}
|
|
4169
|
+
setTodosCleared(false);
|
|
4170
|
+
return;
|
|
4171
|
+
}
|
|
4172
|
+
if (todos && todos.completed > 0) {
|
|
4173
|
+
if (!todosClearTimerRef.current) {
|
|
4174
|
+
todosClearTimerRef.current = setTimeout(() => {
|
|
4175
|
+
setTodosCleared(true);
|
|
4176
|
+
todosClearTimerRef.current = null;
|
|
4177
|
+
}, TODOS_CLEAR_DELAY_MS);
|
|
4178
|
+
}
|
|
4179
|
+
return () => {
|
|
4180
|
+
if (todosClearTimerRef.current) {
|
|
4181
|
+
clearTimeout(todosClearTimerRef.current);
|
|
4182
|
+
todosClearTimerRef.current = null;
|
|
4183
|
+
}
|
|
4184
|
+
};
|
|
4185
|
+
}
|
|
4186
|
+
setTodosCleared(true);
|
|
4187
|
+
return;
|
|
4188
|
+
}, [todos]);
|
|
4159
4189
|
const animationStyle = thinkingAnimationStyle ?? "rainbow";
|
|
4160
4190
|
const [cycleTick, setCycleTick] = useState(0);
|
|
4161
4191
|
useEffect(() => {
|
|
@@ -4186,7 +4216,7 @@ function StatusBar({
|
|
|
4186
4216
|
const hasNextStepsAutoSubmit = nextStepsAutoSubmitCountdown != null && nextStepsAutoSubmitCountdown > 0;
|
|
4187
4217
|
const nextStepsColor = nextStepsAutoSubmitCountdown != null ? countdownColor(nextStepsAutoSubmitCountdown, 20, 10) : "green";
|
|
4188
4218
|
const hasTaskActivity = tasks && (tasks.pending > 0 || tasks.inProgress > 0 || tasks.completed > 0 || tasks.blocked > 0 || tasks.failed > 0);
|
|
4189
|
-
const hasThirdLine = todos && (todos.pending > 0 || todos.inProgress > 0 || todos.completed > 0) && showChip("todos") || plan && (plan.open > 0 || plan.inProgress > 0 || plan.done > 0) && showChip("plan") || hasTaskActivity && showChip("tasks") || fleetHasActivity && showChip("fleet") || showBrain || showDebugStream || showEnhance || hasNextStepsAutoSubmit && showChip("next_steps");
|
|
4219
|
+
const hasThirdLine = todos && (todos.pending > 0 || todos.inProgress > 0 || todos.completed > 0 && !todosCleared) && showChip("todos") || plan && (plan.open > 0 || plan.inProgress > 0 || plan.done > 0) && showChip("plan") || hasTaskActivity && showChip("tasks") || fleetHasActivity && showChip("fleet") || showBrain || showDebugStream || showEnhance || hasNextStepsAutoSubmit && showChip("next_steps");
|
|
4190
4220
|
const minimalWorkParts = [
|
|
4191
4221
|
queueCount > 0 && showChip("queue") ? `q${queueCount}` : "",
|
|
4192
4222
|
todos && showChip("todos") && todos.inProgress + todos.pending > 0 ? `todo ${todos.inProgress}/${todos.pending}` : "",
|
|
@@ -4529,7 +4559,7 @@ function StatusBar({
|
|
|
4529
4559
|
) }) : /* @__PURE__ */ jsx(Box, { height: 1, children: /* @__PURE__ */ jsx(Text, { children: " " }) }),
|
|
4530
4560
|
hasThirdLine ? /* @__PURE__ */ jsx(Box, { flexDirection: "row", gap: 2, children: renderChipLine(
|
|
4531
4561
|
[
|
|
4532
|
-
todos && (todos.pending > 0 || todos.inProgress > 0 || todos.completed > 0) && showChip("todos") ? /* @__PURE__ */ jsxs(Text, { children: [
|
|
4562
|
+
todos && (todos.pending > 0 || todos.inProgress > 0 || todos.completed > 0 && !todosCleared) && showChip("todos") ? /* @__PURE__ */ jsxs(Text, { children: [
|
|
4533
4563
|
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "todos " }),
|
|
4534
4564
|
todos.inProgress > 0 ? /* @__PURE__ */ jsxs(Text, { color: "yellow", children: [
|
|
4535
4565
|
"\u231B",
|
|
@@ -5008,7 +5038,7 @@ function FleetMonitor({
|
|
|
5008
5038
|
nowTick,
|
|
5009
5039
|
collabSession
|
|
5010
5040
|
}) {
|
|
5011
|
-
const
|
|
5041
|
+
const TERMINAL_TTL_MS = 5 * 6e4;
|
|
5012
5042
|
const all = Object.values(entries);
|
|
5013
5043
|
const running = all.filter((e) => e.status === "running");
|
|
5014
5044
|
const idle = all.filter((e) => e.status === "idle").length;
|
|
@@ -5016,7 +5046,7 @@ function FleetMonitor({
|
|
|
5016
5046
|
const failed = all.filter((e) => e.status === "failed" || e.status === "timeout").length;
|
|
5017
5047
|
const recent = all.filter((e) => {
|
|
5018
5048
|
if (e.status === "running" || e.status === "idle") return true;
|
|
5019
|
-
return nowTick - e.lastEventAt <
|
|
5049
|
+
return nowTick - e.lastEventAt < TERMINAL_TTL_MS;
|
|
5020
5050
|
});
|
|
5021
5051
|
const concurrencyRatio = maxConcurrent > 0 ? running.length / maxConcurrent : 0;
|
|
5022
5052
|
const ordered = [...recent].sort((a, b) => {
|
|
@@ -5214,15 +5244,12 @@ var STATUS2 = {
|
|
|
5214
5244
|
};
|
|
5215
5245
|
var IDLE_HIDE_MS = 6e4;
|
|
5216
5246
|
var EMPTY_AGENTS_CLOSE_DELAY_MS = 7500;
|
|
5217
|
-
function isTerminalAgentStatus(status) {
|
|
5218
|
-
return status === "success" || status === "failed" || status === "timeout" || status === "stopped";
|
|
5219
|
-
}
|
|
5220
5247
|
function isLeaderEntry(entry) {
|
|
5221
5248
|
return entry.id === "leader" || entry.name === "LEADER";
|
|
5222
5249
|
}
|
|
5223
5250
|
function selectLiveAgents(all, _now, _idleHideMs = IDLE_HIDE_MS) {
|
|
5224
5251
|
const leader = all.find(isLeaderEntry);
|
|
5225
|
-
const activeSubagents = all.filter((entry) => !isLeaderEntry(entry) &&
|
|
5252
|
+
const activeSubagents = all.filter((entry) => !isLeaderEntry(entry) && entry.status === "running");
|
|
5226
5253
|
const showLeader = leader !== void 0 && (leader.status !== "idle" || activeSubagents.length > 0);
|
|
5227
5254
|
return all.filter((entry) => isLeaderEntry(entry) ? showLeader : activeSubagents.some((active) => active.id === entry.id));
|
|
5228
5255
|
}
|
|
@@ -5551,9 +5578,6 @@ function AgentsMonitor({
|
|
|
5551
5578
|
const running = live.filter((e) => e.status === "running").length;
|
|
5552
5579
|
const totalDone = all.filter((e) => e.status === "success").length;
|
|
5553
5580
|
const totalFailed = all.filter((e) => e.status === "failed" || e.status === "timeout").length;
|
|
5554
|
-
const staleIdle = all.filter(
|
|
5555
|
-
(e) => e.status === "idle" && nowTick - e.lastEventAt >= IDLE_HIDE_MS
|
|
5556
|
-
).length;
|
|
5557
5581
|
const hotAgent = selectHotAgent(live);
|
|
5558
5582
|
const pressure = live.length > 0 ? live.reduce((max, e) => Math.max(max, e.ctxPct ?? 0), 0) : 0;
|
|
5559
5583
|
const toolCalls = live.reduce((sum, e) => sum + e.toolCalls, 0);
|
|
@@ -5645,12 +5669,7 @@ function AgentsMonitor({
|
|
|
5645
5669
|
" \xB7 fleet $",
|
|
5646
5670
|
totalCost.toFixed(4),
|
|
5647
5671
|
")"
|
|
5648
|
-
] })
|
|
5649
|
-
staleIdle > 0 ? /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
5650
|
-
"\xB7 ",
|
|
5651
|
-
staleIdle,
|
|
5652
|
-
" idle stale"
|
|
5653
|
-
] }) : null
|
|
5672
|
+
] })
|
|
5654
5673
|
] }),
|
|
5655
5674
|
live.length === 0 ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: "No live agents \u2014 spawn with /spawn or /fleet dispatch." }) : null,
|
|
5656
5675
|
live.map((e) => e.id === selected?.id ? /* @__PURE__ */ jsx(AgentDetail, { entry: e, now: nowTick }, e.id) : /* @__PURE__ */ jsx(AgentRow, { entry: e, now: nowTick, selected: false }, e.id))
|
|
@@ -6664,8 +6683,8 @@ function detectLang(fenceInfo) {
|
|
|
6664
6683
|
const tag = fenceInfo.trim().toLowerCase().split(/\s+/)[0] ?? "";
|
|
6665
6684
|
return LANG_ALIASES[tag] ?? "plain";
|
|
6666
6685
|
}
|
|
6667
|
-
function langFromPath(
|
|
6668
|
-
const m = /\.([A-Za-z0-9]+)$/.exec(
|
|
6686
|
+
function langFromPath(path10) {
|
|
6687
|
+
const m = /\.([A-Za-z0-9]+)$/.exec(path10.trim());
|
|
6669
6688
|
const ext = m?.[1]?.toLowerCase() ?? "";
|
|
6670
6689
|
return LANG_ALIASES[ext] ?? "plain";
|
|
6671
6690
|
}
|
|
@@ -7459,19 +7478,19 @@ function visualEdit(toolName, text, ok) {
|
|
|
7459
7478
|
const parsed = tryParseJson(text);
|
|
7460
7479
|
if (parsed && typeof parsed === "object") {
|
|
7461
7480
|
const obj = parsed;
|
|
7462
|
-
const
|
|
7481
|
+
const path10 = typeof obj["path"] === "string" ? obj["path"] : void 0;
|
|
7463
7482
|
const replacements = typeof obj["replacements"] === "number" ? obj["replacements"] : void 0;
|
|
7464
7483
|
const bytes = typeof obj["bytes"] === "number" ? obj["bytes"] : void 0;
|
|
7465
7484
|
const created = obj["created"] === true;
|
|
7466
7485
|
const files = Array.isArray(obj["files"]) ? obj["files"] : void 0;
|
|
7467
7486
|
const results = Array.isArray(obj["results"]) ? obj["results"] : void 0;
|
|
7468
|
-
if (toolName === "edit" &&
|
|
7487
|
+
if (toolName === "edit" && path10 !== void 0) {
|
|
7469
7488
|
const repText = replacements !== void 0 ? `${replacements} replacement${replacements === 1 ? "" : "s"}` : void 0;
|
|
7470
|
-
rows.push({ kind: "ok", text: "", marker: "edit ", path:
|
|
7489
|
+
rows.push({ kind: "ok", text: "", marker: "edit ", path: path10 });
|
|
7471
7490
|
if (repText) rows.push({ kind: "meta", text: repText });
|
|
7472
|
-
} else if (toolName === "write" &&
|
|
7491
|
+
} else if (toolName === "write" && path10 !== void 0) {
|
|
7473
7492
|
const sizeText = bytes !== void 0 ? `${bytes} bytes` : created ? "new file" : "updated";
|
|
7474
|
-
rows.push({ kind: "ok", text: "", marker: "write ", path:
|
|
7493
|
+
rows.push({ kind: "ok", text: "", marker: "write ", path: path10 });
|
|
7475
7494
|
rows.push({ kind: "meta", text: sizeText });
|
|
7476
7495
|
} else if ((toolName === "diff" || toolName === "patch") && files && files.length > 0) {
|
|
7477
7496
|
rows.push({
|
|
@@ -7494,8 +7513,8 @@ function visualEdit(toolName, text, ok) {
|
|
|
7494
7513
|
marker: "replace ",
|
|
7495
7514
|
text: `${results.length} replacement${results.length === 1 ? "" : "s"} across ${fileCount} file${fileCount === 1 ? "" : "s"}`
|
|
7496
7515
|
});
|
|
7497
|
-
} else if (
|
|
7498
|
-
rows.push({ kind: "ok", text: "", marker: `${toolName} `, path:
|
|
7516
|
+
} else if (path10 !== void 0) {
|
|
7517
|
+
rows.push({ kind: "ok", text: "", marker: `${toolName} `, path: path10 });
|
|
7499
7518
|
} else {
|
|
7500
7519
|
return void 0;
|
|
7501
7520
|
}
|
|
@@ -7589,12 +7608,12 @@ function parseMatchHit(hit) {
|
|
|
7589
7608
|
}
|
|
7590
7609
|
if (hit && typeof hit === "object") {
|
|
7591
7610
|
const o = hit;
|
|
7592
|
-
const
|
|
7611
|
+
const path10 = stringOf(o["file"]) ?? stringOf(o["path"]) ?? stringOf(o["url"]);
|
|
7593
7612
|
const line = numOf(o["line"]) ?? numOf(o["lineNumber"]);
|
|
7594
7613
|
const title = stringOf(o["title"]);
|
|
7595
7614
|
const snippet2 = stringOf(o["snippet"]);
|
|
7596
7615
|
const text = stringOf(o["text"]) ?? stringOf(o["match"]) ?? stringOf(o["preview"]) ?? [title, snippet2].filter(Boolean).join(" \u2014 ");
|
|
7597
|
-
return { path:
|
|
7616
|
+
return { path: path10, line: line === void 0 ? void 0 : String(line), text };
|
|
7598
7617
|
}
|
|
7599
7618
|
return void 0;
|
|
7600
7619
|
}
|
|
@@ -8402,13 +8421,13 @@ function formatMultiDiffSummary(summary, threshold = MULTI_DIFF_SUMMARY_THRESHOL
|
|
|
8402
8421
|
return parts.join(" \xB7 ");
|
|
8403
8422
|
}
|
|
8404
8423
|
function DiffFileBlock({
|
|
8405
|
-
path:
|
|
8424
|
+
path: path10,
|
|
8406
8425
|
preview,
|
|
8407
8426
|
useColor = true,
|
|
8408
8427
|
contentWidth
|
|
8409
8428
|
}) {
|
|
8410
8429
|
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", marginTop: 1, children: [
|
|
8411
|
-
/* @__PURE__ */ jsx(Text, { dimColor: true, italic: true, children:
|
|
8430
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, italic: true, children: path10 }),
|
|
8412
8431
|
/* @__PURE__ */ jsx(
|
|
8413
8432
|
DiffBlock,
|
|
8414
8433
|
{
|
|
@@ -8419,7 +8438,7 @@ function DiffFileBlock({
|
|
|
8419
8438
|
hiddenAdded: preview.hiddenAdded,
|
|
8420
8439
|
hiddenRemoved: preview.hiddenRemoved,
|
|
8421
8440
|
useColor,
|
|
8422
|
-
lang: langFromPath(
|
|
8441
|
+
lang: langFromPath(path10),
|
|
8423
8442
|
contentWidth
|
|
8424
8443
|
}
|
|
8425
8444
|
)
|
|
@@ -8509,7 +8528,8 @@ function DiffBlock({
|
|
|
8509
8528
|
return row.text || " ";
|
|
8510
8529
|
};
|
|
8511
8530
|
const stats = showStats ? formatDiffStats(added, removed) : null;
|
|
8512
|
-
const
|
|
8531
|
+
const terminalWrapGuard = typeof contentWidth === "number" ? 1 : 0;
|
|
8532
|
+
const bodyBudget = typeof contentWidth === "number" ? Math.max(16, contentWidth - (2 + 3 + gutterWidth + 3 + terminalWrapGuard)) : DIFF_FALLBACK_WRAP_WIDTH;
|
|
8513
8533
|
const hasWidth = typeof contentWidth === "number";
|
|
8514
8534
|
const padBody = (seg) => {
|
|
8515
8535
|
if (!hasWidth) return 0;
|
|
@@ -8677,8 +8697,8 @@ function splitReplaceDiffs(obj) {
|
|
|
8677
8697
|
const record = result;
|
|
8678
8698
|
const diff = stringOf(record["diff"]);
|
|
8679
8699
|
if (!diff?.trim()) continue;
|
|
8680
|
-
const
|
|
8681
|
-
items.push(
|
|
8700
|
+
const path10 = stringOf(record["path"]);
|
|
8701
|
+
items.push(path10 ? { path: path10, diff } : { diff });
|
|
8682
8702
|
}
|
|
8683
8703
|
return items;
|
|
8684
8704
|
}
|
|
@@ -8742,8 +8762,8 @@ function collectMultiFileDiffItems(toolName, output, _input) {
|
|
|
8742
8762
|
if (!diffText?.trim()) return void 0;
|
|
8743
8763
|
const blocks = splitGitStyleDiff(diffText);
|
|
8744
8764
|
if (blocks.length === 0) {
|
|
8745
|
-
const
|
|
8746
|
-
return [{ path:
|
|
8765
|
+
const path10 = explicitFiles[0] ?? extractPatchHeaderPath(diffText);
|
|
8766
|
+
return [{ path: path10, diff: diffText }];
|
|
8747
8767
|
}
|
|
8748
8768
|
return blocks.map((block, idx) => ({
|
|
8749
8769
|
path: explicitFiles[idx] ?? block.path,
|
|
@@ -8789,17 +8809,17 @@ function splitGitStyleDiff(diff) {
|
|
|
8789
8809
|
}
|
|
8790
8810
|
flush();
|
|
8791
8811
|
if (blocks.length === 1 && !blocks[0].path) {
|
|
8792
|
-
const
|
|
8793
|
-
if (
|
|
8812
|
+
const path10 = extractPatchHeaderPath(blocks[0].diff);
|
|
8813
|
+
if (path10) blocks[0] = { path: path10, diff: blocks[0].diff };
|
|
8794
8814
|
}
|
|
8795
8815
|
return blocks;
|
|
8796
8816
|
}
|
|
8797
8817
|
function parseDiffGitPath(line) {
|
|
8798
8818
|
const rest = line.slice("diff --git ".length).trim();
|
|
8799
8819
|
if (!rest) return void 0;
|
|
8800
|
-
const
|
|
8801
|
-
if (
|
|
8802
|
-
return rest.slice(
|
|
8820
|
+
const sep3 = rest.lastIndexOf(" b/");
|
|
8821
|
+
if (sep3 > 0 && sep3 > rest.length - sep3 - 3) {
|
|
8822
|
+
return rest.slice(sep3 + 3);
|
|
8803
8823
|
}
|
|
8804
8824
|
const spaceIdx = rest.lastIndexOf(" ");
|
|
8805
8825
|
if (spaceIdx > 0) {
|
|
@@ -8811,8 +8831,8 @@ function parseDiffGitPath(line) {
|
|
|
8811
8831
|
function extractPatchHeaderPath(diffText) {
|
|
8812
8832
|
for (const line of diffText.split("\n")) {
|
|
8813
8833
|
if (line.startsWith("+++ ")) {
|
|
8814
|
-
const
|
|
8815
|
-
const cleaned =
|
|
8834
|
+
const path10 = line.slice(4).trim();
|
|
8835
|
+
const cleaned = path10.replace(/^b\//, "").split(" ")[0].trim();
|
|
8816
8836
|
return cleaned || void 0;
|
|
8817
8837
|
}
|
|
8818
8838
|
}
|
|
@@ -8838,9 +8858,9 @@ function newFileDiffFromWriteInput(output, input) {
|
|
|
8838
8858
|
const obj = input;
|
|
8839
8859
|
const content = stringOf(obj["content"]);
|
|
8840
8860
|
if (content === void 0) return void 0;
|
|
8841
|
-
const
|
|
8861
|
+
const path10 = stringOf(output["path"]) ?? stringOf(obj["path"]) ?? "new file";
|
|
8842
8862
|
const lines = content === "" ? [] : content.replace(/\n$/, "").split("\n");
|
|
8843
|
-
const header = [`+++ ${
|
|
8863
|
+
const header = [`+++ ${path10}`, `@@ -0,0 +1,${lines.length} @@`];
|
|
8844
8864
|
return [...header, ...lines.map((line) => `+${line}`)].join("\n");
|
|
8845
8865
|
}
|
|
8846
8866
|
var BUTTON_COLOR = {
|
|
@@ -8878,7 +8898,7 @@ function renderDiffLine(line) {
|
|
|
8878
8898
|
"\n"
|
|
8879
8899
|
] }, line);
|
|
8880
8900
|
}
|
|
8881
|
-
function renderDiff(diff,
|
|
8901
|
+
function renderDiff(diff, path10) {
|
|
8882
8902
|
const preview = parseUnifiedDiff(diff, CONFIRM_DIFF_MAX_LINES);
|
|
8883
8903
|
if (preview.rows.length > 0) {
|
|
8884
8904
|
return /* @__PURE__ */ jsx(
|
|
@@ -8891,7 +8911,7 @@ function renderDiff(diff, path8) {
|
|
|
8891
8911
|
hiddenAdded: preview.hiddenAdded,
|
|
8892
8912
|
hiddenRemoved: preview.hiddenRemoved,
|
|
8893
8913
|
useColor: theme.supportsBackground,
|
|
8894
|
-
lang: langFromPath(
|
|
8914
|
+
lang: langFromPath(path10 ?? "")
|
|
8895
8915
|
}
|
|
8896
8916
|
);
|
|
8897
8917
|
}
|
|
@@ -9336,10 +9356,9 @@ function FilePicker({ query, matches, selected }) {
|
|
|
9336
9356
|
] }, m))
|
|
9337
9357
|
] });
|
|
9338
9358
|
}
|
|
9339
|
-
function highlight(
|
|
9340
|
-
return
|
|
9359
|
+
function highlight(path10, _query) {
|
|
9360
|
+
return path10;
|
|
9341
9361
|
}
|
|
9342
|
-
var TERMINAL_TTL_MS = 9e4;
|
|
9343
9362
|
var METER_WIDTH = 10;
|
|
9344
9363
|
function isLeaderEntry2(entry) {
|
|
9345
9364
|
return entry.id === "leader" || entry.name === "LEADER";
|
|
@@ -9413,22 +9432,19 @@ function swarmColumnCount(width) {
|
|
|
9413
9432
|
if (width < 54) return 1;
|
|
9414
9433
|
return Math.max(1, Math.min(5, Math.floor(width / 38)));
|
|
9415
9434
|
}
|
|
9416
|
-
function selectSwarmEntries(entries,
|
|
9417
|
-
const terminalTtlMs = opts.terminalTtlMs ?? TERMINAL_TTL_MS;
|
|
9435
|
+
function selectSwarmEntries(entries, _now, opts = {}) {
|
|
9418
9436
|
return Object.values(entries).filter((entry) => {
|
|
9419
9437
|
if (isLeaderEntry2(entry) && !opts.includeLeader) return false;
|
|
9420
|
-
if (entry
|
|
9421
|
-
return
|
|
9438
|
+
if (isLeaderEntry2(entry)) return true;
|
|
9439
|
+
return entry.status === "running";
|
|
9422
9440
|
}).sort((a, b) => {
|
|
9423
9441
|
const rank = (entry) => {
|
|
9424
9442
|
if (entry.status === "running") return 0;
|
|
9425
|
-
|
|
9426
|
-
return 2;
|
|
9443
|
+
return 1;
|
|
9427
9444
|
};
|
|
9428
9445
|
const ar = rank(a);
|
|
9429
9446
|
const br = rank(b);
|
|
9430
9447
|
if (ar !== br) return ar - br;
|
|
9431
|
-
if (ar === 2) return b.lastEventAt - a.lastEventAt;
|
|
9432
9448
|
return a.startedAt - b.startedAt;
|
|
9433
9449
|
});
|
|
9434
9450
|
}
|
|
@@ -9549,16 +9565,8 @@ function FleetPanel({
|
|
|
9549
9565
|
const hasSwarm = grid.rows.length > 0;
|
|
9550
9566
|
if (!hasSwarm && todoRows.length === 0 && !hasCollab) return null;
|
|
9551
9567
|
const runningCount = subagents.filter((e) => e.status === "running").length;
|
|
9552
|
-
const idleCount = subagents.filter((e) => e.status === "idle").length;
|
|
9553
|
-
const doneCount = subagents.filter((e) => e.status === "success").length;
|
|
9554
|
-
const failedCount = subagents.filter(
|
|
9555
|
-
(e) => e.status === "failed" || e.status === "timeout"
|
|
9556
|
-
).length;
|
|
9557
9568
|
const summaryBits = [
|
|
9558
|
-
runningCount > 0 ? `${runningCount} running` : "
|
|
9559
|
-
idleCount > 0 ? `${idleCount} idle` : "",
|
|
9560
|
-
doneCount > 0 ? `${doneCount} done` : "",
|
|
9561
|
-
failedCount > 0 ? `${failedCount} failed` : "",
|
|
9569
|
+
runningCount > 0 ? `${runningCount} running` : "",
|
|
9562
9570
|
fmtCost2(totalCost)
|
|
9563
9571
|
].filter(Boolean);
|
|
9564
9572
|
const collabLabel = hasCollab && collabSession.sessionId ? `collab ${collabSession.bugCount}b/${collabSession.planCount}p/${collabSession.evalCount}e` : "";
|
|
@@ -9962,8 +9970,8 @@ var SEP_RE = /^\s*\|[\s\-:|]+\|\s*$/;
|
|
|
9962
9970
|
function detectTable(lines, start) {
|
|
9963
9971
|
if (start + 1 >= lines.length) return start;
|
|
9964
9972
|
if (!ROW_RE.test(lines[start] ?? "")) return start;
|
|
9965
|
-
const
|
|
9966
|
-
if (!SEP_RE.test(
|
|
9973
|
+
const sep3 = lines[start + 1] ?? "";
|
|
9974
|
+
if (!SEP_RE.test(sep3) || !/-/.test(sep3)) return start;
|
|
9967
9975
|
let end = start + 2;
|
|
9968
9976
|
while (end < lines.length && ROW_RE.test(lines[end] ?? "")) end++;
|
|
9969
9977
|
return end;
|
|
@@ -9989,8 +9997,8 @@ function parseCells(line) {
|
|
|
9989
9997
|
parts.push(buf);
|
|
9990
9998
|
return parts.map((c) => c.trim());
|
|
9991
9999
|
}
|
|
9992
|
-
function parseAlign(
|
|
9993
|
-
const t =
|
|
10000
|
+
function parseAlign(sep3) {
|
|
10001
|
+
const t = sep3.trim();
|
|
9994
10002
|
const left = t.startsWith(":");
|
|
9995
10003
|
const right = t.endsWith(":");
|
|
9996
10004
|
if (left && right) return "center";
|
|
@@ -10556,7 +10564,7 @@ function Banner({
|
|
|
10556
10564
|
entry
|
|
10557
10565
|
}) {
|
|
10558
10566
|
const cwdShort = shortenPath(entry.cwd, 48);
|
|
10559
|
-
const projectLabel =
|
|
10567
|
+
const projectLabel = path9.basename(entry.cwd);
|
|
10560
10568
|
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", borderStyle: "round", borderColor: "magenta", paddingX: 2, paddingY: 0, children: [
|
|
10561
10569
|
/* @__PURE__ */ jsxs(Text, { children: [
|
|
10562
10570
|
/* @__PURE__ */ jsx(Text, { color: "magenta", bold: true, children: " \u259F\u259B " }),
|
|
@@ -10594,18 +10602,12 @@ function Banner({
|
|
|
10594
10602
|
}
|
|
10595
10603
|
|
|
10596
10604
|
// src/components/suggestions.ts
|
|
10597
|
-
var
|
|
10598
|
-
var PERMISSIVE_HEADING_PATTERNS = [
|
|
10599
|
-
{ re: /💡\s*Next steps?\s*\n+/i, label: "emoji" },
|
|
10600
|
-
{ re: /##?\s*Next steps?\s*\n+/i, label: "markdown" },
|
|
10601
|
-
{ re: /\n{1,2}Next steps?\s*\n+/i, label: "plain" },
|
|
10602
|
-
{ re: /<next_steps>\s*\n+/i, label: "xml-tag" }
|
|
10603
|
-
];
|
|
10605
|
+
var NEXT_STEPS_TAG_RE = /<nextsteps>\s*\n+/i;
|
|
10604
10606
|
var ITEM_RE = /^(?:(\d+)[.)]\s*|[-*•]\s*)(.+?)(\s+auto="true")?$/;
|
|
10605
10607
|
var MAX_STEPS = 6;
|
|
10606
10608
|
function parseNextSteps(content, strict = false, requireHeading = true) {
|
|
10607
10609
|
if (requireHeading) {
|
|
10608
|
-
return parseWithHeading(content
|
|
10610
|
+
return parseWithHeading(content);
|
|
10609
10611
|
}
|
|
10610
10612
|
return parseRawNumbered(content);
|
|
10611
10613
|
}
|
|
@@ -10640,9 +10642,8 @@ function parseRawNumbered(content) {
|
|
|
10640
10642
|
autoTexts: steps.filter((s2) => s2.auto).map((s2) => s2.text)
|
|
10641
10643
|
};
|
|
10642
10644
|
}
|
|
10643
|
-
function parseWithHeading(content,
|
|
10644
|
-
const
|
|
10645
|
-
const headingMatch = headingRe.exec(content);
|
|
10645
|
+
function parseWithHeading(content, _strict) {
|
|
10646
|
+
const headingMatch = NEXT_STEPS_TAG_RE.exec(content);
|
|
10646
10647
|
if (!headingMatch) {
|
|
10647
10648
|
return { steps: [], texts: [], stripped: content, autoTexts: [] };
|
|
10648
10649
|
}
|
|
@@ -10674,8 +10675,7 @@ function parseWithHeading(content, strict) {
|
|
|
10674
10675
|
if (steps.length === 0) {
|
|
10675
10676
|
return { steps: [], texts: [], stripped: content, autoTexts: [] };
|
|
10676
10677
|
}
|
|
10677
|
-
|
|
10678
|
-
if (strict && headingWasXmlTag && !afterHeading.includes("</next_steps>")) {
|
|
10678
|
+
if (!afterHeading.includes("</nextsteps>")) {
|
|
10679
10679
|
return { steps: [], texts: [], stripped: content, autoTexts: [] };
|
|
10680
10680
|
}
|
|
10681
10681
|
const texts = steps.map((s2) => s2.text);
|
|
@@ -10685,14 +10685,10 @@ function parseWithHeading(content, strict) {
|
|
|
10685
10685
|
const stripped = (content.slice(0, blockStart) + content.slice(blockStart + blockEnd)).replace(/\n{3,}/g, "\n\n").trim();
|
|
10686
10686
|
return { steps, texts, stripped, autoTexts };
|
|
10687
10687
|
}
|
|
10688
|
-
function buildPermissiveHeadingRe() {
|
|
10689
|
-
const variants = PERMISSIVE_HEADING_PATTERNS.map(({ re }) => `(?:${re.source})`).join("|");
|
|
10690
|
-
return new RegExp(variants, "i");
|
|
10691
|
-
}
|
|
10692
10688
|
function findBlockEnd(afterHeading, stepCount) {
|
|
10693
|
-
const closeIdx = afterHeading.indexOf("</
|
|
10689
|
+
const closeIdx = afterHeading.indexOf("</nextsteps>");
|
|
10694
10690
|
if (closeIdx !== -1) {
|
|
10695
|
-
let end = closeIdx + "</
|
|
10691
|
+
let end = closeIdx + "</nextsteps>".length;
|
|
10696
10692
|
if (afterHeading[end] === "\n") end += 1;
|
|
10697
10693
|
return end;
|
|
10698
10694
|
}
|
|
@@ -10714,7 +10710,7 @@ function findBlockEnd(afterHeading, stepCount) {
|
|
|
10714
10710
|
return consumed;
|
|
10715
10711
|
}
|
|
10716
10712
|
function stripNextStepsBlock(text) {
|
|
10717
|
-
return text.replace(/<
|
|
10713
|
+
return text.replace(/<nextsteps\b[^>]*>[\s\S]*?<\/nextsteps>/gi, "").replace(/<nextsteps\b[^>]*\/?>/gi, "").replace(/\n{3,}/g, "\n\n").trim();
|
|
10718
10714
|
}
|
|
10719
10715
|
function brainStatusStyle(status) {
|
|
10720
10716
|
switch (status) {
|
|
@@ -10908,15 +10904,15 @@ var Entry = React5.memo(function Entry2({
|
|
|
10908
10904
|
const outObj = outJson && typeof outJson === "object" ? outJson : void 0;
|
|
10909
10905
|
const created = name === "write" && (outObj?.["created"] === true || /^[^\n]*\bcreated=true\b/.test(entry.output ?? ""));
|
|
10910
10906
|
const verb = created ? "Write" : "Update";
|
|
10911
|
-
const
|
|
10912
|
-
const target = multiDiffs2 ? multiDiffs2.length === 1 ? multiDiffs2[0].path : `${multiDiffs2.length} files` :
|
|
10907
|
+
const path10 = stringOf(inputObj?.["path"]) ?? stringOf(outObj?.["path"]);
|
|
10908
|
+
const target = multiDiffs2 ? multiDiffs2.length === 1 ? multiDiffs2[0].path : `${multiDiffs2.length} files` : path10 ?? "file";
|
|
10913
10909
|
const agg = multiDiffs2 ? summarizeMultiFileDiffs(multiDiffs2) : void 0;
|
|
10914
10910
|
return {
|
|
10915
10911
|
verb,
|
|
10916
10912
|
target,
|
|
10917
10913
|
added: agg ? agg.added : diff2?.added ?? 0,
|
|
10918
10914
|
removed: agg ? agg.removed : diff2?.removed ?? 0,
|
|
10919
|
-
lang: langFromPath(multiDiffs2 ? "" :
|
|
10915
|
+
lang: langFromPath(multiDiffs2 ? "" : path10 ?? "")
|
|
10920
10916
|
};
|
|
10921
10917
|
})();
|
|
10922
10918
|
return { argSummary: argSummary2, outLines: outLines2, visualLines: visualLines2, diff: diff2, multiDiffs: multiDiffs2, sizeChip: sizeChip2, mutation: mutation2 };
|
|
@@ -12470,12 +12466,12 @@ var STATUS_ICON = {
|
|
|
12470
12466
|
function planFilePath(projectRoot, sessionId, scope) {
|
|
12471
12467
|
const base = resolveWstackPaths$1({ projectRoot }).projectSessions;
|
|
12472
12468
|
if (scope === "project") {
|
|
12473
|
-
return
|
|
12469
|
+
return path9.join(base, "backlog.plan.json");
|
|
12474
12470
|
}
|
|
12475
12471
|
if (sessionId) {
|
|
12476
12472
|
return sessionScopedPath(base, sessionId, ".plan.json");
|
|
12477
12473
|
}
|
|
12478
|
-
return
|
|
12474
|
+
return path9.join(base, "backlog.plan.json");
|
|
12479
12475
|
}
|
|
12480
12476
|
function PlanPanel({ projectRoot, sessionId, onClose: _onClose }) {
|
|
12481
12477
|
const [items, setItems] = useState([]);
|
|
@@ -12618,9 +12614,14 @@ function PluginPicker({
|
|
|
12618
12614
|
const windowEnd = Math.min(windowStart + maxVisible, total);
|
|
12619
12615
|
const above = windowStart;
|
|
12620
12616
|
const below = total - windowEnd;
|
|
12617
|
+
const hasLockedRows = items.some((item) => item.lockable === false);
|
|
12621
12618
|
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", borderStyle: "round", borderColor: "cyan", paddingX: 1, children: [
|
|
12622
12619
|
/* @__PURE__ */ jsx(Text, { bold: true, color: "cyan", children: "Plugin menu" }),
|
|
12623
|
-
/* @__PURE__ */
|
|
12620
|
+
/* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
12621
|
+
"\u2191/\u2193 select \xB7 Enter/\u2190/\u2192 toggle",
|
|
12622
|
+
hasLockedRows ? " \xB7 \u{1F512} = locked" : "",
|
|
12623
|
+
" \xB7 Esc close"
|
|
12624
|
+
] }),
|
|
12624
12625
|
/* @__PURE__ */ jsx(Box, { marginTop: 1, flexDirection: "column", children: items.length === 0 ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: busy ? "Loading plugins\u2026" : "No plugins available." }) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
12625
12626
|
above > 0 ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: ` \u2191 ${above} more` }) : null,
|
|
12626
12627
|
items.slice(windowStart, windowEnd).map((item, i) => {
|
|
@@ -13546,11 +13547,11 @@ function WorktreeMonitor({
|
|
|
13546
13547
|
useInput((input, key) => {
|
|
13547
13548
|
if (isWorktreeMonitorCloseKey(input, key)) onClose();
|
|
13548
13549
|
});
|
|
13549
|
-
const
|
|
13550
|
+
const TERMINAL_TTL_MS = 5 * 6e4;
|
|
13550
13551
|
const list = Object.values(worktrees);
|
|
13551
13552
|
const recent = list.filter((w) => {
|
|
13552
13553
|
if (["active", "committing", "merging", "needs-review"].includes(w.status)) return true;
|
|
13553
|
-
return nowTick - (w.allocatedAt ?? nowTick) <
|
|
13554
|
+
return nowTick - (w.allocatedAt ?? nowTick) < TERMINAL_TTL_MS;
|
|
13554
13555
|
});
|
|
13555
13556
|
const active = list.filter((w) => ["active", "committing", "merging"].includes(w.status)).length;
|
|
13556
13557
|
const merged = list.filter((w) => w.status === "merged").length;
|
|
@@ -13780,9 +13781,217 @@ function runGit(cwd, args) {
|
|
|
13780
13781
|
}
|
|
13781
13782
|
});
|
|
13782
13783
|
}
|
|
13784
|
+
|
|
13785
|
+
// src/app-initial-state.ts
|
|
13786
|
+
function buildRestoredEntries(messages, restoredToolCalls) {
|
|
13787
|
+
if (!messages || messages.length === 0) return [];
|
|
13788
|
+
const visible = messages.filter((m) => m.role !== "system");
|
|
13789
|
+
if (visible.length === 0) return [];
|
|
13790
|
+
return rehydrateHistory(visible, 1, restoredToolCalls);
|
|
13791
|
+
}
|
|
13792
|
+
function createInitialState(options) {
|
|
13793
|
+
const {
|
|
13794
|
+
banner,
|
|
13795
|
+
appVersion,
|
|
13796
|
+
provider,
|
|
13797
|
+
model,
|
|
13798
|
+
cwd,
|
|
13799
|
+
family,
|
|
13800
|
+
keyTail,
|
|
13801
|
+
restoredEntries,
|
|
13802
|
+
enhanceEnabled,
|
|
13803
|
+
initialAgentsMonitorOpen
|
|
13804
|
+
} = options;
|
|
13805
|
+
const initialNextId = 1 + restoredEntries.length;
|
|
13806
|
+
return {
|
|
13807
|
+
entries: [
|
|
13808
|
+
...banner ? [
|
|
13809
|
+
{
|
|
13810
|
+
id: 0,
|
|
13811
|
+
kind: "banner",
|
|
13812
|
+
version: appVersion ?? "dev",
|
|
13813
|
+
provider: provider ?? "agent",
|
|
13814
|
+
model,
|
|
13815
|
+
cwd,
|
|
13816
|
+
family,
|
|
13817
|
+
keyTail
|
|
13818
|
+
}
|
|
13819
|
+
] : [],
|
|
13820
|
+
...restoredEntries
|
|
13821
|
+
],
|
|
13822
|
+
historyGen: 0,
|
|
13823
|
+
buffer: "",
|
|
13824
|
+
cursor: 0,
|
|
13825
|
+
streamingText: "",
|
|
13826
|
+
toolStream: null,
|
|
13827
|
+
status: "idle",
|
|
13828
|
+
interrupts: 0,
|
|
13829
|
+
steeringPending: false,
|
|
13830
|
+
steerSnapshot: null,
|
|
13831
|
+
hint: "",
|
|
13832
|
+
brain: { state: "idle" },
|
|
13833
|
+
brainPrompt: null,
|
|
13834
|
+
nextId: initialNextId,
|
|
13835
|
+
picker: { open: false, query: "", matches: [], selected: 0 },
|
|
13836
|
+
slashPicker: { open: false, query: "", matches: [], selected: 0 },
|
|
13837
|
+
runningTools: /* @__PURE__ */ new Map(),
|
|
13838
|
+
queue: [],
|
|
13839
|
+
nextQueueId: 1,
|
|
13840
|
+
inputHistory: [],
|
|
13841
|
+
historyIndex: 0,
|
|
13842
|
+
historyDraft: "",
|
|
13843
|
+
modelPicker: {
|
|
13844
|
+
open: false,
|
|
13845
|
+
step: "provider",
|
|
13846
|
+
providerOptions: [],
|
|
13847
|
+
modelOptions: [],
|
|
13848
|
+
filteredOptions: [],
|
|
13849
|
+
selected: 0,
|
|
13850
|
+
searchQuery: ""
|
|
13851
|
+
},
|
|
13852
|
+
autonomyPicker: { open: false, options: [], selected: 0 },
|
|
13853
|
+
modePicker: { open: false, modes: [], selected: 0 },
|
|
13854
|
+
designPicker: { open: false, kits: [], selected: 0, stack: "web" },
|
|
13855
|
+
promptPicker: {
|
|
13856
|
+
open: false,
|
|
13857
|
+
all: [],
|
|
13858
|
+
categories: [],
|
|
13859
|
+
recentSlugs: [],
|
|
13860
|
+
catIndex: 0,
|
|
13861
|
+
selected: 0
|
|
13862
|
+
},
|
|
13863
|
+
resumePicker: {
|
|
13864
|
+
open: false,
|
|
13865
|
+
sessions: [],
|
|
13866
|
+
selected: 0,
|
|
13867
|
+
busy: false,
|
|
13868
|
+
hint: void 0,
|
|
13869
|
+
error: void 0
|
|
13870
|
+
},
|
|
13871
|
+
settingsPicker: {
|
|
13872
|
+
open: false,
|
|
13873
|
+
field: 0,
|
|
13874
|
+
lastSettingsField: 0,
|
|
13875
|
+
filter: "",
|
|
13876
|
+
mode: "off",
|
|
13877
|
+
delayMs: 0,
|
|
13878
|
+
titleAnimation: true,
|
|
13879
|
+
yolo: false,
|
|
13880
|
+
streamFleet: true,
|
|
13881
|
+
chime: false,
|
|
13882
|
+
confirmExit: true,
|
|
13883
|
+
nextPrediction: false,
|
|
13884
|
+
featureMcp: true,
|
|
13885
|
+
featurePlugins: true,
|
|
13886
|
+
featureMemory: true,
|
|
13887
|
+
featureSkills: true,
|
|
13888
|
+
featureModelsRegistry: true,
|
|
13889
|
+
tokenSavingTier: "off",
|
|
13890
|
+
allowOutsideProjectRoot: true,
|
|
13891
|
+
contextAutoCompact: true,
|
|
13892
|
+
contextStrategy: "hybrid",
|
|
13893
|
+
contextMode: "balanced",
|
|
13894
|
+
maxConcurrent: 10,
|
|
13895
|
+
logLevel: "info",
|
|
13896
|
+
auditLevel: "standard",
|
|
13897
|
+
indexOnStart: true,
|
|
13898
|
+
multiDiffSummaryThreshold: 5,
|
|
13899
|
+
maxIterations: 500,
|
|
13900
|
+
autoProceedMaxIterations: 50,
|
|
13901
|
+
enhanceDelayMs: 6e4,
|
|
13902
|
+
enhanceEnabled: true,
|
|
13903
|
+
enhanceLanguage: "original",
|
|
13904
|
+
debugStream: false,
|
|
13905
|
+
statuslineMode: "detailed",
|
|
13906
|
+
reasoningMode: "auto",
|
|
13907
|
+
reasoningEffort: "high",
|
|
13908
|
+
reasoningPreserve: false,
|
|
13909
|
+
thinkingWord: "thinking",
|
|
13910
|
+
thinkingWordEditing: false,
|
|
13911
|
+
thinkingWordDraft: "",
|
|
13912
|
+
cacheTtl: "default",
|
|
13913
|
+
configScope: "global",
|
|
13914
|
+
animationStyle: "rainbow"
|
|
13915
|
+
},
|
|
13916
|
+
statuslinePicker: {
|
|
13917
|
+
open: false,
|
|
13918
|
+
field: 0,
|
|
13919
|
+
hiddenItems: [],
|
|
13920
|
+
visibleChips: [],
|
|
13921
|
+
hint: void 0
|
|
13922
|
+
},
|
|
13923
|
+
pluginPicker: { open: false, items: [], selected: 0, busy: false, hint: void 0 },
|
|
13924
|
+
authPanel: AUTH_PANEL_INITIAL,
|
|
13925
|
+
projectPicker: {
|
|
13926
|
+
open: false,
|
|
13927
|
+
allItems: [],
|
|
13928
|
+
items: [],
|
|
13929
|
+
selected: 0,
|
|
13930
|
+
filter: "",
|
|
13931
|
+
hint: void 0
|
|
13932
|
+
},
|
|
13933
|
+
fKeyPicker: { open: false, selected: 0 },
|
|
13934
|
+
confirmQueue: [],
|
|
13935
|
+
enhance: null,
|
|
13936
|
+
enhanceEnabled,
|
|
13937
|
+
enhanceBusy: false,
|
|
13938
|
+
escConfirm: null,
|
|
13939
|
+
sendModePicker: null,
|
|
13940
|
+
contextChipVersion: 0,
|
|
13941
|
+
fleet: {},
|
|
13942
|
+
leader: {
|
|
13943
|
+
iterations: 0,
|
|
13944
|
+
toolCalls: 0,
|
|
13945
|
+
recentTools: [],
|
|
13946
|
+
currentTool: void 0,
|
|
13947
|
+
startedAt: Date.now(),
|
|
13948
|
+
lastEventAt: Date.now(),
|
|
13949
|
+
iterating: false
|
|
13950
|
+
},
|
|
13951
|
+
fleetCost: 0,
|
|
13952
|
+
fleetTokens: { input: 0, output: 0 },
|
|
13953
|
+
fleetConcurrency: 4,
|
|
13954
|
+
streamFleet: true,
|
|
13955
|
+
monitorOpen: false,
|
|
13956
|
+
agentsMonitorOpen: initialAgentsMonitorOpen ?? false,
|
|
13957
|
+
helpOpen: false,
|
|
13958
|
+
todosMonitorOpen: false,
|
|
13959
|
+
queuePanelOpen: false,
|
|
13960
|
+
processListOpen: false,
|
|
13961
|
+
auditPanelOpen: false,
|
|
13962
|
+
planPanelOpen: false,
|
|
13963
|
+
kanbanPanelOpen: false,
|
|
13964
|
+
goalPanelOpen: false,
|
|
13965
|
+
sessionsPanelOpen: false,
|
|
13966
|
+
sessionsPanel: { sessions: [], busy: false, selected: -1 },
|
|
13967
|
+
sessionResumeConfirm: null,
|
|
13968
|
+
collabSession: null,
|
|
13969
|
+
checkpoints: [],
|
|
13970
|
+
rewindOverlay: null,
|
|
13971
|
+
eternalStage: null,
|
|
13972
|
+
goalSummary: null,
|
|
13973
|
+
autoPhase: null,
|
|
13974
|
+
sddBoard: null,
|
|
13975
|
+
worktrees: {},
|
|
13976
|
+
worktreeMonitorOpen: false,
|
|
13977
|
+
coordinator: {
|
|
13978
|
+
goals: [],
|
|
13979
|
+
timeline: [],
|
|
13980
|
+
knowledgeCount: 0,
|
|
13981
|
+
monitorOpen: false,
|
|
13982
|
+
healthy: false
|
|
13983
|
+
},
|
|
13984
|
+
scrollOffset: 0,
|
|
13985
|
+
totalLines: 0,
|
|
13986
|
+
viewportRows: 0,
|
|
13987
|
+
pendingNewLines: 0,
|
|
13988
|
+
debugStreamStats: null,
|
|
13989
|
+
countdown: null
|
|
13990
|
+
};
|
|
13991
|
+
}
|
|
13783
13992
|
var MB = 1024 * 1024;
|
|
13784
13993
|
function defaultHeapLogPath() {
|
|
13785
|
-
return
|
|
13994
|
+
return path9.join(wstackGlobalRoot(), "logs", "heap.jsonl");
|
|
13786
13995
|
}
|
|
13787
13996
|
function takeHeapSample() {
|
|
13788
13997
|
const m = process.memoryUsage();
|
|
@@ -13812,7 +14021,7 @@ function startHeapWatchdog(opts = {}) {
|
|
|
13812
14021
|
const append = (line) => {
|
|
13813
14022
|
writeChain = writeChain.then(async () => {
|
|
13814
14023
|
if (!dirReady) {
|
|
13815
|
-
await fsp.mkdir(
|
|
14024
|
+
await fsp.mkdir(path9.dirname(logPath), { recursive: true });
|
|
13816
14025
|
dirReady = true;
|
|
13817
14026
|
}
|
|
13818
14027
|
await fsp.appendFile(logPath, `${line}
|
|
@@ -14603,7 +14812,7 @@ async function loadIndex(root) {
|
|
|
14603
14812
|
async function walk(root, rel, depth, out) {
|
|
14604
14813
|
if (out.length >= MAX_FILES_INDEXED) return;
|
|
14605
14814
|
if (depth > MAX_DEPTH) return;
|
|
14606
|
-
const dir = rel ?
|
|
14815
|
+
const dir = rel ? path9.join(root, rel) : root;
|
|
14607
14816
|
let entries;
|
|
14608
14817
|
try {
|
|
14609
14818
|
entries = await fsp.readdir(dir, { withFileTypes: true });
|
|
@@ -14702,7 +14911,7 @@ function useFileSearch(options) {
|
|
|
14702
14911
|
dispatch({ type: "pickerClose" });
|
|
14703
14912
|
return;
|
|
14704
14913
|
}
|
|
14705
|
-
const absPath =
|
|
14914
|
+
const absPath = path9.isAbsolute(picked) ? picked : path9.join(projectRoot, picked);
|
|
14706
14915
|
try {
|
|
14707
14916
|
const data = await fsp.readFile(absPath, "utf8");
|
|
14708
14917
|
const token = await builder.registerFile({
|
|
@@ -15452,50 +15661,164 @@ function usePickerKeys(host) {
|
|
|
15452
15661
|
[host]
|
|
15453
15662
|
);
|
|
15454
15663
|
}
|
|
15455
|
-
|
|
15456
|
-
|
|
15457
|
-
|
|
15458
|
-
|
|
15459
|
-
|
|
15460
|
-
|
|
15461
|
-
|
|
15462
|
-
|
|
15463
|
-
|
|
15464
|
-
|
|
15465
|
-
|
|
15466
|
-
|
|
15467
|
-
|
|
15468
|
-
|
|
15469
|
-
|
|
15470
|
-
|
|
15471
|
-
|
|
15472
|
-
|
|
15473
|
-
|
|
15474
|
-
|
|
15475
|
-
|
|
15476
|
-
|
|
15477
|
-
|
|
15478
|
-
|
|
15479
|
-
|
|
15480
|
-
|
|
15481
|
-
|
|
15482
|
-
}
|
|
15483
|
-
|
|
15484
|
-
|
|
15485
|
-
|
|
15486
|
-
|
|
15487
|
-
|
|
15488
|
-
|
|
15489
|
-
|
|
15490
|
-
|
|
15491
|
-
|
|
15492
|
-
|
|
15493
|
-
|
|
15494
|
-
return
|
|
15495
|
-
|
|
15496
|
-
|
|
15497
|
-
|
|
15498
|
-
|
|
15664
|
+
function useInputHistoryPersistence({
|
|
15665
|
+
projectRoot,
|
|
15666
|
+
inputHistory,
|
|
15667
|
+
dispatch
|
|
15668
|
+
}) {
|
|
15669
|
+
const inputHistoryStore = useMemo(() => {
|
|
15670
|
+
if (!projectRoot) return null;
|
|
15671
|
+
const file = resolveWstackPaths({ projectRoot }).projectInputHistory;
|
|
15672
|
+
return new InputHistoryStore(file, new DefaultSecretScrubber(), INPUT_HISTORY_DEFAULT_MAX);
|
|
15673
|
+
}, [projectRoot]);
|
|
15674
|
+
const inputHistoryLoadedRef = useRef(false);
|
|
15675
|
+
const inputHistorySaveTimerRef = useRef(void 0);
|
|
15676
|
+
const inputHistoryLastSavedRef = useRef("");
|
|
15677
|
+
useEffect(() => {
|
|
15678
|
+
if (!inputHistoryStore) return;
|
|
15679
|
+
let cancelled = false;
|
|
15680
|
+
inputHistoryStore.load().then((entries) => {
|
|
15681
|
+
if (cancelled) return;
|
|
15682
|
+
inputHistoryLoadedRef.current = true;
|
|
15683
|
+
inputHistoryLastSavedRef.current = JSON.stringify(entries);
|
|
15684
|
+
if (entries.length === 0) return;
|
|
15685
|
+
dispatch({ type: "setInputHistory", entries });
|
|
15686
|
+
}).catch(() => {
|
|
15687
|
+
if (!cancelled) inputHistoryLoadedRef.current = true;
|
|
15688
|
+
});
|
|
15689
|
+
return () => {
|
|
15690
|
+
cancelled = true;
|
|
15691
|
+
};
|
|
15692
|
+
}, [inputHistoryStore, dispatch]);
|
|
15693
|
+
useEffect(() => {
|
|
15694
|
+
if (!inputHistoryStore || !inputHistoryLoadedRef.current) return;
|
|
15695
|
+
const snapshot = JSON.stringify(inputHistory);
|
|
15696
|
+
if (snapshot === inputHistoryLastSavedRef.current) return;
|
|
15697
|
+
if (inputHistorySaveTimerRef.current) clearTimeout(inputHistorySaveTimerRef.current);
|
|
15698
|
+
inputHistorySaveTimerRef.current = setTimeout(() => {
|
|
15699
|
+
inputHistoryLastSavedRef.current = snapshot;
|
|
15700
|
+
inputHistoryStore.save(inputHistory).catch(() => {
|
|
15701
|
+
});
|
|
15702
|
+
}, 200);
|
|
15703
|
+
return () => {
|
|
15704
|
+
if (inputHistorySaveTimerRef.current) clearTimeout(inputHistorySaveTimerRef.current);
|
|
15705
|
+
};
|
|
15706
|
+
}, [inputHistory, inputHistoryStore]);
|
|
15707
|
+
}
|
|
15708
|
+
function buildModePickerOptions(result) {
|
|
15709
|
+
return toModeOptions(result.modes, result.activeId);
|
|
15710
|
+
}
|
|
15711
|
+
function useModePicker({
|
|
15712
|
+
dispatch,
|
|
15713
|
+
getModes
|
|
15714
|
+
}) {
|
|
15715
|
+
const openModePicker = useCallback(async () => {
|
|
15716
|
+
if (!getModes) return;
|
|
15717
|
+
const result = await getModes();
|
|
15718
|
+
const options = buildModePickerOptions(result);
|
|
15719
|
+
dispatch({ type: "modePickerOpen", modes: options });
|
|
15720
|
+
}, [dispatch, getModes]);
|
|
15721
|
+
return { openModePicker };
|
|
15722
|
+
}
|
|
15723
|
+
function buildPromptPickerPayload(all, recentSlugs) {
|
|
15724
|
+
const entries = all.map((e) => ({
|
|
15725
|
+
slug: e.slug,
|
|
15726
|
+
title: e.title,
|
|
15727
|
+
description: e.description,
|
|
15728
|
+
category: e.category,
|
|
15729
|
+
source: e.source,
|
|
15730
|
+
content: e.content,
|
|
15731
|
+
favorite: e.favorite
|
|
15732
|
+
}));
|
|
15733
|
+
const hasFavorites = entries.some((e) => e.favorite);
|
|
15734
|
+
const categories = [
|
|
15735
|
+
"all",
|
|
15736
|
+
...recentSlugs.length > 0 ? ["\u{1F558} recent"] : [],
|
|
15737
|
+
...hasFavorites ? ["\u2605 favorites"] : [],
|
|
15738
|
+
...Array.from(new Set(entries.map((e) => e.category))).sort()
|
|
15739
|
+
];
|
|
15740
|
+
return { all: entries, categories, recentSlugs };
|
|
15741
|
+
}
|
|
15742
|
+
function usePromptPicker({
|
|
15743
|
+
projectRoot,
|
|
15744
|
+
dispatch
|
|
15745
|
+
}) {
|
|
15746
|
+
const promptLoaderRef = useRef(null);
|
|
15747
|
+
const promptUsageRef = useRef(null);
|
|
15748
|
+
const getPromptLoader = useCallback(() => {
|
|
15749
|
+
if (!promptLoaderRef.current && projectRoot) {
|
|
15750
|
+
let bundledDir;
|
|
15751
|
+
try {
|
|
15752
|
+
const req = createRequire(import.meta.url);
|
|
15753
|
+
bundledDir = path9.join(
|
|
15754
|
+
path9.dirname(req.resolve("@wrongstack/core/package.json")),
|
|
15755
|
+
"data",
|
|
15756
|
+
"prompts"
|
|
15757
|
+
);
|
|
15758
|
+
} catch {
|
|
15759
|
+
bundledDir = void 0;
|
|
15760
|
+
}
|
|
15761
|
+
const paths = resolveWstackPaths({ projectRoot });
|
|
15762
|
+
promptLoaderRef.current = new DefaultPromptLoader({ paths, bundledDir });
|
|
15763
|
+
promptUsageRef.current = new PromptUsageStore(paths.promptUsage);
|
|
15764
|
+
}
|
|
15765
|
+
return promptLoaderRef.current;
|
|
15766
|
+
}, [projectRoot]);
|
|
15767
|
+
const openPromptPicker = useCallback(async () => {
|
|
15768
|
+
const loader = getPromptLoader();
|
|
15769
|
+
if (!loader) return;
|
|
15770
|
+
loader.invalidateCache();
|
|
15771
|
+
const all = await loader.list();
|
|
15772
|
+
const recentSlugs = (await promptUsageRef.current?.recent(50).catch(() => []))?.map((r) => r.slug) ?? [];
|
|
15773
|
+
const payload = buildPromptPickerPayload(all, recentSlugs);
|
|
15774
|
+
dispatch({ type: "promptPickerOpen", ...payload });
|
|
15775
|
+
}, [dispatch, getPromptLoader]);
|
|
15776
|
+
return { openPromptPicker };
|
|
15777
|
+
}
|
|
15778
|
+
|
|
15779
|
+
// src/queue-slash.ts
|
|
15780
|
+
var USAGE = "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";
|
|
15781
|
+
function createQueueSlashCommand(deps) {
|
|
15782
|
+
return {
|
|
15783
|
+
name: "queue",
|
|
15784
|
+
description: "List, clear, or delete pending messages typed while the agent was running.",
|
|
15785
|
+
async run(args) {
|
|
15786
|
+
const out = handleQueueCommand(args, deps);
|
|
15787
|
+
return { message: out };
|
|
15788
|
+
}
|
|
15789
|
+
};
|
|
15790
|
+
}
|
|
15791
|
+
function handleQueueCommand(args, deps) {
|
|
15792
|
+
const trimmed = args.trim();
|
|
15793
|
+
const [sub, ...rest] = trimmed.split(/\s+/);
|
|
15794
|
+
const subcommand = sub?.toLowerCase() ?? "";
|
|
15795
|
+
if (subcommand === "" || subcommand === "list") {
|
|
15796
|
+
return renderList(deps.getQueue());
|
|
15797
|
+
}
|
|
15798
|
+
if (subcommand === "picker") {
|
|
15799
|
+
if (!deps.getPickerEnabled || !deps.setPickerEnabled) {
|
|
15800
|
+
return "Send-mode picker toggle is unavailable in this session.";
|
|
15801
|
+
}
|
|
15802
|
+
const arg = rest[0]?.toLowerCase() ?? "";
|
|
15803
|
+
if (arg === "" || arg === "status") {
|
|
15804
|
+
return `Mid-run send-mode picker is ${deps.getPickerEnabled() ? "on" : "off"}.`;
|
|
15805
|
+
}
|
|
15806
|
+
if (arg === "on" || arg === "off") {
|
|
15807
|
+
const next = arg === "on";
|
|
15808
|
+
deps.setPickerEnabled(next);
|
|
15809
|
+
return next ? "Mid-run send-mode picker: on \u2014 plain messages typed while busy ask queue/btw/steer." : "Mid-run send-mode picker: off \u2014 plain messages typed while busy are queued silently.";
|
|
15810
|
+
}
|
|
15811
|
+
return "Usage: /queue picker on|off";
|
|
15812
|
+
}
|
|
15813
|
+
if (subcommand === "clear") {
|
|
15814
|
+
const before = deps.getQueue().length;
|
|
15815
|
+
if (before === 0) return "Queue is already empty.";
|
|
15816
|
+
deps.clear();
|
|
15817
|
+
return `Cleared ${before} queued message${before === 1 ? "" : "s"}.`;
|
|
15818
|
+
}
|
|
15819
|
+
if (subcommand === "delete" || subcommand === "del" || subcommand === "rm") {
|
|
15820
|
+
if (rest.length === 0) return "Usage: /queue delete <position> [<position>\u2026]";
|
|
15821
|
+
const queue = deps.getQueue();
|
|
15499
15822
|
if (queue.length === 0) return "Queue is empty \u2014 nothing to delete.";
|
|
15500
15823
|
const parsed = [];
|
|
15501
15824
|
const invalid = [];
|
|
@@ -15615,6 +15938,90 @@ function useQueueManager({
|
|
|
15615
15938
|
};
|
|
15616
15939
|
}, [slashRegistry, stateRef, dispatch, getSettings, saveSettings, midRunSendPickerRef]);
|
|
15617
15940
|
}
|
|
15941
|
+
function statuslineHiddenDiffers(hookHidden, pickerHidden) {
|
|
15942
|
+
const currentHidden = new Set(hookHidden);
|
|
15943
|
+
const pickerHiddenSet = new Set(pickerHidden);
|
|
15944
|
+
return currentHidden.size !== pickerHiddenSet.size || pickerHidden.some((item) => !currentHidden.has(item)) || hookHidden.some((item) => !pickerHiddenSet.has(item));
|
|
15945
|
+
}
|
|
15946
|
+
function useStatuslineHiddenSync({
|
|
15947
|
+
pickerOpen,
|
|
15948
|
+
pickerHidden,
|
|
15949
|
+
hiddenItems,
|
|
15950
|
+
setHiddenItems
|
|
15951
|
+
}) {
|
|
15952
|
+
useEffect(() => {
|
|
15953
|
+
if (!pickerOpen) return;
|
|
15954
|
+
if (statuslineHiddenDiffers(hiddenItems, pickerHidden)) {
|
|
15955
|
+
setHiddenItems([...pickerHidden]);
|
|
15956
|
+
}
|
|
15957
|
+
}, [pickerHidden, pickerOpen, setHiddenItems, hiddenItems]);
|
|
15958
|
+
}
|
|
15959
|
+
function computeStreamChipActions(input) {
|
|
15960
|
+
const actions = [];
|
|
15961
|
+
const visible = new Set(input.visibleChipKeys);
|
|
15962
|
+
if (input.brainPromptNow && !input.brainPromptPrev) {
|
|
15963
|
+
actions.push({ type: "statuslineChipShow", key: "brain", expiresIn: 5 });
|
|
15964
|
+
} else if (!input.brainPromptNow && input.brainPromptPrev && visible.has("brain")) {
|
|
15965
|
+
actions.push({ type: "statuslineChipExpire", key: "brain" });
|
|
15966
|
+
}
|
|
15967
|
+
if (input.enhanceNow && !input.enhancePrev) {
|
|
15968
|
+
actions.push({ type: "statuslineChipShow", key: "enhance", expiresIn: 5 });
|
|
15969
|
+
} else if (!input.enhanceNow && input.enhancePrev && visible.has("enhance")) {
|
|
15970
|
+
actions.push({ type: "statuslineChipExpire", key: "enhance" });
|
|
15971
|
+
}
|
|
15972
|
+
return actions;
|
|
15973
|
+
}
|
|
15974
|
+
function computeExpiredChipKeys(chips, now = Date.now()) {
|
|
15975
|
+
return chips.filter((chip) => isChipExpired(chip, now)).map((chip) => chip.key);
|
|
15976
|
+
}
|
|
15977
|
+
function useStreamChipExpiration({
|
|
15978
|
+
brainPrompt,
|
|
15979
|
+
enhance,
|
|
15980
|
+
visibleChips,
|
|
15981
|
+
dispatch
|
|
15982
|
+
}) {
|
|
15983
|
+
const prevBrainPromptRef = useRef(brainPrompt);
|
|
15984
|
+
const prevEnhanceRef = useRef(enhance);
|
|
15985
|
+
useEffect(() => {
|
|
15986
|
+
const actions = computeStreamChipActions({
|
|
15987
|
+
brainPromptNow: !!brainPrompt,
|
|
15988
|
+
brainPromptPrev: !!prevBrainPromptRef.current,
|
|
15989
|
+
enhanceNow: !!enhance,
|
|
15990
|
+
enhancePrev: !!prevEnhanceRef.current,
|
|
15991
|
+
visibleChipKeys: visibleChips.map((chip) => chip.key)
|
|
15992
|
+
});
|
|
15993
|
+
for (const action of actions) dispatch(action);
|
|
15994
|
+
prevBrainPromptRef.current = brainPrompt;
|
|
15995
|
+
prevEnhanceRef.current = enhance;
|
|
15996
|
+
}, [brainPrompt, enhance, visibleChips, dispatch]);
|
|
15997
|
+
useEffect(() => {
|
|
15998
|
+
const interval = setInterval(() => {
|
|
15999
|
+
const expired = computeExpiredChipKeys(visibleChips, Date.now());
|
|
16000
|
+
for (const key of expired) {
|
|
16001
|
+
dispatch({ type: "statuslineChipExpire", key });
|
|
16002
|
+
}
|
|
16003
|
+
}, 3e4);
|
|
16004
|
+
return () => clearInterval(interval);
|
|
16005
|
+
}, [visibleChips, dispatch]);
|
|
16006
|
+
}
|
|
16007
|
+
function formatWorkingDirChip(workingDir, projectRoot) {
|
|
16008
|
+
if (!workingDir || workingDir === projectRoot) return void 0;
|
|
16009
|
+
const rel = path9.relative(projectRoot, workingDir) || ".";
|
|
16010
|
+
if (rel === ".") return void 0;
|
|
16011
|
+
return rel.replaceAll(path9.sep, "/");
|
|
16012
|
+
}
|
|
16013
|
+
function useWorkingDirChip(ctx, projectRoot) {
|
|
16014
|
+
const [workingDirChip, setWorkingDirChip] = useState(
|
|
16015
|
+
() => formatWorkingDirChip(ctx.workingDir, projectRoot)
|
|
16016
|
+
);
|
|
16017
|
+
useEffect(() => {
|
|
16018
|
+
setWorkingDirChip(formatWorkingDirChip(ctx.workingDir, projectRoot));
|
|
16019
|
+
return ctx.onWorkingDirChanged((newDir) => {
|
|
16020
|
+
setWorkingDirChip(formatWorkingDirChip(newDir, projectRoot));
|
|
16021
|
+
});
|
|
16022
|
+
}, [ctx, projectRoot]);
|
|
16023
|
+
return workingDirChip;
|
|
16024
|
+
}
|
|
15618
16025
|
function useStatuslineState(opts) {
|
|
15619
16026
|
const [liveModel, setLiveModel] = useState(opts.model);
|
|
15620
16027
|
const [liveProvider, setLiveProvider] = useState(opts.provider ?? "agent");
|
|
@@ -16267,6 +16674,22 @@ function createPanelOpenDispatcher(deps) {
|
|
|
16267
16674
|
};
|
|
16268
16675
|
}
|
|
16269
16676
|
|
|
16677
|
+
// src/submit-history.ts
|
|
16678
|
+
function shouldPushSubmittedHistory(raw) {
|
|
16679
|
+
const trimmed = raw.trim();
|
|
16680
|
+
if (!trimmed) return { push: false, route: "empty", trimmed };
|
|
16681
|
+
if (trimmed === "/image" || trimmed === "/paste-image") {
|
|
16682
|
+
return { push: true, route: "paste-image", trimmed };
|
|
16683
|
+
}
|
|
16684
|
+
if (trimmed === "/prompt" || trimmed === "/prompts-browse") {
|
|
16685
|
+
return { push: true, route: "prompt-picker", trimmed };
|
|
16686
|
+
}
|
|
16687
|
+
if (trimmed.startsWith("/")) {
|
|
16688
|
+
return { push: true, route: "slash", trimmed };
|
|
16689
|
+
}
|
|
16690
|
+
return { push: true, route: "normal", trimmed };
|
|
16691
|
+
}
|
|
16692
|
+
|
|
16270
16693
|
// src/paste-accumulator.ts
|
|
16271
16694
|
var BEGIN = "[200~";
|
|
16272
16695
|
var END = "[201~";
|
|
@@ -16295,7 +16718,7 @@ function feedPaste(accum, input) {
|
|
|
16295
16718
|
if (accum === null && !input.includes(BEGIN)) {
|
|
16296
16719
|
if (input.startsWith("[") && !input.startsWith(BEGIN) && !input.startsWith(END)) {
|
|
16297
16720
|
if (PARTIAL_ANSI_RE.test(input)) {
|
|
16298
|
-
return { accum:
|
|
16721
|
+
return { accum: null, complete: null };
|
|
16299
16722
|
}
|
|
16300
16723
|
return null;
|
|
16301
16724
|
}
|
|
@@ -16774,11 +17197,17 @@ function App({
|
|
|
16774
17197
|
useEffect(() => {
|
|
16775
17198
|
setStatuslineHiddenItems(hiddenItems);
|
|
16776
17199
|
saveStatuslineHiddenItems(hiddenItems).catch?.((err) => {
|
|
16777
|
-
console.error(
|
|
17200
|
+
console.error(
|
|
17201
|
+
JSON.stringify({
|
|
17202
|
+
level: "error",
|
|
17203
|
+
event: "statusline.persist_hidden_failed",
|
|
17204
|
+
message: err instanceof Error ? err.message : String(err),
|
|
17205
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
17206
|
+
})
|
|
17207
|
+
);
|
|
16778
17208
|
});
|
|
16779
17209
|
}, [setStatuslineHiddenItems, saveStatuslineHiddenItems, hiddenItems]);
|
|
16780
17210
|
const projectRoot = agent.ctx.projectRoot;
|
|
16781
|
-
const promptLoaderRef = useRef(null);
|
|
16782
17211
|
const promptUsageRef = useRef(null);
|
|
16783
17212
|
const refreshGoalSummary = useCallback(() => {
|
|
16784
17213
|
if (!projectRoot) return;
|
|
@@ -16810,331 +17239,41 @@ function App({
|
|
|
16810
17239
|
useEffect(() => {
|
|
16811
17240
|
refreshGoalSummary();
|
|
16812
17241
|
}, [refreshGoalSummary]);
|
|
16813
|
-
const restoredEntries = (
|
|
16814
|
-
|
|
16815
|
-
|
|
16816
|
-
|
|
16817
|
-
|
|
16818
|
-
|
|
16819
|
-
|
|
16820
|
-
|
|
16821
|
-
|
|
16822
|
-
|
|
16823
|
-
|
|
16824
|
-
|
|
16825
|
-
|
|
16826
|
-
|
|
16827
|
-
|
|
16828
|
-
|
|
16829
|
-
|
|
16830
|
-
|
|
16831
|
-
|
|
16832
|
-
|
|
16833
|
-
|
|
16834
|
-
|
|
16835
|
-
|
|
16836
|
-
|
|
16837
|
-
|
|
16838
|
-
|
|
16839
|
-
|
|
16840
|
-
|
|
16841
|
-
|
|
16842
|
-
|
|
16843
|
-
|
|
16844
|
-
|
|
16845
|
-
|
|
16846
|
-
|
|
16847
|
-
status: "idle",
|
|
16848
|
-
interrupts: 0,
|
|
16849
|
-
steeringPending: false,
|
|
16850
|
-
steerSnapshot: null,
|
|
16851
|
-
hint: "",
|
|
16852
|
-
brain: { state: "idle" },
|
|
16853
|
-
brainPrompt: null,
|
|
16854
|
-
nextId: initialNextId,
|
|
16855
|
-
picker: { open: false, query: "", matches: [], selected: 0 },
|
|
16856
|
-
slashPicker: { open: false, query: "", matches: [], selected: 0 },
|
|
16857
|
-
runningTools: /* @__PURE__ */ new Map(),
|
|
16858
|
-
queue: [],
|
|
16859
|
-
nextQueueId: 1,
|
|
16860
|
-
inputHistory: [],
|
|
16861
|
-
historyIndex: 0,
|
|
16862
|
-
historyDraft: "",
|
|
16863
|
-
modelPicker: {
|
|
16864
|
-
open: false,
|
|
16865
|
-
step: "provider",
|
|
16866
|
-
providerOptions: [],
|
|
16867
|
-
modelOptions: [],
|
|
16868
|
-
filteredOptions: [],
|
|
16869
|
-
selected: 0,
|
|
16870
|
-
searchQuery: ""
|
|
16871
|
-
},
|
|
16872
|
-
autonomyPicker: { open: false, options: [], selected: 0 },
|
|
16873
|
-
modePicker: { open: false, modes: [], selected: 0 },
|
|
16874
|
-
designPicker: { open: false, kits: [], selected: 0, stack: "web" },
|
|
16875
|
-
promptPicker: {
|
|
16876
|
-
open: false,
|
|
16877
|
-
all: [],
|
|
16878
|
-
categories: [],
|
|
16879
|
-
recentSlugs: [],
|
|
16880
|
-
catIndex: 0,
|
|
16881
|
-
selected: 0
|
|
16882
|
-
},
|
|
16883
|
-
resumePicker: {
|
|
16884
|
-
open: false,
|
|
16885
|
-
sessions: [],
|
|
16886
|
-
selected: 0,
|
|
16887
|
-
busy: false,
|
|
16888
|
-
hint: void 0,
|
|
16889
|
-
error: void 0
|
|
16890
|
-
},
|
|
16891
|
-
settingsPicker: {
|
|
16892
|
-
open: false,
|
|
16893
|
-
field: 0,
|
|
16894
|
-
lastSettingsField: 0,
|
|
16895
|
-
filter: "",
|
|
16896
|
-
mode: "off",
|
|
16897
|
-
delayMs: 0,
|
|
16898
|
-
titleAnimation: true,
|
|
16899
|
-
yolo: false,
|
|
16900
|
-
streamFleet: true,
|
|
16901
|
-
chime: false,
|
|
16902
|
-
confirmExit: true,
|
|
16903
|
-
nextPrediction: false,
|
|
16904
|
-
featureMcp: true,
|
|
16905
|
-
featurePlugins: true,
|
|
16906
|
-
featureMemory: true,
|
|
16907
|
-
featureSkills: true,
|
|
16908
|
-
featureModelsRegistry: true,
|
|
16909
|
-
tokenSavingTier: "off",
|
|
16910
|
-
allowOutsideProjectRoot: true,
|
|
16911
|
-
contextAutoCompact: true,
|
|
16912
|
-
contextStrategy: "hybrid",
|
|
16913
|
-
contextMode: "balanced",
|
|
16914
|
-
maxConcurrent: 10,
|
|
16915
|
-
logLevel: "info",
|
|
16916
|
-
auditLevel: "standard",
|
|
16917
|
-
indexOnStart: true,
|
|
16918
|
-
multiDiffSummaryThreshold: 5,
|
|
16919
|
-
maxIterations: 500,
|
|
16920
|
-
autoProceedMaxIterations: 50,
|
|
16921
|
-
enhanceDelayMs: 6e4,
|
|
16922
|
-
enhanceEnabled: true,
|
|
16923
|
-
enhanceLanguage: "original",
|
|
16924
|
-
debugStream: false,
|
|
16925
|
-
statuslineMode: "detailed",
|
|
16926
|
-
reasoningMode: "auto",
|
|
16927
|
-
reasoningEffort: "high",
|
|
16928
|
-
reasoningPreserve: false,
|
|
16929
|
-
thinkingWord: "thinking",
|
|
16930
|
-
thinkingWordEditing: false,
|
|
16931
|
-
thinkingWordDraft: "",
|
|
16932
|
-
cacheTtl: "default",
|
|
16933
|
-
configScope: "global",
|
|
16934
|
-
animationStyle: "rainbow"
|
|
16935
|
-
},
|
|
16936
|
-
statuslinePicker: { open: false, field: 0, hiddenItems: [], visibleChips: [], hint: void 0 },
|
|
16937
|
-
pluginPicker: { open: false, items: [], selected: 0, busy: false, hint: void 0 },
|
|
16938
|
-
authPanel: AUTH_PANEL_INITIAL,
|
|
16939
|
-
projectPicker: {
|
|
16940
|
-
open: false,
|
|
16941
|
-
allItems: [],
|
|
16942
|
-
items: [],
|
|
16943
|
-
selected: 0,
|
|
16944
|
-
filter: "",
|
|
16945
|
-
hint: void 0
|
|
16946
|
-
},
|
|
16947
|
-
fKeyPicker: { open: false, selected: 0 },
|
|
16948
|
-
confirmQueue: [],
|
|
16949
|
-
enhance: null,
|
|
16950
|
-
enhanceEnabled,
|
|
16951
|
-
enhanceBusy: false,
|
|
16952
|
-
escConfirm: null,
|
|
16953
|
-
sendModePicker: null,
|
|
16954
|
-
contextChipVersion: 0,
|
|
16955
|
-
fleet: {},
|
|
16956
|
-
leader: {
|
|
16957
|
-
iterations: 0,
|
|
16958
|
-
toolCalls: 0,
|
|
16959
|
-
recentTools: [],
|
|
16960
|
-
currentTool: void 0,
|
|
16961
|
-
startedAt: Date.now(),
|
|
16962
|
-
lastEventAt: Date.now(),
|
|
16963
|
-
iterating: false
|
|
16964
|
-
},
|
|
16965
|
-
fleetCost: 0,
|
|
16966
|
-
fleetTokens: { input: 0, output: 0 },
|
|
16967
|
-
fleetConcurrency: 4,
|
|
16968
|
-
streamFleet: true,
|
|
16969
|
-
monitorOpen: false,
|
|
16970
|
-
agentsMonitorOpen: initialAgentsMonitorOpen ?? false,
|
|
16971
|
-
helpOpen: false,
|
|
16972
|
-
todosMonitorOpen: false,
|
|
16973
|
-
queuePanelOpen: false,
|
|
16974
|
-
processListOpen: false,
|
|
16975
|
-
auditPanelOpen: false,
|
|
16976
|
-
planPanelOpen: false,
|
|
16977
|
-
kanbanPanelOpen: false,
|
|
16978
|
-
goalPanelOpen: false,
|
|
16979
|
-
sessionsPanelOpen: false,
|
|
16980
|
-
sessionsPanel: { sessions: [], busy: false, selected: -1 },
|
|
16981
|
-
sessionResumeConfirm: null,
|
|
16982
|
-
collabSession: null,
|
|
16983
|
-
checkpoints: [],
|
|
16984
|
-
rewindOverlay: null,
|
|
16985
|
-
eternalStage: null,
|
|
16986
|
-
goalSummary: null,
|
|
16987
|
-
autoPhase: null,
|
|
16988
|
-
sddBoard: null,
|
|
16989
|
-
worktrees: {},
|
|
16990
|
-
worktreeMonitorOpen: false,
|
|
16991
|
-
coordinator: {
|
|
16992
|
-
goals: [],
|
|
16993
|
-
timeline: [],
|
|
16994
|
-
knowledgeCount: 0,
|
|
16995
|
-
monitorOpen: false,
|
|
16996
|
-
healthy: false
|
|
16997
|
-
},
|
|
16998
|
-
scrollOffset: 0,
|
|
16999
|
-
totalLines: 0,
|
|
17000
|
-
viewportRows: 0,
|
|
17001
|
-
pendingNewLines: 0,
|
|
17002
|
-
debugStreamStats: null,
|
|
17003
|
-
countdown: null
|
|
17242
|
+
const restoredEntries = buildRestoredEntries(agent.ctx.messages, restoredToolCalls);
|
|
17243
|
+
const [state, dispatch] = useReducer(
|
|
17244
|
+
reducer,
|
|
17245
|
+
createInitialState({
|
|
17246
|
+
banner,
|
|
17247
|
+
appVersion,
|
|
17248
|
+
provider,
|
|
17249
|
+
model,
|
|
17250
|
+
cwd: agent.ctx.cwd,
|
|
17251
|
+
family,
|
|
17252
|
+
keyTail,
|
|
17253
|
+
restoredEntries,
|
|
17254
|
+
enhanceEnabled,
|
|
17255
|
+
initialAgentsMonitorOpen
|
|
17256
|
+
})
|
|
17257
|
+
);
|
|
17258
|
+
useInputHistoryPersistence({
|
|
17259
|
+
projectRoot,
|
|
17260
|
+
inputHistory: state.inputHistory,
|
|
17261
|
+
dispatch
|
|
17262
|
+
});
|
|
17263
|
+
const { openPromptPicker } = usePromptPicker({ projectRoot, dispatch });
|
|
17264
|
+
const { openModePicker } = useModePicker({ dispatch, getModes });
|
|
17265
|
+
useStatuslineHiddenSync({
|
|
17266
|
+
pickerOpen: state.statuslinePicker.open,
|
|
17267
|
+
pickerHidden: state.statuslinePicker.hiddenItems,
|
|
17268
|
+
hiddenItems,
|
|
17269
|
+
setHiddenItems: (items) => setHiddenItems(items)
|
|
17270
|
+
});
|
|
17271
|
+
useStreamChipExpiration({
|
|
17272
|
+
brainPrompt: state.brainPrompt,
|
|
17273
|
+
enhance: state.enhance,
|
|
17274
|
+
visibleChips: state.statuslinePicker.visibleChips,
|
|
17275
|
+
dispatch
|
|
17004
17276
|
});
|
|
17005
|
-
const inputHistoryStore = useMemo(() => {
|
|
17006
|
-
if (!projectRoot) return null;
|
|
17007
|
-
const file = resolveWstackPaths({ projectRoot }).projectInputHistory;
|
|
17008
|
-
return new InputHistoryStore(file, new DefaultSecretScrubber(), INPUT_HISTORY_DEFAULT_MAX);
|
|
17009
|
-
}, [projectRoot]);
|
|
17010
|
-
const inputHistoryLoadedRef = useRef(false);
|
|
17011
|
-
const inputHistorySaveTimerRef = useRef(void 0);
|
|
17012
|
-
const inputHistoryLastSavedRef = useRef("");
|
|
17013
|
-
useEffect(() => {
|
|
17014
|
-
if (!inputHistoryStore) return;
|
|
17015
|
-
let cancelled = false;
|
|
17016
|
-
inputHistoryStore.load().then((entries) => {
|
|
17017
|
-
if (cancelled) return;
|
|
17018
|
-
inputHistoryLoadedRef.current = true;
|
|
17019
|
-
inputHistoryLastSavedRef.current = JSON.stringify(entries);
|
|
17020
|
-
if (entries.length === 0) return;
|
|
17021
|
-
dispatch({ type: "setInputHistory", entries });
|
|
17022
|
-
}).catch(() => {
|
|
17023
|
-
if (!cancelled) inputHistoryLoadedRef.current = true;
|
|
17024
|
-
});
|
|
17025
|
-
return () => {
|
|
17026
|
-
cancelled = true;
|
|
17027
|
-
};
|
|
17028
|
-
}, [inputHistoryStore]);
|
|
17029
|
-
useEffect(() => {
|
|
17030
|
-
if (!inputHistoryStore || !inputHistoryLoadedRef.current) return;
|
|
17031
|
-
const snapshot = JSON.stringify(state.inputHistory);
|
|
17032
|
-
if (snapshot === inputHistoryLastSavedRef.current) return;
|
|
17033
|
-
if (inputHistorySaveTimerRef.current) clearTimeout(inputHistorySaveTimerRef.current);
|
|
17034
|
-
inputHistorySaveTimerRef.current = setTimeout(() => {
|
|
17035
|
-
inputHistoryLastSavedRef.current = snapshot;
|
|
17036
|
-
inputHistoryStore.save(state.inputHistory).catch(() => {
|
|
17037
|
-
});
|
|
17038
|
-
}, 200);
|
|
17039
|
-
return () => {
|
|
17040
|
-
if (inputHistorySaveTimerRef.current) clearTimeout(inputHistorySaveTimerRef.current);
|
|
17041
|
-
};
|
|
17042
|
-
}, [state.inputHistory, inputHistoryStore]);
|
|
17043
|
-
const getPromptLoader = () => {
|
|
17044
|
-
if (!promptLoaderRef.current && projectRoot) {
|
|
17045
|
-
let bundledDir;
|
|
17046
|
-
try {
|
|
17047
|
-
const req = createRequire(import.meta.url);
|
|
17048
|
-
bundledDir = path6.join(
|
|
17049
|
-
path6.dirname(req.resolve("@wrongstack/core/package.json")),
|
|
17050
|
-
"data",
|
|
17051
|
-
"prompts"
|
|
17052
|
-
);
|
|
17053
|
-
} catch {
|
|
17054
|
-
bundledDir = void 0;
|
|
17055
|
-
}
|
|
17056
|
-
const paths = resolveWstackPaths({ projectRoot });
|
|
17057
|
-
promptLoaderRef.current = new DefaultPromptLoader({ paths, bundledDir });
|
|
17058
|
-
promptUsageRef.current = new PromptUsageStore(paths.promptUsage);
|
|
17059
|
-
}
|
|
17060
|
-
return promptLoaderRef.current;
|
|
17061
|
-
};
|
|
17062
|
-
const openPromptPicker = async () => {
|
|
17063
|
-
const loader = getPromptLoader();
|
|
17064
|
-
if (!loader) return;
|
|
17065
|
-
loader.invalidateCache();
|
|
17066
|
-
const all = await loader.list();
|
|
17067
|
-
const entries = all.map((e) => ({
|
|
17068
|
-
slug: e.slug,
|
|
17069
|
-
title: e.title,
|
|
17070
|
-
description: e.description,
|
|
17071
|
-
category: e.category,
|
|
17072
|
-
source: e.source,
|
|
17073
|
-
content: e.content,
|
|
17074
|
-
favorite: e.favorite
|
|
17075
|
-
}));
|
|
17076
|
-
const recentSlugs = (await promptUsageRef.current?.recent(50).catch(() => []))?.map((r) => r.slug) ?? [];
|
|
17077
|
-
const hasFavorites = entries.some((e) => e.favorite);
|
|
17078
|
-
const cats = [
|
|
17079
|
-
"all",
|
|
17080
|
-
...recentSlugs.length > 0 ? ["\u{1F558} recent"] : [],
|
|
17081
|
-
...hasFavorites ? ["\u2605 favorites"] : [],
|
|
17082
|
-
...Array.from(new Set(entries.map((e) => e.category))).sort()
|
|
17083
|
-
];
|
|
17084
|
-
dispatch({ type: "promptPickerOpen", all: entries, categories: cats, recentSlugs });
|
|
17085
|
-
};
|
|
17086
|
-
const openModePicker = useCallback(async () => {
|
|
17087
|
-
if (!getModes) return;
|
|
17088
|
-
const result = await getModes();
|
|
17089
|
-
const options = toModeOptions(result.modes, result.activeId);
|
|
17090
|
-
dispatch({ type: "modePickerOpen", modes: options });
|
|
17091
|
-
}, [getModes]);
|
|
17092
|
-
useEffect(() => {
|
|
17093
|
-
if (state.statuslinePicker.open) {
|
|
17094
|
-
const pickerHidden = state.statuslinePicker.hiddenItems;
|
|
17095
|
-
const currentHidden = new Set(hiddenItems);
|
|
17096
|
-
const pickerHiddenSet = new Set(pickerHidden);
|
|
17097
|
-
const differs = currentHidden.size !== pickerHiddenSet.size || pickerHidden.some((item) => !currentHidden.has(item)) || hiddenItems.some((item) => !pickerHiddenSet.has(item));
|
|
17098
|
-
if (differs) {
|
|
17099
|
-
setHiddenItems([...pickerHidden]);
|
|
17100
|
-
}
|
|
17101
|
-
}
|
|
17102
|
-
}, [
|
|
17103
|
-
state.statuslinePicker.hiddenItems,
|
|
17104
|
-
state.statuslinePicker.open,
|
|
17105
|
-
setHiddenItems,
|
|
17106
|
-
hiddenItems
|
|
17107
|
-
]);
|
|
17108
|
-
const prevBrainPromptRef = useRef(state.brainPrompt);
|
|
17109
|
-
const prevEnhanceRef = useRef(state.enhance);
|
|
17110
|
-
useEffect(() => {
|
|
17111
|
-
if (state.brainPrompt && !prevBrainPromptRef.current) {
|
|
17112
|
-
dispatch({ type: "statuslineChipShow", key: "brain", expiresIn: 5 });
|
|
17113
|
-
} else if (!state.brainPrompt && prevBrainPromptRef.current) {
|
|
17114
|
-
if (state.statuslinePicker.visibleChips.some((c) => c.key === "brain")) {
|
|
17115
|
-
dispatch({ type: "statuslineChipExpire", key: "brain" });
|
|
17116
|
-
}
|
|
17117
|
-
}
|
|
17118
|
-
prevBrainPromptRef.current = state.brainPrompt;
|
|
17119
|
-
if (state.enhance && !prevEnhanceRef.current) {
|
|
17120
|
-
dispatch({ type: "statuslineChipShow", key: "enhance", expiresIn: 5 });
|
|
17121
|
-
} else if (!state.enhance && prevEnhanceRef.current) {
|
|
17122
|
-
if (state.statuslinePicker.visibleChips.some((c) => c.key === "enhance")) {
|
|
17123
|
-
dispatch({ type: "statuslineChipExpire", key: "enhance" });
|
|
17124
|
-
}
|
|
17125
|
-
}
|
|
17126
|
-
prevEnhanceRef.current = state.enhance;
|
|
17127
|
-
}, [state.brainPrompt, state.enhance, state.statuslinePicker.visibleChips, dispatch]);
|
|
17128
|
-
useEffect(() => {
|
|
17129
|
-
const interval = setInterval(() => {
|
|
17130
|
-
const now = Date.now();
|
|
17131
|
-
const expired = state.statuslinePicker.visibleChips.filter((c) => isChipExpired(c, now));
|
|
17132
|
-
for (const chip of expired) {
|
|
17133
|
-
dispatch({ type: "statuslineChipExpire", key: chip.key });
|
|
17134
|
-
}
|
|
17135
|
-
}, 3e4);
|
|
17136
|
-
return () => clearInterval(interval);
|
|
17137
|
-
}, [state.statuslinePicker.visibleChips, dispatch]);
|
|
17138
17277
|
useAutonomousCoordinator(subscribeCoordinatorEvents, dispatch);
|
|
17139
17278
|
const builderRef = useRef(null);
|
|
17140
17279
|
if (builderRef.current === null) {
|
|
@@ -17146,23 +17285,10 @@ function App({
|
|
|
17146
17285
|
const lastEnterAtRef = useRef(0);
|
|
17147
17286
|
const tokenPreviewsRef = useRef(/* @__PURE__ */ new Map());
|
|
17148
17287
|
const projectName = React5.useMemo(() => {
|
|
17149
|
-
const base =
|
|
17150
|
-
return base && base !==
|
|
17288
|
+
const base = path9.basename(projectRoot);
|
|
17289
|
+
return base && base !== path9.sep ? base : void 0;
|
|
17151
17290
|
}, [projectRoot]);
|
|
17152
|
-
const
|
|
17153
|
-
const ctx = agent.ctx;
|
|
17154
|
-
if (ctx.workingDir && ctx.workingDir !== projectRoot) {
|
|
17155
|
-
return path6.relative(projectRoot, ctx.workingDir) || ".";
|
|
17156
|
-
}
|
|
17157
|
-
return void 0;
|
|
17158
|
-
});
|
|
17159
|
-
React5.useEffect(() => {
|
|
17160
|
-
const ctx = agent.ctx;
|
|
17161
|
-
return ctx.onWorkingDirChanged((newDir) => {
|
|
17162
|
-
const rel = path6.relative(projectRoot, newDir) || ".";
|
|
17163
|
-
setWorkingDirChip(rel === "." ? void 0 : rel);
|
|
17164
|
-
});
|
|
17165
|
-
}, [agent.ctx, projectRoot]);
|
|
17291
|
+
const workingDirChip = useWorkingDirChip(agent.ctx, projectRoot);
|
|
17166
17292
|
const liveSettings = getSettings?.();
|
|
17167
17293
|
const liveStatuslineMode = liveSettings?.statuslineMode ?? "detailed";
|
|
17168
17294
|
const liveAnimationStyle = liveSettings?.animationStyle ?? "rainbow";
|
|
@@ -17564,15 +17690,16 @@ function App({
|
|
|
17564
17690
|
const fleetCounts = useMemo(() => {
|
|
17565
17691
|
const entries = Object.values(state.fleet);
|
|
17566
17692
|
if (entries.length === 0) return void 0;
|
|
17567
|
-
|
|
17568
|
-
|
|
17569
|
-
|
|
17570
|
-
|
|
17571
|
-
|
|
17572
|
-
|
|
17573
|
-
|
|
17574
|
-
|
|
17575
|
-
|
|
17693
|
+
const running = entries.filter((e) => e.status === "running").length;
|
|
17694
|
+
if (running === 0) return void 0;
|
|
17695
|
+
return { running, idle: 0, pending: 0, completed: 0 };
|
|
17696
|
+
}, [state.fleet]);
|
|
17697
|
+
const visibleSubagentCount = fleetCounts?.running ?? 0;
|
|
17698
|
+
const hasVisibleFleetPanel = useMemo(() => {
|
|
17699
|
+
for (const e of Object.values(state.fleet)) {
|
|
17700
|
+
if (e.status === "running") return true;
|
|
17701
|
+
}
|
|
17702
|
+
return false;
|
|
17576
17703
|
}, [state.fleet]);
|
|
17577
17704
|
const entriesWithLeader = useMemo(() => {
|
|
17578
17705
|
const leaderEntry = {
|
|
@@ -20407,7 +20534,10 @@ Available chords:
|
|
|
20407
20534
|
autoSubmitCapWarnedRef.current = false;
|
|
20408
20535
|
dispatch({ type: "scrollToBottom" });
|
|
20409
20536
|
const pushSubmittedHistory = () => {
|
|
20410
|
-
|
|
20537
|
+
const decision = shouldPushSubmittedHistory(trimmed);
|
|
20538
|
+
if (decision.push) {
|
|
20539
|
+
dispatch({ type: "historyPush", text: decision.trimmed });
|
|
20540
|
+
}
|
|
20411
20541
|
};
|
|
20412
20542
|
if (trimmed === "/image" || trimmed === "/paste-image") {
|
|
20413
20543
|
pushSubmittedHistory();
|
|
@@ -21157,7 +21287,7 @@ ${content}
|
|
|
21157
21287
|
brain: state.brain,
|
|
21158
21288
|
projectName,
|
|
21159
21289
|
workingDir: workingDirChip,
|
|
21160
|
-
subagentCount:
|
|
21290
|
+
subagentCount: visibleSubagentCount,
|
|
21161
21291
|
processCount: getProcessRegistry().activeCount,
|
|
21162
21292
|
hiddenItems,
|
|
21163
21293
|
mode: liveStatuslineMode,
|
|
@@ -21255,7 +21385,7 @@ ${content}
|
|
|
21255
21385
|
onCoordinatorStop: onCoordinatorStop ?? void 0,
|
|
21256
21386
|
coordinatorRunning
|
|
21257
21387
|
}
|
|
21258
|
-
) : director ||
|
|
21388
|
+
) : director || hasVisibleFleetPanel || state.collabSession ? /* @__PURE__ */ jsx(
|
|
21259
21389
|
FleetPanel,
|
|
21260
21390
|
{
|
|
21261
21391
|
entries: entriesWithLeader,
|
|
@@ -21442,7 +21572,7 @@ async function runTui(opts) {
|
|
|
21442
21572
|
stdout,
|
|
21443
21573
|
events: opts.events,
|
|
21444
21574
|
model: opts.model,
|
|
21445
|
-
appName: opts.projectRoot ?
|
|
21575
|
+
appName: opts.projectRoot ? path9.basename(opts.projectRoot) : void 0
|
|
21446
21576
|
});
|
|
21447
21577
|
};
|
|
21448
21578
|
const stopTitle = () => {
|
|
@@ -21539,7 +21669,7 @@ async function runTui(opts) {
|
|
|
21539
21669
|
const hqPublisher = createHqPublisherFromEnv({
|
|
21540
21670
|
clientKind: "tui",
|
|
21541
21671
|
projectRoot: opts.projectRoot,
|
|
21542
|
-
projectName:
|
|
21672
|
+
projectName: path9.basename(opts.projectRoot),
|
|
21543
21673
|
appConfig: opts.appConfig
|
|
21544
21674
|
});
|
|
21545
21675
|
hqPublisher?.connect();
|
|
@@ -21579,7 +21709,7 @@ async function runTui(opts) {
|
|
|
21579
21709
|
await mailbox.registerClient({
|
|
21580
21710
|
clientId,
|
|
21581
21711
|
sessionId: opts.getSessionId?.() ?? opts.projectRoot,
|
|
21582
|
-
name: `TUI [${
|
|
21712
|
+
name: `TUI [${path9.basename(opts.projectRoot)}]`,
|
|
21583
21713
|
source: "tui",
|
|
21584
21714
|
pid: process.pid
|
|
21585
21715
|
});
|