@botconnector/bccli 0.4.4 → 0.4.6
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/{acp-SWBX4TT6.js → acp-YGQXX2L7.js} +2 -2
- package/dist/{args-UCLW7NID.js → args-TFKRCKTY.js} +4 -4
- package/dist/{chunk-HQW4BROS.js → chunk-27REMLDV.js} +1 -1
- package/dist/{chunk-OZ5GHMTN.js → chunk-2Y6TH4MA.js} +4 -4
- package/dist/{chunk-TGGKACSE.js → chunk-3JQZ2IKV.js} +3 -3
- package/dist/{chunk-3I5BW3ZT.js → chunk-6EGQI6HJ.js} +1 -1
- package/dist/{chunk-RX4UQX43.js → chunk-AK6TWKET.js} +1 -1
- package/dist/{chunk-FI7RUJRX.js → chunk-AN7SNPFA.js} +11 -11
- package/dist/{chunk-MSDK4IIJ.js → chunk-BBZLRWPR.js} +4 -4
- package/dist/{chunk-SMTBYDNO.js → chunk-BL2KOEXJ.js} +1 -1
- package/dist/{chunk-5BVC3Y6B.js → chunk-CILTKMZW.js} +7 -7
- package/dist/{chunk-YCHCHOMK.js → chunk-D7GAZKXT.js} +3 -3
- package/dist/{chunk-3WHI4LN3.js → chunk-EOOWV6C6.js} +2 -0
- package/dist/{chunk-HBQ6OLQT.js → chunk-NSARPM5C.js} +1 -1
- package/dist/{chunk-JXM6REER.js → chunk-O5ATYRUP.js} +1 -1
- package/dist/{chunk-RZF6A43N.js → chunk-QZKB6VTU.js} +4 -4
- package/dist/{chunk-6M55UPES.js → chunk-WTCWBY2D.js} +2 -2
- package/dist/{chunk-NQOGVP3I.js → chunk-XQVEAF3F.js} +2 -2
- package/dist/{chunk-QQJ2VVIW.js → chunk-XSUFHD67.js} +1 -1
- package/dist/{chunk-CGBSE55G.js → chunk-ZGIK5INC.js} +1 -1
- package/dist/cli.js +38 -38
- package/dist/{completion-D2BSBTQO.js → completion-JCBMQKNQ.js} +1 -1
- package/dist/{config-LAINORU5.js → config-2MR6V7U7.js} +2 -2
- package/dist/{config-ENDRMOTP.js → config-JCI7NAVY.js} +3 -3
- package/dist/{ghBotCli-ZVWU7EMG.js → ghBotCli-IXRHTHC5.js} +14 -14
- package/dist/{integrationCli-HXCSEWH2.js → integrationCli-KOCF73GG.js} +2 -2
- package/dist/{login-QPUWIC76.js → login-IMVSN4X3.js} +4 -4
- package/dist/{mcpCli-SETTCL3K.js → mcpCli-IBC3WCHG.js} +6 -6
- package/dist/{modelsCli-SZK4E2BY.js → modelsCli-BOPAZIG4.js} +6 -6
- package/dist/{oauthLogin-XWY7OHCG.js → oauthLogin-TUXZLIQN.js} +1 -1
- package/dist/{pluginsCli-ZQNKWZHJ.js → pluginsCli-X7NZRU7X.js} +2 -2
- package/dist/{prCli-6PUWTMTP.js → prCli-GPDLWYWC.js} +1 -1
- package/dist/providerCli-IRJTX5JF.js +15 -0
- package/dist/sdk.js +4 -2
- package/dist/{serve-K5AH4MGO.js → serve-A764QS5U.js} +3 -3
- package/dist/{serve-L3SAIAAI.js → serve-XRFCR6MG.js} +15 -15
- package/dist/session-NPKTEDKV.js +12 -0
- package/dist/setup-KYDIUOOG.js +24 -0
- package/dist/{statsCli-XR6BEZQQ.js → statsCli-FKGON32O.js} +1 -1
- package/dist/{transferCli-HKGAWZ3Q.js → transferCli-BQXPUFPH.js} +4 -4
- package/dist/ui/complete.d.ts +2 -0
- package/dist/ui/thinkingMouse.d.ts +2 -0
- package/dist/{ui-NPA52YJH.js → ui-S6OQOIFO.js} +404 -114
- package/dist/{update-AFIM34US.js → update-SYDSYLR6.js} +2 -2
- package/package.json +1 -1
- package/dist/providerCli-PKI7B2SC.js +0 -15
- package/dist/session-ASXO6GXR.js +0 -12
- package/dist/setup-F7FZ66OS.js +0 -24
|
@@ -2,14 +2,14 @@
|
|
|
2
2
|
import {
|
|
3
3
|
CATALOG,
|
|
4
4
|
fillTemplate
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-XQVEAF3F.js";
|
|
6
6
|
import {
|
|
7
7
|
MAX_VERIFY_ROUNDS,
|
|
8
8
|
runVerify,
|
|
9
9
|
toolLabel,
|
|
10
10
|
verifyFollowup,
|
|
11
11
|
worktreeListText
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-D7GAZKXT.js";
|
|
13
13
|
import {
|
|
14
14
|
BUILTIN_AGENTS,
|
|
15
15
|
appendMemory,
|
|
@@ -24,7 +24,7 @@ import {
|
|
|
24
24
|
runCommand,
|
|
25
25
|
runHooks,
|
|
26
26
|
validateGlobPattern
|
|
27
|
-
} from "./chunk-
|
|
27
|
+
} from "./chunk-NSARPM5C.js";
|
|
28
28
|
import "./chunk-PSO7R5AD.js";
|
|
29
29
|
import {
|
|
30
30
|
nextMode,
|
|
@@ -34,39 +34,39 @@ import {
|
|
|
34
34
|
hasKey,
|
|
35
35
|
providerName,
|
|
36
36
|
writeGlobalConfig
|
|
37
|
-
} from "./chunk-
|
|
37
|
+
} from "./chunk-27REMLDV.js";
|
|
38
38
|
import {
|
|
39
39
|
Session
|
|
40
|
-
} from "./chunk-
|
|
40
|
+
} from "./chunk-BL2KOEXJ.js";
|
|
41
41
|
import {
|
|
42
42
|
contentText
|
|
43
|
-
} from "./chunk-
|
|
43
|
+
} from "./chunk-BBZLRWPR.js";
|
|
44
44
|
import {
|
|
45
45
|
REASONING_LEVELS,
|
|
46
46
|
assertReasoningSupported,
|
|
47
47
|
parseReasoningLevel,
|
|
48
48
|
supportedReasoningLevels
|
|
49
|
-
} from "./chunk-
|
|
49
|
+
} from "./chunk-XSUFHD67.js";
|
|
50
50
|
import {
|
|
51
51
|
addGlobalServer,
|
|
52
52
|
globalMcpPath,
|
|
53
53
|
readMcpFile,
|
|
54
54
|
removeGlobalServer
|
|
55
|
-
} from "./chunk-
|
|
55
|
+
} from "./chunk-WTCWBY2D.js";
|
|
56
56
|
import {
|
|
57
57
|
ACCENT,
|
|
58
58
|
PRESETS,
|
|
59
59
|
color,
|
|
60
60
|
matchKeybind,
|
|
61
61
|
removeCredential
|
|
62
|
-
} from "./chunk-
|
|
62
|
+
} from "./chunk-AK6TWKET.js";
|
|
63
63
|
import {
|
|
64
64
|
getLanguage,
|
|
65
65
|
locale,
|
|
66
66
|
parseLang,
|
|
67
67
|
setLanguage,
|
|
68
68
|
t
|
|
69
|
-
} from "./chunk-
|
|
69
|
+
} from "./chunk-EOOWV6C6.js";
|
|
70
70
|
|
|
71
71
|
// src/ui/index.tsx
|
|
72
72
|
import { render } from "ink";
|
|
@@ -77,7 +77,7 @@ import { existsSync as existsSync3, mkdirSync, readFileSync as readFileSync2, wr
|
|
|
77
77
|
import { homedir, tmpdir } from "os";
|
|
78
78
|
import { dirname, join as join3, relative as relative2, resolve as resolve2 } from "path";
|
|
79
79
|
import { Box as Box13, Static, Text as Text16, measureElement, useApp, useInput as useInput9, useStdin, useStdout as useStdout2 } from "ink";
|
|
80
|
-
import { useCallback, useEffect as useEffect3, useRef, useState as
|
|
80
|
+
import { useCallback, useEffect as useEffect3, useRef as useRef2, useState as useState10 } from "react";
|
|
81
81
|
|
|
82
82
|
// src/commands.ts
|
|
83
83
|
var SLASH_COMMANDS = [
|
|
@@ -775,14 +775,38 @@ function masked(s) {
|
|
|
775
775
|
|
|
776
776
|
// src/ui/EditableText.tsx
|
|
777
777
|
import { Fragment, jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
778
|
+
var MAX_VISIBLE_LINES = 10;
|
|
779
|
+
function windowedState(s) {
|
|
780
|
+
const lines = s.value.split("\n");
|
|
781
|
+
if (lines.length <= MAX_VISIBLE_LINES) return { view: s, hiddenAbove: 0, hiddenBelow: 0 };
|
|
782
|
+
const cursorLine = s.value.slice(0, s.cursor).split("\n").length - 1;
|
|
783
|
+
const startLine = Math.max(0, Math.min(cursorLine - Math.floor(MAX_VISIBLE_LINES / 2), lines.length - MAX_VISIBLE_LINES));
|
|
784
|
+
const endLine = Math.min(lines.length, startLine + MAX_VISIBLE_LINES);
|
|
785
|
+
let charStart = 0;
|
|
786
|
+
for (let i = 0; i < startLine; i++) charStart += lines[i].length + 1;
|
|
787
|
+
const sliced = lines.slice(startLine, endLine).join("\n");
|
|
788
|
+
const relCursor = Math.max(0, Math.min(sliced.length, s.cursor - charStart));
|
|
789
|
+
return {
|
|
790
|
+
view: { value: sliced, cursor: relCursor },
|
|
791
|
+
hiddenAbove: startLine,
|
|
792
|
+
hiddenBelow: lines.length - endLine
|
|
793
|
+
};
|
|
794
|
+
}
|
|
778
795
|
function EditableText({ state, mask = false, showCursor = true }) {
|
|
779
|
-
const
|
|
780
|
-
|
|
796
|
+
const raw = mask ? masked(state) : state;
|
|
797
|
+
const { view, hiddenAbove, hiddenBelow } = windowedState(raw);
|
|
798
|
+
const prefix = hiddenAbove > 0 ? `\u2026 (+${hiddenAbove} lines above)
|
|
799
|
+
` : "";
|
|
800
|
+
const suffix = hiddenBelow > 0 ? `
|
|
801
|
+
\u2026 (+${hiddenBelow} lines below)` : "";
|
|
802
|
+
if (!showCursor) return /* @__PURE__ */ jsx2(Fragment, { children: `${prefix}${view.value}${suffix}` });
|
|
781
803
|
const { before, at, after } = splitAtCursor(view);
|
|
782
804
|
return /* @__PURE__ */ jsxs2(Fragment, { children: [
|
|
805
|
+
prefix ? /* @__PURE__ */ jsx2(Text2, { dimColor: true, children: prefix }) : null,
|
|
783
806
|
before,
|
|
784
807
|
/* @__PURE__ */ jsx2(Text2, { inverse: true, children: at }),
|
|
785
|
-
after
|
|
808
|
+
after,
|
|
809
|
+
suffix ? /* @__PURE__ */ jsx2(Text2, { dimColor: true, children: suffix }) : null
|
|
786
810
|
] });
|
|
787
811
|
}
|
|
788
812
|
|
|
@@ -819,8 +843,18 @@ function clickedThinking(click, cursorRow, rootHeight, target) {
|
|
|
819
843
|
const col = target.x + 1;
|
|
820
844
|
return (click.y === row || click.y === row - 1) && click.x >= col && click.x < col + Math.min(target.width, 46);
|
|
821
845
|
}
|
|
846
|
+
function parseMouseWheel(input) {
|
|
847
|
+
const match = /^\[<?(\d+);\d+;\d+[mM]$/.exec(input);
|
|
848
|
+
if (!match) return void 0;
|
|
849
|
+
const button = Number(match[1]);
|
|
850
|
+
if ((button & 64) === 0) return void 0;
|
|
851
|
+
const dir = button & 3;
|
|
852
|
+
if (dir === 0) return "up";
|
|
853
|
+
if (dir === 1) return "down";
|
|
854
|
+
return void 0;
|
|
855
|
+
}
|
|
822
856
|
function isMouseControlInput(input) {
|
|
823
|
-
return /^\[<(?:\d+;){2}\d+[mM]$/.test(input) || /^\[(?:\d+;)
|
|
857
|
+
return /^\[<[\d;]*[mM]?$/.test(input) || /^\[(?:\d+;){2}\d+[mM]$/.test(input) || /^\[(?:\d+;)+\d*R?$/.test(input) || /^\[M[\s\S]{0,3}$/.test(input) || input.includes("\x1B[<");
|
|
824
858
|
}
|
|
825
859
|
function parseThinkingReports(value) {
|
|
826
860
|
const events = [];
|
|
@@ -875,9 +909,20 @@ function ListPicker({ title, items, onPick }) {
|
|
|
875
909
|
const shown = items.filter((i) => i.label.toLowerCase().includes(filter.toLowerCase()));
|
|
876
910
|
const cursor = Math.min(index, Math.max(0, shown.length - 1));
|
|
877
911
|
useInput2((input, key) => {
|
|
912
|
+
const wheel = parseMouseWheel(input);
|
|
913
|
+
if (wheel === "up") {
|
|
914
|
+
setIndex(Math.max(0, cursor - 1));
|
|
915
|
+
return;
|
|
916
|
+
}
|
|
917
|
+
if (wheel === "down") {
|
|
918
|
+
setIndex(Math.min(Math.max(0, shown.length - 1), cursor + 1));
|
|
919
|
+
return;
|
|
920
|
+
}
|
|
878
921
|
if (isMouseControlInput(input)) return;
|
|
879
922
|
if (key.upArrow) setIndex(Math.max(0, cursor - 1));
|
|
880
|
-
else if (key.downArrow) setIndex(Math.min(shown.length - 1, cursor + 1));
|
|
923
|
+
else if (key.downArrow) setIndex(Math.min(Math.max(0, shown.length - 1), cursor + 1));
|
|
924
|
+
else if (key.pageUp) setIndex(Math.max(0, cursor - VISIBLE));
|
|
925
|
+
else if (key.pageDown) setIndex(Math.min(Math.max(0, shown.length - 1), cursor + VISIBLE));
|
|
881
926
|
else if (key.return && !shown[cursor]?.disabled) onPick(shown[cursor]?.id);
|
|
882
927
|
else if (key.escape) onPick(void 0);
|
|
883
928
|
else if (key.backspace || key.delete) {
|
|
@@ -917,11 +962,23 @@ function ModelPicker({ groups, current, onPick }) {
|
|
|
917
962
|
for (const m of models) rows.push({ kind: "model", ref: `${g.providerId}/${m}`, label: m });
|
|
918
963
|
}
|
|
919
964
|
const selectable = rows.flatMap((r, i) => r.kind === "model" ? [i] : []);
|
|
920
|
-
const
|
|
965
|
+
const clampedIndex = Math.min(index, Math.max(0, selectable.length - 1));
|
|
966
|
+
const cursor = selectable[clampedIndex] ?? -1;
|
|
921
967
|
useInput3((input, key) => {
|
|
968
|
+
const wheel = parseMouseWheel(input);
|
|
969
|
+
if (wheel === "up") {
|
|
970
|
+
setIndex(Math.max(0, clampedIndex - 1));
|
|
971
|
+
return;
|
|
972
|
+
}
|
|
973
|
+
if (wheel === "down") {
|
|
974
|
+
setIndex(Math.min(Math.max(0, selectable.length - 1), clampedIndex + 1));
|
|
975
|
+
return;
|
|
976
|
+
}
|
|
922
977
|
if (isMouseControlInput(input)) return;
|
|
923
|
-
if (key.upArrow) setIndex(
|
|
924
|
-
else if (key.downArrow) setIndex(
|
|
978
|
+
if (key.upArrow) setIndex(Math.max(0, clampedIndex - 1));
|
|
979
|
+
else if (key.downArrow) setIndex(Math.min(Math.max(0, selectable.length - 1), clampedIndex + 1));
|
|
980
|
+
else if (key.pageUp) setIndex(Math.max(0, clampedIndex - VISIBLE2));
|
|
981
|
+
else if (key.pageDown) setIndex(Math.min(Math.max(0, selectable.length - 1), clampedIndex + VISIBLE2));
|
|
925
982
|
else if (key.return) {
|
|
926
983
|
const row = rows[cursor];
|
|
927
984
|
if (row?.kind === "model") onPick(row.ref);
|
|
@@ -952,9 +1009,21 @@ import { jsx as jsx6, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
|
952
1009
|
function ProviderMenu({ entries, onPick }) {
|
|
953
1010
|
const rows = [...entries.map((e) => e.id), "custom"];
|
|
954
1011
|
const [index, setIndex] = useState4(0);
|
|
955
|
-
useInput4((
|
|
1012
|
+
useInput4((input, key) => {
|
|
1013
|
+
const wheel = parseMouseWheel(input);
|
|
1014
|
+
if (wheel === "up") {
|
|
1015
|
+
setIndex((i) => Math.max(0, i - 1));
|
|
1016
|
+
return;
|
|
1017
|
+
}
|
|
1018
|
+
if (wheel === "down") {
|
|
1019
|
+
setIndex((i) => Math.min(rows.length - 1, i + 1));
|
|
1020
|
+
return;
|
|
1021
|
+
}
|
|
1022
|
+
if (isMouseControlInput(input) || isFocusReport(input)) return;
|
|
956
1023
|
if (key.upArrow) setIndex((i) => Math.max(0, i - 1));
|
|
957
1024
|
else if (key.downArrow) setIndex((i) => Math.min(rows.length - 1, i + 1));
|
|
1025
|
+
else if (key.pageUp) setIndex((i) => Math.max(0, i - 10));
|
|
1026
|
+
else if (key.pageDown) setIndex((i) => Math.min(rows.length - 1, i + 10));
|
|
958
1027
|
else if (key.return) onPick(rows[index]);
|
|
959
1028
|
else if (key.escape) onPick(void 0);
|
|
960
1029
|
});
|
|
@@ -970,6 +1039,7 @@ function ProviderMenu({ entries, onPick }) {
|
|
|
970
1039
|
|
|
971
1040
|
// src/ui/PermissionPrompt.tsx
|
|
972
1041
|
import { Box as Box7, Text as Text8, useInput as useInput5 } from "ink";
|
|
1042
|
+
import { useState as useState5 } from "react";
|
|
973
1043
|
|
|
974
1044
|
// src/ui/DiffView.tsx
|
|
975
1045
|
import { Box as Box6, Text as Text7 } from "ink";
|
|
@@ -985,11 +1055,41 @@ function DiffView({ diff }) {
|
|
|
985
1055
|
// src/ui/PermissionPrompt.tsx
|
|
986
1056
|
import { jsx as jsx8, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
987
1057
|
var VERB = { edit: "edit", write: "write", bash: "run", fetch: "fetch" };
|
|
1058
|
+
var MAX_DIFF_LINES = 16;
|
|
988
1059
|
function PermissionPrompt({
|
|
989
1060
|
request,
|
|
990
1061
|
onAnswer
|
|
991
1062
|
}) {
|
|
1063
|
+
const diffLines = request.preview ? request.preview.split("\n") : [];
|
|
1064
|
+
const maxOffset = Math.max(0, diffLines.length - MAX_DIFF_LINES);
|
|
1065
|
+
const [offset, setOffset] = useState5(0);
|
|
992
1066
|
useInput5((input, key) => {
|
|
1067
|
+
const wheel = parseMouseWheel(input);
|
|
1068
|
+
if (wheel === "up") {
|
|
1069
|
+
setOffset((o) => Math.max(0, o - 2));
|
|
1070
|
+
return;
|
|
1071
|
+
}
|
|
1072
|
+
if (wheel === "down") {
|
|
1073
|
+
setOffset((o) => Math.min(maxOffset, o + 2));
|
|
1074
|
+
return;
|
|
1075
|
+
}
|
|
1076
|
+
if (isMouseControlInput(input) || isFocusReport(input)) return;
|
|
1077
|
+
if (key.upArrow) {
|
|
1078
|
+
setOffset((o) => Math.max(0, o - 1));
|
|
1079
|
+
return;
|
|
1080
|
+
}
|
|
1081
|
+
if (key.downArrow) {
|
|
1082
|
+
setOffset((o) => Math.min(maxOffset, o + 1));
|
|
1083
|
+
return;
|
|
1084
|
+
}
|
|
1085
|
+
if (key.pageUp) {
|
|
1086
|
+
setOffset((o) => Math.max(0, o - MAX_DIFF_LINES));
|
|
1087
|
+
return;
|
|
1088
|
+
}
|
|
1089
|
+
if (key.pageDown) {
|
|
1090
|
+
setOffset((o) => Math.min(maxOffset, o + MAX_DIFF_LINES));
|
|
1091
|
+
return;
|
|
1092
|
+
}
|
|
993
1093
|
const k2 = input.toLowerCase();
|
|
994
1094
|
if (k2 === "y") onAnswer("yes");
|
|
995
1095
|
else if (k2 === "a" && request.sessionRules?.length) onAnswer("session");
|
|
@@ -998,9 +1098,11 @@ function PermissionPrompt({
|
|
|
998
1098
|
});
|
|
999
1099
|
const rules = request.sessionRules ?? [];
|
|
1000
1100
|
const sessionLabel = !rules.length ? null : request.kind === "edit" ? t("yes for all edits in this project, this session") : t("yes this session for {rules}", { rules: rules.join(", ") });
|
|
1101
|
+
const visibleDiff = diffLines.length > MAX_DIFF_LINES ? diffLines.slice(offset, offset + MAX_DIFF_LINES).join("\n") : request.preview;
|
|
1001
1102
|
return /* @__PURE__ */ jsxs7(Box7, { flexDirection: "column", borderStyle: "round", borderColor: color("yellow"), paddingX: 1, children: [
|
|
1002
1103
|
/* @__PURE__ */ jsx8(Text8, { bold: true, children: `${request.agent ? `[${request.agent}] ` : ""}${t("Allow {verb} {target}?", { verb: t(VERB[request.tool] ?? request.tool), target: request.target })}` }),
|
|
1003
|
-
|
|
1104
|
+
visibleDiff ? /* @__PURE__ */ jsx8(DiffView, { diff: visibleDiff }) : null,
|
|
1105
|
+
diffLines.length > MAX_DIFF_LINES ? /* @__PURE__ */ jsx8(Text8, { dimColor: true, children: `\u2191\u2193 scroll (${offset + 1}\u2013${Math.min(diffLines.length, offset + MAX_DIFF_LINES)} / ${diffLines.length})` }) : null,
|
|
1004
1106
|
/* @__PURE__ */ jsxs7(Text8, { children: [
|
|
1005
1107
|
/* @__PURE__ */ jsx8(Text8, { color: color("green"), children: t("[y] yes") }),
|
|
1006
1108
|
" ",
|
|
@@ -1013,19 +1115,19 @@ function PermissionPrompt({
|
|
|
1013
1115
|
|
|
1014
1116
|
// src/ui/PromptInput.tsx
|
|
1015
1117
|
import { Box as Box8, Text as Text9, useInput as useInput6 } from "ink";
|
|
1016
|
-
import { useEffect, useState as
|
|
1118
|
+
import { useEffect, useRef, useState as useState6 } from "react";
|
|
1017
1119
|
|
|
1018
1120
|
// src/ui/complete.ts
|
|
1019
1121
|
import { existsSync, globSync, readFileSync, statSync } from "fs";
|
|
1020
1122
|
import { isAbsolute, join, relative, resolve } from "path";
|
|
1021
1123
|
var MAX_ATTACH_BYTES = 32768;
|
|
1022
|
-
function
|
|
1124
|
+
function listFileSuggestions(value, cwd, limit = 8) {
|
|
1023
1125
|
const match = /(^|\s)@([^\s]*)$/.exec(value);
|
|
1024
|
-
if (!match) return
|
|
1126
|
+
if (!match) return [];
|
|
1025
1127
|
const prefix = match[2];
|
|
1026
1128
|
const escaped = prefix.replace(/([*?[\]{}()!])/g, "\\$1");
|
|
1027
1129
|
const pattern = `${escaped}*`;
|
|
1028
|
-
if (validateGlobPattern(pattern)) return
|
|
1130
|
+
if (validateGlobPattern(pattern)) return [];
|
|
1029
1131
|
const exclude = ignorePatterns(cwd);
|
|
1030
1132
|
const formatEntry = (entry2) => {
|
|
1031
1133
|
const normalized = normalizeGlobPath(entry2);
|
|
@@ -1035,17 +1137,30 @@ function completeFile(value, cwd) {
|
|
|
1035
1137
|
return normalized;
|
|
1036
1138
|
}
|
|
1037
1139
|
};
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1140
|
+
try {
|
|
1141
|
+
let found = globSync(pattern, { cwd, exclude }).map(formatEntry).sort();
|
|
1142
|
+
if (!found.length && prefix && !prefix.includes("/")) {
|
|
1143
|
+
const deepPattern = `**/*${escaped}*`;
|
|
1144
|
+
if (!validateGlobPattern(deepPattern)) {
|
|
1145
|
+
found = globSync(deepPattern, { cwd, exclude }).map(formatEntry).sort((a, b) => a.split("/").length - b.split("/").length || a.localeCompare(b));
|
|
1146
|
+
}
|
|
1043
1147
|
}
|
|
1148
|
+
return found.slice(0, limit);
|
|
1149
|
+
} catch {
|
|
1150
|
+
return [];
|
|
1044
1151
|
}
|
|
1045
|
-
|
|
1046
|
-
|
|
1152
|
+
}
|
|
1153
|
+
function applyFileSuggestion(value, pick) {
|
|
1154
|
+
const match = /(^|\s)@([^\s]*)$/.exec(value);
|
|
1155
|
+
if (!match) return value;
|
|
1156
|
+
const prefix = match[2];
|
|
1047
1157
|
return `${value.slice(0, value.length - prefix.length)}${pick}${pick.endsWith("/") ? "" : " "}`;
|
|
1048
1158
|
}
|
|
1159
|
+
function completeFile(value, cwd) {
|
|
1160
|
+
const found = listFileSuggestions(value, cwd, 1);
|
|
1161
|
+
if (!found.length) return value;
|
|
1162
|
+
return applyFileSuggestion(value, found[0]);
|
|
1163
|
+
}
|
|
1049
1164
|
function expandAtFileMentions(prompt, cwd, readFiles) {
|
|
1050
1165
|
const matches = [...prompt.matchAll(/(?:^|\s)@([^\s]+)/g)];
|
|
1051
1166
|
if (!matches.length) return prompt;
|
|
@@ -1181,14 +1296,15 @@ ${s.value.slice(start)}`, cursor: start }, mode: "insert", handled: true };
|
|
|
1181
1296
|
// src/ui/PromptInput.tsx
|
|
1182
1297
|
import { jsx as jsx9, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
1183
1298
|
function PromptInput({ disabled, history, cwd, onSubmit, extraCommands, injected, vim }) {
|
|
1184
|
-
const [line, setLine] =
|
|
1299
|
+
const [line, setLine] = useState6({ value: "", cursor: 0 });
|
|
1185
1300
|
const { value } = line;
|
|
1186
|
-
const [historyIndex, setHistoryIndex] =
|
|
1187
|
-
const
|
|
1188
|
-
const [
|
|
1189
|
-
const [
|
|
1190
|
-
const [
|
|
1191
|
-
const
|
|
1301
|
+
const [historyIndex, setHistoryIndex] = useState6(null);
|
|
1302
|
+
const draftRef = useRef("");
|
|
1303
|
+
const [selected, setSelected] = useState6(0);
|
|
1304
|
+
const [dismissed, setDismissed] = useState6(false);
|
|
1305
|
+
const [vimMode, setVimMode] = useState6("insert");
|
|
1306
|
+
const [vimPending, setVimPending] = useState6(void 0);
|
|
1307
|
+
const injectedSeen = useState6(0);
|
|
1192
1308
|
useEffect(() => {
|
|
1193
1309
|
if (injected && injected.n !== injectedSeen[0]) {
|
|
1194
1310
|
injectedSeen[1](injected.n);
|
|
@@ -1198,7 +1314,10 @@ function PromptInput({ disabled, history, cwd, onSubmit, extraCommands, injected
|
|
|
1198
1314
|
}, [injected, injectedSeen]);
|
|
1199
1315
|
const all = [...SLASH_COMMANDS, ...(extraCommands ?? []).filter((c) => !SLASH_COMMANDS.some((b) => b.name === c.name))];
|
|
1200
1316
|
const suggestions = historyIndex === null && !dismissed && value.startsWith("/") && !/\s/.test(value) ? all.filter((c) => c.name.startsWith(value.slice(1))).slice(0, 8) : [];
|
|
1201
|
-
const
|
|
1317
|
+
const beforeCursor = value.slice(0, line.cursor);
|
|
1318
|
+
const fileSuggestions = historyIndex === null && !dismissed && !suggestions.length && /(^|\s)@([^\s]*)$/.test(beforeCursor) ? listFileSuggestions(beforeCursor, cwd, 8) : [];
|
|
1319
|
+
const activeCount = suggestions.length || fileSuggestions.length;
|
|
1320
|
+
const highlighted = Math.min(selected, Math.max(0, activeCount - 1));
|
|
1202
1321
|
const typed = (text) => ({ value: text, cursor: text.length });
|
|
1203
1322
|
const edit = (next) => {
|
|
1204
1323
|
setLine(next);
|
|
@@ -1208,6 +1327,13 @@ function PromptInput({ disabled, history, cwd, onSubmit, extraCommands, injected
|
|
|
1208
1327
|
};
|
|
1209
1328
|
useInput6(
|
|
1210
1329
|
(input, key) => {
|
|
1330
|
+
const wheel = parseMouseWheel(input);
|
|
1331
|
+
if (wheel) {
|
|
1332
|
+
if (activeCount > 0) {
|
|
1333
|
+
setSelected((current) => wheel === "up" ? Math.max(0, Math.min(current, activeCount - 1) - 1) : Math.min(activeCount - 1, Math.min(current, activeCount - 1) + 1));
|
|
1334
|
+
}
|
|
1335
|
+
return;
|
|
1336
|
+
}
|
|
1211
1337
|
if (isMouseControlInput(input)) return;
|
|
1212
1338
|
if (suggestions.length) {
|
|
1213
1339
|
if (key.escape) {
|
|
@@ -1226,13 +1352,33 @@ function PromptInput({ disabled, history, cwd, onSubmit, extraCommands, injected
|
|
|
1226
1352
|
edit(typed(`/${suggestions[highlighted].name} `));
|
|
1227
1353
|
return;
|
|
1228
1354
|
}
|
|
1229
|
-
if (key.return && !key.meta) {
|
|
1355
|
+
if (key.return && !key.meta && !key.shift) {
|
|
1230
1356
|
edit(typed(""));
|
|
1231
1357
|
setHistoryIndex(null);
|
|
1358
|
+
draftRef.current = "";
|
|
1232
1359
|
onSubmit(`/${suggestions[highlighted].name}`);
|
|
1233
1360
|
return;
|
|
1234
1361
|
}
|
|
1235
1362
|
}
|
|
1363
|
+
if (fileSuggestions.length) {
|
|
1364
|
+
if (key.escape) {
|
|
1365
|
+
setDismissed(true);
|
|
1366
|
+
return;
|
|
1367
|
+
}
|
|
1368
|
+
if (key.upArrow) {
|
|
1369
|
+
setSelected(Math.max(0, highlighted - 1));
|
|
1370
|
+
return;
|
|
1371
|
+
}
|
|
1372
|
+
if (key.downArrow) {
|
|
1373
|
+
setSelected(Math.min(fileSuggestions.length - 1, highlighted + 1));
|
|
1374
|
+
return;
|
|
1375
|
+
}
|
|
1376
|
+
if (key.tab && !key.shift) {
|
|
1377
|
+
const completed = applyFileSuggestion(beforeCursor, fileSuggestions[highlighted]);
|
|
1378
|
+
edit({ value: completed + value.slice(line.cursor), cursor: completed.length });
|
|
1379
|
+
return;
|
|
1380
|
+
}
|
|
1381
|
+
}
|
|
1236
1382
|
if (vim) {
|
|
1237
1383
|
const r = applyVim(line, vimMode, input, key, vimPending);
|
|
1238
1384
|
if (r.handled) {
|
|
@@ -1243,7 +1389,7 @@ function PromptInput({ disabled, history, cwd, onSubmit, extraCommands, injected
|
|
|
1243
1389
|
return;
|
|
1244
1390
|
}
|
|
1245
1391
|
}
|
|
1246
|
-
if (key.return && key.meta || key.ctrl && input.toLowerCase() === "j") {
|
|
1392
|
+
if (key.return && (key.meta || key.shift) || key.ctrl && input.toLowerCase() === "j" || input === "\n") {
|
|
1247
1393
|
edit((current) => insert(current, "\n"));
|
|
1248
1394
|
return;
|
|
1249
1395
|
}
|
|
@@ -1258,6 +1404,7 @@ ${value.slice(line.cursor)}`, cursor: before.length });
|
|
|
1258
1404
|
if (!text2) return;
|
|
1259
1405
|
edit(typed(""));
|
|
1260
1406
|
setHistoryIndex(null);
|
|
1407
|
+
draftRef.current = "";
|
|
1261
1408
|
setVimMode("insert");
|
|
1262
1409
|
setVimPending(void 0);
|
|
1263
1410
|
onSubmit(text2);
|
|
@@ -1277,6 +1424,7 @@ ${value.slice(line.cursor)}`, cursor: before.length });
|
|
|
1277
1424
|
}
|
|
1278
1425
|
if (key.upArrow) {
|
|
1279
1426
|
if (!history.length) return;
|
|
1427
|
+
if (historyIndex === null) draftRef.current = value;
|
|
1280
1428
|
const i = historyIndex === null ? history.length - 1 : Math.max(0, historyIndex - 1);
|
|
1281
1429
|
setHistoryIndex(i);
|
|
1282
1430
|
setLine(typed(history[i]));
|
|
@@ -1286,7 +1434,7 @@ ${value.slice(line.cursor)}`, cursor: before.length });
|
|
|
1286
1434
|
if (historyIndex === null) return;
|
|
1287
1435
|
const i = historyIndex + 1;
|
|
1288
1436
|
setHistoryIndex(i >= history.length ? null : i);
|
|
1289
|
-
setLine(typed(i >= history.length ?
|
|
1437
|
+
setLine(typed(i >= history.length ? draftRef.current : history[i]));
|
|
1290
1438
|
return;
|
|
1291
1439
|
}
|
|
1292
1440
|
if (key.tab && !key.shift) {
|
|
@@ -1310,17 +1458,18 @@ ${value.slice(line.cursor)}`, cursor: before.length });
|
|
|
1310
1458
|
t("NORMAL")
|
|
1311
1459
|
] })
|
|
1312
1460
|
] }) }),
|
|
1313
|
-
suggestions.map((s, i) => /* @__PURE__ */ jsx9(Text9, { color: i === highlighted ? color("green") : void 0, dimColor: i !== highlighted, children: `${i === highlighted ? "\u203A" : " "} /${s.name} ${t(s.description)}` }, s.name))
|
|
1461
|
+
suggestions.map((s, i) => /* @__PURE__ */ jsx9(Text9, { color: i === highlighted ? color("green") : void 0, dimColor: i !== highlighted, children: `${i === highlighted ? "\u203A" : " "} /${s.name} ${t(s.description)}` }, s.name)),
|
|
1462
|
+
fileSuggestions.map((f, i) => /* @__PURE__ */ jsx9(Text9, { color: i === highlighted ? color("green") : void 0, dimColor: i !== highlighted, children: `${i === highlighted ? "\u203A" : " "} @${f}` }, f))
|
|
1314
1463
|
] });
|
|
1315
1464
|
}
|
|
1316
1465
|
|
|
1317
1466
|
// src/ui/Spinner.tsx
|
|
1318
1467
|
import { Text as Text10 } from "ink";
|
|
1319
|
-
import { useEffect as useEffect2, useState as
|
|
1468
|
+
import { useEffect as useEffect2, useState as useState7 } from "react";
|
|
1320
1469
|
import { jsx as jsx10 } from "react/jsx-runtime";
|
|
1321
1470
|
var FRAMES = ["\xB7", "\u2722", "\u2733", "\u2736", "\u273B", "\u273D"];
|
|
1322
1471
|
function Spinner({ label, startedAt }) {
|
|
1323
|
-
const [tick, setTick] =
|
|
1472
|
+
const [tick, setTick] = useState7(0);
|
|
1324
1473
|
useEffect2(() => {
|
|
1325
1474
|
const id = setInterval(() => setTick((t2) => t2 + 1), 120);
|
|
1326
1475
|
return () => clearInterval(id);
|
|
@@ -1348,14 +1497,26 @@ function StatusBar({ mode, tokens, busy, model, reasoning = "auto" }) {
|
|
|
1348
1497
|
|
|
1349
1498
|
// src/ui/McpMenu.tsx
|
|
1350
1499
|
import { Box as Box9, Text as Text12, useInput as useInput7 } from "ink";
|
|
1351
|
-
import { useState as
|
|
1500
|
+
import { useState as useState8 } from "react";
|
|
1352
1501
|
import { jsx as jsx12, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
1353
1502
|
var MARK = { ready: "\u2713", error: "\u2717", starting: "\u2026", off: "\u25CB" };
|
|
1354
1503
|
function McpMenu({ items, onPick }) {
|
|
1355
|
-
const [index, setIndex] =
|
|
1356
|
-
useInput7((
|
|
1504
|
+
const [index, setIndex] = useState8(0);
|
|
1505
|
+
useInput7((input, key) => {
|
|
1506
|
+
const wheel = parseMouseWheel(input);
|
|
1507
|
+
if (wheel === "up") {
|
|
1508
|
+
setIndex((i) => Math.max(0, i - 1));
|
|
1509
|
+
return;
|
|
1510
|
+
}
|
|
1511
|
+
if (wheel === "down") {
|
|
1512
|
+
setIndex((i) => Math.min(items.length - 1, i + 1));
|
|
1513
|
+
return;
|
|
1514
|
+
}
|
|
1515
|
+
if (isMouseControlInput(input) || isFocusReport(input)) return;
|
|
1357
1516
|
if (key.upArrow) setIndex((i) => Math.max(0, i - 1));
|
|
1358
1517
|
else if (key.downArrow) setIndex((i) => Math.min(items.length - 1, i + 1));
|
|
1518
|
+
else if (key.pageUp) setIndex((i) => Math.max(0, i - 10));
|
|
1519
|
+
else if (key.pageDown) setIndex((i) => Math.min(items.length - 1, i + 10));
|
|
1359
1520
|
else if (key.return) onPick(items[index]?.name);
|
|
1360
1521
|
else if (key.escape) onPick(void 0);
|
|
1361
1522
|
});
|
|
@@ -1370,17 +1531,50 @@ function McpMenu({ items, onPick }) {
|
|
|
1370
1531
|
|
|
1371
1532
|
// src/ui/PlanApproval.tsx
|
|
1372
1533
|
import { Box as Box10, Text as Text13, useInput as useInput8 } from "ink";
|
|
1534
|
+
import { useState as useState9 } from "react";
|
|
1373
1535
|
import { jsx as jsx13, jsxs as jsxs10 } from "react/jsx-runtime";
|
|
1536
|
+
var MAX_PLAN_LINES = 16;
|
|
1374
1537
|
function PlanApproval({ plan, onAnswer }) {
|
|
1538
|
+
const planLines = plan.split("\n");
|
|
1539
|
+
const maxOffset = Math.max(0, planLines.length - MAX_PLAN_LINES);
|
|
1540
|
+
const [offset, setOffset] = useState9(0);
|
|
1375
1541
|
useInput8((input, key) => {
|
|
1542
|
+
const wheel = parseMouseWheel(input);
|
|
1543
|
+
if (wheel === "up") {
|
|
1544
|
+
setOffset((o) => Math.max(0, o - 2));
|
|
1545
|
+
return;
|
|
1546
|
+
}
|
|
1547
|
+
if (wheel === "down") {
|
|
1548
|
+
setOffset((o) => Math.min(maxOffset, o + 2));
|
|
1549
|
+
return;
|
|
1550
|
+
}
|
|
1551
|
+
if (isMouseControlInput(input) || isFocusReport(input)) return;
|
|
1552
|
+
if (key.upArrow) {
|
|
1553
|
+
setOffset((o) => Math.max(0, o - 1));
|
|
1554
|
+
return;
|
|
1555
|
+
}
|
|
1556
|
+
if (key.downArrow) {
|
|
1557
|
+
setOffset((o) => Math.min(maxOffset, o + 1));
|
|
1558
|
+
return;
|
|
1559
|
+
}
|
|
1560
|
+
if (key.pageUp) {
|
|
1561
|
+
setOffset((o) => Math.max(0, o - MAX_PLAN_LINES));
|
|
1562
|
+
return;
|
|
1563
|
+
}
|
|
1564
|
+
if (key.pageDown) {
|
|
1565
|
+
setOffset((o) => Math.min(maxOffset, o + MAX_PLAN_LINES));
|
|
1566
|
+
return;
|
|
1567
|
+
}
|
|
1376
1568
|
const k2 = input.toLowerCase();
|
|
1377
1569
|
if (k2 === "a") onAnswer("acceptEdits");
|
|
1378
1570
|
else if (k2 === "y") onAnswer("default");
|
|
1379
1571
|
else if (k2 === "n" || key.escape) onAnswer("no");
|
|
1380
1572
|
});
|
|
1573
|
+
const visiblePlan = planLines.length > MAX_PLAN_LINES ? planLines.slice(offset, offset + MAX_PLAN_LINES).join("\n") : plan;
|
|
1381
1574
|
return /* @__PURE__ */ jsxs10(Box10, { flexDirection: "column", borderStyle: "round", borderColor: color("cyan"), paddingX: 1, children: [
|
|
1382
1575
|
/* @__PURE__ */ jsx13(Text13, { bold: true, children: t("Plan from the agent") }),
|
|
1383
|
-
/* @__PURE__ */ jsx13(Markdown, { text:
|
|
1576
|
+
/* @__PURE__ */ jsx13(Markdown, { text: visiblePlan, indent: 5 }),
|
|
1577
|
+
planLines.length > MAX_PLAN_LINES ? /* @__PURE__ */ jsx13(Text13, { dimColor: true, children: `\u2191\u2193 scroll (${offset + 1}\u2013${Math.min(planLines.length, offset + MAX_PLAN_LINES)} / ${planLines.length})` }) : null,
|
|
1384
1578
|
/* @__PURE__ */ jsxs10(Text13, { children: [
|
|
1385
1579
|
/* @__PURE__ */ jsx13(Text13, { color: color("green"), children: t("[a] yes, auto-edit") }),
|
|
1386
1580
|
" ",
|
|
@@ -1402,8 +1596,9 @@ function TodoList({ items }) {
|
|
|
1402
1596
|
|
|
1403
1597
|
// src/ui/ToolBlock.tsx
|
|
1404
1598
|
import { Box as Box12, Text as Text15 } from "ink";
|
|
1405
|
-
import { jsx as jsx15, jsxs as jsxs11 } from "react/jsx-runtime";
|
|
1599
|
+
import { Fragment as Fragment2, jsx as jsx15, jsxs as jsxs11 } from "react/jsx-runtime";
|
|
1406
1600
|
var PREVIEW_LINES = 5;
|
|
1601
|
+
var DIFF_PREVIEW_LINES = 20;
|
|
1407
1602
|
function ToolBlock({ tool, target, output, display, isError, done, expanded, sub, moreBind = "ctrl+o" }) {
|
|
1408
1603
|
const isTask = tool === "task";
|
|
1409
1604
|
const isDiff = !!display && /^\s*\d+ [+\- ] /.test(display);
|
|
@@ -1421,9 +1616,16 @@ function ToolBlock({ tool, target, output, display, isError, done, expanded, sub
|
|
|
1421
1616
|
sub.length > 6 ? /* @__PURE__ */ jsx15(Text15, { dimColor: true, children: t("\u2026 {n} earlier steps", { n: sub.length - 6 }) }) : null
|
|
1422
1617
|
] }) : null,
|
|
1423
1618
|
isTask && done ? /* @__PURE__ */ jsx15(Box12, { marginLeft: 3, children: /* @__PURE__ */ jsx15(Text15, { color: isError ? color("red") : color("green"), children: `${isError ? t("\u2717 failed") : t("\u2713 done")}${display ? ` \xB7 ${display}` : ""}` }) }) : null,
|
|
1424
|
-
isDiff ? /* @__PURE__ */ jsx15(Box12, {
|
|
1619
|
+
isDiff ? /* @__PURE__ */ jsx15(Box12, { flexDirection: "column", marginLeft: 3, children: (() => {
|
|
1620
|
+
const diffLines = display.split("\n");
|
|
1621
|
+
const shownDiff = expanded ? diffLines : diffLines.slice(0, DIFF_PREVIEW_LINES);
|
|
1622
|
+
return /* @__PURE__ */ jsxs11(Fragment2, { children: [
|
|
1623
|
+
/* @__PURE__ */ jsx15(DiffView, { diff: shownDiff.join("\n") }),
|
|
1624
|
+
diffLines.length > shownDiff.length ? /* @__PURE__ */ jsx15(Text15, { dimColor: true, children: t("\u2026 {n} more lines ({bind})", { n: diffLines.length - shownDiff.length, bind: moreBind }) }) : expanded && diffLines.length > DIFF_PREVIEW_LINES ? /* @__PURE__ */ jsx15(Text15, { dimColor: true, children: t("\u2026 ({bind} to collapse)", { bind: moreBind }) }) : null
|
|
1625
|
+
] });
|
|
1626
|
+
})() }) : output && (isError || tool === "bash" || expanded) && !(isTask && !isError) ? /* @__PURE__ */ jsxs11(Box12, { flexDirection: "column", marginLeft: 3, children: [
|
|
1425
1627
|
shown.map((line, i) => /* @__PURE__ */ jsx15(Text15, { dimColor: !isError, color: isError ? color("red") : void 0, children: line }, i)),
|
|
1426
|
-
lines.length > shown.length ? /* @__PURE__ */ jsx15(Text15, { dimColor: true, children: t("\u2026 {n} more lines ({bind})", { n: lines.length - shown.length, bind: moreBind }) }) : null
|
|
1628
|
+
lines.length > shown.length ? /* @__PURE__ */ jsx15(Text15, { dimColor: true, children: t("\u2026 {n} more lines ({bind})", { n: lines.length - shown.length, bind: moreBind }) }) : expanded && lines.length > PREVIEW_LINES ? /* @__PURE__ */ jsx15(Text15, { dimColor: true, children: t("\u2026 ({bind} to collapse)", { bind: moreBind }) }) : null
|
|
1427
1629
|
] }) : null
|
|
1428
1630
|
] });
|
|
1429
1631
|
}
|
|
@@ -1470,7 +1672,10 @@ function applyEvent(t2, event) {
|
|
|
1470
1672
|
case "text": {
|
|
1471
1673
|
const last = t2.live.at(-1);
|
|
1472
1674
|
if (last?.kind === "assistant") return flushLines({ ...t2, live: [...t2.live.slice(0, -1), { ...last, text: last.text + event.delta }] });
|
|
1473
|
-
return flushLines({
|
|
1675
|
+
return flushLines({
|
|
1676
|
+
done: [...t2.done, ...t2.live.filter((e) => !isEmptyCont(e))],
|
|
1677
|
+
live: [entry({ kind: "assistant", text: event.delta })]
|
|
1678
|
+
});
|
|
1474
1679
|
}
|
|
1475
1680
|
case "thinking": {
|
|
1476
1681
|
const last = t2.live.at(-1);
|
|
@@ -1618,49 +1823,56 @@ var INIT_PROMPT = "Study this project (folder structure, package/build files, te
|
|
|
1618
1823
|
var labelFor = (runtime, ref) => `${ref.slice(ref.indexOf("/") + 1)} \xB7 ${runtime.providerLabel()}`;
|
|
1619
1824
|
function App({ runtime, initialPrompt, version, updateMessage }) {
|
|
1620
1825
|
const { exit } = useApp();
|
|
1621
|
-
const [transcript, setTranscript] =
|
|
1826
|
+
const [transcript, setTranscript] = useState10(() => ({
|
|
1622
1827
|
done: [entry({ kind: "header" }), ...updateMessage ? [entry({ kind: "notice", text: updateMessage, tone: "warn" })] : [], ...runtime.agent.messages.length ? replayEntries(runtime.session.loadHistory()) : []],
|
|
1623
1828
|
live: []
|
|
1624
1829
|
}));
|
|
1625
|
-
const [busy, setBusy] =
|
|
1626
|
-
const [cancelling, setCancelling] =
|
|
1627
|
-
const [startedAt, setStartedAt] =
|
|
1628
|
-
const [mode, setMode] =
|
|
1629
|
-
const [reasoning, setReasoning] =
|
|
1630
|
-
const [tokens, setTokens] =
|
|
1631
|
-
const [asks, setAsks] =
|
|
1830
|
+
const [busy, setBusy] = useState10(false);
|
|
1831
|
+
const [cancelling, setCancelling] = useState10(false);
|
|
1832
|
+
const [startedAt, setStartedAt] = useState10(0);
|
|
1833
|
+
const [mode, setMode] = useState10(runtime.agent.permissions.mode);
|
|
1834
|
+
const [reasoning, setReasoning] = useState10(runtime.reasoning);
|
|
1835
|
+
const [tokens, setTokens] = useState10(runtime.agent.totalUsage.inputTokens + runtime.agent.totalUsage.outputTokens);
|
|
1836
|
+
const [asks, setAsks] = useState10([]);
|
|
1632
1837
|
const pending = asks[0] ?? null;
|
|
1633
|
-
const askId =
|
|
1634
|
-
const [picker, setPicker] =
|
|
1635
|
-
const [providerMenu, setProviderMenu] =
|
|
1636
|
-
const [prompt, setPrompt] =
|
|
1838
|
+
const askId = useRef2(0);
|
|
1839
|
+
const [picker, setPicker] = useState10(null);
|
|
1840
|
+
const [providerMenu, setProviderMenu] = useState10(null);
|
|
1841
|
+
const [prompt, setPrompt] = useState10(null);
|
|
1637
1842
|
const ask = useCallback((label, mask = false) => new Promise((resolve3) => setPrompt({ label, mask, resolve: resolve3 })), []);
|
|
1638
|
-
const [modelLabel, setModelLabel] =
|
|
1639
|
-
const [history, setHistory] =
|
|
1640
|
-
const controller =
|
|
1641
|
-
const [todos, setTodos] =
|
|
1642
|
-
const [mcpMenu, setMcpMenu] =
|
|
1643
|
-
const [listPicker, setListPicker] =
|
|
1644
|
-
const [planAsk, setPlanAsk] =
|
|
1645
|
-
const [queued, setQueued] =
|
|
1646
|
-
const [showThinking, setShowThinking] =
|
|
1647
|
-
const showThinkingRef =
|
|
1648
|
-
const [,
|
|
1649
|
-
const [
|
|
1650
|
-
const
|
|
1843
|
+
const [modelLabel, setModelLabel] = useState10(() => labelFor(runtime, runtime.modelRef));
|
|
1844
|
+
const [history, setHistory] = useState10([]);
|
|
1845
|
+
const controller = useRef2(null);
|
|
1846
|
+
const [todos, setTodos] = useState10(runtime.todos.items);
|
|
1847
|
+
const [mcpMenu, setMcpMenu] = useState10(null);
|
|
1848
|
+
const [listPicker, setListPicker] = useState10(null);
|
|
1849
|
+
const [planAsk, setPlanAsk] = useState10(null);
|
|
1850
|
+
const [queued, setQueued] = useState10([]);
|
|
1851
|
+
const [showThinking, setShowThinking] = useState10(runtime.config.thinkingVisible === true);
|
|
1852
|
+
const showThinkingRef = useRef2(showThinking);
|
|
1853
|
+
const [showToolOutput, setShowToolOutput] = useState10(false);
|
|
1854
|
+
const [staticKey, setStaticKey] = useState10(0);
|
|
1855
|
+
const [, setConfigRev] = useState10(0);
|
|
1856
|
+
const liveThinkingEntryId = transcript.live.findLast((e) => e.kind === "thinking" && !!e.text.trim())?.id;
|
|
1651
1857
|
const { stdin } = useStdin();
|
|
1652
1858
|
const { stdout } = useStdout2();
|
|
1653
|
-
const
|
|
1654
|
-
|
|
1655
|
-
|
|
1859
|
+
const refreshStatic = useCallback(() => {
|
|
1860
|
+
if (stdout?.isTTY && "fd" in stdout) {
|
|
1861
|
+
stdout.write("\x1B[2J\x1B[3J\x1B[H");
|
|
1862
|
+
}
|
|
1863
|
+
setStaticKey((k2) => k2 + 1);
|
|
1864
|
+
}, [stdout]);
|
|
1865
|
+
const liveRootRef = useRef2(null);
|
|
1866
|
+
const thinkingTargetRef = useRef2(null);
|
|
1867
|
+
const [injected, setInjected] = useState10();
|
|
1656
1868
|
useEffect3(() => runtime.todos.subscribe(setTodos), [runtime]);
|
|
1657
1869
|
const extraCommands = [
|
|
1658
1870
|
...runtime.commands.filter((c) => !SLASH_COMMANDS.some((b) => b.name === c.name.toLowerCase())).map((c) => ({ name: c.name.toLowerCase(), description: c.description ?? t("custom command") })),
|
|
1659
1871
|
...runtime.skills.filter((s) => !runtime.commands.some((c) => c.name.toLowerCase() === s.name.toLowerCase())).filter((s) => !SLASH_COMMANDS.some((b) => b.name === s.name.toLowerCase())).map((s) => ({ name: s.name, description: t("skill \xB7 {description}", { description: s.description.slice(0, 50) }) }))
|
|
1660
1872
|
];
|
|
1661
|
-
const lastTool =
|
|
1662
|
-
const toolTargets =
|
|
1663
|
-
const editedInTurn =
|
|
1873
|
+
const lastTool = useRef2(null);
|
|
1874
|
+
const toolTargets = useRef2(/* @__PURE__ */ new Map());
|
|
1875
|
+
const editedInTurn = useRef2(false);
|
|
1664
1876
|
const notice = useCallback((text, tone = "info") => {
|
|
1665
1877
|
setTranscript((t2) => ({ ...t2, done: [...t2.done, entry({ kind: "notice", text, tone })] }));
|
|
1666
1878
|
}, []);
|
|
@@ -1671,7 +1883,6 @@ function App({ runtime, initialPrompt, version, updateMessage }) {
|
|
|
1671
1883
|
if ((event.tool === "edit" || event.tool === "write") && !event.isError) editedInTurn.current = true;
|
|
1672
1884
|
}
|
|
1673
1885
|
if (event.type === "usage") setTokens(event.inputTokens + event.outputTokens);
|
|
1674
|
-
if (event.type === "thinking" && event.delta) setLastThinking((prev) => prev + event.delta);
|
|
1675
1886
|
if (event.type === "budgetExceeded") {
|
|
1676
1887
|
notice(
|
|
1677
1888
|
t("Budget exceeded ({kind}): {used} of {limit}. Further model calls are blocked; raise usageCap in ~/.bccli/config.json.", {
|
|
@@ -1699,7 +1910,7 @@ function App({ runtime, initialPrompt, version, updateMessage }) {
|
|
|
1699
1910
|
async (text) => {
|
|
1700
1911
|
setTranscript((t2) => ({ ...t2, done: [...t2.done, entry({ kind: "user", text })] }));
|
|
1701
1912
|
setBusy(true);
|
|
1702
|
-
|
|
1913
|
+
setShowToolOutput(false);
|
|
1703
1914
|
setStartedAt(Date.now());
|
|
1704
1915
|
editedInTurn.current = false;
|
|
1705
1916
|
controller.current = new AbortController();
|
|
@@ -1747,7 +1958,9 @@ function App({ runtime, initialPrompt, version, updateMessage }) {
|
|
|
1747
1958
|
case "clear":
|
|
1748
1959
|
runtime.agent.clear();
|
|
1749
1960
|
setTokens(0);
|
|
1750
|
-
|
|
1961
|
+
setShowToolOutput(false);
|
|
1962
|
+
setTranscript({ done: [entry({ kind: "header" })], live: [] });
|
|
1963
|
+
refreshStatic();
|
|
1751
1964
|
notice(t("Conversation cleared."));
|
|
1752
1965
|
return;
|
|
1753
1966
|
case "cost": {
|
|
@@ -1842,7 +2055,9 @@ function App({ runtime, initialPrompt, version, updateMessage }) {
|
|
|
1842
2055
|
case "new":
|
|
1843
2056
|
runtime.newSession();
|
|
1844
2057
|
setTokens(0);
|
|
1845
|
-
|
|
2058
|
+
setShowToolOutput(false);
|
|
2059
|
+
setTranscript({ done: [entry({ kind: "header" })], live: [] });
|
|
2060
|
+
refreshStatic();
|
|
1846
2061
|
notice(t("New session started. The previous session stays saved (/resume)."));
|
|
1847
2062
|
return;
|
|
1848
2063
|
case "session":
|
|
@@ -1874,9 +2089,11 @@ function App({ runtime, initialPrompt, version, updateMessage }) {
|
|
|
1874
2089
|
const chosen = others.find((s) => s.session.file === id);
|
|
1875
2090
|
if (!chosen) return;
|
|
1876
2091
|
runtime.resume(chosen.session);
|
|
2092
|
+
setModelLabel(labelFor(runtime, runtime.modelRef));
|
|
1877
2093
|
setTokens(0);
|
|
1878
|
-
|
|
2094
|
+
setShowToolOutput(false);
|
|
1879
2095
|
setTranscript({ done: [entry({ kind: "header" }), ...replayEntries(chosen.session.loadHistory())], live: [] });
|
|
2096
|
+
refreshStatic();
|
|
1880
2097
|
}
|
|
1881
2098
|
});
|
|
1882
2099
|
return;
|
|
@@ -2078,6 +2295,15 @@ function App({ runtime, initialPrompt, version, updateMessage }) {
|
|
|
2078
2295
|
notice(t("Nothing to rewind."));
|
|
2079
2296
|
return;
|
|
2080
2297
|
}
|
|
2298
|
+
setTranscript((tr) => {
|
|
2299
|
+
const userIndices = [];
|
|
2300
|
+
tr.done.forEach((e, idx) => {
|
|
2301
|
+
if (e.kind === "user") userIndices.push(idx);
|
|
2302
|
+
});
|
|
2303
|
+
const cutIdx = userIndices[Math.max(0, userIndices.length - result.turns)];
|
|
2304
|
+
return cutIdx !== void 0 ? { done: tr.done.slice(0, cutIdx), live: [] } : tr;
|
|
2305
|
+
});
|
|
2306
|
+
refreshStatic();
|
|
2081
2307
|
const rel = (p) => relative2(runtime.cwd, p) || p;
|
|
2082
2308
|
notice(
|
|
2083
2309
|
[
|
|
@@ -2140,6 +2366,7 @@ function App({ runtime, initialPrompt, version, updateMessage }) {
|
|
|
2140
2366
|
writeGlobalConfig({ thinkingVisible: next }, runtime.env);
|
|
2141
2367
|
showThinkingRef.current = next;
|
|
2142
2368
|
setShowThinking(next);
|
|
2369
|
+
refreshStatic();
|
|
2143
2370
|
} else if (key === "thinkingClickCollapse") writeGlobalConfig({ thinkingClickCollapse: val === "true" || val === "on" }, runtime.env);
|
|
2144
2371
|
else if (key === "sandbox" && (val === "on" || val === "off")) writeGlobalConfig({ sandbox: val }, runtime.env);
|
|
2145
2372
|
else if (key === "networkPolicy" && (val === "allow" || val === "offline")) writeGlobalConfig({ networkPolicy: val }, runtime.env);
|
|
@@ -2176,7 +2403,7 @@ function App({ runtime, initialPrompt, version, updateMessage }) {
|
|
|
2176
2403
|
notice(t("Unknown command: /{name}. Type /help.", { name }), "warn");
|
|
2177
2404
|
}
|
|
2178
2405
|
},
|
|
2179
|
-
[runtime, notice, exit, version, runTurn, ask]
|
|
2406
|
+
[runtime, notice, exit, version, runTurn, ask, refreshStatic]
|
|
2180
2407
|
);
|
|
2181
2408
|
const runSlash = useCallback(
|
|
2182
2409
|
(name, args) => runSlashCommand(name, args).catch((error) => notice(`/${name}: ${error.message}`, "error")),
|
|
@@ -2192,8 +2419,12 @@ function App({ runtime, initialPrompt, version, updateMessage }) {
|
|
|
2192
2419
|
if (text.startsWith("!") && text.slice(1).trim()) {
|
|
2193
2420
|
const cmd = text.slice(1).trim();
|
|
2194
2421
|
setTranscript((tr) => ({ ...tr, done: [...tr.done, entry({ kind: "user", text })] }));
|
|
2422
|
+
setBusy(true);
|
|
2423
|
+
setStartedAt(Date.now());
|
|
2424
|
+
const ctrl = new AbortController();
|
|
2425
|
+
controller.current = ctrl;
|
|
2195
2426
|
const shell = resolveShell({ platform: process.platform, env: runtime.env, exists: existsSync3 });
|
|
2196
|
-
void runCommand(cmd, { cwd: runtime.cwd, timeoutMs: 6e4, signal:
|
|
2427
|
+
void runCommand(cmd, { cwd: runtime.cwd, timeoutMs: 6e4, signal: ctrl.signal, shell }).then((r) => {
|
|
2197
2428
|
const out = r.output.trim() || "(no output)";
|
|
2198
2429
|
notice(`$ ${cmd}
|
|
2199
2430
|
${out}`, r.exitCode ? "error" : "info");
|
|
@@ -2202,6 +2433,10 @@ $ ${cmd}
|
|
|
2202
2433
|
${out}` };
|
|
2203
2434
|
runtime.agent.messages.push(ctxMsg);
|
|
2204
2435
|
runtime.session.append(ctxMsg);
|
|
2436
|
+
}).finally(() => {
|
|
2437
|
+
controller.current = null;
|
|
2438
|
+
setBusy(false);
|
|
2439
|
+
setCancelling(false);
|
|
2205
2440
|
});
|
|
2206
2441
|
return;
|
|
2207
2442
|
}
|
|
@@ -2242,7 +2477,7 @@ ARGUMENTS: ${slash.args}`);
|
|
|
2242
2477
|
setQueued(rest);
|
|
2243
2478
|
submit(next);
|
|
2244
2479
|
}, [busy, pending, planAsk, queued, submit]);
|
|
2245
|
-
const initialSent =
|
|
2480
|
+
const initialSent = useRef2(false);
|
|
2246
2481
|
useEffect3(() => {
|
|
2247
2482
|
if (initialPrompt && !initialSent.current) {
|
|
2248
2483
|
initialSent.current = true;
|
|
@@ -2253,15 +2488,31 @@ ARGUMENTS: ${slash.args}`);
|
|
|
2253
2488
|
const next = !showThinkingRef.current;
|
|
2254
2489
|
showThinkingRef.current = next;
|
|
2255
2490
|
setShowThinking(next);
|
|
2491
|
+
refreshStatic();
|
|
2256
2492
|
try {
|
|
2257
2493
|
writeGlobalConfig({ thinkingVisible: next }, runtime.env);
|
|
2258
2494
|
} catch (error) {
|
|
2259
2495
|
notice(t("Could not save thinking visibility: {error}", { error: error.message }), "warn");
|
|
2260
2496
|
}
|
|
2261
|
-
}, [runtime, notice]);
|
|
2497
|
+
}, [runtime, notice, refreshStatic]);
|
|
2498
|
+
useEffect3(() => {
|
|
2499
|
+
if (!stdout?.isTTY || !("fd" in stdout)) return;
|
|
2500
|
+
stdout.write("\x1B[?1000l\x1B[?1002l\x1B[?1003l\x1B[?1006l\x1B[?2004h");
|
|
2501
|
+
return () => {
|
|
2502
|
+
stdout.write("\x1B[?1000l\x1B[?1002l\x1B[?1003l\x1B[?1006l\x1B[?2004l");
|
|
2503
|
+
};
|
|
2504
|
+
}, [stdout]);
|
|
2505
|
+
const scrollableModalOpen = !!(picker || listPicker || mcpMenu || providerMenu || pending || planAsk);
|
|
2506
|
+
useEffect3(() => {
|
|
2507
|
+
if (!scrollableModalOpen || !stdout?.isTTY || !("fd" in stdout)) return;
|
|
2508
|
+
stdout.write("\x1B[?1000h\x1B[?1006h");
|
|
2509
|
+
return () => {
|
|
2510
|
+
stdout.write("\x1B[?1000l\x1B[?1006l");
|
|
2511
|
+
};
|
|
2512
|
+
}, [scrollableModalOpen, stdout]);
|
|
2262
2513
|
useEffect3(() => {
|
|
2263
2514
|
const modalOpen = !!(pending || planAsk || picker || listPicker || mcpMenu || providerMenu || prompt);
|
|
2264
|
-
if (!runtime.config.thinkingClickCollapse || !busy
|
|
2515
|
+
if (!runtime.config.thinkingClickCollapse || !busy || modalOpen || !stdin.isTTY || !stdout.isTTY || !thinkingTargetRef.current) return;
|
|
2265
2516
|
let click;
|
|
2266
2517
|
let mouseBuffer = "";
|
|
2267
2518
|
const onData = (data) => {
|
|
@@ -2287,7 +2538,7 @@ ARGUMENTS: ${slash.args}`);
|
|
|
2287
2538
|
stdin.off("data", onData);
|
|
2288
2539
|
stdout.write("\x1B[?1000l\x1B[?1006l");
|
|
2289
2540
|
};
|
|
2290
|
-
}, [busy, pending, planAsk, picker, listPicker, mcpMenu, providerMenu, prompt, stdin, stdout, toggleThinking,
|
|
2541
|
+
}, [busy, pending, planAsk, picker, listPicker, mcpMenu, providerMenu, prompt, stdin, stdout, toggleThinking, runtime.config.thinkingClickCollapse]);
|
|
2291
2542
|
useInput9((input, key) => {
|
|
2292
2543
|
if (key.tab && key.shift) {
|
|
2293
2544
|
const next = nextMode(runtime.agent.permissions.mode);
|
|
@@ -2312,10 +2563,11 @@ ARGUMENTS: ${slash.args}`);
|
|
|
2312
2563
|
})();
|
|
2313
2564
|
} else if (matchKeybind(runtime.config.keybinds.thinking, input, key)) {
|
|
2314
2565
|
toggleThinking();
|
|
2315
|
-
} else if (matchKeybind(runtime.config.keybinds.toolOutput, input, key)
|
|
2316
|
-
|
|
2317
|
-
|
|
2318
|
-
|
|
2566
|
+
} else if (matchKeybind(runtime.config.keybinds.toolOutput, input, key)) {
|
|
2567
|
+
setShowToolOutput((prev) => !prev);
|
|
2568
|
+
refreshStatic();
|
|
2569
|
+
} else if (key.ctrl && input.toLowerCase() === "l") {
|
|
2570
|
+
refreshStatic();
|
|
2319
2571
|
}
|
|
2320
2572
|
});
|
|
2321
2573
|
const pickMcp = async (name) => {
|
|
@@ -2380,8 +2632,23 @@ ${t2.output}`);
|
|
|
2380
2632
|
pending?.resolve(a);
|
|
2381
2633
|
setAsks((q) => q.slice(1));
|
|
2382
2634
|
};
|
|
2635
|
+
const isRealTty = Boolean(stdout?.isTTY && "fd" in stdout);
|
|
2636
|
+
const maxLiveLines = Math.max(8, (stdout?.rows ?? 24) - 10);
|
|
2637
|
+
const capLiveMarkdown = (raw) => {
|
|
2638
|
+
if (!isRealTty) return raw;
|
|
2639
|
+
const lines = raw.split("\n");
|
|
2640
|
+
if (lines.length <= maxLiveLines) return raw;
|
|
2641
|
+
const hidden = lines.length - maxLiveLines;
|
|
2642
|
+
const headFence = lines.slice(0, hidden).find((l) => l.trimStart().startsWith("```"));
|
|
2643
|
+
const prefix = headFence ? `${headFence}
|
|
2644
|
+
\u2026 (${hidden} lines above) \u2026
|
|
2645
|
+
` : `\u2026 (${hidden} lines above) \u2026
|
|
2646
|
+
`;
|
|
2647
|
+
return `${prefix}${lines.slice(-maxLiveLines).join("\n")}`;
|
|
2648
|
+
};
|
|
2383
2649
|
const cwd = runtime.cwd.startsWith(homedir()) ? `~${runtime.cwd.slice(homedir().length)}` : runtime.cwd;
|
|
2384
2650
|
const renderEntry = (e) => {
|
|
2651
|
+
const isLive = transcript.live.some((le) => le.id === e.id);
|
|
2385
2652
|
switch (e.kind) {
|
|
2386
2653
|
case "header":
|
|
2387
2654
|
return /* @__PURE__ */ jsx16(Box13, { marginBottom: 1, children: /* @__PURE__ */ jsxs12(Text16, { children: [
|
|
@@ -2391,19 +2658,42 @@ ${t2.output}`);
|
|
|
2391
2658
|
] }) }, e.id);
|
|
2392
2659
|
case "user":
|
|
2393
2660
|
return /* @__PURE__ */ jsx16(Box13, { marginTop: 1, children: /* @__PURE__ */ jsx16(Text16, { dimColor: true, children: `> ${e.text}` }) }, e.id);
|
|
2394
|
-
case "assistant":
|
|
2661
|
+
case "assistant": {
|
|
2662
|
+
const displayText = isLive ? capLiveMarkdown(e.text) : e.text;
|
|
2395
2663
|
if (e.cont) {
|
|
2396
|
-
return
|
|
2664
|
+
return displayText ? /* @__PURE__ */ jsx16(Box13, { paddingLeft: 2, children: /* @__PURE__ */ jsx16(Markdown, { text: displayText }) }, e.id) : null;
|
|
2397
2665
|
}
|
|
2398
|
-
if (!
|
|
2666
|
+
if (!displayText.trim()) return null;
|
|
2399
2667
|
return /* @__PURE__ */ jsxs12(Box13, { marginTop: 1, children: [
|
|
2400
2668
|
/* @__PURE__ */ jsx16(Text16, { color: color(ACCENT), children: "\u25CF " }),
|
|
2401
|
-
/* @__PURE__ */ jsx16(Markdown, { text:
|
|
2669
|
+
/* @__PURE__ */ jsx16(Markdown, { text: displayText.replace(/^\s+/, "") })
|
|
2402
2670
|
] }, e.id);
|
|
2403
|
-
|
|
2404
|
-
|
|
2671
|
+
}
|
|
2672
|
+
case "thinking": {
|
|
2673
|
+
const text = e.text.trim();
|
|
2674
|
+
if (!text) return null;
|
|
2675
|
+
const allLines = text.split("\n");
|
|
2676
|
+
const lines = allLines.length;
|
|
2677
|
+
const shownText = isLive && isRealTty && allLines.length > maxLiveLines ? `\u2026 (${allLines.length - maxLiveLines} lines above) \u2026
|
|
2678
|
+
${allLines.slice(-maxLiveLines).join("\n")}` : text;
|
|
2679
|
+
const isTarget = e.id === liveThinkingEntryId;
|
|
2680
|
+
return /* @__PURE__ */ jsxs12(Box13, { ref: isTarget ? thinkingTargetRef : void 0, marginTop: 1, flexDirection: "column", children: [
|
|
2681
|
+
/* @__PURE__ */ jsxs12(Box13, { flexDirection: "row", children: [
|
|
2682
|
+
/* @__PURE__ */ jsx16(Text16, { dimColor: true, children: showThinking ? t("\u273B Thinking") : t("\u273B Thinking \xB7 {n} lines", { n: lines }) }),
|
|
2683
|
+
/* @__PURE__ */ jsxs12(Text16, { dimColor: true, children: [
|
|
2684
|
+
" \xB7 ",
|
|
2685
|
+
runtime.config.keybinds.thinking.spec,
|
|
2686
|
+
runtime.config.thinkingClickCollapse ? ` \xB7 ${t("click to toggle")}` : ""
|
|
2687
|
+
] })
|
|
2688
|
+
] }),
|
|
2689
|
+
showThinking ? /* @__PURE__ */ jsxs12(Box13, { flexDirection: "column", paddingLeft: 2, children: [
|
|
2690
|
+
/* @__PURE__ */ jsx16(Text16, { dimColor: true, children: t("Model: {model} \xB7 reasoning: {level}", { model: runtime.modelRef, level: reasoning }) }),
|
|
2691
|
+
/* @__PURE__ */ jsx16(Text16, { dimColor: true, italic: true, children: shownText })
|
|
2692
|
+
] }) : null
|
|
2693
|
+
] }, e.id);
|
|
2694
|
+
}
|
|
2405
2695
|
case "tool":
|
|
2406
|
-
return /* @__PURE__ */ jsx16(ToolBlock, { tool: e.tool, target: e.target, output: e.output, display: e.display, isError: e.isError, done: e.done, sub: e.sub, moreBind: runtime.config.keybinds.toolOutput.spec }, e.id);
|
|
2696
|
+
return /* @__PURE__ */ jsx16(ToolBlock, { tool: e.tool, target: e.target, output: e.output, display: e.display, isError: e.isError, done: e.done, expanded: showToolOutput, sub: e.sub, moreBind: runtime.config.keybinds.toolOutput.spec }, e.id);
|
|
2407
2697
|
case "notice":
|
|
2408
2698
|
return /* @__PURE__ */ jsx16(Box13, { marginTop: 1, children: /* @__PURE__ */ jsx16(Text16, { color: e.tone === "error" ? color("red") : e.tone === "warn" ? color("yellow") : void 0, dimColor: e.tone === "info", children: e.text }) }, e.id);
|
|
2409
2699
|
}
|
|
@@ -2414,21 +2704,21 @@ ${t2.output}`);
|
|
|
2414
2704
|
const activeSpinnerSummary = activeToolEntry ? `${toolLabel(activeToolEntry.tool)}${activeTarget ? ` ${activeTarget.length > 20 ? `${activeTarget.slice(0, 20)}\u2026` : activeTarget}` : ""}` : "";
|
|
2415
2705
|
const activeToolSummary = activeToolEntry ? `${toolLabel(activeToolEntry.tool)}${activeTarget ? ` ${activeTarget.length > 68 ? `${activeTarget.slice(0, 68)}\u2026` : activeTarget}` : ""}` : "";
|
|
2416
2706
|
return /* @__PURE__ */ jsxs12(Box13, { ref: liveRootRef, flexDirection: "column", children: [
|
|
2417
|
-
/* @__PURE__ */ jsx16(Static, { items: transcript.done, children: renderEntry }),
|
|
2707
|
+
/* @__PURE__ */ jsx16(Static, { items: transcript.done, children: renderEntry }, staticKey),
|
|
2418
2708
|
transcript.live.map(renderEntry),
|
|
2419
|
-
busy && !pending && !planAsk
|
|
2709
|
+
busy && !pending && !planAsk ? /* @__PURE__ */ jsxs12(Box13, { ref: liveThinkingEntryId === void 0 ? thinkingTargetRef : void 0, marginTop: 1, flexDirection: "column", children: [
|
|
2420
2710
|
/* @__PURE__ */ jsxs12(Box13, { flexDirection: "row", children: [
|
|
2421
|
-
|
|
2711
|
+
/* @__PURE__ */ jsx16(Spinner, { label: cancelling ? t("Cancelling") : activeSpinnerSummary ? `${t("Thinking")} \xB7 ${activeSpinnerSummary}` : t("Thinking"), startedAt }),
|
|
2422
2712
|
/* @__PURE__ */ jsxs12(Text16, { dimColor: true, children: [
|
|
2423
2713
|
" \xB7 ",
|
|
2424
2714
|
runtime.config.keybinds.thinking.spec,
|
|
2425
2715
|
runtime.config.thinkingClickCollapse ? ` \xB7 ${t("click to toggle")}` : ""
|
|
2426
2716
|
] })
|
|
2427
2717
|
] }),
|
|
2428
|
-
showThinking ? /* @__PURE__ */ jsxs12(Box13, { flexDirection: "column", paddingLeft: 2, children: [
|
|
2718
|
+
showThinking && liveThinkingEntryId === void 0 ? /* @__PURE__ */ jsxs12(Box13, { flexDirection: "column", paddingLeft: 2, children: [
|
|
2429
2719
|
/* @__PURE__ */ jsx16(Text16, { dimColor: true, children: t("Model: {model} \xB7 reasoning: {level}", { model: runtime.modelRef, level: reasoning }) }),
|
|
2430
2720
|
activeToolSummary ? /* @__PURE__ */ jsx16(Text16, { dimColor: true, children: `\u25B6 ${activeToolSummary}` }) : null,
|
|
2431
|
-
|
|
2721
|
+
!activeToolSummary ? /* @__PURE__ */ jsx16(Text16, { dimColor: true, children: t("No reasoning summary received yet; tool activity remains visible above.") }) : null
|
|
2432
2722
|
] }) : null
|
|
2433
2723
|
] }) : null,
|
|
2434
2724
|
pending ? /* @__PURE__ */ jsx16(PermissionPrompt, { request: pending.request, onAnswer: answer }, pending.id) : null,
|
|
@@ -2483,7 +2773,7 @@ ${t2.output}`);
|
|
|
2483
2773
|
import { jsx as jsx17 } from "react/jsx-runtime";
|
|
2484
2774
|
async function startInteractive(rt, opts) {
|
|
2485
2775
|
if (opts.resume) {
|
|
2486
|
-
const { Session: Session2 } = await import("./session-
|
|
2776
|
+
const { Session: Session2 } = await import("./session-NPKTEDKV.js");
|
|
2487
2777
|
const list = Session2.list(rt.home, rt.cwd).slice(0, 20);
|
|
2488
2778
|
if (!list.length) console.log(t("No sessions in this folder yet; starting a new one."));
|
|
2489
2779
|
else {
|
|
@@ -2499,7 +2789,7 @@ async function startInteractive(rt, opts) {
|
|
|
2499
2789
|
if (chosen) rt.resume(chosen.session);
|
|
2500
2790
|
}
|
|
2501
2791
|
}
|
|
2502
|
-
const { serversToStart, setProjectTrust } = await import("./config-
|
|
2792
|
+
const { serversToStart, setProjectTrust } = await import("./config-JCI7NAVY.js");
|
|
2503
2793
|
const plan = serversToStart(rt.home, rt.cwd);
|
|
2504
2794
|
if (plan.needTrust.length) {
|
|
2505
2795
|
const { createInterface } = await import("readline/promises");
|