@wrongstack/tui 0.282.2 → 0.283.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +2 -0
- package/dist/index.js +472 -190
- package/dist/index.js.map +1 -1
- package/package.json +4 -4
package/dist/index.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { hasOpenTodos, writeErr, resolveProjectDir, wstackGlobalRoot, createHqPublisherFromEnv, startFleetTelemetryBridge, startBrainTelemetryBridge, startWorktreeTelemetryBridge, startToolTelemetryBridge, startCostTelemetryBridge, GlobalMailbox, resolveWstackPaths, loadGoal, InputBuilder, DefaultSessionRewinder, writeOut, formatTodosList, buildGoalPreamble, expectDefined as expectDefined$1, InputHistoryStore, DefaultSecretScrubber, INPUT_HISTORY_DEFAULT_MAX, DefaultPromptLoader, PromptUsageStore, getDesignKitLoader, clearActiveKit, clearPersistedActiveKit, recordOverrides, setDesignOverrides, loadActiveKit, isDesignStack, materializeTokens, applyTokenOverrides, setActiveKit, projectSlug, shouldEnhance, enhanceUserPrompt, recentTextTurns, normalizedEqual, setBtwNote, listBoards, getBoard, createBoard, addTask, buildChildEnv, removeTask, moveTask, updateTask, duplicateBoard, copyTaskToBoard, transferTaskToBoard } from '@wrongstack/core';
|
|
1
|
+
import { hasOpenTodos, writeErr, resolveProjectDir, wstackGlobalRoot, createHqPublisherFromEnv, startFleetTelemetryBridge, startBrainTelemetryBridge, startWorktreeTelemetryBridge, startToolTelemetryBridge, startCostTelemetryBridge, GlobalMailbox, resolveWstackPaths, loadGoal, InputBuilder, DefaultSessionRewinder, writeOut, formatTodosList, buildGoalPreamble, expectDefined as expectDefined$1, InputHistoryStore, DefaultSecretScrubber, INPUT_HISTORY_DEFAULT_MAX, DefaultPromptLoader, PromptUsageStore, getDesignKitLoader, clearActiveKit, clearPersistedActiveKit, recordOverrides, setDesignOverrides, loadActiveKit, isDesignStack, materializeTokens, applyTokenOverrides, setActiveKit, projectSlug, detectContinueIntent, resolveContinuation, shouldEnhance, enhanceUserPrompt, recentTextTurns, normalizedEqual, setBtwNote, listBoards, getBoard, createBoard, addTask, buildChildEnv, removeTask, moveTask, updateTask, duplicateBoard, copyTaskToBoard, transferTaskToBoard } from '@wrongstack/core';
|
|
2
2
|
export { buildGoalPreamble } from '@wrongstack/core';
|
|
3
3
|
import { Box as Box$1, useStdout, Static, useInput, useStdin, measureElement, Text as Text$1, render, useApp } from 'ink';
|
|
4
4
|
import { randomUUID } from 'crypto';
|
|
5
5
|
import * as path9 from 'path';
|
|
6
|
-
import
|
|
6
|
+
import React7, { forwardRef, useState, useEffect, useMemo, memo, useRef, useLayoutEffect, useCallback, useReducer, isValidElement, Fragment as Fragment$1 } from 'react';
|
|
7
7
|
import * as fsp from 'fs/promises';
|
|
8
8
|
import { expectDefined, toErrorMessage, resolveWstackPaths as resolveWstackPaths$1, sessionScopedPath } from '@wrongstack/core/utils';
|
|
9
9
|
import { routeImagesForModel } from '@wrongstack/runtime/vision';
|
|
@@ -3524,6 +3524,10 @@ function reducer(state, action) {
|
|
|
3524
3524
|
return { ...state, confirmQueue: [...state.confirmQueue, action.info] };
|
|
3525
3525
|
case "confirmClose":
|
|
3526
3526
|
return { ...state, confirmQueue: state.confirmQueue.slice(1) };
|
|
3527
|
+
case "shellCommandWarningOpen":
|
|
3528
|
+
return { ...state, shellCommandWarning: action.info };
|
|
3529
|
+
case "shellCommandWarningClose":
|
|
3530
|
+
return { ...state, shellCommandWarning: null };
|
|
3527
3531
|
case "enhanceOpen":
|
|
3528
3532
|
return { ...state, enhance: action.info };
|
|
3529
3533
|
case "enhanceClose":
|
|
@@ -3532,6 +3536,10 @@ function reducer(state, action) {
|
|
|
3532
3536
|
return { ...state, enhanceEnabled: action.enabled };
|
|
3533
3537
|
case "enhanceBusy":
|
|
3534
3538
|
return { ...state, enhanceBusy: action.on };
|
|
3539
|
+
case "continueConfirmOpen":
|
|
3540
|
+
return { ...state, continueConfirm: action.info };
|
|
3541
|
+
case "continueConfirmClose":
|
|
3542
|
+
return { ...state, continueConfirm: null };
|
|
3535
3543
|
case "escConfirmOpen":
|
|
3536
3544
|
return { ...state, escConfirm: { snapshot: action.snapshot } };
|
|
3537
3545
|
case "escConfirmClose":
|
|
@@ -6346,22 +6354,62 @@ function BrainDecisionPrompt({
|
|
|
6346
6354
|
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "Press A/B/C or 1/2/3 to answer; Esc or D denies with the safe default." })
|
|
6347
6355
|
] });
|
|
6348
6356
|
}
|
|
6357
|
+
function modeFamily(mode) {
|
|
6358
|
+
if (mode.tags?.includes("lite")) return "lite";
|
|
6359
|
+
if (mode.tags?.includes("deep")) return "deep";
|
|
6360
|
+
if (mode.tags?.includes("balanced") || mode.id === "default") return "balanced";
|
|
6361
|
+
return "custom";
|
|
6362
|
+
}
|
|
6349
6363
|
function toModeOptions(modes, activeId) {
|
|
6350
6364
|
return modes.map((m) => ({
|
|
6351
6365
|
id: m.id,
|
|
6352
6366
|
name: m.name,
|
|
6353
6367
|
description: m.description,
|
|
6368
|
+
family: modeFamily(m),
|
|
6354
6369
|
isActive: m.id === activeId
|
|
6355
6370
|
}));
|
|
6356
6371
|
}
|
|
6372
|
+
function familyLabel(family) {
|
|
6373
|
+
switch (family) {
|
|
6374
|
+
case "lite":
|
|
6375
|
+
return "lite";
|
|
6376
|
+
case "deep":
|
|
6377
|
+
return "deep";
|
|
6378
|
+
case "balanced":
|
|
6379
|
+
return "base";
|
|
6380
|
+
case "custom":
|
|
6381
|
+
return "custom";
|
|
6382
|
+
}
|
|
6383
|
+
}
|
|
6384
|
+
function familyColor(family) {
|
|
6385
|
+
switch (family) {
|
|
6386
|
+
case "lite":
|
|
6387
|
+
return "green";
|
|
6388
|
+
case "deep":
|
|
6389
|
+
return "magenta";
|
|
6390
|
+
case "balanced":
|
|
6391
|
+
return "blue";
|
|
6392
|
+
case "custom":
|
|
6393
|
+
return "yellow";
|
|
6394
|
+
}
|
|
6395
|
+
}
|
|
6357
6396
|
function ModePicker({
|
|
6358
6397
|
modes,
|
|
6359
6398
|
selected,
|
|
6360
6399
|
hint
|
|
6361
6400
|
}) {
|
|
6401
|
+
const activeMode = modes.find((mode) => mode.isActive);
|
|
6402
|
+
const modeMeta = `${modes.length} mode${modes.length === 1 ? "" : "s"}`;
|
|
6362
6403
|
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", borderStyle: "round", borderColor: "blue", paddingX: 1, children: [
|
|
6363
|
-
/* @__PURE__ */
|
|
6364
|
-
|
|
6404
|
+
/* @__PURE__ */ jsxs(Text, { color: "cyan", bold: true, children: [
|
|
6405
|
+
"\u2501\u2501 Mode Selection \u2501\u2501 ",
|
|
6406
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: modeMeta })
|
|
6407
|
+
] }),
|
|
6408
|
+
/* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
6409
|
+
"Current: ",
|
|
6410
|
+
activeMode ? activeMode.name : "none",
|
|
6411
|
+
" \xB7 \u2191/\u2193 navigate \xB7 Enter select \xB7 Esc cancel"
|
|
6412
|
+
] }),
|
|
6365
6413
|
modes.length === 0 ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: "No modes available." }) : modes.map((opt, i) => /* @__PURE__ */ jsxs(
|
|
6366
6414
|
Text,
|
|
6367
6415
|
{
|
|
@@ -6369,9 +6417,17 @@ function ModePicker({
|
|
|
6369
6417
|
...i === selected ? { color: "cyan" } : {},
|
|
6370
6418
|
children: [
|
|
6371
6419
|
i === selected ? "\u203A " : " ",
|
|
6372
|
-
/* @__PURE__ */ jsx(Text, { bold: true, children: opt.name.padEnd(
|
|
6373
|
-
/* @__PURE__ */
|
|
6374
|
-
|
|
6420
|
+
/* @__PURE__ */ jsx(Text, { bold: true, children: opt.name.padEnd(18) }),
|
|
6421
|
+
/* @__PURE__ */ jsxs(Text, { color: familyColor(opt.family), children: [
|
|
6422
|
+
"[",
|
|
6423
|
+
familyLabel(opt.family),
|
|
6424
|
+
"]"
|
|
6425
|
+
] }),
|
|
6426
|
+
/* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
6427
|
+
" ",
|
|
6428
|
+
opt.description
|
|
6429
|
+
] }),
|
|
6430
|
+
opt.isActive ? /* @__PURE__ */ jsx(Text, { color: "green", children: " \u25CF active" }) : null
|
|
6375
6431
|
]
|
|
6376
6432
|
},
|
|
6377
6433
|
opt.id
|
|
@@ -8466,7 +8522,7 @@ function streamBoxRows(text, maxLines, contentWidth) {
|
|
|
8466
8522
|
}
|
|
8467
8523
|
return rows;
|
|
8468
8524
|
}
|
|
8469
|
-
var ToolStreamBox =
|
|
8525
|
+
var ToolStreamBox = React7.memo(function ToolStreamBox2({
|
|
8470
8526
|
name,
|
|
8471
8527
|
text,
|
|
8472
8528
|
startedAt,
|
|
@@ -9106,7 +9162,7 @@ function ConfirmPrompt({
|
|
|
9106
9162
|
onEnableYolo,
|
|
9107
9163
|
destructive
|
|
9108
9164
|
}) {
|
|
9109
|
-
|
|
9165
|
+
React7.useEffect(() => {
|
|
9110
9166
|
writeOut("\x07");
|
|
9111
9167
|
}, []);
|
|
9112
9168
|
useInput((input2, _key) => {
|
|
@@ -9140,7 +9196,7 @@ function ConfirmPrompt({
|
|
|
9140
9196
|
inputSummary ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: inputSummary }) : null,
|
|
9141
9197
|
showDiff && diff ? /* @__PURE__ */ jsx(Box, { flexDirection: "column", marginY: 1, children: renderDiff(diff, diffPath) }) : null,
|
|
9142
9198
|
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500" }),
|
|
9143
|
-
/* @__PURE__ */ jsx(Box, { flexDirection: "row", children: /* @__PURE__ */ jsx(Text, { children: buttonLabels(suggestedPattern).map((l) => /* @__PURE__ */ jsxs(
|
|
9199
|
+
/* @__PURE__ */ jsx(Box, { flexDirection: "row", children: /* @__PURE__ */ jsx(Text, { children: buttonLabels(suggestedPattern).map((l) => /* @__PURE__ */ jsxs(React7.Fragment, { children: [
|
|
9144
9200
|
/* @__PURE__ */ jsx(Text, { bold: true, color: BUTTON_COLOR[l.decision], children: l.bracket }),
|
|
9145
9201
|
/* @__PURE__ */ jsx(Text, { dimColor: true, children: l.rest })
|
|
9146
9202
|
] }, l.decision)) }) }),
|
|
@@ -9278,6 +9334,72 @@ function DesignPicker({ kits, selected, stack }) {
|
|
|
9278
9334
|
] }) }, kit.id))
|
|
9279
9335
|
] });
|
|
9280
9336
|
}
|
|
9337
|
+
function continueAutoProceedSeconds(grounded, delayMs) {
|
|
9338
|
+
return grounded ? Math.max(1, Math.ceil(delayMs / 1e3)) : null;
|
|
9339
|
+
}
|
|
9340
|
+
function ContinueConfirmPanel({
|
|
9341
|
+
label,
|
|
9342
|
+
instruction,
|
|
9343
|
+
source,
|
|
9344
|
+
grounded,
|
|
9345
|
+
delayMs,
|
|
9346
|
+
onDecision
|
|
9347
|
+
}) {
|
|
9348
|
+
const autoProceedSecs = continueAutoProceedSeconds(grounded, delayMs);
|
|
9349
|
+
const remainingRef = React7.useRef(autoProceedSecs ?? 0);
|
|
9350
|
+
const decideRef = React7.useRef(onDecision);
|
|
9351
|
+
decideRef.current = onDecision;
|
|
9352
|
+
React7.useEffect(() => {
|
|
9353
|
+
if (!grounded) return;
|
|
9354
|
+
const id = setInterval(() => {
|
|
9355
|
+
const r = remainingRef.current - 1;
|
|
9356
|
+
remainingRef.current = r;
|
|
9357
|
+
if (r <= 0) {
|
|
9358
|
+
clearInterval(id);
|
|
9359
|
+
decideRef.current("proceed");
|
|
9360
|
+
}
|
|
9361
|
+
}, 1e3);
|
|
9362
|
+
return () => clearInterval(id);
|
|
9363
|
+
}, [grounded]);
|
|
9364
|
+
useInput((input, key) => {
|
|
9365
|
+
if (key.return) {
|
|
9366
|
+
onDecision("proceed");
|
|
9367
|
+
} else if (key.escape) {
|
|
9368
|
+
onDecision("cancel");
|
|
9369
|
+
} else if (input?.toLowerCase() === "e") {
|
|
9370
|
+
onDecision("edit");
|
|
9371
|
+
}
|
|
9372
|
+
});
|
|
9373
|
+
const accent = grounded ? "cyan" : "yellow";
|
|
9374
|
+
const preview = instruction.length > 320 ? `${instruction.slice(0, 317)}\u2026` : instruction;
|
|
9375
|
+
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", borderStyle: "round", borderColor: accent, paddingX: 1, children: [
|
|
9376
|
+
/* @__PURE__ */ jsxs(Box, { flexDirection: "row", children: [
|
|
9377
|
+
/* @__PURE__ */ jsx(Text, { bold: true, color: accent, children: grounded ? "\u25B6 Continue" : "\u26A0 Continue (ambiguous)" }),
|
|
9378
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: ' \u2014 you typed a bare "continue"' })
|
|
9379
|
+
] }),
|
|
9380
|
+
/* @__PURE__ */ jsxs(Box, { flexDirection: "row", children: [
|
|
9381
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "resolves to: " }),
|
|
9382
|
+
/* @__PURE__ */ jsx(Text, { color: "white", children: label.replace(/^▶\s*Continue\s*→\s*/, "") })
|
|
9383
|
+
] }),
|
|
9384
|
+
source === "open" ? /* @__PURE__ */ jsxs(Box, { flexDirection: "column", marginTop: 1, children: [
|
|
9385
|
+
/* @__PURE__ */ jsx(Text, { color: "yellow", children: 'No pending todo or suggestion \u2014 "continue" has no anchor here.' }),
|
|
9386
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "If you proceed, I'll choose the next step myself from the conversation and project state. That's a guess \u2014 it can drift from what you meant." })
|
|
9387
|
+
] }) : /* @__PURE__ */ jsx(Box, { flexDirection: "column", marginTop: 1, children: /* @__PURE__ */ jsx(Text, { dimColor: true, children: preview }) }),
|
|
9388
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500" }),
|
|
9389
|
+
/* @__PURE__ */ jsx(Box, { flexDirection: "row", children: /* @__PURE__ */ jsxs(Text, { children: [
|
|
9390
|
+
/* @__PURE__ */ jsx(Text, { bold: true, color: "green", children: "[Enter]" }),
|
|
9391
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: autoProceedSecs != null ? ` proceed (auto ${autoProceedSecs}s) \xB7 ` : " proceed anyway \xB7 " }),
|
|
9392
|
+
/* @__PURE__ */ jsx(Text, { bold: true, color: "cyan", children: "[e]" }),
|
|
9393
|
+
/* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
9394
|
+
" ",
|
|
9395
|
+
source === "open" ? "type what to continue" : "edit",
|
|
9396
|
+
" \xB7 "
|
|
9397
|
+
] }),
|
|
9398
|
+
/* @__PURE__ */ jsx(Text, { bold: true, color: "red", children: "[Esc]" }),
|
|
9399
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: " cancel" })
|
|
9400
|
+
] }) })
|
|
9401
|
+
] });
|
|
9402
|
+
}
|
|
9281
9403
|
function EnhancePanel({
|
|
9282
9404
|
original,
|
|
9283
9405
|
refined,
|
|
@@ -9287,12 +9409,12 @@ function EnhancePanel({
|
|
|
9287
9409
|
onTick
|
|
9288
9410
|
}) {
|
|
9289
9411
|
const totalSecs = Math.max(1, Math.ceil(delayMs / 1e3));
|
|
9290
|
-
const remainingRef =
|
|
9291
|
-
const decideRef =
|
|
9412
|
+
const remainingRef = React7.useRef(totalSecs);
|
|
9413
|
+
const decideRef = React7.useRef(onDecision);
|
|
9292
9414
|
decideRef.current = onDecision;
|
|
9293
|
-
const tickRef =
|
|
9415
|
+
const tickRef = React7.useRef(onTick);
|
|
9294
9416
|
tickRef.current = onTick;
|
|
9295
|
-
|
|
9417
|
+
React7.useEffect(() => {
|
|
9296
9418
|
const id = setInterval(() => {
|
|
9297
9419
|
const r = remainingRef.current - 1;
|
|
9298
9420
|
remainingRef.current = r;
|
|
@@ -9539,6 +9661,44 @@ function FilePicker({ query, matches, selected }) {
|
|
|
9539
9661
|
function highlight(path10, _query) {
|
|
9540
9662
|
return path10;
|
|
9541
9663
|
}
|
|
9664
|
+
function truncateShellCommandWarningCommand(text, max = 80) {
|
|
9665
|
+
return text.length <= max ? text : `${text.slice(0, max - 1)}\u2026`;
|
|
9666
|
+
}
|
|
9667
|
+
function ShellCommandWarning({
|
|
9668
|
+
command,
|
|
9669
|
+
onDecision
|
|
9670
|
+
}) {
|
|
9671
|
+
React7.useEffect(() => {
|
|
9672
|
+
writeOut("\x07");
|
|
9673
|
+
}, []);
|
|
9674
|
+
useInput((input, _key) => {
|
|
9675
|
+
if (!input || input === "\r" || input === "\n") return;
|
|
9676
|
+
const ch = input.toLowerCase();
|
|
9677
|
+
if (ch === "y") onDecision("yes");
|
|
9678
|
+
if (ch === "n") onDecision("no");
|
|
9679
|
+
if (ch === "d") onDecision("dont-show-again");
|
|
9680
|
+
});
|
|
9681
|
+
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", borderStyle: "round", borderColor: "yellow", paddingX: 1, children: [
|
|
9682
|
+
/* @__PURE__ */ jsxs(Box, { flexDirection: "row", children: [
|
|
9683
|
+
/* @__PURE__ */ jsx(Text, { bold: true, color: "yellow", children: "\u26A0 SHELL COMMAND" }),
|
|
9684
|
+
/* @__PURE__ */ jsx(Text, { children: " " }),
|
|
9685
|
+
/* @__PURE__ */ jsxs(Text, { bold: true, color: "white", children: [
|
|
9686
|
+
"!",
|
|
9687
|
+
truncateShellCommandWarningCommand(command)
|
|
9688
|
+
] })
|
|
9689
|
+
] }),
|
|
9690
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "This will execute in your shell via /dev. Only run commands you trust." }),
|
|
9691
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500" }),
|
|
9692
|
+
/* @__PURE__ */ jsx(Box, { flexDirection: "row", children: /* @__PURE__ */ jsxs(Text, { children: [
|
|
9693
|
+
/* @__PURE__ */ jsx(Text, { bold: true, color: "green", children: "[y]" }),
|
|
9694
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "es " }),
|
|
9695
|
+
/* @__PURE__ */ jsx(Text, { bold: true, color: "red", children: "[n]" }),
|
|
9696
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "o " }),
|
|
9697
|
+
/* @__PURE__ */ jsx(Text, { bold: true, color: "cyan", children: "[d]" }),
|
|
9698
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "ont show again" })
|
|
9699
|
+
] }) })
|
|
9700
|
+
] });
|
|
9701
|
+
}
|
|
9542
9702
|
var METER_WIDTH = 10;
|
|
9543
9703
|
function isLeaderEntry2(entry) {
|
|
9544
9704
|
return entry.id === "leader" || entry.name === "LEADER";
|
|
@@ -10918,7 +11078,7 @@ function brainRiskColor(risk) {
|
|
|
10918
11078
|
return "red";
|
|
10919
11079
|
}
|
|
10920
11080
|
}
|
|
10921
|
-
var Entry =
|
|
11081
|
+
var Entry = React7.memo(function Entry2({
|
|
10922
11082
|
entry,
|
|
10923
11083
|
termWidth,
|
|
10924
11084
|
setSuggestions,
|
|
@@ -12963,14 +13123,11 @@ function PluginPicker({
|
|
|
12963
13123
|
] });
|
|
12964
13124
|
}
|
|
12965
13125
|
var CHROME_ROWS5 = 15;
|
|
12966
|
-
function formatCount(noun, count) {
|
|
12967
|
-
return `${count} ${noun}${count === 1 ? "" : "s"}`;
|
|
12968
|
-
}
|
|
12969
13126
|
function toolActionLabel(enabled) {
|
|
12970
|
-
return enabled ? "Enter
|
|
13127
|
+
return enabled ? "Enter makes this tool passive" : "Enter re-enables this tool";
|
|
12971
13128
|
}
|
|
12972
13129
|
function statusBadge2(enabled) {
|
|
12973
|
-
return enabled ? /* @__PURE__ */ jsx(Text, { color: "green", children: "\u25CF active" }) : /* @__PURE__ */ jsx(Text, { color: "red", children: "\u25CB
|
|
13130
|
+
return enabled ? /* @__PURE__ */ jsx(Text, { color: "green", children: "\u25CF active" }) : /* @__PURE__ */ jsx(Text, { color: "red", children: "\u25CB passive" });
|
|
12974
13131
|
}
|
|
12975
13132
|
function rwBadge(mutating) {
|
|
12976
13133
|
return mutating ? /* @__PURE__ */ jsx(Text, { color: "yellow", children: "mut" }) : /* @__PURE__ */ jsx(Text, { color: "cyan", children: "ro" });
|
|
@@ -12979,23 +13136,52 @@ function displayCategory(cat) {
|
|
|
12979
13136
|
if (!cat || cat.trim() === "") return "Other";
|
|
12980
13137
|
return cat.charAt(0).toUpperCase() + cat.slice(1);
|
|
12981
13138
|
}
|
|
12982
|
-
|
|
12983
|
-
|
|
12984
|
-
|
|
12985
|
-
|
|
12986
|
-
|
|
12987
|
-
|
|
12988
|
-
|
|
12989
|
-
|
|
12990
|
-
|
|
12991
|
-
|
|
12992
|
-
|
|
13139
|
+
var DEFAULT_COLUMN_WIDTHS = {
|
|
13140
|
+
name: 28,
|
|
13141
|
+
category: 16,
|
|
13142
|
+
owner: 31,
|
|
13143
|
+
permission: 8
|
|
13144
|
+
};
|
|
13145
|
+
var MIN_COLUMN_WIDTHS = {
|
|
13146
|
+
name: 22,
|
|
13147
|
+
category: 13,
|
|
13148
|
+
owner: 20,
|
|
13149
|
+
permission: 7
|
|
13150
|
+
};
|
|
13151
|
+
function shrinkColumn(widths, column, overflow) {
|
|
13152
|
+
const room = widths[column] - MIN_COLUMN_WIDTHS[column];
|
|
13153
|
+
const shrinkBy = Math.min(room, overflow);
|
|
13154
|
+
widths[column] -= shrinkBy;
|
|
13155
|
+
return overflow - shrinkBy;
|
|
13156
|
+
}
|
|
13157
|
+
function columnWidthsFor(columns) {
|
|
13158
|
+
const widths = { ...DEFAULT_COLUMN_WIDTHS };
|
|
13159
|
+
const rowChromeWidth = 30;
|
|
13160
|
+
const availableVariableWidth = Math.max(
|
|
13161
|
+
Object.values(MIN_COLUMN_WIDTHS).reduce((sum, width) => sum + width, 0),
|
|
13162
|
+
columns - rowChromeWidth
|
|
13163
|
+
);
|
|
13164
|
+
const desiredVariableWidth = Object.values(widths).reduce((sum, width) => sum + width, 0);
|
|
13165
|
+
let overflow = desiredVariableWidth - availableVariableWidth;
|
|
13166
|
+
for (const column of ["owner", "category", "name", "permission"]) {
|
|
13167
|
+
if (overflow <= 0) break;
|
|
13168
|
+
overflow = shrinkColumn(widths, column, overflow);
|
|
12993
13169
|
}
|
|
12994
|
-
return
|
|
13170
|
+
return widths;
|
|
13171
|
+
}
|
|
13172
|
+
function fitCell(value, width) {
|
|
13173
|
+
if (width <= 0) return "";
|
|
13174
|
+
if (value.length > width) {
|
|
13175
|
+
return `${value.slice(0, Math.max(0, width - 1))}\u2026`;
|
|
13176
|
+
}
|
|
13177
|
+
return value.padEnd(width);
|
|
13178
|
+
}
|
|
13179
|
+
function buildRows(items) {
|
|
13180
|
+
return items.map((item, index) => ({ item, index }));
|
|
12995
13181
|
}
|
|
12996
13182
|
function windowRows(rows, focus, max) {
|
|
12997
13183
|
if (rows.length <= max) {
|
|
12998
|
-
return { rows, start: 0, end: rows.length
|
|
13184
|
+
return { rows, start: 0, end: rows.length };
|
|
12999
13185
|
}
|
|
13000
13186
|
let start = focus - Math.floor(max / 2);
|
|
13001
13187
|
if (start < 0) start = 0;
|
|
@@ -13004,20 +13190,7 @@ function windowRows(rows, focus, max) {
|
|
|
13004
13190
|
end = rows.length;
|
|
13005
13191
|
start = end - max;
|
|
13006
13192
|
}
|
|
13007
|
-
|
|
13008
|
-
if (start > 0) {
|
|
13009
|
-
const first = rows[start];
|
|
13010
|
-
if (first && first.type === "item") {
|
|
13011
|
-
for (let i = start - 1; i >= 0; i--) {
|
|
13012
|
-
const r = rows[i];
|
|
13013
|
-
if (r && r.type === "header") {
|
|
13014
|
-
contextHeader = r.category;
|
|
13015
|
-
break;
|
|
13016
|
-
}
|
|
13017
|
-
}
|
|
13018
|
-
}
|
|
13019
|
-
}
|
|
13020
|
-
return { rows: rows.slice(start, end), start, end, contextHeader };
|
|
13193
|
+
return { rows: rows.slice(start, end), start, end };
|
|
13021
13194
|
}
|
|
13022
13195
|
function ToolsPicker({
|
|
13023
13196
|
items,
|
|
@@ -13028,6 +13201,8 @@ function ToolsPicker({
|
|
|
13028
13201
|
}) {
|
|
13029
13202
|
const { stdout } = useStdout();
|
|
13030
13203
|
const termRows = stdout?.rows ?? 24;
|
|
13204
|
+
const termColumns = stdout?.columns ?? 100;
|
|
13205
|
+
const columnWidths = columnWidthsFor(termColumns);
|
|
13031
13206
|
const maxVisible = Math.max(6, termRows - CHROME_ROWS5);
|
|
13032
13207
|
const total = items.length;
|
|
13033
13208
|
let visibleItems;
|
|
@@ -13047,51 +13222,31 @@ function ToolsPicker({
|
|
|
13047
13222
|
}
|
|
13048
13223
|
const rows = buildRows(visibleItems);
|
|
13049
13224
|
const enabledCount = items.filter((item) => item.enabled).length;
|
|
13050
|
-
const
|
|
13225
|
+
const passiveCount = total - enabledCount;
|
|
13051
13226
|
const selectedItem = visibleItems[visibleSelected];
|
|
13052
13227
|
let displayRows;
|
|
13053
13228
|
let hiddenAbove = 0;
|
|
13054
13229
|
let hiddenBelow = 0;
|
|
13055
|
-
let contextHeader = null;
|
|
13056
13230
|
if (filterActive) {
|
|
13057
13231
|
displayRows = rows;
|
|
13058
13232
|
} else {
|
|
13059
|
-
const
|
|
13060
|
-
(r) => r.type === "item" && r.index === visibleSelected
|
|
13061
|
-
);
|
|
13062
|
-
const win = windowRows(
|
|
13063
|
-
rows,
|
|
13064
|
-
selectedRowIdx < 0 ? 0 : selectedRowIdx,
|
|
13065
|
-
maxVisible
|
|
13066
|
-
);
|
|
13233
|
+
const win = windowRows(rows, visibleSelected, maxVisible);
|
|
13067
13234
|
displayRows = win.rows;
|
|
13068
13235
|
hiddenAbove = win.start;
|
|
13069
13236
|
hiddenBelow = rows.length - win.end;
|
|
13070
|
-
contextHeader = win.contextHeader;
|
|
13071
13237
|
}
|
|
13072
13238
|
const hasFilter = filterActive;
|
|
13073
13239
|
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", borderStyle: "round", borderColor: "green", paddingX: 1, children: [
|
|
13074
13240
|
/* @__PURE__ */ jsx(Text, { bold: true, color: "green", children: "\u2501\u2501 Tools \u2501\u2501" }),
|
|
13075
|
-
/* @__PURE__ */ jsx(Text, { dimColor: true, children: hasFilter ? `Filter: ${filter} (${visibleItems.length} match${visibleItems.length === 1 ? "" : "es"}) \xB7 Backspace edit \xB7 Esc clear` : `\u2191/\u2193 select \xB7 type to filter \xB7 Enter toggles \xB7 Esc close \xB7 ${
|
|
13076
|
-
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "
|
|
13241
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: hasFilter ? `Filter: ${filter} (${visibleItems.length} match${visibleItems.length === 1 ? "" : "es"}) \xB7 Backspace edit \xB7 Esc clear` : `\u2191/\u2193 select \xB7 type to filter \xB7 Enter toggles \xB7 Esc close \xB7 ${enabledCount} active / ${passiveCount} passive` }),
|
|
13242
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "Passive tools stay listed for this session so you can select them and re-enable them later." }),
|
|
13077
13243
|
/* @__PURE__ */ jsx(Box, { marginTop: 1, flexDirection: "column", children: total === 0 ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: busy ? "Loading tools\u2026" : "No tools registered." }) : visibleItems.length === 0 ? /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
13078
13244
|
'No tools match "',
|
|
13079
13245
|
filter,
|
|
13080
13246
|
'".'
|
|
13081
13247
|
] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
13082
13248
|
hiddenAbove > 0 && !hasFilter ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: ` \u2191 ${hiddenAbove} more` }) : null,
|
|
13083
|
-
|
|
13084
|
-
" ",
|
|
13085
|
-
contextHeader
|
|
13086
|
-
] }) : null,
|
|
13087
|
-
displayRows.map((row) => {
|
|
13088
|
-
if (row.type === "header") {
|
|
13089
|
-
return /* @__PURE__ */ jsxs(Text, { bold: true, color: "yellow", dimColor: true, children: [
|
|
13090
|
-
" ",
|
|
13091
|
-
row.category
|
|
13092
|
-
] }, `cat-${row.category}`);
|
|
13093
|
-
}
|
|
13094
|
-
const { item, index } = row;
|
|
13249
|
+
displayRows.map(({ item, index }) => {
|
|
13095
13250
|
const focused = index === visibleSelected;
|
|
13096
13251
|
return /* @__PURE__ */ jsxs(
|
|
13097
13252
|
Text,
|
|
@@ -13103,14 +13258,17 @@ function ToolsPicker({
|
|
|
13103
13258
|
focused ? "\u203A " : " ",
|
|
13104
13259
|
statusBadge2(item.enabled),
|
|
13105
13260
|
" ",
|
|
13106
|
-
/* @__PURE__ */ jsx(Text, { bold: true, children: item.name.
|
|
13261
|
+
/* @__PURE__ */ jsx(Text, { bold: true, children: fitCell(item.name, columnWidths.name) }),
|
|
13262
|
+
" ",
|
|
13107
13263
|
/* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
13108
|
-
|
|
13109
|
-
rwBadge(item.mutating),
|
|
13264
|
+
fitCell(displayCategory(item.category), columnWidths.category),
|
|
13110
13265
|
" ",
|
|
13266
|
+
fitCell(`[${item.owner}]`, columnWidths.owner),
|
|
13267
|
+
" ",
|
|
13268
|
+
rwBadge(item.mutating),
|
|
13111
13269
|
" ",
|
|
13112
|
-
item.permission.padEnd(6),
|
|
13113
13270
|
" ",
|
|
13271
|
+
fitCell(item.permission, columnWidths.permission),
|
|
13114
13272
|
" ",
|
|
13115
13273
|
/* @__PURE__ */ jsxs(Text, { color: item.descMode === "simple" ? "yellow" : void 0, children: [
|
|
13116
13274
|
"desc:",
|
|
@@ -13961,6 +14119,7 @@ function SessionsPanel({
|
|
|
13961
14119
|
var MAX_VISIBLE_ITEMS = 8;
|
|
13962
14120
|
function SlashMenu({ query, matches, selected }) {
|
|
13963
14121
|
const placeholder = query ? `/${query}` : "/";
|
|
14122
|
+
const resultMeta = matches.length > 0 ? `${selected + 1}/${matches.length}` : "no matches";
|
|
13964
14123
|
const rows = [];
|
|
13965
14124
|
let lastCategory = "";
|
|
13966
14125
|
for (let i = 0; i < matches.length; i++) {
|
|
@@ -13975,12 +14134,18 @@ function SlashMenu({ query, matches, selected }) {
|
|
|
13975
14134
|
const visible = windowRows3(rows, selectedRowIdx < 0 ? 0 : selectedRowIdx, MAX_VISIBLE_ITEMS);
|
|
13976
14135
|
const hiddenAbove = visible.start;
|
|
13977
14136
|
const hiddenBelow = rows.length - visible.end;
|
|
13978
|
-
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", children: [
|
|
13979
|
-
/* @__PURE__ */ jsxs(Text, {
|
|
13980
|
-
|
|
14137
|
+
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", borderStyle: "round", borderColor: "cyan", paddingX: 1, children: [
|
|
14138
|
+
/* @__PURE__ */ jsxs(Text, { bold: true, color: "cyan", children: [
|
|
14139
|
+
"\u2501\u2501 Command palette \u2501\u2501 ",
|
|
14140
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: placeholder }),
|
|
13981
14141
|
" ",
|
|
13982
|
-
|
|
14142
|
+
/* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
14143
|
+
"(",
|
|
14144
|
+
resultMeta,
|
|
14145
|
+
")"
|
|
14146
|
+
] })
|
|
13983
14147
|
] }),
|
|
14148
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "Type to filter commands by name, alias, or description." }),
|
|
13984
14149
|
hiddenAbove > 0 && /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
13985
14150
|
" \u2191 ",
|
|
13986
14151
|
hiddenAbove,
|
|
@@ -14418,6 +14583,79 @@ function runGit(cwd, args) {
|
|
|
14418
14583
|
});
|
|
14419
14584
|
}
|
|
14420
14585
|
|
|
14586
|
+
// src/rehydrate-history.ts
|
|
14587
|
+
function contentBlocksText(content) {
|
|
14588
|
+
if (typeof content === "string") return content;
|
|
14589
|
+
if (!Array.isArray(content)) return "";
|
|
14590
|
+
return content.filter(
|
|
14591
|
+
(block) => !!block && typeof block === "object" && block.type === "text" && typeof block.text === "string"
|
|
14592
|
+
).map((block) => block.text).join("");
|
|
14593
|
+
}
|
|
14594
|
+
function rehydrateHistory(messages, startId, toolCalls) {
|
|
14595
|
+
const entries = [];
|
|
14596
|
+
const toolCallsById = /* @__PURE__ */ new Map();
|
|
14597
|
+
if (toolCalls) {
|
|
14598
|
+
for (const tc of toolCalls) {
|
|
14599
|
+
if (!toolCallsById.has(tc.id)) toolCallsById.set(tc.id, tc);
|
|
14600
|
+
}
|
|
14601
|
+
}
|
|
14602
|
+
const consumed = /* @__PURE__ */ new Set();
|
|
14603
|
+
const fallback = [];
|
|
14604
|
+
let nextId = startId;
|
|
14605
|
+
const textOf = (msg) => contentBlocksText(msg.content);
|
|
14606
|
+
const toolEntryFor = (tc) => ({
|
|
14607
|
+
id: nextId++,
|
|
14608
|
+
kind: "tool",
|
|
14609
|
+
name: tc.name,
|
|
14610
|
+
durationMs: tc.durationMs,
|
|
14611
|
+
ok: tc.ok,
|
|
14612
|
+
outputBytes: tc.outputBytes,
|
|
14613
|
+
outputTokens: tc.outputTokens,
|
|
14614
|
+
outputLines: tc.outputLines
|
|
14615
|
+
});
|
|
14616
|
+
const pushAssistantText = (parts) => {
|
|
14617
|
+
const text = parts.join("").trim();
|
|
14618
|
+
if (text) entries.push({ id: nextId++, kind: "assistant", text });
|
|
14619
|
+
parts.length = 0;
|
|
14620
|
+
};
|
|
14621
|
+
for (const msg of messages) {
|
|
14622
|
+
if (msg.role === "system") continue;
|
|
14623
|
+
if (msg.role === "user") {
|
|
14624
|
+
const text = textOf(msg).trim();
|
|
14625
|
+
if (text) entries.push({ id: nextId++, kind: "user", text });
|
|
14626
|
+
continue;
|
|
14627
|
+
}
|
|
14628
|
+
if (msg.role === "assistant") {
|
|
14629
|
+
if (!Array.isArray(msg.content)) {
|
|
14630
|
+
const text = textOf(msg).trim();
|
|
14631
|
+
if (text) entries.push({ id: nextId++, kind: "assistant", text });
|
|
14632
|
+
continue;
|
|
14633
|
+
}
|
|
14634
|
+
const textParts = [];
|
|
14635
|
+
for (const block of msg.content) {
|
|
14636
|
+
if (block.type === "text") {
|
|
14637
|
+
textParts.push(block.text);
|
|
14638
|
+
continue;
|
|
14639
|
+
}
|
|
14640
|
+
if (block.type !== "tool_use") continue;
|
|
14641
|
+
pushAssistantText(textParts);
|
|
14642
|
+
const tc = toolCallsById.get(block.id);
|
|
14643
|
+
if (!tc) continue;
|
|
14644
|
+
entries.push(toolEntryFor(tc));
|
|
14645
|
+
consumed.add(block.id);
|
|
14646
|
+
}
|
|
14647
|
+
pushAssistantText(textParts);
|
|
14648
|
+
}
|
|
14649
|
+
}
|
|
14650
|
+
if (toolCalls) {
|
|
14651
|
+
for (const tc of toolCalls) {
|
|
14652
|
+
if (!consumed.has(tc.id)) fallback.push(toolEntryFor(tc));
|
|
14653
|
+
}
|
|
14654
|
+
}
|
|
14655
|
+
entries.push(...fallback);
|
|
14656
|
+
return entries;
|
|
14657
|
+
}
|
|
14658
|
+
|
|
14421
14659
|
// src/app-initial-state.ts
|
|
14422
14660
|
function buildRestoredEntries(messages, restoredToolCalls) {
|
|
14423
14661
|
if (!messages || messages.length === 0) return [];
|
|
@@ -14573,9 +14811,11 @@ function createInitialState(options) {
|
|
|
14573
14811
|
},
|
|
14574
14812
|
fKeyPicker: { open: false, selected: 0 },
|
|
14575
14813
|
confirmQueue: [],
|
|
14814
|
+
shellCommandWarning: null,
|
|
14576
14815
|
enhance: null,
|
|
14577
14816
|
enhanceEnabled,
|
|
14578
14817
|
enhanceBusy: false,
|
|
14818
|
+
continueConfirm: null,
|
|
14579
14819
|
escConfirm: null,
|
|
14580
14820
|
sendModePicker: null,
|
|
14581
14821
|
contextChipVersion: 0,
|
|
@@ -15670,6 +15910,7 @@ function usePasteHandling({
|
|
|
15670
15910
|
};
|
|
15671
15911
|
}
|
|
15672
15912
|
var ENTER_DOUBLE_TAP_MS = 50;
|
|
15913
|
+
var formatTokens = (tokens) => tokens.toLocaleString("en-US");
|
|
15673
15914
|
function debouncedEnter(host) {
|
|
15674
15915
|
const now = Date.now();
|
|
15675
15916
|
if (now - host.lastEnterAtRef.current < ENTER_DOUBLE_TAP_MS) return true;
|
|
@@ -15828,12 +16069,16 @@ function usePickerKeys(host) {
|
|
|
15828
16069
|
dispatch({ type: "modelPickerHint", text: err });
|
|
15829
16070
|
return;
|
|
15830
16071
|
}
|
|
16072
|
+
const previousMaxContext = host.activeMaxContext;
|
|
16073
|
+
const nextMaxContext = host.getAgentCtxMaxContext();
|
|
15831
16074
|
host.setLiveProvider?.(providerId);
|
|
15832
16075
|
host.setLiveModel?.(modelId);
|
|
15833
|
-
host.setActiveMaxContext?.(
|
|
16076
|
+
host.setActiveMaxContext?.(nextMaxContext);
|
|
16077
|
+
const contextWarning = previousMaxContext && nextMaxContext > 0 && nextMaxContext < previousMaxContext ? `
|
|
16078
|
+
\u26A0 smaller context window: ${formatTokens(previousMaxContext)} \u2192 ${formatTokens(nextMaxContext)} tokens${host.currentContextTokens > 0 ? `; current request \u2248 ${formatTokens(host.currentContextTokens)} tokens (${Math.round(host.currentContextTokens / nextMaxContext * 100)}% of new window)` : ""}` : "";
|
|
15834
16079
|
dispatch({
|
|
15835
16080
|
type: "addEntry",
|
|
15836
|
-
entry: { kind: "info", text: `Switched to ${providerId} / ${modelId}
|
|
16081
|
+
entry: { kind: "info", text: `Switched to ${providerId} / ${modelId}.${contextWarning}` }
|
|
15837
16082
|
});
|
|
15838
16083
|
dispatch({ type: "modelPickerClose" });
|
|
15839
16084
|
};
|
|
@@ -17744,78 +17989,8 @@ function selectedSlashCommandLine(picker) {
|
|
|
17744
17989
|
const picked = picker.matches[picker.selected];
|
|
17745
17990
|
return picked ? `/${picked.name}` : null;
|
|
17746
17991
|
}
|
|
17747
|
-
function contentBlocksText(content) {
|
|
17748
|
-
if (typeof content === "string") return content;
|
|
17749
|
-
if (!Array.isArray(content)) return "";
|
|
17750
|
-
return content.filter(
|
|
17751
|
-
(block) => !!block && typeof block === "object" && block.type === "text" && typeof block.text === "string"
|
|
17752
|
-
).map((block) => block.text).join("");
|
|
17753
|
-
}
|
|
17754
|
-
function rehydrateHistory(messages, startId, toolCalls) {
|
|
17755
|
-
const entries = [];
|
|
17756
|
-
const toolCallsById = /* @__PURE__ */ new Map();
|
|
17757
|
-
if (toolCalls) {
|
|
17758
|
-
for (const tc of toolCalls) {
|
|
17759
|
-
if (!toolCallsById.has(tc.id)) toolCallsById.set(tc.id, tc);
|
|
17760
|
-
}
|
|
17761
|
-
}
|
|
17762
|
-
const consumed = /* @__PURE__ */ new Set();
|
|
17763
|
-
const fallback = [];
|
|
17764
|
-
let nextId = startId;
|
|
17765
|
-
const textOf = (msg) => contentBlocksText(msg.content);
|
|
17766
|
-
const toolEntryFor = (tc) => ({
|
|
17767
|
-
id: nextId++,
|
|
17768
|
-
kind: "tool",
|
|
17769
|
-
name: tc.name,
|
|
17770
|
-
durationMs: tc.durationMs,
|
|
17771
|
-
ok: tc.ok,
|
|
17772
|
-
outputBytes: tc.outputBytes,
|
|
17773
|
-
outputTokens: tc.outputTokens,
|
|
17774
|
-
outputLines: tc.outputLines
|
|
17775
|
-
});
|
|
17776
|
-
const pushAssistantText = (parts) => {
|
|
17777
|
-
const text = parts.join("").trim();
|
|
17778
|
-
if (text) entries.push({ id: nextId++, kind: "assistant", text });
|
|
17779
|
-
parts.length = 0;
|
|
17780
|
-
};
|
|
17781
|
-
for (const msg of messages) {
|
|
17782
|
-
if (msg.role === "system") continue;
|
|
17783
|
-
if (msg.role === "user") {
|
|
17784
|
-
const text = textOf(msg).trim();
|
|
17785
|
-
if (text) entries.push({ id: nextId++, kind: "user", text });
|
|
17786
|
-
continue;
|
|
17787
|
-
}
|
|
17788
|
-
if (msg.role === "assistant") {
|
|
17789
|
-
if (!Array.isArray(msg.content)) {
|
|
17790
|
-
const text = textOf(msg).trim();
|
|
17791
|
-
if (text) entries.push({ id: nextId++, kind: "assistant", text });
|
|
17792
|
-
continue;
|
|
17793
|
-
}
|
|
17794
|
-
const textParts = [];
|
|
17795
|
-
for (const block of msg.content) {
|
|
17796
|
-
if (block.type === "text") {
|
|
17797
|
-
textParts.push(block.text);
|
|
17798
|
-
continue;
|
|
17799
|
-
}
|
|
17800
|
-
if (block.type !== "tool_use") continue;
|
|
17801
|
-
pushAssistantText(textParts);
|
|
17802
|
-
const tc = toolCallsById.get(block.id);
|
|
17803
|
-
if (!tc) continue;
|
|
17804
|
-
entries.push(toolEntryFor(tc));
|
|
17805
|
-
consumed.add(block.id);
|
|
17806
|
-
}
|
|
17807
|
-
pushAssistantText(textParts);
|
|
17808
|
-
}
|
|
17809
|
-
}
|
|
17810
|
-
if (toolCalls) {
|
|
17811
|
-
for (const tc of toolCalls) {
|
|
17812
|
-
if (!consumed.has(tc.id)) fallback.push(toolEntryFor(tc));
|
|
17813
|
-
}
|
|
17814
|
-
}
|
|
17815
|
-
entries.push(...fallback);
|
|
17816
|
-
return entries;
|
|
17817
|
-
}
|
|
17818
17992
|
var PASTE_THRESHOLD_CHARS = 200;
|
|
17993
|
+
var CONTINUE_CONFIRM_DELAY_MS = 4e3;
|
|
17819
17994
|
var SB_PADX2 = 2;
|
|
17820
17995
|
function sddLifecycleEntry(op, r) {
|
|
17821
17996
|
if (typeof r === "number") {
|
|
@@ -17991,6 +18166,10 @@ function App({
|
|
|
17991
18166
|
});
|
|
17992
18167
|
const hiddenItemsRef = useRef(hiddenItems);
|
|
17993
18168
|
hiddenItemsRef.current = hiddenItems;
|
|
18169
|
+
const [liveToolCount, setLiveToolCount] = useState(toolCount);
|
|
18170
|
+
useEffect(() => {
|
|
18171
|
+
setLiveToolCount(toolCount);
|
|
18172
|
+
}, [toolCount]);
|
|
17994
18173
|
const prevBranchRef = useRef(null);
|
|
17995
18174
|
const [indexState, setIndexState] = useState(() => getIndexState());
|
|
17996
18175
|
useEffect(() => {
|
|
@@ -18090,19 +18269,19 @@ function App({
|
|
|
18090
18269
|
});
|
|
18091
18270
|
const { openPromptPicker } = usePromptPicker({ projectRoot, dispatch });
|
|
18092
18271
|
const { openModePicker } = useModePicker({ dispatch, getModes });
|
|
18093
|
-
const openBrainPanel =
|
|
18272
|
+
const openBrainPanel = React7.useCallback(() => {
|
|
18094
18273
|
if (!getBrainData) return;
|
|
18095
18274
|
const data = getBrainData();
|
|
18096
18275
|
dispatch({ type: "brainOpen", riskLevel: data.riskLevel, log: data.log });
|
|
18097
18276
|
}, [getBrainData]);
|
|
18098
|
-
const changeBrainRisk =
|
|
18277
|
+
const changeBrainRisk = React7.useCallback(
|
|
18099
18278
|
(delta) => {
|
|
18100
18279
|
dispatch({ type: "brainRiskChange", delta });
|
|
18101
18280
|
},
|
|
18102
18281
|
[]
|
|
18103
18282
|
);
|
|
18104
|
-
const prevRiskRef =
|
|
18105
|
-
|
|
18283
|
+
const prevRiskRef = React7.useRef(state.brainPanel.riskLevel);
|
|
18284
|
+
React7.useEffect(() => {
|
|
18106
18285
|
if (!state.brainPanel.open) return;
|
|
18107
18286
|
const current = state.brainPanel.riskLevel;
|
|
18108
18287
|
if (current !== prevRiskRef.current && onBrainRiskLevel) {
|
|
@@ -18112,12 +18291,12 @@ function App({
|
|
|
18112
18291
|
else dispatch({ type: "brainHint", text: `Risk ceiling \u2192 ${current.toUpperCase()}` });
|
|
18113
18292
|
}
|
|
18114
18293
|
}, [state.brainPanel.riskLevel, state.brainPanel.open, onBrainRiskLevel]);
|
|
18115
|
-
const openShadowPanel =
|
|
18294
|
+
const openShadowPanel = React7.useCallback(() => {
|
|
18116
18295
|
if (!getShadowData) return;
|
|
18117
18296
|
const data = getShadowData();
|
|
18118
18297
|
dispatch({ type: "shadowOpen", shadow: data });
|
|
18119
18298
|
}, [getShadowData]);
|
|
18120
|
-
const handleShadowStart =
|
|
18299
|
+
const handleShadowStart = React7.useCallback(async () => {
|
|
18121
18300
|
if (!onShadowStart) return;
|
|
18122
18301
|
dispatch({ type: "shadowHint", text: "Starting Shadow Agent\u2026" });
|
|
18123
18302
|
try {
|
|
@@ -18131,7 +18310,7 @@ function App({
|
|
|
18131
18310
|
dispatch({ type: "shadowHint", text: `Failed to start: ${toErrorMessage(e)}` });
|
|
18132
18311
|
}
|
|
18133
18312
|
}, [onShadowStart, getShadowData]);
|
|
18134
|
-
const handleShadowStop =
|
|
18313
|
+
const handleShadowStop = React7.useCallback(async () => {
|
|
18135
18314
|
if (!onShadowStop) return;
|
|
18136
18315
|
dispatch({ type: "shadowHint", text: "Stopping Shadow Agent\u2026" });
|
|
18137
18316
|
try {
|
|
@@ -18145,7 +18324,7 @@ function App({
|
|
|
18145
18324
|
dispatch({ type: "shadowHint", text: `Failed to stop: ${toErrorMessage(e)}` });
|
|
18146
18325
|
}
|
|
18147
18326
|
}, [onShadowStop, getShadowData]);
|
|
18148
|
-
const openHelpPanel =
|
|
18327
|
+
const openHelpPanel = React7.useCallback(() => {
|
|
18149
18328
|
const entries = Array.from(slashRegistry.listWithOwner()).map(({ cmd, owner }) => ({
|
|
18150
18329
|
name: owner === "core" ? cmd.name : `${owner}:${cmd.name}`,
|
|
18151
18330
|
description: cmd.description,
|
|
@@ -18177,7 +18356,7 @@ function App({
|
|
|
18177
18356
|
const inputGateRef = useRef(false);
|
|
18178
18357
|
const lastEnterAtRef = useRef(0);
|
|
18179
18358
|
const tokenPreviewsRef = useRef(/* @__PURE__ */ new Map());
|
|
18180
|
-
const projectName =
|
|
18359
|
+
const projectName = React7.useMemo(() => {
|
|
18181
18360
|
const base = path9.basename(projectRoot);
|
|
18182
18361
|
return base && base !== path9.sep ? base : void 0;
|
|
18183
18362
|
}, [projectRoot]);
|
|
@@ -18282,7 +18461,7 @@ function App({
|
|
|
18282
18461
|
}
|
|
18283
18462
|
});
|
|
18284
18463
|
const handleKeyRef = useRef(null);
|
|
18285
|
-
const handleRewindTo =
|
|
18464
|
+
const handleRewindTo = React7.useCallback(
|
|
18286
18465
|
async (checkpointIndex) => {
|
|
18287
18466
|
const sessionId = agent.ctx.session.id;
|
|
18288
18467
|
if (!sessionId) return;
|
|
@@ -18304,7 +18483,7 @@ function App({
|
|
|
18304
18483
|
dispatch({ type: "clearInput" });
|
|
18305
18484
|
};
|
|
18306
18485
|
const startedAtRef = useRef(Date.now());
|
|
18307
|
-
const [nowTick, setNowTick] =
|
|
18486
|
+
const [nowTick, setNowTick] = React7.useState(Date.now());
|
|
18308
18487
|
useEffect(() => {
|
|
18309
18488
|
const t = setInterval(() => setNowTick(Date.now()), 1e4);
|
|
18310
18489
|
return () => clearInterval(t);
|
|
@@ -18390,7 +18569,7 @@ function App({
|
|
|
18390
18569
|
agent.ctx.provider,
|
|
18391
18570
|
agent.ctx.todos
|
|
18392
18571
|
]);
|
|
18393
|
-
const [gitInfo, setGitInfo] =
|
|
18572
|
+
const [gitInfo, setGitInfo] = React7.useState(null);
|
|
18394
18573
|
useEffect(() => {
|
|
18395
18574
|
let cancelled = false;
|
|
18396
18575
|
const refresh = () => {
|
|
@@ -18718,8 +18897,8 @@ function App({
|
|
|
18718
18897
|
} catch {
|
|
18719
18898
|
}
|
|
18720
18899
|
}, []);
|
|
18721
|
-
|
|
18722
|
-
const anyOpenNow = state.picker.open || state.slashPicker.open || state.modelPicker.open || state.autonomyPicker.open || state.designPicker.open || state.resumePicker.open || state.settingsPicker.open || state.enhanceBusy || state.enhance != null || state.coordinator.monitorOpen || state.escConfirm != null || state.sendModePicker != null || state.confirmQueue.length > 0;
|
|
18900
|
+
React7.useLayoutEffect(() => {
|
|
18901
|
+
const anyOpenNow = state.picker.open || state.slashPicker.open || state.modelPicker.open || state.autonomyPicker.open || state.designPicker.open || state.resumePicker.open || state.settingsPicker.open || state.enhanceBusy || state.enhance != null || state.continueConfirm != null || state.coordinator.monitorOpen || state.escConfirm != null || state.sendModePicker != null || state.confirmQueue.length > 0;
|
|
18723
18902
|
const overlayClosed = prevAnyOverlayOpen.current && !anyOpenNow;
|
|
18724
18903
|
const newEntryCommitted = state.entries.length > prevEntriesCount.current;
|
|
18725
18904
|
const curToolStreamLen = state.toolStream?.text.length ?? 0;
|
|
@@ -18739,6 +18918,7 @@ function App({
|
|
|
18739
18918
|
state.settingsPicker.open,
|
|
18740
18919
|
state.enhanceBusy,
|
|
18741
18920
|
state.enhance,
|
|
18921
|
+
state.continueConfirm,
|
|
18742
18922
|
state.coordinator.monitorOpen,
|
|
18743
18923
|
state.escConfirm,
|
|
18744
18924
|
state.sendModePicker,
|
|
@@ -18871,8 +19051,9 @@ function App({
|
|
|
18871
19051
|
process.stdout.off("resize", handleResize);
|
|
18872
19052
|
};
|
|
18873
19053
|
}, [eraseLiveRegion]);
|
|
18874
|
-
|
|
18875
|
-
if (state.enhanceBusy || state.enhance != null
|
|
19054
|
+
React7.useLayoutEffect(() => {
|
|
19055
|
+
if (state.enhanceBusy || state.enhance != null || state.continueConfirm != null)
|
|
19056
|
+
eraseLiveRegion();
|
|
18876
19057
|
});
|
|
18877
19058
|
useEffect(() => {
|
|
18878
19059
|
const trimmed = state.buffer.trimStart();
|
|
@@ -19022,20 +19203,20 @@ function App({
|
|
|
19022
19203
|
slashRegistry.unregister("agents");
|
|
19023
19204
|
};
|
|
19024
19205
|
}, [slashRegistry]);
|
|
19025
|
-
const openModelPicker =
|
|
19206
|
+
const openModelPicker = React7.useCallback(async () => {
|
|
19026
19207
|
if (!getPickableProviders) return;
|
|
19027
19208
|
const providers = await getPickableProviders();
|
|
19028
19209
|
dispatch({ type: "modelPickerOpen", providers });
|
|
19029
19210
|
}, [getPickableProviders]);
|
|
19030
|
-
const openProjectPicker =
|
|
19211
|
+
const openProjectPicker = React7.useCallback(async () => {
|
|
19031
19212
|
if (!getProjectPickerItems) return;
|
|
19032
19213
|
const items = await getProjectPickerItems();
|
|
19033
19214
|
dispatch({ type: "projectPickerOpen", items });
|
|
19034
19215
|
}, [getProjectPickerItems]);
|
|
19035
|
-
const openFKeyPicker =
|
|
19216
|
+
const openFKeyPicker = React7.useCallback(() => {
|
|
19036
19217
|
dispatch({ type: "fKeyPickerOpen" });
|
|
19037
19218
|
}, [dispatch]);
|
|
19038
|
-
const loadLiveSessions =
|
|
19219
|
+
const loadLiveSessions = React7.useCallback(async () => {
|
|
19039
19220
|
if (!getLiveSessions) {
|
|
19040
19221
|
dispatch({ type: "sessionsPanelSet", sessions: [] });
|
|
19041
19222
|
return;
|
|
@@ -19082,7 +19263,7 @@ function App({
|
|
|
19082
19263
|
}, 5e3);
|
|
19083
19264
|
return () => clearInterval(t);
|
|
19084
19265
|
}, [state.sessionsPanelOpen, getLiveSessions, loadLiveSessions]);
|
|
19085
|
-
const openSettings =
|
|
19266
|
+
const openSettings = React7.useCallback(() => {
|
|
19086
19267
|
if (!getSettings) return;
|
|
19087
19268
|
const s2 = getSettings();
|
|
19088
19269
|
dispatch({
|
|
@@ -19127,7 +19308,7 @@ function App({
|
|
|
19127
19308
|
animationStyle: s2.animationStyle ?? "rainbow"
|
|
19128
19309
|
});
|
|
19129
19310
|
}, [getSettings]);
|
|
19130
|
-
const refreshPluginPicker =
|
|
19311
|
+
const refreshPluginPicker = React7.useCallback(() => {
|
|
19131
19312
|
if (!getPluginItems) return;
|
|
19132
19313
|
dispatch({ type: "pluginPickerSetItems", items: getPluginItems() });
|
|
19133
19314
|
}, [getPluginItems]);
|
|
@@ -19135,7 +19316,7 @@ function App({
|
|
|
19135
19316
|
if (!state.pluginPicker.open) return;
|
|
19136
19317
|
refreshPluginPicker();
|
|
19137
19318
|
}, [state.pluginPicker.open, refreshPluginPicker]);
|
|
19138
|
-
const toggleSelectedPlugin =
|
|
19319
|
+
const toggleSelectedPlugin = React7.useCallback(async () => {
|
|
19139
19320
|
if (!onPluginToggle) return;
|
|
19140
19321
|
const selected = stateRef.current.pluginPicker.items[stateRef.current.pluginPicker.selected];
|
|
19141
19322
|
if (!selected) return;
|
|
@@ -19159,7 +19340,7 @@ function App({
|
|
|
19159
19340
|
});
|
|
19160
19341
|
}
|
|
19161
19342
|
}, [onPluginToggle]);
|
|
19162
|
-
const refreshMcpPicker =
|
|
19343
|
+
const refreshMcpPicker = React7.useCallback(() => {
|
|
19163
19344
|
if (!getMcpServers) return;
|
|
19164
19345
|
dispatch({ type: "mcpPickerSetItems", items: getMcpServers() });
|
|
19165
19346
|
}, [getMcpServers]);
|
|
@@ -19167,7 +19348,7 @@ function App({
|
|
|
19167
19348
|
if (!state.mcpPicker.open) return;
|
|
19168
19349
|
refreshMcpPicker();
|
|
19169
19350
|
}, [state.mcpPicker.open, refreshMcpPicker]);
|
|
19170
|
-
const toggleSelectedMcpServer =
|
|
19351
|
+
const toggleSelectedMcpServer = React7.useCallback(async () => {
|
|
19171
19352
|
if (!onMcpToggle) return;
|
|
19172
19353
|
const selected = stateRef.current.mcpPicker.items[stateRef.current.mcpPicker.selected];
|
|
19173
19354
|
if (!selected) return;
|
|
@@ -19184,7 +19365,7 @@ function App({
|
|
|
19184
19365
|
});
|
|
19185
19366
|
}
|
|
19186
19367
|
}, [onMcpToggle]);
|
|
19187
|
-
const restartSelectedMcpServer =
|
|
19368
|
+
const restartSelectedMcpServer = React7.useCallback(async () => {
|
|
19188
19369
|
if (!onMcpRestart) return;
|
|
19189
19370
|
const selected = stateRef.current.mcpPicker.items[stateRef.current.mcpPicker.selected];
|
|
19190
19371
|
if (!selected) return;
|
|
@@ -19201,15 +19382,17 @@ function App({
|
|
|
19201
19382
|
});
|
|
19202
19383
|
}
|
|
19203
19384
|
}, [onMcpRestart]);
|
|
19204
|
-
const refreshToolsPicker =
|
|
19385
|
+
const refreshToolsPicker = React7.useCallback(() => {
|
|
19205
19386
|
if (!getToolsItems) return;
|
|
19206
|
-
|
|
19387
|
+
const items = getToolsItems();
|
|
19388
|
+
dispatch({ type: "toolsPickerSetItems", items });
|
|
19389
|
+
setLiveToolCount(items.filter((item) => item.enabled).length);
|
|
19207
19390
|
}, [getToolsItems]);
|
|
19208
19391
|
useEffect(() => {
|
|
19209
19392
|
if (!state.toolsPicker.open) return;
|
|
19210
19393
|
refreshToolsPicker();
|
|
19211
19394
|
}, [state.toolsPicker.open, refreshToolsPicker]);
|
|
19212
|
-
const toggleSelectedTool =
|
|
19395
|
+
const toggleSelectedTool = React7.useCallback(async () => {
|
|
19213
19396
|
if (!onToolToggle) return;
|
|
19214
19397
|
const selected = stateRef.current.toolsPicker.items[stateRef.current.toolsPicker.selected];
|
|
19215
19398
|
if (!selected) return;
|
|
@@ -19217,6 +19400,7 @@ function App({
|
|
|
19217
19400
|
try {
|
|
19218
19401
|
const result = await onToolToggle(selected.name);
|
|
19219
19402
|
dispatch({ type: "toolsPickerSetItems", items: result.items });
|
|
19403
|
+
setLiveToolCount(result.items.filter((item) => item.enabled).length);
|
|
19220
19404
|
dispatch({ type: "toolsPickerHint", text: result.error ?? result.message });
|
|
19221
19405
|
} catch (err) {
|
|
19222
19406
|
dispatch({ type: "toolsPickerBusy", busy: false });
|
|
@@ -19241,7 +19425,7 @@ function App({
|
|
|
19241
19425
|
nextStepsAutoSubmitSuggestionRef.current = null;
|
|
19242
19426
|
return;
|
|
19243
19427
|
}
|
|
19244
|
-
if (state.enhance != null || state.enhanceBusy) {
|
|
19428
|
+
if (state.enhance != null || state.enhanceBusy || state.continueConfirm != null) {
|
|
19245
19429
|
return;
|
|
19246
19430
|
}
|
|
19247
19431
|
if (nextStepsAutoSubmitTimerRef.current != null) {
|
|
@@ -19322,6 +19506,7 @@ function App({
|
|
|
19322
19506
|
autonomyLive,
|
|
19323
19507
|
state.enhance,
|
|
19324
19508
|
state.enhanceBusy,
|
|
19509
|
+
state.continueConfirm,
|
|
19325
19510
|
nextStepsRecheck,
|
|
19326
19511
|
getSettings,
|
|
19327
19512
|
getSuggestions,
|
|
@@ -19879,11 +20064,14 @@ Available chords:
|
|
|
19879
20064
|
});
|
|
19880
20065
|
});
|
|
19881
20066
|
const offFallback = events.on("provider.fallback", (e) => {
|
|
20067
|
+
const fallbackEvent = e;
|
|
20068
|
+
const contextWarning = fallbackEvent.contextWindowWarning ? `
|
|
20069
|
+
\u26A0 smaller context window: ${fallbackEvent.contextWindowWarning.fromMaxContext.toLocaleString("en-US")} \u2192 ${fallbackEvent.contextWindowWarning.toMaxContext.toLocaleString("en-US")} tokens${fallbackEvent.contextWindowWarning.currentTokens ? `; current request \u2248 ${fallbackEvent.contextWindowWarning.currentTokens.toLocaleString("en-US")} tokens (${Math.round(fallbackEvent.contextWindowWarning.currentTokens / fallbackEvent.contextWindowWarning.toMaxContext * 100)}% of new window)` : ""}` : "";
|
|
19882
20070
|
dispatch({
|
|
19883
20071
|
type: "addEntry",
|
|
19884
20072
|
entry: {
|
|
19885
20073
|
kind: "warn",
|
|
19886
|
-
text: `\u21BB rate-limited (${e.status}) \u2014 switched to ${e.to.providerId}/${e.to.model}`
|
|
20074
|
+
text: `\u21BB rate-limited (${e.status}) \u2014 switched to ${e.to.providerId}/${e.to.model}${contextWarning}`
|
|
19887
20075
|
}
|
|
19888
20076
|
});
|
|
19889
20077
|
});
|
|
@@ -20153,7 +20341,9 @@ Available chords:
|
|
|
20153
20341
|
setLiveProvider,
|
|
20154
20342
|
setLiveModel,
|
|
20155
20343
|
setActiveMaxContext,
|
|
20156
|
-
|
|
20344
|
+
getAgentCtxMaxContext: () => agent.ctx.provider.capabilities.maxContext,
|
|
20345
|
+
activeMaxContext,
|
|
20346
|
+
currentContextTokens,
|
|
20157
20347
|
switchAutonomy,
|
|
20158
20348
|
submit: (text) => submitRef.current(text),
|
|
20159
20349
|
onPromptPickerEnter: () => {
|
|
@@ -20487,11 +20677,13 @@ Available chords:
|
|
|
20487
20677
|
const handleKey = async (input, key) => {
|
|
20488
20678
|
if (state.status === "aborting" && !state.steeringPending && state.interrupts === 0) return;
|
|
20489
20679
|
if (state.confirmQueue.length > 0) return;
|
|
20680
|
+
if (state.shellCommandWarning) return;
|
|
20490
20681
|
if (state.enhanceBusy) {
|
|
20491
20682
|
if (key.escape) enhanceAbortRef.current?.abort();
|
|
20492
20683
|
return;
|
|
20493
20684
|
}
|
|
20494
20685
|
if (state.enhance) return;
|
|
20686
|
+
if (state.continueConfirm) return;
|
|
20495
20687
|
if (state.escConfirm) return;
|
|
20496
20688
|
if (state.sendModePicker) return;
|
|
20497
20689
|
if (state.helpOpen) {
|
|
@@ -21531,6 +21723,33 @@ Available chords:
|
|
|
21531
21723
|
await pasteClipboardImage();
|
|
21532
21724
|
return;
|
|
21533
21725
|
}
|
|
21726
|
+
if (trimmed.startsWith("!")) {
|
|
21727
|
+
const command = trimmed.slice(1).trim();
|
|
21728
|
+
if (!command) {
|
|
21729
|
+
dispatch({
|
|
21730
|
+
type: "addEntry",
|
|
21731
|
+
entry: { kind: "info", text: "Usage: !<shell command>" }
|
|
21732
|
+
});
|
|
21733
|
+
return;
|
|
21734
|
+
}
|
|
21735
|
+
const settings = getSettings?.();
|
|
21736
|
+
if (settings?.shellBangWarningDontShowAgain !== true) {
|
|
21737
|
+
const decision = await new Promise((resolve) => {
|
|
21738
|
+
dispatch({ type: "shellCommandWarningOpen", info: { command, resolve } });
|
|
21739
|
+
});
|
|
21740
|
+
dispatch({ type: "shellCommandWarningClose" });
|
|
21741
|
+
if (decision === "no") return;
|
|
21742
|
+
if (decision === "dont-show-again") {
|
|
21743
|
+
if (settings && saveSettings) {
|
|
21744
|
+
const err = await saveSettings({ ...settings, shellBangWarningDontShowAgain: true });
|
|
21745
|
+
if (err) {
|
|
21746
|
+
dispatch({ type: "addEntry", entry: { kind: "warn", text: err } });
|
|
21747
|
+
}
|
|
21748
|
+
}
|
|
21749
|
+
}
|
|
21750
|
+
}
|
|
21751
|
+
return submit(`/dev ${command}`);
|
|
21752
|
+
}
|
|
21534
21753
|
if (trimmed === "/prompt" || trimmed === "/prompts-browse") {
|
|
21535
21754
|
pushSubmittedHistory();
|
|
21536
21755
|
clearDraft();
|
|
@@ -21613,6 +21832,9 @@ ${content}
|
|
|
21613
21832
|
const currentMode = getModeLabel();
|
|
21614
21833
|
if (currentMode !== liveModeLabel) setLiveModeLabel(currentMode);
|
|
21615
21834
|
}
|
|
21835
|
+
if (getToolsItems) {
|
|
21836
|
+
setLiveToolCount(getToolsItems().filter((item) => item.enabled).length);
|
|
21837
|
+
}
|
|
21616
21838
|
if (res?.exit) {
|
|
21617
21839
|
exit();
|
|
21618
21840
|
onExit(0);
|
|
@@ -21650,6 +21872,10 @@ ${content}
|
|
|
21650
21872
|
const builder = builderRef.current;
|
|
21651
21873
|
if (!builder) return;
|
|
21652
21874
|
const steering = state.steeringPending;
|
|
21875
|
+
const continueResolved = !steering && state.status === "idle" && detectContinueIntent(trimmed) ? resolveContinuation({
|
|
21876
|
+
todos: agent.ctx.todos,
|
|
21877
|
+
suggestions: getSuggestions?.() ?? []
|
|
21878
|
+
}) : null;
|
|
21653
21879
|
let effectiveText = trimmed;
|
|
21654
21880
|
const chips = [];
|
|
21655
21881
|
let cleanText = trimmed;
|
|
@@ -21665,7 +21891,7 @@ ${content}
|
|
|
21665
21891
|
chips.length = 0;
|
|
21666
21892
|
}
|
|
21667
21893
|
}
|
|
21668
|
-
if (enhanceEnabledRef.current && state.status === "idle" && !steering && shouldEnhance(cleanText)) {
|
|
21894
|
+
if (enhanceEnabledRef.current && state.status === "idle" && !steering && !continueResolved && shouldEnhance(cleanText)) {
|
|
21669
21895
|
dispatch({ type: "enhanceBusy", on: true });
|
|
21670
21896
|
const ac = new AbortController();
|
|
21671
21897
|
enhanceAbortRef.current = ac;
|
|
@@ -21728,6 +21954,31 @@ ${content}
|
|
|
21728
21954
|
}
|
|
21729
21955
|
}
|
|
21730
21956
|
}
|
|
21957
|
+
if (continueResolved) {
|
|
21958
|
+
const decision = await new Promise((resolve) => {
|
|
21959
|
+
dispatch({
|
|
21960
|
+
type: "continueConfirmOpen",
|
|
21961
|
+
info: {
|
|
21962
|
+
label: continueResolved.label,
|
|
21963
|
+
instruction: continueResolved.text,
|
|
21964
|
+
source: continueResolved.source,
|
|
21965
|
+
grounded: continueResolved.source !== "open",
|
|
21966
|
+
resolve
|
|
21967
|
+
}
|
|
21968
|
+
});
|
|
21969
|
+
});
|
|
21970
|
+
dispatch({ type: "continueConfirmClose" });
|
|
21971
|
+
if (decision === "cancel") {
|
|
21972
|
+
clearDraft();
|
|
21973
|
+
return;
|
|
21974
|
+
}
|
|
21975
|
+
if (decision === "edit") {
|
|
21976
|
+
const seed = continueResolved.source === "open" ? "" : continueResolved.text;
|
|
21977
|
+
setDraft(seed, seed.length);
|
|
21978
|
+
return;
|
|
21979
|
+
}
|
|
21980
|
+
effectiveText = continueResolved.text;
|
|
21981
|
+
}
|
|
21731
21982
|
const sddContext = await getSDDContext?.();
|
|
21732
21983
|
if (sddContext && trimmed) {
|
|
21733
21984
|
builder.appendText(`[SDD SESSION ACTIVE]
|
|
@@ -21742,7 +21993,7 @@ User message:
|
|
|
21742
21993
|
builder.appendText(toAppend);
|
|
21743
21994
|
}
|
|
21744
21995
|
if (steering) dispatch({ type: "steerConsume" });
|
|
21745
|
-
const displayText = steering ? `\u21AF ${effectiveText}` : effectiveText;
|
|
21996
|
+
const displayText = continueResolved ? continueResolved.label : steering ? `\u21AF ${effectiveText}` : effectiveText;
|
|
21746
21997
|
const pasteParts = [];
|
|
21747
21998
|
for (const m of trimmed.matchAll(new RegExp(INLINE_TOKEN_SRC, "g"))) {
|
|
21748
21999
|
const token = m[0];
|
|
@@ -21873,7 +22124,7 @@ ${content}
|
|
|
21873
22124
|
stdout?.columns ?? 80
|
|
21874
22125
|
);
|
|
21875
22126
|
const inputHeight = Math.max(1, inputCellRows.length);
|
|
21876
|
-
const hideInput = enhanceActive || state.helpOpen || state.processListOpen || state.authPanel.open;
|
|
22127
|
+
const hideInput = enhanceActive || state.continueConfirm != null || state.helpOpen || state.processListOpen || state.authPanel.open;
|
|
21877
22128
|
const lowerFunctionPanelOpen = state.monitorOpen || state.agentsMonitorOpen || (state.autoPhase?.monitorOpen ?? false) || state.worktreeMonitorOpen || state.planPanelOpen || state.kanbanPanelOpen || state.todosMonitorOpen || state.queuePanelOpen || state.processListOpen || state.goalPanelOpen;
|
|
21878
22129
|
return /* @__PURE__ */ jsx(Box, { flexDirection: "column", children: /* @__PURE__ */ jsxs(Box, { flexDirection: "column", flexGrow: 1, flexShrink: 0, children: [
|
|
21879
22130
|
mouseMode ? /* @__PURE__ */ jsx(
|
|
@@ -22166,6 +22417,17 @@ ${content}
|
|
|
22166
22417
|
}
|
|
22167
22418
|
}
|
|
22168
22419
|
) }) : null,
|
|
22420
|
+
state.shellCommandWarning ? (() => {
|
|
22421
|
+
const info = state.shellCommandWarning;
|
|
22422
|
+
let resolved = false;
|
|
22423
|
+
const onDecision = (decision) => {
|
|
22424
|
+
if (resolved) return;
|
|
22425
|
+
resolved = true;
|
|
22426
|
+
info.resolve(decision);
|
|
22427
|
+
dispatch({ type: "shellCommandWarningClose" });
|
|
22428
|
+
};
|
|
22429
|
+
return /* @__PURE__ */ jsx(ShellCommandWarning, { command: info.command, onDecision });
|
|
22430
|
+
})() : null,
|
|
22169
22431
|
state.confirmQueue.length > 0 && (() => {
|
|
22170
22432
|
const head = expectDefined$1(state.confirmQueue[0]);
|
|
22171
22433
|
let resolved = false;
|
|
@@ -22287,6 +22549,26 @@ ${content}
|
|
|
22287
22549
|
}
|
|
22288
22550
|
);
|
|
22289
22551
|
})() : null,
|
|
22552
|
+
state.continueConfirm ? (() => {
|
|
22553
|
+
const info = state.continueConfirm;
|
|
22554
|
+
let resolved = false;
|
|
22555
|
+
const onDecision = (decision) => {
|
|
22556
|
+
if (resolved) return;
|
|
22557
|
+
resolved = true;
|
|
22558
|
+
info.resolve(decision);
|
|
22559
|
+
};
|
|
22560
|
+
return /* @__PURE__ */ jsx(
|
|
22561
|
+
ContinueConfirmPanel,
|
|
22562
|
+
{
|
|
22563
|
+
label: info.label,
|
|
22564
|
+
instruction: info.instruction,
|
|
22565
|
+
source: info.source,
|
|
22566
|
+
grounded: info.grounded,
|
|
22567
|
+
delayMs: CONTINUE_CONFIRM_DELAY_MS,
|
|
22568
|
+
onDecision
|
|
22569
|
+
}
|
|
22570
|
+
);
|
|
22571
|
+
})() : null,
|
|
22290
22572
|
/* @__PURE__ */ jsx(Box, { ref: statusBarWrapRef, flexDirection: "column", flexShrink: 0, children: /* @__PURE__ */ jsx(
|
|
22291
22573
|
StatusBar,
|
|
22292
22574
|
{
|
|
@@ -22337,7 +22619,7 @@ ${content}
|
|
|
22337
22619
|
sessionCount,
|
|
22338
22620
|
mailbox: mailboxStatus,
|
|
22339
22621
|
tokenSavingMode: liveSettings?.featureTokenSaving ?? tokenSavingMode,
|
|
22340
|
-
toolCount,
|
|
22622
|
+
toolCount: liveToolCount,
|
|
22341
22623
|
sideEffectCount: agent.ctx.sideEffects?.length ?? 0
|
|
22342
22624
|
}
|
|
22343
22625
|
) }),
|
|
@@ -22823,7 +23105,7 @@ async function runTui(opts) {
|
|
|
22823
23105
|
};
|
|
22824
23106
|
try {
|
|
22825
23107
|
instance = render(
|
|
22826
|
-
|
|
23108
|
+
React7.createElement(App, {
|
|
22827
23109
|
agent: opts.agent,
|
|
22828
23110
|
slashRegistry: opts.slashRegistry,
|
|
22829
23111
|
attachments: opts.attachments,
|