@wukonglabs/wukong 0.0.8 → 0.0.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli/exit-codes.js +12 -16
- package/dist/cli/exit-codes.js.map +1 -1
- package/dist/cli/help.d.ts.map +1 -1
- package/dist/cli/help.js +10 -9
- package/dist/cli/help.js.map +1 -1
- package/dist/cli/session-commands.d.ts +28 -0
- package/dist/cli/session-commands.d.ts.map +1 -0
- package/dist/cli/session-commands.js +274 -0
- package/dist/cli/session-commands.js.map +1 -0
- package/dist/cli/summary.js +2 -6
- package/dist/cli/summary.js.map +1 -1
- package/dist/cli/workspace-commands.d.ts +15 -0
- package/dist/cli/workspace-commands.d.ts.map +1 -0
- package/dist/cli/workspace-commands.js +98 -0
- package/dist/cli/workspace-commands.js.map +1 -0
- package/dist/index.js +429 -131
- package/dist/index.js.map +1 -1
- package/dist/sigint-handler.d.ts +62 -0
- package/dist/sigint-handler.d.ts.map +1 -0
- package/dist/sigint-handler.js +62 -0
- package/dist/sigint-handler.js.map +1 -0
- package/dist/tui/app.d.ts +57 -0
- package/dist/tui/app.d.ts.map +1 -0
- package/dist/tui/app.js +194 -0
- package/dist/tui/app.js.map +1 -0
- package/dist/tui/header.d.ts +24 -0
- package/dist/tui/header.d.ts.map +1 -0
- package/dist/tui/header.js +26 -0
- package/dist/tui/header.js.map +1 -0
- package/dist/tui/permission-card.d.ts +27 -0
- package/dist/tui/permission-card.d.ts.map +1 -0
- package/dist/tui/permission-card.js +75 -0
- package/dist/tui/permission-card.js.map +1 -0
- package/dist/tui/plan-panel.d.ts +29 -0
- package/dist/tui/plan-panel.d.ts.map +1 -0
- package/dist/tui/plan-panel.js +26 -0
- package/dist/tui/plan-panel.js.map +1 -0
- package/dist/tui/response-panel.d.ts +49 -0
- package/dist/tui/response-panel.d.ts.map +1 -0
- package/dist/tui/response-panel.js +13 -0
- package/dist/tui/response-panel.js.map +1 -0
- package/dist/tui/run-ink.d.ts +22 -0
- package/dist/tui/run-ink.d.ts.map +1 -0
- package/dist/tui/run-ink.js +31 -0
- package/dist/tui/run-ink.js.map +1 -0
- package/dist/tui/should-use-tui.d.ts +25 -0
- package/dist/tui/should-use-tui.d.ts.map +1 -0
- package/dist/tui/should-use-tui.js +29 -0
- package/dist/tui/should-use-tui.js.map +1 -0
- package/dist/tui/text-input.d.ts +52 -0
- package/dist/tui/text-input.d.ts.map +1 -0
- package/dist/tui/text-input.js +321 -0
- package/dist/tui/text-input.js.map +1 -0
- package/dist/tui/thinking-panel.d.ts +40 -0
- package/dist/tui/thinking-panel.d.ts.map +1 -0
- package/dist/tui/thinking-panel.js +54 -0
- package/dist/tui/thinking-panel.js.map +1 -0
- package/dist/tui/tool-cards.d.ts +30 -0
- package/dist/tui/tool-cards.d.ts.map +1 -0
- package/dist/tui/tool-cards.js +34 -0
- package/dist/tui/tool-cards.js.map +1 -0
- package/dist/tui/use-input-history.d.ts +40 -0
- package/dist/tui/use-input-history.d.ts.map +1 -0
- package/dist/tui/use-input-history.js +123 -0
- package/dist/tui/use-input-history.js.map +1 -0
- package/dist/tui/use-plan-state.d.ts +4 -0
- package/dist/tui/use-plan-state.d.ts.map +1 -0
- package/dist/tui/use-plan-state.js +73 -0
- package/dist/tui/use-plan-state.js.map +1 -0
- package/package.json +7 -2
|
@@ -0,0 +1,321 @@
|
|
|
1
|
+
import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
/**
|
|
3
|
+
* 多行文本输入组件(自研,Ink 自带 ink-text-input 不支持多行 + Ctrl+R)。
|
|
4
|
+
*
|
|
5
|
+
* ## 交互
|
|
6
|
+
*
|
|
7
|
+
* - **Enter**:提交(若 `multiline` 为 false,任何 Enter 都提交)
|
|
8
|
+
* - **Shift+Enter / Alt+Enter**:换行(仅 multiline=true 时)
|
|
9
|
+
* - **Ctrl+J**:换行(终端友好,Ctrl+J = LF)
|
|
10
|
+
* - **↑ / ↓**(单行时):浏览历史
|
|
11
|
+
* - **↑ / ↓**(多行时):移动光标到上/下一行
|
|
12
|
+
* - **Ctrl+R**:进入反查模式;再按跳下一条匹配;Enter 提交当前匹配;Esc 退出
|
|
13
|
+
* - **Ctrl+C**:清理后退出(由 App 层接管 graceful shutdown)
|
|
14
|
+
* - **Ctrl+L**:清屏(Ink 原生 clear)
|
|
15
|
+
*
|
|
16
|
+
* ## 粘贴检测
|
|
17
|
+
*
|
|
18
|
+
* Ink 没有原生 paste 事件。通过监听 `stdin` 的 data chunk,当一次 chunk 中
|
|
19
|
+
* 含多个字符(特别是含换行)时,判定为粘贴,直接整体插入(不走逐字符 input)。
|
|
20
|
+
* 这避免了粘贴中文/长文本时每个字符都触发一次 re-render 的性能问题。
|
|
21
|
+
*
|
|
22
|
+
* ## 可访问性
|
|
23
|
+
*
|
|
24
|
+
* `multiline` 模式下不依赖光标可视化(终端光标控制在不同终端差异大),
|
|
25
|
+
* 用 `▋` 字符标记光标位置;`NO_COLOR` 时仍可见。
|
|
26
|
+
*/
|
|
27
|
+
import { useState, useCallback, useEffect, useRef } from 'react';
|
|
28
|
+
import { Text, useInput, useStdin } from 'ink';
|
|
29
|
+
import { reverseSearch, reverseSearchNext, } from './use-input-history.js';
|
|
30
|
+
const INITIAL_RS = {
|
|
31
|
+
active: false,
|
|
32
|
+
query: '',
|
|
33
|
+
matchIndex: -1,
|
|
34
|
+
};
|
|
35
|
+
export function TextInput({ value, onChange, onSubmit, multiline = true, history, prompt = '> ', placeholder = '', disabled = false, onAbort, }) {
|
|
36
|
+
const [cursor, setCursor] = useState(value.length);
|
|
37
|
+
const [rs, setRs] = useState(INITIAL_RS);
|
|
38
|
+
const { stdin, setRawMode } = useStdin();
|
|
39
|
+
// 用于粘贴检测:记录上次 stdin data 到达时间
|
|
40
|
+
const lastChunkTimeRef = useRef(0);
|
|
41
|
+
// stdin 原始模式(捕获 Ctrl+C / Ctrl+R 等控制字符)
|
|
42
|
+
useEffect(() => {
|
|
43
|
+
if (stdin && typeof setRawMode === 'function') {
|
|
44
|
+
setRawMode(true);
|
|
45
|
+
return () => setRawMode(false);
|
|
46
|
+
}
|
|
47
|
+
return;
|
|
48
|
+
}, [stdin, setRawMode]);
|
|
49
|
+
// ── 粘贴检测:监听 stdin chunk,多字符 chunk 视为粘贴 ──
|
|
50
|
+
useEffect(() => {
|
|
51
|
+
if (!stdin)
|
|
52
|
+
return;
|
|
53
|
+
const onData = (chunk) => {
|
|
54
|
+
const data = typeof chunk === 'string' ? chunk : chunk.toString('utf8');
|
|
55
|
+
// 单字符走 useInput;多字符(>=2)且不是控制序列 → 粘贴
|
|
56
|
+
if (data.length >= 2) {
|
|
57
|
+
const now = Date.now();
|
|
58
|
+
const isPaste = now - lastChunkTimeRef.current < 50 || data.includes('\n');
|
|
59
|
+
lastChunkTimeRef.current = now;
|
|
60
|
+
if (isPaste) {
|
|
61
|
+
// 走整体插入(去掉末尾的单个换行,因为很多粘贴末尾带 \n)
|
|
62
|
+
const cleaned = data.replace(/\r\n/g, '\n').replace(/\r/g, '\n');
|
|
63
|
+
insertText(cleaned);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
else {
|
|
67
|
+
lastChunkTimeRef.current = Date.now();
|
|
68
|
+
}
|
|
69
|
+
};
|
|
70
|
+
stdin.on('data', onData);
|
|
71
|
+
return () => {
|
|
72
|
+
stdin.off('data', onData);
|
|
73
|
+
};
|
|
74
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
75
|
+
}, [stdin, value, cursor, rs]);
|
|
76
|
+
// 插入文本到光标位置
|
|
77
|
+
const insertText = useCallback((text) => {
|
|
78
|
+
const newValue = value.slice(0, cursor) + text + value.slice(cursor);
|
|
79
|
+
onChange(newValue);
|
|
80
|
+
setCursor(cursor + text.length);
|
|
81
|
+
}, [value, cursor, onChange]);
|
|
82
|
+
// 提交当前输入
|
|
83
|
+
const submit = useCallback(() => {
|
|
84
|
+
const trimmed = value;
|
|
85
|
+
if (!trimmed)
|
|
86
|
+
return;
|
|
87
|
+
history?.push(trimmed);
|
|
88
|
+
onSubmit(trimmed);
|
|
89
|
+
onChange('');
|
|
90
|
+
setCursor(0);
|
|
91
|
+
setRs(INITIAL_RS);
|
|
92
|
+
}, [value, history, onSubmit, onChange]);
|
|
93
|
+
useInput((input, key) => {
|
|
94
|
+
if (disabled)
|
|
95
|
+
return;
|
|
96
|
+
// ── Ctrl+R:反查模式 ──
|
|
97
|
+
if (key.ctrl && input === 'r') {
|
|
98
|
+
if (!history || history.entries.length === 0)
|
|
99
|
+
return;
|
|
100
|
+
if (!rs.active) {
|
|
101
|
+
// 进入反查模式,空 query → 找最近一条
|
|
102
|
+
const match = reverseSearch(history.entries, '', history.entries.length - 1);
|
|
103
|
+
setRs({ active: true, query: '', matchIndex: match.index });
|
|
104
|
+
if (match.text)
|
|
105
|
+
onChange(match.text);
|
|
106
|
+
}
|
|
107
|
+
else {
|
|
108
|
+
// 已经在反查模式 → 跳下一条匹配
|
|
109
|
+
if (rs.matchIndex >= 0) {
|
|
110
|
+
const next = reverseSearchNext(history.entries, rs.query, rs.matchIndex);
|
|
111
|
+
setRs({ ...rs, matchIndex: next.index });
|
|
112
|
+
if (next.text)
|
|
113
|
+
onChange(next.text);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
return;
|
|
117
|
+
}
|
|
118
|
+
// ── 反查模式下的其他按键 ──
|
|
119
|
+
if (rs.active) {
|
|
120
|
+
if (key.escape) {
|
|
121
|
+
// Esc:退出反查,保留当前匹配作为输入
|
|
122
|
+
setRs(INITIAL_RS);
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
if (key.return) {
|
|
126
|
+
// Enter:提交当前匹配
|
|
127
|
+
setRs(INITIAL_RS);
|
|
128
|
+
submit();
|
|
129
|
+
return;
|
|
130
|
+
}
|
|
131
|
+
if (key.backspace || key.delete) {
|
|
132
|
+
// 删除 query 最后一个字符,重新匹配
|
|
133
|
+
const newQuery = rs.query.slice(0, -1);
|
|
134
|
+
const match = reverseSearch(history.entries, newQuery);
|
|
135
|
+
setRs({ ...rs, query: newQuery, matchIndex: match.index });
|
|
136
|
+
if (match.text)
|
|
137
|
+
onChange(match.text);
|
|
138
|
+
else
|
|
139
|
+
onChange(newQuery);
|
|
140
|
+
return;
|
|
141
|
+
}
|
|
142
|
+
// 可打印字符 → 追加到 query,重新匹配
|
|
143
|
+
if (input && !key.ctrl && !key.meta && input.length === 1 && input >= ' ') {
|
|
144
|
+
const newQuery = rs.query + input;
|
|
145
|
+
const match = reverseSearch(history.entries, newQuery);
|
|
146
|
+
setRs({ ...rs, query: newQuery, matchIndex: match.index });
|
|
147
|
+
if (match.text)
|
|
148
|
+
onChange(match.text);
|
|
149
|
+
else
|
|
150
|
+
onChange(newQuery);
|
|
151
|
+
return;
|
|
152
|
+
}
|
|
153
|
+
// 其他控制键在反查模式下忽略
|
|
154
|
+
return;
|
|
155
|
+
}
|
|
156
|
+
// ── 普通模式 ──
|
|
157
|
+
if (key.return) {
|
|
158
|
+
// Shift+Enter / Meta+Enter → 换行(多行模式)
|
|
159
|
+
if (multiline && (key.shift || key.meta)) {
|
|
160
|
+
insertText('\n');
|
|
161
|
+
return;
|
|
162
|
+
}
|
|
163
|
+
// 普通 Enter → 提交
|
|
164
|
+
submit();
|
|
165
|
+
return;
|
|
166
|
+
}
|
|
167
|
+
if (key.ctrl && input === 'j') {
|
|
168
|
+
// Ctrl+J = LF,多行模式下换行
|
|
169
|
+
if (multiline) {
|
|
170
|
+
insertText('\n');
|
|
171
|
+
}
|
|
172
|
+
else {
|
|
173
|
+
submit();
|
|
174
|
+
}
|
|
175
|
+
return;
|
|
176
|
+
}
|
|
177
|
+
if (key.ctrl && input === 'c') {
|
|
178
|
+
// §3.3 M3:Ctrl+C 交给 App 层处理两次语义(graceful shutdown)
|
|
179
|
+
// Ink raw mode拦截 Ctrl+C 不走 process SIGINT,故需显式回调
|
|
180
|
+
onAbort?.();
|
|
181
|
+
return;
|
|
182
|
+
}
|
|
183
|
+
if (key.backspace || key.delete) {
|
|
184
|
+
if (cursor > 0) {
|
|
185
|
+
// 删除光标前一个字符(含跨行 \n)
|
|
186
|
+
const newValue = value.slice(0, cursor - 1) + value.slice(cursor);
|
|
187
|
+
onChange(newValue);
|
|
188
|
+
setCursor(cursor - 1);
|
|
189
|
+
}
|
|
190
|
+
return;
|
|
191
|
+
}
|
|
192
|
+
if (key.leftArrow) {
|
|
193
|
+
setCursor(Math.max(0, cursor - 1));
|
|
194
|
+
return;
|
|
195
|
+
}
|
|
196
|
+
if (key.rightArrow) {
|
|
197
|
+
setCursor(Math.min(value.length, cursor + 1));
|
|
198
|
+
return;
|
|
199
|
+
}
|
|
200
|
+
if (key.upArrow) {
|
|
201
|
+
// 多行模式:光标移到上一行(如果有)
|
|
202
|
+
if (multiline) {
|
|
203
|
+
const { lineStart, lineIndex, colInLine } = getLineInfo(value, cursor);
|
|
204
|
+
if (lineIndex > 0) {
|
|
205
|
+
// 上一行同列位置
|
|
206
|
+
const prevLineStart = value.lastIndexOf('\n', lineStart - 1) + 1;
|
|
207
|
+
const prevLineEnd = lineStart - 1;
|
|
208
|
+
const prevLineLen = prevLineEnd - prevLineStart;
|
|
209
|
+
const newCol = Math.min(colInLine, prevLineLen);
|
|
210
|
+
setCursor(prevLineStart + newCol);
|
|
211
|
+
return;
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
// 单行模式 或 多行已在第一行 → 浏览历史
|
|
215
|
+
if (history) {
|
|
216
|
+
const text = history.navigate('up', value);
|
|
217
|
+
if (text !== null) {
|
|
218
|
+
onChange(text);
|
|
219
|
+
setCursor(text.length);
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
return;
|
|
223
|
+
}
|
|
224
|
+
if (key.downArrow) {
|
|
225
|
+
if (multiline) {
|
|
226
|
+
const { lineEnd, lineIndex, colInLine, totalLines } = getLineInfo(value, cursor);
|
|
227
|
+
if (lineIndex < totalLines - 1) {
|
|
228
|
+
const nextLineStart = lineEnd + 1;
|
|
229
|
+
const nextLineEnd = value.indexOf('\n', nextLineStart);
|
|
230
|
+
const nextLineLen = (nextLineEnd === -1 ? value.length : nextLineEnd) - nextLineStart;
|
|
231
|
+
const newCol = Math.min(colInLine, nextLineLen);
|
|
232
|
+
setCursor(nextLineStart + newCol);
|
|
233
|
+
return;
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
// 单行 或 多行最后一行 → 浏览历史
|
|
237
|
+
if (history) {
|
|
238
|
+
const text = history.navigate('down', value);
|
|
239
|
+
if (text !== null) {
|
|
240
|
+
onChange(text);
|
|
241
|
+
setCursor(text.length);
|
|
242
|
+
}
|
|
243
|
+
else {
|
|
244
|
+
// 到底恢复草稿
|
|
245
|
+
history.exitNavigation();
|
|
246
|
+
onChange(history.draftBeforeNav);
|
|
247
|
+
setCursor(history.draftBeforeNav.length);
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
return;
|
|
251
|
+
}
|
|
252
|
+
// Home / End
|
|
253
|
+
if (key.ctrl && input === 'a') {
|
|
254
|
+
// 行首
|
|
255
|
+
const lineStart = value.lastIndexOf('\n', cursor - 1) + 1;
|
|
256
|
+
setCursor(lineStart);
|
|
257
|
+
return;
|
|
258
|
+
}
|
|
259
|
+
if (key.ctrl && input === 'e') {
|
|
260
|
+
// 行尾
|
|
261
|
+
const lineEnd = value.indexOf('\n', cursor);
|
|
262
|
+
setCursor(lineEnd === -1 ? value.length : lineEnd);
|
|
263
|
+
return;
|
|
264
|
+
}
|
|
265
|
+
// 可打印字符
|
|
266
|
+
if (input && !key.ctrl && !key.meta && input.length === 1 && input >= ' ') {
|
|
267
|
+
// 任何编辑都退出历史导航
|
|
268
|
+
history?.exitNavigation();
|
|
269
|
+
insertText(input);
|
|
270
|
+
return;
|
|
271
|
+
}
|
|
272
|
+
});
|
|
273
|
+
// ── 渲染 ──
|
|
274
|
+
// 反查模式:显示 (reverse-i-search)`query`: match
|
|
275
|
+
if (rs.active) {
|
|
276
|
+
const matchText = rs.matchIndex >= 0 && history ? history.entries[rs.matchIndex] : '';
|
|
277
|
+
return (_jsxs(Text, { children: [_jsxs(Text, { dimColor: true, children: ["(reverse-i-search)`", rs.query, "`: "] }), _jsx(Text, { color: "cyan", children: matchText || '(无匹配)' })] }));
|
|
278
|
+
}
|
|
279
|
+
// 空输入 + placeholder
|
|
280
|
+
if (!value && placeholder) {
|
|
281
|
+
return (_jsxs(Text, { children: [_jsx(Text, { color: "green", children: prompt }), _jsx(Text, { dimColor: true, children: placeholder })] }));
|
|
282
|
+
}
|
|
283
|
+
// 带光标渲染(▋ 标记光标位置)
|
|
284
|
+
const before = value.slice(0, cursor);
|
|
285
|
+
const at = value.slice(cursor, cursor + 1);
|
|
286
|
+
const after = value.slice(cursor + 1);
|
|
287
|
+
return (_jsxs(Text, { children: [_jsx(Text, { color: "green", children: prompt }), before, _jsx(Text, { inverse: true, children: at || ' ' }), after] }));
|
|
288
|
+
}
|
|
289
|
+
function getLineInfo(value, cursor) {
|
|
290
|
+
// 找当前行的起始
|
|
291
|
+
let lineStart = 0;
|
|
292
|
+
for (let i = cursor - 1; i >= 0; i--) {
|
|
293
|
+
if (value[i] === '\n') {
|
|
294
|
+
lineStart = i + 1;
|
|
295
|
+
break;
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
// 找当前行的结束
|
|
299
|
+
let lineEnd = value.length;
|
|
300
|
+
for (let i = cursor; i < value.length; i++) {
|
|
301
|
+
if (value[i] === '\n') {
|
|
302
|
+
lineEnd = i;
|
|
303
|
+
break;
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
// 行号 + 总行数
|
|
307
|
+
let lineIndex = 0;
|
|
308
|
+
for (let i = 0; i < lineStart; i++) {
|
|
309
|
+
if (value[i] === '\n')
|
|
310
|
+
lineIndex++;
|
|
311
|
+
}
|
|
312
|
+
const totalLines = (value.match(/\n/g)?.length ?? 0) + 1;
|
|
313
|
+
return {
|
|
314
|
+
lineStart,
|
|
315
|
+
lineEnd,
|
|
316
|
+
lineIndex,
|
|
317
|
+
totalLines,
|
|
318
|
+
colInLine: cursor - lineStart,
|
|
319
|
+
};
|
|
320
|
+
}
|
|
321
|
+
//# sourceMappingURL=text-input.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"text-input.js","sourceRoot":"","sources":["../../src/tui/text-input.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Thinking panel —— 流式渲染 agent 的思考过程(thinking_delta)。
|
|
3
|
+
*
|
|
4
|
+
* ## 数据源
|
|
5
|
+
*
|
|
6
|
+
* onStream 回调的 `thinking_delta` 事件(不在 EventBus 里,属于 LLM 流式层)。
|
|
7
|
+
* App 层把 thinking_delta 转发到本组件的 props。
|
|
8
|
+
*
|
|
9
|
+
* ## 渲染
|
|
10
|
+
*
|
|
11
|
+
* 可折叠;默认折叠(只显示一行摘要),按 `t` 键展开。
|
|
12
|
+
* 折叠时:
|
|
13
|
+
* ```
|
|
14
|
+
* 💭 Thinking... (247 字符)
|
|
15
|
+
* ```
|
|
16
|
+
* 展开时:
|
|
17
|
+
* ```
|
|
18
|
+
* 💭 Thinking...
|
|
19
|
+
* 让我先看看 utils/ 下面的文件,可能有重复...
|
|
20
|
+
* ```
|
|
21
|
+
*
|
|
22
|
+
* ## 性能
|
|
23
|
+
*
|
|
24
|
+
* thinking_delta 可能高频(每秒几十次)。本组件用 React state 累积,
|
|
25
|
+
* 依赖 React 的 batch 更新 + Ink 的 30 FPS 渲染上限自然 throttle。
|
|
26
|
+
* 若实测卡顿,M5 后续可加显式 throttle(参见 §3.1 性能预算)。
|
|
27
|
+
*/
|
|
28
|
+
import React from 'react';
|
|
29
|
+
export interface ThinkingPanelProps {
|
|
30
|
+
/** 当前累积的思考内容 */
|
|
31
|
+
thinking: string;
|
|
32
|
+
/** 是否正在流式接收 thinking */
|
|
33
|
+
streaming: boolean;
|
|
34
|
+
/** 是否展开(受控);不传则组件内部管理 */
|
|
35
|
+
expanded?: boolean;
|
|
36
|
+
/** 折叠/展开切换回调 */
|
|
37
|
+
onToggleExpand?: (expanded: boolean) => void;
|
|
38
|
+
}
|
|
39
|
+
export declare function ThinkingPanel({ thinking, streaming, expanded, onToggleExpand, }: ThinkingPanelProps): React.ReactElement | null;
|
|
40
|
+
//# sourceMappingURL=thinking-panel.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"thinking-panel.d.ts","sourceRoot":"","sources":["../../src/tui/thinking-panel.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,OAAO,KAAmB,MAAM,OAAO,CAAC;AAGxC,MAAM,WAAW,kBAAkB;IACjC,gBAAgB;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,wBAAwB;IACxB,SAAS,EAAE,OAAO,CAAC;IACnB,yBAAyB;IACzB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,gBAAgB;IAChB,cAAc,CAAC,EAAE,CAAC,QAAQ,EAAE,OAAO,KAAK,IAAI,CAAC;CAC9C;AAED,wBAAgB,aAAa,CAAC,EAC5B,QAAQ,EACR,SAAS,EACT,QAAgB,EAChB,cAAc,GACf,EAAE,kBAAkB,GAAG,KAAK,CAAC,YAAY,GAAG,IAAI,CAuChD"}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
/**
|
|
3
|
+
* Thinking panel —— 流式渲染 agent 的思考过程(thinking_delta)。
|
|
4
|
+
*
|
|
5
|
+
* ## 数据源
|
|
6
|
+
*
|
|
7
|
+
* onStream 回调的 `thinking_delta` 事件(不在 EventBus 里,属于 LLM 流式层)。
|
|
8
|
+
* App 层把 thinking_delta 转发到本组件的 props。
|
|
9
|
+
*
|
|
10
|
+
* ## 渲染
|
|
11
|
+
*
|
|
12
|
+
* 可折叠;默认折叠(只显示一行摘要),按 `t` 键展开。
|
|
13
|
+
* 折叠时:
|
|
14
|
+
* ```
|
|
15
|
+
* 💭 Thinking... (247 字符)
|
|
16
|
+
* ```
|
|
17
|
+
* 展开时:
|
|
18
|
+
* ```
|
|
19
|
+
* 💭 Thinking...
|
|
20
|
+
* 让我先看看 utils/ 下面的文件,可能有重复...
|
|
21
|
+
* ```
|
|
22
|
+
*
|
|
23
|
+
* ## 性能
|
|
24
|
+
*
|
|
25
|
+
* thinking_delta 可能高频(每秒几十次)。本组件用 React state 累积,
|
|
26
|
+
* 依赖 React 的 batch 更新 + Ink 的 30 FPS 渲染上限自然 throttle。
|
|
27
|
+
* 若实测卡顿,M5 后续可加显式 throttle(参见 §3.1 性能预算)。
|
|
28
|
+
*/
|
|
29
|
+
import { useState } from 'react';
|
|
30
|
+
import { Box, Text, useInput } from 'ink';
|
|
31
|
+
export function ThinkingPanel({ thinking, streaming, expanded = false, onToggleExpand, }) {
|
|
32
|
+
const [internalExpanded, setInternalExpanded] = useState(expanded);
|
|
33
|
+
const isExpanded = onToggleExpand ? expanded : internalExpanded;
|
|
34
|
+
// 按 t 键切换展开/折叠(仅在有内容时响应)
|
|
35
|
+
useInput((input) => {
|
|
36
|
+
if (input === 't' && thinking.length > 0) {
|
|
37
|
+
const next = !isExpanded;
|
|
38
|
+
if (onToggleExpand)
|
|
39
|
+
onToggleExpand(next);
|
|
40
|
+
else
|
|
41
|
+
setInternalExpanded(next);
|
|
42
|
+
}
|
|
43
|
+
});
|
|
44
|
+
// 无内容 → 不渲染
|
|
45
|
+
if (!thinking)
|
|
46
|
+
return null;
|
|
47
|
+
const icon = streaming ? '💭' : '💭';
|
|
48
|
+
const summary = `(按 t 展开, ${thinking.length} 字符)`;
|
|
49
|
+
if (!isExpanded) {
|
|
50
|
+
return (_jsxs(Box, { children: [_jsxs(Text, { color: "magenta", children: [icon, " Thinking..."] }), _jsxs(Text, { dimColor: true, children: [" ", summary] })] }));
|
|
51
|
+
}
|
|
52
|
+
return (_jsxs(Box, { flexDirection: "column", children: [_jsxs(Box, { children: [_jsxs(Text, { color: "magenta", bold: true, children: [icon, " Thinking"] }), _jsx(Text, { dimColor: true, children: " (\u6309 t \u6298\u53E0)" })] }), _jsx(Text, { dimColor: true, color: "magenta", children: thinking })] }));
|
|
53
|
+
}
|
|
54
|
+
//# sourceMappingURL=thinking-panel.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"thinking-panel.js","sourceRoot":"","sources":["../../src/tui/thinking-panel.tsx"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,OAAc,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AACxC,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,KAAK,CAAC;AAa1C,MAAM,UAAU,aAAa,CAAC,EAC5B,QAAQ,EACR,SAAS,EACT,QAAQ,GAAG,KAAK,EAChB,cAAc,GACK;IACnB,MAAM,CAAC,gBAAgB,EAAE,mBAAmB,CAAC,GAAG,QAAQ,CAAC,QAAQ,CAAC,CAAC;IACnE,MAAM,UAAU,GAAG,cAAc,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,gBAAgB,CAAC;IAEhE,yBAAyB;IACzB,QAAQ,CAAC,CAAC,KAAK,EAAE,EAAE;QACjB,IAAI,KAAK,KAAK,GAAG,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACzC,MAAM,IAAI,GAAG,CAAC,UAAU,CAAC;YACzB,IAAI,cAAc;gBAAE,cAAc,CAAC,IAAI,CAAC,CAAC;;gBACpC,mBAAmB,CAAC,IAAI,CAAC,CAAC;QACjC,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,YAAY;IACZ,IAAI,CAAC,QAAQ;QAAE,OAAO,IAAI,CAAC;IAE3B,MAAM,IAAI,GAAG,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC;IACrC,MAAM,OAAO,GAAG,YAAY,QAAQ,CAAC,MAAM,MAAM,CAAC;IAElD,IAAI,CAAC,UAAU,EAAE,CAAC;QAChB,OAAO,CACL,MAAC,GAAG,eACF,MAAC,IAAI,IAAC,KAAK,EAAC,SAAS,aAAE,IAAI,oBAAoB,EAC/C,MAAC,IAAI,IAAC,QAAQ,wBAAG,OAAO,IAAQ,IAC5B,CACP,CAAC;IACJ,CAAC;IAED,OAAO,CACL,MAAC,GAAG,IAAC,aAAa,EAAC,QAAQ,aACzB,MAAC,GAAG,eACF,MAAC,IAAI,IAAC,KAAK,EAAC,SAAS,EAAC,IAAI,mBAAE,IAAI,iBAAiB,EACjD,KAAC,IAAI,IAAC,QAAQ,+CAAiB,IAC3B,EACN,KAAC,IAAI,IAAC,QAAQ,QAAC,KAAK,EAAC,SAAS,YAC3B,QAAQ,GACJ,IACH,CACP,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tool cards —— 每个工具调用一张卡片,展示状态/耗时/参数摘要。
|
|
3
|
+
*
|
|
4
|
+
* ## 数据源
|
|
5
|
+
*
|
|
6
|
+
* 订阅 EventBus 的 `tool_call_start` / `tool_call_end` 事件。
|
|
7
|
+
* 本组件接收 App 维护的 activeTools + completedTools 列表(由 App 订阅事件后传入),
|
|
8
|
+
* 保持组件本身纯展示,便于测试。
|
|
9
|
+
*
|
|
10
|
+
* ## 折叠
|
|
11
|
+
*
|
|
12
|
+
* 并行工具超过 `maxVisible`(默认 5)时,只展示最近 N 个 + "还有 X 个" 折叠提示。
|
|
13
|
+
* 避免一次 15 个 read_file 把终端刷爆(§3.1 性能预算)。
|
|
14
|
+
*
|
|
15
|
+
* ## 状态
|
|
16
|
+
*
|
|
17
|
+
* - ⏳ running(黄色)
|
|
18
|
+
* - ✓ done(绿色)
|
|
19
|
+
* - ✗ failed(红色)
|
|
20
|
+
*/
|
|
21
|
+
import React from 'react';
|
|
22
|
+
import type { ToolCallState } from './response-panel.js';
|
|
23
|
+
export interface ToolCardsProps {
|
|
24
|
+
/** 活跃 + 最近完成的 tool call(已完成但未过期的) */
|
|
25
|
+
tools: ToolCallState[];
|
|
26
|
+
/** 最大可见卡片数;超出折叠(默认 5) */
|
|
27
|
+
maxVisible?: number;
|
|
28
|
+
}
|
|
29
|
+
export declare function ToolCards({ tools, maxVisible }: ToolCardsProps): React.ReactElement | null;
|
|
30
|
+
//# sourceMappingURL=tool-cards.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tool-cards.d.ts","sourceRoot":"","sources":["../../src/tui/tool-cards.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AACH,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAEzD,MAAM,WAAW,cAAc;IAC7B,qCAAqC;IACrC,KAAK,EAAE,aAAa,EAAE,CAAC;IACvB,yBAAyB;IACzB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,wBAAgB,SAAS,CAAC,EAAE,KAAK,EAAE,UAAc,EAAE,EAAE,cAAc,GAAG,KAAK,CAAC,YAAY,GAAG,IAAI,CAmB9F"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { Box, Text } from 'ink';
|
|
3
|
+
export function ToolCards({ tools, maxVisible = 5 }) {
|
|
4
|
+
if (tools.length === 0)
|
|
5
|
+
return null;
|
|
6
|
+
// 按开始时间排序,最近在前
|
|
7
|
+
const sorted = [...tools].sort((a, b) => b.startedAt - a.startedAt);
|
|
8
|
+
const visible = sorted.slice(0, maxVisible);
|
|
9
|
+
const hidden = sorted.length - visible.length;
|
|
10
|
+
return (_jsxs(Box, { flexDirection: "column", marginY: 0, children: [_jsx(Text, { dimColor: true, bold: true, children: "\uD83D\uDD27 Tools" }), visible.map((t) => (_jsx(ToolCardRow, { tool: t }, t.toolCallId))), hidden > 0 && (_jsxs(Text, { dimColor: true, children: [" \u2026 \u8FD8\u6709 ", hidden, " \u4E2A\u5DE5\u5177\u8C03\u7528(\u5DF2\u6298\u53E0)"] }))] }));
|
|
11
|
+
}
|
|
12
|
+
function ToolCardRow({ tool }) {
|
|
13
|
+
const now = Date.now();
|
|
14
|
+
const elapsed = ((tool.endedAt ?? now) - tool.startedAt) / 1000;
|
|
15
|
+
const status = tool.success === undefined ? 'running' : tool.success ? 'done' : 'failed';
|
|
16
|
+
const { icon, color } = statusVisual(status);
|
|
17
|
+
return (_jsxs(Box, { flexDirection: "column", children: [_jsxs(Box, { children: [_jsx(Text, { color: color, children: icon }), _jsxs(Text, { children: [" \u26A1 ", tool.name] }), _jsxs(Text, { dimColor: true, children: [" [", elapsed.toFixed(2), "s]"] }), tool.step > 0 && _jsxs(Text, { dimColor: true, children: [" (step ", tool.step, ")"] })] }), tool.resultPreview && (_jsxs(Text, { dimColor: true, children: [" \u21B3 ", truncate(tool.resultPreview, 100)] }))] }));
|
|
18
|
+
}
|
|
19
|
+
function statusVisual(status) {
|
|
20
|
+
switch (status) {
|
|
21
|
+
case 'done':
|
|
22
|
+
return { icon: '✓', color: 'green' };
|
|
23
|
+
case 'failed':
|
|
24
|
+
return { icon: '✗', color: 'red' };
|
|
25
|
+
default:
|
|
26
|
+
return { icon: '⏳', color: 'yellow' };
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
function truncate(s, max) {
|
|
30
|
+
if (s.length <= max)
|
|
31
|
+
return s;
|
|
32
|
+
return s.slice(0, max - 1) + '…';
|
|
33
|
+
}
|
|
34
|
+
//# sourceMappingURL=tool-cards.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tool-cards.js","sourceRoot":"","sources":["../../src/tui/tool-cards.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
export interface InputHistoryState {
|
|
2
|
+
/** 当前已落盘的历史条目(已提交过的输入),最新在数组末尾 */
|
|
3
|
+
entries: string[];
|
|
4
|
+
/** 添加一条新历史(去重最后一条,空字符串不入) */
|
|
5
|
+
push: (entry: string) => void;
|
|
6
|
+
/** 当前导航到的历史索引;null 表示不在历史导航中(在编辑草稿) */
|
|
7
|
+
navIndex: number | null;
|
|
8
|
+
/** 跳到指定历史索引,并返回该条文本 */
|
|
9
|
+
navigate: (direction: 'up' | 'down', currentDraft: string) => string | null;
|
|
10
|
+
/** 退出历史导航,保留草稿 */
|
|
11
|
+
exitNavigation: () => void;
|
|
12
|
+
/** 保存进入历史导航前的草稿(用于下键到底时恢复) */
|
|
13
|
+
draftBeforeNav: string;
|
|
14
|
+
}
|
|
15
|
+
export declare function useInputHistory(initial?: string[]): InputHistoryState;
|
|
16
|
+
export interface ReverseSearchResult {
|
|
17
|
+
/** 匹配到的历史索引;-1 表示无匹配 */
|
|
18
|
+
index: number;
|
|
19
|
+
/** 匹配到的文本(无匹配时为空串) */
|
|
20
|
+
text: string;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* 在历史中从 `fromIndex`(含)向更早的方向找第一条包含 `query` 的条目。
|
|
24
|
+
*
|
|
25
|
+
* @param entries 历史条目(末尾为最新)
|
|
26
|
+
* @param query 查询子串(大小写不敏感)
|
|
27
|
+
* @param fromIndex 从哪个索引开始往前找(含);默认从末尾开始
|
|
28
|
+
* @returns 匹配结果;无匹配返回 { index: -1, text: '' }
|
|
29
|
+
*/
|
|
30
|
+
export declare function reverseSearch(entries: string[], query: string, fromIndex?: number): ReverseSearchResult;
|
|
31
|
+
/**
|
|
32
|
+
* 跳到当前匹配之前的下一条匹配(用于"再按 Ctrl+R")。
|
|
33
|
+
*
|
|
34
|
+
* @param entries 历史条目
|
|
35
|
+
* @param query 查询子串
|
|
36
|
+
* @param currentIndex 当前匹配的索引
|
|
37
|
+
* @returns 新的匹配结果;无更早匹配时返回原 currentIndex 的结果
|
|
38
|
+
*/
|
|
39
|
+
export declare function reverseSearchNext(entries: string[], query: string, currentIndex: number): ReverseSearchResult;
|
|
40
|
+
//# sourceMappingURL=use-input-history.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-input-history.d.ts","sourceRoot":"","sources":["../../src/tui/use-input-history.ts"],"names":[],"mappings":"AA0BA,MAAM,WAAW,iBAAiB;IAChC,kCAAkC;IAClC,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,6BAA6B;IAC7B,IAAI,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAC9B,uCAAuC;IACvC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,uBAAuB;IACvB,QAAQ,EAAE,CAAC,SAAS,EAAE,IAAI,GAAG,MAAM,EAAE,YAAY,EAAE,MAAM,KAAK,MAAM,GAAG,IAAI,CAAC;IAC5E,kBAAkB;IAClB,cAAc,EAAE,MAAM,IAAI,CAAC;IAC3B,8BAA8B;IAC9B,cAAc,EAAE,MAAM,CAAC;CACxB;AAED,wBAAgB,eAAe,CAAC,OAAO,GAAE,MAAM,EAAO,GAAG,iBAAiB,CAiEzE;AAMD,MAAM,WAAW,mBAAmB;IAClC,wBAAwB;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,sBAAsB;IACtB,IAAI,EAAE,MAAM,CAAC;CACd;AAED;;;;;;;GAOG;AACH,wBAAgB,aAAa,CAC3B,OAAO,EAAE,MAAM,EAAE,EACjB,KAAK,EAAE,MAAM,EACb,SAAS,GAAE,MAA2B,GACrC,mBAAmB,CASrB;AAED;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAC/B,OAAO,EAAE,MAAM,EAAE,EACjB,KAAK,EAAE,MAAM,EACb,YAAY,EAAE,MAAM,GACnB,mBAAmB,CAOrB"}
|