12 KiB
Ygent ↔ WorkBuddy 对话区对标清单
对话区于2026-10-08按用户要求阶段收尾。最新阶段进度汇总已实现、证据边界及剩余工作;本文路线图中的历史状态不能替代当前实现和双端动态验收。
用户要求包含后续流式交互效果一致。当前优先处理 动态交互P0:正文分块、工具增量和取消/迟到事件。旧静态分析及下文路线图不能代替当前版本的双端动态验收。
最新原生验收依据:2026-10-08精确渲染差异清单。下文“已实现/可1:1”是路线图状态,不等于真实窗口验收通过;当前真实样本829条消息,不再适用“几十条消息”的规模假设。
状态:路线图与实现状态(2026-10-08) 依据:WorkBuddy
lib-chat-ui静态分析(2070 个 i18n 键 + 组件 props)、OMP 协议文档 口径:对标可见对话区及 Ygent 已有数据能支撑的交互;平台级分享服务、朗读和消耗体系不复制
结论先说
能做到接近 1:1,但「1:1」要分开看两层:
| 层 | 判断 |
|---|---|
| 渲染与交互层 | 待双端动态验收;需要前端与事件协议/持久化共同调整,当前数据缺reasoning、工具增量映射等,不能认定纯前端即可完成 |
| 能力语义层(消息编辑/回退/排队/压缩/分页) | 🔧 OMP 已提供核心协议,Ygent 按交互逐项接入;编辑重发已接通 |
| 产品体系层(敏感保护/IM/插件/积分/媒体生成) | ❌ 不对标,需要 WorkBuddy 那种平台规模 |
最重要的一个判断:高级对话交互并非不可对标,OMP 已提供多项底层能力,差别在 Ygent 是否完成接线与状态建模;本轮已接通消息编辑后的分支重发。
A. ✅ 可 1:1(纯渲染层,Ygent 数据已够)
| 能力 | WorkBuddy 证据 | Ygent 现状 |
|---|---|---|
| 对话顶栏与工作台 | 搜索、分享、最近任务、任务概览、右侧工作台 | 顶栏入口已实现;工作台正在按当前 WorkBuddy 的标签容器接入真实目录、文本预览和 Git 变更。内嵌浏览器、终端、富文档与来源区尚未完成,详见 工作台进度 |
| Markdown 段落/列表/引用/表格 | markdown.* |
✅ 已有 |
| 表格悬浮「添加到对话」 | .cr-message-quote-table-menu |
✅ 悬停菜单按 116×38px 规格实现;点击后将原始 Markdown 放入输入草稿 |
| 代码块:语言标签 + 复制 | markdown.copy/copied |
✅ 本轮已做 |
| 图片渲染 | — | ✅ 已有 |
| mermaid 流程图 | mermaid.*(12 键) |
✅ 已有按需渲染和源码回退 |
| KaTeX 公式 | markdown 域 |
✅ 已有按需加载 |
| 交互式 widget | show_widget / widget.* |
⚠️ 已加入 sandbox iframe、尺寸上报、CDN 白名单与独立时间线段;1200×762 实窗核对后,卡片宽度与时间线一致,参照 SVG 的 iframe 仍有 5px 高差 |
| 代码 diff(改文件时) | tool-diff 组件 |
✅ write/edit 参数可展开查看 |
| 消息悬浮工具栏 | message.* |
⚠️ 用户气泡下方支持时间、复制、编辑;OMP/直连支持编辑后分支重发,Codex 仍只保留草稿 |
| 助手身份与回合完成耗时 | .cr-agent__header / metaFold.turnCompletedWithDuration |
✅ 导入参照会话按来源显示 WorkBuddy 名称与头像;普通会话显示 Ygent;含工具的已完成回合默认收起过程,可展开 |
| 全局字号 | 六档字号级别 / WorkBuddy 字号滑杆 | ✅ 设置中提供 1–6 级离散滑杆;Markdown 根字号逐档匹配,常规控件偏移在第 5、6 档封顶为 +2px |
| 消息状态:思考中 | message.loading.thinking |
✅ 本轮已做 |
| 消息状态:已中断 | message.interrupted / userCancelled |
⚠️ 有「已停止生成」,可对齐文案 |
| 消息状态:未发送 | message.notSent / notSentFailed |
⚠️ 同步接收失败时保留输入并回滚用户记录;已接收后的异步服务错误仍显示在时间线 |
| 消息时间 | message.time.* |
⚠️ 用户消息悬浮时显示时分;相对日期待做 |
| 空会话占位 | message.empty |
✅ 本轮已做 |
| 滚动到底部 | action.scrollToBottom |
✅ 自动跟随 + 手动回底按钮 |
| 加载更多(历史分页) | message.loadingMore + get_messages_page |
❌ 见 B 类 |
| 工具卡状态 + 回合折叠 | metaFold.*(132 键) |
✅ 连续工具组按正文/回合结束折叠;回合完成行可收起/展开过程;show_widget 独立保序 |
| 结构化错误 | errorBanner.*(16 键) |
⚠️ 有简易错误占位,可增强 |
B. 🔧 可对标 —— 高阶交互与接通状态
这一组是重点:OMP 协议提供基础能力,Ygent 正在逐项接入。
| 能力 | OMP 命令(已存在) | Ygent 要做的 |
|---|---|---|
| 编辑用户消息并重发 | branch { entryId } |
✅ OMP 持久 entryId + 独立子会话;直连按选中消息前的历史重放;Codex 暂不支持 |
| 回退到某条消息 | fork { entryId } |
仍待实现:任意历史点回退及分支切换 |
| 忙时消息排队 | steer / follow_up / set_follow_up_mode |
输入框在 pending 时允许发送并排队;队列 UI(messageQueue.* 11 键可参考) |
| 队列项操作(编辑/删除/立即发送) | remove_queued_message / promote_queued_message |
队列条 UI |
| 上下文压缩提示 | compact / set_auto_compaction |
对话内系统事件流(conversationEvent.contextCompaction.*) |
| 历史分页(加载更多) | get_messages_page(游标 + session_busy/stale_cursor) |
list_messages 改分页 |
| 模型切换提示 | 已有 set_model |
对话内事件条(conversationEvent.modelChange.*) |
| 权限能力清单(文件/互联网/终端三档确认) | — | Ygent 已有 grants / audit_log,扩展成能力清单即可 |
conversationEvent这一组(12 键)揭示了一个 Ygent 完全没有的概念:对话内的「系统事件流」——压缩、历史更新、模型切换、会话边界都作为一类非消息事件渲染在时间线里。这是个值得单独设计的东西。
C. ❌ 不对标(Ygent 无对应能力 / 平台级)
| 能力 | 为什么不列 |
|---|---|
| 平台分享链接、朗读(TTS)、消耗/积分 | Ygent 提供本地选择、复制和 Markdown 导出;不接 WorkBuddy 的外部分享服务与平台权益体系 |
IM 接入(im.* 159 键) |
WorkBuddy 是 IM 客户端,Ygent 不是 |
插件系统(plugins.* 109 键)、MCP(mcp.* 68 键) |
平台规模能力 |
企业版标识、模型积分速度(model.badge.enterprise / credits.*) |
商业化体系 |
敏感内容保护(sensitiveProtection.* 15 键) |
需要凭据检测 + 出入站拦截,是平台级安全能力 |
媒体生成(mediaGeneration.* 11 键) |
Ygent 无此能力 |
计划编辑器的设计配置(planEditor.designConfig.*) |
面向建站/设计场景,Ygent 无 |
沙箱相关(sandbox.* 35 键) |
Ygent 用项目工作目录做边界,模型不同 |
D. ⚠️ 不建议对标(Ygent 规模不需要)
| 能力 | 原因 |
|---|---|
| 虚拟列表 | Ygent 消息量是「几十条」量级;已有块级 memo 缓存 |
widget 分组(presentationGroupId) |
widget 已独立渲染并保序;把解释正文与 widget 绑定成组仍待实现 |
| mermaid 完整查看器(缩放/平移/明暗主题切换/下载 SVG·PNG) | 先做「能渲染 + 失败回退代码」;查看器后置 |
队列上限/超时/升级提示(queue.banner.*) |
商业化限流逻辑 |
建议的推进顺序
按「投入产出比」排(✅ = 已完成):
- ✅ 工具折叠与时间线保序 —— 普通工具折叠,widget 作为独立段保持原位
- ✅ mermaid + KaTeX —— 均按需动态加载
- ✅ 工具改动 diff(write/edit 卡)—— 使用工具帧
args - ⚠️ 消息工具栏与 widget —— 编辑后分支重发已接;仍需真实窗口截图核对 widget
- ⚠️ 消息编辑 + 回退(接
branch/fork)—— 编辑重发已接;任意历史点回退与分支切换待做 - ⬜ 忙时排队(接
steer/follow_up)—— 内核已验证可用,但前端有前置依赖,见下 - ⬜ 对话内系统事件流(压缩 / 模型切换 / 会话边界)—— 需要新概念,建议单独设计
第 6 项的前置依赖(实测发现)
内核侧已经可用。探测结果:流式进行中再发一条
{ "id":"p2", "type":"prompt", "message":"再说一句:收到", "streamingBehavior":"followUp" }
→ success: true,随后收到 queue_update 帧,且第二条的 prompt_result.status = "completed"。
但前端不能只加一个参数就接。 OMP 把排队的 follow-up 视为同一次 run 的延续(在下一次 yield 时汇报), 而 Ygent 现在只有「一条用户消息 → 一个 agent 气泡」的模型,没有回合边界概念 —— 直接接会导致两条回答被合并进同一个气泡。
所以第 6 项的真实依赖是:先补回合边界处理(映射 OMP 的 agent_start / agent_end 事件来切分气泡),
再接 streamingBehavior,最后才是队列 UI(排队标记 / 编辑 / 立即发送)。
建议与第 7 项(系统事件流)一起做 —— 两者都需要「对话内事件」这条通道。
落地时的关键发现(实测)
工具帧里有大量此前被丢弃的信息。 探测 omp --mode rpc-ui 的原始帧:
// tool_execution_start —— 带完整参数与意图
{ "type":"tool_execution_start", "toolCallId":"call_…", "toolName":"write",
"args": { "path":"note.txt", "content":"alpha\nbeta\ngamma\n" },
"intent":"Creating requested note" }
// tool_execution_end —— 带显式失败标记(start 帧没有 args,end 帧没有 args)
{ "type":"tool_execution_end", "toolCallId":"call_…", "toolName":"write",
"result": { "content":[…], "details": { "resolvedPath":"…" } }, "isError": false }
由此得到三条:
args可做代码 diff ——write有content(整份新增),edit有old_string/new_stringisError可准确区分成功/失败 —— 之前靠「result 是否为空」推断是错的(见toolState那次修复)intent可作工具卡副标题 —— 模型自己说明这次调用要干什么
注意 args 只在 start 帧下发,end 帧没有 —— 前端必须记住并在落库时用回来(stores/chat.ts 的 toolCards map)。
mermaid 必须关掉 htmlLabels。 mermaid 默认用 <foreignObject> 承载节点文字,而消毒配置禁掉了 foreignObject(它能把 HTML 塞进 SVG 绕过 SVG profile),结果是「框画出来了但文字全丢」。设 htmlLabels: false(顶层 + flowchart + class)改用原生 SVG <text>,两全其美。
剩余纯渲染层的工作可继续推进;消息编辑已建立独立子会话与持久内核 entry 映射,任意历史回退仍需单独补充分支选择与恢复界面。
一句话
渲染层能 1:1;高级交互也能 1:1,因为 OMP 内核已经支持
branch/fork/steer/compact/get_messages_page,缺的是 Ygent 侧的接线;真正不能对标的是 WorkBuddy 的产品体系(IM、插件、MCP、积分、敏感保护、媒体生成)。