@gird/ccli 2.13.2 → 2.15.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 +36 -2
- package/dist/agent/ai.js +63 -2
- package/dist/agent/ai.js.map +1 -1
- package/dist/cli/args/index.js +4 -0
- package/dist/cli/args/index.js.map +1 -1
- package/dist/cli/file-reference.js +23 -1
- package/dist/cli/file-reference.js.map +1 -1
- package/dist/cli/repl/index.js +49 -8
- package/dist/cli/repl/index.js.map +1 -1
- package/dist/cli/run/format.js +8 -2
- package/dist/cli/run/format.js.map +1 -1
- package/dist/cli/run/hooks.js +134 -0
- package/dist/cli/run/hooks.js.map +1 -0
- package/dist/cli/run/index.js +78 -6
- package/dist/cli/run/index.js.map +1 -1
- package/dist/cli/run/permissions.js +72 -10
- package/dist/cli/run/permissions.js.map +1 -1
- package/dist/cli/run/task.js +41 -6
- package/dist/cli/run/task.js.map +1 -1
- package/dist/cli/slash/mcp/mcp.js.map +1 -1
- package/dist/cli/slash/system/agent.js +2 -1
- package/dist/cli/slash/system/agent.js.map +1 -1
- package/dist/cli/slash/system/goal.js +2 -1
- package/dist/cli/slash/system/goal.js.map +1 -1
- package/dist/cli/slash/system/help.js +2 -0
- package/dist/cli/slash/system/help.js.map +1 -1
- package/dist/config/config.js +78 -19
- package/dist/config/config.js.map +1 -1
- package/dist/config/skills.js +253 -0
- package/dist/config/skills.js.map +1 -0
- package/dist/index.js +10 -1
- package/dist/index.js.map +1 -1
- package/dist/tools/bash-background.js +33 -1
- package/dist/tools/bash-background.js.map +1 -1
- package/dist/tools/bash.js +43 -3
- package/dist/tools/bash.js.map +1 -1
- package/dist/tools/edit-file.js +28 -2
- package/dist/tools/edit-file.js.map +1 -1
- package/dist/tools/glob.js +111 -0
- package/dist/tools/glob.js.map +1 -0
- package/dist/tools/index.js +25 -6
- package/dist/tools/index.js.map +1 -1
- package/dist/tools/shared.js.map +1 -1
- package/dist/tools/skill-tool.js +69 -0
- package/dist/tools/skill-tool.js.map +1 -0
- package/package.json +2 -2
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 生命周期钩子(hooks)运行器。
|
|
3
|
+
*
|
|
4
|
+
* 一期支持两个事件:
|
|
5
|
+
* - PreToolUse:工具执行前触发,可拦截(退出码 2)
|
|
6
|
+
* - PostToolUse:工具成功后触发,只观察
|
|
7
|
+
* - PostToolUseFailure:工具失败后触发,只观察
|
|
8
|
+
*
|
|
9
|
+
* 协议(对齐 Claude Code):
|
|
10
|
+
* - 通过 stdin 给 hook 进程喂 JSON:
|
|
11
|
+
* { hook_event_name, cwd, tool_name, tool_input, tool_response? }
|
|
12
|
+
* - 退出码 0 = 放行(stdout 打印给用户);2 = 拦截(stderr 作为原因喂回模型);
|
|
13
|
+
* 其它非零 / 超时 / 启动失败 = fail open:打印警告但放行。
|
|
14
|
+
* - 同一事件配了多个 hook 时按声明顺序执行;拦截后短路,后续不再执行。
|
|
15
|
+
*
|
|
16
|
+
* 安全底线:每次执行都打印一行透明日志(命令可见),让 hook 行为对用户可观测。
|
|
17
|
+
*/
|
|
18
|
+
import { spawn } from 'node:child_process';
|
|
19
|
+
import { style } from '../style.js';
|
|
20
|
+
const DEFAULT_TIMEOUT_SEC = 10;
|
|
21
|
+
/**
|
|
22
|
+
* matcher 匹配规则:
|
|
23
|
+
* - 省略或 `*`:匹配全部工具
|
|
24
|
+
* - 精确名:`bash` 只匹配 bash
|
|
25
|
+
* - `a|b`:匹配其中任意一个
|
|
26
|
+
* - 末尾带 `*`:前缀匹配,如 `mcp__*` 匹配所有 MCP 工具
|
|
27
|
+
*/
|
|
28
|
+
export function matchHook(matcher, toolName) {
|
|
29
|
+
if (!matcher || matcher === '*')
|
|
30
|
+
return true;
|
|
31
|
+
return matcher.split('|').some((part) => {
|
|
32
|
+
const p = part.trim();
|
|
33
|
+
if (!p)
|
|
34
|
+
return false;
|
|
35
|
+
if (p.endsWith('*'))
|
|
36
|
+
return toolName.startsWith(p.slice(0, -1));
|
|
37
|
+
return p === toolName;
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
/** 执行单个 hook:spawn shell,喂 stdin JSON,按退出码判定结果。 */
|
|
41
|
+
function runOneHook(def, payload) {
|
|
42
|
+
return new Promise((resolve) => {
|
|
43
|
+
const timeoutSec = def.timeout ?? DEFAULT_TIMEOUT_SEC;
|
|
44
|
+
const shell = process.env.SHELL || '/bin/bash';
|
|
45
|
+
let child;
|
|
46
|
+
try {
|
|
47
|
+
child = spawn(shell, ['-c', def.command], {
|
|
48
|
+
cwd: payload.cwd,
|
|
49
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
catch (e) {
|
|
53
|
+
resolve({ action: 'error', message: `启动失败:${e?.message ?? e}` });
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
let stdout = '';
|
|
57
|
+
let stderr = '';
|
|
58
|
+
let settled = false;
|
|
59
|
+
const finish = (outcome) => {
|
|
60
|
+
if (settled)
|
|
61
|
+
return;
|
|
62
|
+
settled = true;
|
|
63
|
+
clearTimeout(timer);
|
|
64
|
+
resolve(outcome);
|
|
65
|
+
};
|
|
66
|
+
const timer = setTimeout(() => {
|
|
67
|
+
child.kill('SIGKILL');
|
|
68
|
+
finish({ action: 'error', message: `超时(${timeoutSec}s)` });
|
|
69
|
+
}, timeoutSec * 1000);
|
|
70
|
+
child.stdout.on('data', (d) => {
|
|
71
|
+
stdout += d;
|
|
72
|
+
});
|
|
73
|
+
child.stderr.on('data', (d) => {
|
|
74
|
+
stderr += d;
|
|
75
|
+
});
|
|
76
|
+
child.on('error', (e) => {
|
|
77
|
+
finish({ action: 'error', message: `启动失败:${e.message}` });
|
|
78
|
+
});
|
|
79
|
+
child.on('close', (code) => {
|
|
80
|
+
if (code === 0) {
|
|
81
|
+
finish({ action: 'allow', message: stdout.trim() || undefined });
|
|
82
|
+
}
|
|
83
|
+
else if (code === 2) {
|
|
84
|
+
finish({
|
|
85
|
+
action: 'block',
|
|
86
|
+
message: stderr.trim() || '(hook 未给出原因)',
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
else {
|
|
90
|
+
const detail = stderr.trim();
|
|
91
|
+
finish({
|
|
92
|
+
action: 'error',
|
|
93
|
+
message: `退出码 ${code}${detail ? `:${detail}` : ''}`,
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
});
|
|
97
|
+
// 喂 stdin 载荷;进程若提前退出会触发 EPIPE,忽略即可
|
|
98
|
+
child.stdin.on('error', () => { });
|
|
99
|
+
child.stdin.end(JSON.stringify(payload));
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* 执行某个事件下所有匹配的 hook。
|
|
104
|
+
* @param defs 配置中的全部 hook(内部按 event + matcher 过滤)
|
|
105
|
+
* @param event 触发事件
|
|
106
|
+
* @param payload 事件载荷(不含 hook_event_name)
|
|
107
|
+
* @param print 输出回调(子代理场景传缩进 print)
|
|
108
|
+
*/
|
|
109
|
+
export async function runHooks(defs, event, payload, print = (c) => process.stdout.write(c)) {
|
|
110
|
+
if (!defs || defs.length === 0)
|
|
111
|
+
return { blocked: false };
|
|
112
|
+
const matched = defs.filter((d) => d.event === event && matchHook(d.matcher, payload.tool_name));
|
|
113
|
+
for (const def of matched) {
|
|
114
|
+
print(style.muted(`\n⏎ [hook] ${event} ← ${def.command}\n`));
|
|
115
|
+
const outcome = await runOneHook(def, {
|
|
116
|
+
hook_event_name: event,
|
|
117
|
+
...payload,
|
|
118
|
+
});
|
|
119
|
+
if (outcome.action === 'allow') {
|
|
120
|
+
if (outcome.message)
|
|
121
|
+
print(outcome.message + '\n');
|
|
122
|
+
continue;
|
|
123
|
+
}
|
|
124
|
+
if (outcome.action === 'error') {
|
|
125
|
+
print(style.warn(`[hook] 执行失败(已放行):${outcome.message}\n`));
|
|
126
|
+
continue;
|
|
127
|
+
}
|
|
128
|
+
// 拦截:告知用户并短路,原因由调用方喂回模型
|
|
129
|
+
print(style.warn(`[hook] 已拦截 ${payload.tool_name}:${outcome.message}\n`));
|
|
130
|
+
return { blocked: true, reason: outcome.message };
|
|
131
|
+
}
|
|
132
|
+
return { blocked: false };
|
|
133
|
+
}
|
|
134
|
+
//# sourceMappingURL=hooks.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hooks.js","sourceRoot":"","sources":["../../../src/cli/run/hooks.ts"],"names":[],"mappings":"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"}
|
package/dist/cli/run/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { style } from '../style.js';
|
|
2
|
-
import { executeTool, getTool, registerMcpTools, registerTool, } from '../../tools/index.js';
|
|
2
|
+
import { executeTool, getTool, registerMcpTools, registerTool, textToolResult, } from '../../tools/index.js';
|
|
3
3
|
import { createTaskTool } from './task.js';
|
|
4
4
|
import { renderTodoPanel } from '../../tools/todo.js';
|
|
5
5
|
import { ruleKeyFor } from './permissions.js';
|
|
@@ -7,6 +7,8 @@ import { formatToolCall, formatToolResult, toolCallLines, } from './format.js';
|
|
|
7
7
|
import { LineFoldPrinter, renderWithFold } from './fold.js';
|
|
8
8
|
import { WriteFileStreamPrinter } from './stream-write.js';
|
|
9
9
|
import { estimatePromptTokens, estimateTokens, } from '../stats/index.js';
|
|
10
|
+
import { DEFAULT_SYSTEM_PROMPT } from '../../config/config.js';
|
|
11
|
+
import { runHooks } from './hooks.js';
|
|
10
12
|
/** 单个用户回合内的默认最大工具调用轮数(未配置 maxStepsPerTurn 时)。
|
|
11
13
|
* 用户可在 config 设 maxStepsPerTurn 调整;0 或负数表示不限。 */
|
|
12
14
|
const DEFAULT_MAX_STEPS = 50;
|
|
@@ -21,12 +23,50 @@ function safeParse(argsJson) {
|
|
|
21
23
|
return {};
|
|
22
24
|
}
|
|
23
25
|
}
|
|
26
|
+
const TOOL_ERROR_STATUS = '<system>ERROR: Tool execution failed.</system>';
|
|
27
|
+
const REPEAT_TOOL_REMINDER = '\n\n<system-reminder>\n' +
|
|
28
|
+
'你正在连续重复同一个工具调用和完全相同的参数。请仔细阅读上一条工具结果;如果任务尚未完成,请换一种方式、调整参数,或先读取/搜索最新信息,而不是原样重试。\n' +
|
|
29
|
+
'</system-reminder>';
|
|
30
|
+
const REPEAT_TOOL_STOP_REMINDER = '\n\n<system-reminder>\n' +
|
|
31
|
+
'你已经多次重复同一个工具调用且没有取得进展。下一步不要继续调用这个完全相同的工具参数;请总结当前卡点,或改用不同工具/参数继续。\n' +
|
|
32
|
+
'</system-reminder>';
|
|
33
|
+
function canonicalToolArgs(argsJson) {
|
|
34
|
+
try {
|
|
35
|
+
return JSON.stringify(sortJson(JSON.parse(argsJson || '{}')));
|
|
36
|
+
}
|
|
37
|
+
catch {
|
|
38
|
+
return argsJson;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
function sortJson(value) {
|
|
42
|
+
if (Array.isArray(value))
|
|
43
|
+
return value.map(sortJson);
|
|
44
|
+
if (value && typeof value === 'object') {
|
|
45
|
+
const out = {};
|
|
46
|
+
for (const key of Object.keys(value).sort()) {
|
|
47
|
+
out[key] = sortJson(value[key]);
|
|
48
|
+
}
|
|
49
|
+
return out;
|
|
50
|
+
}
|
|
51
|
+
return value;
|
|
52
|
+
}
|
|
53
|
+
function repeatedToolReminder(repeatCount) {
|
|
54
|
+
if (repeatCount >= 5)
|
|
55
|
+
return REPEAT_TOOL_STOP_REMINDER;
|
|
56
|
+
if (repeatCount >= 3)
|
|
57
|
+
return REPEAT_TOOL_REMINDER;
|
|
58
|
+
return '';
|
|
59
|
+
}
|
|
60
|
+
function toolResultForModel(result, repeatCount) {
|
|
61
|
+
const prefix = result.isError ? `${TOOL_ERROR_STATUS}\n` : '';
|
|
62
|
+
return `${prefix}${result.output}${repeatedToolReminder(repeatCount)}`;
|
|
63
|
+
}
|
|
24
64
|
/**
|
|
25
65
|
* 驱动一个用户回合:请求模型 → 若它要调用工具则(必要时确认后)执行并回传 → 再请求 …
|
|
26
66
|
* 直到模型不再调用工具(给出最终回答)或达到轮数上限。
|
|
27
67
|
*/
|
|
28
68
|
export async function runAgentTurn(options) {
|
|
29
|
-
const { ai, history, confirm, stats, print = process.stdout.write.bind(process.stdout), maxRounds, requireToolsFirstRound, onToolCall, onToolResult, permission, configMaxSteps, todoPanel = true, endPanel = true, } = options;
|
|
69
|
+
const { ai, history, confirm, stats, print = process.stdout.write.bind(process.stdout), maxRounds, requireToolsFirstRound, onToolCall, onToolResult, permission, configMaxSteps, todoPanel = true, endPanel = true, hooks, } = options;
|
|
30
70
|
// 上限优先级:显式 maxRounds(/agent、/goal)> configMaxSteps(config 解析)> 默认 50。
|
|
31
71
|
// limit <= 0 表示不限(跳过检查),对齐 config maxStepsPerTurn=0 语义。
|
|
32
72
|
const limit = maxRounds ?? configMaxSteps ?? DEFAULT_MAX_STEPS;
|
|
@@ -40,9 +80,12 @@ export async function runAgentTurn(options) {
|
|
|
40
80
|
cwd: process.cwd(),
|
|
41
81
|
maxSteps: configMaxSteps,
|
|
42
82
|
todoPanel,
|
|
83
|
+
hooks,
|
|
43
84
|
};
|
|
44
85
|
// 注册 task 子代理工具(每回合注册一次,registerTool 同名替换幂等)。
|
|
45
86
|
registerTool(createTaskTool(toolCtx));
|
|
87
|
+
let lastToolKey = null;
|
|
88
|
+
let repeatCount = 0;
|
|
46
89
|
for (let round = 0; limit <= 0 || round < limit; round++) {
|
|
47
90
|
let reasoningStarted = false;
|
|
48
91
|
let reasoningEnded = false;
|
|
@@ -102,9 +145,22 @@ export async function runAgentTurn(options) {
|
|
|
102
145
|
// 逐个执行工具,结果以 role:'tool' 消息回传
|
|
103
146
|
for (const tc of turn.toolCalls) {
|
|
104
147
|
const tool = getTool(tc.name);
|
|
148
|
+
const args = safeParse(tc.arguments);
|
|
149
|
+
const toolKey = `${tc.name} ${canonicalToolArgs(tc.arguments)}`;
|
|
150
|
+
// PreToolUse hook:在「始终允许 / 用户确认」之前触发,对所有工具生效;
|
|
151
|
+
// 被拦截则短路——不弹确认、不执行,原因喂回模型。
|
|
152
|
+
const pre = await runHooks(hooks, 'PreToolUse', { cwd: toolCtx.cwd, tool_name: tc.name, tool_input: args }, print);
|
|
153
|
+
if (pre.blocked) {
|
|
154
|
+
const blocked = textToolResult(`操作被 PreToolUse hook 拦截:${pre.reason ?? ''}。请勿重试,可询问用户希望如何继续。`, true);
|
|
155
|
+
history.push({
|
|
156
|
+
role: 'tool',
|
|
157
|
+
tool_call_id: tc.id,
|
|
158
|
+
content: toolResultForModel(blocked, 1),
|
|
159
|
+
});
|
|
160
|
+
continue;
|
|
161
|
+
}
|
|
105
162
|
// 破坏性工具:执行前展示预览并请用户确认
|
|
106
163
|
if (tool?.needsConfirm) {
|
|
107
|
-
const args = safeParse(tc.arguments);
|
|
108
164
|
const preview = tc.name === 'write_file' && writePrinter.anyStreamed
|
|
109
165
|
? `写入文件:${args.path ?? ''}(内容已在上方流式展示)`
|
|
110
166
|
: tool.preview
|
|
@@ -119,10 +175,11 @@ export async function runAgentTurn(options) {
|
|
|
119
175
|
const choice = await confirm(preview, ruleKey ? { ruleKey } : undefined);
|
|
120
176
|
if (choice === 'no') {
|
|
121
177
|
print('\n已取消。\n');
|
|
178
|
+
const rejected = textToolResult('用户拒绝执行此操作。请勿重试,可询问用户希望如何继续。', true);
|
|
122
179
|
history.push({
|
|
123
180
|
role: 'tool',
|
|
124
181
|
tool_call_id: tc.id,
|
|
125
|
-
content:
|
|
182
|
+
content: toolResultForModel(rejected, 1),
|
|
126
183
|
});
|
|
127
184
|
continue; // 不执行,继续下一个工具调用
|
|
128
185
|
}
|
|
@@ -151,16 +208,30 @@ export async function runAgentTurn(options) {
|
|
|
151
208
|
: toolCtx;
|
|
152
209
|
const result = await executeTool(tc.name, tc.arguments, execCtx);
|
|
153
210
|
bashFold?.finish();
|
|
211
|
+
if (toolKey === lastToolKey) {
|
|
212
|
+
repeatCount++;
|
|
213
|
+
}
|
|
214
|
+
else {
|
|
215
|
+
lastToolKey = toolKey;
|
|
216
|
+
repeatCount = 1;
|
|
217
|
+
}
|
|
154
218
|
if (onToolResult) {
|
|
155
219
|
onToolResult(tc, result);
|
|
156
220
|
}
|
|
157
221
|
else {
|
|
158
222
|
print(style.muted(` → ${formatToolResult(tc, result)}\n`));
|
|
159
223
|
}
|
|
224
|
+
// PostToolUse / PostToolUseFailure hook:只观察(stdout 仅打印给用户,不喂回模型)
|
|
225
|
+
await runHooks(hooks, result.isError ? 'PostToolUseFailure' : 'PostToolUse', {
|
|
226
|
+
cwd: toolCtx.cwd,
|
|
227
|
+
tool_name: tc.name,
|
|
228
|
+
tool_input: args,
|
|
229
|
+
tool_response: result.output,
|
|
230
|
+
}, print);
|
|
160
231
|
history.push({
|
|
161
232
|
role: 'tool',
|
|
162
233
|
tool_call_id: tc.id,
|
|
163
|
-
content: result,
|
|
234
|
+
content: toolResultForModel(result, repeatCount),
|
|
164
235
|
});
|
|
165
236
|
}
|
|
166
237
|
// 继续下一轮,让模型基于工具结果接着回答
|
|
@@ -179,7 +250,7 @@ export async function runAgentTurn(options) {
|
|
|
179
250
|
* 以 systemPrompt 开场,把 prompt 作为 user 消息发送,执行一轮后返回。
|
|
180
251
|
*/
|
|
181
252
|
export async function runOnce(options) {
|
|
182
|
-
const { ai, prompt, confirm, print = process.stdout.write.bind(process.stdout), systemPrompt =
|
|
253
|
+
const { ai, prompt, confirm, print = process.stdout.write.bind(process.stdout), systemPrompt = DEFAULT_SYSTEM_PROMPT, mcpManager, configMaxSteps, hooks, } = options;
|
|
183
254
|
if (mcpManager) {
|
|
184
255
|
await registerMcpTools(mcpManager);
|
|
185
256
|
}
|
|
@@ -197,6 +268,7 @@ export async function runOnce(options) {
|
|
|
197
268
|
stats: { promptTokens: 0, completionTokens: 0, totalTokens: 0 },
|
|
198
269
|
print: capturePrint,
|
|
199
270
|
configMaxSteps,
|
|
271
|
+
hooks,
|
|
200
272
|
});
|
|
201
273
|
return output;
|
|
202
274
|
}
|
|
@@ -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,EACH,WAAW,EACX,OAAO,EACP,gBAAgB,EAChB,YAAY,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/cli/run/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -6,13 +6,70 @@
|
|
|
6
6
|
* 始终允许」,把规则记进内存 allow-list,之后同类调用直接放行、不再问。
|
|
7
7
|
*
|
|
8
8
|
* 规则粒度:
|
|
9
|
-
* - bash →
|
|
9
|
+
* - bash → 按「命令首词 + 子命令」(`bash:npm:test`、`bash:git:status`);
|
|
10
|
+
* 没有子命令时退化为 `bash:ls`。因此放行 `npm test` 不会顺带放行 `npm publish`。
|
|
10
11
|
* - write_file / edit_file → 按「路径首段目录」(`write_file:src`、`edit_file:<root>`)。
|
|
12
|
+
* - 高风险命令(rm / sudo / dd / mkfs / git push / npm publish / 管道喂 shell 等)
|
|
13
|
+
* 不提供「始终允许」,每次都需确认(ruleKeyFor 返回 null)。
|
|
11
14
|
* allow-list 只在内存里,随会话结束清空(不持久化)。
|
|
12
15
|
*/
|
|
13
|
-
/**
|
|
14
|
-
function
|
|
15
|
-
|
|
16
|
+
/** 取首词的 basename(`/bin/rm` → `rm`),用于归类与高风险判定。 */
|
|
17
|
+
function headName(head) {
|
|
18
|
+
const i = head.lastIndexOf('/');
|
|
19
|
+
return i === -1 ? head : head.slice(i + 1);
|
|
20
|
+
}
|
|
21
|
+
/** 这些首词破坏力大且不可逆,不提供「始终允许」。 */
|
|
22
|
+
const DANGEROUS_HEADS = new Set(['rm', 'sudo', 'dd', 'mkfs']);
|
|
23
|
+
/** 包管理器 publish 子命令(会把包发到 registry,不可逆)。 */
|
|
24
|
+
const PUBLISH_HEADS = new Set(['npm', 'yarn', 'pnpm']);
|
|
25
|
+
/**
|
|
26
|
+
* 高风险命令判定:命中则不生成放行规则,每次都需确认。
|
|
27
|
+
* 覆盖:管道喂 shell(curl ... | sh)、危险首词(rm/sudo/dd/mkfs)、
|
|
28
|
+
* git push、npm/yarn/pnpm publish。引号内容先剔除,避免 commit message
|
|
29
|
+
* 里出现 push 之类的词被误判。按 | / && / || / ; 切段,复合命令里任何一段
|
|
30
|
+
* 命中都视为高风险。
|
|
31
|
+
*/
|
|
32
|
+
export function isHighRiskCommand(command) {
|
|
33
|
+
// 下载内容直接管道喂 shell:curl -sL url | sh / wget -O- url | sudo bash
|
|
34
|
+
if (/\|\s*(?:sudo\s+)?(?:bash|sh|zsh)\b/.test(command))
|
|
35
|
+
return true;
|
|
36
|
+
const stripped = command.replace(/"[^"]*"|'[^']*'/g, ' ');
|
|
37
|
+
for (const seg of stripped.split(/\|\||&&|[|;]/)) {
|
|
38
|
+
const tokens = seg.trim().split(/\s+/).filter(Boolean);
|
|
39
|
+
if (tokens.length === 0)
|
|
40
|
+
continue;
|
|
41
|
+
const head = headName(tokens[0]);
|
|
42
|
+
if (DANGEROUS_HEADS.has(head))
|
|
43
|
+
return true;
|
|
44
|
+
const rest = tokens.slice(1);
|
|
45
|
+
// 子命令紧跟首词;或首词后是全局 flag,子命令在其后(git -C dir push)
|
|
46
|
+
const hasSub = (sub) => rest[0] === sub ||
|
|
47
|
+
(rest[0]?.startsWith('-') === true && rest.includes(sub));
|
|
48
|
+
if (head === 'git' && hasSub('push'))
|
|
49
|
+
return true;
|
|
50
|
+
if (PUBLISH_HEADS.has(head) && hasSub('publish'))
|
|
51
|
+
return true;
|
|
52
|
+
}
|
|
53
|
+
return false;
|
|
54
|
+
}
|
|
55
|
+
/** shell 连接符,不算子命令(`ls | grep x` → `bash:ls`)。 */
|
|
56
|
+
const SHELL_OPERATORS = new Set(['|', '||', '&&', ';']);
|
|
57
|
+
/**
|
|
58
|
+
* bash 的放行规则 key:`bash:<首词>` 或 `bash:<首词>:<子命令>`。
|
|
59
|
+
* 子命令 = 第二个 token(以 '-' 开头的 flag、shell 连接符都不算,
|
|
60
|
+
* 故 `ls -la` / `ls | grep x` → `bash:ls`)。
|
|
61
|
+
* 高风险命令返回 null(不支持「始终允许」)。
|
|
62
|
+
*/
|
|
63
|
+
function bashRuleKey(command) {
|
|
64
|
+
const tokens = command.trim().split(/\s+/).filter(Boolean);
|
|
65
|
+
if (tokens.length === 0)
|
|
66
|
+
return null;
|
|
67
|
+
if (isHighRiskCommand(command))
|
|
68
|
+
return null;
|
|
69
|
+
const head = headName(tokens[0]);
|
|
70
|
+
const t2 = tokens[1] ?? '';
|
|
71
|
+
const sub = t2 && !t2.startsWith('-') && !SHELL_OPERATORS.has(t2) ? t2 : '';
|
|
72
|
+
return sub ? `bash:${head}:${sub}` : `bash:${head}`;
|
|
16
73
|
}
|
|
17
74
|
/**
|
|
18
75
|
* 把文件路径归一成「放行桶」:
|
|
@@ -33,15 +90,15 @@ function pathBucket(p) {
|
|
|
33
90
|
return idx === -1 ? '<root>' : s.slice(0, idx);
|
|
34
91
|
}
|
|
35
92
|
/**
|
|
36
|
-
* 为一次工具调用生成「同类规则」key。返回 null
|
|
37
|
-
* - bash → `bash
|
|
93
|
+
* 为一次工具调用生成「同类规则」key。返回 null 表示该调用不支持「始终允许」。
|
|
94
|
+
* - bash → `bash:<首词>[:<子命令>]`,例如 `npm test` → `bash:npm:test`;
|
|
95
|
+
* 高风险命令(rm / git push / npm publish 等)→ null。
|
|
38
96
|
* - write_file / edit_file → `<工具>:<路径桶>`,例如写 `src/a.ts` → `write_file:src`。
|
|
39
97
|
* - 其它工具(含 MCP)→ null(每次仍需确认)。
|
|
40
98
|
*/
|
|
41
99
|
export function ruleKeyFor(toolName, args) {
|
|
42
100
|
if (toolName === 'bash') {
|
|
43
|
-
|
|
44
|
-
return head ? `bash:${head}` : null;
|
|
101
|
+
return bashRuleKey(String(args?.command ?? ''));
|
|
45
102
|
}
|
|
46
103
|
if (toolName === 'write_file' || toolName === 'edit_file') {
|
|
47
104
|
const bucket = pathBucket(String(args?.path ?? ''));
|
|
@@ -59,13 +116,18 @@ function bucketLabel(bucket) {
|
|
|
59
116
|
}
|
|
60
117
|
/**
|
|
61
118
|
* 由规则 key 生成「始终允许」选项的展示标签。
|
|
62
|
-
* - `bash:
|
|
119
|
+
* - `bash:ls` → `始终允许 'ls'`
|
|
120
|
+
* - `bash:npm:test` → `始终允许以 'npm test' 开头的命令`
|
|
63
121
|
* - `write_file:src` → `始终允许写 'src/' 目录`
|
|
64
122
|
* - `edit_file:<root>` → `始终允许编辑根目录文件`
|
|
65
123
|
*/
|
|
66
124
|
export function alwaysLabelFor(ruleKey) {
|
|
67
125
|
if (ruleKey.startsWith('bash:')) {
|
|
68
|
-
|
|
126
|
+
const spec = ruleKey.slice('bash:'.length);
|
|
127
|
+
if (spec.includes(':')) {
|
|
128
|
+
return `始终允许以 '${spec.replace(':', ' ')}' 开头的命令`;
|
|
129
|
+
}
|
|
130
|
+
return `始终允许 '${spec}'`;
|
|
69
131
|
}
|
|
70
132
|
if (ruleKey.startsWith('write_file:')) {
|
|
71
133
|
return `始终允许写 ${bucketLabel(ruleKey.slice('write_file:'.length))}`;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"permissions.js","sourceRoot":"","sources":["../../../src/cli/run/permissions.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"permissions.js","sourceRoot":"","sources":["../../../src/cli/run/permissions.ts"],"names":[],"mappings":"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"}
|
package/dist/cli/run/task.js
CHANGED
|
@@ -16,14 +16,24 @@
|
|
|
16
16
|
* 放在 cli/run 而非 tools/:task 需要 runAgentTurn 级别的编排能力与 ctx,
|
|
17
17
|
* 且避免 tools ↔ cli/run 循环依赖(本文件只 import tools / ai / 同层工具)。
|
|
18
18
|
*/
|
|
19
|
-
import { executeTool, getTool, toolNames } from '../../tools/index.js';
|
|
19
|
+
import { executeTool, getTool, textToolResult, toolNames } from '../../tools/index.js';
|
|
20
20
|
import { getTodos, setTodos } from '../../tools/todo.js';
|
|
21
21
|
import { style } from '../style.js';
|
|
22
22
|
import { ruleKeyFor } from './permissions.js';
|
|
23
23
|
import { formatToolCall, formatToolResult, toolCallLines, } from './format.js';
|
|
24
24
|
import { LineFoldPrinter, renderWithFold } from './fold.js';
|
|
25
25
|
import { WriteFileStreamPrinter } from './stream-write.js';
|
|
26
|
-
|
|
26
|
+
import { runHooks } from './hooks.js';
|
|
27
|
+
/**
|
|
28
|
+
* 只读探索类子代理允许的工具(无副作用,硬边界)。
|
|
29
|
+
*
|
|
30
|
+
* 关于 bash_output 的设计说明(审计 P2):后台进程输出可能含 token / 内部 URL /
|
|
31
|
+
* 堆栈等敏感信息,子代理确实可能把它带回主对话上下文。但子代理与主会话共享
|
|
32
|
+
* 同一信任边界(输出实时透传给用户、结论本就回流主会话),且这些输出主会话
|
|
33
|
+
* 随时可见——explore 读它不会扩大用户自身的信息暴露面,真正的边界是「不能
|
|
34
|
+
* 产生副作用」。因此保留 bash_output 以支持「看看 dev server 为什么报错」这类
|
|
35
|
+
* 只读诊断任务;不希望子代理碰后台输出时,用 kill_bash 清掉再委派即可。
|
|
36
|
+
*/
|
|
27
37
|
const EXPLORE_TOOLS = ['read_file', 'list_dir', 'grep', 'bash_output'];
|
|
28
38
|
/** 各类型对应的 system prompt。 */
|
|
29
39
|
const PROMPTS = {
|
|
@@ -49,6 +59,11 @@ function resolveAllowedTools(type) {
|
|
|
49
59
|
}
|
|
50
60
|
/** 子代理最多连续调用工具的轮数,防止失控。 */
|
|
51
61
|
const MAX_ROUNDS = 8;
|
|
62
|
+
const TOOL_ERROR_STATUS = '<system>ERROR: Tool execution failed.</system>';
|
|
63
|
+
function toolResultForModel(result) {
|
|
64
|
+
const prefix = result.isError ? `${TOOL_ERROR_STATUS}\n` : '';
|
|
65
|
+
return `${prefix}${result.output}`;
|
|
66
|
+
}
|
|
52
67
|
function safeParse(argsJson) {
|
|
53
68
|
try {
|
|
54
69
|
return JSON.parse(argsJson || '{}');
|
|
@@ -162,17 +177,29 @@ async function runSubAgent(ctx, args) {
|
|
|
162
177
|
const msg = tc.name === 'task'
|
|
163
178
|
? '错误:子代理不可再委派子任务(task 调用已被拒绝)。请直接完成当前子任务。'
|
|
164
179
|
: `错误:当前子代理(${type ?? 'default'})不允许调用工具 ${tc.name}。请改用允许的工具完成子任务。`;
|
|
180
|
+
const result = textToolResult(msg, true);
|
|
165
181
|
history.push({
|
|
166
182
|
role: 'tool',
|
|
167
183
|
tool_call_id: tc.id,
|
|
168
|
-
content:
|
|
184
|
+
content: toolResultForModel(result),
|
|
169
185
|
});
|
|
170
186
|
continue;
|
|
171
187
|
}
|
|
172
188
|
const tool = getTool(tc.name);
|
|
189
|
+
const a = safeParse(tc.arguments);
|
|
190
|
+
// PreToolUse hook:与主循环同一套配置,缩进打印;拦截则短路。
|
|
191
|
+
const pre = await runHooks(ctx.hooks, 'PreToolUse', { cwd: ctx.cwd, tool_name: tc.name, tool_input: a }, bodyPrint);
|
|
192
|
+
if (pre.blocked) {
|
|
193
|
+
const result = textToolResult(`操作被 PreToolUse hook 拦截:${pre.reason ?? ''}。请勿重试。`, true);
|
|
194
|
+
history.push({
|
|
195
|
+
role: 'tool',
|
|
196
|
+
tool_call_id: tc.id,
|
|
197
|
+
content: toolResultForModel(result),
|
|
198
|
+
});
|
|
199
|
+
continue;
|
|
200
|
+
}
|
|
173
201
|
// 破坏性工具:共享主会话的「始终允许」与确认
|
|
174
202
|
if (tool?.needsConfirm) {
|
|
175
|
-
const a = safeParse(tc.arguments);
|
|
176
203
|
const ruleKey = ctx.permission ? ruleKeyFor(tc.name, a) : null;
|
|
177
204
|
const allowed = ruleKey
|
|
178
205
|
? ctx.permission.isAllowed(ruleKey)
|
|
@@ -185,10 +212,11 @@ async function runSubAgent(ctx, args) {
|
|
|
185
212
|
: `${tc.name}(${tc.arguments})`;
|
|
186
213
|
const choice = await ctx.confirm(preview, ruleKey ? { ruleKey } : undefined);
|
|
187
214
|
if (choice === 'no') {
|
|
215
|
+
const result = textToolResult('用户拒绝执行此操作。', true);
|
|
188
216
|
history.push({
|
|
189
217
|
role: 'tool',
|
|
190
218
|
tool_call_id: tc.id,
|
|
191
|
-
content:
|
|
219
|
+
content: toolResultForModel(result),
|
|
192
220
|
});
|
|
193
221
|
continue;
|
|
194
222
|
}
|
|
@@ -220,10 +248,17 @@ async function runSubAgent(ctx, args) {
|
|
|
220
248
|
});
|
|
221
249
|
bashFold?.finish();
|
|
222
250
|
bodyPrint(style.muted(` → ${formatToolResult(tc, result)}\n`));
|
|
251
|
+
// PostToolUse / PostToolUseFailure hook:只观察
|
|
252
|
+
await runHooks(ctx.hooks, result.isError ? 'PostToolUseFailure' : 'PostToolUse', {
|
|
253
|
+
cwd: ctx.cwd,
|
|
254
|
+
tool_name: tc.name,
|
|
255
|
+
tool_input: a,
|
|
256
|
+
tool_response: result.output,
|
|
257
|
+
}, bodyPrint);
|
|
223
258
|
history.push({
|
|
224
259
|
role: 'tool',
|
|
225
260
|
tool_call_id: tc.id,
|
|
226
|
-
content: result,
|
|
261
|
+
content: toolResultForModel(result),
|
|
227
262
|
});
|
|
228
263
|
}
|
|
229
264
|
}
|
package/dist/cli/run/task.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"task.js","sourceRoot":"","sources":["../../../src/cli/run/task.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAGH,OAAO,EAAE,WAAW,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"task.js","sourceRoot":"","sources":["../../../src/cli/run/task.ts"],"names":[],"mappings":"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"}
|