// docs / modify-agent
修改 Agent
受 Claude Code query() 设计启发的 Agent 循环。 Agent 搜索、阅读、编辑、验证 — 配备质量门控,防止提前停止。
概览
与生成流水线(确定性步骤)不同,修改流是一个开放循环。 Agent 自主决定读哪些文件、改什么、何时结束。 Stop Hook 强制执行最低质量标准。
runModifyProject(projectId, instruction, imageBase64?)
│
├── resolve_project 加载项目元数据
├── read_context 文件树 + design-system.md + globals.css
└── agent_loop while(true),最多 100 次迭代
│
├── 第 1 次迭代:tool_choice="required"(必须行动,不允许空想)
├── 工具执行 → 更新循环状态
├── stop hook 检查 → 注入错误或允许停止
└── 停止时:计算 diff → 持久化到 modificationHistoryAgent 循环
tool_choice 状态机
循环根据上一步的结果控制 tool_choice:
首次迭代required强制先行动,再思考stop hook 重试后required已要求使用工具 — 强制执行工具执行后autoLLM 已有上下文,让它自主决策自然语言 → 代码定位
用户描述的是 UI/产品语言,不是文件路径。由 Agent 结合 file tree、预读文件和工具自行定位——编排层不做关键词切分或固定目录猜测。
conversation / read_only / plan_only / code_change,并可选输出 preloadPaths。工具集
read_file读取文件完整内容(支持行范围)
search_coderipgrep 全项目搜索
list_dir列出目录内容
edit_file精确字符串替换(old_string → new_string)
write_file创建或覆盖文件
generate_imageAI 生图写入 public/images(与生成流水线相同;仅代码修改 intent 暴露)
run_build执行 next build 验证变更
exec_shell受限 shell(诊断与脚手架;受策略与白名单约束)
think无副作用推理草稿,压缩进 reasoning 轨迹
revert_file按快照回滚单个文件
edit_file 的精确匹配要求
old_string 必须在文件中精确匹配唯一一处。 Agent 被要求包含上下文行以确保唯一性,防止意外的多处替换。
Stop Hook
当 LLM 停止调用工具时,stop hook 在允许循环退出前运行。 它检查循环状态(是否探索过仓库、是否完成编辑/回答、类型错误、scoped tsc),并注入通用 Agent 指令——不从用户句子里切关键词,也不硬编码搜索路径。
function runStopHook(state, instruction, modifyMode, { profile }): string | null {
if (!state.hasSearched && !state.hasEdited) {
return modifyMode === "read_only"
? "Use read/search/list; answer in natural language; do not edit."
: "Explore with tools from the file tree, then edit_file.";
}
if (modifyMode === "read_only" && state.hasSearched) return null;
if (modifyMode === "code_change" && !state.hasEdited) return "Make edits now…";
if (profile.verificationMode === "tsc_only") return null;
// optional: remind run_scoped_tsc before finish
return null;
}| 参数 | 值 | 用途 |
|---|---|---|
| MAX_ITERATIONS | 100 | 循环迭代硬上限 |
| MAX_STOP_HOOK_RETRIES | 5 | 防止 stop hook 自身无限循环 |
| stopHookRetries reset | 工具调用后 | 成功执行工具后计数器归零 |
对话记忆与工作记忆
持久层仍是 turn 列表(DB modificationHistory + session 合并去重)。 注入主 Agent / Router 时不再塞「最近 10 轮全文」,而是:
merged = mergeModifyHistoryTurns(dbHistory, sessionHistory) // 工作记忆 = 从 turn 列表确定性投影(不落新 DB 列) workingMemory = projectWorkingMemory(merged) // focusFiles (≤3) · pendingQuestion · lastIntent … // 主 Agent:状态卡 + 最近 2 轮原文(非最近轮 Result 截断) // Router:状态卡 + 短历史 // /clear → 两侧输入为空 → 投影为空
用于稳住「再大一点」类短程指代,同时压低旧 Result 噪音。/clear 重置 session;/memory 打开调试面板(GET /api/projects/[id]/memory)查看将注入的投影与历史。
图片输入
用户可以粘贴截图配合文字指令。图片以 vision content array 格式发送在第一条用户消息中:
content: imageBase64 ? [
{
type: "image_url",
image_url: {
url: imageBase64.startsWith("data:") ? imageBase64
: `data:image/png;base64,${imageBase64}`,
detail: "high",
},
},
{ type: "text", text: userMessage },
] : userMessagemodifyHistory 中,并在对话 UI 中显示为缩略图。 Agent 可以参考截图中的视觉细节来决定修改内容。