Joye Dev

Back

fix(agent): commit each deck page before starting the next

**PR:**fix(agent): commit each deck page before starting the next (#4591)


正文来源:飞书学习文档。以下为通过个人 Feishu API 获取并转换后的完整 Markdown 正文。

Voyager Merged PR 学习 - 2026-07-11 - PR #4591#

今日选择#

**PR:**fix(agent): commit each deck page before starting the next (#4591)

**作者:**magicismight

**Merge 时间:**2026-07-10T15:43:14Z(2026-07-11 01:43:14 AEST)

链接:https://github.com/adastralab-ai/voyager/pull/4591

**模块:**agent-eval/cases/design, agent-eval/provider.ts, backend/workers/agent/src/skills/design-html, backend/workers/agent/src/skills/generate-slide

**学习标签:**agent-runtime, deck-generation, prompt-contract, tool-trajectory-eval, user-visible-progress, long-turn-timeout

为什么值得学#

  • 它把用户可感知的运行时反馈顺序写回技能契约:多页 deck 不是先生成完所有 HTML 再集中提交,而是每页从资产到 HTML 到 commit 闭环完成后再进入下一页。
  • 它没有把问题下沉成复杂工具改造,而是承认工具本来就是单页粒度提交,修复点放在 agent 的技能约束和轨迹回归测试上。
  • 它新增的 eval 检查的是工具调用序列,而不是最终文件数量;这更接近 agent 运行时 bug 的真实形态。
  • 它顺手处理了 eval harness 的 300s 默认超时,让多页 deck 这种长 turn 可以被纳入回归层,而不是因为基础设施限制被排除。

关键代码#

1. 共享 design-html commit policy 把多页生成定义为用户可见的增量提交。

- **One design/page**: write the HTML, run one `inspect-html` preview/validation pass, fix material issues, then commit.
- **Multiple designs/pages**: do not load or run `inspect-html`. Build one page at a time: generate only that page's assets, write a unique working HTML file, self-check the hard rules, and commit it before starting any work on the next page (its image generation included).
plaintext

设计点:这里把“commit”从后处理步骤提升为用户反馈协议。多页任务每一页的 commit 是画布出现内容的边界,因此 agent 不应该为了内部吞吐把可见反馈批处理掉。

2. slide skill 在更具体的 deck 语境里重复同一顺序约束。

## Multi-slide decks

For decks, build slide N end-to-end before touching slide N+1: generate only slide N's assets, write a unique `/workspace/slide-N.html`, self-check, and commit it — only then start slide N+1.
plaintext

设计点:同一规则同时放在通用 HTML contract 和 slide-specific skill,减少模型在组合技能时把约束压缩丢失的概率。它不是泛泛说“commit directly”,而是给出 slide N 到 slide N+1 的严格时序。

3. 新 eval 用 pending uncommitted 标记捕捉“先写下一页”的轨迹。

const seq = context.providerResponse?.metadata?.toolSequence ?? [];
const seen = new Set();
let uncommitted = null;
for (const step of seq) {
  if (step.name === "update_design" || step.name === "insert_page") { uncommitted = null; continue; }
  const path = step.name === "write_file" ? String(step.input?.path ?? "") : "";
  if (!path.endsWith(".html") || seen.has(path)) continue;
  if (uncommitted) return { pass: false, score: 0, reason: `started ${path} before committing ${uncommitted}` };
  seen.add(path);
  uncommitted = path;
}
plaintext

设计点:测试不是断言某个 prompt 文案存在,而是断言 tool trajectory 的业务不变量:一个新 HTML 文件出现后,必须先有 update_design/insert_page 清掉 pending 状态,才能开始下一页。

4. eval provider 为长 agent turn 设置有限但更现实的 undici 超时。

// The eval route answers only when the whole agent turn finishes; multi-page
// deck cases run past undici's default 300s headersTimeout.
const TURN_TIMEOUT_MS = 20 * 60_000;
setGlobalDispatcher(
  new Agent({ headersTimeout: TURN_TIMEOUT_MS, bodyTimeout: TURN_TIMEOUT_MS }),
);
plaintext

设计点:多页生成是单个 agent turn,eval route 只在整个 turn 完成后返回。这里不是无限放宽,而是把超时上限改成能覆盖真实长任务、同时仍能让卡死 worker 失败的有限边界。

和最近学习记录的关系#

它和最近几天的 agent/image 学习链路有直接关系,但关注点从“工具结果/费用/模型选择”转到“多步骤生成的用户可见进度”。#4516 和 #4580 都是在约束模型不要误重试、不要绕过用户确认;#4591 则约束模型不要把多页工作内部批处理成一个最终爆发。共同点是:把隐含产品语义写成 agent 协议和 eval,而不是只依赖 UI 层兜底。

我会怎么吸收#

  • 凡是用户能实时感知的多步骤任务,都要定义“可见提交点”,并把它作为 agent/tool contract 的一部分。
  • prompt/skill 修复要配 trajectory eval;对 agent 类系统,最终状态正确不代表过程正确。
  • 长 turn 的测试基础设施要显式建模超时:默认 HTTP timeout 经常不是产品不变量,只是库默认值。

边界/风险#

看到一个有意接受的 eval 边界:review 曾指出仅把 update_design/insert_page 视为清 pending,未精确校验 htmlPath 可能被无关提交掩盖;作者解释最终选择非脆弱优先,避免绝对/相对路径变体带来的误报。这个取舍合理,但意味着 eval 保证的是“提交节奏”,不是“提交路径与刚写路径严格一致”。如果以后出现错误 htmlPath 的真实 bug,需要补更精确但归一化良好的路径断言。

候选说明#

今天(2026-07-11 Australia/Melbourne)窗口内看到 7 个已 merge 到 main 的候选:#4648、#4636、#4629、#4628、#4623、#4594、#4591。没有因为去重跳过今天候选;昨天已学习 #4580,所以未重复选择。最终选 #4591,是因为它横跨 agent 技能契约、运行时用户反馈和 eval harness,比价格调整、单文件分页大小、worktree DX 等 PR 更有学习价值;#4594 也有价值,但更偏 UI loading 连续性,工程边界不如 #4591 清晰。

🗂️ 这是知识库中的🔬 研究。

内容可能仍在补充或修订中。

← Back