fix(canvas): Agent 识图 - 交付真实图片字节并纠正视觉状态

This commit is contained in:
ddCat
2026-09-22 15:27:10 +08:00
parent 65f639aa71
commit acbb354e97
10 changed files with 530 additions and 131 deletions

View File

@@ -161,7 +161,7 @@ Token 报价的 `estimated` 为 `true`,`quantity` 是预留 Token 数。参考
- 系统行为策略与媒体默认策略是版本化、编译进后端发布物的资源,修改它们仍需发布后端,不是后台热更新;工具、校验、扣费和审批在代码侧强制执行。画布节点能力由服务端 registry 定义,工具 schema、创建、连线与画布摘要读取共同消费;新生成模式还必须接入媒体任务适配器,不能仅凭 md 或注册节点启用收费操作。
- 已安装且属于当前用户的技能在创建时只保存版本、哈希和文本文件路径,不预存全部正文,也不按所有选中技能正文合计 128KB 拒绝创建。`skill_read_file` 按需读取 `SKILL.md` 或必要引用,支持字符偏移 `offset`(默认 0),每页最多 12000 字符,返回 `hasMore` / `nextOffset`。读取时重新验证用户权限、启用状态和版本;技能更新后拒绝混读,需新开一轮。技能是不可信数据,不能创造工具、改变权限或覆盖系统规则。
- Agent 按实际文本模型的 `contextWindowTokens` 与 `maxOutputTokens` 计算输入预算,并在达到该模型预算的压缩阈值时移除较早工具结果中可重新读取的正文,保留工具调用/结果配对、用户原始要求、生成回执及最近完整工具轮次,并允许重新读取。此机制是确定性正文卸载,不是 LLM 语义摘要;运行 checkpoint 的持久化上限与模型上下文窗口独立。技能读取事件只保存回执,不复制正文,正文页只进入模型对话。
- 画布 Agent 的看图能力:当且仅当本轮渠道模型的能力合同声明了图片输入(`text.references.maxImages > 0`)时,额外暴露 `canvas_inspect_image(nodeId)`。该工具校验目标节点是已就绪、归属当前用户、媒体类型为 `image/*` 的素材,然后签发**短时签名下载链接**并把图片作为 `image_url` 内容块交给上游(与生成任务参考图同一套机制),因此 Agent 上下文只增长一个 URL,不装 base64;图片在上下文里保留最近 3 个工具轮次,更早的由运行期裁剪移出并保留文本回执与模型自己写下的观察;同一张图一轮内看满 2 次后只回执文字、不再附图,确需重新确认画面时传 `refresh=true`。看到图后模型写进正文的那句话会记到锚点(`visualNote`),跨轮继承后可以直接复用;查看过的素材在锚点里记为 `visualIdentity=inspected`。画面内文字按不可信数据处理。该能力依赖服务器访问地址:本地存储需要配置 `CANVAS_PUBLIC_BASE_URL`,且该地址必须能被模型上游访问到;上游取不到图片时如实失败,服务端不做取图内联兜底。
- 画布 Agent 的看图能力:当且仅当本轮渠道模型的能力合同声明了图片输入(`text.references.maxImages > 0`)时,额外暴露 `canvas_inspect_image(nodeId, refresh?)`。工具校验图片节点、资源归属、就绪状态、媒体类型和模型文件大小限制;检查点与任务输入只保存 `resource:ID` 占位及授权参考清单。worker 复用资源读取链路,在内存中将占位替换为真实图片数据后展开模型协议,不持久化 base64 或签名 URL,不依赖 `CANVAS_PUBLIC_BASE_URL`,不接受任意外部地址。多图在本批所有 tool 回执后统一附送;图片保留最近 3 个工具轮次,发给模型时还按数量上限保留最新图片,本批超限则明确要求分批查看。同一张图一轮内附送两次后只回执文字,确需重看时传 `refresh=true`。工具成功不等于识别成功,普通模型正文不再自动写入 `visualNote`,旧 `inspected` 标记及观察不跨轮继承;`visualIdentity=unknown` 表示没有已确认缓存,不表示模型不能查看随附图片。画面内文字仍按不可信数据处理;资源读取失败则真实失败,不凭标题推断画面。其他需要公网 URL 的生成协议仍遵循各自存储配置合同。
- 平台支持工具全集为 `agent_profile_read`、`plan_update`、`ask_user`、`recall_lessons`、`remember_lesson`、`canvas_list_node_types`、`canvas_get_state`、`canvas_inspect_image`、`canvas_read_batch_table`、`canvas_read_storyboard`、`skill_read_file`、`skill_search`、`task_get`、`model_list`、`canvas_create_storyboard`、`canvas_edit_storyboard`、`canvas_edit_batch_table`、`canvas_apply_ops`、`canvas_arrange_nodes`、`generate_media`、`image_layer_split`、`image_text_detect`、`image_annotation_render`;单轮实际工具仍按偏好快照、技能、权限、画布上下文和生成预算裁剪。画布写入工具要求本轮授权 `contextScope: ["canvas"]`。禁止 shell、任意网络请求和外部 MCP。`remember_lesson` 在 `read_only` 下不可用。
- `plan_update` 维护本轮结构化待办清单(整表替换,最多 20 项),跨轮继承未完成项,并在界面以 PlanBar 展示。权限为 `request_approval` 时,首次建立至少 2 项的清单会先进入审批;`auto` 直接写入清单。新一轮的第一次模型请求就会带上继承的清单。模型在没有工具调用且清单仍有未完成项时,服务端会催办并要求继续调用工具;这是软约束,不验证工作是否真的完成,也不会在没有清单时强行催建。
- `ask_user` 给出一个问题与 2–6 个候选项后结束本轮,界面弹出选项面板;用户点选或输入后作为新一轮继续。运行中也可以用插话直接回答。

