reasonix 0.35.0 → 0.36.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +17 -0
- package/README.zh-CN.md +17 -0
- package/dashboard/dist/app.js +42 -3
- package/dashboard/dist/app.js.map +1 -1
- package/dist/cli/{chat-AB5D7I3V.js → chat-7AF5SPAJ.js} +16 -15
- package/dist/cli/{chunk-RJ5GUVS2.js → chunk-2MCYGFLK.js} +10 -10
- package/dist/cli/chunk-2MCYGFLK.js.map +1 -0
- package/dist/cli/{chunk-GPHBJWCV.js → chunk-3OBWN2NH.js} +650 -493
- package/dist/cli/chunk-3OBWN2NH.js.map +1 -0
- package/dist/cli/{chunk-SW3CCXEV.js → chunk-4Q3GRJIU.js} +2 -2
- package/dist/cli/{chunk-5JXXEPDM.js → chunk-BHLHOS5Y.js} +8 -2
- package/dist/cli/chunk-BHLHOS5Y.js.map +1 -0
- package/dist/cli/{chunk-IDP65VCC.js → chunk-BJ376EN3.js} +9 -8
- package/dist/cli/chunk-BJ376EN3.js.map +1 -0
- package/dist/cli/{chunk-2AWTGJ2C.js → chunk-CRPQUBP6.js} +26 -9
- package/dist/cli/{chunk-2AWTGJ2C.js.map → chunk-CRPQUBP6.js.map} +1 -1
- package/dist/cli/{chunk-JJTOZPM3.js → chunk-IPCPEZWQ.js} +2 -2
- package/dist/cli/{chunk-SN7YH6FC.js → chunk-MLXUGPJE.js} +168 -35
- package/dist/cli/chunk-MLXUGPJE.js.map +1 -0
- package/dist/cli/{chunk-SX6L4HZZ.js → chunk-QPNZWUZF.js} +53 -6
- package/dist/cli/chunk-QPNZWUZF.js.map +1 -0
- package/dist/cli/{chunk-N2IC4XDL.js → chunk-QRUQ2BFT.js} +13 -8
- package/dist/cli/{chunk-N2IC4XDL.js.map → chunk-QRUQ2BFT.js.map} +1 -1
- package/dist/cli/{chunk-KZHMKOJH.js → chunk-T52GAWPP.js} +25 -3
- package/dist/cli/chunk-T52GAWPP.js.map +1 -0
- package/dist/cli/{chunk-I6YIAK6C.js → chunk-UNMYFZPZ.js} +2 -2
- package/dist/cli/{update-4TJWRUIN.js → chunk-WJ3YX4PZ.js} +51 -12
- package/dist/cli/chunk-WJ3YX4PZ.js.map +1 -0
- package/dist/cli/{chunk-RXGEGA7K.js → chunk-XQIFIB3U.js} +18 -7
- package/dist/cli/{chunk-RXGEGA7K.js.map → chunk-XQIFIB3U.js.map} +1 -1
- package/dist/cli/{chunk-2EBODRRO.js → chunk-ZJR4QLXB.js} +5 -1
- package/dist/cli/{chunk-2EBODRRO.js.map → chunk-ZJR4QLXB.js.map} +1 -1
- package/dist/cli/{code-XBEFHXVM.js → code-SWI4EBME.js} +19 -17
- package/dist/cli/code-SWI4EBME.js.map +1 -0
- package/dist/cli/{commands-MEZPSEHV.js → commands-FE2UDFBC.js} +3 -3
- package/dist/cli/{commit-CE4EFTUQ.js → commit-3IAGB22T.js} +5 -4
- package/dist/cli/commit-3IAGB22T.js.map +1 -0
- package/dist/cli/{doctor-A565GMWD.js → doctor-DKD34EFD.js} +7 -7
- package/dist/cli/index.js +33 -31
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/{mcp-LDFK5QJI.js → mcp-2RDEQST6.js} +2 -2
- package/dist/cli/{mcp-browse-FYHEITCM.js → mcp-browse-VM5GLRBQ.js} +2 -2
- package/dist/cli/{mcp-inspect-T2HBR22P.js → mcp-inspect-CWSVCZUQ.js} +3 -3
- package/dist/cli/{replay-P2WC5N5X.js → replay-D7RT2DR7.js} +2 -2
- package/dist/cli/{run-QBWJETS3.js → run-FK5UBIIM.js} +11 -10
- package/dist/cli/run-FK5UBIIM.js.map +1 -0
- package/dist/cli/{server-SMLVXIW4.js → server-W4XJK4GX.js} +16 -16
- package/dist/cli/{server-SMLVXIW4.js.map → server-W4XJK4GX.js.map} +1 -1
- package/dist/cli/{sessions-55RIZVWG.js → sessions-YZXWMIWW.js} +8 -8
- package/dist/cli/{setup-QXMONZ4P.js → setup-IIAJXHP4.js} +196 -130
- package/dist/cli/setup-IIAJXHP4.js.map +1 -0
- package/dist/cli/update-GUCWB4UN.js +13 -0
- package/dist/cli/update-GUCWB4UN.js.map +1 -0
- package/dist/cli/{version-Q2HA3AAC.js → version-DWD6RLIU.js} +10 -10
- package/dist/index.d.ts +14 -2
- package/dist/index.js +270 -47
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/dist/cli/chunk-5JXXEPDM.js.map +0 -1
- package/dist/cli/chunk-GPHBJWCV.js.map +0 -1
- package/dist/cli/chunk-IDP65VCC.js.map +0 -1
- package/dist/cli/chunk-KZHMKOJH.js.map +0 -1
- package/dist/cli/chunk-RJ5GUVS2.js.map +0 -1
- package/dist/cli/chunk-SN7YH6FC.js.map +0 -1
- package/dist/cli/chunk-SX6L4HZZ.js.map +0 -1
- package/dist/cli/code-XBEFHXVM.js.map +0 -1
- package/dist/cli/commit-CE4EFTUQ.js.map +0 -1
- package/dist/cli/run-QBWJETS3.js.map +0 -1
- package/dist/cli/setup-QXMONZ4P.js.map +0 -1
- package/dist/cli/update-4TJWRUIN.js.map +0 -1
- /package/dist/cli/{chat-AB5D7I3V.js.map → chat-7AF5SPAJ.js.map} +0 -0
- /package/dist/cli/{chunk-SW3CCXEV.js.map → chunk-4Q3GRJIU.js.map} +0 -0
- /package/dist/cli/{chunk-JJTOZPM3.js.map → chunk-IPCPEZWQ.js.map} +0 -0
- /package/dist/cli/{chunk-I6YIAK6C.js.map → chunk-UNMYFZPZ.js.map} +0 -0
- /package/dist/cli/{commands-MEZPSEHV.js.map → commands-FE2UDFBC.js.map} +0 -0
- /package/dist/cli/{doctor-A565GMWD.js.map → doctor-DKD34EFD.js.map} +0 -0
- /package/dist/cli/{mcp-LDFK5QJI.js.map → mcp-2RDEQST6.js.map} +0 -0
- /package/dist/cli/{mcp-browse-FYHEITCM.js.map → mcp-browse-VM5GLRBQ.js.map} +0 -0
- /package/dist/cli/{mcp-inspect-T2HBR22P.js.map → mcp-inspect-CWSVCZUQ.js.map} +0 -0
- /package/dist/cli/{replay-P2WC5N5X.js.map → replay-D7RT2DR7.js.map} +0 -0
- /package/dist/cli/{sessions-55RIZVWG.js.map → sessions-YZXWMIWW.js.map} +0 -0
- /package/dist/cli/{version-Q2HA3AAC.js.map → version-DWD6RLIU.js.map} +0 -0
|
@@ -34,7 +34,7 @@ import {
|
|
|
34
34
|
toWholeFileEditBlock,
|
|
35
35
|
walkFilesStream,
|
|
36
36
|
webFetch
|
|
37
|
-
} from "./chunk-
|
|
37
|
+
} from "./chunk-QRUQ2BFT.js";
|
|
38
38
|
import {
|
|
39
39
|
McpClient,
|
|
40
40
|
SseTransport,
|
|
@@ -42,7 +42,7 @@ import {
|
|
|
42
42
|
StreamableHttpTransport,
|
|
43
43
|
inspectMcpServer,
|
|
44
44
|
parseMcpSpec
|
|
45
|
-
} from "./chunk-
|
|
45
|
+
} from "./chunk-UNMYFZPZ.js";
|
|
46
46
|
import {
|
|
47
47
|
openTranscriptFile,
|
|
48
48
|
recordFromLoopEvent,
|
|
@@ -55,7 +55,7 @@ import {
|
|
|
55
55
|
KeystrokeProvider,
|
|
56
56
|
SingleSelect,
|
|
57
57
|
useKeystroke
|
|
58
|
-
} from "./chunk-
|
|
58
|
+
} from "./chunk-T52GAWPP.js";
|
|
59
59
|
import {
|
|
60
60
|
COLOR,
|
|
61
61
|
GLYPH,
|
|
@@ -63,7 +63,7 @@ import {
|
|
|
63
63
|
ThemeProvider,
|
|
64
64
|
useColor,
|
|
65
65
|
useThemeTokens
|
|
66
|
-
} from "./chunk-
|
|
66
|
+
} from "./chunk-ZJR4QLXB.js";
|
|
67
67
|
import {
|
|
68
68
|
PRESETS,
|
|
69
69
|
PRESET_DESCRIPTIONS,
|
|
@@ -71,7 +71,7 @@ import {
|
|
|
71
71
|
} from "./chunk-MHDNZXJJ.js";
|
|
72
72
|
import {
|
|
73
73
|
runDoctorChecks
|
|
74
|
-
} from "./chunk-
|
|
74
|
+
} from "./chunk-BJ376EN3.js";
|
|
75
75
|
import {
|
|
76
76
|
countTokens
|
|
77
77
|
} from "./chunk-DAEAAVDF.js";
|
|
@@ -84,6 +84,10 @@ import {
|
|
|
84
84
|
import {
|
|
85
85
|
renderDashboard
|
|
86
86
|
} from "./chunk-4DCHFFEY.js";
|
|
87
|
+
import {
|
|
88
|
+
MANUAL_UPDATE_COMMANDS,
|
|
89
|
+
planUpdate
|
|
90
|
+
} from "./chunk-WJ3YX4PZ.js";
|
|
87
91
|
import {
|
|
88
92
|
SLASH_COMMANDS,
|
|
89
93
|
archivePlanState,
|
|
@@ -97,23 +101,23 @@ import {
|
|
|
97
101
|
resolveSlashAlias,
|
|
98
102
|
savePlanState,
|
|
99
103
|
suggestSlashCommands
|
|
100
|
-
} from "./chunk-
|
|
101
|
-
import {
|
|
102
|
-
eventLogPath,
|
|
103
|
-
openEventSink
|
|
104
|
-
} from "./chunk-G3XNWSFN.js";
|
|
104
|
+
} from "./chunk-2MCYGFLK.js";
|
|
105
105
|
import {
|
|
106
106
|
fetchSmitheryDetail,
|
|
107
107
|
loadMorePages,
|
|
108
108
|
openRegistry,
|
|
109
109
|
specStringFor
|
|
110
110
|
} from "./chunk-SOZE7V7V.js";
|
|
111
|
+
import {
|
|
112
|
+
eventLogPath,
|
|
113
|
+
openEventSink
|
|
114
|
+
} from "./chunk-G3XNWSFN.js";
|
|
111
115
|
import {
|
|
112
116
|
BUILTIN_ALLOWLIST,
|
|
113
117
|
formatCommandResult,
|
|
114
118
|
pauseGate,
|
|
115
119
|
runCommand
|
|
116
|
-
} from "./chunk-
|
|
120
|
+
} from "./chunk-QPNZWUZF.js";
|
|
117
121
|
import {
|
|
118
122
|
PROJECT_MEMORY_FILE,
|
|
119
123
|
SkillStore,
|
|
@@ -127,13 +131,7 @@ import {
|
|
|
127
131
|
loadHooks,
|
|
128
132
|
projectSettingsPath,
|
|
129
133
|
runHooks
|
|
130
|
-
} from "./chunk-
|
|
131
|
-
import {
|
|
132
|
-
VERSION,
|
|
133
|
-
compareVersions,
|
|
134
|
-
getLatestVersion,
|
|
135
|
-
isNpxInstall
|
|
136
|
-
} from "./chunk-2AWTGJ2C.js";
|
|
134
|
+
} from "./chunk-IPCPEZWQ.js";
|
|
137
135
|
import {
|
|
138
136
|
deleteSession,
|
|
139
137
|
detectGitBranch,
|
|
@@ -154,7 +152,7 @@ import {
|
|
|
154
152
|
setLanguage,
|
|
155
153
|
t,
|
|
156
154
|
tObj
|
|
157
|
-
} from "./chunk-
|
|
155
|
+
} from "./chunk-MLXUGPJE.js";
|
|
158
156
|
import {
|
|
159
157
|
addProjectShellAllowed,
|
|
160
158
|
clearProjectShellAllowed,
|
|
@@ -162,6 +160,7 @@ import {
|
|
|
162
160
|
editModeHintShown,
|
|
163
161
|
isPlausibleKey,
|
|
164
162
|
loadApiKey,
|
|
163
|
+
loadBaseUrl,
|
|
165
164
|
loadEditMode,
|
|
166
165
|
loadProjectShellAllowed,
|
|
167
166
|
loadReasoningEffort,
|
|
@@ -181,7 +180,7 @@ import {
|
|
|
181
180
|
webSearchEndpoint,
|
|
182
181
|
webSearchEngine,
|
|
183
182
|
writeConfig
|
|
184
|
-
} from "./chunk-
|
|
183
|
+
} from "./chunk-BHLHOS5Y.js";
|
|
185
184
|
import {
|
|
186
185
|
CARD,
|
|
187
186
|
FG,
|
|
@@ -205,6 +204,13 @@ import {
|
|
|
205
204
|
DEEPSEEK_PRICING,
|
|
206
205
|
DEFAULT_CONTEXT_TOKENS
|
|
207
206
|
} from "./chunk-ORM6PK57.js";
|
|
207
|
+
import {
|
|
208
|
+
VERSION,
|
|
209
|
+
compareVersions,
|
|
210
|
+
detectInstallSource,
|
|
211
|
+
detectNpmInstallPrefix,
|
|
212
|
+
getLatestVersion
|
|
213
|
+
} from "./chunk-CRPQUBP6.js";
|
|
208
214
|
|
|
209
215
|
// src/cli/commands/chat.tsx
|
|
210
216
|
import { render } from "ink";
|
|
@@ -231,7 +237,7 @@ function buildMcpServerSummary(opts) {
|
|
|
231
237
|
// src/cli/ui/App.tsx
|
|
232
238
|
import { statSync } from "fs";
|
|
233
239
|
import { resolve as resolve2 } from "path";
|
|
234
|
-
import { Box as Box49, Text as Text52, useStdout as
|
|
240
|
+
import { Box as Box49, Text as Text52, useStdout as useStdout15 } from "ink";
|
|
235
241
|
import React60, { useCallback as useCallback11, useEffect as useEffect12, useMemo as useMemo9, useRef as useRef9, useState as useState20 } from "react";
|
|
236
242
|
|
|
237
243
|
// src/code/checkpoints.ts
|
|
@@ -5322,9 +5328,17 @@ function processMultilineKey(value, cursor, keyIn) {
|
|
|
5322
5328
|
return cursor === value.length ? NOOP : { next: null, cursor: value.length, submit: false };
|
|
5323
5329
|
}
|
|
5324
5330
|
if (key.ctrl && key.input === "p") {
|
|
5331
|
+
if (value.includes("\n")) {
|
|
5332
|
+
const moved = moveCursorUp(value, cursor);
|
|
5333
|
+
if (moved !== cursor) return { next: null, cursor: moved, submit: false };
|
|
5334
|
+
}
|
|
5325
5335
|
return { ...NOOP, historyHandoff: "prev" };
|
|
5326
5336
|
}
|
|
5327
5337
|
if (key.ctrl && key.input === "n") {
|
|
5338
|
+
if (value.includes("\n")) {
|
|
5339
|
+
const moved = moveCursorDown(value, cursor);
|
|
5340
|
+
if (moved !== cursor) return { next: null, cursor: moved, submit: false };
|
|
5341
|
+
}
|
|
5328
5342
|
return { ...NOOP, historyHandoff: "next" };
|
|
5329
5343
|
}
|
|
5330
5344
|
if (key.leftArrow) {
|
|
@@ -5333,15 +5347,8 @@ function processMultilineKey(value, cursor, keyIn) {
|
|
|
5333
5347
|
if (key.rightArrow) {
|
|
5334
5348
|
return { next: null, cursor: Math.min(value.length, cursor + 1), submit: false };
|
|
5335
5349
|
}
|
|
5336
|
-
if (key.upArrow) {
|
|
5337
|
-
|
|
5338
|
-
const moved = moveCursorUp(value, cursor);
|
|
5339
|
-
return moved === cursor ? NOOP : { next: null, cursor: moved, submit: false };
|
|
5340
|
-
}
|
|
5341
|
-
if (key.downArrow) {
|
|
5342
|
-
if (value.length === 0) return { ...NOOP, historyHandoff: "next" };
|
|
5343
|
-
const moved = moveCursorDown(value, cursor);
|
|
5344
|
-
return moved === cursor ? NOOP : { next: null, cursor: moved, submit: false };
|
|
5350
|
+
if (key.upArrow || key.downArrow) {
|
|
5351
|
+
return NOOP;
|
|
5345
5352
|
}
|
|
5346
5353
|
if (key.ctrl && key.input === "a" || key.home) {
|
|
5347
5354
|
return { next: null, cursor: startOfLine(value, cursor), submit: false };
|
|
@@ -5907,7 +5914,8 @@ function HintRow() {
|
|
|
5907
5914
|
const items = [
|
|
5908
5915
|
{ key: "\u23CE", sep: "send" },
|
|
5909
5916
|
{ key: "\u21E7\u23CE", sep: "newline" },
|
|
5910
|
-
{ key: "\u2191\u2193", sep: "
|
|
5917
|
+
{ key: "\u2191\u2193", sep: "scroll" },
|
|
5918
|
+
{ key: "^P/^N", sep: "history" },
|
|
5911
5919
|
{ key: "esc", sep: "abort" },
|
|
5912
5920
|
{ key: "^C", sep: "quit" }
|
|
5913
5921
|
];
|
|
@@ -6423,8 +6431,12 @@ function ArgRow({ value, isSelected }) {
|
|
|
6423
6431
|
}
|
|
6424
6432
|
|
|
6425
6433
|
// src/cli/ui/SlashSuggestions.tsx
|
|
6426
|
-
import { Box as Box23, Text as Text23 } from "ink";
|
|
6434
|
+
import { Box as Box23, Text as Text23, useStdout as useStdout8 } from "ink";
|
|
6427
6435
|
import React27 from "react";
|
|
6436
|
+
var GROUP_MODE_MAX_ROWS = 24;
|
|
6437
|
+
var SEARCH_MODE_MAX_ROWS = 8;
|
|
6438
|
+
var COMMAND_NAME_CELLS = 14;
|
|
6439
|
+
var ARGS_CELLS = 14;
|
|
6428
6440
|
var GROUP_LABEL = {
|
|
6429
6441
|
chat: "CHAT",
|
|
6430
6442
|
setup: "SETUP",
|
|
@@ -6442,26 +6454,82 @@ function SlashSuggestions({
|
|
|
6442
6454
|
advancedHidden
|
|
6443
6455
|
}) {
|
|
6444
6456
|
const color = useColor();
|
|
6457
|
+
const { stdout } = useStdout8();
|
|
6458
|
+
const cols = stdout?.columns ?? 80;
|
|
6459
|
+
const [rememberedWindowStart, setRememberedWindowStart] = React27.useState(0);
|
|
6460
|
+
const maxRows = groupMode ? GROUP_MODE_MAX_ROWS : SEARCH_MODE_MAX_ROWS;
|
|
6461
|
+
const safeMatches = matches ?? [];
|
|
6462
|
+
const windowStart = computeWindowStart(
|
|
6463
|
+
safeMatches,
|
|
6464
|
+
maxRows,
|
|
6465
|
+
selectedIndex,
|
|
6466
|
+
rememberedWindowStart,
|
|
6467
|
+
groupMode
|
|
6468
|
+
);
|
|
6469
|
+
React27.useEffect(() => {
|
|
6470
|
+
setRememberedWindowStart(windowStart);
|
|
6471
|
+
}, [windowStart]);
|
|
6445
6472
|
if (matches === null) return null;
|
|
6446
6473
|
if (matches.length === 0) {
|
|
6447
6474
|
return /* @__PURE__ */ React27.createElement(Box23, { paddingX: 1, marginTop: 1 }, /* @__PURE__ */ React27.createElement(Text23, { color: color.warn, bold: true }, GLYPH.warn), /* @__PURE__ */ React27.createElement(Text23, null, " "), /* @__PURE__ */ React27.createElement(Text23, { color: color.warn }, "no slash command matches that prefix"), /* @__PURE__ */ React27.createElement(Text23, { dimColor: true }, " \u2014 Backspace to edit, or /help for the full list"));
|
|
6448
6475
|
}
|
|
6449
|
-
const MAX = groupMode ? 24 : 8;
|
|
6450
6476
|
const total = matches.length;
|
|
6451
|
-
const
|
|
6452
|
-
const
|
|
6477
|
+
const items = buildVisibleItems(matches, windowStart, maxRows, groupMode);
|
|
6478
|
+
const shownCommands = items.filter((item) => item.kind === "command");
|
|
6453
6479
|
const hiddenAbove = windowStart;
|
|
6454
|
-
const hiddenBelow = total - windowStart -
|
|
6455
|
-
|
|
6456
|
-
|
|
6457
|
-
|
|
6458
|
-
|
|
6459
|
-
|
|
6460
|
-
|
|
6461
|
-
|
|
6480
|
+
const hiddenBelow = total - windowStart - shownCommands.length;
|
|
6481
|
+
return /* @__PURE__ */ React27.createElement(Box23, { flexDirection: "column", paddingX: 1, marginTop: 1, flexShrink: 0, flexWrap: "nowrap" }, /* @__PURE__ */ React27.createElement(Box23, null, /* @__PURE__ */ React27.createElement(Text23, { color: color.accent, bold: true }, "/ "), /* @__PURE__ */ React27.createElement(Text23, { dimColor: true }, `${total} command${total === 1 ? "" : "s"}`), hiddenAbove > 0 ? /* @__PURE__ */ React27.createElement(Text23, { dimColor: true }, ` \u2191 ${hiddenAbove} above`) : null), items.map((item) => {
|
|
6482
|
+
if (item.kind === "group") {
|
|
6483
|
+
return /* @__PURE__ */ React27.createElement(GroupHeader, { key: `group:${item.group}:${item.beforeIndex}`, group: item.group });
|
|
6484
|
+
}
|
|
6485
|
+
return /* @__PURE__ */ React27.createElement(
|
|
6486
|
+
SuggestionRow,
|
|
6487
|
+
{
|
|
6488
|
+
key: `cmd:${item.spec.group}:${item.spec.cmd}`,
|
|
6489
|
+
spec: item.spec,
|
|
6490
|
+
isSelected: item.index === selectedIndex,
|
|
6491
|
+
columns: cols
|
|
6492
|
+
}
|
|
6493
|
+
);
|
|
6462
6494
|
}), hiddenBelow > 0 ? /* @__PURE__ */ React27.createElement(Text23, { dimColor: true }, ` \u2193 ${hiddenBelow} below`) : null, groupMode && advancedHidden && advancedHidden > 0 ? /* @__PURE__ */ React27.createElement(Box23, { marginTop: 1 }, /* @__PURE__ */ React27.createElement(Text23, { dimColor: true }, ` + ${advancedHidden} advanced \xB7 type a letter to search`)) : null, /* @__PURE__ */ React27.createElement(Box23, { marginTop: 0 }, /* @__PURE__ */ React27.createElement(Text23, { dimColor: true }, " \u2191\u2193 navigate \xB7 Tab / \u23CE pick \xB7 esc cancel")));
|
|
6463
6495
|
}
|
|
6464
|
-
function
|
|
6496
|
+
function computeWindowStart(matches, maxRows, selectedIndex, currentWindowStart, groupMode = false) {
|
|
6497
|
+
if (matches.length <= 0) return 0;
|
|
6498
|
+
const maxWindowStart = Math.max(0, matches.length - 1);
|
|
6499
|
+
let start = Math.max(0, Math.min(currentWindowStart, maxWindowStart));
|
|
6500
|
+
const clampedSelectedIndex = Math.max(0, Math.min(selectedIndex, matches.length - 1));
|
|
6501
|
+
if (clampedSelectedIndex < start) start = clampedSelectedIndex;
|
|
6502
|
+
while (start < clampedSelectedIndex) {
|
|
6503
|
+
const visibleCommandIndexes = buildVisibleItems(matches, start, maxRows, groupMode).filter((item) => item.kind === "command").map((item) => item.index);
|
|
6504
|
+
if (visibleCommandIndexes.includes(clampedSelectedIndex)) break;
|
|
6505
|
+
start += 1;
|
|
6506
|
+
}
|
|
6507
|
+
return Math.min(start, maxWindowStart);
|
|
6508
|
+
}
|
|
6509
|
+
function buildVisibleItems(matches, windowStart, maxRows, groupMode = false) {
|
|
6510
|
+
const out = [];
|
|
6511
|
+
for (let idx = windowStart; idx < matches.length && out.length < maxRows; idx += 1) {
|
|
6512
|
+
const spec = matches[idx];
|
|
6513
|
+
if (groupMode && shouldShowGroupHeader(matches, idx)) {
|
|
6514
|
+
if (out.length >= maxRows) break;
|
|
6515
|
+
out.push({ kind: "group", group: spec.group, beforeIndex: idx });
|
|
6516
|
+
}
|
|
6517
|
+
if (out.length >= maxRows) break;
|
|
6518
|
+
out.push({ kind: "command", spec, index: idx });
|
|
6519
|
+
}
|
|
6520
|
+
return out;
|
|
6521
|
+
}
|
|
6522
|
+
function shouldShowGroupHeader(matches, idx) {
|
|
6523
|
+
return idx === 0 || matches[idx]?.group !== matches[idx - 1]?.group;
|
|
6524
|
+
}
|
|
6525
|
+
function GroupHeader({ group }) {
|
|
6526
|
+
return /* @__PURE__ */ React27.createElement(Box23, { flexShrink: 0, height: 1, flexWrap: "nowrap" }, /* @__PURE__ */ React27.createElement(Text23, { dimColor: true, wrap: "truncate" }, ` ${GROUP_LABEL[group]}`));
|
|
6527
|
+
}
|
|
6528
|
+
function SuggestionRow({
|
|
6529
|
+
spec,
|
|
6530
|
+
isSelected,
|
|
6531
|
+
columns
|
|
6532
|
+
}) {
|
|
6465
6533
|
const color = useColor();
|
|
6466
6534
|
const name = `/${spec.cmd}`;
|
|
6467
6535
|
const argsSuffix = spec.argsHint ? spec.argsHint : "";
|
|
@@ -6469,7 +6537,19 @@ function SuggestionRow({ spec, isSelected }) {
|
|
|
6469
6537
|
const translated = t(key);
|
|
6470
6538
|
const summary = translated === key ? spec.summary : translated;
|
|
6471
6539
|
const aliasHint = spec.aliases?.length ? ` \xB7 /${spec.aliases.join(" /")}` : "";
|
|
6472
|
-
|
|
6540
|
+
const reservedCells = 2 + COMMAND_NAME_CELLS + ARGS_CELLS + 2 + 2;
|
|
6541
|
+
const summaryBudget = Math.max(8, columns - reservedCells);
|
|
6542
|
+
const summaryText = truncateCells(`${summary}${aliasHint}`, summaryBudget);
|
|
6543
|
+
return /* @__PURE__ */ React27.createElement(Box23, { flexDirection: "row", flexWrap: "nowrap", flexShrink: 0, height: 1, minHeight: 1 }, /* @__PURE__ */ React27.createElement(Text23, { color: isSelected ? color.primary : color.info, bold: isSelected, wrap: "truncate" }, isSelected ? `${GLYPH.cur} ` : " "), /* @__PURE__ */ React27.createElement(Text23, { color: color.accent, bold: isSelected, wrap: "truncate" }, padOrTrim(name, COMMAND_NAME_CELLS)), /* @__PURE__ */ React27.createElement(Text23, { dimColor: true, wrap: "truncate" }, padOrTrim(argsSuffix, ARGS_CELLS)), /* @__PURE__ */ React27.createElement(Text23, { wrap: "truncate" }, " "), /* @__PURE__ */ React27.createElement(Text23, { color: isSelected ? color.user : color.info, dimColor: !isSelected, wrap: "truncate" }, summaryText));
|
|
6544
|
+
}
|
|
6545
|
+
function padOrTrim(value, cells) {
|
|
6546
|
+
const trimmed = truncateCells(value, cells);
|
|
6547
|
+
return trimmed.padEnd(cells);
|
|
6548
|
+
}
|
|
6549
|
+
function truncateCells(value, maxCells) {
|
|
6550
|
+
if (value.length <= maxCells) return value;
|
|
6551
|
+
if (maxCells <= 1) return value.slice(0, Math.max(0, maxCells));
|
|
6552
|
+
return `${value.slice(0, maxCells - 1)}\u2026`;
|
|
6473
6553
|
}
|
|
6474
6554
|
|
|
6475
6555
|
// src/cli/ui/WelcomeBanner.tsx
|
|
@@ -6814,6 +6894,10 @@ function handleToolStart(ev, ctx) {
|
|
|
6814
6894
|
}
|
|
6815
6895
|
}
|
|
6816
6896
|
function handleErrorEvent(ev, ctx) {
|
|
6897
|
+
ctx.setOngoingTool(null);
|
|
6898
|
+
ctx.setToolProgress(null);
|
|
6899
|
+
ctx.toolStartedAtRef.current = null;
|
|
6900
|
+
ctx.translator.toolAbort(ev.error ?? ev.content);
|
|
6817
6901
|
ctx.log.pushError("tool error", ev.error ?? ev.content);
|
|
6818
6902
|
}
|
|
6819
6903
|
function handleWarningEvent(ev, ctx) {
|
|
@@ -6855,272 +6939,6 @@ function handleToolEvent(ev, ctx) {
|
|
|
6855
6939
|
}
|
|
6856
6940
|
}
|
|
6857
6941
|
|
|
6858
|
-
// src/cli/ui/hooks/useAgentSession.ts
|
|
6859
|
-
import { useMemo as useMemo6 } from "react";
|
|
6860
|
-
function useAgentSession({
|
|
6861
|
-
sessionId,
|
|
6862
|
-
model: model2,
|
|
6863
|
-
workspace,
|
|
6864
|
-
branch
|
|
6865
|
-
}) {
|
|
6866
|
-
return useMemo6(
|
|
6867
|
-
() => ({
|
|
6868
|
-
id: sessionId ?? "default",
|
|
6869
|
-
branch: branch ?? "main",
|
|
6870
|
-
workspace,
|
|
6871
|
-
model: model2
|
|
6872
|
-
}),
|
|
6873
|
-
[sessionId, branch, workspace, model2]
|
|
6874
|
-
);
|
|
6875
|
-
}
|
|
6876
|
-
|
|
6877
|
-
// src/cli/ui/hooks/useChatScroll.ts
|
|
6878
|
-
import { useCallback as useCallback2, useEffect as useEffect4, useRef as useRef2, useState as useState14 } from "react";
|
|
6879
|
-
var SCROLL_PAGE_ROWS = 3;
|
|
6880
|
-
var COALESCE_MS = 16;
|
|
6881
|
-
function useChatScroll() {
|
|
6882
|
-
const [scrollRows, setScrollRows] = useState14(0);
|
|
6883
|
-
const [pinned, setPinned] = useState14(true);
|
|
6884
|
-
const [maxScroll, setMaxScrollState] = useState14(0);
|
|
6885
|
-
const maxScrollRef = useRef2(0);
|
|
6886
|
-
const pendingDelta = useRef2(0);
|
|
6887
|
-
const flushTimer = useRef2(null);
|
|
6888
|
-
const flush = useCallback2(() => {
|
|
6889
|
-
flushTimer.current = null;
|
|
6890
|
-
const d = pendingDelta.current;
|
|
6891
|
-
pendingDelta.current = 0;
|
|
6892
|
-
if (d === 0) return;
|
|
6893
|
-
if (d < 0) setPinned(false);
|
|
6894
|
-
setScrollRows((o) => {
|
|
6895
|
-
const next = Math.max(0, Math.min(maxScrollRef.current, o + d));
|
|
6896
|
-
if (next >= maxScrollRef.current) setPinned(true);
|
|
6897
|
-
return next;
|
|
6898
|
-
});
|
|
6899
|
-
}, []);
|
|
6900
|
-
const schedule = useCallback2(
|
|
6901
|
-
(delta) => {
|
|
6902
|
-
pendingDelta.current += delta;
|
|
6903
|
-
if (flushTimer.current !== null) return;
|
|
6904
|
-
flushTimer.current = setTimeout(flush, COALESCE_MS);
|
|
6905
|
-
},
|
|
6906
|
-
[flush]
|
|
6907
|
-
);
|
|
6908
|
-
useEffect4(() => {
|
|
6909
|
-
return () => {
|
|
6910
|
-
if (flushTimer.current !== null) {
|
|
6911
|
-
clearTimeout(flushTimer.current);
|
|
6912
|
-
flushTimer.current = null;
|
|
6913
|
-
}
|
|
6914
|
-
};
|
|
6915
|
-
}, []);
|
|
6916
|
-
useEffect4(() => {
|
|
6917
|
-
if (pinned) setScrollRows(maxScroll);
|
|
6918
|
-
}, [pinned, maxScroll]);
|
|
6919
|
-
useEffect4(() => {
|
|
6920
|
-
if (scrollRows > maxScroll) setScrollRows(maxScroll);
|
|
6921
|
-
}, [scrollRows, maxScroll]);
|
|
6922
|
-
const scrollUp = useCallback2(() => schedule(-SCROLL_PAGE_ROWS), [schedule]);
|
|
6923
|
-
const scrollDown = useCallback2(() => schedule(SCROLL_PAGE_ROWS), [schedule]);
|
|
6924
|
-
const jumpToBottom = useCallback2(() => {
|
|
6925
|
-
pendingDelta.current = 0;
|
|
6926
|
-
if (flushTimer.current !== null) {
|
|
6927
|
-
clearTimeout(flushTimer.current);
|
|
6928
|
-
flushTimer.current = null;
|
|
6929
|
-
}
|
|
6930
|
-
setPinned(true);
|
|
6931
|
-
}, []);
|
|
6932
|
-
const setMaxScroll = useCallback2((rows) => {
|
|
6933
|
-
maxScrollRef.current = rows;
|
|
6934
|
-
setMaxScrollState(rows);
|
|
6935
|
-
}, []);
|
|
6936
|
-
return { scrollRows, pinned, scrollUp, scrollDown, jumpToBottom, setMaxScroll };
|
|
6937
|
-
}
|
|
6938
|
-
|
|
6939
|
-
// src/cli/ui/hooks/useCodeMode.ts
|
|
6940
|
-
import { useCallback as useCallback3 } from "react";
|
|
6941
|
-
function useCodeMode(opts) {
|
|
6942
|
-
const { codeMode, pendingEdits, currentRootDir, session, syncPendingCount, recordEdit } = opts;
|
|
6943
|
-
const codeApply = useCallback3(
|
|
6944
|
-
(indices) => {
|
|
6945
|
-
if (!codeMode) return "not in code mode";
|
|
6946
|
-
const blocks = pendingEdits.current;
|
|
6947
|
-
if (blocks.length === 0) {
|
|
6948
|
-
return "nothing pending \u2014 the model hasn't proposed edits since the last /apply or /discard.";
|
|
6949
|
-
}
|
|
6950
|
-
const useSubset = indices !== void 0 && indices.length > 0;
|
|
6951
|
-
const { selected, remaining } = useSubset ? partitionEdits(blocks, indices) : { selected: blocks, remaining: [] };
|
|
6952
|
-
if (selected.length === 0) {
|
|
6953
|
-
return "\u25B8 no edits matched those indices \u2014 nothing applied. Use /apply with no args to commit them all.";
|
|
6954
|
-
}
|
|
6955
|
-
const snaps = snapshotBeforeEdits(selected, currentRootDir);
|
|
6956
|
-
const results = applyEditBlocks(selected, currentRootDir);
|
|
6957
|
-
const anyApplied = results.some((r) => r.status === "applied" || r.status === "created");
|
|
6958
|
-
if (anyApplied) recordEdit("review-apply", selected, results, snaps);
|
|
6959
|
-
pendingEdits.current = remaining;
|
|
6960
|
-
if (remaining.length === 0) clearPendingEdits(session ?? null);
|
|
6961
|
-
else savePendingEdits(session ?? null, remaining);
|
|
6962
|
-
syncPendingCount();
|
|
6963
|
-
const tail = remaining.length > 0 ? `
|
|
6964
|
-
\u25B8 ${remaining.length} edit block(s) still pending \u2014 /apply or /discard to clear them.` : "";
|
|
6965
|
-
return formatEditResults(results) + tail;
|
|
6966
|
-
},
|
|
6967
|
-
[codeMode, currentRootDir, session, syncPendingCount, recordEdit, pendingEdits]
|
|
6968
|
-
);
|
|
6969
|
-
const codeDiscard = useCallback3(
|
|
6970
|
-
(indices) => {
|
|
6971
|
-
const blocks = pendingEdits.current;
|
|
6972
|
-
if (blocks.length === 0) return "nothing pending to discard.";
|
|
6973
|
-
const useSubset = indices !== void 0 && indices.length > 0;
|
|
6974
|
-
const { selected, remaining } = useSubset ? partitionEdits(blocks, indices) : { selected: blocks, remaining: [] };
|
|
6975
|
-
if (selected.length === 0) {
|
|
6976
|
-
return "\u25B8 no edits matched those indices \u2014 nothing discarded.";
|
|
6977
|
-
}
|
|
6978
|
-
pendingEdits.current = remaining;
|
|
6979
|
-
if (remaining.length === 0) clearPendingEdits(session ?? null);
|
|
6980
|
-
else savePendingEdits(session ?? null, remaining);
|
|
6981
|
-
syncPendingCount();
|
|
6982
|
-
const tail = remaining.length > 0 ? ` (${remaining.length} block(s) still pending)` : ". Nothing was written to disk.";
|
|
6983
|
-
return `\u25B8 discarded ${selected.length} pending edit block(s)${tail}`;
|
|
6984
|
-
},
|
|
6985
|
-
[session, syncPendingCount, pendingEdits]
|
|
6986
|
-
);
|
|
6987
|
-
return { codeApply, codeDiscard };
|
|
6988
|
-
}
|
|
6989
|
-
|
|
6990
|
-
// src/cli/ui/hooks/useInputRecall.ts
|
|
6991
|
-
import { useCallback as useCallback4, useRef as useRef3 } from "react";
|
|
6992
|
-
function useInputRecall(setInput) {
|
|
6993
|
-
const promptHistory = useRef3([]);
|
|
6994
|
-
const historyCursor = useRef3(-1);
|
|
6995
|
-
const recallPrev = useCallback4(() => {
|
|
6996
|
-
const hist = promptHistory.current;
|
|
6997
|
-
if (hist.length === 0) return;
|
|
6998
|
-
const nextCursor = Math.min(historyCursor.current + 1, hist.length - 1);
|
|
6999
|
-
historyCursor.current = nextCursor;
|
|
7000
|
-
setInput(hist[hist.length - 1 - nextCursor] ?? "");
|
|
7001
|
-
}, [setInput]);
|
|
7002
|
-
const recallNext = useCallback4(() => {
|
|
7003
|
-
if (historyCursor.current < 0) return;
|
|
7004
|
-
const hist = promptHistory.current;
|
|
7005
|
-
const nextCursor = historyCursor.current - 1;
|
|
7006
|
-
historyCursor.current = nextCursor;
|
|
7007
|
-
setInput(nextCursor < 0 ? "" : hist[hist.length - 1 - nextCursor] ?? "");
|
|
7008
|
-
}, [setInput]);
|
|
7009
|
-
const pushHistory = useCallback4((text) => {
|
|
7010
|
-
promptHistory.current.push(text);
|
|
7011
|
-
}, []);
|
|
7012
|
-
const resetCursor = useCallback4(() => {
|
|
7013
|
-
historyCursor.current = -1;
|
|
7014
|
-
}, []);
|
|
7015
|
-
return { recallPrev, recallNext, pushHistory, resetCursor };
|
|
7016
|
-
}
|
|
7017
|
-
|
|
7018
|
-
// src/cli/ui/hooks/useLoopMode.ts
|
|
7019
|
-
import { useCallback as useCallback5, useEffect as useEffect5, useRef as useRef4, useState as useState15 } from "react";
|
|
7020
|
-
function useLoopMode(opts) {
|
|
7021
|
-
const { log, busyRef, handleSubmitRef } = opts;
|
|
7022
|
-
const [activeLoop, setActiveLoop] = useState15(null);
|
|
7023
|
-
const activeLoopRef = useRef4(null);
|
|
7024
|
-
const loopTimerRef = useRef4(null);
|
|
7025
|
-
const loopFiringRef = useRef4(false);
|
|
7026
|
-
useEffect5(() => {
|
|
7027
|
-
activeLoopRef.current = activeLoop;
|
|
7028
|
-
}, [activeLoop]);
|
|
7029
|
-
const stopLoop = useCallback5(() => {
|
|
7030
|
-
if (loopTimerRef.current) {
|
|
7031
|
-
clearTimeout(loopTimerRef.current);
|
|
7032
|
-
loopTimerRef.current = null;
|
|
7033
|
-
}
|
|
7034
|
-
const cur = activeLoopRef.current;
|
|
7035
|
-
if (!cur) return;
|
|
7036
|
-
setActiveLoop(null);
|
|
7037
|
-
log.pushInfo(`\u25B8 loop stopped (after ${cur.iter} iter${cur.iter === 1 ? "" : "s"}).`);
|
|
7038
|
-
}, [log]);
|
|
7039
|
-
const startLoop = useCallback5((intervalMs, prompt) => {
|
|
7040
|
-
if (loopTimerRef.current) {
|
|
7041
|
-
clearTimeout(loopTimerRef.current);
|
|
7042
|
-
loopTimerRef.current = null;
|
|
7043
|
-
}
|
|
7044
|
-
setActiveLoop({
|
|
7045
|
-
prompt,
|
|
7046
|
-
intervalMs,
|
|
7047
|
-
nextFireAt: Date.now() + intervalMs,
|
|
7048
|
-
iter: 0
|
|
7049
|
-
});
|
|
7050
|
-
}, []);
|
|
7051
|
-
const getLoopStatus = useCallback5(() => {
|
|
7052
|
-
const cur = activeLoopRef.current;
|
|
7053
|
-
if (!cur) return null;
|
|
7054
|
-
return {
|
|
7055
|
-
prompt: cur.prompt,
|
|
7056
|
-
intervalMs: cur.intervalMs,
|
|
7057
|
-
iter: cur.iter,
|
|
7058
|
-
nextFireMs: Math.max(0, cur.nextFireAt - Date.now())
|
|
7059
|
-
};
|
|
7060
|
-
}, []);
|
|
7061
|
-
const isLoopActive = useCallback5(() => activeLoopRef.current !== null, []);
|
|
7062
|
-
const isLoopFiring = useCallback5(() => loopFiringRef.current, []);
|
|
7063
|
-
const clearFiringFlag = useCallback5(() => {
|
|
7064
|
-
loopFiringRef.current = false;
|
|
7065
|
-
}, []);
|
|
7066
|
-
useEffect5(() => {
|
|
7067
|
-
if (!activeLoop) return;
|
|
7068
|
-
const delay = Math.max(0, activeLoop.nextFireAt - Date.now());
|
|
7069
|
-
const timer = setTimeout(async () => {
|
|
7070
|
-
loopTimerRef.current = null;
|
|
7071
|
-
if (busyRef.current) {
|
|
7072
|
-
setActiveLoop((cur2) => cur2 ? { ...cur2, nextFireAt: Date.now() + 1e3 } : cur2);
|
|
7073
|
-
return;
|
|
7074
|
-
}
|
|
7075
|
-
const cur = activeLoopRef.current;
|
|
7076
|
-
if (!cur) return;
|
|
7077
|
-
const nextIter = cur.iter + 1;
|
|
7078
|
-
setActiveLoop(
|
|
7079
|
-
(c) => c ? { ...c, iter: nextIter, nextFireAt: Date.now() + cur.intervalMs } : c
|
|
7080
|
-
);
|
|
7081
|
-
log.pushInfo(`\u25B8 /loop iter ${nextIter} \u2192 ${cur.prompt}`);
|
|
7082
|
-
loopFiringRef.current = true;
|
|
7083
|
-
try {
|
|
7084
|
-
await handleSubmitRef.current?.(cur.prompt);
|
|
7085
|
-
} catch {
|
|
7086
|
-
stopLoop();
|
|
7087
|
-
} finally {
|
|
7088
|
-
loopFiringRef.current = false;
|
|
7089
|
-
}
|
|
7090
|
-
}, delay);
|
|
7091
|
-
loopTimerRef.current = timer;
|
|
7092
|
-
return () => clearTimeout(timer);
|
|
7093
|
-
}, [activeLoop, stopLoop, log, busyRef, handleSubmitRef]);
|
|
7094
|
-
return {
|
|
7095
|
-
startLoop,
|
|
7096
|
-
stopLoop,
|
|
7097
|
-
getLoopStatus,
|
|
7098
|
-
isLoopActive,
|
|
7099
|
-
isLoopFiring,
|
|
7100
|
-
clearFiringFlag,
|
|
7101
|
-
activeLoop
|
|
7102
|
-
};
|
|
7103
|
-
}
|
|
7104
|
-
|
|
7105
|
-
// src/cli/ui/hooks/useQuit.ts
|
|
7106
|
-
import { useCallback as useCallback6, useEffect as useEffect6 } from "react";
|
|
7107
|
-
function useQuit(transcriptRef) {
|
|
7108
|
-
const quitProcess = useCallback6(() => {
|
|
7109
|
-
transcriptRef.current?.end();
|
|
7110
|
-
process.exit(0);
|
|
7111
|
-
}, [transcriptRef]);
|
|
7112
|
-
useEffect6(() => {
|
|
7113
|
-
process.on("SIGINT", quitProcess);
|
|
7114
|
-
return () => {
|
|
7115
|
-
process.off("SIGINT", quitProcess);
|
|
7116
|
-
};
|
|
7117
|
-
}, [quitProcess]);
|
|
7118
|
-
return quitProcess;
|
|
7119
|
-
}
|
|
7120
|
-
|
|
7121
|
-
// src/cli/ui/hooks/useScrollback.ts
|
|
7122
|
-
import { useMemo as useMemo7 } from "react";
|
|
7123
|
-
|
|
7124
6942
|
// src/cli/ui/state/provider.tsx
|
|
7125
6943
|
import React29 from "react";
|
|
7126
6944
|
|
|
@@ -7450,68 +7268,343 @@ function initialState(session, cards = []) {
|
|
|
7450
7268
|
sessionCost: 0,
|
|
7451
7269
|
cacheHit: 0
|
|
7452
7270
|
},
|
|
7453
|
-
focusedCardId: null,
|
|
7454
|
-
toasts: [],
|
|
7455
|
-
turnInProgress: false
|
|
7456
|
-
};
|
|
7271
|
+
focusedCardId: null,
|
|
7272
|
+
toasts: [],
|
|
7273
|
+
turnInProgress: false
|
|
7274
|
+
};
|
|
7275
|
+
}
|
|
7276
|
+
|
|
7277
|
+
// src/cli/ui/state/store.ts
|
|
7278
|
+
function createStore(session, initialCards) {
|
|
7279
|
+
let state = initialState(session, initialCards);
|
|
7280
|
+
const stateListeners = /* @__PURE__ */ new Set();
|
|
7281
|
+
const eventListeners = /* @__PURE__ */ new Set();
|
|
7282
|
+
return {
|
|
7283
|
+
getState() {
|
|
7284
|
+
return state;
|
|
7285
|
+
},
|
|
7286
|
+
dispatch(event) {
|
|
7287
|
+
state = reduce(state, event);
|
|
7288
|
+
for (const listener of stateListeners) listener();
|
|
7289
|
+
for (const listener of eventListeners) listener(event);
|
|
7290
|
+
},
|
|
7291
|
+
subscribe(listener) {
|
|
7292
|
+
stateListeners.add(listener);
|
|
7293
|
+
return () => {
|
|
7294
|
+
stateListeners.delete(listener);
|
|
7295
|
+
};
|
|
7296
|
+
},
|
|
7297
|
+
onEvent(listener) {
|
|
7298
|
+
eventListeners.add(listener);
|
|
7299
|
+
return () => {
|
|
7300
|
+
eventListeners.delete(listener);
|
|
7301
|
+
};
|
|
7302
|
+
}
|
|
7303
|
+
};
|
|
7304
|
+
}
|
|
7305
|
+
|
|
7306
|
+
// src/cli/ui/state/provider.tsx
|
|
7307
|
+
var StoreCtx = React29.createContext(null);
|
|
7308
|
+
function AgentStoreProvider({
|
|
7309
|
+
session,
|
|
7310
|
+
initialCards,
|
|
7311
|
+
children
|
|
7312
|
+
}) {
|
|
7313
|
+
const initialCardsRef = React29.useRef(initialCards);
|
|
7314
|
+
const store = React29.useMemo(() => createStore(session, initialCardsRef.current), [session]);
|
|
7315
|
+
return /* @__PURE__ */ React29.createElement(StoreCtx.Provider, { value: store }, children);
|
|
7316
|
+
}
|
|
7317
|
+
function useAgentStore() {
|
|
7318
|
+
const store = React29.useContext(StoreCtx);
|
|
7319
|
+
if (!store) throw new Error("useAgentStore must be used inside AgentStoreProvider");
|
|
7320
|
+
return store;
|
|
7321
|
+
}
|
|
7322
|
+
function useAgentState(selector) {
|
|
7323
|
+
const store = useAgentStore();
|
|
7324
|
+
const subscribe = React29.useCallback((cb) => store.subscribe(cb), [store]);
|
|
7325
|
+
const getSnapshot = React29.useCallback(() => selector(store.getState()), [store, selector]);
|
|
7326
|
+
return React29.useSyncExternalStore(subscribe, getSnapshot, getSnapshot);
|
|
7327
|
+
}
|
|
7328
|
+
function useDispatch() {
|
|
7329
|
+
return useAgentStore().dispatch;
|
|
7330
|
+
}
|
|
7331
|
+
|
|
7332
|
+
// src/cli/ui/hooks/useActivityPhase.ts
|
|
7333
|
+
function deriveActivityLabel(cards) {
|
|
7334
|
+
if (cards.some((c) => c.kind === "reasoning" && c.streaming)) return "thinking\u2026";
|
|
7335
|
+
const last = cards[cards.length - 1];
|
|
7336
|
+
if (!last || last.kind === "user") return "waiting for model\u2026";
|
|
7337
|
+
return "processing\u2026";
|
|
7338
|
+
}
|
|
7339
|
+
function useActivityLabel() {
|
|
7340
|
+
return useAgentState((s) => deriveActivityLabel(s.cards));
|
|
7341
|
+
}
|
|
7342
|
+
|
|
7343
|
+
// src/cli/ui/hooks/useAgentSession.ts
|
|
7344
|
+
import { useMemo as useMemo6 } from "react";
|
|
7345
|
+
function useAgentSession({
|
|
7346
|
+
sessionId,
|
|
7347
|
+
model: model2,
|
|
7348
|
+
workspace,
|
|
7349
|
+
branch
|
|
7350
|
+
}) {
|
|
7351
|
+
return useMemo6(
|
|
7352
|
+
() => ({
|
|
7353
|
+
id: sessionId ?? "default",
|
|
7354
|
+
branch: branch ?? "main",
|
|
7355
|
+
workspace,
|
|
7356
|
+
model: model2
|
|
7357
|
+
}),
|
|
7358
|
+
[sessionId, branch, workspace, model2]
|
|
7359
|
+
);
|
|
7360
|
+
}
|
|
7361
|
+
|
|
7362
|
+
// src/cli/ui/hooks/useChatScroll.ts
|
|
7363
|
+
import { useCallback as useCallback2, useEffect as useEffect4, useRef as useRef2, useState as useState14 } from "react";
|
|
7364
|
+
var SCROLL_PAGE_ROWS = 3;
|
|
7365
|
+
var COALESCE_MS = 16;
|
|
7366
|
+
function useChatScroll() {
|
|
7367
|
+
const [scrollRows, setScrollRows] = useState14(0);
|
|
7368
|
+
const [pinned, setPinned] = useState14(true);
|
|
7369
|
+
const [maxScroll, setMaxScrollState] = useState14(0);
|
|
7370
|
+
const maxScrollRef = useRef2(0);
|
|
7371
|
+
const pendingDelta = useRef2(0);
|
|
7372
|
+
const flushTimer = useRef2(null);
|
|
7373
|
+
const flush = useCallback2(() => {
|
|
7374
|
+
flushTimer.current = null;
|
|
7375
|
+
const d = pendingDelta.current;
|
|
7376
|
+
pendingDelta.current = 0;
|
|
7377
|
+
if (d === 0) return;
|
|
7378
|
+
if (d < 0) setPinned(false);
|
|
7379
|
+
setScrollRows((o) => {
|
|
7380
|
+
const next = Math.max(0, Math.min(maxScrollRef.current, o + d));
|
|
7381
|
+
if (next >= maxScrollRef.current) setPinned(true);
|
|
7382
|
+
return next;
|
|
7383
|
+
});
|
|
7384
|
+
}, []);
|
|
7385
|
+
const schedule = useCallback2(
|
|
7386
|
+
(delta) => {
|
|
7387
|
+
pendingDelta.current += delta;
|
|
7388
|
+
if (flushTimer.current !== null) return;
|
|
7389
|
+
flushTimer.current = setTimeout(flush, COALESCE_MS);
|
|
7390
|
+
},
|
|
7391
|
+
[flush]
|
|
7392
|
+
);
|
|
7393
|
+
useEffect4(() => {
|
|
7394
|
+
return () => {
|
|
7395
|
+
if (flushTimer.current !== null) {
|
|
7396
|
+
clearTimeout(flushTimer.current);
|
|
7397
|
+
flushTimer.current = null;
|
|
7398
|
+
}
|
|
7399
|
+
};
|
|
7400
|
+
}, []);
|
|
7401
|
+
useEffect4(() => {
|
|
7402
|
+
if (pinned) setScrollRows(maxScroll);
|
|
7403
|
+
}, [pinned, maxScroll]);
|
|
7404
|
+
useEffect4(() => {
|
|
7405
|
+
if (scrollRows > maxScroll) setScrollRows(maxScroll);
|
|
7406
|
+
}, [scrollRows, maxScroll]);
|
|
7407
|
+
const scrollUp = useCallback2(() => schedule(-SCROLL_PAGE_ROWS), [schedule]);
|
|
7408
|
+
const scrollDown = useCallback2(() => schedule(SCROLL_PAGE_ROWS), [schedule]);
|
|
7409
|
+
const jumpToBottom = useCallback2(() => {
|
|
7410
|
+
pendingDelta.current = 0;
|
|
7411
|
+
if (flushTimer.current !== null) {
|
|
7412
|
+
clearTimeout(flushTimer.current);
|
|
7413
|
+
flushTimer.current = null;
|
|
7414
|
+
}
|
|
7415
|
+
setPinned(true);
|
|
7416
|
+
}, []);
|
|
7417
|
+
const setMaxScroll = useCallback2((rows) => {
|
|
7418
|
+
maxScrollRef.current = rows;
|
|
7419
|
+
setMaxScrollState(rows);
|
|
7420
|
+
}, []);
|
|
7421
|
+
return { scrollRows, pinned, scrollUp, scrollDown, jumpToBottom, setMaxScroll };
|
|
7422
|
+
}
|
|
7423
|
+
|
|
7424
|
+
// src/cli/ui/hooks/useCodeMode.ts
|
|
7425
|
+
import { useCallback as useCallback3 } from "react";
|
|
7426
|
+
function useCodeMode(opts) {
|
|
7427
|
+
const { codeMode, pendingEdits, currentRootDir, session, syncPendingCount, recordEdit } = opts;
|
|
7428
|
+
const codeApply = useCallback3(
|
|
7429
|
+
(indices) => {
|
|
7430
|
+
if (!codeMode) return "not in code mode";
|
|
7431
|
+
const blocks = pendingEdits.current;
|
|
7432
|
+
if (blocks.length === 0) {
|
|
7433
|
+
return "nothing pending \u2014 the model hasn't proposed edits since the last /apply or /discard.";
|
|
7434
|
+
}
|
|
7435
|
+
const useSubset = indices !== void 0 && indices.length > 0;
|
|
7436
|
+
const { selected, remaining } = useSubset ? partitionEdits(blocks, indices) : { selected: blocks, remaining: [] };
|
|
7437
|
+
if (selected.length === 0) {
|
|
7438
|
+
return "\u25B8 no edits matched those indices \u2014 nothing applied. Use /apply with no args to commit them all.";
|
|
7439
|
+
}
|
|
7440
|
+
const snaps = snapshotBeforeEdits(selected, currentRootDir);
|
|
7441
|
+
const results = applyEditBlocks(selected, currentRootDir);
|
|
7442
|
+
const anyApplied = results.some((r) => r.status === "applied" || r.status === "created");
|
|
7443
|
+
if (anyApplied) recordEdit("review-apply", selected, results, snaps);
|
|
7444
|
+
pendingEdits.current = remaining;
|
|
7445
|
+
if (remaining.length === 0) clearPendingEdits(session ?? null);
|
|
7446
|
+
else savePendingEdits(session ?? null, remaining);
|
|
7447
|
+
syncPendingCount();
|
|
7448
|
+
const tail = remaining.length > 0 ? `
|
|
7449
|
+
\u25B8 ${remaining.length} edit block(s) still pending \u2014 /apply or /discard to clear them.` : "";
|
|
7450
|
+
return formatEditResults(results) + tail;
|
|
7451
|
+
},
|
|
7452
|
+
[codeMode, currentRootDir, session, syncPendingCount, recordEdit, pendingEdits]
|
|
7453
|
+
);
|
|
7454
|
+
const codeDiscard = useCallback3(
|
|
7455
|
+
(indices) => {
|
|
7456
|
+
const blocks = pendingEdits.current;
|
|
7457
|
+
if (blocks.length === 0) return "nothing pending to discard.";
|
|
7458
|
+
const useSubset = indices !== void 0 && indices.length > 0;
|
|
7459
|
+
const { selected, remaining } = useSubset ? partitionEdits(blocks, indices) : { selected: blocks, remaining: [] };
|
|
7460
|
+
if (selected.length === 0) {
|
|
7461
|
+
return "\u25B8 no edits matched those indices \u2014 nothing discarded.";
|
|
7462
|
+
}
|
|
7463
|
+
pendingEdits.current = remaining;
|
|
7464
|
+
if (remaining.length === 0) clearPendingEdits(session ?? null);
|
|
7465
|
+
else savePendingEdits(session ?? null, remaining);
|
|
7466
|
+
syncPendingCount();
|
|
7467
|
+
const tail = remaining.length > 0 ? ` (${remaining.length} block(s) still pending)` : ". Nothing was written to disk.";
|
|
7468
|
+
return `\u25B8 discarded ${selected.length} pending edit block(s)${tail}`;
|
|
7469
|
+
},
|
|
7470
|
+
[session, syncPendingCount, pendingEdits]
|
|
7471
|
+
);
|
|
7472
|
+
return { codeApply, codeDiscard };
|
|
7457
7473
|
}
|
|
7458
7474
|
|
|
7459
|
-
// src/cli/ui/
|
|
7460
|
-
|
|
7461
|
-
|
|
7462
|
-
const
|
|
7463
|
-
const
|
|
7464
|
-
|
|
7465
|
-
|
|
7466
|
-
|
|
7467
|
-
|
|
7468
|
-
|
|
7469
|
-
|
|
7470
|
-
|
|
7471
|
-
|
|
7472
|
-
|
|
7473
|
-
|
|
7474
|
-
|
|
7475
|
-
|
|
7476
|
-
|
|
7477
|
-
|
|
7478
|
-
|
|
7479
|
-
|
|
7480
|
-
|
|
7481
|
-
|
|
7482
|
-
|
|
7483
|
-
|
|
7475
|
+
// src/cli/ui/hooks/useInputRecall.ts
|
|
7476
|
+
import { useCallback as useCallback4, useRef as useRef3 } from "react";
|
|
7477
|
+
function useInputRecall(setInput) {
|
|
7478
|
+
const promptHistory = useRef3([]);
|
|
7479
|
+
const historyCursor = useRef3(-1);
|
|
7480
|
+
const recallPrev = useCallback4(() => {
|
|
7481
|
+
const hist = promptHistory.current;
|
|
7482
|
+
if (hist.length === 0) return;
|
|
7483
|
+
const nextCursor = Math.min(historyCursor.current + 1, hist.length - 1);
|
|
7484
|
+
historyCursor.current = nextCursor;
|
|
7485
|
+
setInput(hist[hist.length - 1 - nextCursor] ?? "");
|
|
7486
|
+
}, [setInput]);
|
|
7487
|
+
const recallNext = useCallback4(() => {
|
|
7488
|
+
if (historyCursor.current < 0) return;
|
|
7489
|
+
const hist = promptHistory.current;
|
|
7490
|
+
const nextCursor = historyCursor.current - 1;
|
|
7491
|
+
historyCursor.current = nextCursor;
|
|
7492
|
+
setInput(nextCursor < 0 ? "" : hist[hist.length - 1 - nextCursor] ?? "");
|
|
7493
|
+
}, [setInput]);
|
|
7494
|
+
const pushHistory = useCallback4((text) => {
|
|
7495
|
+
promptHistory.current.push(text);
|
|
7496
|
+
}, []);
|
|
7497
|
+
const resetCursor = useCallback4(() => {
|
|
7498
|
+
historyCursor.current = -1;
|
|
7499
|
+
}, []);
|
|
7500
|
+
return { recallPrev, recallNext, pushHistory, resetCursor };
|
|
7501
|
+
}
|
|
7502
|
+
|
|
7503
|
+
// src/cli/ui/hooks/useLoopMode.ts
|
|
7504
|
+
import { useCallback as useCallback5, useEffect as useEffect5, useRef as useRef4, useState as useState15 } from "react";
|
|
7505
|
+
function useLoopMode(opts) {
|
|
7506
|
+
const { log, busyRef, handleSubmitRef } = opts;
|
|
7507
|
+
const [activeLoop, setActiveLoop] = useState15(null);
|
|
7508
|
+
const activeLoopRef = useRef4(null);
|
|
7509
|
+
const loopTimerRef = useRef4(null);
|
|
7510
|
+
const loopFiringRef = useRef4(false);
|
|
7511
|
+
useEffect5(() => {
|
|
7512
|
+
activeLoopRef.current = activeLoop;
|
|
7513
|
+
}, [activeLoop]);
|
|
7514
|
+
const stopLoop = useCallback5(() => {
|
|
7515
|
+
if (loopTimerRef.current) {
|
|
7516
|
+
clearTimeout(loopTimerRef.current);
|
|
7517
|
+
loopTimerRef.current = null;
|
|
7518
|
+
}
|
|
7519
|
+
const cur = activeLoopRef.current;
|
|
7520
|
+
if (!cur) return;
|
|
7521
|
+
setActiveLoop(null);
|
|
7522
|
+
log.pushInfo(`\u25B8 loop stopped (after ${cur.iter} iter${cur.iter === 1 ? "" : "s"}).`);
|
|
7523
|
+
}, [log]);
|
|
7524
|
+
const startLoop = useCallback5((intervalMs, prompt) => {
|
|
7525
|
+
if (loopTimerRef.current) {
|
|
7526
|
+
clearTimeout(loopTimerRef.current);
|
|
7527
|
+
loopTimerRef.current = null;
|
|
7484
7528
|
}
|
|
7529
|
+
setActiveLoop({
|
|
7530
|
+
prompt,
|
|
7531
|
+
intervalMs,
|
|
7532
|
+
nextFireAt: Date.now() + intervalMs,
|
|
7533
|
+
iter: 0
|
|
7534
|
+
});
|
|
7535
|
+
}, []);
|
|
7536
|
+
const getLoopStatus = useCallback5(() => {
|
|
7537
|
+
const cur = activeLoopRef.current;
|
|
7538
|
+
if (!cur) return null;
|
|
7539
|
+
return {
|
|
7540
|
+
prompt: cur.prompt,
|
|
7541
|
+
intervalMs: cur.intervalMs,
|
|
7542
|
+
iter: cur.iter,
|
|
7543
|
+
nextFireMs: Math.max(0, cur.nextFireAt - Date.now())
|
|
7544
|
+
};
|
|
7545
|
+
}, []);
|
|
7546
|
+
const isLoopActive = useCallback5(() => activeLoopRef.current !== null, []);
|
|
7547
|
+
const isLoopFiring = useCallback5(() => loopFiringRef.current, []);
|
|
7548
|
+
const clearFiringFlag = useCallback5(() => {
|
|
7549
|
+
loopFiringRef.current = false;
|
|
7550
|
+
}, []);
|
|
7551
|
+
useEffect5(() => {
|
|
7552
|
+
if (!activeLoop) return;
|
|
7553
|
+
const delay = Math.max(0, activeLoop.nextFireAt - Date.now());
|
|
7554
|
+
const timer = setTimeout(async () => {
|
|
7555
|
+
loopTimerRef.current = null;
|
|
7556
|
+
if (busyRef.current) {
|
|
7557
|
+
setActiveLoop((cur2) => cur2 ? { ...cur2, nextFireAt: Date.now() + 1e3 } : cur2);
|
|
7558
|
+
return;
|
|
7559
|
+
}
|
|
7560
|
+
const cur = activeLoopRef.current;
|
|
7561
|
+
if (!cur) return;
|
|
7562
|
+
const nextIter = cur.iter + 1;
|
|
7563
|
+
setActiveLoop(
|
|
7564
|
+
(c) => c ? { ...c, iter: nextIter, nextFireAt: Date.now() + cur.intervalMs } : c
|
|
7565
|
+
);
|
|
7566
|
+
log.pushInfo(`\u25B8 /loop iter ${nextIter} \u2192 ${cur.prompt}`);
|
|
7567
|
+
loopFiringRef.current = true;
|
|
7568
|
+
try {
|
|
7569
|
+
await handleSubmitRef.current?.(cur.prompt);
|
|
7570
|
+
} catch {
|
|
7571
|
+
stopLoop();
|
|
7572
|
+
} finally {
|
|
7573
|
+
loopFiringRef.current = false;
|
|
7574
|
+
}
|
|
7575
|
+
}, delay);
|
|
7576
|
+
loopTimerRef.current = timer;
|
|
7577
|
+
return () => clearTimeout(timer);
|
|
7578
|
+
}, [activeLoop, stopLoop, log, busyRef, handleSubmitRef]);
|
|
7579
|
+
return {
|
|
7580
|
+
startLoop,
|
|
7581
|
+
stopLoop,
|
|
7582
|
+
getLoopStatus,
|
|
7583
|
+
isLoopActive,
|
|
7584
|
+
isLoopFiring,
|
|
7585
|
+
clearFiringFlag,
|
|
7586
|
+
activeLoop
|
|
7485
7587
|
};
|
|
7486
7588
|
}
|
|
7487
7589
|
|
|
7488
|
-
// src/cli/ui/
|
|
7489
|
-
|
|
7490
|
-
function
|
|
7491
|
-
|
|
7492
|
-
|
|
7493
|
-
|
|
7494
|
-
})
|
|
7495
|
-
|
|
7496
|
-
|
|
7497
|
-
|
|
7498
|
-
|
|
7499
|
-
|
|
7500
|
-
|
|
7501
|
-
|
|
7502
|
-
return store;
|
|
7503
|
-
}
|
|
7504
|
-
function useAgentState(selector) {
|
|
7505
|
-
const store = useAgentStore();
|
|
7506
|
-
const subscribe = React29.useCallback((cb) => store.subscribe(cb), [store]);
|
|
7507
|
-
const getSnapshot = React29.useCallback(() => selector(store.getState()), [store, selector]);
|
|
7508
|
-
return React29.useSyncExternalStore(subscribe, getSnapshot, getSnapshot);
|
|
7509
|
-
}
|
|
7510
|
-
function useDispatch() {
|
|
7511
|
-
return useAgentStore().dispatch;
|
|
7590
|
+
// src/cli/ui/hooks/useQuit.ts
|
|
7591
|
+
import { useCallback as useCallback6, useEffect as useEffect6 } from "react";
|
|
7592
|
+
function useQuit(transcriptRef) {
|
|
7593
|
+
const quitProcess = useCallback6(() => {
|
|
7594
|
+
transcriptRef.current?.end();
|
|
7595
|
+
process.exit(0);
|
|
7596
|
+
}, [transcriptRef]);
|
|
7597
|
+
useEffect6(() => {
|
|
7598
|
+
process.on("SIGINT", quitProcess);
|
|
7599
|
+
return () => {
|
|
7600
|
+
process.off("SIGINT", quitProcess);
|
|
7601
|
+
};
|
|
7602
|
+
}, [quitProcess]);
|
|
7603
|
+
return quitProcess;
|
|
7512
7604
|
}
|
|
7513
7605
|
|
|
7514
7606
|
// src/cli/ui/hooks/useScrollback.ts
|
|
7607
|
+
import { useMemo as useMemo7 } from "react";
|
|
7515
7608
|
var seq = 0;
|
|
7516
7609
|
function nextId2(prefix) {
|
|
7517
7610
|
seq += 1;
|
|
@@ -7838,10 +7931,16 @@ function CtxCard({ card }) {
|
|
|
7838
7931
|
{
|
|
7839
7932
|
glyph: "\u2318",
|
|
7840
7933
|
tone: TONE.brand,
|
|
7841
|
-
title: "context",
|
|
7934
|
+
title: t("cardTitles.context"),
|
|
7842
7935
|
meta: [`${used.toLocaleString()} / ${cap.toLocaleString()} (${usedPct.toFixed(1)}%)`]
|
|
7843
7936
|
}
|
|
7844
|
-
), row("system", card.systemTokens, card.systemTokens / cap, TONE.brand), row("tools", card.toolsTokens, card.toolsTokens / cap, TONE.warn), row("log", card.logTokens, card.logTokens / cap, TONE.ok), row("input", card.inputTokens, card.inputTokens / cap, TONE.accent), card.topTools.length > 0 ? /* @__PURE__ */ React32.createElement(React32.Fragment, null, /* @__PURE__ */ React32.createElement(Text26, { color: FG.faint },
|
|
7937
|
+
), row(t("cardLabels.system"), card.systemTokens, card.systemTokens / cap, TONE.brand), row(t("cardLabels.tools"), card.toolsTokens, card.toolsTokens / cap, TONE.warn), row(t("cardLabels.log"), card.logTokens, card.logTokens / cap, TONE.ok), row(t("cardLabels.input"), card.inputTokens, card.inputTokens / cap, TONE.accent), card.topTools.length > 0 ? /* @__PURE__ */ React32.createElement(React32.Fragment, null, /* @__PURE__ */ React32.createElement(Text26, { color: FG.faint }, `${t("cardLabels.topTools")} \xB7 ${card.toolsCount} ${t("cardLabels.tools")} \xB7 ${card.logMessages} ${t("cardLabels.logMsgs")}`), card.topTools.slice(0, 5).map((tool) => /* @__PURE__ */ React32.createElement(Box27, { key: `${tool.turn}-${tool.name}`, flexDirection: "row", gap: 1 }, /* @__PURE__ */ React32.createElement(Text26, { color: FG.sub }, tool.name), /* @__PURE__ */ React32.createElement(
|
|
7938
|
+
Text26,
|
|
7939
|
+
{
|
|
7940
|
+
color: FG.faint
|
|
7941
|
+
},
|
|
7942
|
+
`\xB7 ${t("cardLabels.turn")} ${tool.turn} \xB7 ${tool.tokens.toLocaleString()}`
|
|
7943
|
+
)))) : null);
|
|
7845
7944
|
}
|
|
7846
7945
|
|
|
7847
7946
|
// src/cli/ui/cards/DiffCard.tsx
|
|
@@ -7909,7 +8008,7 @@ import { Box as Box30, Text as Text29 } from "ink";
|
|
|
7909
8008
|
import React35 from "react";
|
|
7910
8009
|
var STACK_TAIL = 5;
|
|
7911
8010
|
function ErrorCard({ card }) {
|
|
7912
|
-
const retryNote = card.retries !== void 0 && card.retries > 0 ? `${card.retries}
|
|
8011
|
+
const retryNote = card.retries !== void 0 && card.retries > 0 ? `${card.retries} ${t("cardLabels.retries")}` : null;
|
|
7913
8012
|
const stackLines = card.stack ? card.stack.split("\n") : [];
|
|
7914
8013
|
const stackTrunc = stackLines.length > STACK_TAIL;
|
|
7915
8014
|
const stackVisible = stackTrunc ? stackLines.slice(-STACK_TAIL) : stackLines;
|
|
@@ -7921,10 +8020,13 @@ function ErrorCard({ card }) {
|
|
|
7921
8020
|
{
|
|
7922
8021
|
glyph: "\u2716",
|
|
7923
8022
|
tone: TONE.err,
|
|
7924
|
-
title: card.title || "error",
|
|
8023
|
+
title: card.title || t("cardTitles.error"),
|
|
7925
8024
|
meta: retryNote ? [retryNote] : void 0
|
|
7926
8025
|
}
|
|
7927
|
-
), messageLines.map((line, i) => /* @__PURE__ */ React35.createElement(Text29, { key: `${card.id}:msg:${i}`, color: TONE.err }, line || " ")), hasStack ? /* @__PURE__ */ React35.createElement(Box30, { flexDirection: "column", marginTop: 1 }, /* @__PURE__ */ React35.createElement(Text29, { color: FG.meta }, "
|
|
8026
|
+
), messageLines.map((line, i) => /* @__PURE__ */ React35.createElement(Text29, { key: `${card.id}:msg:${i}`, color: TONE.err }, line || " ")), hasStack ? /* @__PURE__ */ React35.createElement(Box30, { flexDirection: "column", marginTop: 1 }, /* @__PURE__ */ React35.createElement(Text29, { color: FG.meta }, t("cardLabels.stackTrace")), stackHidden > 0 ? /* @__PURE__ */ React35.createElement(Text29, { color: FG.faint }, t(
|
|
8027
|
+
stackHidden === 1 ? "cardLabels.earlierStackLine" : "cardLabels.earlierStackLines",
|
|
8028
|
+
{ count: stackHidden }
|
|
8029
|
+
)) : null, stackVisible.map((line, i) => /* @__PURE__ */ React35.createElement(Text29, { key: `${card.id}:stk:${stackHidden + i}`, color: FG.meta }, line || " "))) : null);
|
|
7928
8030
|
}
|
|
7929
8031
|
|
|
7930
8032
|
// src/cli/ui/cards/LiveCard.tsx
|
|
@@ -8090,7 +8192,7 @@ function anchorIndex(steps) {
|
|
|
8090
8192
|
}
|
|
8091
8193
|
|
|
8092
8194
|
// src/cli/ui/cards/ReasoningCard.tsx
|
|
8093
|
-
import { Box as Box34, Text as Text35, useStdout as
|
|
8195
|
+
import { Box as Box34, Text as Text35, useStdout as useStdout9 } from "ink";
|
|
8094
8196
|
import React41 from "react";
|
|
8095
8197
|
|
|
8096
8198
|
// src/frame/width.ts
|
|
@@ -8157,7 +8259,7 @@ function ReasoningCard({
|
|
|
8157
8259
|
card,
|
|
8158
8260
|
expanded
|
|
8159
8261
|
}) {
|
|
8160
|
-
const { stdout } =
|
|
8262
|
+
const { stdout } = useStdout9();
|
|
8161
8263
|
const cols = stdout?.columns ?? 80;
|
|
8162
8264
|
const lineCells = Math.max(20, cols - 4);
|
|
8163
8265
|
const allLines = card.text.length > 0 ? card.text.split("\n") : [];
|
|
@@ -8169,7 +8271,7 @@ function ReasoningHeader({ card }) {
|
|
|
8169
8271
|
const streamingActive = card.streaming && !card.aborted;
|
|
8170
8272
|
const headColor = card.aborted ? TONE.err : streamingActive ? TONE_ACTIVE.accent : TONE.accent;
|
|
8171
8273
|
const glyph = streamingActive ? "\u25C7" : "\u25C6";
|
|
8172
|
-
const title = streamingActive ? "
|
|
8274
|
+
const title = streamingActive ? t("cardTitles.reasoningEllipsis") : card.aborted ? t("cardTitles.reasoningAborted") : t("cardTitles.reasoning");
|
|
8173
8275
|
const meta = [];
|
|
8174
8276
|
const m = headerMeta(card);
|
|
8175
8277
|
if (m) meta.push(m);
|
|
@@ -8191,11 +8293,11 @@ function ReasoningHeader({ card }) {
|
|
|
8191
8293
|
}
|
|
8192
8294
|
function headerMeta(card) {
|
|
8193
8295
|
if (card.streaming) {
|
|
8194
|
-
return card.tokens > 0 ? `${card.tokens.toLocaleString()} tok` : "";
|
|
8296
|
+
return card.tokens > 0 ? `${card.tokens.toLocaleString()} ${t("cardLabels.tok")}` : "";
|
|
8195
8297
|
}
|
|
8196
8298
|
const parts = [];
|
|
8197
|
-
if (card.tokens > 0) parts.push(`${card.tokens.toLocaleString()} tok`);
|
|
8198
|
-
if (card.paragraphs > 0) parts.push(`${card.paragraphs}
|
|
8299
|
+
if (card.tokens > 0) parts.push(`${card.tokens.toLocaleString()} ${t("cardLabels.tok")}`);
|
|
8300
|
+
if (card.paragraphs > 0) parts.push(`${card.paragraphs} ${t("cardLabels.pilcrow")}`);
|
|
8199
8301
|
return parts.join(" \xB7 ");
|
|
8200
8302
|
}
|
|
8201
8303
|
function headerDuration(card) {
|
|
@@ -8246,18 +8348,24 @@ import React42 from "react";
|
|
|
8246
8348
|
function SearchCard({ card }) {
|
|
8247
8349
|
const fileCount = new Set(card.hits.map((h) => h.file)).size;
|
|
8248
8350
|
const elapsed = `${(card.elapsedMs / 1e3).toFixed(2)}s`;
|
|
8249
|
-
const stats2 =
|
|
8351
|
+
const stats2 = t(card.hits.length === 1 ? "cardLabels.hitSingular" : "cardLabels.hitsPlural", {
|
|
8352
|
+
count: card.hits.length,
|
|
8353
|
+
files: fileCount
|
|
8354
|
+
});
|
|
8250
8355
|
const grouped = groupByFile(card.hits.slice(0, 10));
|
|
8251
8356
|
return /* @__PURE__ */ React42.createElement(Card, { tone: TONE.info }, /* @__PURE__ */ React42.createElement(
|
|
8252
8357
|
CardHeader,
|
|
8253
8358
|
{
|
|
8254
8359
|
glyph: "\u2299",
|
|
8255
8360
|
tone: TONE.info,
|
|
8256
|
-
title: "search",
|
|
8361
|
+
title: t("cardTitles.search"),
|
|
8257
8362
|
subtitle: `"${card.query}"`,
|
|
8258
8363
|
meta: [stats2, elapsed]
|
|
8259
8364
|
}
|
|
8260
|
-
), grouped.map(([file, hits]) => /* @__PURE__ */ React42.createElement(Box35, { key: file, flexDirection: "column" }, /* @__PURE__ */ React42.createElement(Text36, { bold: true, color: FG.strong }, file), hits.map((h, i) => /* @__PURE__ */ React42.createElement(Box35, { key: `${file}:${h.line}:${i}`, flexDirection: "row", gap: 1 }, /* @__PURE__ */ React42.createElement(Text36, { color: FG.faint }, `${h.line.toString().padStart(4)} \u2502`), /* @__PURE__ */ React42.createElement(HighlightedLine, { text: h.preview, start: h.matchStart, end: h.matchEnd }))))), card.hits.length > 10 ? /* @__PURE__ */ React42.createElement(Text36, { color: FG.faint },
|
|
8365
|
+
), grouped.map(([file, hits]) => /* @__PURE__ */ React42.createElement(Box35, { key: file, flexDirection: "column" }, /* @__PURE__ */ React42.createElement(Text36, { bold: true, color: FG.strong }, file), hits.map((h, i) => /* @__PURE__ */ React42.createElement(Box35, { key: `${file}:${h.line}:${i}`, flexDirection: "row", gap: 1 }, /* @__PURE__ */ React42.createElement(Text36, { color: FG.faint }, `${h.line.toString().padStart(4)} \u2502`), /* @__PURE__ */ React42.createElement(HighlightedLine, { text: h.preview, start: h.matchStart, end: h.matchEnd }))))), card.hits.length > 10 ? /* @__PURE__ */ React42.createElement(Text36, { color: FG.faint }, t(
|
|
8366
|
+
card.hits.length - 10 === 1 ? "cardLabels.moreHitSingular" : "cardLabels.moreHitsPlural",
|
|
8367
|
+
{ count: card.hits.length - 10 }
|
|
8368
|
+
)) : null);
|
|
8261
8369
|
}
|
|
8262
8370
|
function HighlightedLine({
|
|
8263
8371
|
text,
|
|
@@ -8280,7 +8388,7 @@ function groupByFile(hits) {
|
|
|
8280
8388
|
}
|
|
8281
8389
|
|
|
8282
8390
|
// src/cli/ui/cards/StreamingCard.tsx
|
|
8283
|
-
import { Box as Box37, Text as Text38, useStdout as
|
|
8391
|
+
import { Box as Box37, Text as Text38, useStdout as useStdout11 } from "ink";
|
|
8284
8392
|
import React44, { useContext as useContext5 } from "react";
|
|
8285
8393
|
|
|
8286
8394
|
// src/cli/ui/layout/LiveExpandContext.ts
|
|
@@ -8289,7 +8397,7 @@ var LiveExpandContext = createContext3(false);
|
|
|
8289
8397
|
|
|
8290
8398
|
// src/cli/ui/markdown.tsx
|
|
8291
8399
|
import { highlight, supportsLanguage } from "cli-highlight";
|
|
8292
|
-
import { Box as Box36, Text as Text37, useStdout as
|
|
8400
|
+
import { Box as Box36, Text as Text37, useStdout as useStdout10 } from "ink";
|
|
8293
8401
|
import React43 from "react";
|
|
8294
8402
|
import stringWidth from "string-width";
|
|
8295
8403
|
var BODY_LEFT_CELLS = 7;
|
|
@@ -8297,7 +8405,7 @@ var MarkdownWidthCtx = React43.createContext(void 0);
|
|
|
8297
8405
|
function useWidth() {
|
|
8298
8406
|
const ctx = React43.useContext(MarkdownWidthCtx);
|
|
8299
8407
|
if (ctx !== void 0) return ctx;
|
|
8300
|
-
return (
|
|
8408
|
+
return (useStdout10()?.stdout?.columns ?? process.stdout.columns ?? 80) - BODY_LEFT_CELLS;
|
|
8301
8409
|
}
|
|
8302
8410
|
marked.setOptions({ gfm: true, breaks: false });
|
|
8303
8411
|
function Markdown({ text, width }) {
|
|
@@ -8618,7 +8726,7 @@ function tokenRate(text, startTs, endTs) {
|
|
|
8618
8726
|
}
|
|
8619
8727
|
var PILL_RATE = { bg: "#11141a", fg: "#8b949e" };
|
|
8620
8728
|
function StreamingCard({ card }) {
|
|
8621
|
-
const { stdout } =
|
|
8729
|
+
const { stdout } = useStdout11();
|
|
8622
8730
|
const cols = stdout?.columns ?? 80;
|
|
8623
8731
|
const expanded = useContext5(LiveExpandContext);
|
|
8624
8732
|
const reserveCap = expanded ? EXPANDED_MAX_LINES + 2 : STREAMING_PREVIEW_LINES2 + 2;
|
|
@@ -8637,7 +8745,7 @@ function StreamingCard({ card }) {
|
|
|
8637
8745
|
{
|
|
8638
8746
|
glyph: "\u2039",
|
|
8639
8747
|
tone: TONE.ok,
|
|
8640
|
-
title: "reply",
|
|
8748
|
+
title: t("cardTitles.reply"),
|
|
8641
8749
|
right: /* @__PURE__ */ React44.createElement(React44.Fragment, null, ratePill, modelPill)
|
|
8642
8750
|
}
|
|
8643
8751
|
), /* @__PURE__ */ React44.createElement(Markdown, { text: card.text }));
|
|
@@ -8651,7 +8759,7 @@ function StreamingCard({ card }) {
|
|
|
8651
8759
|
const aborted = !!card.aborted;
|
|
8652
8760
|
const headColor = aborted ? TONE.err : TONE_ACTIVE.brand;
|
|
8653
8761
|
const glyph = aborted ? "\u2039" : "\u25C8";
|
|
8654
|
-
const headLabel = aborted ? "aborted" : "writing
|
|
8762
|
+
const headLabel = aborted ? t("cardLabels.aborted") : t("cardLabels.writing");
|
|
8655
8763
|
const { tokens: liveTokens, tps: liveTps } = tokenRate(card.text, card.ts, Date.now());
|
|
8656
8764
|
const liveRatePill = !aborted && liveTokens >= MIN_TOKENS_FOR_RATE && liveTps !== null ? /* @__PURE__ */ React44.createElement(Pill, { label: `${liveTps} t/s`, ...PILL_RATE, bold: false }) : null;
|
|
8657
8765
|
const expandPill = !aborted ? /* @__PURE__ */ React44.createElement(Pill, { label: expanded ? "expanded \u2303o" : "preview \u2303o", ...PILL_RATE, bold: false }) : null;
|
|
@@ -8663,13 +8771,9 @@ function StreamingCard({ card }) {
|
|
|
8663
8771
|
title: headLabel,
|
|
8664
8772
|
right: /* @__PURE__ */ React44.createElement(React44.Fragment, null, liveRatePill, expandPill, aborted ? null : /* @__PURE__ */ React44.createElement(Spinner, { kind: "braille", color: TONE_ACTIVE.brand }), modelPill)
|
|
8665
8773
|
}
|
|
8666
|
-
), expanded && droppedAbove > 0 ? /* @__PURE__ */ React44.createElement(
|
|
8667
|
-
|
|
8668
|
-
|
|
8669
|
-
color: FG.faint
|
|
8670
|
-
},
|
|
8671
|
-
`\u22EF ${droppedAbove} earlier line${droppedAbove === 1 ? "" : "s"} above`
|
|
8672
|
-
) : null, visible.map((line, i) => /* @__PURE__ */ React44.createElement(Box37, { key: `${card.id}:${visualLines.length - visible.length + i}`, flexDirection: "row" }, /* @__PURE__ */ React44.createElement(Text38, { color: aborted ? FG.meta : FG.body }, clipToCells(line, lineCells)))), aborted ? /* @__PURE__ */ React44.createElement(Text38, { color: FG.faint }, "[truncated by esc]") : null);
|
|
8774
|
+
), expanded && droppedAbove > 0 ? /* @__PURE__ */ React44.createElement(Text38, { color: FG.faint }, t(droppedAbove === 1 ? "cardLabels.earlierLine" : "cardLabels.earlierLines", {
|
|
8775
|
+
count: droppedAbove
|
|
8776
|
+
})) : null, visible.map((line, i) => /* @__PURE__ */ React44.createElement(Box37, { key: `${card.id}:${visualLines.length - visible.length + i}`, flexDirection: "row" }, /* @__PURE__ */ React44.createElement(Text38, { color: aborted ? FG.meta : FG.body }, clipToCells(line, lineCells)))), aborted ? /* @__PURE__ */ React44.createElement(Text38, { color: FG.faint }, t("cardLabels.truncatedByEsc")) : null);
|
|
8673
8777
|
}
|
|
8674
8778
|
|
|
8675
8779
|
// src/cli/ui/cards/SubAgentCard.tsx
|
|
@@ -8683,22 +8787,22 @@ function SubAgentCard({ card }) {
|
|
|
8683
8787
|
failed: tone.err
|
|
8684
8788
|
};
|
|
8685
8789
|
const headColor = statusColor[card.status];
|
|
8686
|
-
const headGlyph = card.status === "failed" ? "\
|
|
8790
|
+
const headGlyph = card.status === "failed" ? "\u2717" : "\u232C";
|
|
8687
8791
|
const runningChildren = card.children.filter((c) => !isChildDone(c)).length;
|
|
8688
8792
|
const isRunning = card.status === "running";
|
|
8689
8793
|
const inLive = useContext6(ActiveCardContext);
|
|
8690
|
-
const headerMeta2 = isRunning ? runningChildren > 0 ? [`${runningChildren}
|
|
8794
|
+
const headerMeta2 = isRunning ? runningChildren > 0 ? [`${runningChildren} ${t("cardLabels.runningLabel")}`] : [t("cardLabels.workingLabel")] : [{ text: card.status, color: headColor }];
|
|
8691
8795
|
return /* @__PURE__ */ React45.createElement(Card, { tone: headColor }, /* @__PURE__ */ React45.createElement(
|
|
8692
8796
|
CardHeader,
|
|
8693
8797
|
{
|
|
8694
8798
|
glyph: headGlyph,
|
|
8695
8799
|
tone: headColor,
|
|
8696
|
-
title: "subagent",
|
|
8800
|
+
title: t("cardTitles.subagent"),
|
|
8697
8801
|
titleColor: tone.violet,
|
|
8698
8802
|
subtitle: card.task,
|
|
8699
8803
|
meta: headerMeta2
|
|
8700
8804
|
}
|
|
8701
|
-
), card.name ? /* @__PURE__ */ React45.createElement(Text39, { color: fg.faint },
|
|
8805
|
+
), card.name ? /* @__PURE__ */ React45.createElement(Text39, { color: fg.faint }, `${t("cardLabels.agent")} \xB7 ${card.name}`) : null, card.tools && card.tools.length > 0 && /* @__PURE__ */ React45.createElement(Text39, { color: fg.faint }, `${t("cardLabels.tools")} \xB7 ${card.tools.join(", ")}`), card.children.map((child) => /* @__PURE__ */ React45.createElement(Box38, { key: child.id, flexDirection: "row", gap: 1 }, inLive ? null : /* @__PURE__ */ React45.createElement(Text39, { color: tone.violet }, "\u258E"), /* @__PURE__ */ React45.createElement(ChildRow, { card: child }))));
|
|
8702
8806
|
}
|
|
8703
8807
|
function isChildDone(card) {
|
|
8704
8808
|
switch (card.kind) {
|
|
@@ -8734,7 +8838,7 @@ function childVisual(card, doneColor, failedColor, fallbackColor) {
|
|
|
8734
8838
|
statusGlyph: done ? doneGlyph(doneColor) : runningGlyph(CARD.reasoning.color),
|
|
8735
8839
|
kindGlyph: "\u25C6",
|
|
8736
8840
|
kindColor: CARD.reasoning.color,
|
|
8737
|
-
text:
|
|
8841
|
+
text: t("cardLabels.reasoningLabel", { count: card.paragraphs })
|
|
8738
8842
|
};
|
|
8739
8843
|
}
|
|
8740
8844
|
case "tool": {
|
|
@@ -8751,7 +8855,7 @@ function childVisual(card, doneColor, failedColor, fallbackColor) {
|
|
|
8751
8855
|
statusGlyph: card.done ? doneGlyph(doneColor) : runningGlyph(CARD.streaming.color),
|
|
8752
8856
|
kindGlyph: "\u25C8",
|
|
8753
8857
|
kindColor: CARD.streaming.color,
|
|
8754
|
-
text: card.done ? "response" : "writing
|
|
8858
|
+
text: card.done ? t("cardLabels.response") : t("cardLabels.writing")
|
|
8755
8859
|
};
|
|
8756
8860
|
case "diff":
|
|
8757
8861
|
return {
|
|
@@ -8848,7 +8952,7 @@ function TipRowRender({
|
|
|
8848
8952
|
}
|
|
8849
8953
|
|
|
8850
8954
|
// src/cli/ui/cards/ToolCard.tsx
|
|
8851
|
-
import { Text as Text42, useStdout as
|
|
8955
|
+
import { Text as Text42, useStdout as useStdout12 } from "ink";
|
|
8852
8956
|
import React48 from "react";
|
|
8853
8957
|
var READ_TAIL = 2;
|
|
8854
8958
|
var OTHER_TAIL = 5;
|
|
@@ -8857,7 +8961,7 @@ function tailLinesFor(name) {
|
|
|
8857
8961
|
return /(?:^|_)(read|search|list|tree|get|status|diff|fetch|grep)(_|$)/.test(lower) || lower === "job_output" ? READ_TAIL : OTHER_TAIL;
|
|
8858
8962
|
}
|
|
8859
8963
|
function ToolCard({ card }) {
|
|
8860
|
-
const { stdout } =
|
|
8964
|
+
const { stdout } = useStdout12();
|
|
8861
8965
|
const cols = stdout?.columns ?? 80;
|
|
8862
8966
|
const lineCells = Math.max(20, cols - 4);
|
|
8863
8967
|
const argsLabel = formatArgsSummary(card.args);
|
|
@@ -8876,7 +8980,7 @@ function ToolCard({ card }) {
|
|
|
8876
8980
|
meta.push({ text: `\u21BB ${card.retry.attempt}/${card.retry.max}`, color: TONE.warn });
|
|
8877
8981
|
}
|
|
8878
8982
|
if (card.rejected) {
|
|
8879
|
-
meta.push({ text: "rejected", color: TONE.err });
|
|
8983
|
+
meta.push({ text: t("cardLabels.rejected"), color: TONE.err });
|
|
8880
8984
|
}
|
|
8881
8985
|
for (const part of metaTrail(card)) meta.push(part);
|
|
8882
8986
|
return /* @__PURE__ */ React48.createElement(Card, { tone: headColor }, /* @__PURE__ */ React48.createElement(
|
|
@@ -8889,7 +8993,9 @@ function ToolCard({ card }) {
|
|
|
8889
8993
|
meta: meta.length > 0 ? meta : void 0,
|
|
8890
8994
|
right: status2 === "running" ? /* @__PURE__ */ React48.createElement(Spinner, { kind: "braille", color: TONE_ACTIVE.brand, bold: true }) : void 0
|
|
8891
8995
|
}
|
|
8892
|
-
), showBody && (subagentMarkdown !== null ? /* @__PURE__ */ React48.createElement(Markdown, { text: subagentMarkdown, width: lineCells }) : /* @__PURE__ */ React48.createElement(React48.Fragment, null, hidden > 0 ? /* @__PURE__ */ React48.createElement(Text42, { color: FG.faint },
|
|
8996
|
+
), showBody && (subagentMarkdown !== null ? /* @__PURE__ */ React48.createElement(Markdown, { text: subagentMarkdown, width: lineCells }) : /* @__PURE__ */ React48.createElement(React48.Fragment, null, hidden > 0 ? /* @__PURE__ */ React48.createElement(Text42, { color: FG.faint }, t(hidden === 1 ? "cardLabels.earlierLine" : "cardLabels.earlierLines", {
|
|
8997
|
+
count: hidden
|
|
8998
|
+
})) : null, visible.map((line, i) => /* @__PURE__ */ React48.createElement(
|
|
8893
8999
|
Text42,
|
|
8894
9000
|
{
|
|
8895
9001
|
key: `${card.id}:${hidden + i}`,
|
|
@@ -8949,10 +9055,11 @@ function headerColorFor(s) {
|
|
|
8949
9055
|
function metaTrail(card) {
|
|
8950
9056
|
const parts = [];
|
|
8951
9057
|
const inputBytes = largestStringInputBytes(card.args);
|
|
8952
|
-
if (inputBytes !== null) parts.push(
|
|
8953
|
-
if (card.elapsedMs > 0)
|
|
9058
|
+
if (inputBytes !== null) parts.push(t("cardLabels.bytesIn", { bytes: formatBytes(inputBytes) }));
|
|
9059
|
+
if (card.elapsedMs > 0)
|
|
9060
|
+
parts.push(t("cardLabels.elapsedSec", { secs: (card.elapsedMs / 1e3).toFixed(2) }));
|
|
8954
9061
|
if (card.done && !card.rejected && !card.aborted && card.exitCode !== void 0 && card.exitCode !== 0) {
|
|
8955
|
-
parts.push(
|
|
9062
|
+
parts.push(t("cardLabels.exit", { code: card.exitCode }));
|
|
8956
9063
|
}
|
|
8957
9064
|
return parts;
|
|
8958
9065
|
}
|
|
@@ -9009,13 +9116,16 @@ function UsageCard({ card }) {
|
|
|
9009
9116
|
const promptRatio = card.tokens.prompt / cap;
|
|
9010
9117
|
const reasonRatio = card.tokens.reason / cap;
|
|
9011
9118
|
const outputRatio = card.tokens.output / cap;
|
|
9012
|
-
const headerMeta2 = [
|
|
9119
|
+
const headerMeta2 = [
|
|
9120
|
+
`${t("cardLabels.turn")} ${card.turn}`,
|
|
9121
|
+
formatCost(card.cost, card.balanceCurrency)
|
|
9122
|
+
];
|
|
9013
9123
|
if (card.elapsedMs !== void 0) headerMeta2.push(`${(card.elapsedMs / 1e3).toFixed(1)}s`);
|
|
9014
|
-
return /* @__PURE__ */ React49.createElement(Card, { tone: FG.meta }, /* @__PURE__ */ React49.createElement(CardHeader, { glyph: "\u03A3", tone: FG.meta, title: "usage", meta: headerMeta2 }), /* @__PURE__ */ React49.createElement(Box42, { flexDirection: "row", gap: 1 }, /* @__PURE__ */ React49.createElement(Text43, { color: FG.sub }, "prompt"), bar(promptRatio, TONE.brand), /* @__PURE__ */ React49.createElement(Text43, { bold: true, color: FG.body }, card.tokens.prompt.toLocaleString()), /* @__PURE__ */ React49.createElement(Text43, { color: FG.faint }, `/ 1M \xB7 ${(promptRatio * 100).toFixed(1)}%`)), /* @__PURE__ */ React49.createElement(Box42, { flexDirection: "row", gap: 1 }, /* @__PURE__ */ React49.createElement(Text43, { color: FG.sub }, "reason"), bar(reasonRatio, TONE.accent), /* @__PURE__ */ React49.createElement(Text43, { bold: true, color: FG.body }, card.tokens.reason.toLocaleString())), /* @__PURE__ */ React49.createElement(Box42, { flexDirection: "row", gap: 1 }, /* @__PURE__ */ React49.createElement(Text43, { color: FG.sub }, "output"), bar(outputRatio, TONE.brand), /* @__PURE__ */ React49.createElement(Text43, { bold: true, color: FG.body }, card.tokens.output.toLocaleString())), /* @__PURE__ */ React49.createElement(Box42, { flexDirection: "row", gap: 1 }, /* @__PURE__ */ React49.createElement(Text43, { color: FG.sub }, "cache "), bar(card.cacheHit, TONE.ok), /* @__PURE__ */ React49.createElement(Text43, { bold: true, color: TONE.ok }, `${(card.cacheHit * 100).toFixed(1)}%`)), /* @__PURE__ */ React49.createElement(Box42, { flexDirection: "row", gap: 1 }, /* @__PURE__ */ React49.createElement(Text43, { color: FG.faint }, "session"), /* @__PURE__ */ React49.createElement(Text43, { bold: true, color: FG.body }, `\u26C1 ${formatCost(card.sessionCost, card.balanceCurrency, 3)}`), card.balance !== void 0 ? /* @__PURE__ */ React49.createElement(React49.Fragment, null, /* @__PURE__ */ React49.createElement(Text43, { color: FG.faint },
|
|
9124
|
+
return /* @__PURE__ */ React49.createElement(Card, { tone: FG.meta }, /* @__PURE__ */ React49.createElement(CardHeader, { glyph: "\u03A3", tone: FG.meta, title: t("cardTitles.usage"), meta: headerMeta2 }), /* @__PURE__ */ React49.createElement(Box42, { flexDirection: "row", gap: 1 }, /* @__PURE__ */ React49.createElement(Text43, { color: FG.sub }, t("cardLabels.prompt")), bar(promptRatio, TONE.brand), /* @__PURE__ */ React49.createElement(Text43, { bold: true, color: FG.body }, card.tokens.prompt.toLocaleString()), /* @__PURE__ */ React49.createElement(Text43, { color: FG.faint }, `/ 1M \xB7 ${(promptRatio * 100).toFixed(1)}%`)), /* @__PURE__ */ React49.createElement(Box42, { flexDirection: "row", gap: 1 }, /* @__PURE__ */ React49.createElement(Text43, { color: FG.sub }, t("cardLabels.reason")), bar(reasonRatio, TONE.accent), /* @__PURE__ */ React49.createElement(Text43, { bold: true, color: FG.body }, card.tokens.reason.toLocaleString())), /* @__PURE__ */ React49.createElement(Box42, { flexDirection: "row", gap: 1 }, /* @__PURE__ */ React49.createElement(Text43, { color: FG.sub }, t("cardLabels.output")), bar(outputRatio, TONE.brand), /* @__PURE__ */ React49.createElement(Text43, { bold: true, color: FG.body }, card.tokens.output.toLocaleString())), /* @__PURE__ */ React49.createElement(Box42, { flexDirection: "row", gap: 1 }, /* @__PURE__ */ React49.createElement(Text43, { color: FG.sub }, t("cardLabels.cache"), " "), bar(card.cacheHit, TONE.ok), /* @__PURE__ */ React49.createElement(Text43, { bold: true, color: TONE.ok }, `${(card.cacheHit * 100).toFixed(1)}%`)), /* @__PURE__ */ React49.createElement(Box42, { flexDirection: "row", gap: 1 }, /* @__PURE__ */ React49.createElement(Text43, { color: FG.faint }, t("cardLabels.session")), /* @__PURE__ */ React49.createElement(Text43, { bold: true, color: FG.body }, `\u26C1 ${formatCost(card.sessionCost, card.balanceCurrency, 3)}`), card.balance !== void 0 ? /* @__PURE__ */ React49.createElement(React49.Fragment, null, /* @__PURE__ */ React49.createElement(Text43, { color: FG.faint }, `\xB7 ${t("cardLabels.balance")}`), /* @__PURE__ */ React49.createElement(Text43, { bold: true, color: TONE.brand }, formatBalance(card.balance, card.balanceCurrency))) : null));
|
|
9015
9125
|
}
|
|
9016
9126
|
function CompactUsageRow({ card }) {
|
|
9017
9127
|
const elapsed = card.elapsedMs !== void 0 ? ` \xB7 ${(card.elapsedMs / 1e3).toFixed(1)}s` : "";
|
|
9018
|
-
return /* @__PURE__ */ React49.createElement(Box42, { flexDirection: "row", gap: 1, marginTop: 1 }, /* @__PURE__ */ React49.createElement(Text43, { color: FG.meta }, "\u03A3"), /* @__PURE__ */ React49.createElement(Text43, { color: FG.faint },
|
|
9128
|
+
return /* @__PURE__ */ React49.createElement(Box42, { flexDirection: "row", gap: 1, marginTop: 1 }, /* @__PURE__ */ React49.createElement(Text43, { color: FG.meta }, "\u03A3"), /* @__PURE__ */ React49.createElement(Text43, { color: FG.faint }, `${t("cardLabels.turn")} ${card.turn}`), /* @__PURE__ */ React49.createElement(Text43, { color: FG.meta }, `\xB7 ${compactNum(card.tokens.prompt)} ${t("cardLabels.prompt")} \xB7 ${compactNum(card.tokens.output)} ${t("cardLabels.output")}`), /* @__PURE__ */ React49.createElement(Text43, { color: FG.faint }, `\xB7 ${t("cardLabels.cache")}`), /* @__PURE__ */ React49.createElement(Text43, { color: TONE.ok }, `${(card.cacheHit * 100).toFixed(0)}%`), /* @__PURE__ */ React49.createElement(Text43, { color: FG.faint }, `\xB7 ${formatCost(card.cost, card.balanceCurrency)}${elapsed}`), card.balance !== void 0 ? /* @__PURE__ */ React49.createElement(Text43, { color: TONE.brand }, `\xB7 ${formatBalance(card.balance, card.balanceCurrency)}`) : null);
|
|
9019
9129
|
}
|
|
9020
9130
|
|
|
9021
9131
|
// src/cli/ui/cards/UserCard.tsx
|
|
@@ -9338,7 +9448,7 @@ function summarizeToolArgs(name, args) {
|
|
|
9338
9448
|
}
|
|
9339
9449
|
|
|
9340
9450
|
// src/cli/ui/layout/StatusRow.tsx
|
|
9341
|
-
import { Box as Box46, Text as Text49, useStdout as
|
|
9451
|
+
import { Box as Box46, Text as Text49, useStdout as useStdout13 } from "ink";
|
|
9342
9452
|
import React56 from "react";
|
|
9343
9453
|
|
|
9344
9454
|
// src/cli/ui/primitives/Countdown.tsx
|
|
@@ -9359,21 +9469,28 @@ var FEEDBACK_HINT_MIN_COLS = 100;
|
|
|
9359
9469
|
function StatusRow() {
|
|
9360
9470
|
const status2 = useAgentState((s) => s.status);
|
|
9361
9471
|
const session = useAgentState((s) => s.session);
|
|
9362
|
-
const { stdout } =
|
|
9472
|
+
const { stdout } = useStdout13();
|
|
9363
9473
|
const cols = stdout?.columns ?? 80;
|
|
9364
9474
|
const ruleWidth = Math.max(RULE_MIN, cols - RULE_PAD);
|
|
9365
9475
|
const hasTurn = status2.cost > 0;
|
|
9366
9476
|
const hasSession = status2.sessionCost > 0;
|
|
9367
9477
|
const hasBalance = typeof status2.balance === "number";
|
|
9368
9478
|
const showWallet = cols >= WALLET_MIN_COLS && (hasSession || hasBalance);
|
|
9369
|
-
return /* @__PURE__ */ React56.createElement(Box46, { flexDirection: "column" }, /* @__PURE__ */ React56.createElement(Box46,
|
|
9479
|
+
return /* @__PURE__ */ React56.createElement(Box46, { flexDirection: "column", flexShrink: 0, flexWrap: "nowrap" }, /* @__PURE__ */ React56.createElement(Box46, { height: 1, flexWrap: "nowrap" }, /* @__PURE__ */ React56.createElement(Text49, null, " "), /* @__PURE__ */ React56.createElement(Text49, { color: FG.faint, wrap: "truncate" }, "\u2500".repeat(ruleWidth))), /* @__PURE__ */ React56.createElement(Box46, { flexDirection: "row", height: 1, minHeight: 1, flexWrap: "nowrap", flexShrink: 0 }, /* @__PURE__ */ React56.createElement(Text49, { wrap: "truncate" }, " "), status2.recording ? /* @__PURE__ */ React56.createElement(RecordingPill, { rec: status2.recording }) : status2.countdownSeconds !== void 0 ? /* @__PURE__ */ React56.createElement(CountdownRow, { mode: status2.mode, secondsLeft: status2.countdownSeconds }) : /* @__PURE__ */ React56.createElement(ModePill2, { mode: status2.mode, network: status2.network, detail: status2.networkDetail }), /* @__PURE__ */ React56.createElement(Sep, null), /* @__PURE__ */ React56.createElement(Text49, { color: FG.sub, wrap: "truncate" }, `${session.id} \xB7 ${session.branch}`), hasTurn && /* @__PURE__ */ React56.createElement(React56.Fragment, null, /* @__PURE__ */ React56.createElement(Sep, null), /* @__PURE__ */ React56.createElement(Text49, { bold: true, color: TONE.brand, wrap: "truncate" }, "\u25B8 "), /* @__PURE__ */ React56.createElement(Text49, { bold: true, color: FG.body, wrap: "truncate" }, `${formatCost(status2.cost, status2.balanceCurrency)} turn`)), /* @__PURE__ */ React56.createElement(Sep, null), /* @__PURE__ */ React56.createElement(
|
|
9480
|
+
Text49,
|
|
9481
|
+
{
|
|
9482
|
+
color: TONE.accent,
|
|
9483
|
+
wrap: "truncate"
|
|
9484
|
+
},
|
|
9485
|
+
`cache ${Math.round(status2.cacheHit * 100)}%`
|
|
9486
|
+
), showWallet && /* @__PURE__ */ React56.createElement(
|
|
9370
9487
|
WalletPill,
|
|
9371
9488
|
{
|
|
9372
9489
|
sessionCostUsd: status2.sessionCost,
|
|
9373
9490
|
balance: status2.balance,
|
|
9374
9491
|
currency: status2.balanceCurrency
|
|
9375
9492
|
}
|
|
9376
|
-
), cols >= VERSION_MIN_COLS && /* @__PURE__ */ React56.createElement(React56.Fragment, null, /* @__PURE__ */ React56.createElement(Sep, null), /* @__PURE__ */ React56.createElement(Text49, { color: FG.faint }, `v${VERSION}`), cols >= FEEDBACK_HINT_MIN_COLS && /* @__PURE__ */ React56.createElement(React56.Fragment, null, /* @__PURE__ */ React56.createElement(Text49, { color: FG.faint }, " \xB7 "), /* @__PURE__ */ React56.createElement(Text49, { color: FG.meta }, "\u2691 "), /* @__PURE__ */ React56.createElement(Text49, { color: FG.sub }, "/feedback")))));
|
|
9493
|
+
), cols >= VERSION_MIN_COLS && /* @__PURE__ */ React56.createElement(React56.Fragment, null, /* @__PURE__ */ React56.createElement(Sep, null), /* @__PURE__ */ React56.createElement(Text49, { color: FG.faint, wrap: "truncate" }, `v${VERSION}`), cols >= FEEDBACK_HINT_MIN_COLS && /* @__PURE__ */ React56.createElement(React56.Fragment, null, /* @__PURE__ */ React56.createElement(Text49, { color: FG.faint, wrap: "truncate" }, " \xB7 "), /* @__PURE__ */ React56.createElement(Text49, { color: FG.meta, wrap: "truncate" }, "\u2691 "), /* @__PURE__ */ React56.createElement(Text49, { color: FG.sub, wrap: "truncate" }, "/feedback")))));
|
|
9377
9494
|
}
|
|
9378
9495
|
function WalletPill({
|
|
9379
9496
|
sessionCostUsd,
|
|
@@ -9382,7 +9499,14 @@ function WalletPill({
|
|
|
9382
9499
|
}) {
|
|
9383
9500
|
const showSpent = sessionCostUsd > 0;
|
|
9384
9501
|
const showBalance = typeof balance === "number";
|
|
9385
|
-
return /* @__PURE__ */ React56.createElement(React56.Fragment, null, /* @__PURE__ */ React56.createElement(Sep, null), /* @__PURE__ */ React56.createElement(Text49, { color: FG.meta
|
|
9502
|
+
return /* @__PURE__ */ React56.createElement(React56.Fragment, null, /* @__PURE__ */ React56.createElement(Sep, null), /* @__PURE__ */ React56.createElement(Text49, { color: FG.meta, wrap: "truncate" }, "\u26C1 "), showSpent && /* @__PURE__ */ React56.createElement(
|
|
9503
|
+
Text49,
|
|
9504
|
+
{
|
|
9505
|
+
color: FG.body,
|
|
9506
|
+
wrap: "truncate"
|
|
9507
|
+
},
|
|
9508
|
+
`${formatCost(sessionCostUsd, currency, 2)} spent`
|
|
9509
|
+
), showSpent && showBalance && /* @__PURE__ */ React56.createElement(Text49, { color: FG.meta, wrap: "truncate" }, " / "), showBalance && /* @__PURE__ */ React56.createElement(Text49, { bold: true, color: balanceColor(balance, currency), wrap: "truncate" }, formatBalance(balance, currency, { fractionDigits: 2 })), showBalance && /* @__PURE__ */ React56.createElement(Text49, { color: FG.faint, wrap: "truncate" }, " left"));
|
|
9386
9510
|
}
|
|
9387
9511
|
function ModePill2({
|
|
9388
9512
|
mode: mode2,
|
|
@@ -9391,18 +9515,18 @@ function ModePill2({
|
|
|
9391
9515
|
}) {
|
|
9392
9516
|
if (network === "online") {
|
|
9393
9517
|
const pill = modeGlyph(mode2);
|
|
9394
|
-
return /* @__PURE__ */ React56.createElement(Box46, { flexDirection: "row" }, /* @__PURE__ */ React56.createElement(Text49, { color: pill.color }, pill.glyph), /* @__PURE__ */ React56.createElement(Text49, { color: FG.sub }, ` ${mode2}`));
|
|
9518
|
+
return /* @__PURE__ */ React56.createElement(Box46, { flexDirection: "row", height: 1, flexWrap: "nowrap" }, /* @__PURE__ */ React56.createElement(Text49, { color: pill.color, wrap: "truncate" }, pill.glyph), /* @__PURE__ */ React56.createElement(Text49, { color: FG.sub, wrap: "truncate" }, ` ${mode2}`));
|
|
9395
9519
|
}
|
|
9396
9520
|
const dot = networkDot(network);
|
|
9397
9521
|
if (network === "slow") {
|
|
9398
9522
|
const tail = detail ? ` \xB7 ${detail}` : "";
|
|
9399
|
-
return /* @__PURE__ */ React56.createElement(Box46, { flexDirection: "row" }, /* @__PURE__ */ React56.createElement(Text49, { color: dot.color }, dot.glyph), /* @__PURE__ */ React56.createElement(Text49, { color: dot.color }, ` ${mode2} \xB7 slow${tail}`));
|
|
9523
|
+
return /* @__PURE__ */ React56.createElement(Box46, { flexDirection: "row", height: 1, flexWrap: "nowrap" }, /* @__PURE__ */ React56.createElement(Text49, { color: dot.color, wrap: "truncate" }, dot.glyph), /* @__PURE__ */ React56.createElement(Text49, { color: dot.color, wrap: "truncate" }, ` ${mode2} \xB7 slow${tail}`));
|
|
9400
9524
|
}
|
|
9401
9525
|
if (network === "disconnected") {
|
|
9402
9526
|
const tail = detail ? ` \xB7 ${detail}` : "";
|
|
9403
|
-
return /* @__PURE__ */ React56.createElement(Box46, { flexDirection: "row" }, /* @__PURE__ */ React56.createElement(Text49, { color: dot.color }, dot.glyph), /* @__PURE__ */ React56.createElement(Text49, { color: dot.color }, ` disconnect${tail}`));
|
|
9527
|
+
return /* @__PURE__ */ React56.createElement(Box46, { flexDirection: "row", height: 1, flexWrap: "nowrap" }, /* @__PURE__ */ React56.createElement(Text49, { color: dot.color, wrap: "truncate" }, dot.glyph), /* @__PURE__ */ React56.createElement(Text49, { color: dot.color, wrap: "truncate" }, ` disconnect${tail}`));
|
|
9404
9528
|
}
|
|
9405
|
-
return /* @__PURE__ */ React56.createElement(Box46, { flexDirection: "row" }, /* @__PURE__ */ React56.createElement(Text49, { color: dot.color }, dot.glyph), /* @__PURE__ */ React56.createElement(Text49, { color: dot.color }, " reconnecting\u2026"));
|
|
9529
|
+
return /* @__PURE__ */ React56.createElement(Box46, { flexDirection: "row", height: 1, flexWrap: "nowrap" }, /* @__PURE__ */ React56.createElement(Text49, { color: dot.color, wrap: "truncate" }, dot.glyph), /* @__PURE__ */ React56.createElement(Text49, { color: dot.color, wrap: "truncate" }, " reconnecting\u2026"));
|
|
9406
9530
|
}
|
|
9407
9531
|
function CountdownRow({
|
|
9408
9532
|
mode: mode2,
|
|
@@ -9410,14 +9534,14 @@ function CountdownRow({
|
|
|
9410
9534
|
}) {
|
|
9411
9535
|
const pill = modeGlyph(mode2);
|
|
9412
9536
|
const endsAt = Date.now() + secondsLeft * 1e3;
|
|
9413
|
-
return /* @__PURE__ */ React56.createElement(Box46, { flexDirection: "row" }, /* @__PURE__ */ React56.createElement(Text49, { color: pill.color }, pill.glyph), /* @__PURE__ */ React56.createElement(Text49, { color: FG.sub }, ` ${mode2} \xB7 `), /* @__PURE__ */ React56.createElement(Text49, { color: TONE.warn }, "approving in "), /* @__PURE__ */ React56.createElement(Countdown, { endsAt }), /* @__PURE__ */ React56.createElement(Text49, { color: TONE.warn }, "s \xB7 esc to interrupt"));
|
|
9537
|
+
return /* @__PURE__ */ React56.createElement(Box46, { flexDirection: "row", height: 1, flexWrap: "nowrap" }, /* @__PURE__ */ React56.createElement(Text49, { color: pill.color, wrap: "truncate" }, pill.glyph), /* @__PURE__ */ React56.createElement(Text49, { color: FG.sub, wrap: "truncate" }, ` ${mode2} \xB7 `), /* @__PURE__ */ React56.createElement(Text49, { color: TONE.warn, wrap: "truncate" }, "approving in "), /* @__PURE__ */ React56.createElement(Countdown, { endsAt }), /* @__PURE__ */ React56.createElement(Text49, { color: TONE.warn, wrap: "truncate" }, "s \xB7 esc to interrupt"));
|
|
9414
9538
|
}
|
|
9415
9539
|
function RecordingPill({ rec }) {
|
|
9416
9540
|
const sizeMb = (rec.sizeBytes / (1024 * 1024)).toFixed(1);
|
|
9417
|
-
return /* @__PURE__ */ React56.createElement(Box46, { flexDirection: "row" }, /* @__PURE__ */ React56.createElement(Text49, { bold: true, color: TONE.err }, "\u25CFREC"), /* @__PURE__ */ React56.createElement(Text49, { color: TONE.err }, ` ${sizeMb} MB \xB7 ${rec.events} evt`));
|
|
9541
|
+
return /* @__PURE__ */ React56.createElement(Box46, { flexDirection: "row", height: 1, flexWrap: "nowrap" }, /* @__PURE__ */ React56.createElement(Text49, { bold: true, color: TONE.err, wrap: "truncate" }, "\u25CFREC"), /* @__PURE__ */ React56.createElement(Text49, { color: TONE.err, wrap: "truncate" }, ` ${sizeMb} MB \xB7 ${rec.events} evt`));
|
|
9418
9542
|
}
|
|
9419
9543
|
function Sep() {
|
|
9420
|
-
return /* @__PURE__ */ React56.createElement(Text49, { color: FG.meta }, " \xB7 ");
|
|
9544
|
+
return /* @__PURE__ */ React56.createElement(Text49, { color: FG.meta, wrap: "truncate" }, " \xB7 ");
|
|
9421
9545
|
}
|
|
9422
9546
|
function modeGlyph(mode2) {
|
|
9423
9547
|
switch (mode2) {
|
|
@@ -9445,7 +9569,7 @@ function networkDot(state) {
|
|
|
9445
9569
|
}
|
|
9446
9570
|
|
|
9447
9571
|
// src/cli/ui/layout/ToastRail.tsx
|
|
9448
|
-
import { Box as Box47, Text as Text50, useStdout as
|
|
9572
|
+
import { Box as Box47, Text as Text50, useStdout as useStdout14 } from "ink";
|
|
9449
9573
|
import React57, { useEffect as useEffect8 } from "react";
|
|
9450
9574
|
var TONE_COLOR = {
|
|
9451
9575
|
ok: TONE.ok,
|
|
@@ -9468,7 +9592,7 @@ function ToastRail() {
|
|
|
9468
9592
|
const toasts = useAgentState((s) => s.toasts);
|
|
9469
9593
|
const dispatch = useDispatch();
|
|
9470
9594
|
useSlowTick();
|
|
9471
|
-
const { stdout } =
|
|
9595
|
+
const { stdout } = useStdout14();
|
|
9472
9596
|
const cols = stdout?.columns ?? 80;
|
|
9473
9597
|
const rule = "\u2501".repeat(Math.max(20, cols - 4));
|
|
9474
9598
|
const now = Date.now();
|
|
@@ -9873,24 +9997,28 @@ var update = (_args, _loop, ctx) => {
|
|
|
9873
9997
|
return { info: lines.join("\n") };
|
|
9874
9998
|
}
|
|
9875
9999
|
lines.push(t("handlers.admin.updateLatest", { version: latest }));
|
|
9876
|
-
|
|
9877
|
-
if (diff >= 0) {
|
|
10000
|
+
if (compareVersions(VERSION, latest) >= 0) {
|
|
9878
10001
|
lines.push("", t("handlers.admin.updateUpToDate"));
|
|
9879
10002
|
return { info: lines.join("\n") };
|
|
9880
10003
|
}
|
|
9881
|
-
|
|
10004
|
+
const installSource = detectInstallSource();
|
|
10005
|
+
const npmPrefix = installSource === "npm" ? detectNpmInstallPrefix() : null;
|
|
10006
|
+
const plan2 = planUpdate({ current: VERSION, latest, installSource, npmPrefix });
|
|
10007
|
+
if (plan2.action === "npx-hint") {
|
|
9882
10008
|
lines.push("", t("handlers.admin.updateNpxHint"), t("handlers.admin.updateNpxForce"));
|
|
10009
|
+
return { info: lines.join("\n") };
|
|
10010
|
+
}
|
|
10011
|
+
lines.push("", t("handlers.admin.updateUpgradeHint"), t("handlers.admin.updateUpgradeCmd1"));
|
|
10012
|
+
if (plan2.action === "run-install" && plan2.command) {
|
|
10013
|
+
lines.push(t("handlers.admin.updateUpgradeCmd2", { command: plan2.command.join(" ") }));
|
|
9883
10014
|
} else {
|
|
9884
|
-
lines.push(
|
|
9885
|
-
"",
|
|
9886
|
-
t("handlers.admin.updateUpgradeHint"),
|
|
9887
|
-
t("handlers.admin.updateUpgradeCmd1"),
|
|
9888
|
-
t("handlers.admin.updateUpgradeCmd2"),
|
|
9889
|
-
"",
|
|
9890
|
-
t("handlers.admin.updateInSessionDisabled"),
|
|
9891
|
-
t("handlers.admin.updateInSessionDisabled2")
|
|
9892
|
-
);
|
|
10015
|
+
lines.push(...MANUAL_UPDATE_COMMANDS.map((c) => ` ${c}`));
|
|
9893
10016
|
}
|
|
10017
|
+
lines.push(
|
|
10018
|
+
"",
|
|
10019
|
+
t("handlers.admin.updateInSessionDisabled"),
|
|
10020
|
+
t("handlers.admin.updateInSessionDisabled2")
|
|
10021
|
+
);
|
|
9894
10022
|
return { info: lines.join("\n") };
|
|
9895
10023
|
};
|
|
9896
10024
|
var stats = () => {
|
|
@@ -11067,7 +11195,9 @@ function buildFeedbackDiagnostic(input) {
|
|
|
11067
11195
|
}
|
|
11068
11196
|
function formatVersion(installed, latest) {
|
|
11069
11197
|
if (!latest) return installed;
|
|
11070
|
-
|
|
11198
|
+
const cmp = compareVersions(installed, latest);
|
|
11199
|
+
if (cmp === 0) return `${installed} (latest)`;
|
|
11200
|
+
if (cmp > 0) return installed;
|
|
11071
11201
|
return `${installed} (latest: ${latest})`;
|
|
11072
11202
|
}
|
|
11073
11203
|
function formatModel(model2, effort) {
|
|
@@ -11715,6 +11845,31 @@ var handlers17 = {
|
|
|
11715
11845
|
se: (args, loop2, ctx) => handlers17["search-engine"](args, loop2, ctx)
|
|
11716
11846
|
};
|
|
11717
11847
|
|
|
11848
|
+
// src/cli/ui/slash/nearest.ts
|
|
11849
|
+
function nearestCommands(input, all, opts = {}) {
|
|
11850
|
+
if (!input) return [];
|
|
11851
|
+
const max = opts.max ?? 3;
|
|
11852
|
+
const maxDistance = Math.min(opts.maxDistance ?? 3, Math.floor(input.length / 2));
|
|
11853
|
+
if (max <= 0 || maxDistance <= 0) return [];
|
|
11854
|
+
return all.map((name) => ({ name, distance: levenshtein(input, name) })).filter((entry) => entry.distance <= maxDistance).sort((a, b) => a.distance - b.distance || a.name.localeCompare(b.name)).slice(0, max).map((entry) => entry.name);
|
|
11855
|
+
}
|
|
11856
|
+
function levenshtein(a, b) {
|
|
11857
|
+
if (a === b) return 0;
|
|
11858
|
+
if (!a) return b.length;
|
|
11859
|
+
if (!b) return a.length;
|
|
11860
|
+
let prev = Array.from({ length: b.length + 1 }, (_, i) => i);
|
|
11861
|
+
let next = new Array(b.length + 1).fill(0);
|
|
11862
|
+
for (let i = 0; i < a.length; i += 1) {
|
|
11863
|
+
next[0] = i + 1;
|
|
11864
|
+
for (let j = 0; j < b.length; j += 1) {
|
|
11865
|
+
const cost2 = a[i] === b[j] ? 0 : 1;
|
|
11866
|
+
next[j + 1] = Math.min((next[j] ?? 0) + 1, (prev[j + 1] ?? 0) + 1, (prev[j] ?? 0) + cost2);
|
|
11867
|
+
}
|
|
11868
|
+
[prev, next] = [next, prev];
|
|
11869
|
+
}
|
|
11870
|
+
return prev[b.length] ?? 0;
|
|
11871
|
+
}
|
|
11872
|
+
|
|
11718
11873
|
// src/cli/ui/slash/dispatch.ts
|
|
11719
11874
|
var HANDLERS = {
|
|
11720
11875
|
...handlers,
|
|
@@ -11738,6 +11893,11 @@ var HANDLERS = {
|
|
|
11738
11893
|
function handleSlash(cmd, args, loop2, ctx = {}) {
|
|
11739
11894
|
const h = HANDLERS[resolveSlashAlias(cmd)];
|
|
11740
11895
|
if (h) return h(args, loop2, ctx);
|
|
11896
|
+
const suggestions = nearestCommands(cmd, Object.keys(HANDLERS));
|
|
11897
|
+
if (suggestions.length > 0) {
|
|
11898
|
+
const list2 = suggestions.map((name) => `/${name}`).join(", ");
|
|
11899
|
+
return { unknown: true, info: `unknown command: /${cmd} \u2014 did you mean ${list2}?` };
|
|
11900
|
+
}
|
|
11741
11901
|
return { unknown: true, info: `unknown command: /${cmd} (try /help)` };
|
|
11742
11902
|
}
|
|
11743
11903
|
|
|
@@ -11774,6 +11934,16 @@ var TurnTranslator = class {
|
|
|
11774
11934
|
this.toolCardId = null;
|
|
11775
11935
|
}
|
|
11776
11936
|
}
|
|
11937
|
+
toolAbort(output) {
|
|
11938
|
+
if (this.toolCardId) {
|
|
11939
|
+
this.log.endTool(this.toolCardId, {
|
|
11940
|
+
output,
|
|
11941
|
+
elapsedMs: Date.now() - this.toolStartedAt,
|
|
11942
|
+
aborted: true
|
|
11943
|
+
});
|
|
11944
|
+
this.toolCardId = null;
|
|
11945
|
+
}
|
|
11946
|
+
}
|
|
11777
11947
|
toolRetry(attempt, max) {
|
|
11778
11948
|
if (this.toolCardId) this.log.retryTool(this.toolCardId, attempt, max);
|
|
11779
11949
|
}
|
|
@@ -12658,9 +12828,9 @@ function useSubagent({
|
|
|
12658
12828
|
// src/cli/ui/App.tsx
|
|
12659
12829
|
var FLUSH_INTERVAL_MS = (() => {
|
|
12660
12830
|
const raw = process.env.REASONIX_FLUSH_MS;
|
|
12661
|
-
if (!raw) return
|
|
12831
|
+
if (!raw) return 16;
|
|
12662
12832
|
const parsed = Number(raw);
|
|
12663
|
-
if (!Number.isFinite(parsed) || parsed < 16 || parsed > 1e3) return
|
|
12833
|
+
if (!Number.isFinite(parsed) || parsed < 16 || parsed > 1e3) return 16;
|
|
12664
12834
|
return Math.round(parsed);
|
|
12665
12835
|
})();
|
|
12666
12836
|
var PLAIN_UI = process.env.REASONIX_UI === "plain";
|
|
@@ -12702,7 +12872,8 @@ function AppInner({
|
|
|
12702
12872
|
progressSink,
|
|
12703
12873
|
codeMode,
|
|
12704
12874
|
noDashboard,
|
|
12705
|
-
onSwitchSession
|
|
12875
|
+
onSwitchSession,
|
|
12876
|
+
mouse = true
|
|
12706
12877
|
}) {
|
|
12707
12878
|
markPhase("app_inner_start");
|
|
12708
12879
|
const log = useScrollback();
|
|
@@ -12711,6 +12882,7 @@ function AppInner({
|
|
|
12711
12882
|
(s) => s.cards.some((c) => c.kind === "user" || c.kind === "streaming")
|
|
12712
12883
|
);
|
|
12713
12884
|
const isStreaming = useAgentState((s) => s.cards.some((c) => c.kind === "streaming" && !c.done));
|
|
12885
|
+
const activityLabel = useActivityLabel();
|
|
12714
12886
|
const chatScroll = useChatScroll();
|
|
12715
12887
|
const [input, setInput] = useState20("");
|
|
12716
12888
|
const [busy, setBusy] = useState20(false);
|
|
@@ -12734,18 +12906,18 @@ function AppInner({
|
|
|
12734
12906
|
}, [busy]);
|
|
12735
12907
|
const [ongoingTool, setOngoingTool] = useState20(null);
|
|
12736
12908
|
const [toolProgress, setToolProgress] = useState20(null);
|
|
12737
|
-
const { stdout } =
|
|
12909
|
+
const { stdout } = useStdout15();
|
|
12738
12910
|
useEffect12(() => {
|
|
12739
12911
|
if (!stdout || !stdout.isTTY) return;
|
|
12740
12912
|
stdout.write("\x1B[?2004h");
|
|
12741
12913
|
stdout.write("\x1B[>4;2m");
|
|
12742
|
-
stdout.write("\x1B[?
|
|
12914
|
+
if (mouse) stdout.write("\x1B[?1007h");
|
|
12743
12915
|
return () => {
|
|
12744
|
-
stdout.write("\x1B[?
|
|
12916
|
+
if (mouse) stdout.write("\x1B[?1007l");
|
|
12745
12917
|
stdout.write("\x1B[?2004l");
|
|
12746
12918
|
stdout.write("\x1B[>4m");
|
|
12747
12919
|
};
|
|
12748
|
-
}, [stdout]);
|
|
12920
|
+
}, [stdout, mouse]);
|
|
12749
12921
|
const walletCurrencyRef = useRef9(void 0);
|
|
12750
12922
|
const { activities: subagentActivities, sinkRef: subagentSinkRef } = useSubagent({
|
|
12751
12923
|
session,
|
|
@@ -12894,7 +13066,7 @@ function AppInner({
|
|
|
12894
13066
|
const loopRef = useRef9(null);
|
|
12895
13067
|
const loop2 = useMemo9(() => {
|
|
12896
13068
|
if (loopRef.current) return loopRef.current;
|
|
12897
|
-
const client = new DeepSeekClient();
|
|
13069
|
+
const client = new DeepSeekClient({ baseUrl: loadBaseUrl() });
|
|
12898
13070
|
if (tools && !tools.has("run_skill")) {
|
|
12899
13071
|
registerSkillTools(tools, {
|
|
12900
13072
|
projectRoot: codeMode?.rootDir,
|
|
@@ -13214,11 +13386,12 @@ function AppInner({
|
|
|
13214
13386
|
}, [session, loop2, codeMode, syncPendingCount, log]);
|
|
13215
13387
|
const quitProcess = useQuit(transcriptRef);
|
|
13216
13388
|
useKeystroke((ev) => {
|
|
13389
|
+
const pickerOwnsArrows = (atState?.entries.length ?? 0) > 0 || (slashMatches?.length ?? 0) > 0 || (slashArgMatches?.length ?? 0) > 0 || pendingShell != null;
|
|
13217
13390
|
if (ev.pageUp || ev.mouseScrollUp) chatScroll.scrollUp();
|
|
13218
13391
|
else if (ev.pageDown || ev.mouseScrollDown) chatScroll.scrollDown();
|
|
13219
13392
|
else if (ev.end) chatScroll.jumpToBottom();
|
|
13220
|
-
else if (
|
|
13221
|
-
else if (
|
|
13393
|
+
else if (!pickerOwnsArrows && ev.upArrow) chatScroll.scrollUp();
|
|
13394
|
+
else if (!pickerOwnsArrows && ev.downArrow) chatScroll.scrollDown();
|
|
13222
13395
|
}, !modalOpen);
|
|
13223
13396
|
useKeystroke((ev) => {
|
|
13224
13397
|
const chKey = ev.input;
|
|
@@ -13433,7 +13606,7 @@ function AppInner({
|
|
|
13433
13606
|
if (dashboardRef.current) return dashboardRef.current.url;
|
|
13434
13607
|
if (dashboardStartingRef.current) return dashboardStartingRef.current;
|
|
13435
13608
|
const startup = (async () => {
|
|
13436
|
-
const { startDashboardServer } = await import("./server-
|
|
13609
|
+
const { startDashboardServer } = await import("./server-W4XJK4GX.js");
|
|
13437
13610
|
const handle = await startDashboardServer({
|
|
13438
13611
|
mode: "attached",
|
|
13439
13612
|
configPath: defaultConfigPath(),
|
|
@@ -13757,7 +13930,7 @@ function AppInner({
|
|
|
13757
13930
|
}
|
|
13758
13931
|
if (text.startsWith("/") && !text.includes(" ")) {
|
|
13759
13932
|
const typed = text.slice(1).toLowerCase();
|
|
13760
|
-
const matches = suggestSlashCommands(typed, !!codeMode);
|
|
13933
|
+
const matches = suggestSlashCommands(typed, !!codeMode, slashUsage);
|
|
13761
13934
|
const exact = matches.find((m) => m.cmd === typed);
|
|
13762
13935
|
if (!exact && matches.length > 0) {
|
|
13763
13936
|
const chosen = matches[slashSelected] ?? matches[0];
|
|
@@ -14197,7 +14370,13 @@ function AppInner({
|
|
|
14197
14370
|
codeModeOn: !!codeMode
|
|
14198
14371
|
});
|
|
14199
14372
|
} else if (ev.role === "error") {
|
|
14200
|
-
handleErrorEvent(ev, {
|
|
14373
|
+
handleErrorEvent(ev, {
|
|
14374
|
+
log,
|
|
14375
|
+
setOngoingTool,
|
|
14376
|
+
setToolProgress,
|
|
14377
|
+
toolStartedAtRef,
|
|
14378
|
+
translator
|
|
14379
|
+
});
|
|
14201
14380
|
} else if (ev.role === "warning") {
|
|
14202
14381
|
handleWarningEvent(ev, { log, setTurnOnPro });
|
|
14203
14382
|
}
|
|
@@ -14251,6 +14430,7 @@ function AppInner({
|
|
|
14251
14430
|
planMode,
|
|
14252
14431
|
session,
|
|
14253
14432
|
slashSelected,
|
|
14433
|
+
slashUsage,
|
|
14254
14434
|
atState,
|
|
14255
14435
|
atSelected,
|
|
14256
14436
|
pickAtMention,
|
|
@@ -14376,7 +14556,7 @@ function AppInner({
|
|
|
14376
14556
|
}
|
|
14377
14557
|
if (!staged) return;
|
|
14378
14558
|
const trimmed = feedback2.trim();
|
|
14379
|
-
|
|
14559
|
+
const tail = trimmed.length > 50 ? `${trimmed.slice(0, 50)}\u2026` : trimmed;
|
|
14380
14560
|
let marker;
|
|
14381
14561
|
if (staged.mode === "approve") {
|
|
14382
14562
|
togglePlanMode(false);
|
|
@@ -14394,19 +14574,7 @@ function AppInner({
|
|
|
14394
14574
|
});
|
|
14395
14575
|
persistPlanState();
|
|
14396
14576
|
}
|
|
14397
|
-
|
|
14398
|
-
synthetic = `The plan above has been approved. Implement it now. You are out of plan mode \u2014 use edit_file / write_file / run_command as needed.
|
|
14399
|
-
|
|
14400
|
-
User's additional instructions / answers to your open questions:
|
|
14401
|
-
|
|
14402
|
-
${trimmed}
|
|
14403
|
-
|
|
14404
|
-
Factor these in before the first edit. Stick to the plan unless you discover a concrete reason to deviate; if you do, tell me and wait for a response.`;
|
|
14405
|
-
marker = `\u25B8 plan approved + instructions \u2014 ${trimmed.length > 50 ? `${trimmed.slice(0, 50)}\u2026` : trimmed}`;
|
|
14406
|
-
} else {
|
|
14407
|
-
synthetic = "The plan above has been approved. Implement it now. You are out of plan mode \u2014 use edit_file / write_file / run_command as needed. If the plan listed open questions and I didn't answer them, default to the safest interpretation and call them out in your first reply. Don't fabricate preferences \u2014 if a question is truly unanswerable without me, stop and ask.";
|
|
14408
|
-
marker = "\u25B8 plan approved \u2014 implementing";
|
|
14409
|
-
}
|
|
14577
|
+
marker = trimmed ? `\u25B8 plan approved + instructions \u2014 ${tail}` : "\u25B8 plan approved \u2014 implementing";
|
|
14410
14578
|
} else if (staged.mode === "reject") {
|
|
14411
14579
|
planStepsRef.current = null;
|
|
14412
14580
|
completedStepIdsRef.current = /* @__PURE__ */ new Set();
|
|
@@ -14415,38 +14583,20 @@ Factor these in before the first edit. Stick to the plan unless you discover a c
|
|
|
14415
14583
|
persistPlanState();
|
|
14416
14584
|
togglePlanMode(false);
|
|
14417
14585
|
agentStore.dispatch({ type: "plan.drop" });
|
|
14418
|
-
|
|
14419
|
-
synthetic = `The plan was rejected. User's reason / what they actually want:
|
|
14420
|
-
|
|
14421
|
-
${trimmed}
|
|
14422
|
-
|
|
14423
|
-
Drop the proposed plan entirely. Use this guidance to understand what the user is after \u2014 ask follow-up questions if anything is still unclear, otherwise propose a different plan that addresses it.`;
|
|
14424
|
-
marker = `\u25B8 plan rejected \u2014 ${trimmed.length > 50 ? `${trimmed.slice(0, 50)}\u2026` : trimmed}`;
|
|
14425
|
-
} else {
|
|
14426
|
-
synthetic = "The plan was cancelled. Drop it entirely. Ask me what I actually want before proposing another plan or making any changes.";
|
|
14427
|
-
marker = "\u25B8 plan cancelled";
|
|
14428
|
-
}
|
|
14586
|
+
marker = trimmed ? `\u25B8 plan rejected \u2014 ${tail}` : "\u25B8 plan cancelled";
|
|
14429
14587
|
} else {
|
|
14430
|
-
|
|
14431
|
-
synthetic = `The plan needs refinement. User feedback / answers:
|
|
14432
|
-
|
|
14433
|
-
${trimmed}
|
|
14434
|
-
|
|
14435
|
-
Stay in plan mode \u2014 address the feedback (explore more if needed), then submit an improved submit_plan call. Don't propose a near-identical plan unless you explain why the feedback doesn't apply.`;
|
|
14436
|
-
marker = `\u25B8 refining \u2014 ${trimmed.length > 50 ? `${trimmed.slice(0, 50)}\u2026` : trimmed}`;
|
|
14437
|
-
} else {
|
|
14438
|
-
synthetic = "The plan needs refinement. The user saw your open questions / risks block and chose not to answer specifics. Pick the safest default for each open question, call those defaults out explicitly in the new plan, and submit the refined submit_plan. Do not re-ask \u2014 the user already saw the questions.";
|
|
14439
|
-
marker = "\u25B8 refining \u2014 using safe defaults";
|
|
14440
|
-
}
|
|
14588
|
+
marker = trimmed ? `\u25B8 refining \u2014 ${tail}` : "\u25B8 refining \u2014 using safe defaults";
|
|
14441
14589
|
}
|
|
14590
|
+
log.pushInfo(marker);
|
|
14442
14591
|
const gateId = pendingGateIdRef.current;
|
|
14443
14592
|
if (gateId !== null) {
|
|
14593
|
+
const fb = trimmed || void 0;
|
|
14444
14594
|
if (staged.mode === "approve") {
|
|
14445
|
-
pauseGate.resolve(gateId, { type: "approve" });
|
|
14595
|
+
pauseGate.resolve(gateId, { type: "approve", feedback: fb });
|
|
14446
14596
|
} else if (staged.mode === "reject") {
|
|
14447
|
-
pauseGate.resolve(gateId, { type: "cancel" });
|
|
14597
|
+
pauseGate.resolve(gateId, { type: "cancel", feedback: fb });
|
|
14448
14598
|
} else {
|
|
14449
|
-
pauseGate.resolve(gateId, { type: "refine" });
|
|
14599
|
+
pauseGate.resolve(gateId, { type: "refine", feedback: fb });
|
|
14450
14600
|
}
|
|
14451
14601
|
}
|
|
14452
14602
|
},
|
|
@@ -14740,7 +14890,7 @@ Stay in plan mode \u2014 address the feedback (explore more if needed), then sub
|
|
|
14740
14890
|
dashboardUrl,
|
|
14741
14891
|
languageVersion
|
|
14742
14892
|
}
|
|
14743
|
-
) : null, !PLAIN_UI && !pendingShell && !pendingPlan && !pendingReviseEditor && !pendingSessionsPicker && !pendingCheckpointPicker && !pendingMcpHub && !stagedInput && !pendingEditReview && ongoingTool ? /* @__PURE__ */ React60.createElement(OngoingToolRow, { tool: ongoingTool, progress: toolProgress }) : null, !PLAIN_UI && !pendingShell && !pendingPlan && !pendingReviseEditor && !pendingSessionsPicker && !pendingCheckpointPicker && !pendingMcpHub && !stagedInput && !pendingEditReview && subagentActivities.length > 0 ? /* @__PURE__ */ React60.createElement(SubagentLiveStack, { activities: subagentActivities, max: 3 }) : null, !PLAIN_UI && !pendingShell && !pendingPlan && !pendingReviseEditor && !pendingSessionsPicker && !pendingCheckpointPicker && !pendingMcpHub && !stagedInput && !pendingEditReview && !ongoingTool && statusLine ? /* @__PURE__ */ React60.createElement(ThinkingRow, { text: statusLine }) : null, !PLAIN_UI && undoBanner && !pendingShell && !pendingPlan && !pendingReviseEditor && !pendingSessionsPicker && !pendingCheckpointPicker && !pendingMcpHub && !stagedInput && !pendingEditReview && !pendingChoice && !stagedChoiceCustom && !pendingRevision && !stagedCheckpointRevise && !pendingCheckpoint ? /* @__PURE__ */ React60.createElement(UndoBanner, { banner: undoBanner }) : null, !PLAIN_UI && !pendingShell && !pendingPlan && !pendingReviseEditor && !pendingSessionsPicker && !pendingCheckpointPicker && !pendingMcpHub && !stagedInput && !pendingEditReview && busy && !isStreaming && !ongoingTool && !statusLine ? /* @__PURE__ */ React60.createElement(ThinkingRow, { text:
|
|
14893
|
+
) : null, !PLAIN_UI && !pendingShell && !pendingPlan && !pendingReviseEditor && !pendingSessionsPicker && !pendingCheckpointPicker && !pendingMcpHub && !stagedInput && !pendingEditReview && ongoingTool ? /* @__PURE__ */ React60.createElement(OngoingToolRow, { tool: ongoingTool, progress: toolProgress }) : null, !PLAIN_UI && !pendingShell && !pendingPlan && !pendingReviseEditor && !pendingSessionsPicker && !pendingCheckpointPicker && !pendingMcpHub && !stagedInput && !pendingEditReview && subagentActivities.length > 0 ? /* @__PURE__ */ React60.createElement(SubagentLiveStack, { activities: subagentActivities, max: 3 }) : null, !PLAIN_UI && !pendingShell && !pendingPlan && !pendingReviseEditor && !pendingSessionsPicker && !pendingCheckpointPicker && !pendingMcpHub && !stagedInput && !pendingEditReview && !ongoingTool && statusLine ? /* @__PURE__ */ React60.createElement(ThinkingRow, { text: statusLine }) : null, !PLAIN_UI && undoBanner && !pendingShell && !pendingPlan && !pendingReviseEditor && !pendingSessionsPicker && !pendingCheckpointPicker && !pendingMcpHub && !stagedInput && !pendingEditReview && !pendingChoice && !stagedChoiceCustom && !pendingRevision && !stagedCheckpointRevise && !pendingCheckpoint ? /* @__PURE__ */ React60.createElement(UndoBanner, { banner: undoBanner }) : null, !PLAIN_UI && !pendingShell && !pendingPlan && !pendingReviseEditor && !pendingSessionsPicker && !pendingCheckpointPicker && !pendingMcpHub && !stagedInput && !pendingEditReview && busy && !isStreaming && !ongoingTool && !statusLine ? /* @__PURE__ */ React60.createElement(ThinkingRow, { text: activityLabel }) : null, !PLAIN_UI && !pendingShell && !pendingPlan && !pendingReviseEditor && !pendingSessionsPicker && !pendingCheckpointPicker && !pendingMcpHub && !stagedInput && !pendingEditReview ? /* @__PURE__ */ React60.createElement(PlanLiveRow, null) : null, /* @__PURE__ */ React60.createElement(ToastRail, null)), stagedInput ? /* @__PURE__ */ React60.createElement(
|
|
14744
14894
|
PlanRefineInput,
|
|
14745
14895
|
{
|
|
14746
14896
|
mode: stagedInput.mode,
|
|
@@ -14989,7 +15139,7 @@ Stay in plan mode \u2014 address the feedback (explore more if needed), then sub
|
|
|
14989
15139
|
block: pendingEdits.current[0],
|
|
14990
15140
|
onChoose: handleWalkChoice
|
|
14991
15141
|
}
|
|
14992
|
-
) : !chatScroll.pinned ? /* @__PURE__ */ React60.createElement(Text52, { color: FG.faint }, " \u{1F4D6} reading history \u2014 End / PgDn to return \xB7 \u2193 to advance one line") : /* @__PURE__ */ React60.createElement(React60.
|
|
15142
|
+
) : !chatScroll.pinned ? /* @__PURE__ */ React60.createElement(Text52, { color: FG.faint }, " \u{1F4D6} reading history \u2014 End / PgDn to return \xB7 \u2193 to advance one line") : /* @__PURE__ */ React60.createElement(Box49, { flexDirection: "column", flexShrink: 0, flexWrap: "nowrap" }, /* @__PURE__ */ React60.createElement(Box49, { flexDirection: "column", flexShrink: 0, flexWrap: "nowrap" }, codeMode ? /* @__PURE__ */ React60.createElement(
|
|
14993
15143
|
ModeStatusBar,
|
|
14994
15144
|
{
|
|
14995
15145
|
editMode,
|
|
@@ -15009,15 +15159,16 @@ Stay in plan mode \u2014 address the feedback (explore more if needed), then sub
|
|
|
15009
15159
|
onHistoryPrev: recallPrev,
|
|
15010
15160
|
onHistoryNext: recallNext
|
|
15011
15161
|
}
|
|
15012
|
-
), slashMatches !== null ? /* @__PURE__ */ React60.createElement(
|
|
15162
|
+
)), /* @__PURE__ */ React60.createElement(Box49, { flexDirection: "column", flexShrink: 0, flexWrap: "nowrap" }, slashMatches !== null ? /* @__PURE__ */ React60.createElement(
|
|
15013
15163
|
SlashSuggestions,
|
|
15014
15164
|
{
|
|
15165
|
+
key: `slash-suggestions:${slashGroupMode ? "group" : "search"}`,
|
|
15015
15166
|
matches: slashMatches,
|
|
15016
15167
|
selectedIndex: slashSelected,
|
|
15017
15168
|
groupMode: slashGroupMode,
|
|
15018
15169
|
advancedHidden: slashAdvancedHidden
|
|
15019
15170
|
}
|
|
15020
|
-
) : null, atState !== null ? /* @__PURE__ */ React60.createElement(AtMentionSuggestions, { state: atState, selectedIndex: atSelected }) : null, slashArgContext ? /* @__PURE__ */ React60.createElement(
|
|
15171
|
+
) : null, atState !== null ? /* @__PURE__ */ React60.createElement(AtMentionSuggestions, { state: atState, selectedIndex: atSelected }) : null), slashArgContext ? /* @__PURE__ */ React60.createElement(
|
|
15021
15172
|
SlashArgPicker,
|
|
15022
15173
|
{
|
|
15023
15174
|
matches: slashArgMatches,
|
|
@@ -15089,7 +15240,7 @@ function Setup({ onReady }) {
|
|
|
15089
15240
|
return;
|
|
15090
15241
|
}
|
|
15091
15242
|
if (!isPlausibleKey(trimmed)) {
|
|
15092
|
-
setError("
|
|
15243
|
+
setError("Key looks too short \u2014 paste the full token (16+ chars, no spaces).");
|
|
15093
15244
|
setValue("");
|
|
15094
15245
|
return;
|
|
15095
15246
|
}
|
|
@@ -15382,6 +15533,7 @@ function Root({
|
|
|
15382
15533
|
progressSink,
|
|
15383
15534
|
codeMode: appProps.codeMode,
|
|
15384
15535
|
noDashboard: appProps.noDashboard,
|
|
15536
|
+
mouse: appProps.mouse,
|
|
15385
15537
|
onSwitchSession: setActiveSession
|
|
15386
15538
|
}
|
|
15387
15539
|
));
|
|
@@ -15456,7 +15608,12 @@ async function chatCommand(opts) {
|
|
|
15456
15608
|
exitOnCtrlC: true,
|
|
15457
15609
|
// patchConsole:false — winpty/MINTTY redraw-glitch source.
|
|
15458
15610
|
patchConsole: false,
|
|
15459
|
-
incrementalRendering:
|
|
15611
|
+
// incrementalRendering:false — Ink's diff drifts when stringWidth
|
|
15612
|
+
// misjudges CJK / emoji ZWJ width or when async terminal-event
|
|
15613
|
+
// bytes interleave mid-render, leaving residual rows. Full-frame
|
|
15614
|
+
// redraws cost more stdout bytes per flush but eliminate the
|
|
15615
|
+
// ghost class.
|
|
15616
|
+
incrementalRendering: false,
|
|
15460
15617
|
// Default true — alt-screen is the only mode without scrollback-
|
|
15461
15618
|
// reflow ghosting. `--no-alt-screen` opts back into scrollback mode
|
|
15462
15619
|
// for users who need chat output preserved in shell history on exit.
|
|
@@ -15474,4 +15631,4 @@ async function chatCommand(opts) {
|
|
|
15474
15631
|
export {
|
|
15475
15632
|
chatCommand
|
|
15476
15633
|
};
|
|
15477
|
-
//# sourceMappingURL=chunk-
|
|
15634
|
+
//# sourceMappingURL=chunk-3OBWN2NH.js.map
|