@gird/ccli 2.11.0 → 2.12.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -1
- package/dist/agent/ai.js +18 -4
- package/dist/agent/ai.js.map +1 -1
- package/dist/cli/confirm-select.js +123 -0
- package/dist/cli/confirm-select.js.map +1 -1
- package/dist/cli/repl/index.js +34 -6
- package/dist/cli/repl/index.js.map +1 -1
- package/dist/cli/run/fold.js +48 -0
- package/dist/cli/run/fold.js.map +1 -0
- package/dist/cli/run/format.js +278 -0
- package/dist/cli/run/format.js.map +1 -0
- package/dist/cli/run/index.js +102 -15
- package/dist/cli/run/index.js.map +1 -1
- package/dist/cli/run/permissions.js +98 -0
- package/dist/cli/run/permissions.js.map +1 -0
- package/dist/cli/run/stream-write.js +146 -0
- package/dist/cli/run/stream-write.js.map +1 -0
- package/dist/cli/slash/system/agent.js +1 -1
- package/dist/cli/slash/system/agent.js.map +1 -1
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,278 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 工具调用与结果的一行摘要(供 REPL 默认展示)。
|
|
3
|
+
*
|
|
4
|
+
* 之前 REPL 在工具调用前直接打印 `⚙ name(<原始 JSON 参数>)`,长 content 会整段刷屏,
|
|
5
|
+
* 工具结果又不展示,看起来「猛地一坨、没有格式」。这里把调用和结果都提炼成清爽的一行,
|
|
6
|
+
* 每个工具即时打印两行(调用 → 结果),逐步出现、不刷屏。
|
|
7
|
+
*/
|
|
8
|
+
import { style } from '../style.js';
|
|
9
|
+
function safeParse(argsJson) {
|
|
10
|
+
try {
|
|
11
|
+
return JSON.parse(argsJson || '{}');
|
|
12
|
+
}
|
|
13
|
+
catch {
|
|
14
|
+
return {};
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
/** 压成单行(去掉换行 / 多余空白)。 */
|
|
18
|
+
function oneLine(s) {
|
|
19
|
+
return s.replace(/\s+/g, ' ').trim();
|
|
20
|
+
}
|
|
21
|
+
function trunc(s, n) {
|
|
22
|
+
const o = oneLine(s);
|
|
23
|
+
return o.length > n ? o.slice(0, n) + '…' : o;
|
|
24
|
+
}
|
|
25
|
+
function lineCount(s) {
|
|
26
|
+
if (s === '')
|
|
27
|
+
return 0;
|
|
28
|
+
return s.split('\n').length;
|
|
29
|
+
}
|
|
30
|
+
function firstLine(s) {
|
|
31
|
+
return s.split('\n')[0] ?? '';
|
|
32
|
+
}
|
|
33
|
+
/** 工具调用的一行摘要(不含前缀符号,由调用方加 ⚙)。 */
|
|
34
|
+
export function formatToolCall(tc) {
|
|
35
|
+
const args = safeParse(tc.arguments);
|
|
36
|
+
switch (tc.name) {
|
|
37
|
+
case 'read_file':
|
|
38
|
+
case 'list_dir':
|
|
39
|
+
return `${tc.name} ${args.path ?? ''}`;
|
|
40
|
+
case 'grep':
|
|
41
|
+
return `grep "${trunc(String(args.pattern ?? ''), 40)}" ${args.path ?? ''}`;
|
|
42
|
+
case 'write_file': {
|
|
43
|
+
const lines = lineCount(String(args.content ?? ''));
|
|
44
|
+
return `write_file ${args.path ?? ''} (${lines} 行)`;
|
|
45
|
+
}
|
|
46
|
+
case 'edit_file':
|
|
47
|
+
return `edit_file ${args.path ?? ''}`;
|
|
48
|
+
case 'bash':
|
|
49
|
+
return `bash ${trunc(String(args.command ?? ''), 60)}`;
|
|
50
|
+
case 'bash_output':
|
|
51
|
+
case 'kill_bash':
|
|
52
|
+
return `${tc.name} ${args.id ?? ''}`;
|
|
53
|
+
default: {
|
|
54
|
+
if (tc.name.startsWith('mcp__')) {
|
|
55
|
+
const [, server, tool] = tc.name.split('__');
|
|
56
|
+
return `mcp ${server}.${tool}`;
|
|
57
|
+
}
|
|
58
|
+
return `${tc.name}(${trunc(tc.arguments, 60)})`;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
/** 工具结果的一行摘要。bash 额外提取退出码;错误结果以 ✗ 开头。 */
|
|
63
|
+
export function formatToolResult(tc, result) {
|
|
64
|
+
const text = result ?? '';
|
|
65
|
+
if (!text || text === '(无输出)')
|
|
66
|
+
return '(无输出)';
|
|
67
|
+
if (tc.name === 'bash') {
|
|
68
|
+
const m = text.match(/\[退出码 (\d+)\]/);
|
|
69
|
+
const code = m ? m[1] : '0';
|
|
70
|
+
const body = text.replace(/\n?\[退出码 \d+\]/, '').trim();
|
|
71
|
+
const summary = body
|
|
72
|
+
? `${trunc(firstLine(body), 60)}${lineCount(body) > 1 ? ` (共 ${lineCount(body)} 行)` : ''}`
|
|
73
|
+
: '(无输出)';
|
|
74
|
+
return `退出码 ${code} · ${summary}`;
|
|
75
|
+
}
|
|
76
|
+
const isError = text.startsWith('错误');
|
|
77
|
+
const summary = `${trunc(firstLine(text), 80)}${lineCount(text) > 1 ? ` (共 ${lineCount(text)} 行)` : ''}`;
|
|
78
|
+
return isError ? `✗ ${summary}` : summary;
|
|
79
|
+
}
|
|
80
|
+
/* ------------------------------------------------------------------ *
|
|
81
|
+
* 工具调用「内容」展示(带行号 / diff)。
|
|
82
|
+
*
|
|
83
|
+
* write_file 与 edit_file 的内容来自 LLM 在工具参数里一次性给全的文本,
|
|
84
|
+
* 所以「落盘前」就已经有完整内容:先渲染给用户看,再由工具真正写盘。
|
|
85
|
+
* 这里只做渲染(纯函数、可测),不读写文件。
|
|
86
|
+
* ------------------------------------------------------------------ */
|
|
87
|
+
/** 单行展示的最大字符数,超过则截断(应对压缩过的一行代码)。 */
|
|
88
|
+
const MAX_LINE_CHARS = 1000;
|
|
89
|
+
/** write_file 默认最多展示多少行内容。 */
|
|
90
|
+
const WRITE_MAX_LINES = 40;
|
|
91
|
+
/** edit_file diff 默认最多展示多少行。 */
|
|
92
|
+
const DIFF_MAX_LINES = 60;
|
|
93
|
+
/** 把文本拆成行;去掉「末尾换行」多出来的空行,保证行数语义正确。 */
|
|
94
|
+
function splitLines(s) {
|
|
95
|
+
if (s === '')
|
|
96
|
+
return [];
|
|
97
|
+
const lines = s.split('\n');
|
|
98
|
+
if (lines[lines.length - 1] === '')
|
|
99
|
+
lines.pop();
|
|
100
|
+
return lines;
|
|
101
|
+
}
|
|
102
|
+
function clampLine(line) {
|
|
103
|
+
return line.length > MAX_LINE_CHARS
|
|
104
|
+
? line.slice(0, MAX_LINE_CHARS) + ' …(行过长已截断)'
|
|
105
|
+
: line;
|
|
106
|
+
}
|
|
107
|
+
/** 右对齐行号到固定宽度,返回 muted 着色后的 gutter 文本。 */
|
|
108
|
+
function gutter(num, width) {
|
|
109
|
+
return style.muted(String(num).padStart(width, ' '));
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* 渲染 write_file 的待写入内容:每行带行号,超出 maxLines 截断并提示。
|
|
113
|
+
*/
|
|
114
|
+
export function formatWriteContent(content, opts) {
|
|
115
|
+
const max = opts?.maxLines ?? WRITE_MAX_LINES;
|
|
116
|
+
const lines = splitLines(content);
|
|
117
|
+
const width = String(Math.max(lines.length, 1)).length;
|
|
118
|
+
const shown = lines.slice(0, max);
|
|
119
|
+
const out = shown.map((line, i) => ` ${gutter(i + 1, width)} ${clampLine(line)}`);
|
|
120
|
+
if (lines.length > max) {
|
|
121
|
+
out.push(style.muted(` …(共 ${lines.length} 行,仅展示前 ${max} 行)`));
|
|
122
|
+
}
|
|
123
|
+
return out.join('\n') + (out.length ? '\n' : '');
|
|
124
|
+
}
|
|
125
|
+
/** LCS 逐行 diff;输入过大时退化为「整块删 / 整块增」避免卡顿。 */
|
|
126
|
+
function diffLines(a, b) {
|
|
127
|
+
const n = a.length;
|
|
128
|
+
const m = b.length;
|
|
129
|
+
if (n * m > 250_000) {
|
|
130
|
+
const ops = [];
|
|
131
|
+
for (const x of a)
|
|
132
|
+
ops.push({ type: 'del', line: x });
|
|
133
|
+
for (const y of b)
|
|
134
|
+
ops.push({ type: 'add', line: y });
|
|
135
|
+
return ops;
|
|
136
|
+
}
|
|
137
|
+
const dp = Array.from({ length: n + 1 }, () => new Array(m + 1).fill(0));
|
|
138
|
+
for (let i = n - 1; i >= 0; i--) {
|
|
139
|
+
for (let j = m - 1; j >= 0; j--) {
|
|
140
|
+
dp[i][j] =
|
|
141
|
+
a[i] === b[j]
|
|
142
|
+
? dp[i + 1][j + 1] + 1
|
|
143
|
+
: Math.max(dp[i + 1][j], dp[i][j + 1]);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
const ops = [];
|
|
147
|
+
let i = 0;
|
|
148
|
+
let j = 0;
|
|
149
|
+
while (i < n && j < m) {
|
|
150
|
+
if (a[i] === b[j]) {
|
|
151
|
+
ops.push({ type: 'eq', line: a[i] });
|
|
152
|
+
i++;
|
|
153
|
+
j++;
|
|
154
|
+
}
|
|
155
|
+
else if (dp[i + 1][j] >= dp[i][j + 1]) {
|
|
156
|
+
ops.push({ type: 'del', line: a[i] });
|
|
157
|
+
i++;
|
|
158
|
+
}
|
|
159
|
+
else {
|
|
160
|
+
ops.push({ type: 'add', line: b[j] });
|
|
161
|
+
j++;
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
while (i < n) {
|
|
165
|
+
ops.push({ type: 'del', line: a[i] });
|
|
166
|
+
i++;
|
|
167
|
+
}
|
|
168
|
+
while (j < m) {
|
|
169
|
+
ops.push({ type: 'add', line: b[j] });
|
|
170
|
+
j++;
|
|
171
|
+
}
|
|
172
|
+
return ops;
|
|
173
|
+
}
|
|
174
|
+
/**
|
|
175
|
+
* 渲染 edit_file 的改动 diff:删除行 `-`(红)、新增行 `+`(绿)、
|
|
176
|
+
* 上下文行(muted 行号)。带旧/新两侧行号,超出 maxLines 截断。
|
|
177
|
+
*/
|
|
178
|
+
export function formatEditDiff(oldText, newText, opts) {
|
|
179
|
+
const max = opts?.maxLines ?? DIFF_MAX_LINES;
|
|
180
|
+
const oldLines = splitLines(oldText);
|
|
181
|
+
const newLines = splitLines(newText);
|
|
182
|
+
const width = String(Math.max(oldLines.length, newLines.length, 1)).length;
|
|
183
|
+
const ops = diffLines(oldLines, newLines);
|
|
184
|
+
const out = [];
|
|
185
|
+
let oldNo = 1;
|
|
186
|
+
let newNo = 1;
|
|
187
|
+
let truncated = false;
|
|
188
|
+
for (const op of ops) {
|
|
189
|
+
if (out.length >= max) {
|
|
190
|
+
truncated = true;
|
|
191
|
+
break;
|
|
192
|
+
}
|
|
193
|
+
if (op.type === 'eq') {
|
|
194
|
+
out.push(` ${gutter(newNo, width)} ${clampLine(op.line)}`);
|
|
195
|
+
oldNo++;
|
|
196
|
+
newNo++;
|
|
197
|
+
}
|
|
198
|
+
else if (op.type === 'del') {
|
|
199
|
+
out.push(` ${style.error('-')} ${gutter(oldNo, width)} ${clampLine(op.line)}`);
|
|
200
|
+
oldNo++;
|
|
201
|
+
}
|
|
202
|
+
else {
|
|
203
|
+
out.push(` ${style.success('+')} ${gutter(newNo, width)} ${clampLine(op.line)}`);
|
|
204
|
+
newNo++;
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
if (truncated) {
|
|
208
|
+
out.push(style.muted(` …(diff 过长,仅展示前 ${max} 行)`));
|
|
209
|
+
}
|
|
210
|
+
return out.join('\n') + (out.length ? '\n' : '');
|
|
211
|
+
}
|
|
212
|
+
/**
|
|
213
|
+
* 工具调用前的「内容块」展示。仅 write_file / edit_file 有多行内容,
|
|
214
|
+
* 其余工具返回 null(调用方维持一行摘要即可)。
|
|
215
|
+
*/
|
|
216
|
+
export function formatToolCallBody(tc) {
|
|
217
|
+
const args = safeParse(tc.arguments);
|
|
218
|
+
if (tc.name === 'write_file') {
|
|
219
|
+
return formatWriteContent(String(args.content ?? ''));
|
|
220
|
+
}
|
|
221
|
+
if (tc.name === 'edit_file') {
|
|
222
|
+
return formatEditDiff(String(args.old_text ?? ''), String(args.new_text ?? ''));
|
|
223
|
+
}
|
|
224
|
+
return null;
|
|
225
|
+
}
|
|
226
|
+
/* ------------------------------------------------------------------ *
|
|
227
|
+
* 长内容折叠用的「全量行」渲染(不截断)。
|
|
228
|
+
*
|
|
229
|
+
* 与 formatWriteContent / formatEditDiff 渲染同一套行格式,但不做截断、不加
|
|
230
|
+
* 「仅展示前 N 行」提示——把完整行数组交给上层(run/fold)决定是否折叠。
|
|
231
|
+
* ------------------------------------------------------------------ */
|
|
232
|
+
/** write_file 内容的全量带行号行(不截断),供折叠展示使用。 */
|
|
233
|
+
export function writeContentLines(content) {
|
|
234
|
+
const lines = splitLines(content);
|
|
235
|
+
const width = String(Math.max(lines.length, 1)).length;
|
|
236
|
+
return lines.map((line, i) => ` ${gutter(i + 1, width)} ${clampLine(line)}`);
|
|
237
|
+
}
|
|
238
|
+
/** edit_file 的全量 diff 行(不截断),供折叠展示使用。 */
|
|
239
|
+
export function editDiffLines(oldText, newText) {
|
|
240
|
+
const oldLines = splitLines(oldText);
|
|
241
|
+
const newLines = splitLines(newText);
|
|
242
|
+
const width = String(Math.max(oldLines.length, newLines.length, 1)).length;
|
|
243
|
+
const ops = diffLines(oldLines, newLines);
|
|
244
|
+
const out = [];
|
|
245
|
+
let oldNo = 1;
|
|
246
|
+
let newNo = 1;
|
|
247
|
+
for (const op of ops) {
|
|
248
|
+
if (op.type === 'eq') {
|
|
249
|
+
out.push(` ${gutter(newNo, width)} ${clampLine(op.line)}`);
|
|
250
|
+
oldNo++;
|
|
251
|
+
newNo++;
|
|
252
|
+
}
|
|
253
|
+
else if (op.type === 'del') {
|
|
254
|
+
out.push(` ${style.error('-')} ${gutter(oldNo, width)} ${clampLine(op.line)}`);
|
|
255
|
+
oldNo++;
|
|
256
|
+
}
|
|
257
|
+
else {
|
|
258
|
+
out.push(` ${style.success('+')} ${gutter(newNo, width)} ${clampLine(op.line)}`);
|
|
259
|
+
newNo++;
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
return out;
|
|
263
|
+
}
|
|
264
|
+
/**
|
|
265
|
+
* 工具调用的全量内容行(不截断)。仅 write_file / edit_file 有内容,
|
|
266
|
+
* 其它工具返回 null。供 run 配合 renderWithFold 做折叠展示。
|
|
267
|
+
*/
|
|
268
|
+
export function toolCallLines(tc) {
|
|
269
|
+
const args = safeParse(tc.arguments);
|
|
270
|
+
if (tc.name === 'write_file') {
|
|
271
|
+
return writeContentLines(String(args.content ?? ''));
|
|
272
|
+
}
|
|
273
|
+
if (tc.name === 'edit_file') {
|
|
274
|
+
return editDiffLines(String(args.old_text ?? ''), String(args.new_text ?? ''));
|
|
275
|
+
}
|
|
276
|
+
return null;
|
|
277
|
+
}
|
|
278
|
+
//# sourceMappingURL=format.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"format.js","sourceRoot":"","sources":["../../../src/cli/run/format.ts"],"names":[],"mappings":"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"}
|
package/dist/cli/run/index.js
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
import { style } from '../style.js';
|
|
2
2
|
import { executeTool, getTool, registerMcpTools } from '../../tools/index.js';
|
|
3
|
+
import { ruleKeyFor } from './permissions.js';
|
|
4
|
+
import { formatToolCall, formatToolResult, toolCallLines, } from './format.js';
|
|
5
|
+
import { renderWithFold } from './fold.js';
|
|
6
|
+
import { WriteContentStreamer } from './stream-write.js';
|
|
3
7
|
import { estimatePromptTokens, estimateTokens, } from '../stats/index.js';
|
|
4
8
|
/** 单个用户回合内,最多允许模型连续调用工具的轮数,防止失控循环。 */
|
|
5
9
|
const MAX_TOOL_ROUNDS = 10;
|
|
@@ -19,10 +23,70 @@ function safeParse(argsJson) {
|
|
|
19
23
|
* 直到模型不再调用工具(给出最终回答)或达到轮数上限。
|
|
20
24
|
*/
|
|
21
25
|
export async function runAgentTurn(options) {
|
|
22
|
-
const { ai, history, confirm, stats, print = process.stdout.write.bind(process.stdout), maxRounds, requireToolsFirstRound, onToolCall, onToolResult, } = options;
|
|
26
|
+
const { ai, history, confirm, stats, print = process.stdout.write.bind(process.stdout), maxRounds, requireToolsFirstRound, onToolCall, onToolResult, permission, } = options;
|
|
23
27
|
const rounds = maxRounds ?? MAX_TOOL_ROUNDS;
|
|
24
28
|
for (let round = 0; round < rounds; round++) {
|
|
25
|
-
|
|
29
|
+
let reasoningStarted = false;
|
|
30
|
+
let reasoningEnded = false;
|
|
31
|
+
const onReasoningDelta = (text) => {
|
|
32
|
+
if (!reasoningStarted) {
|
|
33
|
+
print(style.muted('思考中…\n'));
|
|
34
|
+
reasoningStarted = true;
|
|
35
|
+
}
|
|
36
|
+
print(style.muted(text));
|
|
37
|
+
};
|
|
38
|
+
const onDelta = (text) => {
|
|
39
|
+
// 首个正文 delta 到达时,与前面的思考块之间补一行分隔
|
|
40
|
+
if (reasoningStarted && !reasoningEnded) {
|
|
41
|
+
print('\n');
|
|
42
|
+
reasoningEnded = true;
|
|
43
|
+
}
|
|
44
|
+
print(text);
|
|
45
|
+
};
|
|
46
|
+
// write_file 内容的流式渲染:边收参数边带行号打印,营造「正在写」观感。
|
|
47
|
+
// 每个工具 index 一个 streamer(增量解码)+ 一份行号状态。
|
|
48
|
+
const streamers = new Map();
|
|
49
|
+
const lineState = new Map();
|
|
50
|
+
let streamedAnyWrite = false;
|
|
51
|
+
const onToolArgumentDelta = (index, name, argsSoFar) => {
|
|
52
|
+
if (name !== 'write_file')
|
|
53
|
+
return;
|
|
54
|
+
let streamer = streamers.get(index);
|
|
55
|
+
if (!streamer) {
|
|
56
|
+
streamer = new WriteContentStreamer();
|
|
57
|
+
streamers.set(index, streamer);
|
|
58
|
+
}
|
|
59
|
+
let st = lineState.get(index);
|
|
60
|
+
if (!st) {
|
|
61
|
+
st = { headerPrinted: false, lineNo: 1, atLineStart: true };
|
|
62
|
+
lineState.set(index, st);
|
|
63
|
+
}
|
|
64
|
+
const r = streamer.feed(argsSoFar);
|
|
65
|
+
if (!r.started || r.delta.length === 0)
|
|
66
|
+
return;
|
|
67
|
+
if (!st.headerPrinted) {
|
|
68
|
+
print(style.tool(`\n⚙ write_file ${r.path ?? ''} (生成中…)\n`));
|
|
69
|
+
st.headerPrinted = true;
|
|
70
|
+
}
|
|
71
|
+
for (const ch of r.delta) {
|
|
72
|
+
if (st.atLineStart) {
|
|
73
|
+
print(style.muted(String(st.lineNo).padStart(2, ' ')) + ' ');
|
|
74
|
+
st.atLineStart = false;
|
|
75
|
+
}
|
|
76
|
+
print(ch);
|
|
77
|
+
if (ch === '\n') {
|
|
78
|
+
st.lineNo++;
|
|
79
|
+
st.atLineStart = true;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
// content 已闭合且末尾不是换行 → 补换行,让结果摘要另起一行
|
|
83
|
+
if (r.ended && !st.atLineStart) {
|
|
84
|
+
print('\n');
|
|
85
|
+
st.atLineStart = true;
|
|
86
|
+
}
|
|
87
|
+
streamedAnyWrite = true;
|
|
88
|
+
};
|
|
89
|
+
const turn = await ai.chat(history, onDelta, round === 0 && requireToolsFirstRound ? { requireTools: true } : undefined, onReasoningDelta, onToolArgumentDelta);
|
|
26
90
|
// 优先使用后端返回的真实 usage;不支持时降级为字符估算
|
|
27
91
|
if (turn.usage) {
|
|
28
92
|
stats.promptTokens += turn.usage.promptTokens;
|
|
@@ -57,30 +121,53 @@ export async function runAgentTurn(options) {
|
|
|
57
121
|
const tool = getTool(tc.name);
|
|
58
122
|
// 破坏性工具:执行前展示预览并请用户确认
|
|
59
123
|
if (tool?.needsConfirm) {
|
|
60
|
-
const
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
124
|
+
const args = safeParse(tc.arguments);
|
|
125
|
+
const preview = tc.name === 'write_file' && streamedAnyWrite
|
|
126
|
+
? `写入文件:${args.path ?? ''}(内容已在上方流式展示)`
|
|
127
|
+
: tool.preview
|
|
128
|
+
? tool.preview(args)
|
|
129
|
+
: `${tc.name}(${tc.arguments})`;
|
|
130
|
+
const ruleKey = permission ? ruleKeyFor(tc.name, args) : null;
|
|
131
|
+
// 已放行的同类:跳过确认直接执行(打印一行保持透明)
|
|
132
|
+
if (ruleKey && permission.isAllowed(ruleKey)) {
|
|
133
|
+
print(style.tool(`\n✓ 已自动允许(${ruleKey})\n`));
|
|
134
|
+
}
|
|
135
|
+
else {
|
|
136
|
+
const choice = await confirm(preview, ruleKey ? { ruleKey } : undefined);
|
|
137
|
+
if (choice === 'no') {
|
|
138
|
+
print('\n已取消。\n');
|
|
139
|
+
history.push({
|
|
140
|
+
role: 'tool',
|
|
141
|
+
tool_call_id: tc.id,
|
|
142
|
+
content: '用户拒绝执行此操作。请勿重试,可询问用户希望如何继续。',
|
|
143
|
+
});
|
|
144
|
+
continue; // 不执行,继续下一个工具调用
|
|
145
|
+
}
|
|
146
|
+
if (choice === 'always' && ruleKey) {
|
|
147
|
+
permission.allow(ruleKey);
|
|
148
|
+
}
|
|
72
149
|
}
|
|
73
150
|
}
|
|
74
151
|
if (onToolCall) {
|
|
75
152
|
onToolCall(tc);
|
|
76
153
|
}
|
|
77
154
|
else {
|
|
78
|
-
|
|
155
|
+
// write_file 内容已在流式中逐行打印过,不再重复输出摘要+完整块
|
|
156
|
+
const alreadyStreamed = tc.name === 'write_file' && streamedAnyWrite;
|
|
157
|
+
if (!alreadyStreamed) {
|
|
158
|
+
print(style.tool(`\n⚙ ${formatToolCall(tc)}\n`));
|
|
159
|
+
const lines = toolCallLines(tc);
|
|
160
|
+
if (lines)
|
|
161
|
+
print(renderWithFold(lines));
|
|
162
|
+
}
|
|
79
163
|
}
|
|
80
164
|
const result = await executeTool(tc.name, tc.arguments);
|
|
81
165
|
if (onToolResult) {
|
|
82
166
|
onToolResult(tc, result);
|
|
83
167
|
}
|
|
168
|
+
else {
|
|
169
|
+
print(style.muted(` → ${formatToolResult(tc, result)}\n`));
|
|
170
|
+
}
|
|
84
171
|
history.push({
|
|
85
172
|
role: 'tool',
|
|
86
173
|
tool_call_id: tc.id,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/cli/run/index.ts"],"names":[],"mappings":"AASA,OAAO,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AACpC,OAAO,EAAE,WAAW,EAAE,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAC9E,OAAO,EACH,oBAAoB,EACpB,cAAc,GAEjB,MAAM,mBAAmB,CAAC;AAE3B,sCAAsC;AACtC,MAAM,eAAe,GAAG,EAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/cli/run/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 会话内工具调用权限(「本次会话始终允许同类」)。
|
|
3
|
+
*
|
|
4
|
+
* 破坏性工具(write_file / edit_file / bash)每次执行前都要确认,高频使用时很烦——
|
|
5
|
+
* 比如反复跑 `npm test`、反复改 `src/` 下的文件。这里让用户在确认时选「本次会话
|
|
6
|
+
* 始终允许」,把规则记进内存 allow-list,之后同类调用直接放行、不再问。
|
|
7
|
+
*
|
|
8
|
+
* 规则粒度:
|
|
9
|
+
* - bash → 按「命令首词」(`bash:npm`、`bash:git`)。
|
|
10
|
+
* - write_file / edit_file → 按「路径首段目录」(`write_file:src`、`edit_file:<root>`)。
|
|
11
|
+
* allow-list 只在内存里,随会话结束清空(不持久化)。
|
|
12
|
+
*/
|
|
13
|
+
/** 取 bash 命令的首词(第一个空白分隔的 token),用于同类匹配。 */
|
|
14
|
+
function bashHead(command) {
|
|
15
|
+
return command.trim().split(/\s+/)[0] ?? '';
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* 把文件路径归一成「放行桶」:
|
|
19
|
+
* - 相对路径取首段目录:`src/tools/foo.ts` → `src`;`./src/foo.ts`(去 ./)→ `src`。
|
|
20
|
+
* - 根级文件(无目录):`README.md` → `<root>`。
|
|
21
|
+
* - 绝对路径:`/Users/x/foo.ts` → `<abs>`(不与相对路径混,单独成桶,更保守)。
|
|
22
|
+
* 空字符串 → ''(调用方据此返回 null)。
|
|
23
|
+
*/
|
|
24
|
+
function pathBucket(p) {
|
|
25
|
+
let s = String(p ?? '').trim();
|
|
26
|
+
if (!s)
|
|
27
|
+
return '';
|
|
28
|
+
while (s.startsWith('./'))
|
|
29
|
+
s = s.slice(2);
|
|
30
|
+
if (s.startsWith('/'))
|
|
31
|
+
return '<abs>';
|
|
32
|
+
const idx = s.indexOf('/');
|
|
33
|
+
return idx === -1 ? '<root>' : s.slice(0, idx);
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* 为一次工具调用生成「同类规则」key。返回 null 表示该工具不支持「始终允许」。
|
|
37
|
+
* - bash → `bash:<首词>`,例如 `npm test` → `bash:npm`。
|
|
38
|
+
* - write_file / edit_file → `<工具>:<路径桶>`,例如写 `src/a.ts` → `write_file:src`。
|
|
39
|
+
* - 其它工具(含 MCP)→ null(每次仍需确认)。
|
|
40
|
+
*/
|
|
41
|
+
export function ruleKeyFor(toolName, args) {
|
|
42
|
+
if (toolName === 'bash') {
|
|
43
|
+
const head = bashHead(String(args?.command ?? ''));
|
|
44
|
+
return head ? `bash:${head}` : null;
|
|
45
|
+
}
|
|
46
|
+
if (toolName === 'write_file' || toolName === 'edit_file') {
|
|
47
|
+
const bucket = pathBucket(String(args?.path ?? ''));
|
|
48
|
+
return bucket ? `${toolName}:${bucket}` : null;
|
|
49
|
+
}
|
|
50
|
+
return null;
|
|
51
|
+
}
|
|
52
|
+
/** 路径桶的人类可读描述(用于确认选项标签)。 */
|
|
53
|
+
function bucketLabel(bucket) {
|
|
54
|
+
if (bucket === '<root>')
|
|
55
|
+
return '根目录文件';
|
|
56
|
+
if (bucket === '<abs>')
|
|
57
|
+
return '绝对路径文件';
|
|
58
|
+
return `'${bucket}/' 目录`;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* 由规则 key 生成「始终允许」选项的展示标签。
|
|
62
|
+
* - `bash:npm` → `始终允许 'npm'`
|
|
63
|
+
* - `write_file:src` → `始终允许写 'src/' 目录`
|
|
64
|
+
* - `edit_file:<root>` → `始终允许编辑根目录文件`
|
|
65
|
+
*/
|
|
66
|
+
export function alwaysLabelFor(ruleKey) {
|
|
67
|
+
if (ruleKey.startsWith('bash:')) {
|
|
68
|
+
return `始终允许 '${ruleKey.slice('bash:'.length)}'`;
|
|
69
|
+
}
|
|
70
|
+
if (ruleKey.startsWith('write_file:')) {
|
|
71
|
+
return `始终允许写 ${bucketLabel(ruleKey.slice('write_file:'.length))}`;
|
|
72
|
+
}
|
|
73
|
+
if (ruleKey.startsWith('edit_file:')) {
|
|
74
|
+
return `始终允许编辑 ${bucketLabel(ruleKey.slice('edit_file:'.length))}`;
|
|
75
|
+
}
|
|
76
|
+
return `始终允许 ${ruleKey}`;
|
|
77
|
+
}
|
|
78
|
+
/** 会话级 allow-list。 */
|
|
79
|
+
export class Permission {
|
|
80
|
+
allowed = new Set();
|
|
81
|
+
/** key 是否已放行。 */
|
|
82
|
+
isAllowed(key) {
|
|
83
|
+
return this.allowed.has(key);
|
|
84
|
+
}
|
|
85
|
+
/** 放行 key(本次会话内)。 */
|
|
86
|
+
allow(key) {
|
|
87
|
+
this.allowed.add(key);
|
|
88
|
+
}
|
|
89
|
+
/** 清空全部放行(例如 /clear 或新会话)。 */
|
|
90
|
+
clear() {
|
|
91
|
+
this.allowed.clear();
|
|
92
|
+
}
|
|
93
|
+
/** 当前放行规则数(调试用)。 */
|
|
94
|
+
size() {
|
|
95
|
+
return this.allowed.size;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
//# sourceMappingURL=permissions.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"permissions.js","sourceRoot":"","sources":["../../../src/cli/run/permissions.ts"],"names":[],"mappings":"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"}
|