Joye Dev

Back

feat(agent): home composer creation controls + agent-chosen image model

PR: #4389 feat(agent): home composer creation controls + agent-chosen image model


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

Voyager Merged PR 学习 - 2026-07-09 - PR #4389#

PR:#4389 feat(agent): home composer creation controls + agent-chosen image model

**作者:**Horcrux / magicismight

**Merge 时间:**2026-07-09T04:38:27Z(2026-07-09 14:38:27 Australia/Melbourne)

**模块:**agent runtime、home composer、agent chat protocol、image generation、page commit tools、agent-eval

**学习标签:**agent-runtime、creation-directive、home-composer、image-model-routing、terminal-failure、agent-eval、protocol-boundary

今日选择#

选择 PR #4389。它把首页的创作类型、尺寸/比例/分辨率、图片模型选择转成可传给 agent 的结构化 creation directive,并同步处理固定尺寸 design 的预建页、图片模型升级策略、保存失败终态语义和 eval 覆盖。

为什么值得学#

  • 它把 UI 选择提升为协议,而不是只做前端状态。ChatMessageMetadata.creation 让同一条消息 regenerate 时能重放同一个 directive,避免“用户首页选了 poster,agent 只看到自由文本”的漂移。
  • 它在 agent 边界显式区分“用户已绑定的意图”和“agent 可推理的部分”。类型、preset、ratio 是硬约束;Auto 尺寸仍交给 agent 问或判断。
  • 它把模型成本/质量策略放在工具 schema 和运行时 fallback 中,而不是暴露成全局模型选择器。普通图默认低成本,显式 2K/4K 或 exact text/photorealistic 才升级。
  • 它延续昨天 #4516 的终态失败语义:保存页时的后端/导出服务故障返回 failed result,并给模型停止指令;Go 4xx 仍抛给模型修正。

关键代码#

1. 首页选择变成 wire protocol#

export type ChatMessageMetadata = {
  // ...
  // Kept on the message so regenerating it replays the same directive.
  creation?: CreationDirective;
};

export const creationDirectiveSchema = z.discriminatedUnion("kind", [
  z.object({ kind: z.literal("design"), presetId: z.enum(CREATION_PRESET_IDS).optional() }),
  z.object({ kind: z.literal("image"), aspectRatio: z.enum(IMAGE_ASPECT_RATIOS).optional() }),
]);
plaintext

设计点:creation directive 挂在消息 metadata 上,说明它是用户本轮请求的一部分,不是某个页面组件的临时状态。这样 retry/regenerate、agent worker、eval 都能使用同一份输入。

2. Directive prompt 把已选创作类型变成硬约束#

return [
  `The user chose to create a "${preset.label}" before this conversation. Treat this as binding.`,
  "",
  `- Skip target selection — the creation type is already chosen: call \`load_creation_target\` with exactly \`${target.id}\` before target-specific work.`,
  `- A blank \`${presetId}\` page (...) was already created ... Build into it ... via \`update_design\`; do not insert a new page.`,
];
plaintext

设计点:这里没有让模型“参考”用户选择,而是要求跳过 target selection,并绑定到预建的 selected page。这解决了 fixed-size design 打开后 agent 又 insert_page,用户仍停在空白页的问题。

3. 图片模型升级由工具边界兜底#

const wantsAboveLiteCeiling =
  input.resolution != null && input.resolution !== "1K";
const modelId =
  imageModelId ??
  input.modelId ??
  (wantsAboveLiteCeiling
    ? HIGH_RESOLUTION_IMAGE_MODEL_ID
    : DEFAULT_IMAGE_GENERATION_SETTINGS.modelId);

return {
  resolution: modelId === NANO_BANANA_LITE_IMAGE_MODEL_ID ? "1K" : ...,
  modelId,
};
plaintext

设计点:schema/prompt 告诉模型什么时候升级,但运行时仍保证 2K/4K 不会被 Lite 静默压成 1K。用户或 chat-level 显式模型选择优先,默认 fallback 才按分辨率升级。

4. Page commit 故障复用终态结果模式#

if (output.status === "failed") {
  return { type: "text", value: "... Stop here — do not retry ..." };
}

if (!isServiceOutage(error)) throw error;
logger.capture(error, { tags: { scope: "page-commit", tool: toolName } });
return { status: "failed", reason: "service_unavailable" };
plaintext

设计点:服务故障不再作为 retryable throw 交给模型无限重发;原始错误进 Sentry,模型只看到产品化、无内部细节的失败结果。4xx 仍抛出,保留模型修正错误调用的空间。

和最近学习记录的关系#

强相关。最近几条学习记录从 #4314(AI Gateway image provider 边界)、#4344(referenceAssetIds 进入 agent tool schema)、#4309(新增 Nano Banana Lite 的跨层契约)、#4516(图片终态失败作为 result)一路推进。#4389 是这条链路的上层收束:把首页入口的用户选择变成 agent 可执行协议,并把图片模型路由和 page commit 失败语义纳入同一套 agent runtime 规则。

我会怎么吸收#

  • 用户在入口处做出的选择,如果会影响 agent 行为,应进入协议/metadata,而不是留在 UI state 或 prompt 文本里。
  • LLM 工具的“建议策略”要有运行时 guardrail:schema 描述负责引导,工具实现负责兜底,eval 负责防回退。
  • 对有副作用的工具,区分可纠正调用错误和不可立即重试的服务故障;后者应返回终态 result,让模型停止,而不是抛成 retryable error。

边界/风险#

主要风险是 PR 面很宽:home composer、协议、agent prompt、工具失败语义、eval、UI chip 都在一个 PR 里改,review 成本高。好处是它用多组 agent-eval 把关键行为钉住,包括固定画布不 insert_page、服务故障不重试、图片模型升级、回复语言和失败话术。未看到明显缺失的核心风险,但后续需要继续观察实际数据里 agent 是否过度升级到 gpt-image-2,以及 Auto preset 是否在更多创作类型里保持语义清晰。

候选说明#

今天(Australia/Melbourne 2026-07-09)查到 4 个已 merge 到 main 且未在本地日志记录过的候选:#4546、#4543、#4539、#4389。#4546 是 context menu 子菜单关闭语义,#4543/#4539 是 docs 编辑器行为;都可学习,但工程跨度和近期主题关联不如 #4389。昨天窗口还有若干已 merge PR,其中 #4516 已在 2026-07-08 学过并被去重跳过。

飞书文档#

本文档即本次学习记录。

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

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

← Back