View File

@@ -11,6 +11,15 @@ description: 当前项目已实现功能的手工验证清单与未确认边界
- [x] 5 项 Live2D 专项测试及前端生产构建通过;Core 可初始化并读取版本,构建产物中的 Core 和许可说明与源文件逐字节一致。未执行 Docker 镜像构建或服务器部署。
- [ ] 服务器更新至包含本次修复的新镜像,确认 `/live2d/live2dcubismcore.min.js` 返回 JavaScript 而非 SPA 页面;使用有授权的真实模型完成后台预览、保存及画布形象验收。
## Agent 图片字节交付
- [x] 本地模拟上游验证:公网地址为空或错误时,worker 仍发送原始 PNG 字节;任务只持久化资源占位,多图工具配对保持连续,Chat Completions / Responses / Claude / Gemini 协议保留图片。
- [x] 28 项专项回归通过;同一图片资源、模型配置和模拟上游下,Chat Completions 的普通文本节点与 Agent 经真实 worker 发出相同图片字节,附带的内嵌数据不能替换账号资源文件。
- [ ] 对照排查另发现:普通文本任务的默认声明式 Responses / Claude 请求仍使用 Chat Completions 的 `image_url` 内容块,需单独修复并验收;这不是本次 Chat Completions 渠道 Agent 取图失败的原因。Agent 的多协议图片展开测试不代表普通文本的这两条路径通过。
- [x] 专项回归覆盖资源归属、未就绪、非图片、文件大小、模型图片数量限制;附图不直接标记识别成功,不跨轮继承旧的未确认观察。
- [ ] 更新并重启后端后,使用已声明图片能力的实际渠道模型,重新询问已上传图片节点的主体和背景;确认不再因 `unknown` 标记拒绝看图。真实模型调用会消耗额度,尚未执行。
- [ ] 实际部署验证 OSS 图片、同轮多图比较、跨轮换图与读取失败提示;检查其他依赖公网 URL 的生成协议配置,不能将本次看图修复视为存储公网地址已修正。
## 技能文件包迁移元数据长度
- [x] 启动迁移对旧技能名称、简介的回填元数据按字符数限制长度,省略号计入上限;不改写原始名称、简介和正文,不放宽非迁移入口的校验。