feat(adapters): shell→apply_patch server-side normalize (refs #235, stacked on #236)#239
Open
Cmochance wants to merge 2 commits into
Conversation
…erwrite 3 模式自动触发 Codex Desktop diff UI PR #236 修了 wire 层(custom_tool_call SSE 桥接 + 多轮历史回放),issue #235 真机 capture(round 2)显示 Kimi 偏好 `exec_command` 跑 `cat <<EOF > file` / `printf >` / `echo >` 一次性写文件,绕过 `apply_patch` 工具 → Codex Desktop 收不到 apply_patch SSE → 不渲染 diff UI(代码块行号 / +N -M / 文件清单 / 颜色 / 抬头 / 可点击文件名 6 个元素失效)。 设计灵感取自 Antigravity Go agent(`~/.local/bin/agy` strings dump 实证含 `FILE_CHANGE_TYPE_EDIT` / `file_diff` / `trajectory_file_diffs` 等 token,印证 server 层产出统一 diff 事件而非依赖模型工具选择),具体 shell → V4A 规则自创。 adapter 在 SSE 转换层归一化 file-write shell 意图为 apply_patch wire 事件: MVP scope(3 happy pattern) - `cat <<'EOF' > /path/file\n<body>\nEOF`(here-doc,unquoted/single/double 终止符) - `printf '<content>' > /path/file`(支持 \n / \t / \\ / \' / \" / \r 转义展开) - `echo '<content>' > /path/file`(字面 literal,自动补尾 newline) 严格 reject(透传原 exec_command 不动) - `>>` append / `sed -i` in-place / `tee` / `tee -a` / 多命令组合(`;` `&&` `||`) - pipe `|` / 子 shell `$(...)` / `` `...` `` / bare `$VAR` `${VAR}` 变量 - 多 `>` / `2>` / `&>` / `echo -e/-n` flags / `printf %s` 格式串 - here-doc 终止符不合法 / path 含 shell metachar 主要改动 - 新增 `crates/adapters/src/responses/shell_to_apply_patch.rs`:detector + V4A patch generator,21 个 unit test 覆盖 3 happy + 多个 reject + corner case。 - 改 `crates/adapters/src/responses/converter.rs`:`PendingToolCall` 加 `is_exec_command` flag,open 阶段对 exec_command **不立即** emit `output_item.added`(buffer 整段 args 到 close 阶段);close 阶段 run detector: - 检测到 file-write → emit 完整 custom_tool_call apply_patch SSE 序列 (added → input.delta → input.done → output_item.done),call_id 复用模型 原 exec_command call_id 让下一 turn tool_result 回灌正确关联。 - 未检测到 → 补 emit 完整 function_call SSE 序列(added → arguments.delta (整段)→ arguments.done → output_item.done),Codex Desktop 当普通 shell 跑, 行为跟改前 100% 一致。 - **interrupted exec_command 路径特判** emit `status="incomplete"`,对称 apply_patch interrupted 处理,防 Codex Desktop 跑半截 shell(truncated here-doc 等 destructive)。 - 新增 `docs/followup/39-shell-to-apply-patch-edit-and-append.md` + 索引行: Edit / append (`>>` / `tee -a` / `cat <<EOF >>`) / `sed -i` in-place / output normalize 跟踪。 - `docs/CHANGELOG.md` + protocol-conversion 3way 同步。 pre-push 3-agent review 已修 - IMPORTANT-1 (code-reviewer):normalize 后 `pending.args_acc` 同步 synthetic `{"input":<V4A>}`,跟 ToolCallCache + assistant_message() 三处一致,防下一 turn previous_response_id 重建给上游 name/args mismatch 数据。 - IMPORTANT-2 (code-reviewer):`echo "hello $USER" > file` reject — bare `$VAR` / `${VAR}` shell 会展开,normalize 写字面跟模型意图 divergence(SECRET 落盘等 危险场景),强制 reject 让模型 fallback apply_patch。 - IMPORTANT-3 (code-reviewer):interrupted exec_command emit `status="incomplete"` 对称 apply_patch interrupted 处理(原默认 function_call 关闭路径 emit completed 会让 Codex Desktop 跑半截 shell)。 - BLOCKER B1/B2 (comment-analyzer):followup pointer 补 tee -a 引用 + #39 ref; trade-off 注释删除 hard claim(`<1KB` / `<2s`,无数据支撑),改成 issue #235 capture 数据对照 + round 3 真机后回填。 - Antigravity 措辞精确化(strings dump 证据 vs design 推断的边界明示)。 - doc orphan comment 修复(extract_apply_patch_input 跟 detect 函数 reorder)。 - 5 个新 unit test 覆盖 3 个 IMPORTANT 修复(args_acc 同步 / bare-$ reject / interrupted incomplete)。 540 tests pass。 成功率改善幅度待 push 后真机 regression round 3 数据出来回填 PR 评论。 Refs #235
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Scope
Stacked on top of #236(apply_patch wire 修复)。本 PR 处理 issue #235 的另一个根因:chat-completions provider 上模型偏好
exec_commandshell 写文件,Codex Desktop 收不到 apply_patch SSE → 不渲染 diff UI。设计灵感取自 Antigravity Go agent(
~/.local/bin/agystrings dump 实证含FILE_CHANGE_TYPE_EDIT/file_diff/trajectory_file_diffs等 token,印证 server 层统一 diff 事件模型),adapter 在 SSE 转换层 normalize file-write shell 意图为custom_tool_call apply_patchwire。跟 PR #238 关系
PR #238 是 prompt 工程路径(让模型主动选 apply_patch);本 PR 是 server-side normalize 路径(模型选 shell 也能渲染 diff UI)。两条路径不冲突,本 PR ship 后用户可再评估 PR #238 是否仍要 merge(round 3 真机数据出来后)。
MVP scope(3 happy + 严格 reject)
✅ Add File / 完整 overwrite 3 模式(detector tested):
cat <<'EOF' > /path/file\n<body>\nEOF(here-doc,unquoted/single/double 终止符)printf '<content>' > /path/file(\n\t\\\'\"\r转义展开)echo '<content>' > /path/file(字面 literal,自动补尾 newline)🚫 严格 reject(透传原 exec_command 不动):
>>append /sed -iin-place /tee/tee -a;&&|||)/ 子 shell\$(...)/\...``\$VAR/\${VAR}(变量展开 vs 字面 divergence,IMPORTANT-2)>/2>/&>/echo -e/-nflags /printf %s格式串Edit / append / sed -i / output normalize →
docs/followup-tracker.md#39。主要改动
crates/adapters/src/responses/shell_to_apply_patch.rs:detector + V4A patch generator,21 unit testcrates/adapters/src/responses/converter.rs:pre-push 3-agent review
3 IMPORTANT 真 bug 全修 + 2 BLOCKER doc 类全修 + 5 IMPORTANT doc 类全修。详见 commit message。
Verification
Regression baseline + round 3
issue #235 真机 capture(round 1 / round 2)= 26MB + 17 min Kimi+DeepSeek 数据保留 baseline。本 PR push 后 round 3 真机测试,对比 `exec_command` 转 `apply_patch` 触发率 + UI 渲染验证,届时在本 PR 评论补具体数字。
Refs #235