02 · 编辑后自动处理
利用 after_edit hook,在文件修改后自动格式化代码——让 agent 的输出更规范。
问题的提出
Agent 修改文件时,模型的输出格式不一定完美。可能多了空格、少了换行、缩进不一致。虽然不影响功能,但会让代码审查者觉得"agent 写的代码不够规范"。
人类开发者通常在编辑器里配置了自动格式化(保存时运行 Prettier)。Agent 也应该有同样的能力——修改文件后自动格式化。
after_edit Hook
after_edit 在 write_file 或 patch_file 执行后触发。它知道哪个文件被编辑了、用什么方式编辑的:
interface AfterEditContext {
path: string; // "src/agent.ts"
method: "write" | "patch";
result: string;
}有了这些信息,就可以在编辑后执行格式化:
export function createAutoFormatHook(): Hook {
return {
name: "auto_format",
timing: "after_edit",
handler: async (ctx: AfterEditContext) => {
const supportedExtensions = [".ts", ".tsx", ".js", ".jsx"];
if (!supportedExtensions.some((ext) => ctx.path.endsWith(ext))) return;
try {
await execFileAsync("npx", ["prettier", "--write", ctx.path], {
timeout: 10000,
});
} catch {
// prettier 不存在或执行失败,静默跳过
}
},
};
}关键设计点:
只处理支持的文件类型。 .ts、.tsx、.js、.jsx 用 Prettier 格式化。Markdown、JSON、YAML 等文件不处理。
静默失败。 如果项目没有安装 Prettier,或者 Prettier 执行出错,不影响 agent 的正常工作。格式化是"锦上添花",不是必需品。
有超时保护。 10 秒超时,防止格式化命令卡住整个 agent。
在 agent 中的触发
agent 循环中,after_edit hook 在工具执行成功后、上下文记录之前触发:
if (options?.hookManager) {
await options.hookManager.executeAfterTool({
tool: toolCall.name,
args: toolArgs,
result,
});
if (toolCall.name === "write_file" || toolCall.name === "patch_file") {
await options.hookManager.executeAfterEdit({
path: String(toolArgs.path ?? ""),
method: toolCall.name === "write_file" ? "write" : "patch",
result,
});
}
}注意 after_edit 是在 after_tool 之后才触发的——先执行通用的工具后处理,再执行文件编辑的专门处理。
扩展:编辑后自动验证
同样的 after_edit 时机,还可以做"编辑后自动跑测试":
export function createEditVerifyHook(): Hook {
return {
name: "edit_verify",
timing: "after_edit",
handler: async (ctx: AfterEditContext) => {
if (!ctx.path.endsWith(".ts")) return;
if (ctx.path.includes(".test.") || ctx.path.includes(".spec.")) return;
// 找到对应的测试文件
const testPath = ctx.path.replace("src/", "test/").replace(".ts", ".test.ts");
// 如果测试文件存在,运行它
// ...
},
};
}修改 src/agent.ts 后自动跑 test/agent.test.ts——如果测试失败了,agent 能在下一次工具调用中看到失败结果并尝试修复。
Hook 的组合
多个 after_edit hook 可以共存。它们按注册顺序执行:
hookManager.register(createAutoFormatHook()); // 先格式化
hookManager.register(createEditVerifyHook()); // 再跑测试先格式化、再验证——顺序很重要。如果不先格式化,测试可能在格式不一致的代码上运行,结果不可靠。
Hook 的组合能力让 agent 的行为可以灵活定制。需要格式化就注册格式化 hook,不需要就不注册。不同的项目可以注册不同的 hook 组合。
下一节讲解审计日志和安全相关的 hook。
登录以继续阅读
解锁完整文档、代码示例及更多高级功能。