4e0c0c8cd9
移除从轻量任务摘要读取主任务结果载荷的错误实现。 画布 Agent 继续轮询摘要状态,并通过画布完成回写刷新工程结果。
17 KiB
17 KiB
画布Agent对话面板
日期:2026-07-10
定位与边界
- 画布Agent对话 是图片画布工程(
/editor/canvas)右侧的对话式编辑器工具:用户通过自然语言调度画布已有的图片类生成与编辑能力,并可附加画布资源或素材库图片作为参考。 - 它是画布域工具,不承接玩法创作、不产出玩法作品或模板,与
CONTEXT.md中「表单/图片输入创作工作台」的 Avoid 边界不冲突。 - 独立于拼图专用的
/api/runtime/creative-agent/sessions(该会话为 api-server 内存态、拼图领域专用,不复用)。
能力范围
对话 Agent 可通过 function-calling 触发以下八类工具,全部复用既有计费收口接口:
| 工具 | 后端接口 |
|---|---|
| 生成图片 | POST /api/editor/images/generations |
| 修改图片(基于附件/画布素材) | POST /api/editor/images/edits |
| 生成角色形象 | 既有角色形象生成入口对应接口 |
| 生成图标素材 | POST /api/editor/icon-spritesheets/generations |
| 生成 UI 设计图 | 既有 UI 设计图生成入口对应接口 |
| 生成视频 | POST /api/editor/videos/generations |
| 生成游戏音效 | POST /api/editor/audios/sound-effects/generations |
| 生成背景音乐 | POST /api/editor/audios/background-music/generations |
- 意图解析与工具编排在后端 api-server,前端只渲染状态,不承接业务规则。
- 下面的工具选择口径属于 Agent 规划 prompt / function-calling 约束,不是侧边栏 UI 说明文案;侧边栏面板不展示这些规则解释。
- 用户要求“规范图 / 视觉规范图 / 风格规范图 / 素材规范展板”时,规划默认选择
generate_image,并在 prompt 中明确要求生成规范展板,包含统一视角、线条粗细、色卡、材质、阴影、圆角、状态层级、尺寸标注等可落地的视觉规范元素。 - 用户要求“角色规范图”且语义是角色的规范展板、风格展板或设定板时,仍走
generate_image,不要误分流到generate_character;只有实际生成角色立绘、角色主形象或角色视觉资产时才走generate_character。用户要求多个图标素材、图集或 spritesheet 时才走generate_icon_spritesheet。 - 所有生成必须走
execute_billable_asset_operation_with_cost与模型定价配置,禁止绕过定价收口。 - 图层操作及其他未注册的画板功能第一期不进入对话工具面,仍走现有面板。
当前分支落地状态
- 已落地:会话元数据、OSS 消息文档、会话 CRUD、SSE 消息流、后端 LLM 工具规划、右侧对话面板、会话历史、新建 / 软删会话、停止当前 SSE 回合、附件从画布资源 / 账号素材库选择,以及八类图片 / 音视频工具对既有生成入口的复用。
- 已落地:
tool_started/tool_completed事件携带status;工具失败时也会写入失败 generation record,并随后发送stage=failed与error,前端应保留消息内失败条目。 - 未落地:附件弹窗末尾上传格、跨刷新异步生成恢复、external generation task 轮询回填。未落地前,对话消息状态只表示本次 SSE 回合记录,不作为后台任务队列真相。
会话与持久化
- 对话归属单个图片画布工程;每个工程有自己的会话列表,可新开会话。
- SpacetimeDB 新表
editor_agent_conversation只存会话元数据:会话 ID、projectId、ownerUserId、标题、软删标记、聊天记录 OSS 对象引用、创建/更新时间。 - 完整消息内容存 OSS:
editor-agent/{conversationId}.json,会话粒度整体读写(追加消息=重写对象),不按消息拆对象。 - 不把对话塞进画布工程快照 payload,不在 api-server 内存中保存会话真相。
- 会话标题:新会话默认「新对话」,首条含文本的用户消息发出后自动截取前 N 字作为标题;列表摘要、详情和消息回包均携带同一必填标题,前端只展示该标题,不以会话 ID 或本地推导兜底。标题写入失败会使该消息请求失败,不能静默继续。
- 会话删除:列表项 hover 出删除按钮 + 确认;软删(表打 deleted 标记,OSS 对象保留)。
生成结果落画板(对现有占位规则的例外)
- 对话入口触发的生成不创建"即将生成"画布占位(区别于其余生成面板);生成中状态由对话消息流承载。
- 生成完成后:结果图按统一 placement 避让模型(视口中心就近、避开现有图层、32px 间距)落画板为新图层,同时登记到默认项目素材库,并在对话消息内显示纯缩略图;前端收到
generation_result后立即刷新工程快照与素材库,缩略图本身不显示名称也不承担图层跳转。 - 消息内生成结果缩略图必须携带并优先使用
objectKey/assetObjectId,前端通过ResolvedAssetImage//api/assets/read-url换签后渲染,不能把裸/generated-*私有路径直接交给<img>。 - 当前第一阶段通过既有编辑器生成 BFF 的
canvasCompletion写回工程快照;刷新后异步任务恢复和轮询回填属于后续能力,不在本阶段声明为已完成。 - 该例外已同步登记在《生成类面板Lovart统一改造方案-2026-06-17》「画布占位落点」节。
右侧布局
- 对话框与既有任务侧栏(
ImageCanvasTaskSidebarView)互斥展开:展开一个自动收起另一个;各自收起后保留入口按钮。 - 对话框与左侧素材 / 图层侧栏也互斥:打开画布 Agent 时收起左侧栏;再次打开素材、图层或任务侧栏时收起 Agent 面板。
- 桌面端对话框固定宽约 360–400px;移动端抽屉式全宽覆盖;收起态为胶囊/圆形入口按钮。
- 会话管理入口在对话框头部:当前会话标题 + 历史会话下拉(按更新时间倒序)+ 新建对话按钮,全部包在对话框内。
- 收起对话框只是隐藏面板,不卸载当前会话 hook;流式回复、
生成中阶段和停止按钮状态必须在收起 / 重新打开之间保持一致。
附件
- 输入区
+按钮打开图片选择弹窗(仅图片,无音视频):- 「画布」页签(默认):展示当前工程图层引用的图片资源;
- 「素材库」页签:账号级素材库(复用
ImageCanvasAssetLibrary数据源); - 多选 + 底部「取消 / 应用」。
- 网格末尾上传格为后续补齐项;在上传格未落地前,对话附件只从已有画布资源和账号素材库选择。后续若从对话入口上传图片,必须复用素材库 / 画布资源登记链路,不新增对话私有图片类型。
- 应用后附件以胶囊 chip 挂在输入框上方;发出的消息内附件渲染为纯文本胶囊 chip(名称 + 小图标),默认无缩略图,鼠标悬浮才浮出缩略图预览。
- 附件领域形状:统一为画布资源 / 素材库对象引用(
resourceId/assetId+ 可选objectKey),不存在只属于对话的第三种图;单条消息上限 9 张(前后端共同校验)。前端可携带展示用imageSrc/thumbnailSrc,后端必须按当前工程和当前账号重新归一、校验归属与objectKey。
工具调用确认展示契约
- Agent 规划出生成或编辑工具后,先把没有
externalJobId/cancelledAt的工具消息持久化为待确认记录;确认卡必须在真正调用生成 provider 前展示本次提示词、规格参数、目标图和参考图缩略图,用户确认后才执行,取消后保留同一条已取消记录。内部 system 文本和图片哈希 ID 不直接展示给用户。 - 工具消息不再保存独立
status。OSS 文档只保存可选externalJobId与确认前取消时间cancelledAt:两者都为空表示待确认,只有cancelledAt表示已取消;存在externalJobId时,排队、执行、完成和失败状态统一读取 SpacetimeDBexternal_generation_job,不得在 OSS 中复制第二套执行状态。 - 确认接口必须先把工具参数转换为既有编辑器 worker payload,再使用
editor-agent:{conversationId}:{messageId}:{toolName}稳定 dedupe key 入队;同一确认的请求重试只能得到同一个 external job。入队成功后把返回的 job id 写回同一条 OSS 工具消息,不新增 Agent 工具执行关联表。 - 前端根据
externalJobId查询通用 external-generation job 状态;worker 继续通过canvasCompletion把生成结果写回工程与素材库。浏览器断线、刷新或 api-server 重启不得导致确认接口重新扣费或重新提交 provider。 EditorAgentToolCall.args保留为工具返回的原始 JSON,是确认接口重新反序列化并执行工具的唯一参数真相。图片参数继续只保存由真实 data key 计算出的 opaque SHA-256imageId;不得为了前端预览把args中的图片 ID 改写成objectKey、URL 或展示对象,也不得由前端重组或回传一份新的执行参数。EditorAgentToolCall.displayArgs是必填、只读的用户确认展示投影,与args分离:stringArgs保存提示词、比例、清晰度、模型、时长等可展示参数的稳定名称、用户可见标题和值;imageArgs按“目标图片 / 参考图片”等参数分组,每个refs项包含与原始参数对应的imageId,以及后端从已校验会话上下文解析出的objectKey、imageSrc、可选thumbnailSrc/label/width/height。extras.priceMudPoints保存创建待确认消息时按后端运行时模型定价快照计算的预计泥点消耗;前端统一展示为“预计消耗 N泥点”,不自行计算价格。
displayArgs只能由 api-server 按已注册 tool 白名单,基于已经通过 ToolArgs 校验的args和当前 OSS 会话文档中的附件 / 历史生成结果构建;不能信任 LLM 自报的展示地址、标题或素材元数据。展示投影不参与确认执行,确认接口仍只读取同一条持久化 tool call 的args,避免“看到的素材”和“实际执行的素材”分叉。extras.priceMudPoints同样只属于展示投影,不作为扣费输入;确认后仍由既有生成 BFF 按后端运行时定价执行预扣费,因此该字段表达用户确认时看到的价格快照,而不是前端可提交或覆盖的计费真相。EditorAgentToolCall.summary只是args的重复字符串且没有稳定语义,当前契约删除该字段,不再作为展示或执行输入。- 前端待确认卡只消费必填
displayArgs,不解析各 tool 私有的 snake_case / camelCase schema,也不把sha256:*ID 当标题或图片地址。图片统一通过ResolvedAssetImage使用objectKey换签后显示,签名 URL 不进入消息文档。模块尚未上线,不保留缺少displayArgs时读取 rawargs的旧消息降级路径。
LLM 与计费
- 编排复用
creative_agent_gpt5_client的 LLM 接入配置(同 provider/env,独立用途标识),画布 Agent 规划请求固定使用 VectorEnginegpt-5.4-miniChat Completions;function-calling 注册八类工具。 - 每个用户回合必须由 LLM 返回结构化计划;LLM 未配置、请求失败或返回格式不可解析时,后端写入明确错误消息,不使用本地关键词或“收到:...”回显兜底。
- 规划 prompt 必须自动带入上一条已完成生成结果的
latestGeneratedImage引用,内容只包含上一轮 generation 的toolName/resourceId/objectKey/assetObjectId等轻量元数据,不把私有签名 URL 或大图内容塞进 prompt。 - 工具参数中的图片 ID 是由真实 object key 或图片地址计算的稳定 SHA-256 标识;真实 data key 仅存于 api-server 的工具上下文映射,所有图片工具在执行时查表恢复,不能把 object key 或图片地址作为 LLM 可见的工具 ID。
- 用户使用「这张」「刚才那个」「上一张」「把衣服换成……」等方式指代或编辑上一张结果图时,LLM 默认选择
edit_image并引用latestGeneratedImage作为源图;除非用户明确要求全新生成,否则不能因为本轮没有重新上传附件而降级为generate_image。 - 规划 prompt 必须显式区分“规范展板”和“实际素材产出”:规范图、视觉规范图、风格规范图、素材规范展板、角色规范图等规范展板请求走
generate_image,并补齐统一视角、线条粗细、色卡、材质、阴影、圆角、状态层级、尺寸标注等要求;实际角色立绘才走generate_character,多个图标素材 / 图集才走generate_icon_spritesheet。 - 画布 Agent 规划请求使用 Chat Completions、1024
max_tokens和 60 秒 Agent 专用请求超时;生成图片/编辑图片仍走对应生成工具和模型计费。 - 对话回合免费(聊天、分析回复不扣泥点),仅 Agent 实际触发生成工具时按对应模型定价扣泥点。
- 工具调用前后端校验泥点余额;不足时该次生成失败并在对话中以明确错误气泡告知,对话本身可继续。
Lovart 参照做/不做清单(验收标准)
做(第一期):
- 助手文本 SSE 流式输出;
- 阶段提示行(思考中 → 思考完成 → 生成中 → 完成/失败);
- 工具/模型标注行(生成时显示模型名 + 图标);
- 消息内生成结果缩略图(纯预览,不显示名称,不点击聚焦图层);
- 生成中的进行中动画;
- 错误气泡(失败/余额不足,带原因);
- 发送中断:进行中时发送按钮变「停止」,可中断当前回合(已提交的生成任务不追回,照常落画板)。
不做(明确排除,防止后人补齐):
- 点赞/点踩反馈按钮;
- 消息复制、分享/导出对话;
- Agent 模式切换下拉(固定单一 Agent);
- 语音输入、@引用、多 Agent 协作;
- Lovart 的积分/加速档位显示(泥点扣费只在生成动作上体现)。
顺手需求
- 左侧侧边栏默认隐藏:
useImageCanvasEditorChrome.ts中activeSidebarPanel初始值'assets'→null; - 小地图默认隐藏:
isMinimapOpen初始值true→false; - 纯默认值修改,不加 localStorage 偏好记忆。
后端分层落位
module-editor-agent(新 crate):领域规则——会话/消息校验、状态机、附件上限、软删规则、工具清单领域定义;纯逻辑无 IO。spacetime-module:新表editor_agent_conversation+ procedure;同步migration.rs、表目录、生成绑定,运行npm run check:spacetime-schema。spacetime-client:facade 读写方法。api-server:GET/POST /api/editor/projects/{projectId}/agent-conversations(列表/新建);GET/DELETE /api/editor/agent-conversations/{conversationId}(详情/软删);POST /api/editor/agent-conversations/{conversationId}/messages/stream(SSE);- Agent 编排(function-calling 循环、工具内部调既有生成执行链路)放 api-server 编排层,独立文件,不复用
creative_agent.rs内存会话。
shared-contracts+packages/shared:新editorAgentDTO 与 SSE 事件契约(stage、message_delta、tool_started、tool_completed、generation_result、error、done)。
实施顺序
- 契约与领域规则(shared-contracts / packages/shared + module-editor-agent);
- 存储层(spacetime-module 表 + procedure + migration + spacetime-client + schema check);
- api-server 会话 CRUD + 消息 OSS 读写 + SSE 回显桩(不接 LLM,先保证会话链路端到端真实落库);
- 前端最小纵切(对话框、会话管理、消息流、附件弹窗、侧边栏/小地图默认值)——可与 3 并行:3 只碰
server-rs/,4 只碰src/且先以契约 mock 客户端联调,汇合点在 4 末接真实 API; - LLM 编排 + 八类工具接入 + 生成落画板 + 停止/错误态(替换回显桩这一个点);
- 验证与文档:定向测试、类型检查、
npm run check:encoding、git diff --check、npm run check:spacetime-schema、api-server smoke/healthz;同步CONTEXT.md与相关文档。
第一阶段验收补充
- 打开画布 Agent 后,任务侧栏和左侧素材 / 图层面板应关闭;再次打开任务侧栏或素材 / 图层面板时,Agent 面板应关闭。
- 发送消息时先本地追加用户消息,再消费 SSE 增量;停止按钮只中断当前 SSE 回合,不追回已经提交的生成工具调用。
- Agent 消息内生成结果缩略图只用于预览,不显示名称,也不点击跳转图层;收到
generation_result时统一刷新工程快照和素材库。 - 对话内容可被用户选中复制;用户从输入框或对话内容点击回画布图层 / 生成器时,焦点应回到画布对象,Backspace / Delete 等画布快捷键继续生效。