@wrongstack/tui 0.273.1 → 0.274.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +10 -0
- package/dist/index.js +1384 -106
- package/dist/index.js.map +1 -1
- package/package.json +4 -4
package/dist/index.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { writeErr, resolveProjectDir, wstackGlobalRoot, createHqPublisherFromEnv, GlobalMailbox, resolveWstackPaths, loadGoal, InputBuilder, DefaultSessionRewinder, writeOut, formatTodosList, buildGoalPreamble, expectDefined as expectDefined$1, projectSlug, shouldEnhance, enhanceUserPrompt, recentTextTurns, normalizedEqual, buildChildEnv } from '@wrongstack/core';
|
|
2
2
|
export { buildGoalPreamble } from '@wrongstack/core';
|
|
3
|
-
import { Box as Box$1, useInput, useStdin,
|
|
3
|
+
import { Box as Box$1, useStdout, Static, measureElement, useInput, useStdin, Text as Text$1, render, useApp } from 'ink';
|
|
4
4
|
import { randomUUID } from 'crypto';
|
|
5
5
|
import * as path5 from 'path';
|
|
6
|
-
import React5, { forwardRef, useState, useEffect, useMemo, memo, useRef, useCallback, useReducer,
|
|
6
|
+
import React5, { forwardRef, useState, useEffect, useMemo, memo, useRef, useLayoutEffect, useCallback, useReducer, isValidElement, Fragment as Fragment$1 } from 'react';
|
|
7
7
|
import * as fs3 from 'fs/promises';
|
|
8
8
|
import { expectDefined, toErrorMessage, resolveWstackPaths as resolveWstackPaths$1 } from '@wrongstack/core/utils';
|
|
9
9
|
import { routeImagesForModel } from '@wrongstack/runtime/vision';
|
|
@@ -119,6 +119,32 @@ function useTokenCounterRefresh(tokenCounter, events) {
|
|
|
119
119
|
// src/thinking-word.ts
|
|
120
120
|
var DEFAULT_TUI_THINKING_WORD = "thinking";
|
|
121
121
|
var MAX_TUI_THINKING_WORD_LENGTH = 16;
|
|
122
|
+
var TUI_THINKING_WORD_POOL = [
|
|
123
|
+
"pondering",
|
|
124
|
+
"cogitating",
|
|
125
|
+
"ruminating",
|
|
126
|
+
"noodling",
|
|
127
|
+
"brewing",
|
|
128
|
+
"conjuring",
|
|
129
|
+
"percolating",
|
|
130
|
+
"scheming",
|
|
131
|
+
"tinkering",
|
|
132
|
+
"vibing",
|
|
133
|
+
"crafting",
|
|
134
|
+
"wrangling",
|
|
135
|
+
"summoning",
|
|
136
|
+
"finagling",
|
|
137
|
+
"marinating",
|
|
138
|
+
"hatching",
|
|
139
|
+
"juggling",
|
|
140
|
+
"spelunking",
|
|
141
|
+
"contemplating",
|
|
142
|
+
"bamboozling",
|
|
143
|
+
"alchemizing",
|
|
144
|
+
"incubating",
|
|
145
|
+
"doodling",
|
|
146
|
+
"mulling"
|
|
147
|
+
];
|
|
122
148
|
function normalizeTuiThinkingWord(value) {
|
|
123
149
|
if (typeof value !== "string") return DEFAULT_TUI_THINKING_WORD;
|
|
124
150
|
const word = value.trim();
|
|
@@ -128,6 +154,18 @@ function normalizeTuiThinkingWord(value) {
|
|
|
128
154
|
if (!/^[\p{L}\p{N}_-]+$/u.test(word)) return DEFAULT_TUI_THINKING_WORD;
|
|
129
155
|
return word;
|
|
130
156
|
}
|
|
157
|
+
function isRandomTuiThinkingWord(value) {
|
|
158
|
+
if (typeof value !== "string") return true;
|
|
159
|
+
const word = value.trim().toLowerCase();
|
|
160
|
+
return word.length === 0 || word === DEFAULT_TUI_THINKING_WORD || word === "random";
|
|
161
|
+
}
|
|
162
|
+
function pickRandomTuiThinkingWord(previous) {
|
|
163
|
+
const pool = TUI_THINKING_WORD_POOL;
|
|
164
|
+
const candidates = previous ? pool.filter((w) => w !== previous) : pool;
|
|
165
|
+
const list = candidates.length > 0 ? candidates : pool;
|
|
166
|
+
const idx = Math.floor(Math.random() * list.length);
|
|
167
|
+
return list[idx] ?? list[0] ?? DEFAULT_TUI_THINKING_WORD;
|
|
168
|
+
}
|
|
131
169
|
function chipExpired(meta, now = Date.now()) {
|
|
132
170
|
if (meta.expiresIn == null) return false;
|
|
133
171
|
return now >= meta.shownAt + meta.expiresIn * 6e4;
|
|
@@ -2477,10 +2515,84 @@ function helpSections() {
|
|
|
2477
2515
|
{ keys: "/fleet", desc: "multi-agent fleet controls" },
|
|
2478
2516
|
{ keys: "/goal", desc: "set an autonomous goal" },
|
|
2479
2517
|
{ keys: "/autonomy", desc: "autonomy mode (eternal / off)" },
|
|
2480
|
-
{ keys: "/settings", desc: "
|
|
2518
|
+
{ keys: "/settings", desc: "settings picker (also: /settings <chord> <value> \xB7 /settings reset <chord>)" },
|
|
2519
|
+
{ keys: "/settings-get", desc: "show setting value(s) without opening picker" },
|
|
2481
2520
|
{ keys: "/clear", desc: "clear the conversation" }
|
|
2482
2521
|
]
|
|
2483
2522
|
},
|
|
2523
|
+
{
|
|
2524
|
+
// Surface user-facing knobs that don't have a key chord or slash
|
|
2525
|
+
// command of their own — the only way to change them is through the
|
|
2526
|
+
// settings picker. Keeping the descriptions terse so the overlay
|
|
2527
|
+
// fits in narrow terminals.
|
|
2528
|
+
title: "Settings",
|
|
2529
|
+
entries: [
|
|
2530
|
+
{
|
|
2531
|
+
keys: "Multi-diff summary",
|
|
2532
|
+
desc: "min files before per-tool aggregate footer (Ctrl+M in picker, settings \u2192 tools, 0 = off, default 5)"
|
|
2533
|
+
},
|
|
2534
|
+
{
|
|
2535
|
+
keys: "Index on session start",
|
|
2536
|
+
desc: "run incremental index at startup (Ctrl+I in picker)"
|
|
2537
|
+
},
|
|
2538
|
+
{
|
|
2539
|
+
keys: "Thinking word",
|
|
2540
|
+
desc: "status-bar working word (Ctrl+W in picker; Enter to type your own)"
|
|
2541
|
+
},
|
|
2542
|
+
{
|
|
2543
|
+
keys: "Refine countdown / Refine",
|
|
2544
|
+
desc: "prompt refinement delay / on-off (Ctrl+R / Ctrl+E in picker)"
|
|
2545
|
+
},
|
|
2546
|
+
{
|
|
2547
|
+
keys: "Reasoning mode",
|
|
2548
|
+
desc: "auto / on / off (Ctrl+N in picker)"
|
|
2549
|
+
},
|
|
2550
|
+
{
|
|
2551
|
+
keys: "Max concurrent",
|
|
2552
|
+
desc: "parallel subagent cap (Ctrl+L in picker, settings \u2192 fleet)"
|
|
2553
|
+
},
|
|
2554
|
+
{
|
|
2555
|
+
keys: "Statusline",
|
|
2556
|
+
desc: "detailed / minimum density (Ctrl+D in picker)"
|
|
2557
|
+
},
|
|
2558
|
+
{
|
|
2559
|
+
keys: "Default autonomy mode",
|
|
2560
|
+
desc: "off / suggest / auto (Alt+A in picker, settings \u2192 autonomy)"
|
|
2561
|
+
},
|
|
2562
|
+
{
|
|
2563
|
+
keys: "YOLO mode",
|
|
2564
|
+
desc: "skip all confirmation prompts (Alt+Y in picker, settings \u2192 UX)"
|
|
2565
|
+
},
|
|
2566
|
+
{
|
|
2567
|
+
keys: "Token-saving mode",
|
|
2568
|
+
desc: "off / minimal / light / medium / aggressive (Alt+T in picker)"
|
|
2569
|
+
},
|
|
2570
|
+
{
|
|
2571
|
+
keys: "Context mode",
|
|
2572
|
+
desc: "balanced / frugal / deep / archival (Alt+X in picker, settings \u2192 context)"
|
|
2573
|
+
},
|
|
2574
|
+
{
|
|
2575
|
+
keys: "Confirm before exit",
|
|
2576
|
+
desc: "confirmation on Esc interrupt & Ctrl+C exit (Alt+S in picker, settings \u2192 UX)"
|
|
2577
|
+
},
|
|
2578
|
+
{
|
|
2579
|
+
keys: "Completion chime",
|
|
2580
|
+
desc: "play a sound when agent finishes (Alt+C in picker, settings \u2192 UX)"
|
|
2581
|
+
},
|
|
2582
|
+
{
|
|
2583
|
+
keys: "Log level / Audit level",
|
|
2584
|
+
desc: "console log verbosity / audit depth (Alt+Shift+L / Alt+Shift+A in picker, settings \u2192 logging)"
|
|
2585
|
+
},
|
|
2586
|
+
{
|
|
2587
|
+
keys: "Stream debug logging",
|
|
2588
|
+
desc: "hex-dump raw SSE bytes to stderr (Alt+Shift+B in picker, settings \u2192 debug)"
|
|
2589
|
+
},
|
|
2590
|
+
{
|
|
2591
|
+
keys: "Config scope",
|
|
2592
|
+
desc: "global / project (Alt+Shift+G in picker, settings \u2192 debug)"
|
|
2593
|
+
}
|
|
2594
|
+
]
|
|
2595
|
+
},
|
|
2484
2596
|
{
|
|
2485
2597
|
title: "Tool Colors",
|
|
2486
2598
|
entries: toolColorLegend()
|
|
@@ -5017,6 +5129,61 @@ function CodeBlock({
|
|
|
5017
5129
|
}
|
|
5018
5130
|
);
|
|
5019
5131
|
}
|
|
5132
|
+
var MULTI_DIFF_SUMMARY_THRESHOLD = 5;
|
|
5133
|
+
function summarizeMultiFileDiffs(items) {
|
|
5134
|
+
let added = 0;
|
|
5135
|
+
let removed = 0;
|
|
5136
|
+
let hiddenAdded = 0;
|
|
5137
|
+
let hiddenRemoved = 0;
|
|
5138
|
+
let truncatedFiles = 0;
|
|
5139
|
+
for (const item of items) {
|
|
5140
|
+
added += item.preview.added;
|
|
5141
|
+
removed += item.preview.removed;
|
|
5142
|
+
hiddenAdded += item.preview.hiddenAdded;
|
|
5143
|
+
hiddenRemoved += item.preview.hiddenRemoved;
|
|
5144
|
+
if (item.preview.hidden > 0) truncatedFiles += 1;
|
|
5145
|
+
}
|
|
5146
|
+
return {
|
|
5147
|
+
fileCount: items.length,
|
|
5148
|
+
added,
|
|
5149
|
+
removed,
|
|
5150
|
+
hiddenAdded,
|
|
5151
|
+
hiddenRemoved,
|
|
5152
|
+
truncatedFiles
|
|
5153
|
+
};
|
|
5154
|
+
}
|
|
5155
|
+
function formatMultiDiffSummary(summary, threshold = MULTI_DIFF_SUMMARY_THRESHOLD) {
|
|
5156
|
+
if (threshold === 0) return null;
|
|
5157
|
+
const effectiveThreshold = threshold < 0 ? MULTI_DIFF_SUMMARY_THRESHOLD : threshold;
|
|
5158
|
+
if (summary.fileCount < effectiveThreshold) return null;
|
|
5159
|
+
const parts = [`${summary.fileCount} files`];
|
|
5160
|
+
if (summary.added > 0) parts.push(`+${summary.added}`);
|
|
5161
|
+
if (summary.removed > 0) parts.push(`-${summary.removed}`);
|
|
5162
|
+
if (summary.hiddenAdded > 0 || summary.hiddenRemoved > 0) {
|
|
5163
|
+
const hiddenParts = [];
|
|
5164
|
+
if (summary.hiddenAdded > 0) hiddenParts.push(`+${summary.hiddenAdded}`);
|
|
5165
|
+
if (summary.hiddenRemoved > 0) hiddenParts.push(`-${summary.hiddenRemoved}`);
|
|
5166
|
+
parts.push(`\u2026 ${hiddenParts.join(" ")} hidden across ${summary.truncatedFiles} file${summary.truncatedFiles === 1 ? "" : "s"}`);
|
|
5167
|
+
}
|
|
5168
|
+
return parts.join(" \xB7 ");
|
|
5169
|
+
}
|
|
5170
|
+
function DiffFileBlock({
|
|
5171
|
+
path: path7,
|
|
5172
|
+
preview
|
|
5173
|
+
}) {
|
|
5174
|
+
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", marginTop: 1, children: [
|
|
5175
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, italic: true, children: path7 }),
|
|
5176
|
+
/* @__PURE__ */ jsx(
|
|
5177
|
+
DiffBlock,
|
|
5178
|
+
{
|
|
5179
|
+
rows: preview.rows,
|
|
5180
|
+
hidden: preview.hidden,
|
|
5181
|
+
hiddenAdded: preview.hiddenAdded,
|
|
5182
|
+
hiddenRemoved: preview.hiddenRemoved
|
|
5183
|
+
}
|
|
5184
|
+
)
|
|
5185
|
+
] });
|
|
5186
|
+
}
|
|
5020
5187
|
function DiffBlock({
|
|
5021
5188
|
rows,
|
|
5022
5189
|
hidden,
|
|
@@ -5154,20 +5321,167 @@ function extractDiffPreview(toolName, output, input) {
|
|
|
5154
5321
|
} else if (toolName === "replace") {
|
|
5155
5322
|
const parsed = tryParseJson(text);
|
|
5156
5323
|
if (parsed && typeof parsed === "object") {
|
|
5157
|
-
diff =
|
|
5324
|
+
diff = joinReplaceDiffs(parsed);
|
|
5158
5325
|
}
|
|
5159
5326
|
}
|
|
5160
5327
|
if (!diff?.trim() || diff.startsWith("(no-op")) return void 0;
|
|
5161
5328
|
const preview = parseUnifiedDiff(diff, DIFF_MAX_LINES);
|
|
5162
5329
|
return preview.rows.length > 0 ? preview : void 0;
|
|
5163
5330
|
}
|
|
5164
|
-
function
|
|
5165
|
-
const
|
|
5166
|
-
const diffs =
|
|
5167
|
-
(result) => result && typeof result === "object" ? stringOf(result["diff"]) : void 0
|
|
5168
|
-
).filter((diff) => Boolean(diff?.trim()));
|
|
5331
|
+
function joinReplaceDiffs(obj) {
|
|
5332
|
+
const items = splitReplaceDiffs(obj);
|
|
5333
|
+
const diffs = items.map((item) => item.diff);
|
|
5169
5334
|
return diffs.length > 0 ? diffs.join("\n") : void 0;
|
|
5170
5335
|
}
|
|
5336
|
+
function splitReplaceDiffs(obj) {
|
|
5337
|
+
const results = Array.isArray(obj["results"]) ? obj["results"] : [];
|
|
5338
|
+
const items = [];
|
|
5339
|
+
for (const result of results) {
|
|
5340
|
+
if (!result || typeof result !== "object") continue;
|
|
5341
|
+
const record = result;
|
|
5342
|
+
const diff = stringOf(record["diff"]);
|
|
5343
|
+
if (!diff?.trim()) continue;
|
|
5344
|
+
const path7 = stringOf(record["path"]);
|
|
5345
|
+
items.push(path7 ? { path: path7, diff } : { diff });
|
|
5346
|
+
}
|
|
5347
|
+
return items;
|
|
5348
|
+
}
|
|
5349
|
+
function extractMultiFileDiffs(toolName, output, input) {
|
|
5350
|
+
if (!output) return void 0;
|
|
5351
|
+
const items = collectMultiFileDiffItems(toolName, output, input);
|
|
5352
|
+
if (items === void 0) return void 0;
|
|
5353
|
+
if (items.length === 0) return void 0;
|
|
5354
|
+
const previews = [];
|
|
5355
|
+
for (const item of items) {
|
|
5356
|
+
const preview = parseUnifiedDiff(item.diff, DIFF_MAX_LINES);
|
|
5357
|
+
if (preview.rows.length === 0) continue;
|
|
5358
|
+
previews.push({ path: item.path ?? "unknown file", preview });
|
|
5359
|
+
}
|
|
5360
|
+
return previews.length > 0 ? previews : void 0;
|
|
5361
|
+
}
|
|
5362
|
+
function collectMultiFileDiffItems(toolName, output, _input) {
|
|
5363
|
+
const trimmed = output.trim();
|
|
5364
|
+
if (!trimmed) return void 0;
|
|
5365
|
+
if (toolName === "replace") {
|
|
5366
|
+
const parsed = tryParseJson(trimmed);
|
|
5367
|
+
if (!parsed || typeof parsed !== "object") return void 0;
|
|
5368
|
+
const items = splitReplaceDiffs(parsed);
|
|
5369
|
+
if (items.length === 0) return items;
|
|
5370
|
+
const allMissing = items.every((item) => !item.path);
|
|
5371
|
+
const fallback = allMissing && _input && typeof _input === "object" && typeof _input["path"] === "string" ? stringOf(_input["path"]) : void 0;
|
|
5372
|
+
if (fallback) {
|
|
5373
|
+
return items.map((item) => ({ path: item.path ?? fallback, diff: item.diff }));
|
|
5374
|
+
}
|
|
5375
|
+
return items;
|
|
5376
|
+
}
|
|
5377
|
+
if (toolName === "diff") {
|
|
5378
|
+
const parsed = tryParseJson(trimmed);
|
|
5379
|
+
if (parsed && typeof parsed === "object") {
|
|
5380
|
+
const obj = parsed;
|
|
5381
|
+
const files = Array.isArray(obj["files"]) ? obj["files"].map(stringOf).filter((p) => Boolean(p)) : [];
|
|
5382
|
+
const diff = stringOf(obj["diff"]) ?? stringOf(obj["stdout"]);
|
|
5383
|
+
if (!diff?.trim()) return void 0;
|
|
5384
|
+
const blocks = splitGitStyleDiff(diff);
|
|
5385
|
+
return blocks.map((block, idx) => ({
|
|
5386
|
+
path: files[idx] ?? block.path,
|
|
5387
|
+
diff: block.diff
|
|
5388
|
+
}));
|
|
5389
|
+
}
|
|
5390
|
+
if (trimmed.includes("@@")) return [{ diff: trimmed }];
|
|
5391
|
+
return void 0;
|
|
5392
|
+
}
|
|
5393
|
+
if (toolName === "patch") {
|
|
5394
|
+
const parsed = tryParseJson(trimmed);
|
|
5395
|
+
let diffText;
|
|
5396
|
+
let explicitFiles = [];
|
|
5397
|
+
if (parsed && typeof parsed === "object") {
|
|
5398
|
+
const obj = parsed;
|
|
5399
|
+
diffText = stringOf(obj["diff"]) ?? stringOf(obj["stdout"]);
|
|
5400
|
+
if (Array.isArray(obj["files"])) {
|
|
5401
|
+
explicitFiles = obj["files"].map(stringOf).filter((p) => Boolean(p));
|
|
5402
|
+
}
|
|
5403
|
+
} else if (trimmed.includes("@@") || trimmed.startsWith("---")) {
|
|
5404
|
+
diffText = trimmed;
|
|
5405
|
+
}
|
|
5406
|
+
if (!diffText?.trim()) return void 0;
|
|
5407
|
+
const blocks = splitGitStyleDiff(diffText);
|
|
5408
|
+
if (blocks.length === 0) {
|
|
5409
|
+
const path7 = explicitFiles[0] ?? extractPatchHeaderPath(diffText);
|
|
5410
|
+
return [{ path: path7, diff: diffText }];
|
|
5411
|
+
}
|
|
5412
|
+
return blocks.map((block, idx) => ({
|
|
5413
|
+
path: explicitFiles[idx] ?? block.path,
|
|
5414
|
+
diff: block.diff
|
|
5415
|
+
}));
|
|
5416
|
+
}
|
|
5417
|
+
return void 0;
|
|
5418
|
+
}
|
|
5419
|
+
function splitGitStyleDiff(diff) {
|
|
5420
|
+
const lines = diff.split("\n");
|
|
5421
|
+
const blocks = [];
|
|
5422
|
+
let current = null;
|
|
5423
|
+
const flush = () => {
|
|
5424
|
+
if (!current) return;
|
|
5425
|
+
const text = current.body.join("\n").trim();
|
|
5426
|
+
if (text) blocks.push({ path: current.path, diff: text });
|
|
5427
|
+
current = null;
|
|
5428
|
+
};
|
|
5429
|
+
for (const line of lines) {
|
|
5430
|
+
if (line.startsWith("diff --git ")) {
|
|
5431
|
+
flush();
|
|
5432
|
+
current = { path: parseDiffGitPath(line), body: [line], hasGitHeader: true };
|
|
5433
|
+
continue;
|
|
5434
|
+
}
|
|
5435
|
+
if (current) {
|
|
5436
|
+
current.body.push(line);
|
|
5437
|
+
if (!current.hasGitHeader && line.startsWith("--- a/") && current.body.length > 2) {
|
|
5438
|
+
const carriedBody = current.body.slice(0, -1);
|
|
5439
|
+
const carriedPath = current.path;
|
|
5440
|
+
const text = carriedBody.join("\n").trim();
|
|
5441
|
+
if (text) blocks.push({ path: carriedPath, diff: text });
|
|
5442
|
+
current = {
|
|
5443
|
+
path: line.slice("--- a/".length).trim(),
|
|
5444
|
+
body: [line],
|
|
5445
|
+
hasGitHeader: false
|
|
5446
|
+
};
|
|
5447
|
+
}
|
|
5448
|
+
} else if (line.startsWith("--- a/")) {
|
|
5449
|
+
current = { path: line.slice("--- a/".length).trim(), body: [line], hasGitHeader: false };
|
|
5450
|
+
} else if (line.startsWith("+++ b/")) {
|
|
5451
|
+
current = { body: [line], hasGitHeader: false };
|
|
5452
|
+
}
|
|
5453
|
+
}
|
|
5454
|
+
flush();
|
|
5455
|
+
if (blocks.length === 1 && !blocks[0].path) {
|
|
5456
|
+
const path7 = extractPatchHeaderPath(blocks[0].diff);
|
|
5457
|
+
if (path7) blocks[0] = { path: path7, diff: blocks[0].diff };
|
|
5458
|
+
}
|
|
5459
|
+
return blocks;
|
|
5460
|
+
}
|
|
5461
|
+
function parseDiffGitPath(line) {
|
|
5462
|
+
const rest = line.slice("diff --git ".length).trim();
|
|
5463
|
+
if (!rest) return void 0;
|
|
5464
|
+
const sep2 = rest.lastIndexOf(" b/");
|
|
5465
|
+
if (sep2 > 0 && sep2 > rest.length - sep2 - 3) {
|
|
5466
|
+
return rest.slice(sep2 + 3);
|
|
5467
|
+
}
|
|
5468
|
+
const spaceIdx = rest.lastIndexOf(" ");
|
|
5469
|
+
if (spaceIdx > 0) {
|
|
5470
|
+
const rhs = rest.slice(spaceIdx + 1);
|
|
5471
|
+
return rhs.startsWith("b/") ? rhs.slice(2) : rhs;
|
|
5472
|
+
}
|
|
5473
|
+
return void 0;
|
|
5474
|
+
}
|
|
5475
|
+
function extractPatchHeaderPath(diffText) {
|
|
5476
|
+
for (const line of diffText.split("\n")) {
|
|
5477
|
+
if (line.startsWith("+++ ")) {
|
|
5478
|
+
const path7 = line.slice(4).trim();
|
|
5479
|
+
const cleaned = path7.replace(/^b\//, "").split(" ")[0].trim();
|
|
5480
|
+
return cleaned || void 0;
|
|
5481
|
+
}
|
|
5482
|
+
}
|
|
5483
|
+
return void 0;
|
|
5484
|
+
}
|
|
5171
5485
|
function newFileDiffFromWriteInput(output, input) {
|
|
5172
5486
|
if (!input || typeof input !== "object") return void 0;
|
|
5173
5487
|
const obj = input;
|
|
@@ -5466,7 +5780,7 @@ var Entry = React5.memo(function Entry2({
|
|
|
5466
5780
|
termWidth,
|
|
5467
5781
|
setSuggestions,
|
|
5468
5782
|
autonomyMode,
|
|
5469
|
-
|
|
5783
|
+
multiDiffSummaryThreshold
|
|
5470
5784
|
}) {
|
|
5471
5785
|
const nextSteps = useMemo(() => {
|
|
5472
5786
|
if (entry.kind !== "assistant") return { steps: [], stripped: "" };
|
|
@@ -5549,7 +5863,7 @@ var Entry = React5.memo(function Entry2({
|
|
|
5549
5863
|
/* @__PURE__ */ jsx(Text, { bold: true, color: theme.accent, children: ` ${s2.index}. ` }),
|
|
5550
5864
|
/* @__PURE__ */ jsx(Text, { children: s2.text }),
|
|
5551
5865
|
s2.auto ? /* @__PURE__ */ jsx(Text, { color: "cyan", dimColor: true, children: " auto" }) : null,
|
|
5552
|
-
autonomyMode === "auto" && i === 0 ?
|
|
5866
|
+
autonomyMode === "auto" && i === 0 ? /* @__PURE__ */ jsx(Text, { color: "cyan", children: " \u23E9" }) : null
|
|
5553
5867
|
] }) }, s2.index))
|
|
5554
5868
|
]
|
|
5555
5869
|
}
|
|
@@ -5558,30 +5872,49 @@ var Entry = React5.memo(function Entry2({
|
|
|
5558
5872
|
}
|
|
5559
5873
|
case "tool": {
|
|
5560
5874
|
const { glyph, color } = getToolVisual(entry.name);
|
|
5561
|
-
const
|
|
5562
|
-
|
|
5875
|
+
const {
|
|
5876
|
+
argSummary,
|
|
5877
|
+
outLines,
|
|
5878
|
+
visualLines,
|
|
5879
|
+
diff,
|
|
5880
|
+
multiDiffs,
|
|
5881
|
+
sizeChip
|
|
5882
|
+
} = useMemo(() => {
|
|
5883
|
+
const argSummary2 = formatToolArgs(entry.name, entry.input);
|
|
5884
|
+
const outLines2 = formatToolOutput(
|
|
5885
|
+
entry.name,
|
|
5886
|
+
entry.output,
|
|
5887
|
+
entry.ok,
|
|
5888
|
+
entry.outputBytes,
|
|
5889
|
+
entry.outputLines
|
|
5890
|
+
);
|
|
5891
|
+
const visualLines2 = formatToolVisualOutput(entry.name, entry.output, entry.ok, entry.input);
|
|
5892
|
+
const diff2 = entry.ok ? extractDiffPreview(entry.name, entry.output, entry.input) : void 0;
|
|
5893
|
+
const multiDiffs2 = entry.ok && !diff2 && (entry.name === "replace" || entry.name === "diff" || entry.name === "patch") ? extractMultiFileDiffs(entry.name, entry.output, entry.input) : void 0;
|
|
5894
|
+
const sizeChip2 = (() => {
|
|
5895
|
+
if (!entry.ok) return "";
|
|
5896
|
+
const parts = [];
|
|
5897
|
+
if (entry.outputLines !== void 0 && entry.outputLines > 0) {
|
|
5898
|
+
parts.push(`${entry.outputLines} L`);
|
|
5899
|
+
}
|
|
5900
|
+
if (entry.outputBytes && entry.outputBytes > 0) {
|
|
5901
|
+
parts.push(fmtBytes(entry.outputBytes));
|
|
5902
|
+
}
|
|
5903
|
+
if (entry.outputTokens && entry.outputTokens > 0) {
|
|
5904
|
+
parts.push(`\u2248${fmtTok2(entry.outputTokens)} tok`);
|
|
5905
|
+
}
|
|
5906
|
+
return parts.join(" \xB7 ");
|
|
5907
|
+
})();
|
|
5908
|
+
return { argSummary: argSummary2, outLines: outLines2, visualLines: visualLines2, diff: diff2, multiDiffs: multiDiffs2, sizeChip: sizeChip2 };
|
|
5909
|
+
}, [
|
|
5563
5910
|
entry.name,
|
|
5564
5911
|
entry.output,
|
|
5912
|
+
entry.input,
|
|
5565
5913
|
entry.ok,
|
|
5566
5914
|
entry.outputBytes,
|
|
5567
|
-
entry.outputLines
|
|
5568
|
-
|
|
5569
|
-
|
|
5570
|
-
const diff = entry.ok ? extractDiffPreview(entry.name, entry.output, entry.input) : void 0;
|
|
5571
|
-
const sizeChip = (() => {
|
|
5572
|
-
if (!entry.ok) return "";
|
|
5573
|
-
const parts = [];
|
|
5574
|
-
if (entry.outputLines !== void 0 && entry.outputLines > 0) {
|
|
5575
|
-
parts.push(`${entry.outputLines} L`);
|
|
5576
|
-
}
|
|
5577
|
-
if (entry.outputBytes && entry.outputBytes > 0) {
|
|
5578
|
-
parts.push(fmtBytes(entry.outputBytes));
|
|
5579
|
-
}
|
|
5580
|
-
if (entry.outputTokens && entry.outputTokens > 0) {
|
|
5581
|
-
parts.push(`\u2248${fmtTok2(entry.outputTokens)} tok`);
|
|
5582
|
-
}
|
|
5583
|
-
return parts.join(" \xB7 ");
|
|
5584
|
-
})();
|
|
5915
|
+
entry.outputLines,
|
|
5916
|
+
entry.outputTokens
|
|
5917
|
+
]);
|
|
5585
5918
|
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", children: [
|
|
5586
5919
|
/* @__PURE__ */ jsxs(Text, { children: [
|
|
5587
5920
|
/* @__PURE__ */ jsx(Text, { color, children: glyph }),
|
|
@@ -5594,8 +5927,8 @@ var Entry = React5.memo(function Entry2({
|
|
|
5594
5927
|
/* @__PURE__ */ jsx(Text, { dimColor: true, children: ` \xB7 ${fmtDuration(entry.durationMs)}` }),
|
|
5595
5928
|
sizeChip ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: ` \xB7 ${sizeChip}` }) : null
|
|
5596
5929
|
] }),
|
|
5597
|
-
visualLines ? /* @__PURE__ */ jsx(ToolOutputLines, { lines: visualLines, hasFollowingBlock: Boolean(diff) }) : outLines.map((line, i) => /* @__PURE__ */ jsxs(Text, { children: [
|
|
5598
|
-
/* @__PURE__ */ jsx(Text, { dimColor: true, children: i === outLines.length - 1 && !diff ? " \u2514\u2500 " : " \u251C\u2500 " }),
|
|
5930
|
+
visualLines ? /* @__PURE__ */ jsx(ToolOutputLines, { lines: visualLines, hasFollowingBlock: Boolean(diff || multiDiffs) }) : outLines.map((line, i) => /* @__PURE__ */ jsxs(Text, { children: [
|
|
5931
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: i === outLines.length - 1 && !diff && !multiDiffs ? " \u2514\u2500 " : " \u251C\u2500 " }),
|
|
5599
5932
|
/* @__PURE__ */ jsx(
|
|
5600
5933
|
Text,
|
|
5601
5934
|
{
|
|
@@ -5605,7 +5938,16 @@ var Entry = React5.memo(function Entry2({
|
|
|
5605
5938
|
}
|
|
5606
5939
|
)
|
|
5607
5940
|
] }, i)),
|
|
5608
|
-
|
|
5941
|
+
multiDiffs ? /* @__PURE__ */ jsxs(Box, { flexDirection: "column", children: [
|
|
5942
|
+
(() => {
|
|
5943
|
+
const summaryLine = formatMultiDiffSummary(
|
|
5944
|
+
summarizeMultiFileDiffs(multiDiffs),
|
|
5945
|
+
multiDiffSummaryThreshold ?? -1
|
|
5946
|
+
);
|
|
5947
|
+
return summaryLine ? /* @__PURE__ */ jsx(Text, { dimColor: true, italic: true, children: summaryLine }) : null;
|
|
5948
|
+
})(),
|
|
5949
|
+
multiDiffs.map((item) => /* @__PURE__ */ jsx(DiffFileBlock, { path: item.path, preview: item.preview }, item.path))
|
|
5950
|
+
] }) : diff ? /* @__PURE__ */ jsx(
|
|
5609
5951
|
DiffBlock,
|
|
5610
5952
|
{
|
|
5611
5953
|
rows: diff.rows,
|
|
@@ -5725,7 +6067,7 @@ var Entry = React5.memo(function Entry2({
|
|
|
5725
6067
|
}
|
|
5726
6068
|
}
|
|
5727
6069
|
});
|
|
5728
|
-
|
|
6070
|
+
var History = memo(function History2({ entries, generation, streamingText, toolStream, setSuggestions, autonomyMode, multiDiffSummaryThreshold }) {
|
|
5729
6071
|
const { stdout } = useStdout();
|
|
5730
6072
|
const [termSize, setTermSize] = useState({
|
|
5731
6073
|
columns: stdout?.columns ?? 80,
|
|
@@ -5743,10 +6085,10 @@ function History({ entries, generation, streamingText, toolStream, setSuggestion
|
|
|
5743
6085
|
const termWidth = termSize.columns;
|
|
5744
6086
|
const tail = streamingText ? tailForDisplay(streamingText, MAX_STREAM_DISPLAY_CHARS) : "";
|
|
5745
6087
|
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
5746
|
-
/* @__PURE__ */ jsx(Static, { items: entries, children: (entry) => /* @__PURE__ */ jsx(Box, { marginBottom: entry.kind === "turn-summary" ? 1 : 0, children: /* @__PURE__ */ jsx(Entry, { entry, termWidth, setSuggestions, autonomyMode,
|
|
6088
|
+
/* @__PURE__ */ jsx(Static, { items: entries, children: (entry) => /* @__PURE__ */ jsx(Box, { marginBottom: entry.kind === "turn-summary" ? 1 : 0, children: /* @__PURE__ */ jsx(Entry, { entry, termWidth, setSuggestions, autonomyMode, multiDiffSummaryThreshold }) }, entry.id) }, generation ?? 0),
|
|
5747
6089
|
/* @__PURE__ */ jsx(Box, { flexGrow: 1, children: tail ? /* @__PURE__ */ jsx(AssistantTail, { text: tail, termWidth }) : null })
|
|
5748
6090
|
] });
|
|
5749
|
-
}
|
|
6091
|
+
});
|
|
5750
6092
|
var MAX_MOUNTED = 500;
|
|
5751
6093
|
function scrollbarThumb(rows, offset, total) {
|
|
5752
6094
|
const scrollable = total > rows;
|
|
@@ -5784,7 +6126,7 @@ function Scrollbar({
|
|
|
5784
6126
|
i
|
|
5785
6127
|
)) });
|
|
5786
6128
|
}
|
|
5787
|
-
|
|
6129
|
+
var ScrollableHistory = memo(function ScrollableHistory2({
|
|
5788
6130
|
entries,
|
|
5789
6131
|
streamingText,
|
|
5790
6132
|
toolStream,
|
|
@@ -5794,8 +6136,7 @@ function ScrollableHistory({
|
|
|
5794
6136
|
onMeasure,
|
|
5795
6137
|
maxWidth,
|
|
5796
6138
|
setSuggestions,
|
|
5797
|
-
autonomyMode
|
|
5798
|
-
autoSubmitCountdown
|
|
6139
|
+
autonomyMode
|
|
5799
6140
|
}) {
|
|
5800
6141
|
const { stdout } = useStdout();
|
|
5801
6142
|
const rawWidth = stdout?.columns ?? 80;
|
|
@@ -5834,7 +6175,7 @@ function ScrollableHistory({
|
|
|
5834
6175
|
flexShrink: 0,
|
|
5835
6176
|
children: [
|
|
5836
6177
|
hiddenCount > 0 ? /* @__PURE__ */ jsx(Box, { flexShrink: 0, children: /* @__PURE__ */ jsx(Text, { dimColor: true, italic: true, children: ` \u2191 ${hiddenCount} earlier ${hiddenCount === 1 ? "entry" : "entries"} (scroll lives in this session; full log on disk)` }) }) : null,
|
|
5837
|
-
shown.map((entry) => /* @__PURE__ */ jsx(Box, { marginBottom: entry.kind === "turn-summary" ? 1 : 0, flexShrink: 0, children: /* @__PURE__ */ jsx(Entry, { entry, termWidth, setSuggestions, autonomyMode
|
|
6178
|
+
shown.map((entry) => /* @__PURE__ */ jsx(Box, { marginBottom: entry.kind === "turn-summary" ? 1 : 0, flexShrink: 0, children: /* @__PURE__ */ jsx(Entry, { entry, termWidth, setSuggestions, autonomyMode }) }, entry.id)),
|
|
5838
6179
|
tail ? /* @__PURE__ */ jsx(AssistantTail, { text: tail, termWidth }) : null,
|
|
5839
6180
|
toolTail && toolStream ? /* @__PURE__ */ jsx(
|
|
5840
6181
|
ToolStreamBox,
|
|
@@ -5852,7 +6193,7 @@ function ScrollableHistory({
|
|
|
5852
6193
|
),
|
|
5853
6194
|
/* @__PURE__ */ jsx(Scrollbar, { rows: vp, offset: Math.max(0, scrollOffset), total: totalLines })
|
|
5854
6195
|
] });
|
|
5855
|
-
}
|
|
6196
|
+
});
|
|
5856
6197
|
var MB = 1024 * 1024;
|
|
5857
6198
|
function defaultHeapLogPath() {
|
|
5858
6199
|
return path5.join(wstackGlobalRoot(), "logs", "heap.jsonl");
|
|
@@ -7606,6 +7947,7 @@ var MAX_ITERATIONS_PRESETS = [100, 200, 500, 1e3, 0];
|
|
|
7606
7947
|
var MAX_CONCURRENT_PRESETS = [1, 3, 4, 5, 10, 25, 50, 0];
|
|
7607
7948
|
var AUTO_PROCEED_MAX_PRESETS = [10, 25, 50, 100, 250, 0];
|
|
7608
7949
|
var ENHANCE_DELAY_PRESETS = [15e3, 3e4, 45e3, 6e4, 9e4, 12e4];
|
|
7950
|
+
var MULTI_DIFF_SUMMARY_THRESHOLD_PRESETS = [3, 5, 8, 10, 15, 0];
|
|
7609
7951
|
var ENHANCE_LANGUAGES = ["original", "english"];
|
|
7610
7952
|
var TOKEN_SAVING_TIERS = ["off", "minimal", "light", "medium", "aggressive"];
|
|
7611
7953
|
var TOKEN_SAVING_TIER_DESCS = {
|
|
@@ -7624,6 +7966,10 @@ function formatMaxIterations(n) {
|
|
|
7624
7966
|
if (n === 0) return "unlimited";
|
|
7625
7967
|
return String(n);
|
|
7626
7968
|
}
|
|
7969
|
+
function formatMultiDiffSummaryThreshold(n) {
|
|
7970
|
+
if (n === 0) return "off";
|
|
7971
|
+
return String(n);
|
|
7972
|
+
}
|
|
7627
7973
|
function formatEnhanceDelay(ms) {
|
|
7628
7974
|
return `${Math.round(ms / 1e3)}s`;
|
|
7629
7975
|
}
|
|
@@ -7632,10 +7978,473 @@ var MODE_DESC = {
|
|
|
7632
7978
|
suggest: "Shows next-step suggestions after each turn",
|
|
7633
7979
|
auto: "Self-driving \u2014 agent continues automatically"
|
|
7634
7980
|
};
|
|
7635
|
-
var SETTINGS_FIELD_COUNT =
|
|
7981
|
+
var SETTINGS_FIELD_COUNT = 36;
|
|
7982
|
+
var THINKING_WORD_FIELD = 22;
|
|
7983
|
+
var SETTINGS_PICKER_JUMP_CHORDS = Object.freeze([
|
|
7984
|
+
// ── Ctrl chords (Tools / Reasoning / Fleet / Debug sections) ──
|
|
7985
|
+
// Most-tweaked rows first — these are the knobs users reach for daily.
|
|
7986
|
+
{ mod: "ctrl", letter: "i", field: 20, label: "Index on session start" },
|
|
7987
|
+
{ mod: "ctrl", letter: "m", field: 21, label: "Multi-diff summary" },
|
|
7988
|
+
{ mod: "ctrl", letter: "w", field: 22, label: "Thinking word" },
|
|
7989
|
+
{ mod: "ctrl", letter: "r", field: 17, label: "Refine preview countdown" },
|
|
7990
|
+
{ mod: "ctrl", letter: "e", field: 18, label: "Refine" },
|
|
7991
|
+
{ mod: "ctrl", letter: "n", field: 23, label: "Reasoning mode" },
|
|
7992
|
+
{ mod: "ctrl", letter: "l", field: 30, label: "Max concurrent" },
|
|
7993
|
+
{ mod: "ctrl", letter: "d", field: 34, label: "Statusline" },
|
|
7994
|
+
// ── Alt chords (Autonomy / UX / Features / Context sections) ──
|
|
7995
|
+
// The Ctrl set above is dominated by Tools + Reasoning rows; Alt picks up
|
|
7996
|
+
// the spread-out sections to give every region of the picker a fast path.
|
|
7997
|
+
{ mod: "alt", letter: "a", field: 0, label: "Default autonomy mode" },
|
|
7998
|
+
{ mod: "alt", letter: "y", field: 3, label: "YOLO mode" },
|
|
7999
|
+
{ mod: "alt", letter: "c", field: 5, label: "Completion chime" },
|
|
8000
|
+
{ mod: "alt", letter: "s", field: 6, label: "Confirm before exit" },
|
|
8001
|
+
{ mod: "alt", letter: "t", field: 13, label: "Token-saving mode" },
|
|
8002
|
+
{ mod: "alt", letter: "x", field: 29, label: "Context mode" },
|
|
8003
|
+
// ── Alt+Shift chords (Logging / Debug sections) ──
|
|
8004
|
+
// 'L' is taken by Ctrl+L (Max concurrent), so the Logging rows get the
|
|
8005
|
+
// composed Alt+Shift version. A standalone Alt+L would shadow the same
|
|
8006
|
+
// letter as Max concurrent's Ctrl chord, so the composition is the
|
|
8007
|
+
// disambiguator. 'A' and 'B' are both currently free as Alt+Shift
|
|
8008
|
+
// letters (B is unmapped at any mod), so the Debug row's "Stream debug
|
|
8009
|
+
// logging" takes B (de**B**ug, raw-**B**yte stream) rather than churn
|
|
8010
|
+
// the existing Ctrl+D → Statusline binding to make room. The Config
|
|
8011
|
+
// scope row uses G (**G**lobal / project) — G is free as Alt+Shift even
|
|
8012
|
+
// though Ctrl+G is the agents-monitor chord, because the mod+letter
|
|
8013
|
+
// composition makes them distinct at the keyboard-handler level.
|
|
8014
|
+
{ mod: "alt-shift", letter: "l", field: 31, label: "Log level" },
|
|
8015
|
+
{ mod: "alt-shift", letter: "a", field: 32, label: "Audit level" },
|
|
8016
|
+
{ mod: "alt-shift", letter: "b", field: 33, label: "Stream debug logging" },
|
|
8017
|
+
{ mod: "alt-shift", letter: "g", field: 35, label: "Config scope" }
|
|
8018
|
+
]);
|
|
8019
|
+
function settingsPickerJumpField(mod, letter) {
|
|
8020
|
+
const lower = letter.toLowerCase();
|
|
8021
|
+
const chord = SETTINGS_PICKER_JUMP_CHORDS.find((c) => c.mod === mod && c.letter === lower);
|
|
8022
|
+
return chord?.field;
|
|
8023
|
+
}
|
|
8024
|
+
function settingsPickerSlug(label) {
|
|
8025
|
+
return label.toLowerCase().replace(/\s+/g, "-");
|
|
8026
|
+
}
|
|
8027
|
+
function settingsPickerJumpByName(name) {
|
|
8028
|
+
const query = settingsPickerSlug(name);
|
|
8029
|
+
if (!query) return void 0;
|
|
8030
|
+
const exact = SETTINGS_PICKER_JUMP_CHORDS.find(
|
|
8031
|
+
(c) => settingsPickerSlug(c.label) === query
|
|
8032
|
+
);
|
|
8033
|
+
if (exact) return exact.field;
|
|
8034
|
+
const queryTokens = query.split("-");
|
|
8035
|
+
for (const c of SETTINGS_PICKER_JUMP_CHORDS) {
|
|
8036
|
+
const labelTokens = settingsPickerSlug(c.label).split("-");
|
|
8037
|
+
if (queryTokens.every((t, i) => labelTokens[i] === t)) {
|
|
8038
|
+
return c.field;
|
|
8039
|
+
}
|
|
8040
|
+
}
|
|
8041
|
+
for (const c of SETTINGS_PICKER_JUMP_CHORDS) {
|
|
8042
|
+
const labelTokens = settingsPickerSlug(c.label).split("-");
|
|
8043
|
+
if (labelTokens.some((t) => t === query || t.startsWith(`${query}-`))) {
|
|
8044
|
+
return c.field;
|
|
8045
|
+
}
|
|
8046
|
+
}
|
|
8047
|
+
return void 0;
|
|
8048
|
+
}
|
|
8049
|
+
function settingsPickerJumpNames() {
|
|
8050
|
+
return SETTINGS_PICKER_JUMP_CHORDS.map((c) => settingsPickerSlug(c.label));
|
|
8051
|
+
}
|
|
8052
|
+
var THINKING_WORD_PRESETS = [
|
|
8053
|
+
"thinking",
|
|
8054
|
+
"random",
|
|
8055
|
+
"working",
|
|
8056
|
+
"cooking",
|
|
8057
|
+
"vibing",
|
|
8058
|
+
"pondering",
|
|
8059
|
+
"brewing",
|
|
8060
|
+
"crunching",
|
|
8061
|
+
"computing",
|
|
8062
|
+
"grinding",
|
|
8063
|
+
"noodling",
|
|
8064
|
+
"churning",
|
|
8065
|
+
"hacking"
|
|
8066
|
+
];
|
|
7636
8067
|
var CONFIG_SCOPES = ["global", "project"];
|
|
8068
|
+
var SETTINGS_FIELD_LABELS = [
|
|
8069
|
+
"Default autonomy mode",
|
|
8070
|
+
// 0
|
|
8071
|
+
"Auto-proceed delay",
|
|
8072
|
+
// 1
|
|
8073
|
+
"Terminal title animation",
|
|
8074
|
+
// 2
|
|
8075
|
+
"YOLO mode",
|
|
8076
|
+
// 3
|
|
8077
|
+
"Stream fleet",
|
|
8078
|
+
// 4
|
|
8079
|
+
"Completion chime",
|
|
8080
|
+
// 5
|
|
8081
|
+
"Confirm before exit",
|
|
8082
|
+
// 6
|
|
8083
|
+
"Next prediction",
|
|
8084
|
+
// 7
|
|
8085
|
+
"MCP features",
|
|
8086
|
+
// 8
|
|
8087
|
+
"Plugin features",
|
|
8088
|
+
// 9
|
|
8089
|
+
"Memory features",
|
|
8090
|
+
// 10
|
|
8091
|
+
"Skills features",
|
|
8092
|
+
// 11
|
|
8093
|
+
"Models registry",
|
|
8094
|
+
// 12
|
|
8095
|
+
"Token-saving mode",
|
|
8096
|
+
// 13
|
|
8097
|
+
"Allow outside project root",
|
|
8098
|
+
// 14
|
|
8099
|
+
"Max iterations",
|
|
8100
|
+
// 15
|
|
8101
|
+
"Auto-proceed max iterations",
|
|
8102
|
+
// 16
|
|
8103
|
+
"Refine preview countdown",
|
|
8104
|
+
// 17
|
|
8105
|
+
"Refine",
|
|
8106
|
+
// 18
|
|
8107
|
+
"Refine language",
|
|
8108
|
+
// 19
|
|
8109
|
+
"Index on session start",
|
|
8110
|
+
// 20
|
|
8111
|
+
"Multi-diff summary",
|
|
8112
|
+
// 21
|
|
8113
|
+
"Thinking word",
|
|
8114
|
+
// 22
|
|
8115
|
+
"Reasoning mode",
|
|
8116
|
+
// 23
|
|
8117
|
+
"Reasoning effort",
|
|
8118
|
+
// 24
|
|
8119
|
+
"Reasoning preserve",
|
|
8120
|
+
// 25
|
|
8121
|
+
"Cache TTL",
|
|
8122
|
+
// 26
|
|
8123
|
+
"Context auto-compact",
|
|
8124
|
+
// 27
|
|
8125
|
+
"Compactor strategy",
|
|
8126
|
+
// 28
|
|
8127
|
+
"Context mode",
|
|
8128
|
+
// 29
|
|
8129
|
+
"Max concurrent",
|
|
8130
|
+
// 30
|
|
8131
|
+
"Log level",
|
|
8132
|
+
// 31
|
|
8133
|
+
"Audit level",
|
|
8134
|
+
// 32
|
|
8135
|
+
"Stream debug logging",
|
|
8136
|
+
// 33
|
|
8137
|
+
"Statusline",
|
|
8138
|
+
// 34
|
|
8139
|
+
"Config scope"
|
|
8140
|
+
// 35
|
|
8141
|
+
];
|
|
8142
|
+
function resolveSettingsFieldValue(field, input) {
|
|
8143
|
+
const raw = input.trim().toLowerCase();
|
|
8144
|
+
const label = SETTINGS_FIELD_LABELS[field] ?? `Field ${field}`;
|
|
8145
|
+
const BOOL_FIELDS = /* @__PURE__ */ new Map([
|
|
8146
|
+
[2, "titleAnimation"],
|
|
8147
|
+
[3, "yolo"],
|
|
8148
|
+
[4, "streamFleet"],
|
|
8149
|
+
[5, "chime"],
|
|
8150
|
+
[6, "confirmExit"],
|
|
8151
|
+
[7, "nextPrediction"],
|
|
8152
|
+
[8, "featureMcp"],
|
|
8153
|
+
[9, "featurePlugins"],
|
|
8154
|
+
[10, "featureMemory"],
|
|
8155
|
+
[11, "featureSkills"],
|
|
8156
|
+
[12, "featureModelsRegistry"],
|
|
8157
|
+
[14, "allowOutsideProjectRoot"],
|
|
8158
|
+
[18, "enhanceEnabled"],
|
|
8159
|
+
[20, "indexOnStart"],
|
|
8160
|
+
[25, "reasoningPreserve"],
|
|
8161
|
+
[27, "contextAutoCompact"],
|
|
8162
|
+
[33, "debugStream"]
|
|
8163
|
+
]);
|
|
8164
|
+
const boolKey = BOOL_FIELDS.get(field);
|
|
8165
|
+
if (boolKey) {
|
|
8166
|
+
if (["on", "true", "yes", "1"].includes(raw)) {
|
|
8167
|
+
return { ok: true, patch: { [boolKey]: true }, label, displayValue: "on" };
|
|
8168
|
+
}
|
|
8169
|
+
if (["off", "false", "no", "0"].includes(raw)) {
|
|
8170
|
+
return { ok: true, patch: { [boolKey]: false }, label, displayValue: "off" };
|
|
8171
|
+
}
|
|
8172
|
+
return { ok: false, error: `Invalid value "${input}" for ${label}. Use on or off.` };
|
|
8173
|
+
}
|
|
8174
|
+
const ENUM_FIELDS = [
|
|
8175
|
+
[0, "mode", SETTINGS_MODES],
|
|
8176
|
+
[13, "tokenSavingTier", TOKEN_SAVING_TIERS],
|
|
8177
|
+
[19, "enhanceLanguage", ENHANCE_LANGUAGES],
|
|
8178
|
+
[23, "reasoningMode", REASONING_MODES],
|
|
8179
|
+
[24, "reasoningEffort", REASONING_EFFORTS],
|
|
8180
|
+
[26, "cacheTtl", CACHE_TTLS],
|
|
8181
|
+
[28, "contextStrategy", COMPACTOR_STRATEGIES],
|
|
8182
|
+
[29, "contextMode", CONTEXT_MODES],
|
|
8183
|
+
[31, "logLevel", LOG_LEVELS],
|
|
8184
|
+
[32, "auditLevel", AUDIT_LEVELS],
|
|
8185
|
+
[34, "statuslineMode", STATUSLINE_MODES],
|
|
8186
|
+
[35, "configScope", CONFIG_SCOPES]
|
|
8187
|
+
];
|
|
8188
|
+
for (const [f, key, values] of ENUM_FIELDS) {
|
|
8189
|
+
if (field !== f) continue;
|
|
8190
|
+
const match = values.find((v) => v.toLowerCase() === raw);
|
|
8191
|
+
if (match) {
|
|
8192
|
+
return { ok: true, patch: { [key]: match }, label, displayValue: match };
|
|
8193
|
+
}
|
|
8194
|
+
return {
|
|
8195
|
+
ok: false,
|
|
8196
|
+
error: `Invalid value "${input}" for ${label}. Valid: ${values.join(", ")}.`
|
|
8197
|
+
};
|
|
8198
|
+
}
|
|
8199
|
+
const presetLabel = (n, zeroLabel) => n === 0 ? zeroLabel : String(n);
|
|
8200
|
+
const PRESET_FIELDS = [
|
|
8201
|
+
[1, "delayMs", DELAY_PRESETS_MS, (n) => formatSettingsDelay(n)],
|
|
8202
|
+
[15, "maxIterations", MAX_ITERATIONS_PRESETS, (n) => formatMaxIterations(n)],
|
|
8203
|
+
[16, "autoProceedMaxIterations", AUTO_PROCEED_MAX_PRESETS, (n) => formatMaxIterations(n)],
|
|
8204
|
+
[17, "enhanceDelayMs", ENHANCE_DELAY_PRESETS, (n) => formatEnhanceDelay(n)],
|
|
8205
|
+
[21, "multiDiffSummaryThreshold", MULTI_DIFF_SUMMARY_THRESHOLD_PRESETS, (n) => formatMultiDiffSummaryThreshold(n)],
|
|
8206
|
+
[30, "maxConcurrent", MAX_CONCURRENT_PRESETS, (n) => presetLabel(n, "runtime default")]
|
|
8207
|
+
];
|
|
8208
|
+
for (const [f, key, presets, fmt2] of PRESET_FIELDS) {
|
|
8209
|
+
if (field !== f) continue;
|
|
8210
|
+
const asNum = Number.parseInt(raw, 10);
|
|
8211
|
+
if (!Number.isNaN(asNum) && presets.includes(asNum)) {
|
|
8212
|
+
return { ok: true, patch: { [key]: asNum }, label, displayValue: fmt2(asNum) };
|
|
8213
|
+
}
|
|
8214
|
+
const byName = presets.find((p) => fmt2(p).toLowerCase() === raw);
|
|
8215
|
+
if (byName !== void 0) {
|
|
8216
|
+
return { ok: true, patch: { [key]: byName }, label, displayValue: fmt2(byName) };
|
|
8217
|
+
}
|
|
8218
|
+
const options = presets.map((p) => fmt2(p)).join(", ");
|
|
8219
|
+
return {
|
|
8220
|
+
ok: false,
|
|
8221
|
+
error: `Invalid value "${input}" for ${label}. Available: ${options}.`
|
|
8222
|
+
};
|
|
8223
|
+
}
|
|
8224
|
+
if (field === 22) {
|
|
8225
|
+
const word = input.trim();
|
|
8226
|
+
if (word.length === 0 || word.length > MAX_TUI_THINKING_WORD_LENGTH) {
|
|
8227
|
+
return {
|
|
8228
|
+
ok: false,
|
|
8229
|
+
error: `"${input}" is not a valid thinking word. Use a single short word (1\u2013${MAX_TUI_THINKING_WORD_LENGTH} chars, letters/numbers only).`
|
|
8230
|
+
};
|
|
8231
|
+
}
|
|
8232
|
+
if (!/^[\p{L}\p{N}_-]+$/u.test(word)) {
|
|
8233
|
+
return {
|
|
8234
|
+
ok: false,
|
|
8235
|
+
error: `"${input}" is not a valid thinking word. Use a single short word (1\u2013${MAX_TUI_THINKING_WORD_LENGTH} chars, letters/numbers only).`
|
|
8236
|
+
};
|
|
8237
|
+
}
|
|
8238
|
+
return { ok: true, patch: { thinkingWord: word }, label, displayValue: word };
|
|
8239
|
+
}
|
|
8240
|
+
return { ok: false, error: `Unknown settings field ${field}.` };
|
|
8241
|
+
}
|
|
8242
|
+
function getSettingsFieldValue(values, field) {
|
|
8243
|
+
const label = SETTINGS_FIELD_LABELS[field] ?? `Field ${field}`;
|
|
8244
|
+
const BOOL_KEYS = [
|
|
8245
|
+
[2, "titleAnimation"],
|
|
8246
|
+
[3, "yolo"],
|
|
8247
|
+
[4, "streamFleet"],
|
|
8248
|
+
[5, "chime"],
|
|
8249
|
+
[6, "confirmExit"],
|
|
8250
|
+
[7, "nextPrediction"],
|
|
8251
|
+
[8, "featureMcp"],
|
|
8252
|
+
[9, "featurePlugins"],
|
|
8253
|
+
[10, "featureMemory"],
|
|
8254
|
+
[11, "featureSkills"],
|
|
8255
|
+
[12, "featureModelsRegistry"],
|
|
8256
|
+
[14, "allowOutsideProjectRoot"],
|
|
8257
|
+
[18, "enhanceEnabled"],
|
|
8258
|
+
[20, "indexOnStart"],
|
|
8259
|
+
[25, "reasoningPreserve"],
|
|
8260
|
+
[27, "contextAutoCompact"],
|
|
8261
|
+
[33, "debugStream"]
|
|
8262
|
+
];
|
|
8263
|
+
for (const [f, key] of BOOL_KEYS) {
|
|
8264
|
+
if (field !== f) continue;
|
|
8265
|
+
return { ok: true, label, displayValue: values[key] ? "on" : "off" };
|
|
8266
|
+
}
|
|
8267
|
+
const ENUM_KEYS = [
|
|
8268
|
+
[0, "mode"],
|
|
8269
|
+
[13, "tokenSavingTier"],
|
|
8270
|
+
[19, "enhanceLanguage"],
|
|
8271
|
+
[23, "reasoningMode"],
|
|
8272
|
+
[24, "reasoningEffort"],
|
|
8273
|
+
[26, "cacheTtl"],
|
|
8274
|
+
[28, "contextStrategy"],
|
|
8275
|
+
[29, "contextMode"],
|
|
8276
|
+
[31, "logLevel"],
|
|
8277
|
+
[32, "auditLevel"],
|
|
8278
|
+
[34, "statuslineMode"],
|
|
8279
|
+
[35, "configScope"]
|
|
8280
|
+
];
|
|
8281
|
+
for (const [f, key] of ENUM_KEYS) {
|
|
8282
|
+
if (field !== f) continue;
|
|
8283
|
+
return { ok: true, label, displayValue: String(values[key]) };
|
|
8284
|
+
}
|
|
8285
|
+
const presetLabel = (n, zeroLabel) => n === 0 ? zeroLabel : String(n);
|
|
8286
|
+
const PRESET_KEYS = [
|
|
8287
|
+
[1, "delayMs", formatSettingsDelay],
|
|
8288
|
+
[15, "maxIterations", formatMaxIterations],
|
|
8289
|
+
[16, "autoProceedMaxIterations", formatMaxIterations],
|
|
8290
|
+
[17, "enhanceDelayMs", formatEnhanceDelay],
|
|
8291
|
+
[21, "multiDiffSummaryThreshold", formatMultiDiffSummaryThreshold],
|
|
8292
|
+
[30, "maxConcurrent", (n) => presetLabel(n, "runtime default")]
|
|
8293
|
+
];
|
|
8294
|
+
for (const [f, key, fmt2] of PRESET_KEYS) {
|
|
8295
|
+
if (field !== f) continue;
|
|
8296
|
+
return { ok: true, label, displayValue: fmt2(values[key]) };
|
|
8297
|
+
}
|
|
8298
|
+
if (field === 22) {
|
|
8299
|
+
return { ok: true, label, displayValue: values.thinkingWord };
|
|
8300
|
+
}
|
|
8301
|
+
return { ok: false, error: `Unknown settings field ${field}.` };
|
|
8302
|
+
}
|
|
8303
|
+
var SETTINGS_SECTIONS = [
|
|
8304
|
+
{
|
|
8305
|
+
name: "Autonomy",
|
|
8306
|
+
fields: [0, 1]
|
|
8307
|
+
},
|
|
8308
|
+
{
|
|
8309
|
+
name: "UX",
|
|
8310
|
+
fields: [2, 3, 4, 5, 6, 7]
|
|
8311
|
+
},
|
|
8312
|
+
{
|
|
8313
|
+
name: "Features",
|
|
8314
|
+
fields: [8, 9, 10, 11, 12, 13, 14]
|
|
8315
|
+
},
|
|
8316
|
+
{
|
|
8317
|
+
name: "Tools",
|
|
8318
|
+
fields: [15, 16, 17, 18, 19, 20, 21, 22]
|
|
8319
|
+
},
|
|
8320
|
+
{
|
|
8321
|
+
name: "Reasoning",
|
|
8322
|
+
fields: [23, 24, 25, 26]
|
|
8323
|
+
},
|
|
8324
|
+
{
|
|
8325
|
+
name: "Context",
|
|
8326
|
+
fields: [27, 28, 29]
|
|
8327
|
+
},
|
|
8328
|
+
{
|
|
8329
|
+
name: "Fleet",
|
|
8330
|
+
fields: [30]
|
|
8331
|
+
},
|
|
8332
|
+
{
|
|
8333
|
+
name: "Logging",
|
|
8334
|
+
fields: [31, 32]
|
|
8335
|
+
},
|
|
8336
|
+
{
|
|
8337
|
+
name: "Debug",
|
|
8338
|
+
fields: [33, 34, 35]
|
|
8339
|
+
}
|
|
8340
|
+
];
|
|
8341
|
+
function formatAllSettingsSummary(values) {
|
|
8342
|
+
const lines = [];
|
|
8343
|
+
for (const section of SETTINGS_SECTIONS) {
|
|
8344
|
+
lines.push(`\u2500\u2500 ${section.name} \u2500\u2500`);
|
|
8345
|
+
for (const field of section.fields) {
|
|
8346
|
+
const result = getSettingsFieldValue(values, field);
|
|
8347
|
+
if (result.ok) {
|
|
8348
|
+
lines.push(` ${result.label.padEnd(28)} ${result.displayValue}`);
|
|
8349
|
+
}
|
|
8350
|
+
}
|
|
8351
|
+
}
|
|
8352
|
+
return lines.join("\n");
|
|
8353
|
+
}
|
|
8354
|
+
var SETTINGS_DEFAULTS = Object.freeze({
|
|
8355
|
+
mode: "off",
|
|
8356
|
+
delayMs: 0,
|
|
8357
|
+
titleAnimation: true,
|
|
8358
|
+
yolo: false,
|
|
8359
|
+
streamFleet: true,
|
|
8360
|
+
chime: false,
|
|
8361
|
+
confirmExit: true,
|
|
8362
|
+
nextPrediction: false,
|
|
8363
|
+
featureMcp: true,
|
|
8364
|
+
featurePlugins: true,
|
|
8365
|
+
featureMemory: true,
|
|
8366
|
+
featureSkills: true,
|
|
8367
|
+
featureModelsRegistry: true,
|
|
8368
|
+
tokenSavingTier: "off",
|
|
8369
|
+
allowOutsideProjectRoot: true,
|
|
8370
|
+
contextAutoCompact: true,
|
|
8371
|
+
contextStrategy: "hybrid",
|
|
8372
|
+
contextMode: "balanced",
|
|
8373
|
+
maxConcurrent: 10,
|
|
8374
|
+
logLevel: "info",
|
|
8375
|
+
auditLevel: "standard",
|
|
8376
|
+
indexOnStart: true,
|
|
8377
|
+
multiDiffSummaryThreshold: 5,
|
|
8378
|
+
maxIterations: 500,
|
|
8379
|
+
autoProceedMaxIterations: 50,
|
|
8380
|
+
enhanceDelayMs: 6e4,
|
|
8381
|
+
enhanceEnabled: true,
|
|
8382
|
+
enhanceLanguage: "original",
|
|
8383
|
+
debugStream: false,
|
|
8384
|
+
statuslineMode: "detailed",
|
|
8385
|
+
reasoningMode: "auto",
|
|
8386
|
+
reasoningEffort: "high",
|
|
8387
|
+
reasoningPreserve: false,
|
|
8388
|
+
thinkingWord: "thinking",
|
|
8389
|
+
cacheTtl: "default",
|
|
8390
|
+
configScope: "global"
|
|
8391
|
+
});
|
|
8392
|
+
function resetSettingsFieldValue(field) {
|
|
8393
|
+
const result = getSettingsFieldValue(SETTINGS_DEFAULTS, field);
|
|
8394
|
+
if (!result.ok) return result;
|
|
8395
|
+
const patch = buildResetPatch(field);
|
|
8396
|
+
if (!patch) return { ok: false, error: `Unknown settings field ${field}.` };
|
|
8397
|
+
return { ok: true, patch, label: result.label, displayValue: result.displayValue };
|
|
8398
|
+
}
|
|
8399
|
+
function buildResetPatch(field) {
|
|
8400
|
+
const KEY_MAP = [
|
|
8401
|
+
[0, "mode"],
|
|
8402
|
+
[1, "delayMs"],
|
|
8403
|
+
[2, "titleAnimation"],
|
|
8404
|
+
[3, "yolo"],
|
|
8405
|
+
[4, "streamFleet"],
|
|
8406
|
+
[5, "chime"],
|
|
8407
|
+
[6, "confirmExit"],
|
|
8408
|
+
[7, "nextPrediction"],
|
|
8409
|
+
[8, "featureMcp"],
|
|
8410
|
+
[9, "featurePlugins"],
|
|
8411
|
+
[10, "featureMemory"],
|
|
8412
|
+
[11, "featureSkills"],
|
|
8413
|
+
[12, "featureModelsRegistry"],
|
|
8414
|
+
[13, "tokenSavingTier"],
|
|
8415
|
+
[14, "allowOutsideProjectRoot"],
|
|
8416
|
+
[15, "maxIterations"],
|
|
8417
|
+
[16, "autoProceedMaxIterations"],
|
|
8418
|
+
[17, "enhanceDelayMs"],
|
|
8419
|
+
[18, "enhanceEnabled"],
|
|
8420
|
+
[19, "enhanceLanguage"],
|
|
8421
|
+
[20, "indexOnStart"],
|
|
8422
|
+
[21, "multiDiffSummaryThreshold"],
|
|
8423
|
+
[22, "thinkingWord"],
|
|
8424
|
+
[23, "reasoningMode"],
|
|
8425
|
+
[24, "reasoningEffort"],
|
|
8426
|
+
[25, "reasoningPreserve"],
|
|
8427
|
+
[26, "cacheTtl"],
|
|
8428
|
+
[27, "contextAutoCompact"],
|
|
8429
|
+
[28, "contextStrategy"],
|
|
8430
|
+
[29, "contextMode"],
|
|
8431
|
+
[30, "maxConcurrent"],
|
|
8432
|
+
[31, "logLevel"],
|
|
8433
|
+
[32, "auditLevel"],
|
|
8434
|
+
[33, "debugStream"],
|
|
8435
|
+
[34, "statuslineMode"],
|
|
8436
|
+
[35, "configScope"]
|
|
8437
|
+
];
|
|
8438
|
+
for (const [f, key] of KEY_MAP) {
|
|
8439
|
+
if (f === field) {
|
|
8440
|
+
return { [key]: SETTINGS_DEFAULTS[key] };
|
|
8441
|
+
}
|
|
8442
|
+
}
|
|
8443
|
+
return null;
|
|
8444
|
+
}
|
|
7637
8445
|
function SettingsPicker({
|
|
7638
8446
|
field,
|
|
8447
|
+
filter,
|
|
7639
8448
|
mode,
|
|
7640
8449
|
delayMs,
|
|
7641
8450
|
titleAnimation,
|
|
@@ -7657,7 +8466,10 @@ function SettingsPicker({
|
|
|
7657
8466
|
enhanceEnabled,
|
|
7658
8467
|
enhanceLanguage,
|
|
7659
8468
|
indexOnStart,
|
|
8469
|
+
multiDiffSummaryThreshold,
|
|
7660
8470
|
thinkingWord,
|
|
8471
|
+
thinkingWordEditing,
|
|
8472
|
+
thinkingWordDraft,
|
|
7661
8473
|
reasoningMode,
|
|
7662
8474
|
reasoningEffort,
|
|
7663
8475
|
reasoningPreserve,
|
|
@@ -7784,12 +8596,17 @@ function SettingsPicker({
|
|
|
7784
8596
|
value: boolVal(indexOnStart),
|
|
7785
8597
|
detail: "Run incremental index at session start"
|
|
7786
8598
|
},
|
|
8599
|
+
{
|
|
8600
|
+
label: "Multi-diff summary",
|
|
8601
|
+
value: formatMultiDiffSummaryThreshold(multiDiffSummaryThreshold),
|
|
8602
|
+
detail: "Min files before aggregate header (0 = off, default 5, 10 for big diffs)"
|
|
8603
|
+
},
|
|
7787
8604
|
// ── Reasoning ──
|
|
7788
8605
|
{ section: "Reasoning" },
|
|
7789
8606
|
{
|
|
7790
8607
|
label: "Thinking word",
|
|
7791
|
-
value: thinkingWord,
|
|
7792
|
-
detail: "
|
|
8608
|
+
value: thinkingWordEditing ? `${thinkingWordDraft ?? ""}\u258F` : thinkingWord,
|
|
8609
|
+
detail: thinkingWordEditing ? "type a word \xB7 Enter \u2713 \xB7 Esc \u2717 (\u226416, letters/digits/_/-)" : "Status-bar working word \xB7 thinking/random = surprise me \xB7 \u2190/\u2192 presets \xB7 Enter to type"
|
|
7793
8610
|
},
|
|
7794
8611
|
{
|
|
7795
8612
|
label: "Reasoning mode",
|
|
@@ -7869,6 +8686,94 @@ function SettingsPicker({
|
|
|
7869
8686
|
for (let i = 0; i < rows.length; i++) {
|
|
7870
8687
|
if (!rows[i]?.section) fieldRowIndex.push(i);
|
|
7871
8688
|
}
|
|
8689
|
+
const filterActive = Boolean(filter && filter.length > 1);
|
|
8690
|
+
const filterQuery = filter && filter.length > 1 ? filter.slice(1).toLowerCase() : "";
|
|
8691
|
+
const fuzzyMatch = (haystack, needle) => {
|
|
8692
|
+
const lower = haystack.toLowerCase();
|
|
8693
|
+
const indices = [];
|
|
8694
|
+
let ni = 0;
|
|
8695
|
+
for (let hi = 0; hi < lower.length && ni < needle.length; hi++) {
|
|
8696
|
+
if (lower[hi] === needle[ni]) {
|
|
8697
|
+
indices.push(hi);
|
|
8698
|
+
ni++;
|
|
8699
|
+
}
|
|
8700
|
+
}
|
|
8701
|
+
return ni === needle.length ? indices : void 0;
|
|
8702
|
+
};
|
|
8703
|
+
const scoreMatch = (contiguous, matchIndices, labelLength) => {
|
|
8704
|
+
const tier = contiguous ? 0 : 1e3;
|
|
8705
|
+
if (!matchIndices || matchIndices.length === 0) {
|
|
8706
|
+
return tier;
|
|
8707
|
+
}
|
|
8708
|
+
const firstPos = matchIndices[0] ?? 0;
|
|
8709
|
+
const span = (matchIndices.at(-1) ?? 0) - firstPos;
|
|
8710
|
+
const gap = span - (matchIndices.length - 1);
|
|
8711
|
+
const lengthPenalty = Math.max(0, labelLength - 8);
|
|
8712
|
+
return tier + firstPos + gap * 2 + lengthPenalty;
|
|
8713
|
+
};
|
|
8714
|
+
const fuzzyResults = filterActive ? SETTINGS_PICKER_JUMP_CHORDS.map((c) => {
|
|
8715
|
+
const label = c.label;
|
|
8716
|
+
const contiguous = label.toLowerCase().includes(filterQuery);
|
|
8717
|
+
if (contiguous) {
|
|
8718
|
+
const firstIdx = label.toLowerCase().indexOf(filterQuery);
|
|
8719
|
+
const indices = Array.from({ length: filterQuery.length }, (_, i) => firstIdx + i);
|
|
8720
|
+
return { chord: c, contiguous, fuzzyIdx: void 0, score: scoreMatch(true, indices, label.length) };
|
|
8721
|
+
}
|
|
8722
|
+
const fuzzyIdx = fuzzyMatch(label, filterQuery);
|
|
8723
|
+
return {
|
|
8724
|
+
chord: c,
|
|
8725
|
+
contiguous: false,
|
|
8726
|
+
fuzzyIdx,
|
|
8727
|
+
score: fuzzyIdx !== void 0 ? scoreMatch(false, fuzzyIdx, label.length) : Infinity
|
|
8728
|
+
};
|
|
8729
|
+
}) : [];
|
|
8730
|
+
const rankedResults = fuzzyResults.filter((r) => r.contiguous || r.fuzzyIdx !== void 0).sort((a, b) => a.score - b.score);
|
|
8731
|
+
const filteredFieldIndices = rankedResults.map((r) => r.chord.field);
|
|
8732
|
+
const highlightSegments = (label) => {
|
|
8733
|
+
if (!filterActive || !filterQuery) return [{ text: label, match: false }];
|
|
8734
|
+
const result = fuzzyResults.find((r) => r.chord.label === label);
|
|
8735
|
+
if (!result) return [{ text: label, match: false }];
|
|
8736
|
+
if (result.contiguous) {
|
|
8737
|
+
const lower = label.toLowerCase();
|
|
8738
|
+
const segments = [];
|
|
8739
|
+
let cursor = 0;
|
|
8740
|
+
while (cursor < label.length) {
|
|
8741
|
+
const idx = lower.indexOf(filterQuery, cursor);
|
|
8742
|
+
if (idx === -1) {
|
|
8743
|
+
segments.push({ text: label.slice(cursor), match: false });
|
|
8744
|
+
break;
|
|
8745
|
+
}
|
|
8746
|
+
if (idx > cursor) {
|
|
8747
|
+
segments.push({ text: label.slice(cursor, idx), match: false });
|
|
8748
|
+
}
|
|
8749
|
+
segments.push({ text: label.slice(idx, idx + filterQuery.length), match: true });
|
|
8750
|
+
cursor = idx + filterQuery.length;
|
|
8751
|
+
}
|
|
8752
|
+
return segments;
|
|
8753
|
+
}
|
|
8754
|
+
if (result.fuzzyIdx) {
|
|
8755
|
+
const matchSet = new Set(result.fuzzyIdx);
|
|
8756
|
+
const segments = [];
|
|
8757
|
+
let current = "";
|
|
8758
|
+
let currentMatch = false;
|
|
8759
|
+
for (let i = 0; i < label.length; i++) {
|
|
8760
|
+
const isMatch = matchSet.has(i);
|
|
8761
|
+
if (i === 0) {
|
|
8762
|
+
current = label[i] ?? "";
|
|
8763
|
+
currentMatch = isMatch;
|
|
8764
|
+
} else if (isMatch === currentMatch) {
|
|
8765
|
+
current += label[i] ?? "";
|
|
8766
|
+
} else {
|
|
8767
|
+
segments.push({ text: current, match: currentMatch });
|
|
8768
|
+
current = label[i] ?? "";
|
|
8769
|
+
currentMatch = isMatch;
|
|
8770
|
+
}
|
|
8771
|
+
}
|
|
8772
|
+
if (current) segments.push({ text: current, match: currentMatch });
|
|
8773
|
+
return segments;
|
|
8774
|
+
}
|
|
8775
|
+
return [{ text: label, match: false }];
|
|
8776
|
+
};
|
|
7872
8777
|
const VISIBLE_FIELDS = 8;
|
|
7873
8778
|
const totalFields = fieldRowIndex.length;
|
|
7874
8779
|
const windowStart = totalFields <= VISIBLE_FIELDS ? 0 : Math.max(0, Math.min(field - Math.floor(VISIBLE_FIELDS / 2), totalFields - VISIBLE_FIELDS));
|
|
@@ -7897,30 +8802,80 @@ function SettingsPicker({
|
|
|
7897
8802
|
};
|
|
7898
8803
|
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", borderStyle: "round", borderColor: "yellow", paddingX: 1, children: [
|
|
7899
8804
|
/* @__PURE__ */ jsx(Text, { color: "cyan", bold: true, children: "\u2501\u2501 Settings \u2501\u2501" }),
|
|
7900
|
-
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2191/\u2193 field \xB7 \u2190/\u2192 change + autosave \xB7 F5 to close" }),
|
|
7901
|
-
hasAbove ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: ` \u2191 ${windowStart} field${windowStart === 1 ? "" : "s"} above` }) : null,
|
|
7902
|
-
|
|
7903
|
-
|
|
7904
|
-
|
|
7905
|
-
|
|
7906
|
-
|
|
7907
|
-
|
|
7908
|
-
|
|
7909
|
-
|
|
7910
|
-
|
|
8805
|
+
filterActive ? /* @__PURE__ */ jsx(Text, { color: "yellow", bold: true, children: `Filter: ${filter} (${filteredFieldIndices.length} match${filteredFieldIndices.length === 1 ? "" : "es"})` }) : /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2191/\u2193 field \xB7 \u2190/\u2192 change + autosave \xB7 `/` to search \xB7 F5 to close" }),
|
|
8806
|
+
hasAbove && !filterActive ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: ` \u2191 ${windowStart} field${windowStart === 1 ? "" : "s"} above` }) : null,
|
|
8807
|
+
filterActive && filteredFieldIndices.length === 0 ? /* @__PURE__ */ jsx(Text, { dimColor: true, italic: true, children: "No matching settings rows." }) : null,
|
|
8808
|
+
filterActive ? (
|
|
8809
|
+
// Filter mode: render ranked rows in score order (not picker
|
|
8810
|
+
// order). Each row is looked up by its field index from the
|
|
8811
|
+
// `rows` array via `fieldRowIndex`.
|
|
8812
|
+
rankedResults.map((result) => {
|
|
8813
|
+
const fieldIdx = result.chord.field;
|
|
8814
|
+
const rowIdx = fieldRowIndex[fieldIdx] ?? -1;
|
|
8815
|
+
const row = rows[rowIdx];
|
|
8816
|
+
if (!row || !row.label) return null;
|
|
8817
|
+
const selected = fieldIdx === field;
|
|
8818
|
+
const labelStr = row.label;
|
|
8819
|
+
const segments = highlightSegments(labelStr);
|
|
8820
|
+
const padNeeded = Math.max(0, 26 - labelStr.length);
|
|
8821
|
+
return /* @__PURE__ */ jsxs(Text, { inverse: selected, ...selected ? { color: "yellow" } : {}, children: [
|
|
8822
|
+
selected ? "\u203A " : " ",
|
|
8823
|
+
segments.map((seg, j) => /* @__PURE__ */ jsx(
|
|
8824
|
+
Text,
|
|
8825
|
+
{
|
|
8826
|
+
bold: true,
|
|
8827
|
+
...seg.match ? { color: "yellow" } : { dimColor: true },
|
|
8828
|
+
children: seg.text
|
|
8829
|
+
},
|
|
8830
|
+
j
|
|
8831
|
+
)),
|
|
8832
|
+
/* @__PURE__ */ jsx(Text, { bold: true, dimColor: true, children: " ".repeat(padNeeded) }),
|
|
8833
|
+
/* @__PURE__ */ jsx(Text, { color: "cyan", children: String(row.value ?? "").padEnd(12) }),
|
|
8834
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: row.detail ?? "" })
|
|
8835
|
+
] }, `frow-${labelStr}`);
|
|
8836
|
+
})
|
|
8837
|
+
) : (
|
|
8838
|
+
// Normal mode: render rows in picker order with windowing.
|
|
8839
|
+
rows.map((row, i) => {
|
|
8840
|
+
const fieldAtRow = fieldRowIndex.indexOf(i);
|
|
8841
|
+
if (fieldAtRow === -1) {
|
|
8842
|
+
if (filterActive) return null;
|
|
8843
|
+
if (shouldShowSection(i)) {
|
|
8844
|
+
return /* @__PURE__ */ jsxs(Text, { bold: true, color: "green", children: [
|
|
8845
|
+
"\u2500\u2500 ",
|
|
8846
|
+
row.section,
|
|
8847
|
+
" \u2500\u2500"
|
|
8848
|
+
] }, `section-${row.section ?? i}`);
|
|
8849
|
+
}
|
|
8850
|
+
return null;
|
|
7911
8851
|
}
|
|
7912
|
-
|
|
7913
|
-
|
|
7914
|
-
|
|
7915
|
-
|
|
7916
|
-
|
|
7917
|
-
|
|
7918
|
-
|
|
7919
|
-
/* @__PURE__ */
|
|
7920
|
-
|
|
7921
|
-
|
|
7922
|
-
|
|
7923
|
-
|
|
8852
|
+
if (filterActive) {
|
|
8853
|
+
if (!filteredFieldIndices.includes(fieldAtRow)) return null;
|
|
8854
|
+
} else if (fieldAtRow < windowStart || fieldAtRow >= windowEnd) return null;
|
|
8855
|
+
const selected = fieldAtRow === field;
|
|
8856
|
+
const labelStr = row.label ?? "";
|
|
8857
|
+
const segments = highlightSegments(labelStr);
|
|
8858
|
+
const padNeeded = Math.max(0, 26 - labelStr.length);
|
|
8859
|
+
return /* @__PURE__ */ jsxs(Text, { inverse: selected, ...selected ? { color: "yellow" } : {}, children: [
|
|
8860
|
+
selected ? "\u203A " : " ",
|
|
8861
|
+
filterActive ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
8862
|
+
segments.map((seg, j) => /* @__PURE__ */ jsx(
|
|
8863
|
+
Text,
|
|
8864
|
+
{
|
|
8865
|
+
bold: true,
|
|
8866
|
+
...seg.match ? { color: "yellow" } : { dimColor: true },
|
|
8867
|
+
children: seg.text
|
|
8868
|
+
},
|
|
8869
|
+
j
|
|
8870
|
+
)),
|
|
8871
|
+
/* @__PURE__ */ jsx(Text, { bold: true, dimColor: true, children: " ".repeat(padNeeded) })
|
|
8872
|
+
] }) : /* @__PURE__ */ jsx(Text, { bold: true, children: labelStr.padEnd(26) }),
|
|
8873
|
+
/* @__PURE__ */ jsx(Text, { color: "cyan", children: String(row.value ?? "").padEnd(12) }),
|
|
8874
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: row.detail ?? "" })
|
|
8875
|
+
] }, `row-${row.label ?? fieldAtRow}`);
|
|
8876
|
+
})
|
|
8877
|
+
),
|
|
8878
|
+
hasBelow && !filterActive ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: ` \u2193 ${totalFields - windowEnd} field${totalFields - windowEnd === 1 ? "" : "s"} below` }) : null,
|
|
7924
8879
|
/* @__PURE__ */ jsx(Text, { dimColor: true, children: configScope === "project" ? "Persisted to <project>/.wrongstack/config.json" : "Persisted to ~/.wrongstack/config.json" }),
|
|
7925
8880
|
hint ? /* @__PURE__ */ jsx(Text, { color: "yellow", children: hint }) : null
|
|
7926
8881
|
] });
|
|
@@ -8066,19 +9021,23 @@ function StatuslinePicker({
|
|
|
8066
9021
|
const visibleChipsMap = new Map(visibleChips.map((c) => [c.key, c]));
|
|
8067
9022
|
const totalFields = STATUSLINE_ITEMS.length;
|
|
8068
9023
|
const byLine = groupByLine(STATUSLINE_ITEMS);
|
|
9024
|
+
const VISIBLE_FIELDS = 8;
|
|
9025
|
+
const windowStart = Math.max(0, Math.min(field - Math.floor(VISIBLE_FIELDS / 2), totalFields - VISIBLE_FIELDS));
|
|
9026
|
+
const windowEnd = Math.min(windowStart + VISIBLE_FIELDS, totalFields);
|
|
9027
|
+
const hasAbove = windowStart > 0;
|
|
9028
|
+
const hasBelow = windowEnd < totalFields;
|
|
8069
9029
|
const rows = [];
|
|
8070
9030
|
for (const [line, items] of [...byLine.entries()].sort((a, b) => a[0] - b[0])) {
|
|
9031
|
+
const windowedItems = items.filter((item) => {
|
|
9032
|
+
const idx = STATUSLINE_ITEMS.indexOf(item);
|
|
9033
|
+
return idx >= windowStart && idx < windowEnd;
|
|
9034
|
+
});
|
|
9035
|
+
if (windowedItems.length === 0) continue;
|
|
8071
9036
|
rows.push({ section: `Line ${line}` });
|
|
8072
|
-
for (const item of
|
|
8073
|
-
|
|
8074
|
-
rows.push({ item, fieldIdx });
|
|
9037
|
+
for (const item of windowedItems) {
|
|
9038
|
+
rows.push({ item, fieldIdx: STATUSLINE_ITEMS.indexOf(item) });
|
|
8075
9039
|
}
|
|
8076
9040
|
}
|
|
8077
|
-
const VISIBLE_FIELDS = 7;
|
|
8078
|
-
const windowStart = Math.max(0, Math.min(field - Math.floor(VISIBLE_FIELDS / 2), totalFields - VISIBLE_FIELDS));
|
|
8079
|
-
const windowEnd = Math.min(windowStart + VISIBLE_FIELDS, totalFields);
|
|
8080
|
-
const hasAbove = windowStart > 0;
|
|
8081
|
-
const hasBelow = windowEnd < totalFields;
|
|
8082
9041
|
const boolVal = (item) => {
|
|
8083
9042
|
if (hiddenSet.has(item)) return "off";
|
|
8084
9043
|
if (STREAM_CHIP_KEYS.includes(item)) {
|
|
@@ -10402,7 +11361,21 @@ function reducer(state, action) {
|
|
|
10402
11361
|
...closePanels(state),
|
|
10403
11362
|
settingsPicker: {
|
|
10404
11363
|
open: true,
|
|
10405
|
-
|
|
11364
|
+
// The persisted `lastSettingsField` (from the canonical Settings
|
|
11365
|
+
// shape) drives where the picker lands on open. The slice's
|
|
11366
|
+
// `field` is a working copy that mirrors it until the user
|
|
11367
|
+
// navigates again. `state.settingsPicker.lastSettingsField` is
|
|
11368
|
+
// the fallback for the (rare) case where the action omits it
|
|
11369
|
+
// — e.g., a tests/dispatch path that hasn't been updated yet.
|
|
11370
|
+
// `||` (not `??`): a payload `lastSettingsField` of 0 means
|
|
11371
|
+
// "no saved value" (the default in the canonical Settings),
|
|
11372
|
+
// so we fall through to the runtime state's tracked value.
|
|
11373
|
+
// This lets the in-session `settingsFieldSet`/`settingsFieldMove`
|
|
11374
|
+
// preserve the field across close/reopen within the same session,
|
|
11375
|
+
// while a non-zero persisted value (loaded from disk) takes
|
|
11376
|
+
// priority on a fresh open.
|
|
11377
|
+
field: action.lastSettingsField || state.settingsPicker.lastSettingsField || 0,
|
|
11378
|
+
lastSettingsField: action.lastSettingsField || state.settingsPicker.lastSettingsField || 0,
|
|
10406
11379
|
mode: action.mode,
|
|
10407
11380
|
delayMs: action.delayMs,
|
|
10408
11381
|
titleAnimation: action.titleAnimation,
|
|
@@ -10425,6 +11398,7 @@ function reducer(state, action) {
|
|
|
10425
11398
|
logLevel: action.logLevel,
|
|
10426
11399
|
auditLevel: action.auditLevel,
|
|
10427
11400
|
indexOnStart: action.indexOnStart,
|
|
11401
|
+
multiDiffSummaryThreshold: action.multiDiffSummaryThreshold,
|
|
10428
11402
|
maxIterations: action.maxIterations,
|
|
10429
11403
|
autoProceedMaxIterations: action.autoProceedMaxIterations,
|
|
10430
11404
|
enhanceDelayMs: action.enhanceDelayMs,
|
|
@@ -10436,6 +11410,11 @@ function reducer(state, action) {
|
|
|
10436
11410
|
reasoningEffort: action.reasoningEffort,
|
|
10437
11411
|
reasoningPreserve: action.reasoningPreserve,
|
|
10438
11412
|
thinkingWord: action.thinkingWord,
|
|
11413
|
+
thinkingWordEditing: false,
|
|
11414
|
+
thinkingWordDraft: "",
|
|
11415
|
+
// Filter is always cleared on open — the user starts fresh.
|
|
11416
|
+
// Persisted `lastSettingsField` is restored separately above.
|
|
11417
|
+
filter: "",
|
|
10439
11418
|
cacheTtl: action.cacheTtl,
|
|
10440
11419
|
configScope: action.configScope,
|
|
10441
11420
|
hint: void 0
|
|
@@ -10450,13 +11429,28 @@ function reducer(state, action) {
|
|
|
10450
11429
|
const next = (state.settingsPicker.field + action.delta + SETTINGS_FIELD_COUNT) % SETTINGS_FIELD_COUNT;
|
|
10451
11430
|
return {
|
|
10452
11431
|
...state,
|
|
10453
|
-
settingsPicker: {
|
|
11432
|
+
settingsPicker: {
|
|
11433
|
+
...state.settingsPicker,
|
|
11434
|
+
field: next,
|
|
11435
|
+
lastSettingsField: next,
|
|
11436
|
+
thinkingWordEditing: false,
|
|
11437
|
+
thinkingWordDraft: "",
|
|
11438
|
+
hint: void 0
|
|
11439
|
+
}
|
|
10454
11440
|
};
|
|
10455
11441
|
}
|
|
10456
11442
|
case "settingsFieldSet": {
|
|
10457
11443
|
const field = action.field >= 0 && action.field < SETTINGS_FIELD_COUNT ? action.field : 0;
|
|
10458
|
-
return {
|
|
11444
|
+
return {
|
|
11445
|
+
...state,
|
|
11446
|
+
settingsPicker: { ...state.settingsPicker, field, lastSettingsField: field, hint: void 0 }
|
|
11447
|
+
};
|
|
10459
11448
|
}
|
|
11449
|
+
case "settingsFilterSet":
|
|
11450
|
+
return {
|
|
11451
|
+
...state,
|
|
11452
|
+
settingsPicker: { ...state.settingsPicker, filter: action.filter }
|
|
11453
|
+
};
|
|
10460
11454
|
case "settingsValueChange": {
|
|
10461
11455
|
const sp = state.settingsPicker;
|
|
10462
11456
|
const f = sp.field;
|
|
@@ -10618,8 +11612,28 @@ function reducer(state, action) {
|
|
|
10618
11612
|
...state,
|
|
10619
11613
|
settingsPicker: { ...sp, indexOnStart: !sp.indexOnStart, hint: bootHint }
|
|
10620
11614
|
};
|
|
10621
|
-
if (f === 21)
|
|
10622
|
-
|
|
11615
|
+
if (f === 21) {
|
|
11616
|
+
const j = MULTI_DIFF_SUMMARY_THRESHOLD_PRESETS.indexOf(sp.multiDiffSummaryThreshold);
|
|
11617
|
+
const base = j < 0 ? 0 : j;
|
|
11618
|
+
const next = (base + action.delta + MULTI_DIFF_SUMMARY_THRESHOLD_PRESETS.length) % MULTI_DIFF_SUMMARY_THRESHOLD_PRESETS.length;
|
|
11619
|
+
const multiDiffSummaryThreshold = expectDefined$1(MULTI_DIFF_SUMMARY_THRESHOLD_PRESETS[next]);
|
|
11620
|
+
return {
|
|
11621
|
+
...state,
|
|
11622
|
+
settingsPicker: { ...sp, multiDiffSummaryThreshold, hint: void 0 }
|
|
11623
|
+
};
|
|
11624
|
+
}
|
|
11625
|
+
if (f === THINKING_WORD_FIELD) {
|
|
11626
|
+
const cur = sp.thinkingWord;
|
|
11627
|
+
const list = THINKING_WORD_PRESETS.includes(cur) ? [...THINKING_WORD_PRESETS] : [cur, ...THINKING_WORD_PRESETS];
|
|
11628
|
+
const i = list.indexOf(cur);
|
|
11629
|
+
const base = i < 0 ? 0 : i;
|
|
11630
|
+
const next = (base + action.delta + list.length) % list.length;
|
|
11631
|
+
return {
|
|
11632
|
+
...state,
|
|
11633
|
+
settingsPicker: { ...sp, thinkingWord: expectDefined$1(list[next]), hint: void 0 }
|
|
11634
|
+
};
|
|
11635
|
+
}
|
|
11636
|
+
if (f === 23) {
|
|
10623
11637
|
const i = REASONING_MODES.indexOf(sp.reasoningMode);
|
|
10624
11638
|
const base = i < 0 ? 0 : i;
|
|
10625
11639
|
const next = (base + action.delta + REASONING_MODES.length) % REASONING_MODES.length;
|
|
@@ -10632,7 +11646,7 @@ function reducer(state, action) {
|
|
|
10632
11646
|
}
|
|
10633
11647
|
};
|
|
10634
11648
|
}
|
|
10635
|
-
if (f ===
|
|
11649
|
+
if (f === 24) {
|
|
10636
11650
|
const i = REASONING_EFFORTS.indexOf(
|
|
10637
11651
|
sp.reasoningEffort
|
|
10638
11652
|
);
|
|
@@ -10647,12 +11661,12 @@ function reducer(state, action) {
|
|
|
10647
11661
|
}
|
|
10648
11662
|
};
|
|
10649
11663
|
}
|
|
10650
|
-
if (f ===
|
|
11664
|
+
if (f === 25)
|
|
10651
11665
|
return {
|
|
10652
11666
|
...state,
|
|
10653
11667
|
settingsPicker: { ...sp, reasoningPreserve: !sp.reasoningPreserve, hint: void 0 }
|
|
10654
11668
|
};
|
|
10655
|
-
if (f ===
|
|
11669
|
+
if (f === 26) {
|
|
10656
11670
|
const i = CACHE_TTLS.indexOf(sp.cacheTtl);
|
|
10657
11671
|
const base = i < 0 ? 0 : i;
|
|
10658
11672
|
const next = (base + action.delta + CACHE_TTLS.length) % CACHE_TTLS.length;
|
|
@@ -10661,12 +11675,12 @@ function reducer(state, action) {
|
|
|
10661
11675
|
settingsPicker: { ...sp, cacheTtl: expectDefined$1(CACHE_TTLS[next]), hint: void 0 }
|
|
10662
11676
|
};
|
|
10663
11677
|
}
|
|
10664
|
-
if (f ===
|
|
11678
|
+
if (f === 27)
|
|
10665
11679
|
return {
|
|
10666
11680
|
...state,
|
|
10667
11681
|
settingsPicker: { ...sp, contextAutoCompact: !sp.contextAutoCompact, hint: void 0 }
|
|
10668
11682
|
};
|
|
10669
|
-
if (f ===
|
|
11683
|
+
if (f === 28) {
|
|
10670
11684
|
const i = COMPACTOR_STRATEGIES.indexOf(sp.contextStrategy);
|
|
10671
11685
|
const base = i < 0 ? 0 : i;
|
|
10672
11686
|
const next = (base + action.delta + COMPACTOR_STRATEGIES.length) % COMPACTOR_STRATEGIES.length;
|
|
@@ -10679,7 +11693,7 @@ function reducer(state, action) {
|
|
|
10679
11693
|
}
|
|
10680
11694
|
};
|
|
10681
11695
|
}
|
|
10682
|
-
if (f ===
|
|
11696
|
+
if (f === 29) {
|
|
10683
11697
|
const i = CONTEXT_MODES.indexOf(sp.contextMode);
|
|
10684
11698
|
const base = i < 0 ? 0 : i;
|
|
10685
11699
|
const next = (base + action.delta + CONTEXT_MODES.length) % CONTEXT_MODES.length;
|
|
@@ -10692,7 +11706,7 @@ function reducer(state, action) {
|
|
|
10692
11706
|
}
|
|
10693
11707
|
};
|
|
10694
11708
|
}
|
|
10695
|
-
if (f ===
|
|
11709
|
+
if (f === 30) {
|
|
10696
11710
|
const j = MAX_CONCURRENT_PRESETS.indexOf(sp.maxConcurrent);
|
|
10697
11711
|
const base = j < 0 ? 0 : j;
|
|
10698
11712
|
const next = (base + action.delta + MAX_CONCURRENT_PRESETS.length) % MAX_CONCURRENT_PRESETS.length;
|
|
@@ -10706,7 +11720,7 @@ function reducer(state, action) {
|
|
|
10706
11720
|
}
|
|
10707
11721
|
};
|
|
10708
11722
|
}
|
|
10709
|
-
if (f ===
|
|
11723
|
+
if (f === 31) {
|
|
10710
11724
|
const i = LOG_LEVELS.indexOf(sp.logLevel);
|
|
10711
11725
|
const base = i < 0 ? 0 : i;
|
|
10712
11726
|
const next = (base + action.delta + LOG_LEVELS.length) % LOG_LEVELS.length;
|
|
@@ -10715,7 +11729,7 @@ function reducer(state, action) {
|
|
|
10715
11729
|
settingsPicker: { ...sp, logLevel: expectDefined$1(LOG_LEVELS[next]), hint: void 0 }
|
|
10716
11730
|
};
|
|
10717
11731
|
}
|
|
10718
|
-
if (f ===
|
|
11732
|
+
if (f === 32) {
|
|
10719
11733
|
const i = AUDIT_LEVELS.indexOf(sp.auditLevel);
|
|
10720
11734
|
const base = i < 0 ? 0 : i;
|
|
10721
11735
|
const next = (base + action.delta + AUDIT_LEVELS.length) % AUDIT_LEVELS.length;
|
|
@@ -10724,12 +11738,12 @@ function reducer(state, action) {
|
|
|
10724
11738
|
settingsPicker: { ...sp, auditLevel: expectDefined$1(AUDIT_LEVELS[next]), hint: void 0 }
|
|
10725
11739
|
};
|
|
10726
11740
|
}
|
|
10727
|
-
if (f ===
|
|
11741
|
+
if (f === 33)
|
|
10728
11742
|
return {
|
|
10729
11743
|
...state,
|
|
10730
11744
|
settingsPicker: { ...sp, debugStream: !sp.debugStream, hint: void 0 }
|
|
10731
11745
|
};
|
|
10732
|
-
if (f ===
|
|
11746
|
+
if (f === 34) {
|
|
10733
11747
|
const i = STATUSLINE_MODES.indexOf(sp.statuslineMode);
|
|
10734
11748
|
const base = i < 0 ? STATUSLINE_MODES.indexOf("detailed") : i;
|
|
10735
11749
|
const next = (base + action.delta + STATUSLINE_MODES.length) % STATUSLINE_MODES.length;
|
|
@@ -10742,7 +11756,7 @@ function reducer(state, action) {
|
|
|
10742
11756
|
}
|
|
10743
11757
|
};
|
|
10744
11758
|
}
|
|
10745
|
-
if (f ===
|
|
11759
|
+
if (f === 35) {
|
|
10746
11760
|
const i = CONFIG_SCOPES.indexOf(sp.configScope);
|
|
10747
11761
|
const base = i < 0 ? 0 : i;
|
|
10748
11762
|
const next = (base + action.delta + CONFIG_SCOPES.length) % CONFIG_SCOPES.length;
|
|
@@ -10757,8 +11771,67 @@ function reducer(state, action) {
|
|
|
10757
11771
|
}
|
|
10758
11772
|
return state;
|
|
10759
11773
|
}
|
|
11774
|
+
case "settingsValueSet": {
|
|
11775
|
+
return {
|
|
11776
|
+
...state,
|
|
11777
|
+
settingsPicker: { ...state.settingsPicker, ...action.patch, hint: void 0 }
|
|
11778
|
+
};
|
|
11779
|
+
}
|
|
10760
11780
|
case "settingsHint":
|
|
10761
11781
|
return { ...state, settingsPicker: { ...state.settingsPicker, hint: action.text } };
|
|
11782
|
+
case "settingsThinkingEditStart":
|
|
11783
|
+
return {
|
|
11784
|
+
...state,
|
|
11785
|
+
settingsPicker: {
|
|
11786
|
+
...state.settingsPicker,
|
|
11787
|
+
thinkingWordEditing: true,
|
|
11788
|
+
// Seed the draft with the current word so the user edits from it.
|
|
11789
|
+
thinkingWordDraft: state.settingsPicker.thinkingWord,
|
|
11790
|
+
hint: void 0
|
|
11791
|
+
}
|
|
11792
|
+
};
|
|
11793
|
+
case "settingsThinkingEditChange":
|
|
11794
|
+
return {
|
|
11795
|
+
...state,
|
|
11796
|
+
settingsPicker: {
|
|
11797
|
+
...state.settingsPicker,
|
|
11798
|
+
// Hard-cap the draft so it can't grow past the persisted limit.
|
|
11799
|
+
thinkingWordDraft: action.draft.slice(0, MAX_TUI_THINKING_WORD_LENGTH),
|
|
11800
|
+
hint: void 0
|
|
11801
|
+
}
|
|
11802
|
+
};
|
|
11803
|
+
case "settingsThinkingEditCommit": {
|
|
11804
|
+
const sp = state.settingsPicker;
|
|
11805
|
+
const raw = sp.thinkingWordDraft.trim();
|
|
11806
|
+
if (raw.length === 0) {
|
|
11807
|
+
return {
|
|
11808
|
+
...state,
|
|
11809
|
+
settingsPicker: { ...sp, thinkingWordEditing: false, thinkingWordDraft: "", hint: void 0 }
|
|
11810
|
+
};
|
|
11811
|
+
}
|
|
11812
|
+
const normalized = normalizeTuiThinkingWord(raw);
|
|
11813
|
+
const valid = normalized === raw;
|
|
11814
|
+
return {
|
|
11815
|
+
...state,
|
|
11816
|
+
settingsPicker: {
|
|
11817
|
+
...sp,
|
|
11818
|
+
thinkingWord: valid ? normalized : sp.thinkingWord,
|
|
11819
|
+
thinkingWordEditing: false,
|
|
11820
|
+
thinkingWordDraft: "",
|
|
11821
|
+
hint: valid ? void 0 : `Invalid word \u2014 keep it \u2264${MAX_TUI_THINKING_WORD_LENGTH} chars (letters/digits/_/-)`
|
|
11822
|
+
}
|
|
11823
|
+
};
|
|
11824
|
+
}
|
|
11825
|
+
case "settingsThinkingEditCancel":
|
|
11826
|
+
return {
|
|
11827
|
+
...state,
|
|
11828
|
+
settingsPicker: {
|
|
11829
|
+
...state.settingsPicker,
|
|
11830
|
+
thinkingWordEditing: false,
|
|
11831
|
+
thinkingWordDraft: "",
|
|
11832
|
+
hint: void 0
|
|
11833
|
+
}
|
|
11834
|
+
};
|
|
10762
11835
|
// ── Statusline picker ───────────────────────────────────────────────
|
|
10763
11836
|
case "statuslineOpen":
|
|
10764
11837
|
return {
|
|
@@ -12085,7 +13158,7 @@ function App({
|
|
|
12085
13158
|
},
|
|
12086
13159
|
autonomyPicker: { open: false, options: [], selected: 0 },
|
|
12087
13160
|
resumePicker: { open: false, sessions: [], selected: 0, busy: false, hint: void 0, error: void 0 },
|
|
12088
|
-
settingsPicker: { open: false, field: 0, mode: "off", delayMs: 0, titleAnimation: true, yolo: false, streamFleet: true, chime: false, confirmExit: true, nextPrediction: false, featureMcp: true, featurePlugins: true, featureMemory: true, featureSkills: true, featureModelsRegistry: true, tokenSavingTier: "off", allowOutsideProjectRoot: true, contextAutoCompact: true, contextStrategy: "hybrid", contextMode: "balanced", maxConcurrent: 10, logLevel: "info", auditLevel: "standard", indexOnStart: true, maxIterations: 500, autoProceedMaxIterations: 50, enhanceDelayMs: 6e4, enhanceEnabled: true, enhanceLanguage: "original", debugStream: false, statuslineMode: "detailed", reasoningMode: "auto", reasoningEffort: "high", reasoningPreserve: false, thinkingWord: "thinking", cacheTtl: "default", configScope: "global" },
|
|
13161
|
+
settingsPicker: { open: false, field: 0, lastSettingsField: 0, filter: "", mode: "off", delayMs: 0, titleAnimation: true, yolo: false, streamFleet: true, chime: false, confirmExit: true, nextPrediction: false, featureMcp: true, featurePlugins: true, featureMemory: true, featureSkills: true, featureModelsRegistry: true, tokenSavingTier: "off", allowOutsideProjectRoot: true, contextAutoCompact: true, contextStrategy: "hybrid", contextMode: "balanced", maxConcurrent: 10, logLevel: "info", auditLevel: "standard", indexOnStart: true, multiDiffSummaryThreshold: 5, maxIterations: 500, autoProceedMaxIterations: 50, enhanceDelayMs: 6e4, enhanceEnabled: true, enhanceLanguage: "original", debugStream: false, statuslineMode: "detailed", reasoningMode: "auto", reasoningEffort: "high", reasoningPreserve: false, thinkingWord: "thinking", thinkingWordEditing: false, thinkingWordDraft: "", cacheTtl: "default", configScope: "global" },
|
|
12089
13162
|
statuslinePicker: { open: false, field: 0, hiddenItems: [], visibleChips: [], hint: void 0 },
|
|
12090
13163
|
projectPicker: { open: false, allItems: [], items: [], selected: 0, filter: "", hint: void 0 },
|
|
12091
13164
|
fKeyPicker: { open: false, selected: 0 },
|
|
@@ -12222,6 +13295,20 @@ function App({
|
|
|
12222
13295
|
const liveSettings = getSettings?.();
|
|
12223
13296
|
const liveStatuslineMode = liveSettings?.statuslineMode ?? "detailed";
|
|
12224
13297
|
const liveThinkingWord = liveSettings?.thinkingWord ?? "thinking";
|
|
13298
|
+
const [rolledThinkingWord, setRolledThinkingWord] = useState(
|
|
13299
|
+
() => pickRandomTuiThinkingWord()
|
|
13300
|
+
);
|
|
13301
|
+
const thinkingWorking = state.status === "running" || state.status === "streaming";
|
|
13302
|
+
const prevThinkingWorkingRef = useRef(false);
|
|
13303
|
+
useEffect(() => {
|
|
13304
|
+
if (thinkingWorking && !prevThinkingWorkingRef.current) {
|
|
13305
|
+
setRolledThinkingWord((prev) => pickRandomTuiThinkingWord(prev));
|
|
13306
|
+
}
|
|
13307
|
+
prevThinkingWorkingRef.current = thinkingWorking;
|
|
13308
|
+
}, [thinkingWorking]);
|
|
13309
|
+
const displayThinkingWord = isRandomTuiThinkingWord(liveThinkingWord) ? rolledThinkingWord : liveThinkingWord;
|
|
13310
|
+
const displayThinkingWordRef = useRef(displayThinkingWord);
|
|
13311
|
+
displayThinkingWordRef.current = displayThinkingWord;
|
|
12225
13312
|
const chimeRef = useRef(chime);
|
|
12226
13313
|
chimeRef.current = liveSettings?.chime ?? chime;
|
|
12227
13314
|
const confirmExitRef = useRef(confirmExit);
|
|
@@ -12809,6 +13896,8 @@ function App({
|
|
|
12809
13896
|
logLevel: sp.logLevel,
|
|
12810
13897
|
auditLevel: sp.auditLevel,
|
|
12811
13898
|
indexOnStart: sp.indexOnStart,
|
|
13899
|
+
multiDiffSummaryThreshold: sp.multiDiffSummaryThreshold,
|
|
13900
|
+
lastSettingsField: sp.lastSettingsField,
|
|
12812
13901
|
maxIterations: sp.maxIterations,
|
|
12813
13902
|
autoProceedMaxIterations: sp.autoProceedMaxIterations,
|
|
12814
13903
|
enhanceDelayMs: sp.enhanceDelayMs,
|
|
@@ -13208,6 +14297,8 @@ function App({
|
|
|
13208
14297
|
logLevel: s2.logLevel ?? "info",
|
|
13209
14298
|
auditLevel: s2.auditLevel ?? "standard",
|
|
13210
14299
|
indexOnStart: s2.indexOnStart ?? true,
|
|
14300
|
+
multiDiffSummaryThreshold: s2.multiDiffSummaryThreshold ?? 5,
|
|
14301
|
+
lastSettingsField: s2.lastSettingsField ?? 0,
|
|
13211
14302
|
maxIterations: s2.maxIterations ?? 500,
|
|
13212
14303
|
autoProceedMaxIterations: s2.autoProceedMaxIterations ?? 50,
|
|
13213
14304
|
enhanceDelayMs: s2.enhanceDelayMs ?? 6e4,
|
|
@@ -13352,6 +14443,8 @@ function App({
|
|
|
13352
14443
|
logLevel: sp.logLevel,
|
|
13353
14444
|
auditLevel: sp.auditLevel,
|
|
13354
14445
|
indexOnStart: sp.indexOnStart,
|
|
14446
|
+
multiDiffSummaryThreshold: sp.multiDiffSummaryThreshold,
|
|
14447
|
+
lastSettingsField: sp.lastSettingsField,
|
|
13355
14448
|
maxIterations: sp.maxIterations,
|
|
13356
14449
|
autoProceedMaxIterations: sp.autoProceedMaxIterations,
|
|
13357
14450
|
enhanceDelayMs: sp.enhanceDelayMs,
|
|
@@ -13442,8 +14535,95 @@ function App({
|
|
|
13442
14535
|
const cmd = {
|
|
13443
14536
|
name: "settings",
|
|
13444
14537
|
aliases: ["config", "prefs"],
|
|
13445
|
-
description: "Open the
|
|
13446
|
-
|
|
14538
|
+
description: "Open the settings editor, or set a value inline: /settings [<chord> [<value>]].",
|
|
14539
|
+
argsHint: "[<chord> [<value>]]",
|
|
14540
|
+
help: "Open the settings editor.\n\n /settings Open on the last-visited row\n /settings <chord> Open on that row\n /settings <chord> <v> Set <chord> to <v> without opening the picker\n /settings reset <chord> Reset <chord> to its factory default\n\nExamples:\n /settings yolo on Enable YOLO mode\n /settings multi-diff 8 Set multi-diff threshold to 8\n /settings thinking-word pondering Set the working-state word\n\nAvailable chords:\n " + settingsPickerJumpNames().join("\n "),
|
|
14541
|
+
async run(args) {
|
|
14542
|
+
const query = args.trim();
|
|
14543
|
+
if (query === "") {
|
|
14544
|
+
openSettings();
|
|
14545
|
+
return { message: void 0 };
|
|
14546
|
+
}
|
|
14547
|
+
if (query === "reset" || query.startsWith("reset ")) {
|
|
14548
|
+
const subArg = query.slice("reset".length).trim();
|
|
14549
|
+
if (subArg === "") {
|
|
14550
|
+
return {
|
|
14551
|
+
message: "Usage: /settings reset <chord>\nAvailable: " + settingsPickerJumpNames().join(", ")
|
|
14552
|
+
};
|
|
14553
|
+
}
|
|
14554
|
+
const field2 = settingsPickerJumpByName(subArg);
|
|
14555
|
+
if (field2 === void 0) {
|
|
14556
|
+
return {
|
|
14557
|
+
message: `Unknown settings row "${subArg}".
|
|
14558
|
+
Available chords:
|
|
14559
|
+
${settingsPickerJumpNames().join("\n ")}`
|
|
14560
|
+
};
|
|
14561
|
+
}
|
|
14562
|
+
const result = resetSettingsFieldValue(field2);
|
|
14563
|
+
if (!result.ok) {
|
|
14564
|
+
return { message: result.error };
|
|
14565
|
+
}
|
|
14566
|
+
dispatch({ type: "settingsValueSet", patch: result.patch });
|
|
14567
|
+
const cur = getSettings ? getSettings() : void 0;
|
|
14568
|
+
if (cur && saveSettings) {
|
|
14569
|
+
const { tokenSavingTier, ...rest } = result.patch;
|
|
14570
|
+
Promise.resolve(
|
|
14571
|
+
saveSettings({
|
|
14572
|
+
...cur,
|
|
14573
|
+
...rest,
|
|
14574
|
+
...tokenSavingTier !== void 0 ? { featureTokenSaving: tokenSavingTier } : {}
|
|
14575
|
+
})
|
|
14576
|
+
).then((err) => {
|
|
14577
|
+
if (err) dispatch({ type: "settingsHint", text: err });
|
|
14578
|
+
});
|
|
14579
|
+
}
|
|
14580
|
+
return { message: `\u21BA ${result.label} reset to ${result.displayValue}` };
|
|
14581
|
+
}
|
|
14582
|
+
const spaceIdx = query.indexOf(" ");
|
|
14583
|
+
if (spaceIdx > 0) {
|
|
14584
|
+
const rowName = query.slice(0, spaceIdx);
|
|
14585
|
+
const valueStr = query.slice(spaceIdx + 1).trim();
|
|
14586
|
+
const field2 = settingsPickerJumpByName(rowName);
|
|
14587
|
+
if (field2 === void 0) {
|
|
14588
|
+
return {
|
|
14589
|
+
message: `Unknown settings row "${rowName}".
|
|
14590
|
+
Available chords:
|
|
14591
|
+
${settingsPickerJumpNames().join("\n ")}`
|
|
14592
|
+
};
|
|
14593
|
+
}
|
|
14594
|
+
if (valueStr === "") {
|
|
14595
|
+
dispatch({ type: "settingsFieldSet", field: field2 });
|
|
14596
|
+
openSettings();
|
|
14597
|
+
return { message: void 0 };
|
|
14598
|
+
}
|
|
14599
|
+
const result = resolveSettingsFieldValue(field2, valueStr);
|
|
14600
|
+
if (!result.ok) {
|
|
14601
|
+
return { message: result.error };
|
|
14602
|
+
}
|
|
14603
|
+
dispatch({ type: "settingsValueSet", patch: result.patch });
|
|
14604
|
+
const cur = getSettings ? getSettings() : void 0;
|
|
14605
|
+
if (cur && saveSettings) {
|
|
14606
|
+
const { tokenSavingTier, ...rest } = result.patch;
|
|
14607
|
+
const updated = {
|
|
14608
|
+
...cur,
|
|
14609
|
+
...rest,
|
|
14610
|
+
...tokenSavingTier !== void 0 ? { featureTokenSaving: tokenSavingTier } : {}
|
|
14611
|
+
};
|
|
14612
|
+
Promise.resolve(saveSettings(updated)).then((err) => {
|
|
14613
|
+
if (err) dispatch({ type: "settingsHint", text: err });
|
|
14614
|
+
});
|
|
14615
|
+
}
|
|
14616
|
+
return { message: `\u2713 ${result.label} \u2192 ${result.displayValue}` };
|
|
14617
|
+
}
|
|
14618
|
+
const field = settingsPickerJumpByName(query);
|
|
14619
|
+
if (field === void 0) {
|
|
14620
|
+
return {
|
|
14621
|
+
message: `Unknown settings row "${query}".
|
|
14622
|
+
Available chords:
|
|
14623
|
+
${settingsPickerJumpNames().join("\n ")}`
|
|
14624
|
+
};
|
|
14625
|
+
}
|
|
14626
|
+
dispatch({ type: "settingsFieldSet", field });
|
|
13447
14627
|
openSettings();
|
|
13448
14628
|
return { message: void 0 };
|
|
13449
14629
|
}
|
|
@@ -13452,7 +14632,39 @@ function App({
|
|
|
13452
14632
|
return () => {
|
|
13453
14633
|
slashRegistry.unregister("settings");
|
|
13454
14634
|
};
|
|
13455
|
-
}, [slashRegistry, getSettings, saveSettings, openSettings]);
|
|
14635
|
+
}, [slashRegistry, getSettings, saveSettings, openSettings, dispatch]);
|
|
14636
|
+
useEffect(() => {
|
|
14637
|
+
const cmd = {
|
|
14638
|
+
name: "settings-get",
|
|
14639
|
+
aliases: ["config-get", "get"],
|
|
14640
|
+
description: "Read a setting value without opening the picker.",
|
|
14641
|
+
argsHint: "<chord>",
|
|
14642
|
+
help: 'Show the current value of a setting.\n\nExamples:\n /settings-get yolo \u2192 "YOLO mode: off"\n /settings-get multi-diff \u2192 "Multi-diff summary: 5"\n /settings-get log-level \u2192 "Log level: info"\n\nAvailable chords:\n ' + settingsPickerJumpNames().join("\n "),
|
|
14643
|
+
async run(args) {
|
|
14644
|
+
const query = args.trim();
|
|
14645
|
+
if (query === "") {
|
|
14646
|
+
return { message: formatAllSettingsSummary(state.settingsPicker) };
|
|
14647
|
+
}
|
|
14648
|
+
const field = settingsPickerJumpByName(query);
|
|
14649
|
+
if (field === void 0) {
|
|
14650
|
+
return {
|
|
14651
|
+
message: `Unknown settings row "${query}".
|
|
14652
|
+
Available chords:
|
|
14653
|
+
${settingsPickerJumpNames().join("\n ")}`
|
|
14654
|
+
};
|
|
14655
|
+
}
|
|
14656
|
+
const result = getSettingsFieldValue(state.settingsPicker, field);
|
|
14657
|
+
if (!result.ok) {
|
|
14658
|
+
return { message: result.error };
|
|
14659
|
+
}
|
|
14660
|
+
return { message: `${result.label}: ${result.displayValue}` };
|
|
14661
|
+
}
|
|
14662
|
+
};
|
|
14663
|
+
slashRegistry.register(cmd, "tui", { official: true });
|
|
14664
|
+
return () => {
|
|
14665
|
+
slashRegistry.unregister("settings-get");
|
|
14666
|
+
};
|
|
14667
|
+
}, [slashRegistry, state.settingsPicker]);
|
|
13456
14668
|
useEffect(() => {
|
|
13457
14669
|
const cmd = {
|
|
13458
14670
|
name: "statusline",
|
|
@@ -14207,6 +15419,29 @@ function App({
|
|
|
14207
15419
|
return;
|
|
14208
15420
|
}
|
|
14209
15421
|
if (state.settingsPicker.open) {
|
|
15422
|
+
const sp = state.settingsPicker;
|
|
15423
|
+
if (sp.thinkingWordEditing) {
|
|
15424
|
+
if (key.escape) {
|
|
15425
|
+
dispatch({ type: "settingsThinkingEditCancel" });
|
|
15426
|
+
return;
|
|
15427
|
+
}
|
|
15428
|
+
if (isEnter) {
|
|
15429
|
+
const now = Date.now();
|
|
15430
|
+
if (now - lastEnterAtRef.current < 50) return;
|
|
15431
|
+
lastEnterAtRef.current = now;
|
|
15432
|
+
dispatch({ type: "settingsThinkingEditCommit" });
|
|
15433
|
+
return;
|
|
15434
|
+
}
|
|
15435
|
+
if (key.backspace) {
|
|
15436
|
+
dispatch({ type: "settingsThinkingEditChange", draft: sp.thinkingWordDraft.slice(0, -1) });
|
|
15437
|
+
return;
|
|
15438
|
+
}
|
|
15439
|
+
if (input && input.length === 1 && input.charCodeAt(0) >= 32 && input.charCodeAt(0) < 127) {
|
|
15440
|
+
dispatch({ type: "settingsThinkingEditChange", draft: sp.thinkingWordDraft + input });
|
|
15441
|
+
return;
|
|
15442
|
+
}
|
|
15443
|
+
return;
|
|
15444
|
+
}
|
|
14210
15445
|
if (key.escape || key.ctrl && input === "s") {
|
|
14211
15446
|
dispatch({ type: "settingsClose" });
|
|
14212
15447
|
return;
|
|
@@ -14215,6 +15450,33 @@ function App({
|
|
|
14215
15450
|
dispatch({ type: "settingsFieldMove", delta: key.mouse.wheel > 0 ? -1 : 1 });
|
|
14216
15451
|
return;
|
|
14217
15452
|
}
|
|
15453
|
+
if (input && input.length === 1 && (key.ctrl || key.meta)) {
|
|
15454
|
+
const mod = key.ctrl ? "ctrl" : key.shift ? "alt-shift" : "alt";
|
|
15455
|
+
const field = settingsPickerJumpField(mod, input);
|
|
15456
|
+
if (field !== void 0) {
|
|
15457
|
+
dispatch({ type: "settingsFieldSet", field });
|
|
15458
|
+
return;
|
|
15459
|
+
}
|
|
15460
|
+
}
|
|
15461
|
+
if (input === "/" && sp.filter === "") {
|
|
15462
|
+
dispatch({ type: "settingsFilterSet", filter: "/" });
|
|
15463
|
+
return;
|
|
15464
|
+
}
|
|
15465
|
+
if (sp.filter !== "") {
|
|
15466
|
+
if (key.escape) {
|
|
15467
|
+
dispatch({ type: "settingsFilterSet", filter: "" });
|
|
15468
|
+
return;
|
|
15469
|
+
}
|
|
15470
|
+
if (key.backspace) {
|
|
15471
|
+
const next2 = sp.filter.length > 1 ? sp.filter.slice(0, -1) : "";
|
|
15472
|
+
dispatch({ type: "settingsFilterSet", filter: next2 });
|
|
15473
|
+
return;
|
|
15474
|
+
}
|
|
15475
|
+
if (input && input.length === 1 && input.charCodeAt(0) >= 32 && input.charCodeAt(0) < 127) {
|
|
15476
|
+
dispatch({ type: "settingsFilterSet", filter: sp.filter + input });
|
|
15477
|
+
return;
|
|
15478
|
+
}
|
|
15479
|
+
}
|
|
14218
15480
|
if (key.upArrow) {
|
|
14219
15481
|
dispatch({ type: "settingsFieldMove", delta: -1 });
|
|
14220
15482
|
return;
|
|
@@ -14235,7 +15497,15 @@ function App({
|
|
|
14235
15497
|
const now = Date.now();
|
|
14236
15498
|
if (now - lastEnterAtRef.current < 50) return;
|
|
14237
15499
|
lastEnterAtRef.current = now;
|
|
14238
|
-
|
|
15500
|
+
if (sp.filter !== "") {
|
|
15501
|
+
dispatch({ type: "settingsFilterSet", filter: "" });
|
|
15502
|
+
return;
|
|
15503
|
+
}
|
|
15504
|
+
if (sp.field === THINKING_WORD_FIELD) {
|
|
15505
|
+
dispatch({ type: "settingsThinkingEditStart" });
|
|
15506
|
+
} else {
|
|
15507
|
+
dispatch({ type: "settingsValueChange", delta: 1 });
|
|
15508
|
+
}
|
|
14239
15509
|
return;
|
|
14240
15510
|
}
|
|
14241
15511
|
return;
|
|
@@ -14853,6 +16123,8 @@ function App({
|
|
|
14853
16123
|
logLevel: cfg.logLevel ?? "info",
|
|
14854
16124
|
auditLevel: cfg.auditLevel ?? "standard",
|
|
14855
16125
|
indexOnStart: cfg.indexOnStart ?? true,
|
|
16126
|
+
multiDiffSummaryThreshold: cfg.multiDiffSummaryThreshold ?? 5,
|
|
16127
|
+
lastSettingsField: cfg.lastSettingsField ?? 0,
|
|
14856
16128
|
maxIterations: cfg.maxIterations ?? 500,
|
|
14857
16129
|
autoProceedMaxIterations: cfg.autoProceedMaxIterations ?? 50,
|
|
14858
16130
|
enhanceDelayMs: cfg.enhanceDelayMs ?? 6e4,
|
|
@@ -15124,7 +16396,7 @@ function App({
|
|
|
15124
16396
|
// Must match the rendered state label width — while streaming the bar
|
|
15125
16397
|
// shows the configured thinking word, so the span shifts with it.
|
|
15126
16398
|
// Omitting this made the model chip un-clickable mid-stream.
|
|
15127
|
-
thinkingWord:
|
|
16399
|
+
thinkingWord: displayThinkingWordRef.current,
|
|
15128
16400
|
model: `${liveProvider}/${liveModel}`
|
|
15129
16401
|
});
|
|
15130
16402
|
if (inSpan(span)) {
|
|
@@ -15732,10 +17004,12 @@ User message:
|
|
|
15732
17004
|
if (autonomyLive === "auto" && nextStepsAutoSubmitTimerRef.current != null) {
|
|
15733
17005
|
switchAutonomy?.("off");
|
|
15734
17006
|
}
|
|
15735
|
-
|
|
15736
|
-
|
|
15737
|
-
|
|
15738
|
-
|
|
17007
|
+
if (!steering) {
|
|
17008
|
+
dispatch({
|
|
17009
|
+
type: "addEntry",
|
|
17010
|
+
entry: { kind: "user", text: displayText, queued: true, pasteContent }
|
|
17011
|
+
});
|
|
17012
|
+
}
|
|
15739
17013
|
dispatch({ type: "enqueue", item: { displayText, blocks } });
|
|
15740
17014
|
return;
|
|
15741
17015
|
}
|
|
@@ -15808,7 +17082,7 @@ User message:
|
|
|
15808
17082
|
onMeasure: (totalLines) => dispatch({ type: "setMeasuredLines", totalLines }),
|
|
15809
17083
|
setSuggestions,
|
|
15810
17084
|
autonomyMode: autonomyLive,
|
|
15811
|
-
|
|
17085
|
+
multiDiffSummaryThreshold: state.settingsPicker.multiDiffSummaryThreshold
|
|
15812
17086
|
}
|
|
15813
17087
|
) : /* @__PURE__ */ jsx(
|
|
15814
17088
|
History,
|
|
@@ -15819,7 +17093,7 @@ User message:
|
|
|
15819
17093
|
toolStream: state.toolStream,
|
|
15820
17094
|
setSuggestions,
|
|
15821
17095
|
autonomyMode: autonomyLive,
|
|
15822
|
-
|
|
17096
|
+
multiDiffSummaryThreshold: state.settingsPicker.multiDiffSummaryThreshold
|
|
15823
17097
|
}
|
|
15824
17098
|
),
|
|
15825
17099
|
/* @__PURE__ */ jsxs(Box, { flexDirection: "column", flexShrink: 0, ref: bottomRegionRef, children: [
|
|
@@ -15909,7 +17183,10 @@ User message:
|
|
|
15909
17183
|
logLevel: state.settingsPicker.logLevel,
|
|
15910
17184
|
auditLevel: state.settingsPicker.auditLevel,
|
|
15911
17185
|
indexOnStart: state.settingsPicker.indexOnStart,
|
|
17186
|
+
multiDiffSummaryThreshold: state.settingsPicker.multiDiffSummaryThreshold,
|
|
15912
17187
|
thinkingWord: state.settingsPicker.thinkingWord,
|
|
17188
|
+
thinkingWordEditing: state.settingsPicker.thinkingWordEditing,
|
|
17189
|
+
thinkingWordDraft: state.settingsPicker.thinkingWordDraft,
|
|
15913
17190
|
maxIterations: state.settingsPicker.maxIterations,
|
|
15914
17191
|
autoProceedMaxIterations: state.settingsPicker.autoProceedMaxIterations,
|
|
15915
17192
|
enhanceDelayMs: state.settingsPicker.enhanceDelayMs,
|
|
@@ -15922,6 +17199,7 @@ User message:
|
|
|
15922
17199
|
reasoningPreserve: state.settingsPicker.reasoningPreserve,
|
|
15923
17200
|
cacheTtl: state.settingsPicker.cacheTtl,
|
|
15924
17201
|
configScope: state.settingsPicker.configScope,
|
|
17202
|
+
filter: state.settingsPicker.filter,
|
|
15925
17203
|
hint: state.settingsPicker.hint
|
|
15926
17204
|
}
|
|
15927
17205
|
) : null,
|
|
@@ -16080,7 +17358,7 @@ User message:
|
|
|
16080
17358
|
model: `${liveProvider}/${liveModel}`,
|
|
16081
17359
|
version: appVersion,
|
|
16082
17360
|
state: state.status,
|
|
16083
|
-
thinkingWord:
|
|
17361
|
+
thinkingWord: displayThinkingWord,
|
|
16084
17362
|
tokenCounter,
|
|
16085
17363
|
hint: renderRunningTools(state.runningTools) || state.hint,
|
|
16086
17364
|
queueCount: state.queue.length,
|