chore: establish YCode replication baseline and TODO
No files matched your search
@@ -0,0 +1,94 @@
|
||||
# WorkBuddy 1:1 复刻重新评估
|
||||
|
||||
> 本文是实施前的评估快照。后续实际实现和验证见 [复刻进展](复刻进展-2026-10-15.md);源码差距表保留当时状态,不作为最新完成度。
|
||||
|
||||
日期:2026-10-15。目标版本:本机 WorkBuddy 5.8.2。原版查看全部通过 REA;YCode 源码通过正常项目工具检查。本轮只评估,不改变用户的 1:1 目标,不改产品代码。
|
||||
|
||||
## 判断
|
||||
|
||||
**不能承诺完整产品的无条件 100% 等价;可以将固定版本、固定环境下的客户端视觉及确定性交互作为严格 1:1 的实施和验收目标。**
|
||||
|
||||
当前证据支持继续重建客户端,尚不足以证明全部功能都可原样实现。尤其是原生编辑/沙盒、服务端行为及模型输出,需要分别补证据或获得对应服务能力。它们不能通过完善界面或接入 OMP 自动解决。
|
||||
|
||||
“可实施”是工程判断,尚不是已经通过验收。没有依据提供整体完成百分比或精确工期。
|
||||
|
||||
| 1:1 的对象 | 本轮判断 | 条件及限制 |
|
||||
| --- | --- | --- |
|
||||
| 固定版本的客户端视觉 | 可作为严格目标推进,当前未验收 | 固定 OS、Electron/Chromium、DPR、窗口尺寸、字体、主题、字号、数据及滚动位置;需通过 REA 获取可比较的像素样本 |
|
||||
| 确定性交互:菜单、选择、编辑、折叠、滚动、取消、恢复 | 可逐场景实现和验证 | 需要完整状态与错误分支证据;只比最终截图不足以验证 |
|
||||
| 本地 Agent 功能与流程 | 有条件可重建;尚未证明完整等价 | 逐项还原工具契约、权限、提问、子任务、扩展、上下文及生命周期;OMP 需要适配与差距验证 |
|
||||
| 模型的每次文字回答、工具选择及耗时 | 当前不能保证逐次相同 | 同一提示不等于相同模型版本、提示词、上下文、路由、采样和调度条件;模型生成还可能具有随机性 |
|
||||
| 官方账号、权益、订单及其他服务端业务结果 | 仅靠客户端证据不能还原官方事实 | 可以实现自己的同类服务;接口形状不包含官方后台状态及完整实现,mock 不构成等价 |
|
||||
| 原生编辑器与沙盒行为 | 本轮未知;需单独评估 | 观察到相关原生组件存在,未完成其接口、文件兼容性、权限边界与失败模式验证;不能用体积推断不可能或容易 |
|
||||
| 所有环境、全部隐藏分支、未来版本 | 不能据有限证据作全局等价承诺 | 验收应针对明确版本和覆盖范围;版本变化后需重新对比 |
|
||||
|
||||
## 旧评估中需要撤回的推理
|
||||
|
||||
1. **“1:1 等于复制原始源码”不成立。** 本项目的工程目标是用户可观察的视觉、交互及功能一致;实现代码可以不同。源码逐字节一致是另一个要求。
|
||||
2. **“没有 source map / 名称被压缩,所以不能复刻”不成立。** 这会增加理解和重建成本,不自动否定可观察行为的重建。
|
||||
3. **“原生组件数百 MB,所以不可能重建”证据不足。** 文件体积不等于业务复杂度;应按实际接口、行为覆盖和兼容性要求判断。
|
||||
4. **“本机没配置反编译器,所以永久做不到”不成立。** 工具配置是当前条件,不是不可改变的技术定理。本轮也未重新确认全部 native provider 状态。
|
||||
5. **“排除官方云就没有 AI 能力”过度推断。** 可以连接自己的模型服务并提供 AI 功能,但不因此获得原版模型与业务结果的等价保证。
|
||||
6. **“依赖清单或字符串足以证明原版 Agent 循环来自某 SDK/产品”证据不足。** 依赖存在不等于该调用路径实际承担主循环,需要追踪和运行时证据。
|
||||
|
||||
上一轮接手确认了用户目标并收尾取消问题,没有完成全产品可行性验证。不能把“接受 1:1 目标”当成“已证明可以全量 1:1”。
|
||||
|
||||
## 本轮新增原版证据
|
||||
|
||||
复用先前 ASAR 身份与清单:SHA-256 `035254bc76310ea46317433e4840602094543ef323d2d5c5aff7c131729de918`。
|
||||
|
||||
REA 本轮选择分析了:
|
||||
|
||||
- `main/index.js`
|
||||
- `renderer/assets/account-9NjO6QCF.js`
|
||||
- `renderer/assets/conversation-CmigeZ37.js`
|
||||
- `renderer/assets/charge-user-api-BAFEErUh.js`
|
||||
- `renderer/assets/permission-preference-service-BrHJCEMO.js`
|
||||
|
||||
5 个 JavaScript 文件均解析成功,遍历 107909 个 AST 节点;观察到 3 个 BrowserWindow 语法记录及 52 个 IPC 操作,其中有动态通道。**这些是静态语法观察,不能写成“运行时创建了 3 个窗口/调用了 52 次 IPC”。**
|
||||
|
||||
| 证据 | 实际支持的结论 |
|
||||
| --- | --- |
|
||||
| 父分析 `ev_1c590592d84ebb5e65c68816bbfc7c5da005c9b4fb427f96c31f7dbabf0f2ce8`;摘要 `ev_cb9e8d4498e2ab57130dc066d826f83bfef643a56ee7269bd55adc1b9a1cacdc` | 选定文件可进行 AST 分析;其余 11384 个文件未分析;语义图受本轮 8000/12000 节点预算限制,覆盖不完整 |
|
||||
| 账户模块视图 `ev_864d3c1f1d64164133eae079565619f92f6f8fe42daef515a4a5e7759086ff02` 及导出观察 | 存在账户组件及 CreditsMenuItem / EditionBadge 的静态导出,不能据此声称已还原官方账号行为 |
|
||||
| 权限模块视图 `ev_d01df66f6751a3ec47ba5b7dfddbe4fbd109cb49627618577f1e2adbe0558d1b` | 存在 ConversationPermissionPreferenceService 的静态导出;完整权限执行机制尚未验证 |
|
||||
| 权益模块追踪 `ev_cdeb75ab51d531dcc460f74ee0563f5c939429fb4e6906d6e635fafbf6c5f691` | 存在 checkEntitlement / getOrderStatus / refundOrder 等导出及订单/权益返回字段的静态候选;字段值、服务器逻辑和实际调用仍未知 |
|
||||
| 先前被动 Electron 观察 `ev_07b84c62b706541456e7415ae6d886bc0b3e8e98f1fbf3456e29ba12cb46db9b` | 可通过 REA 读取当前 file 页面结构及脚本元信息,不等于取得了像素与 computed style |
|
||||
|
||||
选定证据投影保存在 `.tmp/rea-reassessment-selected-evidence-2026-10-15.json`;它不是完整 Evidence bundle。
|
||||
完整原始分析仍保留在 REA 会话,前一轮清单 bundle 位于 `.tmp/rea-workbuddy-takeover-2026-10-15.json`。
|
||||
|
||||
## REA 的当前验证边界
|
||||
|
||||
- `list_electron_targets` 和 `inspect_electron_page` 对当前原版 file 目标可用。
|
||||
- 本轮对同一目标调用 `capture_web_screenshot`,返回 `target_unavailable` / `reason: target_not_allowed`。**原版结构观察已打通,像素截图验收尚未打通。** 不能绕过用户约束去运行直接 CDP 脚本。
|
||||
- ASAR 伴随原生文件有完整性声明与实际摘要不符的记录。本轮使用 `record-and-continue` 保留矛盾分析,不能推断其原因或具体功能故障。
|
||||
- 对通用 `url` 属性的语义追踪完成后超出 MCP 传输预算;对应保留证据为 `ev_239628541386759af69e1a3b16f07d1a5ba84759264f73a43698b63edb22acb9`。本轮没有消费该完整结果,不将其用于端点或服务器实现结论。
|
||||
- 没有运行原版业务动作、登录、提交订单、读取凭据或重启原版;没有重新验证 CLI 全部代码、原生组件或官方云实现。
|
||||
|
||||
## 当前 YCode + OMP 能否直接达到目标
|
||||
|
||||
**当前实现不够;继续只补 CSS 和转发 OMP 文本流,达不到完整交互与功能 1:1。** Electron/React 壳层可以保留,状态与协议层需要扩展。
|
||||
|
||||
| 源码事实 | 对目标的影响 |
|
||||
| --- | --- |
|
||||
| `src/shared/types.ts`:ChatMessage.content 是字符串;ChatEvent 只有 started/text/tool_call/tool_result/done/cancelled/error | 无法直接表达审批、用户提问、结构化内容块、产物、子任务等丰富状态;应先扩展领域模型再接渲染 |
|
||||
| `src/main/agent/omp-turn.ts`:只映射 text_delta、三类工具事件和终态;其他事件忽略 | 不能把“OMP 已支持”当成“YCode 已支持”;需要逐项核实内核能力和适配映射 |
|
||||
| 同文件:工具结果摘要限制 600 字符;工具状态只有 running/ok/error | 全量输出、取消中工具、审批、结果产物等需另建数据结构;不能靠摘要完成完整结果交互 |
|
||||
| `src/main/omp.ts`:固定 ycode profile、进程使用 --no-session;`ipc.ts` 的 OMP 分支只发送当轮文本 | 本地保存的消息尚未重新灌入新内核;会话恢复后的模型上下文可能与 UI 显示分离 |
|
||||
| `src/renderer/src/stores/chat.ts`:单一 running 状态,运行中拒绝切换/新建/删除 | 当前前端限制并行会话;原版实际并行语义尚需 REA 复核,不能提前宣称一致 |
|
||||
| 账号/通知/空间及多个入口仍为 mock 或提示;正文纯文本 | 表面具备入口不代表对应功能已实现 |
|
||||
|
||||
另有两项可靠性风险:`OmpKernel.handleLine` 将带关联 id 的响应发到 `frame` 后返回,而适配器只监听 `event` 并仅检查 prompt ack 的 `success === false`;如果终态只出现在关联响应中,就可能漏处理。当前也没有回合级终态等待超时,abort 响应/失败被忽略;若没有后续终态事件,界面可能一直运行。是否触发这些风险需 OMP 协议及运行时复核。
|
||||
|
||||
本轮审计的是 YCode 适配器,没有证据证明 OMP 本体必然无法提供这些能力,也没有证据证明它可以不经扩展完整承接。暂不作换内核或推倒重写决定。
|
||||
|
||||
## 继续实施前的验收关口
|
||||
|
||||
1. **客户端参照**:通过 REA 获取固定版本、固定环境的原版截图/状态样本,补齐当前像素采集缺口;为每个页面和关键交互列出参照。
|
||||
2. **对话协议**:原版文本→工具→审批/提问→取消→恢复等流程建立事件与状态样本;YCode 扩充消息块、工具状态、产物和会话生命周期,再用确定的输入/模型响应重放验证。
|
||||
3. **内核差距**:逐项映射原版能力与 OMP 的实际接口;已支持就适配,未支持就实现扩展,再决定是否需要其他内核。
|
||||
4. **外部与原生能力**:账号、模型、同步、文档、沙盒等分别评估可接入服务/自建实现/未知边界;不得将替代实现或 mock 标为原版等价通过。
|
||||
|
||||
如果要求“自主运行、所有官方功能和每次 AI 结果都与原版完全相同”,当前结论是**不具备可承诺的可行性**。
|
||||
如果验收对象是明确版本与环境下的完整客户端视觉、确定性交互及逐项定义的功能契约,结论是**可以继续严格推进,但需要补证据与实现,不能宣称已证明全量可行**。
|
||||
@@ -0,0 +1,96 @@
|
||||
# WorkBuddy 1:1 对标:长任务评估与执行基线
|
||||
|
||||
用户最新范围:先评估同会话的实际效果,再准备新建任务交互、自定义模型添加、空间、右侧工具栏的 1:1 长任务。自定义模型使用用户自己的上游,不接 WorkBuddy 服务端模型;此前暂后的云服务与子代理调度继续暂后。本轮只评估,未修改生产组件、已导入会话或用户配置,未创建后台长任务/定时任务。
|
||||
|
||||
## 结论
|
||||
|
||||
可以推进,但这是跨会话状态、模型配置、工作目录归属和右侧工作台的中大型客户端改造。已取得相关主脚本、模型表单 JS/CSS 和关键实际画面;主要阻碍转为实现缺口与验收覆盖,而非拿不到原版 CSS。
|
||||
|
||||
此前的局部正文像素结果、源码恢复、导入回读和 fixture 通过,只覆盖各自声明范围。新导入会话的校验证明内容已加载,未证明其取消语义、工具规范化、消息投影或整页显示与原版等价。本轮已发现会显著改变整页效果的具体问题。
|
||||
|
||||
## 实际对照
|
||||
|
||||
两端会话同为「开始新会话」,来源 `4653e36f-6b2a-446f-a9c9-3f2d2d04644e`,YCode 副本 `6c000be8-b0e8-4768-9a7f-1a0d94a35951`。都以 1336×901、浅色、右栏打开观察最后一轮;截图是各端现状,没有人为改正文、折叠状态或列宽来掩盖差距。
|
||||
|
||||
对照图:[原版 / YCode 同屏对照](../.tmp/assessment-comparison/same-conversation.png)。YCode 运行配置值在拼图中遮挡;原始采集留在本机。
|
||||
|
||||
| 已确认问题 | 证据与影响 | 优先级 |
|
||||
| --- | --- | --- |
|
||||
| 取消被导为 error | 6 轮 `Interrupted by user` 被同时保留为正文和 error;原版 provider 明确投影为取消。最后轮原版「已取消 17m15s」且过程闭合,YCode 展开历史并重复报错 | P0 |
|
||||
| 终态折叠门控不完整 | 7 个 error 轮不进入完成投影,summary 还被标为运行中。最后轮当前 21 个根渲染单元,终态诊断为 2 个正文锚点和折叠;其他历史轮需逐轮实拍确认 | P0 |
|
||||
| 工具名规范化缺失 | 47/691 次调用走通用兜底:TaskCreate/Update、DeferExecuteTool、present_files、大写 AskUserQuestion。其余命中专用 renderer 也不代表已验收 | P0 |
|
||||
| 产物没有形成所属会话/回合入口 | 原版本轮展示 13 个产物及「查看所有产物」,当前仍缺相应聚合、标签和导航;来源有 21 条文件引用,不能直接等同于 21 个最终产物 | P0/P1 |
|
||||
| 主布局和右栏结构不同 | 当前采样原版中栏约 526.7px、右栏 525px;YCode 中栏 409px、右栏 647px。原版是标签工作台,YCode 是环境统计页,正文换行也随列宽改变 | P1 |
|
||||
| 正文间距与消息尾部仍不完整 | 原版正文有 both/top/bottom 间距规则;YCode 仍按索引统一顶距。头像、操作栏、模型/用量、取消说明和产物区等还需统一恢复 | P1 |
|
||||
|
||||
第 31 轮耗时 17m15s 已与原版一致,不再列作差距。357 条 reasoning rawContent 有原始文本结构,但原版历史是否以及如何显示尚需复核,不能盲目全部显示或宣称已经对齐。
|
||||
|
||||
## 五个范围的真实基线
|
||||
|
||||
| 范围 | 当前 YCode | 目标与工作规模 |
|
||||
| --- | --- | --- |
|
||||
| 同会话效果 | 已有正文、工具、Diff 和附件基础;导入/投影仍有上述结构错误 | 先恢复显示语义,再统一布局/间距/图标/状态。中到大 |
|
||||
| 新建任务 | 点击即落盘空 session,首页场景/推荐有 mock | 原版首页草稿独立,首条提交才创建任务,绑定目录、模型、模式和权限;含附件、IME、失败重试、导航草稿。大 |
|
||||
| 自定义模型 | 单一旧网关配置,不能代表当前 OMP 生效模型;缺多模型管理 | 模型列表、添加/编辑、覆盖确认、测试、删除、能力和 token 配置;UI、持久化及实际请求目标一致。大 |
|
||||
| 空间 | 固定 MOCK_SPACES;会话无独立 workspace/cwd | 本地工作区创建/目录选择/分组/重命名/删除语义、任务归属、切换恢复与路径正确性。大 |
|
||||
| 右侧工具栏 | 自制运行统计占位,预览能力另有基础 | 原版多标签、文件树、变更、产物、预览、浏览器、终端,含拖动宽度与会话恢复;宿主浏览器/终端是新增能力。很大 |
|
||||
|
||||
这里的「空间」首先是侧栏本地工作区。团队知识库/云文档、登录、分享和云同步另有服务体系,不将它们混入本地空间完成度。
|
||||
|
||||
## 长任务依赖与批次
|
||||
|
||||
统一的数据关系应先明确为 `工作区 → 会话 → 回合/消息 → 产物与右侧标签`;任务保存模型标识和有效配置,执行前由同一解析入口生成 OMP/后备路径配置。右侧读取会话所属目录,避免沿用一个全局 workspace 导致跨空间串目录。既有会话和配置需要迁移与回读,不能通过清空数据获得新界面。
|
||||
|
||||
| 批次 | 工作与依赖 | 完成门槛 |
|
||||
| --- | --- | --- |
|
||||
| 0:证据与场景账本 | 固定当前原版版本、会话、截图、源码摘要;补取消/429/工具/产物等展开状态与字体、窗口条件 | 每个场景有原版 Evidence、输入、预期行为和未知项;不把静态分支当动态通过 |
|
||||
| 1:修正同会话效果 | 取消/错误归一、provider 工具规范化、消息投影、产物映射、正文间距;复用已有源渲染器 | 此会话最后轮默认显示、6 取消轮及真实 429 分别正确;47 个回退调用逐类消除,原正文/输出/图片不丢失 |
|
||||
| 2:统一归属与配置 | workspace/session/model 引用、历史数据迁移、有效模型解析、panel session 状态;主上下文统筹接口 | 切换两个空间及会话不会串目录、模型、草稿、附件或标签;旧数据回读一致 |
|
||||
| 3:新建任务与空间 | 首页草稿、场景、选择目录/空间/模型/权限、首次提交创建、防重复/失败重试;真实空间 CRUD | 从首页到首轮执行实际走通;取消创建不产生空任务,创建失败保留输入,空间操作副作用符合已采原版契约 |
|
||||
| 4:自定义模型 | 本地多模型/凭据存储、源码表单/列表/选择器、验证与覆盖/删除确认、连接测试和 OMP 接入 | 测试不保存,保存重启有效;选定模型实际生效,上游使用用户配置;鉴权/超时/失败可复现,运行中切换契约明确 |
|
||||
| 5:右侧工作台 | 先标签/布局/会话恢复,再文件树/变更/产物/预览,最后浏览器和 Windows 终端宿主;已有 Pierre/图片/HTML 预览复用 | 入口有真实内容和行为,多标签及切换/关闭/恢复正确;不能用按钮占位或静态输出代替浏览器/终端 |
|
||||
| 6:整体验收 | 按相同会话/视口/布局/字号/字体/滚动锚点/折叠状态做截图与行为对照,覆盖明暗/宽窄/长文本/错误/动效 | 必要状态逐项验收,修复差异后复验;构建、fixture、真实 IPC 与原版对照分别记录 |
|
||||
|
||||
批次 3、4、5 的 UI 和局部宿主能力可以在批次 2 的接口固定后有边界地并行。最终集成、迁移、跨模块状态和真实验收由主上下文负责。每批应保存可接手的完成/未完成/证据/下一步,长任务中断后从账本继续。
|
||||
|
||||
## 必须覆盖的验收状态
|
||||
|
||||
- 对话:正常完成、6 个取消样本、429、工具等待/运行/失败/取消、问答回放、长输出、产物跳转、历史恢复、字体与正文间距。
|
||||
- 新任务:进入不创建、重复点击、草稿往返、目录/空间切换、模型/权限选择、附件、多行/IME、首条发送、防重复、失败重试、重启恢复边界。
|
||||
- 模型:空列表、添加/编辑、必填与 URL/Key 校验、重复 ID 覆盖、能力与 token 值、测试中/成功/鉴权失败/超时、保存失败、删除选中模型、重启和实际运行。
|
||||
- 空间:空/多空间、创建名称、目录已存在/不可用、重命名、带关联任务的删除、排序与紧凑模式、会话归属、切换时后台任务不受误操作影响。
|
||||
- 右栏:开/关/拖动宽度、不同标签内容、关闭当前/其他/右侧标签、文件与产物同路径去重、切会话恢复、预览过期、空/失败/大文件、浏览器和终端实际宿主生命周期。
|
||||
|
||||
目标是各状态的视觉与交互 1:1。对不可调用的原版云分支,明确记录服务依赖及未验收范围,不伪造成功,不把整项目降级成 mock。
|
||||
|
||||
## 新增原版采集与范围
|
||||
|
||||
全程通过 REA 公共入口,原版未执行创建任务/空间、添加/修改/删除模型、连接测试或终端命令;仅打开页面/空表单观察并取消,设置窗口已关闭,原会话已恢复。
|
||||
|
||||
| 场景 | Evidence | 本机产物 |
|
||||
| --- | --- | --- |
|
||||
| 同会话/右侧工作台 | `ev_d6e6920ff4e47f73a182fac5312c5f02393366a035445d18c8a6733a8c8a11ed` | `.tmp/rea-assessment-initial/` |
|
||||
| 独立设置窗口 | `ev_2309de12a003fca2c863a223cbda5bccad36b3af73e29bc309fdaed94745cf9e` | `.tmp/rea-assessment-settings-window/` |
|
||||
| 自定义模型列表 | `ev_40da6df0424193923bae64a8ccb6fca97ea67813d7de671986d4d7e154b848c1` | `.tmp/rea-assessment-models/frame-000.png` |
|
||||
| 模型添加空表单 | `ev_45d3e5c9b0b0961cb58c9628598c8a777569c83062a0e8fe9c3d5f435e394632` | `.tmp/rea-assessment-model-add/frame-000.png` |
|
||||
| 模型表单 JS/CSS | `ev_25f013c9fd2ad66153046eec06e94fb6128bfacc1e87e57aa90db6bc419075ec` | `.tmp/rea-assessment-model-source.json` |
|
||||
| 创建本地空间空表单 | `ev_1e096ecf360249286260ceef24f1195919b8f1cbae8dd81751a2e36eb631bab2` | `.tmp/rea-assessment-create-space/frame-000.png` |
|
||||
| 新建任务首页 | `ev_5c3eb3e638af074b017eb8f96ce3e90464d8e2a8ca3e6978cc202a7c36374283` | `.tmp/rea-assessment-home/frame-000.png` |
|
||||
| 原会话恢复 | `ev_84d140d762fe4f59ebca649da52bcbe7c85778842941a9603fabdde21c260344` | `.tmp/rea-assessment-restored/` |
|
||||
| 恢复后稳定状态 | `ev_43441ee1f76b15e3482ed305ebefa4ac82a2131fe29ea0ba0c387596d3c7129c` | `.tmp/rea-assessment-final-state/` |
|
||||
|
||||
模型表单已取得完整正文:重复 ID 覆盖确认、Key 去空白及字符校验、测试不保存、token 快捷值和能力区条件都已明确。实际协议请求层、删除选中模型与运行中切换等仍需长任务内动态验证。不是继续等待 CSS 或表单源码。
|
||||
|
||||
采集脚本仅补 `--target-id` 来区分同文件路径的主窗口和设置窗口;原版所有协议交互仍由 REA 执行。关闭设置窗口的那次 capture 因目标关闭返回失败,随后 REA 目标列表确认只剩原主窗口;不把该次失败计作成功截图。
|
||||
|
||||
YCode 双布局实拍见 `.tmp/assessment-ycode/`。截图条件只对齐视口/主题/会话,尚未完全控制两端 GPU、字体、布局与折叠状态,不输出整页像素差异百分比,也不复用此前单段正文的零差异来证明当前整页通过。
|
||||
|
||||
原会话重新进入后的稳定原版状态已确认无 skeleton;其右栏宽度变为 360px,中栏约 691.7px。首次比较使用之前的 525px 右栏状态。两次均是实际观察,不能把 525px 硬编码为原版固定宽度;长任务应查明导航、默认比例、拖动与布局恢复的状态契约。
|
||||
|
||||
## 分项报告
|
||||
|
||||
- [对话数据与投影审计](assessment-chat-projection-2026-10-15.md)
|
||||
- [新建任务与自定义模型](assessment-task-models-2026-10-15.md)
|
||||
- [空间与右侧工作台](assessment-space-tools-2026-10-15.md)
|
||||
|
||||
评估已形成可执行批次和验收门槛。完整工时依赖终端/浏览器宿主、协议接入和动态状态补证,不给未经验证的完成百分比或小时承诺。
|
||||
@@ -0,0 +1,64 @@
|
||||
# REA CSS 正文采集修复
|
||||
|
||||
> 后续已升级本地副本至 `6.5.0-visual.1`,补齐 PNG、计算布局和 SVG 采集,开始实际接入对话组件;见 [对话样式与调试画面采集](对话样式实对齐-2026-10-15.md)。下文保留 CSS 首次修复结果,旧的问答选择器、计算样式和截图阻塞已推进解决。
|
||||
|
||||
当前已通过本地修复版 REA 取得 WorkBuddy 已加载的 CSS 正文。原来的阻塞是 REA 6.5.0 Electron provider 没有实现样式正文采集,而不是调试连接不可用。此结果解除当前已覆盖组件的 CSS 正文获取阻塞,不代表 YCode 界面已完成 1:1 对齐。
|
||||
|
||||
## 实测结果
|
||||
|
||||
- WorkBuddy 5.8.2 / Electron 37.10.3 / Chrome 138.0.7204.251;既有端口 `http://127.0.0.1:9223`,页面 `WorkBuddy/resources/app.asar/renderer/index.html`。
|
||||
- 本地 REA `6.5.0-css.1`,provider `rea-cdp-electron` / `1+css-local.1`。这是基于已安装 6.5.0 编译模块的本地修复,**不是上游正式发布版本,也不是恢复了 REA 的原始 TypeScript 工程**。
|
||||
- 实际 REA Evidence:`ev_377c8790468b3c67dad8577aabb327f98d3140659f0fffdbabfcff5a40cc9e94`,归档 `.tmp/rea-css-evidence/ev_377c8790468b3c67dad8577aabb327f98d3140659f0fffdbabfcff5a40cc9e94.json`。
|
||||
- 观察到 65 张样式表,64 张正文读取成功,1 张因来源或 frame 范围不符排除;读取失败 0,未触发截断。64 份合计 **5,946,566 UTF-8 字节**,其中 63 份文件样式、1 份内联样式。
|
||||
- 导出到 `.tmp/rea-css-recovered/`;每份都核对 REA 文本 SHA-256、UTF-8 字节数、media type,使用 PostCSS 解析,并重新读取导出文件复验摘要。清单位于 `.tmp/rea-css-recovered/manifest.json`。
|
||||
- 没有导航、点击、重载 WorkBuddy,也没有执行 renderer JavaScript。
|
||||
|
||||
## 已找到的组件规则
|
||||
|
||||
| 选择器族 | CSS 文件 | 匹配规则数 |
|
||||
| --- | --- | --- |
|
||||
| `cr-tool-call` | `src-CyXHA0IC.css` | 17 |
|
||||
| `cr-reasoning` | `src-CyXHA0IC.css` | 7 |
|
||||
| `cb-plan-task-wait-icon` | `cb-bridge-jsj-8pWS.css`、`src-CBaV_A3S.css` | 各 1 |
|
||||
| `cb-plan-tool-container` | `src-CBaV_A3S.css` | 38 |
|
||||
| `cb-task-tool-renderer` | `src-CBaV_A3S.css` | 40 |
|
||||
| `artifact-content` | `src-BPUOynUo.css` | 2 |
|
||||
| `markdown-editor-container` | `src-BPUOynUo.css` | 16 |
|
||||
|
||||
规则数按 PostCSS rule selector 包含上述字符串统计,是覆盖定位,不是组件完整性证明。对 `question-floating` 没有匹配选择器;变量名中出现该字符串不能当作组件样式已经定位。另已取得输入区、图片预览、编辑器与全局 token 的样式正文。
|
||||
|
||||
## 运行时正文与原包身份
|
||||
|
||||
与此前 REA 导出的 17 项 ASAR 样式清单比对:当前观察到其中 15 项,**13 项摘要与大小完全一致、2 项不一致**;其余 2 项未在本次加载样式中观察到。清单父 Evidence 为 `ev_97959691fb7cabf7c41f948b08332196924fec1fa8cb71e34dbafd65d912e637`,当时 ASAR SHA-256 为 `035254bc76310ea46317433e4840602094543ef323d2d5c5aff7c131729de918`。本次没有重新散列整个 ASAR。
|
||||
|
||||
| 不一致文件 | 运行时字节数 | 既有 ASAR 清单字节数 |
|
||||
| --- | --- | --- |
|
||||
| `main-content-core-D2cL2TEf.css` | 717360 | 717356 |
|
||||
| `src-CBaV_A3S.css` | 912607 | 909372 |
|
||||
|
||||
两份仍以实际运行时正文保存,manifest 同时保留原清单的预期摘要和大小,`asarComparison.status` 标为 `mismatch`。差异原因未确定,不能宣称它们与包内原文件逐字节相同;也没有拿本地内容替换原版。未观察到的清单文件是 `lightbox-shell-impl-CZr0IQzL.css` 与 `src-CJIPtKK-.css`。
|
||||
|
||||
## 修复入口与复用
|
||||
|
||||
```powershell
|
||||
npm run rea:css:prepare
|
||||
npm run test:rea-css
|
||||
npm run rea:css:capture
|
||||
npm run recover:css-reference
|
||||
```
|
||||
|
||||
`prepare-css-runtime.mjs` 将已安装 REA 6.5.0 复制到 `.tmp/rea-css-runtime`,在副本应用受锚点校验的补丁;依赖通过只读复用的 junction 解析,代码不会写入该依赖目录。源安装位置可通过 `npm run rea:css:prepare -- <绝对路径>` 指定。不修改全局 REA、Codex 注册或技能;当前会话原有 REA MCP 仍是原版本,后续采集使用上述本地入口。
|
||||
|
||||
采集包装器只启动本地 REA 的公开 `scripts/rea.mjs`,先通过 REA `list-electron-targets` 按完整文件路径唯一选定 WorkBuddy,再调用 REA `inspect-electron-page`。包装器自身没有 CDP/WebSocket 实现。可显式指定其他已授权端口及页面:`npm run rea:css:capture -- <loopback端点> <完整页面路径>`。证据按 ID 归档,同时更新最新证据别名;导出脚本只读取 REA Evidence,不访问原版。
|
||||
|
||||
REA 内部新增 `include_style_sources`(默认 false):在选定 target session 启用 DOM/CSS,收集样式表生命周期事件,仅对获准本地 frame、`regular` 来源的本地文件或内联/constructed 样式调用 `CSS.getStyleSheetText`,沿用 REA 文本 artifact 摘要与 Evidence 生成。CLI 参数为 `--include-style-sources`;本地副本 MCP 的输入 schema 同步暴露该选项。限制为最多 1024 次正文请求、单份 8 MiB、合计 64 MiB,正文读取后执行字节预算检查;CSS 有独立失败/排除/截断字段,不能只看旧的 scripts/resources 完整性字段。
|
||||
|
||||
可审查文件:`scripts/rea/prepare-css-runtime.mjs`、`scripts/rea/patches/CdpElectronStyles.js`、`scripts/rea/capture-css.mjs`、`scripts/rea/export-css-reference.mjs`。副本里的 `css-repair-manifest.json` 保存 11 个变更模块的原始/修改摘要,`css-repair-baseline/` 保存对应原模块。`.tmp` 中的运行时和证据应保留;删除副本后可以重新 prepare,但删除 Evidence 会失去此次观察记录。
|
||||
|
||||
## 验证与剩余范围
|
||||
|
||||
`npm run test:rea-css` 已通过:真实修复模块配合隔离 mock 协议测试来源/frame/session 过滤、默认不开启、移除事件、读取错误和字节/数量预算;验证输入/输出 schema 与实际 Evidence 保留正文;通过公开 launcher 启动真实 MCP 进程验证版本、工具列表和 CSS 参数;最后检查 11 个本地模块摘要及对应全局原文件未改变。测试只用自有临时 fixture,不采集原版。
|
||||
|
||||
另外已通过公开 REA CLI 真实采集 WorkBuddy,并完成 64 份文件的导出校验。本轮没有修改 YCode 产品组件,所以不以应用构建代替采集验证。
|
||||
|
||||
仍需后续单独处理:未加载/未归属的样式、两个摘要差异的原因、问答组件选择器定位、字体资源及最终计算样式、同状态截图和动效对照。当前 CSS 可以作为后续组件源码级对齐的依据;仍需连同原版 DOM、变量、资源路径和组件行为集成并验收,不能只全局导入便宣称 1:1。
|
||||
@@ -0,0 +1,29 @@
|
||||
# Responses 协议与真实对话验收(2026-10-16)
|
||||
|
||||
用户选择恢复原有 API 服务后,重新检查发现当前模型已由用户更新为 `gpt-6-luna`,接口为完整 `/v1/responses`。旧 YCode 连接测试在它后面追加 `/chat/completions`;OMP 又固定使用 `openai-completions`。此前的旧模型连接拒绝属于历史结果,不能作为新配置不可用的依据。
|
||||
|
||||
## 修复
|
||||
|
||||
- `src/shared/openai-endpoint.ts` 统一区分完整 Responses 地址、完整 Chat Completions 地址和普通 API 根。明确 `/responses` 选择 Responses,其余根保持 Chat 兼容;用户落盘地址和密钥保持原值。
|
||||
- `src/main/omp-model.ts` 选择真实 OMP `openai-responses` 适配器,给 SDK 提供 API 根,避免重复拼接。协议及有效根进入配置 fingerprint,活动回合仍使用自己的不可变配置。
|
||||
- `src/main/models.ts` 分协议构造未保存配置连接测试,正确识别 Responses output,包括短 token 预算导致的合法 reasoning/incomplete。错误不回显上游正文或秘密。
|
||||
- `src/main/gateway/responses.ts` 与 Gateway 入口兼容备用内核的 Responses 输入、图像、工具历史、流式文本/reasoning/function-call 及终态。只有合法 completed 终态才交付可执行工具调用;失败、截断和 incomplete 不冒充完成。
|
||||
|
||||
协议依据:[OpenAI 官方流式响应说明](https://developers.openai.com/api/docs/guides/streaming-responses)、[官方 Responses 流事件定义](https://developers.openai.com/api/reference/resources/responses/streaming-events)。这是对用户自定义网关协议的兼容,没有查询或推断该模型的公开供应商可用性,没有迁移用户模型。
|
||||
|
||||
## 验证
|
||||
|
||||
- 最终 `npm run build`,含两端 typecheck,通过。日志 `.tmp/responses-final-build-20261016.log`。
|
||||
- 模型注册表 focused 回归通过:完整/尾斜线路径、请求 schema、无鉴权、留空保留旧密钥、不写配置、非法结果和 HTTP 错误。
|
||||
- 实际 OMP loader 接受 `openai-responses`,SDK 根为 `/v1`;`.tmp/omp-responses-loader-nz5Pns/report.json`。该检查没有调用用户上游。
|
||||
- 隔离生产 App → preload/IPC → 实际 OMP → 受控 Responses 上游,28/28;两轮历史、准确路径、认证、禁工具、token 参数、取消及真实 transcript。`.tmp/responses-integration-UbxGhB/report.json`。
|
||||
- 备用 Gateway 30/30,含实际 fallback `runTurn` 工具执行与回填、文本/推理、非法终态、失败和取消;旧 Chat smoke 通过。`.tmp/gateway-responses-7RoDVm/report.json`。
|
||||
- 修改后的旧 Chat 实际 OMP 能力回归22/22仍通过,覆盖无鉴权、禁工具/图像、token配置及真实回复,`.tmp/model-capabilities-PEJKAM/report.json`。
|
||||
- **实际用户配置连接测试成功。随后经真实生产 DOM 发送两条简短验收消息,真实远程上游两轮均为 done,第二轮正确回忆第一轮验证码。** `.tmp/live-responses-acceptance-HP2ruM/report.json`;没有使用受控响应替代。这两轮保留在此前专用测试会话 `b54d80bd-ff69-4ec8-9bb1-e21b31b2b9a9`,没有向 WorkBuddy 发消息。
|
||||
- 另从真实 `sessions.json` 核对最后四条 user/assistant/user/assistant,两个 assistant 均 done、内容匹配、modelId 为当前模型;完成后返回原会话。更新时先检查活动回合及草稿,第一次检查遇到忙状态未关闭窗口,空闲后才更新;未丢弃用户输入。
|
||||
|
||||
没有在报告中记录真实端点主机、API Key 或任意上游诊断正文;真实测试只记录状态、长度和预期文本匹配布尔值。
|
||||
|
||||
## 范围限制
|
||||
|
||||
本轮证明真实供应商的简单两轮文本对话与保存,不能替代所有模型/工具/图像/复杂 reasoning 的验收。备用 Gateway 现有历史契约未保存 encrypted reasoning 等不透明上下文;对要求这些数据连续回传的供应商仍需扩展。UI 的文字栅格与全状态动效差异仍按持续进度文档跟踪,本次协议修复不构成整个 UI 1:1 通过。
|
||||
@@ -0,0 +1,88 @@
|
||||
> 最新迁移状态:主上下文已将本包安装到用户 YCode,原文/技能/头像资源与激活及原生鼠标召唤验证通过。四包共356项资源验收,详见[四位专家迁入记录](四位专家迁入YCode-2026-10-16.md)。本文“未安装/只读”描述保留为恢复子任务阶段范围。
|
||||
|
||||
# UI设计师|像素君:REA 包恢复与兼容拆解(2026-10-16)
|
||||
|
||||
本轮已恢复完整功能包,共 **143 文件、6,249,920 字节**,全部与固定 REA 目录库存及保留导出的 SHA/字节核验一致。未安装到用户 YCode,未执行原 Python/JS/HTML,未调用 MiniMax 或浏览器服务;安装与实际运行由主任务继续验证。本结论是包内容恢复,不能据此宣称专家运行结果或 UI 已完成 1:1。
|
||||
|
||||
## 原版身份与证据范围
|
||||
|
||||
- 产品基线:WorkBuddy 5.8.2;专家包自身版本 **1.0.1**,两个版本不可混同。
|
||||
- 正式 REA 选中目录:`C:/Users/Administrator/.workbuddy/plugins/marketplaces/experts/plugins/ui-designer`。本轮仅将此路径传入隔离 REA 公共 CLI;所有内容分析均读取 REA 导出副本,没有直接读取原目录。
|
||||
- 完整目录库存 Evidence:`ev_a3defb3a940984c72aa5664163fab523b10ab867192a529ba9d3a672f0e7b95b`,保留于 `.tmp/rea-ui-designer-inventory-20261016.json`,coverage 为 `container-entries/complete`。
|
||||
- 固定 root SHA256:`c9c83df190f0f0f871706d52b7e372f20b7ad63fde739f59cf9181ace1d08afa`。这是 REA 目录身份,不能与单文件 SHA 混同。
|
||||
- 完整恢复目录:`.tmp/rea-ui-designer-recovered-20261016/`。`evidence-manifest.json` 每项含 `path/bytes/sha256/evidenceId/retainedExport/encoding`,二进制另含 mediaType;`remaining=[]`。
|
||||
- 原库存 144 文件、6,249,944B,仅排除 `.downloaded_at` 24B(WorkBuddy 下载宿主标记)。未发现需要排除的其他 session 标记。恢复目录新增的 `evidence-manifest.json` 是本项目审计文件,不是原专家包成员,安装 helper 应继续排除该审计文件。
|
||||
|
||||
以下单文件 SHA 均由库存、REA 选中导出和恢复副本三方核验;其他文件身份在 manifest 中完整保留。
|
||||
|
||||
| 原相对路径 | 字节 | SHA256 |
|
||||
| --- | ---: | --- |
|
||||
| `.codebuddy-plugin/plugin.json` | 1928 | `e612a42daaff52e5be8d66c26d1d6748f31e4a4e2cd3506acc59d897b55e6d85` |
|
||||
| `agents/ui-designer.md` | 15703 | `d6e54ca64ab54c6d3122ff0114a46d3820cedd1f05a5a14c541afa6a55e654aa` |
|
||||
| `avatars/expert.png` | 291079 | `86399b938def53e15c84d7c3e3e7542248c2d834862511b6e2e78ed62b332014` |
|
||||
| `skills/impeccable/SKILL.md` | 10412 | `dc66284a2a16f49773eabe1b96a92ec88f9a5a7f39c1320a3c9b87940d679a7c` |
|
||||
| `skills/frontend-dev/SKILL.md` | 20710 | `6cc0f077f282b56b4fa666be6c7549f3176e88510eeda7becc271bf188a0444a` |
|
||||
| `skills/browser-use/SKILL.md` | 10909 | `fb839ae844ae8c3aa16d07ed6f5d1db448718d0cea9ef3a30a8ed934796f1208` |
|
||||
| `skills/frontend-dev/templates/generator_template.js` | 7822 | `b601d56dc95b4749adc1fcbae0ab889f93e83403ce8b07ccf1bd201638437944` |
|
||||
| `skills/frontend-dev/templates/viewer.html` | 20714 | `f3584b5b365b36f17a5a87047ac7c1e5cd12c26f3b1dd24b6fa3d7cc77462d10` |
|
||||
|
||||
## 角色、技能与工作流
|
||||
|
||||
`plugin.json` 的真实显示名为中文 **像素君**、英文 **Sam**;职业为 **UI设计师 / UI Designer**,内部 name/agentName 为 `ui-designer`,expertType 为 `agent`,categoryId 为 `01-ProductDesign`。原头像、三个标签、三个 quickPrompts、双语 description 和 defaultInitPrompt 均原样保留。
|
||||
|
||||
角色主体 `agents/ui-designer.md` 是 UI Designer 身份与设计方法说明。定位为视觉设计系统、组件库、可访问性、精确界面和开发交付。四阶段分别在原恢复文件行 239/246/252/258:Design System Foundation、Component Architecture、Visual Hierarchy System、Developer Handoff。它不是预生成网页或确定性 UI 渲染器。
|
||||
|
||||
manifest 实际声明的技能仅三项,均已恢复 SKILL.md 与全部包内参考资源:
|
||||
|
||||
| 技能 | 原声明 | 主要工作流与资源 |
|
||||
| --- | --- | --- |
|
||||
| `impeccable` | version 2.0.0;allowed-tools Read,Write,Bash | 先读 `.impeccable.md`,缺失时读 `references/teach-impeccable.md` 收集设计上下文(SKILL.md 58–59行);按审查、排版、色彩、空间、响应式、动效、交互、文案等能力组合。30 份 references 全恢复。 |
|
||||
| `frontend-dev` | 顶层 version 0.1.1;metadata.version 1.0.0 | 六阶段:设计架构→动效架构→资产生成→文案→实现UI→质量门(169/174/178/185/188/191行);10份参考文档、4个Python媒体脚本、生成艺术 JS/HTML 模板、54个 TTF 与27个OFL文本。 |
|
||||
| `browser-use` | version 2.0.0;allowed-tools Bash(browser-use:*) | `open→state→click/input→state/screenshot` 循环(34–37行);本地 headless/可见浏览器、连接 Chrome/profile、可选 cloud。2份 references 全恢复。 |
|
||||
|
||||
`frontend-dev` 的生成艺术分支要求先创作 philosophy,再实施算法并保留模板的结构、seed 控件。`viewer.html` 原文有算法与参数处理的 `fill this in`,这是预期供模型改写的模板,不能把未改写模板标成已完成产物。JS 模板同样是算法结构参考。
|
||||
|
||||
## 完整目录覆盖
|
||||
|
||||
恢复文件扩展统计:JSON1、Markdown47、PNG1、LICENSE7、TXT27、TTF54、Python4、JavaScript1、HTML1,总数143。
|
||||
|
||||
| 资源组 | 文件数 | 字节 |
|
||||
| --- | ---: | ---: |
|
||||
| `skills/frontend-dev/canvas-fonts/`(TTF+OFL文本) | 81 | 5,530,719 |
|
||||
| 其中 TTF | 54 | 5,412,104 |
|
||||
| `skills/impeccable/references/` | 30 | 199,872 |
|
||||
| `skills/frontend-dev/references/` | 10 | 80,923 |
|
||||
| `skills/browser-use/references/` | 2 | 6,467 |
|
||||
| `license/` | 7 | 31,081 |
|
||||
| `avatars/expert.png` | 1 | 291,079 |
|
||||
|
||||
许可包括 agency-agents/browser-use MIT、anthropics-skills Apache-2.0 与字体 OFL;恢复保留原文件及字体目录中的 OFL 文本,未改写授权声明。
|
||||
|
||||
## 真实依赖、原包矛盾与 YCode 边界
|
||||
|
||||
1. **没有包级 MCP 配置。** manifest 无 MCP/connector 依赖字段,完整库存也没有 `.mcp.json`。`browser-use` 文档中的可用能力不能冒充已注册 YCode MCP 工具。
|
||||
2. **MiniMax 媒体生成需要真实环境。** 四个 `scripts/minimax_*.py` 都 `import requests`,都读取 `MINIMAX_API_KEY` 和 `MINIMAX_API_BASE`;缺少 API_BASE 会立即退出,缺 key 在请求前退出。接口涉及 image_generation、music_generation、t2a_v2、video_generation 及查询/下载。需要 Python+requests 与显式凭据/网络,不应静默复用对话模型 key。`references/env-setup.md` 6行及 SKILL.md 385行只提 key,遗漏脚本实际必需的 API_BASE,属于原包文档不一致。FFmpeg 为文档提到的可选音频后处理依赖。
|
||||
3. **browser-use 是独立 CLI 宿主依赖。** SKILL.md 14–17行要求 binary 与 Unix curl/bash 安装命令;Windows 可运行性、版本、浏览器/daemon 安装都待验。cloud 模式另需 `BROWSER_USE_API_KEY`(133行)。YCode 的 WebContentsView 存在不等于该 CLI 已安装或 API 等价。本轮没有安装、连接用户 Chrome、同步 profile、开 tunnel、调用 cloud。
|
||||
4. **HTML 不是完全离线自包含。** `viewer.html` 23–26行直接引用 p5.js **1.7.0** cdnjs 和 Google Fonts Poppins/Lora;已保留原 URL,未联网抓取依赖。包内字体不能自动替代模板中的远程字体。断网、CSP、字体fallback、CDN版本效果仍需运行验收。
|
||||
5. **UI 工程依赖按任务选择。** frontend-dev 提及 React/Next 等框架、Tailwind、Framer Motion/GSAP/Three.js/Lottie 等动效工具,不表示这些都随专家包打包或已经安装。模型需要依据目标项目检查并选择依赖。
|
||||
6. **两个角色自报技能不在包内。** Agent 398–401行提及 `brand-guidelines` 与 `canvas-design`,但 manifest 和完整库存均没有它们;实际注册必须依据上述三项。不能凭文字补造缺失 SKILL.md 或把其他本机技能拼入包。Agent 列表也未列实际声明的 browser-use。
|
||||
7. **角色文本保留与宿主权限分别处理。** Agent 13行声称身份覆盖 prior identity 等,该内容已按原数据保留;它不能提升宿主权限、覆盖系统指令或授权联网/读取用户资料。技能 allowed-tools 同样只是包的声明。
|
||||
8. **容量和资源读取。** 包约6.25MB,原 YCode4MiB总包限制会拒绝,root 已接管统一升至16MiB及 HTML/LICENSE 文本支持。54个TTF必须作为二进制原文件保留;文本 resource 工具不能单凭返回字符串交付字体或 PNG。后续需要明确、受限的本地资源路径/复制使用通路。此轮未改 production。
|
||||
|
||||
## 恢复与核验命令
|
||||
|
||||
入口脚本都仅通过公共 REA CLI 读取原版。无需重新 prepare;旧 prepare 可能覆盖 root 此轮统一增强的 provider。
|
||||
|
||||
```powershell
|
||||
node scripts/rea/ui-designer-inventory.mjs
|
||||
node scripts/rea/ui-designer-recover.mjs --text-supported
|
||||
node scripts/rea/ui-designer-recover.mjs --all
|
||||
node scripts/rea/ui-designer-recover.mjs --verify
|
||||
node scripts/rea/ui-designer-audit.mjs
|
||||
```
|
||||
|
||||
已执行结果:最初80个已有文本类型恢复;增强后另8文本与55二进制(avatar+54TTF)恢复。最终 `--verify` 完成,audit 将全部143项与库存、10份保留 REA export、落盘副本逐字节比对,**143/143通过,remaining0**。报告 `.tmp/rea-ui-designer-audit-20261016.json`,含每项检查、技能 YAML、原 template URL 与脚本依赖摘要。
|
||||
|
||||
10份 export 的完整 Evidence ID 和保留路径在 manifest 中;新增类型的 Evidence 为:文本 `ev_87a0455d315432eba3eab54db60a20bc0052fce97648995aa7873545af7444fe`;二进制 `ev_e957f76844c1027d6b71082a174a49e430947bbcadc16d40529ca24dd660eb71`、`ev_1a96bd5f0318afd1bdbbdb602dce964168177bfc953742ba80b6b35d69fadf4c`、`ev_35e6daa82ade3e59e7d9aa747ea5701d5aa5e81a284df6015764c5482042c2b4`、`ev_aa2295332cd76efb5f3555842d7a48f6d523f0318adade2ca3718f787edfa82a`。
|
||||
|
||||
安装后仍需验证:角色/三技能实际进入模型上下文;references/templates可读取;头像可见;字体/模板可安全用于项目;缺依赖时诚实报错;外部媒体/浏览器任务在用户授权与真实环境下成功。以上尚未验证,不纳入本轮恢复通过结论。
|
||||
@@ -0,0 +1,167 @@
|
||||
# WorkBuddy AI 能否「1:1 复刻」——基于 REA 的可行性评估
|
||||
|
||||
> 历史评估,结论已由 `1比1复刻重新评估-2026-10-15.md` 修正。本文把“行为复刻”等同于“源码复制”、从体积/压缩/工具未配置推出“不可能”的推理不成立;原生和云端未覆盖项应标为条件或未知,不沿用本文的一概否定。
|
||||
|
||||
**评估对象**:《WorkBuddy-AI-实现分析报告.md》所述目标(本机安装的 WorkBuddy 桌面版 v37.10.3-42)
|
||||
**评估方法**:REA MCP 实测(`analyze_javascript_application`、`binary_session` 能力探测)+ asar 清单解析 + 混淆度/源码可得性度量
|
||||
**评估日期**:2026-10-14
|
||||
|
||||
---
|
||||
|
||||
## 0. 结论(TL;DR)
|
||||
|
||||
**不能 1:1 复刻。** REA 足以支撑「**读懂**」和「**功能等价重写(clean-room)**」,但达不到「**1:1 复刻**」——这是三重封死,不是工具能力不足:
|
||||
|
||||
| 维度 | 能否 1:1 | 决定性原因 |
|
||||
| --- | --- | --- |
|
||||
| 法律 | ❌ | 1:1 复刻 = 复制腾讯专有代码,直接侵权。分析可以,照抄不行 |
|
||||
| 原生二进制 | ❌ | ≈360MB 原生代码(含单个 199.5MB 的 `editor_sdk.exe`);本机**无任何反编译器可用**,即便装上 Ghidra 也只出伪代码 |
|
||||
| 压缩 JS | ❌ | 主 bundle 全部 rolldown/rspack 压缩,**0 个 source map**、`.js.map` 不含 `sourcesContent`、无 `.ts` 源 |
|
||||
| 云依赖 | ⚠️ | 排除云部分后,本地引擎**不推理**,AI 能力实质归零——复刻出来是个没有大脑的壳 |
|
||||
|
||||
**一句话**:REA 能给你一张足够精确的「建筑图纸」,但拿不到「原始建材」;而且这栋楼的主脑(模型+提示词)本来就在云上,拆掉之后剩下的部分 1:1 复刻也没有意义。
|
||||
|
||||
---
|
||||
|
||||
## 1. 先说法律红线(这条是决定性的)
|
||||
|
||||
「1:1 复刻」在工程上等价于**逐字节/逐逻辑复制专有软件**。WorkBuddy 的 `@genie/agent-cli`、`tsbx` 沙盒、`editor_sdk.exe` 均为腾讯闭源资产,`package.json` 的 `private: true` + 无开源许可声明。因此:
|
||||
|
||||
- **可以做**:逆向分析、理解架构、提取可公开观察的接口契约、用干净室(clean-room)方式独立实现等价系统。
|
||||
- **不能做**:1:1 复制代码、重新打包分发。
|
||||
|
||||
下面所有技术结论都建立在「即使技术上允许」这一假设上——结论依然是**做不到 1:1**。
|
||||
|
||||
---
|
||||
|
||||
## 2. REA 实测:工具链本身的能力边界
|
||||
|
||||
在本机(Windows 11 / x64)实测 `binary_session`,得到关键事实:
|
||||
|
||||
| Provider | 状态 | 影响 |
|
||||
| --- | --- | --- |
|
||||
| JavaScript/Electron 分析 | ✅ 可用 | 唯一能真正跑起来的主力 |
|
||||
| **Ghidra(原生反编译)** | ❌ `not_configured` — `GHIDRA_INSTALL_DIR` 未设置 | **无法反编译任何 .dll/.exe** |
|
||||
| Hopper | ❌ `unsupported_host`(仅 macOS) | Windows 上不可用 |
|
||||
| IDA | ❌ `not_configured` | 不可用 |
|
||||
| `recover_javascript_sources`(Wakaru 反压缩) | ❌ `provider_missing`(仅 Linux x64) | **无法把压缩 bundle 还原成可读命名** |
|
||||
| PE 资源 / .NET 静态分析 | ✅ 可用 | 只能看结构,不能出伪代码 |
|
||||
|
||||
> 这就是第一个硬约束:**本机对原生层是「黑盒」**。REA 自己声明其伪代码产物 *"not original source and not text-equivalent"*——即便配上 Ghidra,也只是逼近语义,不是还原源码。
|
||||
|
||||
**实测运行记录**:对 `app.asar` 限定 2 个源文件分析,结果——
|
||||
|
||||
- `parsed_javascript_files: 2`、`visited_ast_nodes: 11395`、`findings: 10`、`parse_failures: 0`
|
||||
- 但 `coverage.status: partial`,遗留 **11,387 application unknowns / 128,327 semantic unknowns**
|
||||
- 12 个语义族(call-flow、data-flow、boundary…)**全部 partial**
|
||||
|
||||
对比原报告 §8:跑主 bundle(2,238,569 AST 节点)耗时 5 分钟 / 6GB 堆,语义图**被父级预算截断**。结论一致:**REA 出的是抽样级证据,不是完整重建**。
|
||||
|
||||
---
|
||||
|
||||
## 3. 逐层拆解:哪些能量化,哪些不能
|
||||
|
||||
### 3.1 实际体积构成(asar 清单 + unpacked 实测)
|
||||
|
||||
安装总体积 ≈ **935MB**(Electron 运行时 279MB + `app.asar` 94MB + `app.asar.unpacked` 562MB),共 14,475 + 4,596 个文件。
|
||||
|
||||
| 类别 | 体积 | REA 可得性 | 能否 1:1 |
|
||||
| --- | --- | --- | --- |
|
||||
| **原生二进制** | ≈360MB | ❌ 本机无反编译器 | ❌ |
|
||||
| **首方压缩 JS**(renderer 116.7MB、extensions 49.9MB、plugins 31.5MB、cli/dist 13.1MB、main/server.js 3.4MB) | ≈235MB | ⚠️ 语义可恢复,命名/注释丢失 | ❌ |
|
||||
| **首方可读源码**(`cli/vendor/shim/*.cjs`、`cli/bin/*.cjs`) | ≈2.7MB | ✅ **就是完整源码** | ✅(但复制=侵权) |
|
||||
| **第三方 OSS**(OpenAI Agents SDK、MCP SDK、OpenTelemetry、node-pty、koffi、zod、hono、@larksuiteoapi…) | ≈58MB | ✅ 公开可得 | ✅ 直接 `npm install`,无需复刻 |
|
||||
|
||||
### 3.2 无法 1:1 的「不可还原物」清单(实测)
|
||||
|
||||
**A. 原生二进制(决定性障碍)**
|
||||
|
||||
```
|
||||
199.5 MB node_modules/@tencent/tencent-docs-ai-engine/bin/win32-x64/editor_sdk.exe ← Office 编辑器引擎(CEF 级)
|
||||
22.0 MB cli/vendor/sandbox/5.8.5/betterleaks.exe
|
||||
9.7 MB node_modules/@genie/im-channels-native/build/Release/ImSDK.dll
|
||||
9.0 MB cli/vendor/sandbox/5.8.5/sandbox-center.exe
|
||||
2.3 MB cli/vendor/sandbox/5.8.5/sandbox_ffi.dll
|
||||
1.6 MB 合计 tsbx.dll / tsbx_sdk.dll / tsbxldr.dll / tsbxlow.dll ← 腾讯自研沙盒核心
|
||||
+ 各 .node:turing_sdk、perf_metrics、wechat_copydata_decoder、job-object、ripgrep、qimei、os-bridge…
|
||||
```
|
||||
|
||||
`tsbx.dll`(795KB)是自研沙盒的**策略执行核心**,`betterleaks.exe`(22MB)是泄漏检测引擎——这两个是 WorkBuddy 安全模型的关键差异点,**恰恰是最不可能被还原的部分**。而 199.5MB 的 `editor_sdk.exe` 基本可以判定为「不可重建」。
|
||||
|
||||
**B. 压缩 JS(语义可读,源码不可还原)**
|
||||
|
||||
主 bundle 度量:
|
||||
|
||||
```
|
||||
cli/dist/codebuddy-lite-wb.mjs 9.48MB 2679 行 平均行长 3539 字符 最长 488,181 字符
|
||||
main/server.js 3.60MB 1185 行 平均行长 3037 字符
|
||||
```
|
||||
|
||||
证据:
|
||||
- `sourceMappingURL` 出现次数 = **0**
|
||||
- 全文 `.js.map` 共 60 个,抽样解析 `@genie/im-channels-sidecar/.../*.js.map` → **无 `sourcesContent` 字段**
|
||||
- 安装包内 `.ts` 源文件 = **0 个**(仅 65 个 `.d.ts` 类型声明,只给接口形状、不给实现)
|
||||
|
||||
好消息:压缩不算彻底——**保留了 235 个可读函数名**(`doIsToolCall`、`isProxyToolCalls`、`bindAutowiredProvider`、`applyServiceDecorator`…)和几乎全部字符串字面量。这让 REA 的语义恢复质量明显高于典型混淆产物,但**仍无法还原原始文件划分与命名**。
|
||||
|
||||
**C. 可读源码层(这块确实能 1:1)**
|
||||
|
||||
`cli/vendor/shim/` 与 `cli/bin/` 下的 `.cjs` 是**未压缩完整源码**,带缩进、带注释:
|
||||
|
||||
```
|
||||
1162 行 node-brokered-fs-shim.cjs (fs 走 broker IPC)
|
||||
861 行 node-safe-delete-shim.cjs (删除进回收站)
|
||||
465 行 safe-delete-bulk-guard.cjs (批量误删防护,DEFAULT_THRESHOLD=20)
|
||||
311 行 broker-ipc-client.cjs
|
||||
128 行 daemon-supervisor.cjs
|
||||
```
|
||||
|
||||
**沙盒 shim 层可以 100% 读懂并等价重写**——但这是全栈里最容易的部分。
|
||||
|
||||
### 3.3 「排除云部分」反而掏空了核心
|
||||
|
||||
原报告 §4 已明确:**本地不推理**,`@genie/model-compatibility` 只做 API 适配,模型选择/路由在服务端按套餐决定。被排除的云部分包括:
|
||||
|
||||
- 多模型网关与路由策略(GLM/混元/DeepSeek/Qwen/Kimi/MiniMax/GPT/Gemini/Claude)
|
||||
- **主系统提示词全文**(本地仅有碎片,例如 bundle 里可检索到 `You are a background fork of the main agent. Follow these rules strictly:`)
|
||||
- 账号鉴权(Bearer + `X-User-Id`)、套餐/配额、可观测上报
|
||||
|
||||
也就是说:**排除云部分后,你要复刻的「AI 能力」其智能来源本身就在被排除的那部分里**。剩下的本地引擎即使 100% 重写,接不上自己的模型网关也只是个空壳——除非你自建网关,那又变成另一件事(自研产品,而非复刻)。
|
||||
|
||||
---
|
||||
|
||||
## 4. 能力光谱:REA 究竟能带你走到哪一步
|
||||
|
||||
| 目标 | 可行性 | 说明 |
|
||||
| --- | --- | --- |
|
||||
| **读懂架构 / 写分析报告** | ✅ 完全可行 | 原报告已是范例,REA + 字符串证据足够 |
|
||||
| **导出接口契约**(ACP 协议、工具 schema、MCP/Skill 约定、`.d.ts`) | ✅ 可行 | 协议与类型声明清晰可提取 |
|
||||
| **等价重写可读 JS 层**(shim / daemon / bin) | ✅ 可行 | 有完整源码参考 |
|
||||
| **等价重写压缩 JS 层**(agent 循环、工具系统、模型适配) | ⚠️ 可行但成本极高 | 语义可恢复 ≠ 源码可还原;需逐模块重建,且缺服务端提示词 |
|
||||
| **重建原生沙盒**(tsbx + sandbox-center + betterleaks) | ❌ | 无反编译器;即便有,伪代码也无法 1:1 |
|
||||
| **重建编辑器引擎**(`editor_sdk.exe` 199.5MB) | ❌ | 实质不可行 |
|
||||
| **1:1 复刻整体** | ❌ | 法律 + 原生 + 压缩 + 云依赖,四重封死 |
|
||||
|
||||
---
|
||||
|
||||
## 5. 如果目标是「自己做一个同类产品」,正确路径
|
||||
|
||||
不要走「复刻」,走「参照 + 自研」:
|
||||
|
||||
1. **复用 OSS 底座**:Electron + Anthropic 沙盒 runtime(开源)+ MCP SDK + OpenAI Agents SDK —— WorkBuddy 自己也是这么拼的。
|
||||
2. **自研 agent 内核**:参照 Claude Code 的公开架构(工具循环、hooks、Skill/Plugin 约定、`CLAUDE.md` 体系),这些是**公开文档**级别的知识,不需要逆向。
|
||||
3. **自建模型网关**:这是被排除的「云部分」,也是真正的护城河——自己实现多模型路由 + 提示词工程。
|
||||
4. **沙盒另选方案**:Windows 上可用 AppContainer / Job Object + 文件系统虚拟化,或直接用已开源的 `anthropic sandbox-runtime`,不必也无法复刻 `tsbx`。
|
||||
5. **明确边界**:抄协议与公开约定是安全的,抄二进制与压缩代码是侵权。
|
||||
|
||||
---
|
||||
|
||||
## 6. 最终判断
|
||||
|
||||
> **用 REA 做「理解」是够的,做「1:1 复刻」是不够的,且不需要——因为被排除的云部分才是核心价值所在。**
|
||||
|
||||
- REA 在本机的实际天花板:JS/Electron 层语义分析(coverage 明确为 *partial*),原生层**完全黑盒**(无 Ghidra/Hopper/IDA)。
|
||||
- 结构上可 1:1 的只有约 **2.7MB 的 shim/daemon 可读源码**;占大头的 **360MB 原生二进制 + 235MB 压缩 JS** 都无法 1:1。
|
||||
- 「排除云部分」这一前提,使复刻产物失去智能来源,投入产出比极低。
|
||||
|
||||
**建议**:把这次分析定位为「架构学习 + 接口提取」,产出「设计说明书」而非「副本」。若真要落地产品,按 §5 的自研路径走。
|
||||
@@ -0,0 +1,122 @@
|
||||
# WorkBuddy-AI-实现分析报告
|
||||
|
||||
> 历史静态分析报告。SDK 依赖、环境变量或字符串的存在不能单独证明主循环来源、血统或运行时调用。相关架构结论需 REA 调用追踪与运行时证据复核;现行可行性判断见 `1比1复刻重新评估-2026-10-15.md`。
|
||||
|
||||
# WorkBuddy AI 实现分析报告
|
||||
|
||||
**分析对象**:本机安装的腾讯 WorkBuddy 桌面版(`C:\Users\Administrator\AppData\Local\Programs\WorkBuddy`)
|
||||
**分析方法**:纯静态逆向(REA MCP `analyze_javascript_application` + 字符串证据提取 + 配置/依赖解析),未运行、未 hook、未联网抓包
|
||||
**分析日期**:2026-10-14
|
||||
|
||||
---
|
||||
|
||||
## 0. TL;DR
|
||||
|
||||
WorkBuddy 的 AI 能力 = **一个本地 agent 引擎(**`@genie/agent-cli`**,Claude Code / CodeBuddy 血统)** + **Electron 桌面壳经 ACP 协议驱动它** + **云端多模型网关(OpenAI 兼容 **`/chat/completions`** + SSE 流式)** + **双层沙盒(Anthropic 开源 runtime + 腾讯自研 tsbx 驱动)** + **MCP / Skills / A2A 扩展体系**。
|
||||
|
||||
---
|
||||
|
||||
## 1. 总体架构
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────┐
|
||||
│ Electron 桌面壳(app.asar,主进程 + 渲染进程 + 原生插件) │
|
||||
│ · workbuddy-editor-sdk(Office 文档编辑) │
|
||||
│ · workbuddy-baas-v2(BaaS 扩展,esbuild) │
|
||||
└──────────────────┬──────────────────────────────────┘
|
||||
│ ACP (Agent Client Protocol)
|
||||
│ 本地 HTTP: /api/v1/acp, /api/v1/acp/connect
|
||||
▼
|
||||
┌─────────────────────────────────────────────────────┐
|
||||
│ Agent 引擎 @genie/agent-cli(cli/dist/,9.4MB 主 bundle │
|
||||
│ codebuddy-lite-wb.mjs + 66 个懒加载分块) │
|
||||
│ · bin: codebuddy / cbc / codebuddy-lowmem │
|
||||
│ · daemon-supervisor(守护进程)+ windows-job(作业对象) │
|
||||
│ ├─ Agent 循环 + 工具系统(约 30 种内置工具) │
|
||||
│ ├─ 沙盒层(见 §5) │
|
||||
│ ├─ 多模型适配层 @genie/model-compatibility │
|
||||
│ └─ 团队协作 /api/v1/team/messages/send|read │
|
||||
└──────────────────┬──────────────────────────────────┘
|
||||
│ HTTPS Bearer Token + X-User-Id,路径前缀 /plugin
|
||||
▼
|
||||
┌─────────────────────────────────────────────────────┐
|
||||
│ 云端网关 www.workbuddy.cn(其余官方端点: │
|
||||
│ wb.tencentbuddy.com / copilot.tencent.com / │
|
||||
│ www.codebuddy.ai —— 同一引擎服务双品牌) │
|
||||
│ · /chat/completions(OpenAI 兼容)+ text/event-stream │
|
||||
│ · 模型路由在服务端:GLM / 混元 / DeepSeek / Qwen / │
|
||||
│ Kimi / MiniMax / GPT / Gemini / Claude │
|
||||
└─────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 2. Agent 引擎:Claude Code 血统(硬证据)
|
||||
|
||||
引擎包名 `@genie/agent-cli`(内部代号 **genie**),但 bundle 里的字符串直接暴露了来源:
|
||||
|
||||
| 证据 | 含义 |
|
||||
| --- | --- |
|
||||
| `CLAUDE_SESSION_ID`、`CLAUDE_PROJECT_DIR` | Claude Code 的标准环境变量原样保留 |
|
||||
| `CLAUDE_CODE_ENABLE_FUNCTION_HOOKS`、`CLAUDE_CODE_HOST_HTTP_PROXY_PORT`、`CLAUDE_CODE_HOST_SOCKS_PROXY_PORT` | hooks 与代理机制沿用 Claude Code 实现 |
|
||||
| `claude-sonnet-4-20250514`、`ANTHROPIC_API_KEY`、`anthropic-ratelimit-unified-reset` | Anthropic API 兼容层与限流头 |
|
||||
| `Claude-Code-Ide-Authorization` | IDE 集成握手协议同名 |
|
||||
| `anthropics/claude-plugins-official`、`CLAUDE_PLUGIN_ROOT`、`CLAUDE_PLUGIN_DATA` | 插件体系直接兼容 Anthropic 官方插件市场格式 |
|
||||
| `@anthropic-ai/sandbox-runtime@0.0.17`、`AnthropicSandboxManager.initialize` | 沙盒直接采用 Anthropic 开源实现 |
|
||||
| bin 名:`codebuddy-code` / `codebuddy` / `cbc`;主 bundle 名 `codebuddy-lite-wb.mjs` | 腾讯 CodeBuddy 同源内核,WorkBuddy 是其 lite-wb 变体 |
|
||||
|
||||
**结论**:WorkBuddy AI 的 agent 内核 = Claude Code 架构的腾讯分支(CodeBuddy CLI),叠加腾讯自有协议栈(galileo 遥测、agentdr SDK、ACC 产品配置体系)。
|
||||
|
||||
## 3. Agent 循环与工具系统
|
||||
|
||||
- **循环原语**:依赖 `@openai/agents` + `@openai/agents-core` 0.5.2(OpenAI Agents SDK 提供 Runner/循环调度),上层是自研 genie 工作区包(`@genie/core` / `runtime` / `prompts` / `agent-provider` / `cbc-worker`)。
|
||||
- **内置工具**(bundle 中出现的与对外暴露完全一致):`AskUserQuestion`(15)、`Grep`(12)、`Skill`(11)、`Glob`(10)、`DeferExecuteTool`(9)、`WebFetch`(9)、`WebSearch`(9)、`SendMessage`(8)、`NotebookEdit`(6)、`ToolSearch`(5)、`TaskCreate/Update/List/Get/Output`、`EnterPlanMode/ExitPlanMode`、`ImageGen/VideoGen/AudioTranscribe`、`show_widget`、`present_files`、`BrowserUse`、`BashOutput/KillShell`、`TodoWrite` 等。
|
||||
- **循环防护**:`CBC_LOOP_GUARD_CONSECUTIVE_THRESHOLD`、`CBC_LOOP_GUARD_SEQUENCE_REPEATS`、`CBC_LOOP_GUARD_DISABLED` —— 检测 agent 连续重复动作的死循环保护。
|
||||
- **多 agent 团队**:`CBC_TEAM_IMMEDIATE_DISPATCH` + `/api/v1/team/messages/send|read` —— Task 工具派发子 agent、消息互通。
|
||||
- **进程模型**:`daemon-supervisor.cjs` 守护进程管理、`windows-job.cjs` 用 Windows Job Object 绑定子进程树(防孤儿进程)、`cbc-prewarm` 启动预热、`preload-lazy-chunks` 懒加载预热、`codebuddy-lowmem` 低内存模式(RSS 阈值触发 heap snapshot)。
|
||||
|
||||
## 4. 模型层
|
||||
|
||||
- **本地不推理**。`@genie/model-compatibility` 只做多家 API 适配;实际模型选择/路由在云端网关按账号套餐决定。
|
||||
- **调用协议**:OpenAI 兼容 `chat/completions`(17 处)+ `text/event-stream` SSE 流式(56 处)+ JSONL 本地流式记录(62 处)。
|
||||
- **bundle 中可见的模型标识**:`hunyuan`(混元)、`deepseek`(含 `deepseek_flash_unavailable` 降级标记)、`qwen-token-plan(-cn/-individual)`、`kimi-k2.5`、`kimi-coding`、`minimax(-cn)`、`gpt-4.1`、`gpt-5`、`gemini`、`claude-sonnet-4-20250514`;多模态:`wb-asr` + `gpt-4o-mini-transcribe`(语音转写)、`hunyuan-image-v2.0-general-edit` / `hunyuan-image-v3.0`(图像生成/编辑)。
|
||||
- 本会话由 GLM 驱动(服务端路由),与上述适配层结论一致。
|
||||
|
||||
## 5. 沙盒与安全(双层)
|
||||
|
||||
1. **策略层**:`@anthropic-ai/sandbox-runtime`(Anthropic 开源),负责权限策略与审批流(`CBC_SANDBOX_APPROVAL_TIMEOUT_MS`),权限提升经本地 `/api/v1/permission-bridge/request`。
|
||||
2. **执行层(腾讯自研,Windows)**:`cli/vendor/sandbox/5.8.5/` —— `tsbx.dll` + `tsbx_rules.json`(规则)+ `tsbxldr.dll`(加载器)+ `sandbox_ffi.dll` + `sandbox-center.exe`(中心进程)+ `betterleaks.exe`(泄漏检测)+ `sandbox-cli*.exe`。
|
||||
3. **Shim 层**:`cli/vendor/shim/` —— agent 子进程的 fs/exec/python 全部经过 shim 代理:`node-brokered-fs-shim`(文件系统走 broker IPC)、`node-language-shim`、`sitecustomize.py`(Python 运行时注入)、`safe-delete` 体系(删除进回收站 `GENIE_TRASH_DIR`,含 bulk-guard 防批量误删)、`brokered-bin/safe-bin` 白名单命令目录。
|
||||
|
||||
## 6. 扩展体系
|
||||
|
||||
- **MCP**:`@modelcontextprotocol/sdk@1.29.0`,配置在 `~/.workbuddy/mcp.json`(本次分析的 REA 即通过此机制接入)。
|
||||
- **Skills**:`Skill` 工具 + A2A 扩展 `codebuddy.ai/a2a/extensions/skill-routing`;技能目录约定 `SKILL.md`(兼容 Anthropic Agent Skills 格式)。
|
||||
- **A2A**:`@a2a-js/sdk`(agent-to-agent 协作);**ACP**:`@agentclientprotocol/sdk`(桌面 UI ↔ 引擎通信)。
|
||||
- **消息通道**:`/api/v1/channels/wechat|wecom` + `qyapi.weixin.qq.com` 全套客服/群机器人 API(微信侧接入)。
|
||||
- **插件**:`/api/v1/plugins/uninstall` 等本地 API + Anthropic 插件市场兼容。
|
||||
|
||||
## 7. 部署与治理
|
||||
|
||||
- **部署变体**:`product.json` 一套引擎四份配置 —— `cloudhosted`(公有云)/ `selfhosted`(自托管)/ `ioa`(私有化)/ `internal`(内部),由 `ACC_PRODUCT_CONFIG_V2/V3` 环境变量切换。
|
||||
- **认证**:腾讯云账号体系,Bearer Token + `X-User-Id` 头,`account-scoped-external-link` 类型,桌面端 id 为 `workbuddy-desktop`。
|
||||
- **可观测**:`@tencent/galileo-node-sdk`(腾讯内部遥测)+ OpenTelemetry `/v1/traces`。
|
||||
- **资源治理**:COS 加速桶 `acc-*.cos.accelerate.myqcloud.com`(资源分发)。
|
||||
|
||||
## 8. REA 分析记录(诚实声明)
|
||||
|
||||
- 第一次运行:worker 堆(1GB 默认)耗尽,失败。
|
||||
- 第二次运行(6GB 堆 / 5 分钟超时):成功解析主 bundle —— 遍历 **2,238,569 个 AST 节点**、产出 **248 个 findings**、0 解析失败;语义图超出父级结果预算被截断,仅保留静态与模块级事实。
|
||||
- 其余 66 个懒加载分块未逐一分析;`.mjs` 为压缩产物,原始模块名已丢失。
|
||||
|
||||
## 9. 分析局限性
|
||||
|
||||
1. 静态分析不等于运行时行为——提示词全文、服务端模型路由策略、鉴权细节均在云端,本地不可见。
|
||||
2. 无法从字节码确定引擎 fork 的确切基线版本。
|
||||
3. app.asar 内的渲染进程 UI 逻辑未纳入本次范围(与"AI 如何实现"关系较小)。
|
||||
|
||||
---
|
||||
|
||||
## 一句话总结
|
||||
|
||||
**WorkBuddy AI = Claude Code 架构的本地 agent 引擎(腾讯 genie/codebuddy 内核)+ 腾讯云多模型网关 + 自研 Windows 沙盒 + MCP/Skill/A2A 扩展生态;桌面 App 本身只是这个引擎的一个 ACP 客户端。**
|
||||
@@ -0,0 +1,227 @@
|
||||
# WorkBuddy 对话区 / 右侧栏 UI 能否 1:1 复刻
|
||||
|
||||
**评估对象**:WorkBuddy 桌面版渲染进程 UI(`app.asar.unpacked/renderer`)+ 侧栏类扩展(`resources/extensions/*/ui`)
|
||||
**评估方法**:REA MCP(`analyze_javascript_application` 实测)+ 资源清单/混淆度/CSS 类名/库指纹取证
|
||||
**评估日期**:2026-10-14
|
||||
**结论前置**:**UI 层是整个 WorkBuddy 里最接近可复刻的部分——视觉与结构可做到高度 1:1,交互行为需重写,数据流为 0(在云端)。**
|
||||
|
||||
---
|
||||
|
||||
## 0. 一句话结论
|
||||
|
||||
引擎层「不可 1:1」的核心障碍是**原生二进制 + 压缩 bundle**;而 UI 层**两个障碍都不存在**——
|
||||
|
||||
- 渲染进程代码**基本没有混淆**(920 个具名 React 组件、10,347 个可读函数名保留在 7.5MB 主 chunk 中,函数体逐行可读)
|
||||
- CSS、设计 token、i18n、图标资源**全部明文可提取**
|
||||
- UI 技术栈**几乎全是开源库**
|
||||
|
||||
**所以:对话区与右侧栏,可以做到「视觉 + 结构 + 交互行为」层面的 1:1 复刻;但「源码/二进制 1:1」仍然不行(版权),且排除云之后它是一套没有数据的空界面。**
|
||||
|
||||
---
|
||||
|
||||
## 1. 决定性证据:渲染进程代码未混淆
|
||||
|
||||
### 1.1 实测:函数体逐行可读
|
||||
|
||||
抽取 `contexts-BMeWSUHk.js`(7,549,089 B)中的真实代码:
|
||||
|
||||
```js
|
||||
function ConversationInputArea({viewConversationId:e, renderRootId:t, scenarioId:n,
|
||||
maxContentWidth:r, inputTopSlot:i, customFloatingSlot:a, cloudServiceQuotaBar:o,
|
||||
fullscreenDropContainerRef:s, onPromptQueueInsetChange:c}){
|
||||
let l = useConversationError(),
|
||||
u = useConversationSessionSelector(selectConversationInputAreaSession, shallow$1),
|
||||
{pending:d, planAdjustment:f} = useConversationInteraction(),
|
||||
p = useConversationPromptQueue(),
|
||||
m = useCreditInputBannerProvider(),
|
||||
h = useConversationBackgroundTasks(),
|
||||
g = useConversationApi(), ...
|
||||
```
|
||||
|
||||
```js
|
||||
function ConversationStreamingFooterImpl({options:e}){
|
||||
let t = useConversationSessionSelector(selectConversationStreamingFooterSession, shallow$1),
|
||||
n = useConversationI18n(),
|
||||
...
|
||||
let {reasoningOnly:s, credit:c, hasMessage:l} =
|
||||
useConversationMessagesSelector(createStreamingFooterMessageSelector(e.messageId,o), shallow$1), ...
|
||||
```
|
||||
|
||||
**解读**:只有空白被压掉(平均行长 9,764 字符)和**局部变量重命名为单字母**(`e/t/n/r`),而——
|
||||
- **组件名、props 名、自定义 Hook 名、selector 名、状态机枚举值全部保留**
|
||||
- 依赖注入关系(哪个组件用哪个 Hook)一目了然
|
||||
|
||||
对照:`main/server.js` 是真正压缩过的(平均行长 3,037、全单字母标识符)——**腾讯压了主进程,却没压渲染进程**。这是 UI 可复刻率远高于引擎的直接原因。
|
||||
|
||||
### 1.2 量化指标
|
||||
|
||||
| 文件 | 大小 | 行数 | 平均行长 | 保留的可读函数名 |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| `contexts-BMeWSUHk.js` | 7.55 MB | 772 | 9,764 | **10,347** |
|
||||
| `src-0FGg1seX.js` | 2.68 MB | 1,347 | 1,986 | 1,136 |
|
||||
| `colleague-chat-page-DUBLIFUp.js` | 225 KB | 3 | 56,379 | 258 |
|
||||
| `agent-chat-pane-CUPwHdfj.js` | 7.4 KB | — | — | **整文件可直读** |
|
||||
|
||||
全量普查:**920 个具名 React 组件**(`AccountPanel`、`ConversationPromptQueuePanel`、`DetailPanelSurfaceProvider`、`ClawSecondarySidebar`…)。
|
||||
|
||||
### 1.3 REA 实测运行记录
|
||||
|
||||
| 目标 | 结果 |
|
||||
| --- | --- |
|
||||
| `renderer`(限定 2 个 JS 源文件) | parsed=2、AST 节点=2,495、findings=67、**parse_failures=0**;data-flow 关系 1,561、closure 237 |
|
||||
| coverage | `partial`(1,165 个文件未在本次选入范围) |
|
||||
| 限制 | REA 自身声明:静态语法观察,不代表运行时;未执行 bundle bootstrap |
|
||||
|
||||
> 注意:CSS 文件**不能**作为 `analyze_javascript_application` 的 `source_paths`(实测被拒:`invalid_value`)——CSS 需用普通文本/样式工具处理,不归 REA。
|
||||
|
||||
---
|
||||
|
||||
## 2. 视觉层:CSS + 设计 token 可完整提取
|
||||
|
||||
### 2.1 CSS 明文且类名语义化
|
||||
|
||||
CSS 是压缩的(注释已被剥离,`/* */` 计数为 0),但**是 100% 有效 CSS,可直接提取**,且**类名一个都没被 hash**:
|
||||
|
||||
```css
|
||||
.claw-agent-chat-pane{--claw-agent-chat-content-max-width:832px;
|
||||
background:var(--wb-home-bg-secondary);flex-direction:column;width:100%;height:100%;...}
|
||||
.colleague-chat-cb-chat [class*=input-area-container]{max-width:var(--cb-chat-max-content-width);...}
|
||||
```
|
||||
|
||||
对话区相关类名(抽样):
|
||||
|
||||
```
|
||||
.cb-chat-message--user .cb-chat-message--assistant .cb-chat-message-bubble
|
||||
.cb-chat-tool-renderer .cb-chat-search-hit--current .cb-message-time-tip
|
||||
.cb-input-banner--error .cb-message-queue-item .cb-message-queue-item-dragging
|
||||
.cb-message-queue-item-drag-over-before .assistant-message-tool-container
|
||||
.cb-chat-toast .cb-message-queue-item-single .cb-task-list-input
|
||||
```
|
||||
|
||||
右侧栏相关类名(抽样):
|
||||
|
||||
```
|
||||
.detail-sidebar .detail-sidebar--collapsed .detail-sidebar--file-version
|
||||
.detail-sidebar-sash .claw-secondary-sidebar .claw-secondary-sidebar--pinned
|
||||
.claw-secondary-sidebar--floating .claw-sidebar-drawer--floating .conversation-sidebar
|
||||
.colleague-detail-panel .colleague-detail-sidebar-module .cb-sidebar-nav--compact
|
||||
.cb-sidebar-category--file-tree .codicon-layout-sidebar-right-dock
|
||||
```
|
||||
|
||||
**类名本身就是 DOM 结构说明书**(BEM 风格:块-元素-修饰符)。CSS 总量:`wb-` 前缀变量/类 1,425 个 + `cb-` 前缀组件类 437 个。
|
||||
|
||||
### 2.2 设计 token 完整(1,563 KB 的 `contexts-BkjwYSZT.css`)
|
||||
|
||||
```css
|
||||
:root,body[data-vscode-theme-name=IDE\ Light]{
|
||||
--wb-palette-brand-8:#00c29a; --wb-palette-brand-9:#009273;
|
||||
--wb-palette-blue-7:#3370ff; --wb-palette-purple-6:#7c5cfc;
|
||||
--wb-color-text-primary; --wb-color-border-secondary; --wb-radius-lg;
|
||||
--wb-spacing-4; --wb-font-h1-size; --wb-alert-border-radius; ...
|
||||
}
|
||||
```
|
||||
|
||||
主题系统(light/dark/皮肤)**完全基于 CSS 变量**,且 `index.html` 内联脚本展示了主题注入协议(`windowTheme`/`colorScheme` → `root.dataset.theme`)。这意味着**换肤体系可以原样重建**。
|
||||
|
||||
顺带:`codicon-layout-sidebar-*` 证明图标用了 **VS Code codicon**(MIT 开源)。
|
||||
|
||||
---
|
||||
|
||||
## 3. 资源与国际化:全部本地明文
|
||||
|
||||
| 资源 | 状态 |
|
||||
| --- | --- |
|
||||
| i18n 语言包 | ✅ 全量本地:`zh-cn`(1.14MB)、`zh-tw`(1.07MB)、`en`(0.87MB),含全部 `chat.*` key(`chat.input.placeholder`、`chat.search.*`、`chat.input.sendShortcutTooltip`…) |
|
||||
| 图标 | ✅ `icons-DmAL6CTu.js`(3.7MB)、大量 `.svg`(`file-pdf-color-link`、`wechat-color-link`…) |
|
||||
| 插图/位图 | ✅ `claw-welcome-light.svg`(1.6MB)、`inspiration-fallback-{1,2,3}.png`、`empty-no-files.png`、`drop-files-icon-{light,dark}.png` |
|
||||
| 字体 | ✅ 本地字体文件(`PingFang SC` 等走系统回退) |
|
||||
|
||||
> i18n key 用模板字符串存 Unicode 转义,可无损还原中文原文。**UI 文案零云依赖**。
|
||||
|
||||
---
|
||||
|
||||
## 4. UI 技术栈几乎全开源 → 直接复用,无需"复刻"
|
||||
|
||||
库指纹扫描(在 renderer bundle 中命中):
|
||||
|
||||
| 能力 | 采用的开源库 | 命中文件数 |
|
||||
| --- | --- | --- |
|
||||
| 框架 | **React 18** + rolldown 构建 | — |
|
||||
| 无障碍/弹层原语 | Radix UI | 17 |
|
||||
| 定位/浮层 | Floating UI | 54 |
|
||||
| 状态管理 | Zustand | 39 |
|
||||
| 图表 | **mermaid** | 101 |
|
||||
| 公式 | **KaTeX** | 49 |
|
||||
| 白板 | **Excalidraw** | 63 |
|
||||
| PDF | **PDF.js** | 1 |
|
||||
| 终端 | xterm | 9 |
|
||||
| 代码编辑器 | **Monaco** | 15 |
|
||||
| Markdown | marked / markdown-it | 17 / 1 |
|
||||
| 代码高亮 | shiki / prism | 4 / 7 |
|
||||
| 净化 | DOMPurify | 3 |
|
||||
| 国际化 | i18next | 16 |
|
||||
| 时间 | dayjs | 50 |
|
||||
| 动画 | framer-motion | 3 |
|
||||
|
||||
**除 `cb-` 前缀的内部设计系统组件库外,UI 没有任何自研底层**。这意味着"复刻 UI"实际是"用同一批开源库重搭一遍"。
|
||||
|
||||
---
|
||||
|
||||
## 5. 侧栏的形态:壳 + 扩展
|
||||
|
||||
右侧栏不是单一组件,而是**主壳 + 独立扩展 UI**:
|
||||
|
||||
```
|
||||
resources/extensions/
|
||||
library/ ← 资料库 {assets/ ui/assets/ extension.json distribution.json}
|
||||
global-search/ ← 全局搜索
|
||||
im-channels/ ← 消息通道(23MB) 含 server/ + ui/
|
||||
community/ ← 社区 (12MB)
|
||||
cloud-assistant/ ← 云助手
|
||||
workbuddy-baas-v2/ (15MB) edge-sync/ remote-desktop/
|
||||
```
|
||||
|
||||
主壳侧栏由 `DetailPanelSurfaceProvider / DetailPanelSurfaceHost / DetailPanelSurfacePortal`、`ClawSecondarySidebar`、`ConversationArtifactPanelHost` 等组件驱动(均为可读组件名),扩展以独立 `ui/assets` 形式挂载。
|
||||
|
||||
---
|
||||
|
||||
## 6. 那么,到底能复刻到什么程度?
|
||||
|
||||
| 层面 | 可复刻度 | 说明 |
|
||||
| --- | --- | --- |
|
||||
| **视觉外观**(布局/配色/圆角/间距/阴影/动效) | **~95%** | CSS 明文 + token 完整 + 资源可复制;剩余差异来自字体渲染与平台差异 |
|
||||
| **DOM 结构 / 组件树** | **~90%** | 类名语义化 + 920 个具名组件 + props 可读;可完整重建组件边界 |
|
||||
| **交互行为**(输入、发送、流式渲染、折叠、拖拽排序、滚动、快捷键) | **~70%** | 状态机与 Hook 语义可读但要**重写**(局部变量被混淆、跨文件依赖多);跨进程/原生部分受限 |
|
||||
| **数据/内容流**(模型列表、专家、会话历史、配额) | **0%** | 全在云端,属被排除的「云部分」 |
|
||||
| **源码二进制 1:1** | **0%** | 复制 CSS/资源/代码仍构成侵权 |
|
||||
|
||||
### 具体受限点(诚实清单)
|
||||
|
||||
1. **函数内部逻辑被混淆**——`let l=..., u=...` 只能靠 Hook 名与调用顺序推断;行为需重写而非复制。
|
||||
2. **跨进程交互**:窗口控件、原生菜单、文件对话框、拖到 Dock、剪贴板、截图 → 走主进程 + 原生模块(`@ban-dal/os-bridge`、`wwapi-electron` 等)。
|
||||
3. **富文档预览**:office 预览经 `editor_sdk.exe`(199.5MB,见引擎报告)→ **不可复刻**;但 PDF.js / Excalidraw / 图片 预览路径是开源的,可复用。
|
||||
4. **内部组件库**:`cb-` 前缀 437 个类对应的组件需自行重写。
|
||||
5. **数据源**:排除云后,对话区与侧栏**没有内容可渲染**——必须自建模型网关与服务端(这是真正的护城河,也是上篇报告已指出的核心)。
|
||||
|
||||
---
|
||||
|
||||
## 7. 最终判断
|
||||
|
||||
> **对话区 / 右侧栏:UI 层可以做到 1:1 的「样子和手感」,做不到 1:1 的「源码」,且做出来是空壳。**
|
||||
|
||||
- 与引擎层的本质差别:**引擎层卡在原生二进制与压缩 bundle;UI 层这两者都不存在。** 渲染进程代码几乎未混淆、CSS/token/i18n/资源全明文、技术栈全开源。
|
||||
- 工作量重心从"逆向还原"变成"用开源栈重搭 + 按可读组件名重组交互",这比复刻引擎现实得多。
|
||||
- 但两个天花板不变:**版权**(不能复制产出物)与**云依赖**(没有数据源,界面无内容)。
|
||||
- 结论落到可执行建议:**把 UI 分析产出当作「设计规范 + 组件清单 + 交互说明」来用**——这是安全且高价值的用法;要落地产品,用同一批开源库 + 自建后端重写。
|
||||
|
||||
---
|
||||
|
||||
### 附:本次取证命令与命中数据(可复核)
|
||||
|
||||
- `agent-chat-pane-CUPwHdfj.js` 与 `-F5lfde1Z.css` 全文可读(`AgentChatPane`、`computeAgentChatMaxContentWidth`、`shouldHideAssistantDuration`)
|
||||
- `contexts-BMeWSUHk.js`:10,347 个具名函数;`ConversationInputArea`、`ConversationStreamingFooterImpl` 函数体可读
|
||||
- CSS 类名抽样:`.cb-chat-message--user`、`.detail-sidebar--collapsed`、`.claw-secondary-sidebar--pinned`、`.codicon-layout-sidebar-right-dock`
|
||||
- token 抽样:`--wb-palette-brand-8:#00c29a`、`--wb-color-text-primary`
|
||||
- i18n:`zh-cn-Dfzn8myY.js` 含 `chat.input.placeholder`、`chat.search.placeholder`、`chat.input.sendShortcutTooltip`
|
||||
- 库指纹:radix=17、floating-ui=54、zustand=39、mermaid=101、katex=49、excalidraw=63、pdfjs=1、monaco=15、marked=17、i18next=16、dayjs=50
|
||||
- REA:`renderer` 目录分析 → 2 文件 / 2,495 AST 节点 / 67 findings / 0 parse failures / coverage=partial
|
||||
@@ -0,0 +1,28 @@
|
||||
# WorkBuddy“开始新会话”副本导入
|
||||
|
||||
用户要求将原版该会话复制一份到 YCode。本轮已实际落盘并在真实桌面 YCode 打开,不是只增加浏览器 fixture。
|
||||
|
||||
- 来源 ID:`4653e36f-6b2a-446f-a9c9-3f2d2d04644e`;项目 `C:/Users/Administrator/code/YCode`;标题“开始新会话”。
|
||||
- YCode 新 ID:`6c000be8-b0e8-4768-9a7f-1a0d94a35951`;标题同为“开始新会话”。原有 4 个会话逐字段回读未变,共 5 个会话。
|
||||
- 当前分支 62 条消息:31 用户、31 助手;691 个工具调用(673 成功、15 失败、3 无结果归档为取消);4 张图片已独立内嵌保存,不依赖原版 blob 路径。
|
||||
- 显式应用 2 次编辑重发分支,排除 357 条旧分支记录。31 条用户文本按来源去掉提示词包装,10 条明确 isMeta 的任务通知不作为用户输入显示;原始全部 2,810 条记录保留在 REA 导出。
|
||||
- 工具按 callId 配对,未匹配结果 0。完整输出保留,仅摘要截断;保留展示结构白名单,排除原版宿主执行通道、终端句柄和待审批状态。
|
||||
- 仅导入 1 条明文明示的 reasoning。357 条仅含 rawContent 的非展示记录留在原始导出,不把它们猜成可见推理。1 处无效 JSON 工具参数保留原文。
|
||||
|
||||
## REA 证据
|
||||
|
||||
会话元信息由 REA SQLite 工具读取 `.workbuddy/workbuddy.db`:`ev_e8774053dc05115885f43bb1a443031619966103f632d09afaa097c7bb5932c4`。未使用旧的 `.workbuddy-ai` 数据库作为当前来源。
|
||||
|
||||
正文及图片由本地 REA 新增的 `export-selected-conversation-text` 公共入口导出。该 provider 复用 REA `DirectoryArtifactReader` 的稳定身份与只读流,按 UUID 唯一选择 JSONL;图片只读取该记录引用的 content-addressed blob,校验根目录、hash 文件名、SHA-256 和大小。未用外部文件读取器绕过 REA 查看原版数据。
|
||||
|
||||
最终 Evidence `ev_3c4593ae51bbee833ca9fcbe3b9ad172d108cc82cfd6783d9c06a1a78794f209`,正文 SHA-256 `5311865227e9c278798b458d722cc54ac362aeb78f4eb52cece394d3608a04ed`,11,723,885 bytes;4 张图片 292,573 bytes。完整导出 `.tmp/rea-workbuddy-session-with-images.json`;元信息证据 `.tmp/rea-workbuddy-copy-metadata-evidence.json`。原版文件未写入。
|
||||
|
||||
## 应用与验证
|
||||
|
||||
YCode 无活动消息后正常关闭,备份 `C:/Users/Administrator/AppData/Roaming/YCode/sessions.json.before-workbuddy-1792078651509.bak`,再以原子替换追加副本并逐字段回读。导入器拒绝活动应用离线写入,检测来源重复时返回已有副本。重新打开 YCode 后实际 IPC 返回 62 消息/691 工具/4 图片;DOM 实际渲染 31 用户及 31 助手,任务标题可见,无提示词包装、无 streaming 消息、无运行时异常。
|
||||
|
||||
报告 `.tmp/workbuddy-copy-report.json`、`.tmp/ycode-workbuddy-copy-ui-report.json`;截图 `.tmp/ycode-workbuddy-copy.png`。真实桌面窗口已显示该会话。
|
||||
|
||||
`test:workbuddy-import`、`test:rea-conversation`、`test:rea-css`(18 模块完整性)、`typecheck` 通过;重复执行导入返回 already-imported,无新增重复会话。
|
||||
|
||||
这是独立历史快照,不恢复原版内核或自动执行工具。完整消息及历史分支原文留在本机 REA 归档;本轮不把导入与展示通过宣称为整段对话的原版像素等价。
|
||||
@@ -0,0 +1,135 @@
|
||||
# 同会话对话区差距评估(2026-10-15)
|
||||
|
||||
当前导入让两端拥有相同的用户问题、助手正文和大部分工具结果,但没有复制原版的完整显示投影。整页差距包含已证实的取消状态误判、工具名规范化缺失和内容块映射缺失,不能继续只靠 CSS token 调整来消除。
|
||||
|
||||
本次是只读评估,未修改生产代码、会话数据或原版。所有原版实现依据均来自已保存的 REA exports;实时截图由主上下文通过 REA 采集。本报告不粘贴原始思考文本、工具输出和图片内容。
|
||||
|
||||
## 样本与证据
|
||||
|
||||
- 原版:WorkBuddy 5.8.2。原会话 `4653e36f-6b2a-446f-a9c9-3f2d2d04644e`,YCode 副本 `6c000be8-b0e8-4768-9a7f-1a0d94a35951`,标题「开始新会话」。
|
||||
- 历史导出:`.tmp/rea-workbuddy-session-with-images.json`,Evidence `ev_3c4593ae51bbee833ca9fcbe3b9ad172d108cc82cfd6783d9c06a1a78794f209`,JSONL SHA-256 `5311865227e9c278798b458d722cc54ac362aeb78f4eb52cece394d3608a04ed`。
|
||||
- 原版脚本:`.tmp/rea-runtime-scripts.json`,Evidence `ev_717fa5e846e64d67ac19c8925d121bff632c0d3aefb3603b10858559cabb2dcb`。
|
||||
- 当前真实画面:`.tmp/rea-assessment-initial/workbuddy.png` / `layout.json`,Evidence `ev_d6e6920ff4e47f73a182fac5312c5f02393366a035445d18c8a6733a8c8a11ed`,2026-10-15T15:47:25.821Z,视口 1336 × 901。主上下文对照 YCode `.tmp/assessment-ycode/panel-closed.png` / `panel-open.png`。
|
||||
- 本地导入产物:`.tmp/workbuddy-copy-session.json`、`.tmp/workbuddy-copy-report.json`、`.tmp/ycode-workbuddy-copy-ui-report.json`。
|
||||
|
||||
原版截图与 DOM 是先后观察,非原子快照;仅证明该会话当前可见范围。不能由最后一轮推断每个历史失败轮或所有展开状态均已验收。
|
||||
|
||||
## 导入目前真实保留了什么
|
||||
|
||||
| 项目 | 原可见分支中的记录 | YCode 副本 |
|
||||
|---|---:|---:|
|
||||
| 用户轮次 | 31 个可见用户问题,另 10 个注入通知被隐藏 | 31 |
|
||||
| 助手文本记录 | 257 | 合并为 31 条助手消息中的 257 个 text part |
|
||||
| 工具调用 / 结果 | 691 / 688 | 691 个工具,3 个无终态结果改为 cancelled |
|
||||
| reasoning | 358 | 1 个 reasoning part |
|
||||
| 图片 | 4 | 4 |
|
||||
| 助手终态 | 249 completed、8 incomplete 文本记录 | 24 done、7 error 消息 |
|
||||
| 富内容 part | 来源还有工具 renderer 与 metadata | 只有 text 257、tool 691、reasoning 1;无 artifact / plan / task / image part |
|
||||
|
||||
2 次 resend-fork-notice 共排除 357 条旧分支记录;31 个用户文本已剥离 prompt context。没有未匹配的工具结果。这些保证的是导入完整性与当前分支选择,不等同于显示结构或交互一致。
|
||||
|
||||
## 已证实的优先差距
|
||||
|
||||
### 1. 用户取消被导成红色错误,且取消提示显示两次
|
||||
|
||||
`src/shared/workbuddy-import.ts:168` 的 `finishAssistant` 优先判断 `lastAssistantError`,只要存在错误文案便将整轮设为 `error`。`src/shared/workbuddy-import.ts:239` 同时把所有 assistant output_text 原样保留为正文。
|
||||
|
||||
第 3、5、8、9、23、31 轮均满足:源末记录 `status: incomplete`,`providerData.error.message` 为 `Interrupted by user`,末正文也为 `Interrupted by user`。导入后两者都保留,形成英文正文和红色错误的重复展示。第 28 轮是 429,不能和用户取消混同处理。
|
||||
|
||||
原版 `workbuddy-provider-DkH2YFYM.js` SHA-256 `b588e875c469978f216beec86bdf4b6c33a31c0266f9bf996881b8dbf37b5dc7`,AST 方法锚点:
|
||||
|
||||
- `isHistoryInterruptedByUserChunk` offset 478633:识别精确文本 `Interrupted by user` 或 `[User Cancelled]`。
|
||||
- `projectHistoryAssistantTextMessage` offset 475180:命中后设 `complete: true` 与 `buildCancelledMessageExtra`,不把该标记追加为普通正文。
|
||||
|
||||
第 31 轮已经通过主上下文 REA 画面闭环:原版显示「已取消 17m15s」和「用户已取消」,历史过程闭合;YCode 同一轮展开历史正文并在底部显示重复英文取消和红色 error。其他 5 个取消轮的具体画面仍须逐轮复核,但导入语义错误已有源码和数据证据。
|
||||
|
||||
修复应保留真实 429 错误,并把可明确识别的取消标记转换为显示终态;不能把所有 error 都粗暴转成 cancelled。
|
||||
|
||||
### 2. 错误终态未进入完成投影,直接拉长页面
|
||||
|
||||
`src/renderer/src/components/MessageBubble.tsx:124` 仅在 `done` 或 `cancelled` 时传 `turnFinished: true`。上述 7 个 error 因此被投影为仍未完成;摘要组的 `isRunning` 也成为 true。原版现代 `computeTurnFinished`(`src-DbE1_mgM.js` offset 975305)依据最后分组、request terminal、会话 busy 等信号计算结束,并不等同于这个两个状态的枚举判断。
|
||||
|
||||
对当前 `completed-fold.ts` 做内存 bundle 后直接调用纯模型,未改会话数据,结果如下。右列是把相同 parts 按终态投影的诊断结果,不能冒充每一轮原版截图。
|
||||
|
||||
| 轮次 | 当前状态 | 当前根渲染单元 | 按终态投影的根正文锚点 | 当前完成 / 过程折叠 | 终态诊断折叠 |
|
||||
|---|---|---:|---:|---:|---:|
|
||||
| 3 | error | 11 | 2 | 0 | 2 |
|
||||
| 5 | error | 17 | 2 | 0 | 2 |
|
||||
| 8 | error | 13 | 2 | 0 | 2 |
|
||||
| 9 | error | 3 | 2 | 0 | 2 |
|
||||
| 23 | error | 3(模型为 null,原 parts 直接渲染) | 2 | 0 | 2 |
|
||||
| 28 | error / 429 | 13 | 2 | 0 | 2 |
|
||||
| 31 | error / 用户取消 | 21 | 2 | 0 | 2 |
|
||||
|
||||
第 31 轮原版已确认闭合,其差距首先是状态与消息投影。取消语义修复会自然修复这 6 轮的主折叠门控;真实 error 轮还需明确原版终态契约。
|
||||
|
||||
### 3. 原版 provider 做了工具规范化,副本直接使用原始工具名
|
||||
|
||||
原版 provider 的 `Bi` alias 表 offset 190005、`canonicalizeToolName` offset 191155,以及 `normalizeWorkbuddyNotification` offset 290986,会在 UI 前规范化工具名和字段;`unwrapDeferExecuteTool` offset 287955 将延迟调用展开为目标工具并改用 `params`。
|
||||
|
||||
YCode 导入 `src/shared/workbuddy-import.ts:261` 直接保存 `record.name`。`ToolCallRenderer.tsx:102` 的有限 alias 表不能替代 provider 全流程;`MessageBubble.tsx:65` 的分类又另有一份不完整名单。
|
||||
|
||||
| 本会话原工具名 | 次数 | 原版规范化或专门路径 | 当前 YCode |
|
||||
|---|---:|---|---|
|
||||
| TaskCreate / TaskUpdate | 10 / 14 | `todo_write`,provider 还调用 `todoManager.ensureNormalized` | 无 alias,走通用卡片 |
|
||||
| DeferExecuteTool | 12 | 解包目标 `mcp__rea__*` 工具及 `params` | 通用 DeferExecuteTool 卡片 |
|
||||
| present_files | 10 | 存在专门 compact view 与产物来源识别 | 通用卡片,未生成 artifact part |
|
||||
| AskUserQuestion | 1 | `askuserquestion`,inline question 分类、回答恢复 | 大写名称未命中 question renderer,也未命中 MessageBubble inline 分类 |
|
||||
|
||||
这 47 / 691 次调用确定进入现有通用兜底。另 644 次虽然命中某个已实现 renderer,并不代表已完成内容、展开默认值、预览和像素验收。
|
||||
|
||||
`present_files` 的 10 个调用含 21 条文件引用(可能重复),副本没有 artifact part;原版当前画面有「13 产物」入口。文件引用不是 13 个独立产物的等价计数,必须恢复原版产物提取、过滤、去重、归属与入口,而非直接将数字设为 13。
|
||||
|
||||
### 4. 正文 spacing 还没有消费原版的排列结论
|
||||
|
||||
原版 `src-DbE1_mgM.js` SHA-256 `6c6ce63c93854783270e855572797d75e536e3b8d4548410e31fe9d147e1feb4`,`markBodyTextSpacing` offset 946304,按最后正文、前一个非空块是否工具、回合是否结束,分别输出 `both` / `top` / `bottom` spacing。
|
||||
|
||||
YCode `MessageBubble.tsx:172` 仍只按 `index > 0` 添加 `cr-text-block--spaced-top`,其适配 CSS 只有 `margin-top: 12px`(`source-adapters.css:15`)。`CompletedFold` 已返回 render context,但这里没有使用它恢复原版 spacing。即使相同文本和字体,混排正文与工具、折叠前后相邻关系仍会产生系统性间距差异。具体像素影响需在相同展开状态截图上测量。
|
||||
|
||||
## 已知信息损失及验证边界
|
||||
|
||||
### reasoning:有源字节,但还不能凭 JSONL 直接认定全部应显示
|
||||
|
||||
可见分支中 357 个 reasoning 的 `content: []`,但 `rawContent` 是 `[{ type: 'reasoning_text', text: ... }]` 形状,另 1 个有显式 content。导入器 `workbuddy-import.ts:254` 明确排除 rawContent,所以当前只保留 1 个 reasoning。
|
||||
|
||||
已经证明数据在导出中存在,不是无法取得源码或缺少字节。仍未证明原版历史回放会把这 357 个 raw reasoning 全部投影为可见思考块:已保存 renderer/provider 脚本不含 JSONL 的 reasoning_text 处理入口,该环节可能在 daemon/replay producer。必须通过 REA 查回放转换或选定展开状态观察后,按原版显示契约转换,不能仅因存在 text 就展示全部 raw reasoning。
|
||||
|
||||
若需要显示,缺失 reasoning 会改变连续 foldable 段、工具摘要中的消息数及展开内容;只恢复字体无助于此。
|
||||
|
||||
### 模型信息、消息身份与合并
|
||||
|
||||
原可见 assistant 记录含 requestModelId/requestModelName/model;222 条来自 deepseek-v4.1-flash,28 条来自 glm-5.3-flash,7 条取消/失败末记录没有模型字段。副本 assistant 只保留 id、role、content、createdAt、status、parts、tools、turnDurationMs,缺少模型显示、request 身份和原消息边界。
|
||||
|
||||
导入将每个可见用户问题后的全部助手记录合为一条;原版 provider 按 messageId/requestId 累积再交给上层分组。`projectHistoryAssistantTextMessage` 对同一 message 的相邻同类型 text/reasoning 会直接连接;YCode 每条 assistant source record 单独成为 text part,content 再用两个换行连接。
|
||||
|
||||
当前样本存在 257 个文本记录、约 250 个非空 provider messageId。合为 31 条并不必然错误(原版也有 turn grouping),但不能仅用 31/31 消息数证明分组等价。须比较按 turn 的有序「显示块树」,包括同类型连续连接、去重、正文锚点、source ID 到显示节点的映射。恢复模型显示可以保留纯展示 metadata,无需接入原服务端模型。
|
||||
|
||||
### 工具结果与 metadata
|
||||
|
||||
当前 688 个结果的 renderer 类型:text 336、list 1、code 101、diff 188、todo 24、无 renderer 38。导入保留 title/content/renderer/rawResponse/error/acpV2PlanSnapshot,并把 rawResponse 放入当前专用视图会读取的 namespace,不能笼统声称 rawResponse 全丢了。
|
||||
|
||||
丢弃字段中有 10 个 terminalId 和 12 个 mcpMeta。历史副本不应恢复可执行原 terminal/session,但可以根据原版显示需要保留经白名单转换的静态展示字段。需要区分「为了避免恢复执行态而不导入 native ID」与「因此连静态显示内容也缺失」。todo renderer 的 24 份计划/任务快照已有字节,主要先解决规范化和对应 view 接入。
|
||||
|
||||
### 耗时
|
||||
|
||||
当前 turnDurationMs 取该用户 timestamp 到本轮已接收的最后助手/工具结果 timestamp;原版 `computeTurnDurationMs`(`src-0FGg1seX.js` offset 757590)取分组内用户 createTime 与 assistantEndTime,并跨连续助手组查找。现代 renderer 也消费 extra.turnDurationMs/assistantEndTime/processingStartedAt。
|
||||
|
||||
第 31 轮导入值 1,035,822 ms 格式化为 17m15s,恰与当前原版截图相同,因此这一轮耗时不构成已证实差异。其他轮、跨请求或后台工具结束晚于助手的情况仍应逐轮比较,不能直接换一个估算公式就宣称修复。
|
||||
|
||||
## 长任务应先处理的顺序与验收
|
||||
|
||||
1. 建立本会话按 source record/provenance 回溯的显示块树基线,分清取消、真实失败与正常完成;先修 6 个明确取消轮及最后一轮闭合效果。
|
||||
2. 恢复 provider 展示规范化层:alias、defer 解包、question 回答/分类、todo snapshot 与 present_files 产物归属;执行层继续使用自己的实现。
|
||||
3. 完成原版 spacing、模型显示 metadata、附件/产物入口和历史工具默认展开状态,再做 CSS/图标/尺寸修正。
|
||||
4. 对同一会话至少覆盖首轮、带图片轮、工具密集轮、提问轮、todo 轮、取消轮、429 轮、最后一轮;每个点记录原版 REA Evidence、原窗口尺寸、主题、左右面板状态、滚动锚点和每层折叠状态。
|
||||
5. 验收先比较显示块树与可见文本/状态,再比布局矩形、字体、截图像素及操作结果。整页差异不能用少数通用 fixture 通过代替。
|
||||
|
||||
阻碍目前主要是数据到 UI 的转换契约和真实状态覆盖,已有脚本、历史字节和 REA 画面足以开始修复。reasoning 的历史显示契约及部分原版回放 metadata 是明确未知项,需要 REA 补证;不需要为上述已证实问题先接入云端服务或子代理调度。
|
||||
|
||||
## 本次验证与修改范围
|
||||
|
||||
- 只读统计 REA JSONL,按已存在 resend-fork-notice 规则选择当前分支,再和副本数据计数比较。
|
||||
- 使用 `@babel/parser` / `@babel/traverse` 只解析 REA 保存的脚本文本,记录上述 AST 方法与字符 offset、脚本 SHA。
|
||||
- 使用 esbuild `write: false` 将本地 completed-fold.ts 内存打包,直接调用纯模型复现 7 个 error 轮的门控差异;没有修改生产代码或生成替代会话。
|
||||
- 主上下文提供最后一轮原版 REA 与 YCode 真实画面对照。没有自行重复 live 采集。
|
||||
- 本子任务唯一新增文件:本报告。未运行构建或回归,因为无实现变更;纯模型诊断及数据审计均成功。AST 首次遍历遇到无名称 class method,补充空值判断后完成,只读操作未留下文件改动。
|
||||
@@ -0,0 +1,144 @@
|
||||
# WorkBuddy 连接器复刻评估(2026-10-16)
|
||||
|
||||
当前可直接推进原 DOM/CSS 的商店、详情、搜索、自定义 MCP 列表和配置界面;真正可用的连接器还需要连接状态服务、凭据与授权流程、MCP host,以及会话工具选择/执行链路。YCode 现有工具展示组件不等于已实现 MCP 连接。官方目录、企业下发、WorkBuddy OAuth 中转与账号绑定包含 WorkBuddy 服务依赖;YCode 可实现自己的目录、授权和 MCP host,但不能把相同界面或受控测试成功称为原版云端等价。
|
||||
|
||||
本轮仅静态评估与拆解。没有改生产代码,没有安装 MCP、添加/启用连接器或授权任何账号。没有通过直接原版文件、CDP、WebSocket、evaluate 或旧文档取证。
|
||||
|
||||
## 证据、范围、校验
|
||||
|
||||
版本 **WorkBuddy 5.8.2**;固定安装包 root pin **035254bc76310ea46317433e4840602094543ef323d2d5c5aff7c131729de918**。后续需要增补主进程/daemon 时,仍应通过 public REA 选中路径 export 并固定此 root;本轮未增补读取安装包。
|
||||
|
||||
- **S1**:`.tmp/rea-runtime-scripts.json`,REA `ev_717fa5e846e64d67ac19c8925d121bff632c0d3aefb3603b10858559cabb2dcb`;339/339 脚本文本按 UTF-8 SHA-256 验证通过。
|
||||
- **S2**:Root 新采 `.tmp/rea-expert-runtime-scripts-20261016.json`,`ev_e91787b1d4dea651582c6cf12827775b9068b0ee8b80c68ba08d4c1d87d94e90`;329/329 通过,共有同名脚本没有 hash 变化。本轮实现结论以 S1 为主。
|
||||
- **C1**:`.tmp/rea-css-recovered/manifest.json`,`ev_377c8790468b3c67dad8577aabb327f98d3140659f0fffdbabfcff5a40cc9e94`;下列 3 份连接器 CSS 实际文件 hash 已复验。
|
||||
- **V1**:Root 原版连接器页 action 后 PNG `.tmp/rea-market-connectors-20261016/frame-000.png`,`ev_d0183b5ee9e28b74126f773e134d9e4b1e856fcc67083212c6e258813c9ea890`。该操作记录顶层 layout 属于 action 前,不能作为连接器页布局证据。
|
||||
- **V2**:Root 随后静态捕获 `.tmp/rea-market-connectors-static-20261016/layout.json`、`workbuddy.png`,`ev_e91bdc6e46275f4460985cfff25fd7f7bc334afc45f49fac1935de1249f4cb22`,PNG SHA-256 `2a537f83fcad50cf355668cc007c70f48446c7d92dc9a3a6ec388b84c4b12854`。这里已存在连接器页 DOM。V1 可见“专家/技能/连接器”、搜索框、“自定义连接器”、三列卡片/加号;不能由此证明连接健康或成功授权。
|
||||
- **V3(partial)**:Root `.tmp/rea-connector-detail-20261016/frame-000.png`、`frame-001.png`,`ev_b898a87832d1e800810d391145a6ec6c6999e98b5cea6c7f382a3fc19aa7b3ac`。frame 000 为 QQ 邮箱主体点击后的详情,frame 001 为 Escape 后仍打开的详情。Root 报告操作 steps 成功,但 neutral-pointer cleanup 被取消,因此 overall failed,不能把整条 probe 说成 PASS;顶层 layout 属于 action 前。两帧本地 SHA 分别 `0b4c3fd29fdedded1fafd7e53e4b1216a3ac3d9117ff6acb6a41269b99e4f6bc`、`38d15afce56622e03e50b93cbb52aaeb8174028faed83483e5729e6bef25786d`。
|
||||
- **V4**:Root `.tmp/rea-custom-connectors-static-20261016/layout.json`、稳定 `workbuddy.png`,`ev_b89281177f6a1cf2e4697887d576b8ddf7d811a8fa2d1148b7024a4ec898906f`,PNG SHA-256 `8d76ef16a32d9415bb8116715b386df5fbd0c11f498837e74df083004bcfcd5d`。可见“MCP 服务管理”“我的 MCP(4)”“3 启用”、搜索/Hub/添加、80 工具警告、4 个现存 server 与工具数/健康点/开关。这里只观察现存状态,Root 没有 toggle/connect/save/auth。最初半透明过渡帧不作为稳定像素基线。
|
||||
|
||||
新增 `scripts/audit-connectors.cjs` 只读上述工作区 REA 归档,不读取原版路径、不执行源 JS。默认生成 `.tmp/connector-assessment-20261016/integrity-and-anchors.json`;`--find <精确文件名> <文本...>` 和 `--excerpt <精确文件名> <start> <length>` 可复查。下文 offset 都是 **0 起始 JavaScript UTF-16 字符偏移,不是字节偏移**。
|
||||
|
||||
| S1 归档脚本 | SHA-256 | 核心锚点 |
|
||||
|---|---|---|
|
||||
| `skills-panel-CvMlV3m8.js` | `b30c43c11ec476db639d6be58065d927411845487d34b0ea8e839d1c6eb7a238` | `ConnectorPanel` 62950;`McpPanel` 27216;`McpConfigEditor` 20816;`ConnectorDetailSetting` 11484 |
|
||||
| `store-BKmTj0KI.js` | `ea51bfd988c299d00574dccdb28f73c199502d79074da9ae560031a3307a2f89` | `createConnectorCatalogGateway` 8673;状态投影 19577;`executeConnectorAction` 51049;cancel 57566 |
|
||||
| `use-connector-actions-DhLHDumM.js` | `04d7f42118e0d6190fde9fda001baef7ccfa78bc1035be31a35bd2c029b1c3a8` | `useConnectorActions`;handleConnect/Repair/Disconnect/Cancel;5 分钟 pending-auth 追踪 |
|
||||
| `open-deeplink-connector-store-GkwgNaZv.js` | `56095700d10ad8427243a03fb3257ce9df11b308e19b7287af5d39eefff2f9d3` | `setOpenDeeplinkPendingConnectors`、remove/clear;去重 ID 集合,非商店实现本体 |
|
||||
| `connector-token-config-gate-DtzOLq6x.js` | `da8bd45173a3d000dfa025481f29f196ff51bf1002ea9189d6d69e08c5d2825c` | `runTokenConnectorSaveFlow` 513;Gate 1154 |
|
||||
| `connector-token-config-modal-DXJvYxRD.js` | `16560cc681eb38e34be8687350d3782903a28ca6df9f9c4029939968e65887bf` | 必填 327;payload 574;初值 747;Modal 1342 |
|
||||
| `connector-device-code-modal-ClMm_s3k.js` | `ced26ec4253dc675267f136451322376cc81bf0d3f14cd86f73fffac49b720d7` | `formatRemaining` 1022;Modal 1173;Host 4434 |
|
||||
| `connector-runtime-toast-DmevVoHX.js` | `97431e4b57a37c3be9973e83903c99f860a43f3a8a226fbb5e2f6d64955384fa` | `ProgressToastBody` 618;Subscriber 1237 |
|
||||
| `oauth-contract-D3wxpVaW.js` | `39621f3478f1c56dcb2d0080581500d2036c2306baa10665ddca3481c3160b4f` | `readAuthScope`、`notifyIfAuthExpired`;account/runtime 过期分流,不等于 connector OAuth 后端 |
|
||||
| `connector-icon-C4VuqOCA.js` | `c14c59b43943fe4af821cb6155171dca1a3502743fa70deb65dbb16ad334d2cc` | 详情批量补齐、stateful 目录合并、图标失败 fallback |
|
||||
| `mcp-server-loader-DFUSVF9N.js` | `b37999cd9a1e38450f8ff30ce4ceb0f08ff3aca249135e77b426cf95c6a58db6` | `getMcpServersDedupedWithMeta`、`mergeMcpDescription`、状态/来源投影 |
|
||||
| `contexts-BMeWSUHk.js` | `5f35b7489b107e21ef452c8ee88a95265756f6fc444841eef869228bbc44768b` | `useConnectorFacade` 1762814;keyword filter 3526103;专家依赖 3934216;会话选择/注入 6072687/6076938 |
|
||||
| `workbuddy-provider-DkH2YFYM.js` | `b588e875c469978f216beec86bdf4b6c33a31c0266f9bf996881b8dbf37b5dc7` | `pollAuthStatus` 14550;`DesktopConnectorManager` 15291;desktop localOps 约 35200 |
|
||||
| `adapters-SPAem2E3.js` | `b1f740a608087d6ede5a94f3b485c189e3b57698a79aff4b07da9c66acfae1ba` | client.sessions MCP 113602;getConnectorConfigs 117713;updateConnectorEnv 120264 |
|
||||
| `common-DRZ6FwkK.js` | `924f348494323c3b09cfbde84f7729a178cd95a72e4f9ca654859c75fec9e2f5` | BackendProvider `/console/as/connector/user/`、task 约 430350–432500 |
|
||||
| `runtime-B7PLES2V.js` | `b944fdfed0d52ca4c588833f94f50f878169a9244c05ed186abfa4eb37957911` | `connector:init/getConfigs/getStates/connect/repairConnect/...` IPC 常量约 7260 |
|
||||
| `wb-CocRQn4C.js` | `d9ddb5d5464f2d863659a01493b58220bb5a0e270c22b16f405cfaeab2a7a972` | reason→动作 28900;bridge authorizer 89000;connectors/mcp/cloud guest proxy 101851 |
|
||||
| `wb-input-add-B045GnIg.js` | `7842fa4321d5351bf6c822bbd0253e0d6d6e68cc9cfae3f2470b3d493c23daf4` | `sortConnectorsLikeCapsule` 22935;ConnectorsSubmenu 约 24200 |
|
||||
| `desktop-sdk-setup-C2AUiJmx.js` | `ac3bdeb6d81776491e175ddfae262e64f77d3dc9c0821d6075a91bf1b889dc23` | `prepareInput` connectorIds→UI/configManager 约 376400 |
|
||||
|
||||
| C1 CSS | SHA-256 | 已归档内容 |
|
||||
|---|---|---|
|
||||
| `skills-panel-CsnIUki4.css` | `c1d5c5de51554a886fde0399c5202cd45063fa091b213b842014bea91dbb69a0` | 59,787 bytes / 470 rules,包含连接器与 MCP 面板规则 |
|
||||
| `connector-token-config-modal-B4MFl7DI.css` | `08a4b349ae9020ad87fe798e2b5ea44f77f38ea46f5b4e7b4daa97fd21a297f7` | 4,610 bytes / 32 rules |
|
||||
| `connector-device-code-modal-DLS20fDt.css` | `b6ed4f94669f02815fb2969bfd2e8b6cbf40097c8840343e0a080480415d6bd8` | 4,818 bytes / 30 rules |
|
||||
|
||||
## 已知实现与原版边界
|
||||
|
||||
### 商店、已添加、搜索与详情
|
||||
|
||||
`ConnectorPanel` 是实际连接器页。local 模式保留目录顺序,逐项映射 installed/available 卡片;非 local 会先显示 installed 再 available。installed 判定是 **bound 或 connected 或 pending 或 enabled 任一为真**,不是只有 connected。状态有 disconnected/connecting/connected/unauthorized/error,reason 类型驱动重授权、配置、重连、升级或联系管理员。
|
||||
|
||||
目录 gateway 支持 local `listMarket({start,limit,includeStateful})`,每页 50;market 模式才使用服务端 search/getDetails,legacy 模式在已加载名称/描述上过滤。列表与搜索分别有 loading/loadingMore/hasMore/cursor;搜索 trim、200ms 防抖、IME composition;epoch/关键词检查防止旧响应覆盖新结果。`useInfiniteScroll` 用 200px 接近阈值。初次列表 skeleton 数 9,面板加载超时 20s。详情补 examples 与 stateful 目录缺项,按 ID 去重。
|
||||
|
||||
本版本 `ConnectorPanel` 源码有 conditional **official/enterprise** tab:仅存在企业专有连接器时显示;没有证据表明这里必有“办公/开发/设计”或更多固定分类,不能把专家页分类移植成连接器分类。V1 当前画面没有该企业 tab,目录内容随服务和账号变化,不能写死为完整永恒清单。
|
||||
|
||||
卡片主体点击仅展示详情(必要时只读补 examples),卡片 `.connector-card-action` 的加号独立 stopPropagation 后连接。详情有名称、描述、图标、版本不兼容提示、最多 10 个 examples、连接/重授权/配置/试用/重置、已安装且存在 tools 时的可展开工具名与描述。背景点击/关闭按钮关闭详情。试用先确保连接,再 `conversations.prepareInput({target:{type:'new'},contentBlocks,connectorIds})`,不是静态提示文案。
|
||||
|
||||
V3 已只读观察 QQ 邮箱详情的未连接态、examples 与滚动截断;Escape 在该观察中未关闭,关闭按钮随后由 Root 使用。不得把其他 modal 的 Escape 规则擅加到该详情。没有点击“连接”或 examples,因此没有真实授权行为。
|
||||
|
||||
`open-deeplink-connector-store` 文件名容易误导:其中主体是首页草稿与 pending connector IDs 去重集合。商店列表和详情主体位于 `skills-panel`,不能仅复制 deeplink store 当成商店实现。
|
||||
|
||||
### 添加、Token 配置、OAuth 与 device code
|
||||
|
||||
存在至少两条 Token UI 路径,不能强行合成一个返回 success 的表单:
|
||||
|
||||
1. schema 多字段 modal/gate:`tokenConfig.fields`,字段 key/label/type/required/defaultValue/placeholder/description,title/description/docUrl/docLabel。password 必填允许已有 `hasSecretFields` 且本次留空;password 空白不进入 env payload,其他字段即使为空也提交。初值优先 initialValues,非 password 才采用 defaultValue。修改清对应错误/submit error;第一字段 autofocus、最后字段 Enter 提交;保存时 input/close/cancel disabled,Escape 仅非 busy 可取消。overlay 没有 click-away cancel handler。
|
||||
2. 新 `action-required/form` 分支:store 取 fields 的第一字段 key(缺省 token),显示 connectorTokenPrompt,submit `{kind:'form',values:{[key]:token}}`。Token invalid 可以保留表单重试,CLI_ 错误有终止分支。须在后续 UI 采集中区分它与多字段 modal。
|
||||
|
||||
Gate 的保存顺序是 **updateEnv 成功 → connect**。保存配置失败与连接失败分 stage;connecting 可返回 pending 而不是 connected。connect-failed/secretInvalidated 可再次打开配置并丢弃“已有 secret”标记;取消会调用真实 cancelMcpConnector。渲染端支持 hasSecretFields 不等于已经证明主进程凭据加密或“原版永不返明文”:buildInitialFormValues 对传入 string initialValues 也会设置 password,真实 adapter 返回值边界仍需后端证据。
|
||||
|
||||
`DesktopConnectorManager` 分 local、server-side、gateway 和 projectConnectorAuth。server-side 可从 service.authAccessToken 取 token 写 Authorization header;userInitiated 会走 authRevoke 后重新 OAuth。gateway 的 authStart 可能返回 connected、show_form 或 redirect;redirect 打开外部浏览器并轮询 authStatus(1.5s,默认期限 5 分钟/服务提供 expireAt,AbortSignal 支持取消)。这证明接口和前端分支,未证明任何账号实际授权成功、token refresh/PKCE/state 校验实现。普通本地连接转 localOps;WorkBuddy service facade 与本地操作同时存在。
|
||||
|
||||
device code 从 `connector:device-code` 事件取得 verificationUri/userCode/expiresIn/codeEmbeddedInUri。Modal 每秒更新时间、剩余不足 60s 高亮、到期调用 onExpired 或 onCancel;复制 code/link 成功提示 2s,Clipboard API 有 textarea fallback;可只有 URL 没有 code。Host cancel 会关闭 modal 并 cancelMcpConnector。Modal 声明 `onOpenInBrowser` 但本体此归档没有调用该 callback;打开浏览器可来自 action flow 或链接,不能推断“显示 modal 必自动打开”。QR code 有独立 `connector:auth-qr-url` 分支,也应保留待验。
|
||||
|
||||
### 自定义 MCP、健康、工具、删除与 trust
|
||||
|
||||
“自定义连接器”入口仅 local 且企业 customConnectorPolicy 允许时展示。入口刷新 policy、打开 McpModal 并只读计数;不是直接安装/启用。McpPanel 使用 `wb.mcp.list/describe/setEnabled/connect/beginAuthorization/remove/setToolEnabled/approve`。UI 的 connected/connecting/idle/disabled/disconnected 是 host 状态投影;工具列表、prompts/resources/resourceTemplates、来源 plugin/marketplace、editable、trusted/configHash 均影响操作。缓存 500ms、并发 list 去重;connecting 轮询 5s、最长 60s,隐藏窗口暂停。官方 connector store 的 pending poll 为 3s/最长 60s,状态 event 与异步 snapshot 的写入代次/intent guard 防回滚;两个 poll 不应混为一个。
|
||||
|
||||
自定义配置不是简单“名称+URL”表单:`McpConfigEditor` 为 JSON Monaco 编辑器,显示真实配置路径、dirty 标记,Ctrl/Cmd-V 支持 host clipboard,返回时确认未保存改动。空文本规范化 `{mcpServers:{}}`,JSON syntax 和顶层结构校验;兼容把误套的 mcpServers 扁平化。此处 validator **只证实结构**,不能据此宣称所有 command/args/env/HTTP/stdio/SSE transport 均已校验或支持。保存全配置走 `wb.mcp.saveConfiguration`,具体后端原子性/启动方式尚未知。
|
||||
|
||||
未信任 server 的 toggle 强制关且 disabled;有 approve 按钮,调用 **approve({id,configHash}) → setEnabled → connect**。服务/工具操作 busy 去重,工具 disabled/外层 server off 不可点;>80 个 enabled tools 有警告。OAuth unauthorized 的 reconnect 可调用 beginAuthorization 后外部浏览器,避免重复 authorizing。网络错误有 reconnect/troubleshooting/copyLog。
|
||||
|
||||
三种操作必须区分:
|
||||
|
||||
- **disconnect/disable**:停用当前连接,可保留 bound/已授权关系;会话选择 off 也有 selection-only 分支。
|
||||
- **unbind/reset 官方连接器**:详情实际调用 `wb.connectors.unbind`;manager 可先 service.authRevoke 或腾讯文档 revoke,再 local unbind。企业 oneidGate/admin 权限可阻止,builtinPluginId 可隐藏重置按钮。不能把它实现成简单本地删一行。
|
||||
- **remove 自定义 MCP**:editable 条件下进入确认框后 `mcp.remove(id)`;非 editable/plugin 来源项不应随意显示相同删除入口。源当前详情 unbind handler 本身没有二次确认框;legacy connector revoke、MCP remove 则有确认。
|
||||
|
||||
runtime toast 单独处理 `connector-prepare` 与 `connector-install`、progress/complete/error,按 operationId 去重,进度可无百分比,complete 延迟 300ms 关闭、error 5s。这说明存在二进制/package 准备/安装流程,不能用 loading UI 冒充安装已实现。实际包分发、校验、可执行进程与 transport 不在本轮 renderer 证据内。
|
||||
|
||||
### 会话工具注入、权限和凭据
|
||||
|
||||
`useConversationConnectorSelection` 把 enabled 选择写 `conversation.config.setConnectors`,保存 name/displayName/description/connectStatus/activeStatus。后台 automation 的 selectionOnlyToggle/scope 来自已持久 config;scope cache 以会话 ID 分离,删除清理。lookup missing 与 unresolved 有区别,只有确定 missing 才 reconcile 删除;外部 auth 完成可自动选择。普通 local 与 cloud-input 操作取不同 facade/runtime key;必须保留不同会话/传输边界。
|
||||
|
||||
`prepareInput` 将 connectorIds 同步给输入 UI/configManager;send diagnostics 获取真实 states,不可把菜单“已选中”当作 supplier tools 已注入。专家依赖另有 connector connect/repair 与 custom MCP import/connect/authorize 路径;importServer 冲突可在该依赖分支重试 overwrite。实际工具如何注册内核、名称空间冲突/权限、进程调用与结果回写仍需 host/daemon证据及端到端验收。
|
||||
|
||||
SDK connectors/mcp/cloud 是 guest proxy;bridge 具有 trusted subject/authorizer 分支。MCP UI approve/configHash 是信任边界的可见证据,但不是已证实所有 host 调用都被正确授权。企业 policy、authScope(account/runtime)、登录过期、connector reason 和每工具 enabled 状态需要分别处理。原版 secret at rest、日志脱敏、OAuth callback/state/refresh/revoke、取消后迟到回调无副作用都没有真实认证验证;不能由 renderer 猜成已完成。
|
||||
|
||||
## YCode 当前真实基线与依赖
|
||||
|
||||
本轮只读当前 YCode:`SettingsDialog` 的 supportedTabs 为 models/appearance;Sidebar 非新建任务导航仍提示尚未实现;`src/main`、`src/shared`、`src/preload` 的 connector/MCP 检索没有连接器 host/API 实现;`agent/tools/index.ts` 的 ALL_TOOLS 是 8 个本地文件/命令/问答/计划工具。现有 `workbuddy/conversation/ToolCallRenderer.tsx` 可展示 MCP 名称/参数/结果,recovered summary/词典包含 MCP 文本,均不构成运行 MCP 的证据。模型凭据存储已有实现也不能自动推出连接器凭据已接入。
|
||||
|
||||
| 范围 | 可由 YCode 自有实现 | WorkBuddy/第三方依赖或未知 |
|
||||
|---|---|---|
|
||||
| 原 DOM/CSS/搜索/详情/空态/busy | 可按固定源码及 REA 画面恢复 | 更多尺寸、hover、暗色、动态异常的原版基线待采 |
|
||||
| 自有目录与已添加持久化 | 可定义自有 catalog/provider 适配与 registry,保留状态契约 | 官方 listMarket/search/details 排序、更新、资产和企业目录依赖原版服务;静态快照不能称实时商店 |
|
||||
| Token/环境配置 | 自有 secret store、schema/blank-preserve/update-then-connect 流程 | 每个连接器的真实 token scope/可用性需第三方配置与验证 |
|
||||
| OAuth/device/QR | 自有授权状态机、外部浏览器/回调、取消/过期界面 | 不能复用 WorkBuddy 私有 account token/client registration;自有第三方 OAuth app/redirect 配置是实际依赖 |
|
||||
| 自定义 MCP host | 可实现 list/describe/tools/resources/prompts、trust、连接/取消/删除 | transport/包安装/原版 daemon 细节尚未证实;需要受控 server 与真实内核端到端 |
|
||||
| 会话选择/注入 | 可接现有 session/OMP host tools,主上下文决定接口 | 当前 OMP 通路通过不等于动态 MCP 注入/审批/取消等价 |
|
||||
| 企业管理、server-side OAuth、项目授权、WB内置业务 | 自有服务可另行提供对应能力 | 原版企业 policy、registry2cList/revocation、腾讯文档/ima/乐享 oneid gate、云任务 APIs 等依赖 WB/第三方;无权限不能伪造成功 |
|
||||
|
||||
这里是任务/依赖建议,不替主上下文决定生产模块架构或授权账号。
|
||||
|
||||
## 可委派任务与验收矩阵
|
||||
|
||||
建议先冻结一组只读原版基线和状态契约,再分界面与 host 两条实现任务;未接入后端的状态只能在显式 QA fixture 演示,不写回生产“已连接”。
|
||||
|
||||
| 任务边界 | 交付与依赖 | 验收状态 |
|
||||
|---|---|---|
|
||||
| A. 商店/详情 source UI | 新连接器 page/modal 组件及作用域化原 CSS;依赖 catalog/state props | 1336×901 V2 原几何/字体/卡片/搜索;长标题、图标失败、空目录、无结果、load failure/retry、分页/stale search;官方/企业分支独立 |
|
||||
| B. MCP 管理与配置 UI | McpModal/McpPanel/JSON editor source DOM;仅UI helper与明确 host callbacks | 空/连接中/健康/未授权/错误/disabled/untrusted/readonly plugin;工具 toggle;JSON syntax/schema/nested/blank/dirty/cancel;删除确认;原版像素以采样状态逐个验证 |
|
||||
| C. Token/device/QR UI | 两种 Token 路径分别恢复,通用 schema helpers、source CSS | 必填trim/已有secret留空/新secret/默认值、update失败/connect失败/pending、busy Enter/Escape、取消;device 无code/embedded/复制失败/低剩余/过期。原版未真实授权的状态标未验 |
|
||||
| D. 自有连接状态服务 | registry、op queue、generation/intent guard、bounded poll/event、cancel/repair/disconnect/unbind | 重复connect、迟到snapshot、搜索换代、窗口隐藏、取消后迟到success、restart恢复;禁用与解绑不混;具体生产文件由主上下文分配 |
|
||||
| E. 自有 MCP host/凭据 | trust/configHash、server/tool enable、describe/resources/prompts、secret storage、host生命周期 | 自有受控 MCP server证明list→connect→toolcall→结果→cancel/remove;未trust不启动、config变更重审、密钥不回显;安装/transport支持只按实测声明 |
|
||||
| F. 会话与内核接线 | per-session选择/scope、prepareInput、动态工具注册/执行/approval | 两会话不串、selection-only不开新全局连接、disconnect后不发工具、tools:false不注入、MCP错误/cancel不混done、历史回放;必须真实 App/preload/IPC→OMP→MCP 验收 |
|
||||
| G. 第三方授权适配 | 在明确用户授权后接自有 provider OAuth/device/token;不使用WB私钥/账号 | 真实提供方 success/deny/expire/cancel/revoke/reauth/刷新;原版服务无法访问的分支独立标依赖,不拿受控PASS替代真实auth |
|
||||
|
||||
每个任务都需返回修改文件、source Evidence/SHA/offset、验证命令与结果、未验状态。视觉验收需要同内容/同宽度/同主题/同渲染条件和严格像素报告;token 一致/编译通过不能算 UI 或服务全量 1:1。
|
||||
|
||||
## 下一批只读取证与未知项
|
||||
|
||||
Root 当前独占原版 runtime,本 worker 未操作原版。已确认可只读采:card 主体详情;“自定义连接器”入口打开 MCP 列表;配置编辑页展示读取。不要误点 card action plus、详情连接/试用/reset、MCP toggle/reconnect/approve/remove/save。
|
||||
|
||||
已补 V3 QQ 邮箱未连接详情 action 后截图(partial,无 action 后 layout)和 V4 稳定现有 MCP 列表截图/layout。尚需:详情 action 后静态 DOM、MCP empty/config editor 基线;搜索文本及清除/IME/空结果与分页;原版现存 server 展开后的 readonly tools/prompts/resources;企业 tab 是否可观察;暗色/窄宽/hover/键盘 focus/滚动和 toast 动效。Token/device/QR auth 动态状态本轮不触发,后续需明确授权或经 REA 的受控原版场景,不能用 YCode fixture 冒充已观察。
|
||||
|
||||
核心后端未知:主进程 connectors/mcp namespace 的实现路径、daemon RPC 与具体 transport/schema、安装包下载/完整性/重启策略、secret at rest/refresh/revoke、服务端 state machine/回调校验、会话工具实际注入/权限。图标有失败 fallback 的源逻辑与 V1/V2 外观,完整实际图标资源尚未逐项经 REA 导出,不能用截图存在代替资源字节已恢复。客户端可读分支已足够拆任务,但尚不足声称完整连接器功能已能 1:1 等价。
|
||||
|
||||
## 本轮验证
|
||||
|
||||
`node --check scripts/audit-connectors.cjs` 与 `node scripts/audit-connectors.cjs`:退出 0;339/339 baseline、329/329 supplementary script hashes、3/3 CSS hashes 通过,同名 source 无变化。25 个相关脚本的 SHA/function offsets 已写机器报告;3 份归档 workbuddy PNG 与 V3 的 2 份 action frame 均按 REA 声明 hash 复验,并保留 V3 failed/steps/restoration 原始状态。所有原版事实来自上述 REA 归档;未跑生产修改测试,因为没有生产修改;未真实 auth/安装/启用。
|
||||
@@ -0,0 +1,156 @@
|
||||
# WorkBuddy 专家:源码评估与实现拆分(2026-10-16)
|
||||
|
||||
本轮仅评估,未改生产、未安装或启用专家、未向原版发送消息。所有原版输入均为 REA 已保存记录,补采安装包文本使用 REA public `export-selected-artifact-text` 并固定 ASAR SHA。未使用历史 CDP 文档作证。
|
||||
|
||||
**结论:专家页面及选择菜单有足够源码可做严格恢复;真正的专家能力涉及插件包、会话绑定、依赖连接和对话驱动创建,当前证据不足以把它缩成一张 prompt CRUD 表。** 创建/编辑入口在原版注入 `expert-manager` 技能及提示词并返回首页;本地 daemon 的包处理与实际 agent 执行仍需补证。云端商店、分享、购买及同步有独立服务依赖。
|
||||
|
||||
## 证据与身份
|
||||
|
||||
目标版本 **WorkBuddy 5.8.2**,根 ASAR SHA-256:
|
||||
`035254bc76310ea46317433e4840602094543ef323d2d5c5aff7c131729de918`。
|
||||
|
||||
版本依据:REA `ev_2caae424199a38371af743ef9111db835504c2dae54c1f02e1f9e5511032cc6b` 中 `package.json`,SHA `a295ae602e936abda5ae45f7a5c21fc481014989d2cf369182d3ce5d9dd400c2`,`name=@genie/workbuddy-desktop`、`version=5.8.2`、`main=main/index.js`。
|
||||
|
||||
下表缩写用于后文逐项定位。JS/CSS offset 为 **UTF-16 字符索引、end exclusive**,不是字节偏移。全文 SHA 以 UTF-8 计算;函数/赋值源体另有 SHA,见 `.tmp/experts-source-audit.json`。表中所有源码事实均属于此固定版本;静态代码存在不等于分支已执行。
|
||||
|
||||
| 引用 | 文件 | 全文 SHA-256 | REA Evidence |
|
||||
| --- | --- | --- | --- |
|
||||
| C | `renderer/assets/contexts-BMeWSUHk.js` | `5f35b7489b107e21ef452c8ee88a95265756f6fc444841eef869228bbc44768b` | R |
|
||||
| P | `renderer/assets/workbuddy-provider-DkH2YFYM.js` | `b588e875c469978f216beec86bdf4b6c33a31c0266f9bf996881b8dbf37b5dc7` | R |
|
||||
| W | `renderer/assets/wb-CocRQn4C.js` | `d9ddb5d5464f2d863659a01493b58220bb5a0e270c22b16f405cfaeab2a7a972` | R |
|
||||
| I | `renderer/assets/wb-input-add-B045GnIg.js` | `7842fa4321d5351bf6c822bbd0253e0d6d6e68cc9cfae3f2470b3d493c23daf4` | R |
|
||||
| M | `renderer/assets/main-content-core-Dlaq72qt.js` | `998ada4969d1bf7af8d2dace15c0bc2a3ca5bf0ee9cf941823d85a66d6967991` | R |
|
||||
| S | `renderer/assets/services-Dzvfe5BC.js` | `fb5344ad7a525593e4fde494997539a148a0ea7233dd09ede96ab206b178fc57` | R |
|
||||
| T | `renderer/assets/runtime-B7PLES2V.js` | `b944fdfed0d52ca4c588833f94f50f878169a9244c05ed186abfa4eb37957911` | R |
|
||||
| U | `renderer/assets/expert-url-entry-coordinator-DDSbvr4R.js` | `34788957ae698799b6863d2d183c3a7d22b4dd08d4fc646ace656d766e86455f` | R |
|
||||
| B | `renderer/assets/expert-install-intent-buffer-EAdFw3P1.js` | `bda5eca334cc2a713b1bab0fe8119a21000b104d834deb11647641050814b8ae` | R |
|
||||
| CSS | `renderer/assets/contexts-BkjwYSZT.css` | `50cbd673f7f35fc7f966bdddc6c9f5677fdfe944cb904888d214619fca259380` | `ev_377c8790468b3c67dad8577aabb327f98d3140659f0fffdbabfcff5a40cc9e94` |
|
||||
| MAIN | `main/index.js` | `6cc9d3079aca910b7c14c37a0a3b6f6af03f2b319d5625625926dbf5ad61aec8` | `ev_3de1f34ca809cd2e4f98dfac960b1913db75e43cd88957d3e4f82b3b16f47fbf` |
|
||||
|
||||
R = `ev_717fa5e846e64d67ac19c8925d121bff632c0d3aefb3603b10858559cabb2dcb`,保存于 `.tmp/rea-runtime-scripts.json`,本轮 **339/339** 正文 SHA 匹配。Root 新采 `.tmp/rea-expert-runtime-scripts-20261016.json`,Evidence `ev_e91787b1d4dea651582c6cf12827775b9068b0ee8b80c68ba08d4c1d87d94e90`,**329/329** 正文 SHA 匹配;以上相关同名模块 SHA 未变。
|
||||
|
||||
补采 MAIN 与其已引用 `main/host.js`、`main/workbuddy-packaged-runtime.js`、`main/bridge.js`、`main/workbuddy-paths.js`,使用 public REA root pin。四个补充文件 Evidence `ev_4b2ecb341891999360045418cacfa9a51cd7bd4185d370f6766dc4cb4713b653`;每项 SHA 及长度保存在 audit 的 `supplementary`。本轮没有声称搜索完整 daemon/CLI 文件树。
|
||||
|
||||
## 1. 页面、列表与详情
|
||||
|
||||
| 源码观察 | 精确依据 | 实施含义 / 尚未验证 |
|
||||
| --- | --- | --- |
|
||||
| `ExpertCenter` 管理 center / 我的专家子页、搜索、专家/专家团、builtin/enterprise 来源、reco/popular/newest 排序、详情选择;窄布局条件 `0 < screenWidth < 980` | C `ExpertCenter` `[3876908,3886115)`;源体 SHA `aa152a80d85870f456cad1c9d53383696a637c597ded7128ce9bd55458312f67` | 可恢复同一页面状态机;980 临界值尚无本轮窄屏原版验收 |
|
||||
| 页面依赖布局配置与 feature flags;布局 tabs 从 expert/expert_group/enterprise_expert 映射,并按 position 排序去重 | C `resolveExpertPageLayoutTabs` `[3568360,3568681)`、`useExpertPageLayout` `[3567807,3568197)` | 不能把当前账号看到的 tabs/分类/推广数据写死成全量规格 |
|
||||
| 列表卡可展示头像、职业、描述、标签、作者/版本/使用量、付费/购买状态、云同步徽标;支持 selectable、disabled、footer、额外内容等 props | C `ExpertCard$1` `[3531248,3540077)`,SHA `a5fc885e829f97854a6cbbf6b0cfbcab21e6f2c7cd0f2581b5f911b662f019e3`;纯字段辅助函数 `[3525615,3527802)` | 可恢复 DOM/图标/CSS;购买规则与遥测通过明确 host adapter,不能伪称已有支付 |
|
||||
| 详情提供头像/角色、简介、标签、metadata、快捷提示词、相关案例、团队成员与召唤动作 | C `ExpertDetailContent` `[3826056,3833750)`,SHA `6edf5d32b8ecba712593611f13ea8d763d9659551d2db060d8dab2fb7428eb56`;`ExpertDetailMetadata` `[3821706,3823592)` | 原 props:`{expert,resolveAvatarUrl,onClose,onSummon,onCaseClick,onRefreshExperts}`;详情与召唤/购买控制需拆开适配 |
|
||||
| 我的专家分专家/专家团;过滤、空态、编辑/删除、逐个/批量云上传、下载及云端删除 | C `CreatedExpertsPanel` `[3845690,3851495)`,SHA `73d81b6f1c3205fa1b8c67639fa821af60f0b29d236be4d2260406a75f579e47`;`CreatedExpertCard` `[3836312,3843963)` | “我的专家”包含本地与云状态;不是另一个固定 marketplace 列表 |
|
||||
| 搜索当前 locale 的 name/displayName/profession/description/displayDescription,忽略大小写,含空格关键字也尝试去空格 | C `filterExpertsByKeyword` `[3527461,3527802)` 及相邻纯函数;I `useExpertSearch` `[38275,39285)` | 页面本地过滤与 picker 的跨目录搜索不同,不宜共用一个简化 includes 全部替代 |
|
||||
|
||||
Root 已保存原版专家首页真实画面和计算布局:
|
||||
`.tmp/rea-expert-entry-static-20261016/{workbuddy.png,layout.json}`,Evidence
|
||||
`ev_20de2f04c99b1c27bc39b61f5e2f5a430c3c7029b09afb76b363652eb4fadc89`。
|
||||
PNG SHA `e49ce30072a11898f3114b73dd3b941fe93fc0da46eee6fb15cb765635c5591a` 已核验;视口 **1336×901**。这里只读取该 REA 记录,没有本子任务新操作原版。
|
||||
|
||||
已观察几何:node783 `.expert-center-page` 为 `[284.28125,30,1051.703125,871]`;node786 topbar 高64;node826 起推广卡264×202、间隔16,DOM 实际有10张,首屏可见区域涉及前4张,不能把“4张可见”当总数;node1115/1147起常规卡宽319.234375、高156,三列、横距16。此截图只是一个账号/浅色/宽度/数据态,尚不证明暗色、hover、详情、我的专家、错误/加载、长文本或全响应式像素一致。
|
||||
|
||||
对应可直接恢复的 CSS:CSS offset811600 `.\_page_1yu3o_7` 定义 gutter24、主题背景/文字与布局;733774 `.\_card_1hdcm_2`;735217 `.\_centerCard_1hdcm_60` 定义中心卡156px;765443 list row/tabs/sort;730341 分类横向拖动滚动条;722717 我的专家空态。须保留上下文主题 token、keyframes、媒体条件、module class mapping;抽出几条颜色/字号不足以验收 1:1。
|
||||
|
||||
## 2. 数据模型(观察到的 renderer 契约,不冒称持久化 schema)
|
||||
|
||||
| 层 | 已观察字段 / 枚举 | 源码依据 |
|
||||
| --- | --- | --- |
|
||||
| 商店原始条目 → 专家展示数据 | marketExpertId/sourceId/categoryId,name/displayName/profession/description 多语言,avatar,plugin/version/downloadUrl,defaultInitPrompt/quickPrompts/tags,expertType,useCount/author/developer,members/leader,visibility/source/namespace,payMode/payDetail,createdAt/updatedAt/isCloud/isInCloud | W `mapMarketItemToExpertInfo` `[108592,110484)`,SHA `30fecc1b1838880639efd68cf31f494ac14691d6ce5e2ab4eb104bc4b1edbc0b` |
|
||||
| picker / 输入区选择项 | id/name/profession/avatarUrl,defaultInitPrompt,pluginName/updatedAt,expertType=`agent|skill|plugin|team`,source=`builtin|enterprise|custom`,marketplace,agentName,categoryId/industryId,leader/members,downloadUrl/marketExpertId/quickPrompts,expertRootDir/isCustomExpert,summonedAt | I `normalizeExpertToMenuItem` `[32274,34201)`,SHA `3a3ec6541714621e238d3cbbc376834ee0790abf104696c70521548a37e88a98` |
|
||||
| 运行时已激活选择 | 还含 prompt、localPath、pluginRegisteredName、summonTimestamp/reliability、assistantDisplayName/assistantProfession/assistantAvatarUrl、teamMembers | P `hydrateSelectedExpertForRuntime` `[431496,433326)`;`resolveCustomExpertRootDir` `[39581,39733)` 仅接受自定义来源 |
|
||||
| 可持久化运行时身份字符串 | `expert-v2:` + JSON `{v:2,kind:'expert',expertId,marketExpertId?,pluginRegisteredName?,agentName?,source?}`;source 仅 builtin/enterprise/custom;官方 market ID 检查 `^ex_[A-Za-z0-9-]+$` | C `[847880,850063)`,`createExpertRuntimeIdentity` `[848557,849001)`;prefix850082 |
|
||||
| 会话助理显示快照 | source=expert,name/profession/avatarUrl/expertId/expertType/isCloud/resolution/identityKey/identityVariant | C `buildExpertAssistantDisplaySnapshot` `[3906431,3907161)` |
|
||||
| 云同步展示状态 | presence 可为 local_only/cloud_only/both/local_ahead/cloud_ahead;cloudStatus checking/ready 等;cloudUid/cloud/syncReason/invalidLocal 参与 UI 与传输判定 | C 云徽标3523524附近、`CreatedExpertsPanel`3845690、`ensureExpertReadyForTransport` `[3955051,3956226)` |
|
||||
|
||||
注意:W 把远端 `source:'custom'` 条目映射为 **enterprise**,不能直接等同“本机自建专家”。本机判断采用 `marketplace:'my-experts'` 或 `isCustomExpert:true`(C847880、P39489)。包内部 plugin manifest、AGENT/prompt 文件格式、索引路径、同名覆盖/版本升级细则及实际持久化迁移,本轮尚未取得 handler,仍未知。
|
||||
|
||||
## 3. 创建、编辑、发现新专家
|
||||
|
||||
**观察**:C `[926000,927450)` 定义 `expert-manager`、默认创建提示、编辑指定 ID 提示和创建专家团提示。`buildCreateExpertModeBlocks` `[3863507,3863752)` 返回 skill block 加 text block;`useMyExperts` `[3863923,3867901)` 的 create/edit 均 `navigation.goHome()` 后发布输入草稿。C880431附近的公开 `wb.experts.create` 也是 session.prepare `{skill:{name:'expert-manager',displayText:'创建专家'},editExpert?:{id}}`。
|
||||
|
||||
**观察**:M `useExpertCreationDetector` `[32571,37974)` 检测 `createdBySession`,维护按会话的 created experts 索引,刷新专家预览并切右侧 expert 视图,然后调用 `custom.clearSessionMarker`;`custom` 列表/插件文件变化订阅由 P580293之后转交 daemon watch-path 与 file-change API。
|
||||
|
||||
**推断 / 边界**:原版设计是对话驱动写入/更新专家包,再通过发现事件反映到 UI;可真实复现入口与草稿,却不能仅把“创建成功”Toast 或一个自建 prompt JSON 当作已复刻创建流程。`expert-manager` 技能正文、写包工具、session marker 格式与 agent 执行方式是本地创建下一步所需证据。当前未安装/运行该技能,没有验证它实际生成哪些文件。
|
||||
|
||||
## 4. 导入、安装、分享与深链
|
||||
|
||||
| 已观察流程 | 源码定位 | 仍依赖 / 未验证 |
|
||||
| --- | --- | --- |
|
||||
| 分享导入先取 share detail 首个 inode,再 verifyShare 得到访问资料,构建下载 URL;调用 `experts.import.fromUrl({downloadUrl,expertName,overwrite,securityCheck:true})` | S `useExpertImportConfirm` `[12813,16585)`,SHA `15d186da0713d48a70d47034625c3a0b17ffac75ec44fd25bd4e3a9b515ffed0` | 分享/鉴权是服务依赖,本轮未发下载请求 |
|
||||
| 处理 duplicate_expert:若非当前用户拥有,记入我的专家;若拥有,要求覆盖确认,再重试安装 | 同上;S19207之后 checked-path 安装分支 | “重复即覆盖”不是原版流程;覆盖实际磁盘语义待 handler |
|
||||
| security_check_blocked 返回 preCheck/selectedPath/md5/scanResult;轮询扫描,非高风险自动继续、跳过及风险确认有专门 modal;本地 checked-path 走 `fromPath({zipPath,expertName,overwrite})` | S12813/19207;P625748之后 `installExpertFromUrl/Path` | 有安全服务 appKey/扫描结果依赖;本地 scanner 与包路径校验实现尚未恢复 |
|
||||
| URL `expertId` 只消费一次并从地址栏删掉;get专家存在则 summon;不存在而 resolver 有提示词则回首页填草稿 | U `consumeExpertIdFromUrl` `[508,882)`、`ExpertUrlEntryCoordinator` `[953,1885)` | `__wbExpertPromptResolver` 是 host 注册的全局 holder,不等于专家 API 文本全部内置 |
|
||||
| 安装意图需要 expertName/shareCode,保存一个 pending intent;订阅时消费并向监听器交付 | B `setPendingExpertInstallIntent` `[145,345)` / `subscribePendingExpertInstallIntent` `[345,522)`,函数 SHA见 audit | 可以原体恢复缓冲逻辑;不代表导入已经成功 |
|
||||
|
||||
## 5. 选择与发送消息绑定
|
||||
|
||||
| 源码事实 | 精确依据 | YCode 需要真实连接的部分 |
|
||||
| --- | --- | --- |
|
||||
| 本地选择会 `experts.summon`,传 expertId/sessionId/source/locale/marketExpertId/updatedAt/applicationId;有竞态代次、重复请求复用、500ms提示及失败回滚;云 transport 走不同分支 | C `useExpertSummon` `[3951518,3954856)`,SHA `e891982347cd938912d18ae4dc3614251180a87359f39658d28c5beedb52f610` | 会话和草稿选择作用域必须隔离;不能只改变 chip 文本 |
|
||||
| summon 激活结果可含 expertType/agentName/localPath/pluginRegisteredName;无 legacy prompt 时尝试激活插件;既无 prompt 也无激活信息会报不可用 | P `getExpert` `[609114,610423)`、`activateExpertPlugin` `[618015,618502)`、`hydrateSelectedExpertForRuntime` `[431496,433326)` | 本地插件执行/启停需要能力适配;OMP 当前可用不证明其与原插件机制等价 |
|
||||
| bind会话设置 expertId 及 locale/marketplace/marketExpertId/expertType/source/runtimeIdentity/assistantDisplay,且模式改为 craft;返回原会话保留既有输入并抑制默认提示 | C `bindExpertToConversation` `[3907799,3908569)`、`returnExpertToConversation` `[3908569,3909521)` | SessionConfig 持久化、历史恢复、助理头像/身份快照都需接入 |
|
||||
| 发送前保存 recent;cached prompt 排除等于 defaultInitPrompt 的值;无指令时重试插件激活,仍不可用清除无效绑定;最终 `_meta['codebuddy.ai']` 含 expertId、可选 expert prompt、`tags:['expert:…']`、assistantDisplay | M `[225000,229900)` | 默认开场提示不是专家系统指令;不应直接把输入模板当专家 prompt |
|
||||
| 会话切换插件单独请求 disablePluginName/enablePluginName/agentName/sourcePluginId,可携内部 model 请求 headers;选择更新串行并同步 launch config;失败回滚 | P `setSelectedExpertForSessionInternal` `[612975,614938)`、`switchExpertPluginForSession` `[618762,619301)` | 原插件启停与用户模型 headers 的桥接需另证,不能复制 WorkBuddy 私有请求信息 |
|
||||
| 专家声明 dependencies;requirements API可返回 connector/MCP,分别连接、修复、token字段、授权打开外部页与等待状态 | C `connectExpertDependency` `[3934992,3936890)`、`useExpertDependencyGate` `[3938212,3946396)` | 不能把 dependencybar 接成功 mock;本轮未连接任何服务 |
|
||||
|
||||
以上发送 metadata 是原版 renderer 构造事实,**不是已验证服务器如何消费该 metadata**。原版团队专家/子代理编排也未由此证明;团队成员展示可恢复,执行调度另列未知。
|
||||
|
||||
## 6. 本地与云、host API
|
||||
|
||||
**本地与云的选择并非只有 `isCloud` 一个布尔值。** C `createExpertApi` `[3560992,3562607)` 可选 default 或 cloud-in-local scope;picker 根据 transport 选择 `wb.experts` / `wb.cloud.experts`(C3957662)。本地使用 cloud_only 专家先下载;云会话使用 local_only 专家先上传,conflict_local_wins 要求覆盖确认;checking 中取消;源纯函数 `ensureExpertReadyForTransport` `[3955051,3956226)` 可恢复,实际 upload/download 是外部宿主接口。
|
||||
|
||||
本机 custom.list 是本地专家入口,启用云同步时可能改 cloudSync.list,NOT_SUPPORTED/NOT_READY 可回退(C `useLocalExperts` `[3862148,3863357)`)。云上传处理 confirmation_required/preflight_blocked/quota_blocked、批量 succeeded/failed/skipped;删除本机专家与删除 cloudUid 是不同动作(C3863923)。商店发布资料、推广布局、企业可见性、付费权益、分享和云同步都可能受账号/产品配置影响。
|
||||
|
||||
T8991起定义 expert IPC,T29132附近绑定 invoke;P 转给 `getDaemonClientFeature`。已证实 renderer/daemon 契约:
|
||||
|
||||
| 类别 | 通道 / 接口 |
|
||||
| --- | --- |
|
||||
| 目录 | `expert:init/getCategories/getExperts/getFeaturedScenes/getExpert/getAgentTemplates/getUseRequirements/refresh`,`expert:loadStateChanged` |
|
||||
| 激活 | `expert:activatePlugin/deactivatePlugin/getActivePlugins/switchPluginForSession` |
|
||||
| 包与导入 | `expert:exportZip/importFromUrl/installFromPath/previewFromUrl/preCheckShare/queryShareSecurityScan` |
|
||||
| 本地自建 | `expert:scanCustomExperts/getCustomExpert/deleteCustomExpert/addUserExperts/clearCustomExpertSessionMarker`;`localExpertsGetWatchPath/localExpertsGetPluginJsonPath` |
|
||||
| 历史 | `expert-history:getRecent/add/remove/clear` |
|
||||
| 同步 | `expert:cloudSyncList/cloudSyncCheckUploadQuota/cloudSyncUpload/cloudSyncUploadMany/cloudSyncDownload/cloudSyncDeleteCloud` |
|
||||
|
||||
具体参数已在前文函数定位可读。新增审计输出保留 import binding graph,便于下一轮从确切 exported symbol 接口恢复;本轮不假造 TS 原类型或 IPC handler 实现。
|
||||
|
||||
MAIN 静态入口与已引用补采文件没有提供上述 expert handler 定义;这是**所查文件范围的负结果**,不是说安装包不含实现。下一步应由 REA 包清单/模块图定位 daemon 注册点和 expert-manager bundled skill,定向补 exact paths;不得猜路径后自行读原包,或用直接 CDP/手写提取器替代 REA。
|
||||
|
||||
## 7. 可复用源码与真实依赖边界
|
||||
|
||||
| 恢复单元 | 可直接恢复的原体 | 必须明确替换的宿主依赖 |
|
||||
| --- | --- | --- |
|
||||
| 纯数据/展示 | `normalizeExpertToMenuItem`、去重、locale字段选择、title/version/useCount/tags/search、runtimeIdentity生成读取、云传输分支判定 | URL/avatar resolver、locale 与 feature输入;这些纯函数不需要 WorkBuddy 云服务才能测试 |
|
||||
| 基础页面 | ExpertCenterContainer、card/avatar、category/source/sort tabs、searchbar、empty/skeleton、CreatedExpertsPanel、detail/quickprompt;同名 CSS module maps 与 SVG | React/JSX singleton、原按钮/tooltip/dialog/scroll primitives、主题/字号、i18n、account/产品flag;不能直接加载7.5MB contexts而把其全局 app/provider 初始化也执行 |
|
||||
| 有状态 hooks | useLocalExperts、useMyExperts、useExpertDirectory、useExpertPinState、useExpertSummon、useExpertTransfer、创建检测、URL/buffer协调 | YCode registry/session/navigation/events、atomic本地持久化、真实列表/安装/执行结果;toast/telemetry应显式适配 |
|
||||
| 导入/依赖 | 可恢复导入/覆盖/安全确认 modal 与状态机,dependencybar UI | ZIP读写/路径约束、下载/安全扫描、文件监控、MCP授权与连接;服务可用性要明确表达 |
|
||||
| 云商业功能 | 已有源码可说明 upload/download/share/pay/quota 展示和请求契约 | 云后端与账号/权益,不在本轮恢复或替换;不能用本地假成功冒充 |
|
||||
|
||||
真实已见模块依赖是同包 `react-z__Ncn__.js`、`jsx-runtime-DM1VED__.js`、`rolldown-runtime-BJCASTsb.js`、contexts、module-host-context、provider/adapter/runtime,以及 CSS token/图片资源。没有本轮证据支持为“专家”安装一个新的第三方专家 SDK;也没有确证原 React npm semver或本地插件/skill包的 schema/version。依赖表记录实际 module path,不猜 npm 版本。
|
||||
|
||||
## 8. YCode 实施建议(候选拆分,主上下文决定架构)
|
||||
|
||||
YCode 当前 `src/renderer/src/mock.ts:90` 的 experts 为 `implemented:false`,`Sidebar.tsx` 只有导航图标;共享词典含部分专家文案不等于页面/宿主已实现。`src/main`/`src/shared` 本轮搜索未见专家 CRUD 主进程接口。以下按可验收模块拆分,避免先铺一套无法执行的空壳。
|
||||
|
||||
1. **固定页面证据及纯源恢复**:恢复卡片、tabs、分类、排序、详情/我的专家空态与 CSS/图标。验收同视口/主题/字体、搜索/长名/加载/错误、980临界和hover;商店数据暂作为明确的 REA 离线fixture,不能标真实已安装。Root 正在独立补我的专家和详情只读样本。
|
||||
2. **本地包模型与 registry**:先补 daemon/skill证据,确定 manifest、prompt/agents/skills/connector依赖、用户索引、createdBySession、ZIP安全和覆盖语义,再实现 YCode 自有 host + focused真实临时目录测试。普通prompt型专家、plugin/agent/skill/team要按真实能力区分。
|
||||
3. **选择、会话与发送**:接 draft/会话 expert selection、recents/pins、runtime identity、assistantDisplay、craft模式与默认prompt草稿;接真实指令加载/能力校验、切换清理、重启恢复。实际 OMP 请求/工具行为验证后才能宣称可使用专家。
|
||||
4. **对话创建/编辑闭环**:恢复expert-manager入口和草稿,接本地真实管理工具/能力,发现marker和filechange后打开专家预览;以真实磁盘产物、编辑更新、取消/失败/重启验收,不能以点击入口代替完成。
|
||||
5. **导入导出与依赖**:真实ZIP/路径/重复安装/错误/取消/清理,再接MCP依赖授权;根据所恢复实现表达安全检查的真实能力。
|
||||
6. **云功能单独验收**:目录服务、同步/配额/分享/付费与账号后端另接;用户此前云端与子代理暂后要求下,不妨碍本地页面和可真实工作的本地子集先做,但全功能1:1仍保留在差距表。
|
||||
|
||||
## 9. 未知与所需新证据
|
||||
|
||||
- **本地 daemon handler / expert-manager技能 / 包schema**:REA模块清单与精确导出路径;优先 expertScanCustomExperts、expertActivatePlugin、expertInstallFromPath、expertSwitchPluginForSession、exportZip注册函数以及 bundled expert-manager 的 SKILL.md/工具依赖。当前 renderer 可知参数,无法代替磁盘及执行语义。
|
||||
- **实际创建/编辑/安装闭环**:后续得到明确测试授权再做受控原版 REA scenario;本轮只读,没有修改原版。需要原始产物manifest、变化事件、取消/错误/覆盖的执行证据;不能单凭静态入口断言创建工具已可移植。
|
||||
- **详情/我的专家/暗色/窄屏/hover等视觉态**:Root 的后续 REA采样;当前仅首页宽屏浅色静态样本。动态市场图片/列表排序不是包内固定CSS的替代品。
|
||||
- **云端语义与服务替代**:哪些资源属于内置可离线、企业权限、市场manifest、账号云同步、扫描、付费、分享;本轮没有访问这些服务。私有后端源码不因客户端请求契约存在而被恢复。
|
||||
- **专家团执行/子代理等价**:显示 members/leader 和expertType已证,运行调度及各模型工具兼容未验。不可把多头像/UI字段当实际协同完成。
|
||||
|
||||
## 验证与交接
|
||||
|
||||
新增 `scripts/audit-experts-source.mjs` 只读已导出的 REA JSON;所有读取正文先校验 SHA,选中模块用 Babel AST 记录函数/赋值的范围、源体 SHA及 imports,不执行原应用。默认生成 `.tmp/experts-source-audit.json`,输出有界文件摘要;`node scripts/audit-experts-source.mjs contexts-BMe getCustomExpert` 可查有界源码片段。
|
||||
|
||||
本轮 `node scripts/audit-experts-source.mjs` **PASS**:339旧脚本、329当前脚本、5个 publicREA补采文本、专家CSS和首页PNG均身份匹配。`node --check scripts/audit-experts-source.mjs` **PASS**。未修改 production,无需 build/产品测试;没有把静态审计当运行验收。
|
||||
|
||||
本轮文件:本评估、独立audit脚本;`.tmp/experts-{audit-inventory,source-audit}.json`、`.tmp/rea-experts-{main,host}-evidence.json`。Root 新采runtime/首页是Root证据,本子任务只读。后续实现须由主上下文决定架构与执行顺序。
|
||||
@@ -0,0 +1,128 @@
|
||||
# WorkBuddy 技能部分评估与拆解
|
||||
|
||||
2026-10-16,仅评估。技能是“市场发现→详情→本地/云端安装管理→输入引用→会话内实际加载/执行”的完整链路,不能用一组静态卡片代替。客户端的 DOM/CSS/SVG、列表状态和大量纯 helper 已有可恢复源码;本地安装器、扫描判定、运行内核和云目录/付费权益还有独立宿主及服务依赖。没有依据把全部技能功能宣称为已完成或已证明可完整等价。
|
||||
|
||||
本次只新增审查脚本、评估文档和 `.tmp` 报告;没有改生产、操作原版 runtime、导入/安装/启用/购买技能。原版新增静态采集只使用 REA 根哈希固定的选中文件导出。原版 UI 截图由主上下文通过 REA 采集,本任务只读其已保存结果。历史 CDP 结论不纳入已验证结论。
|
||||
|
||||
## 源身份与可复现材料
|
||||
|
||||
原版 **WorkBuddy 5.8.2**,安装包根 SHA-256:`035254bc76310ea46317433e4840602094543ef323d2d5c5aff7c131729de918`。
|
||||
|
||||
| 简称 | REA 来源 | 观察范围 |
|
||||
| --- | --- | --- |
|
||||
| R | `ev_717fa5e846e64d67ac19c8925d121bff632c0d3aefb3603b10858559cabb2dcb`,`.tmp/rea-runtime-scripts.json` | 339个导出脚本,逐项先验证正文 SHA 再解析,不执行模块初始化 |
|
||||
| S | `ev_e8faf60b3d22b99ede302f2d0efdfb3145f53f59789d4a345f5892dc13a589a4`,`.tmp/rea-skills-market-selected-20261016.json` | 精确选取 `renderer/assets/skills-market-Cwf-NvXV.js` 与 `skills-market-d_hn_qWB.css`;未读未选中文件内容 |
|
||||
| L | `ev_e91787b1d4dea651582c6cf12827775b9068b0ee8b80c68ba08d4c1d87d94e90`,`.tmp/rea-expert-runtime-scripts-20261016.json` | 主上下文后续329个加载脚本;全部校验,市场 JS 与 S 的 SHA 相同,证实实际已加载 |
|
||||
| C | `ev_377c8790468b3c67dad8577aabb327f98d3140659f0fffdbabfcff5a40cc9e94`,`.tmp/rea-css-recovered/manifest.json` | 已保存的组件 CSS/token 来源;本任务复验选用文件 SHA |
|
||||
| V | `ev_c827c8dc7dee0c67c7870f6bf8417b87ec7b4d90d507ecc5dc592b5878579f10`,`.tmp/rea-market-skills-20261016/frame-000.png` | 主上下文原生1336×901技能市场默认画面;已加载内容与当前账号状态,不代表固定目录 |
|
||||
| VI | `ev_9d8628a28fed60291e628cebaec55537bfb8274d4b6c8f746bffadcbc277d3fb`,`.tmp/rea-installed-skills-static-20261016/workbuddy.png` | 稳定已安装列表:5个市场来源条目、套件badge、开关、搜索与批量管理 |
|
||||
| VA | `ev_ddef9315aaf0ff534cf02573212e205ba70e5b69dfc1b3dcf555b430920faf22`,`.tmp/rea-add-skill-options-20261016/frame-000.png` | 添加技能菜单:查找技能/上传技能/创建技能;仅打开菜单并关闭 |
|
||||
|
||||
V 中可见共享“专家/技能/连接器”顶部导航、搜索技能、已安装(5)、添加技能、三张精选卡、推荐/SkillHub/套件、横向分类和三列列表。卡片名称、图标、推荐位、使用/安装数属于该账号/时刻的数据。`workbuddy.png`/顶层layout是 probe 前状态;本次切换后的市场证据使用 `frame-000.png`,不把两个时点混用。
|
||||
|
||||
VI确认已安装页的“来自市场(5)”和混合套件条目;不能把UI计数反推为5个独立SKILL.md目录,源码计数确实合并skills与plugins。V及VA的动作steps全部completed、各自画面帧有效,但neutral-pointer cleanup cancelled使整体probe为failed,故只标**部分动作证据**,不标全场景成功。VI是稳定static采集,未请求probe。未触发find/upload/create,也未选择或扫描任何文件;导入dialog尚未runtime取证。审查脚本复核以上三张PNG的REA artifact SHA。
|
||||
|
||||
重要发现:`skills-panel-CvMlV3m8.js` 94,896 B 大部分实际是 Connector/MCP;`SkillsPanel` offset **93769** 仅101字符,返回 Suspense,并懒加载真正的 `skills-market-Cwf-NvXV.js`。只复用这个名字对应文件会遗漏技能市场主体。S 补齐了真实主体,L 随后证实它已加载。
|
||||
|
||||
| 文件别名 | 文件 | SHA-256 |
|
||||
| --- | --- | --- |
|
||||
| P | `skills-panel-CvMlV3m8.js` | `b30c43c11ec476db639d6be58065d927411845487d34b0ea8e839d1c6eb7a238` |
|
||||
| M | `skills-market-Cwf-NvXV.js`,148,298 B | `f1434cadabf5ed3762f00fc2a356bc7418b0b4aab27db62dc9fbbe5add6f6dfb` |
|
||||
| D | `standalone-skill-detail-modal-Bi5X8CZ4.js` | `ee7de2a7123f94110aa01258d3d6b3fcc3ce48f2ec5fd8f91cb3367c817a0f01` |
|
||||
| X | `contexts-BMeWSUHk.js` | `5f35b7489b107e21ef452c8ee88a95265756f6fc444841eef869228bbc44768b` |
|
||||
| H | `workbuddy-provider-DkH2YFYM.js` | `b588e875c469978f216beec86bdf4b6c33a31c0266f9bf996881b8dbf37b5dc7` |
|
||||
| I | `installed-skills-entitlement-CcKsu3c9.js` | `760a0b3d0678c3560cfdb03472f4bc30908ca89c8abf2adc001fa301c718129f` |
|
||||
| G | `paid-skill-registry-ClOa9K12.js` | `6aefb8bcabe5a79aba236b882e0440bc10736c83ef368ce5aea8f483cb7e94af` |
|
||||
| F | `paid-goods-gate-D3Mx0eHl.js` | `a727b1748c192f51c89f3bc394eb3ac87d0dfa647409871e99e0711e558680da` |
|
||||
| B | `wb-input-add-B045GnIg.js` | `7842fa4321d5351bf6c822bbd0253e0d6d6e68cc9cfae3f2470b3d493c23daf4` |
|
||||
| N | `local-skills-memory-Bb3Kqaxi.js` | `5ba6d1b837ef191d8bbef0f4bf21f2ac56b442e101656f0c1e881794a3d6afb8` |
|
||||
| Q | `skill-scan-result-dialog-CWSA6ZCh.js` | `4a91c1d114d143d4267ba9b283397ba5445905d65c9dea8a8de065de5eee87dd` |
|
||||
|
||||
CSS:M配套 `skills-market-d_hn_qWB.css` 51,694 B,SHA `935d55effde68d03b2fbc2529ec94b19a6cd7210d9bc79febd6d115b115f60b6`;详情CSS `7967df52bacb7594f934b32d8d5fb24854dbc8c47d0217d4677c7d7da0655f49`;扫描dialog CSS `0e657f3b531d73590ca9a5d0bd026f8b31f9fecaac7a59bf79bd737c4195fc77`。不应误把 P 的连接器样式当成市场主样式。
|
||||
|
||||
执行 `node scripts/audit-skills-reference.mjs`。输出 `.tmp/skills-audit-20261016/report.json`、格式化的市场/详情模块、有限 helper/class/宿主方法。报告保留 source、SHA、import/export边、函数与class方法 offset。下文 offset 是**原始导出字符串的字符位置**,不是格式化文件行号或二进制地址。
|
||||
|
||||
## 客户端状态与可恢复范围
|
||||
|
||||
| 部分 | 已查证行为与状态 | 源锚点 |
|
||||
| --- | --- | --- |
|
||||
| 入口和路由 | 共享市场导航;Market/Installed/SkillDetail/PluginDetail;详情返回原列表视图;`initialLevel1Tab=installed` intent;visible/active生命周期、bootstrap skeleton/error/retry | M `SkillsMarketRouteShell`143580、`SkillsMarketContent`145021;X `MarketUIService`3797944 |
|
||||
| 市场发现 | 精选/推荐集合、SkillHub、Knot、企业集合、Plugins;分类横滚、更多分类、排序、分页/无限滚动、回顶部;部分源按账号/企业/产品feature显示 | M `DiscoverSection`71985、`CollectionPanel`45127、`SkillhubCategories`38872;X `MarketLayoutService`3746274、`MarketBuiltinService`3665734、`SkillhubService`3788762、`KnotService`3735308 |
|
||||
| 全源搜索 | 输入200ms debounce,后续300ms调度;按集合/source并行检索,generation丢弃过期结果;pending/fulfilled/rejected、partialFail、失败banner、空结果、loadMore、hideInstalled;多词搜索部分源另试去空格查询并去重 | X `SearchService`3772106(`search`3772496、`fetchAll`3773749);M `SearchResults`138322 |
|
||||
| 卡片 | 名称/描述/remote头像或fallback、使用/下载/星数、API Key/云/来源标记、安装/已安装/升级/加载/禁用、试用/更多菜单;不同source/插件卡片有不同动作 | M `CardFrame`/`MarketSkillCard`/`MySkillCard`(完整offset见报告);D各纯SVG定义、`resolve*` helpers |
|
||||
| 我的已安装 | 本地及cloud-only合并、插件分组;中文/英文描述搜索;按置顶/启用/安装时间排序,用户操作中稳定顺序;批量启用/禁用/卸载、失败项、计数、更新提示;启用数>80的可关闭提示;分页每次增加100项 | M `InstalledSection`126083、`InstalledList`114407、`useBatchActions`79059、`usePinnedInstalled`90446;X `InstalledSkillsService`3719062 |
|
||||
| 详情 | 本地/远程身份与来源归一,描述展开、markdown说明、语言切换与翻译提示、详情内搜索高亮/命中导航、示例、相关案例、开发者/版本/来源/计数/标签、安装/更新/试用、模型调用开关、更多菜单 | D `useSkillDetail`8265、`useSkillDetailOverview`59966、`OverviewSection`65624、`ActionRow`84719、`SkillDetailModal`101233;X `DetailService`3682486 |
|
||||
| 本地导入 | 文件夹、zip、拖放;SKILL.md/frontmatter元数据、错误/上传/等待/风险/失败/取消、自动安装非高风险选项;Desktop dialog和浏览器文件流是不同分支 | X `useDesktopSkillPick`4394604、`usePersonalSkillImport`4395325、`PersonalSkillImportModal`4393454、`useSkillUpload`4362230;M `SkillImportModal`141312 |
|
||||
| 安装与更新 | 市场源install/update不同;optimistic开关失败回滚;批量操作部分失败;用户修改过的技能更新前确认覆盖;新装立即upsert并延迟reconcile,toggle后2秒抑制旧列表覆盖;无法只改checkbox就视为完成 | X `InstalledSkillsService.toggleSkill`3723087、`uninstall`3725366、`runUpdateSkill`3730356、`batchUpdate`3731577;D `runUpdateIfAllowed`51856、`useSkillDetailActions`51972 |
|
||||
| 云同步 | 本地/云/两端presence、cloud UID/version/syncState;上传preflight/配额/覆盖确认、下载确保本地路径、批量进度/失败重试;卸载区分删本地和可选删云端,付费/内置资源有约束 | M `useCloudDownload`、`useCloudUpload`、`useInstalledCloudSync`;D `runSkillUninstallWithCloud`73220、`checkUploadQuotaBeforeUpload`79878;X `getSkillCloudAction`2307304 |
|
||||
| 扫描 | 预检查与异步查询;pending/safe/risk/black/suspicious、timeout/error/unavailable;风险tags、fileAnalysis、virusName;黑名单/高风险策略;已安装后发现高风险可提示卸载/保留 | X `buildSecurityScanDialogProps`2335743、`AsyncSecurityScanService`2329330;Q `SingleScanResultDialog`及`SkillScanResultDialog` |
|
||||
| 授权/付费 | requires_api_key是能力标记;商品购买权限按账号/enterprise/type gate;monthly/permanent、未购/已购/过期、购买后安装、续费、退款、退款次数限制;不是单一“已付费”布尔 | D `resolveRequiresApiKey`5067、`useSkillPaidState`7712、`ActionRow`84719、`SkillPaidDetailChip`93591;I `mapMarketSkillPayToPricing`3272;F `shouldRequestSkillPayAssets`215 |
|
||||
| 输入选择/调用 | +菜单技能列表、搜索/置顶/最近、local/cloud与cwd/Buddy/account scope,运行可用性/购买状态过滤;slash命令合并个人/项目技能与已有命令;选择产生结构化引用,试用可创建新任务或回传office输入 | B `SkillRow`57379;X `useCommand`4181840、`assembleSkillCommandItems`4179893、`useWbSkillProvider`4480437;D `useTrySkill`50768 |
|
||||
|
||||
DOM/CSS/SVG和纯归一函数可直接恢复为有限源码模块。UI hooks中的业务策略可保留并换成YCode真实宿主接口;不能直接初始化整个原 bundle,其DI、账号、telemetry、facade、navigation、transport会绑定原产品。卡片远程头像/markdown/使用数/榜单由目录数据提供,不能用假数据填补服务缺失后称1:1。
|
||||
|
||||
详情的 `requires_api_key` 只证实显示标记;本次未查证存在通用的“所有技能API Key配置表单/秘密注入协议”。不能把原模型provider的密钥界面直接挪过来当技能授权实现。商品license、组织可见性、执行所需第三方credential、模型调用开关要分别建模。
|
||||
|
||||
## 数据、宿主接口和运行链
|
||||
|
||||
```mermaid
|
||||
flowchart LR
|
||||
Market[市场与详情] --> Catalog[目录与商品权益 facade]
|
||||
Import[本地导入] --> Check[宿主预检查与扫描]
|
||||
Check --> Install[真实安装与文件管理]
|
||||
Install --> Installed[已安装 store 与刷新事件]
|
||||
Installed --> Picker[输入技能与 slash provider]
|
||||
Picker --> Link[skill URI 与结构化元信息]
|
||||
Link --> Session[会话 transport 与可用命令]
|
||||
Session --> Kernel[实际加载技能的运行内核]
|
||||
Kernel --> Render[Skill 工具与结果渲染]
|
||||
Catalog --> Market
|
||||
Catalog --> Installed
|
||||
```
|
||||
|
||||
**主要数据身份**需要保留 name/displayName/description及多语言、filePath/ref、skillId/slug/canonicalName/cloudUid、source/marketplaceSource/assetType、version/local/cloudVersion、installedAt、userModified、disable/disableModelInvocation/userInvocable、marketInstall presence、icon、requires_api_key、风险结果和付费pricing。不能用name作为所有跨源/跨空间主键:原版有strong identity匹配、来源过滤、cloud-only placeholder、别名和唯一名称fallback。
|
||||
|
||||
1. **个人技能 facade**:H offset8654的methodMap明确映射 `list→skillList`、`toggle→skillToggle`、`batchToggle→skillBatchToggle`、`delete→skillDelete`、`getContent→skillContent`、`importFromPath→skillImport`、`installByPath→skillInstallByPath`、`installFromUrl→skillInstallFromUrl`、`querySecurityScan→skillQueryScanResult`、`exportZip→skillExportZip`,另有Buddy技能桶ensure/remove/prune/meta/update。调用参数包含source、folderPath/filePath、cwd/global、excludePluginSkills、securityCheck/appKey/securityVerdict、overrideKeys。不是 renderer 直接读写目录。
|
||||
2. **市场 facade**:H `createSkillsMarketplaceProxy` offset10086,分 builtin/skillhub/knot/local/marketInstallConfig,各自list/install/categories/detail/search/installedMetas;builtin还有getByIds/getLayout/backfill,knot有tags,marketInstallConfig有ensureLocal/setEnabled/batchSetEnabled/uninstall。企业技能另一个facade。调用点有模板/集合/类别、page/pageSize、enterpriseId、needPayAssets等真实条件。
|
||||
3. **详情读取**:X `DetailService.loadMarkdown`3683897按source调用personal getContent或市场detail/content;读取取消与选中项竞态有独立处理。H `getBuiltinSkillRoot`458143、`readBuiltinSkillFile`458531调用daemon的明确能力并缓存。renderer导出不能证明底层安装器怎样解析所有辅助文件或执行脚本。
|
||||
4. **扫描来源**:`skillQueryScanResult`是真宿主判定。X异步扫描按md5去重;初始5秒,×1.5退避最多15秒,总等待120秒,连续fatal unavailable到3次归error;关闭/移除task取消timer。产品配置提供 `skillSecurityAppKey`,另有high-risk install policy读取和变更订阅。实现UI、缓存、轮询可以源码恢复;真实病毒/安全结论依赖对应扫描服务,绝不能把本地“未发现问题”假装成原扫描结果。
|
||||
5. **权益来源**:I `fetchEntitlementViews`4582向 `/v2/operation-platform/market/skill/get-by-ids`,按100个skill IDs分块;`pay_detail`归一金额分→元,monthly/permanent、latestPaidAt、expiry/refundable/orderId。`market-skills-cache:installed-entitlement`与registry/version更新触发可见性刷新。D购买/续费跳 `/open-pay/skill?assetId=...`,支付成功回调后install或刷新,退款后联动registry;这里只恢复客户状态,不能制造有效商品权益。
|
||||
6. **已安装缓存和隔离**:X `SkillsInstalledStore`2318706有scope、query、version/ifVersion、TTL默认5分钟、hydrate、inflight复用、invalidate期间拒绝旧写、监听和持久化最多5个query。`useWbSkillProvider`的scope含transport、user/enterprise、cwd、Buddy application/scene/resourceSnapshot。置顶由user storage串行写并迁移legacy key;最近项还有跨Buddy快照/文件路径验证。N local memory开关使用 `CODEBUDDY_LOCAL_SKILLS_MEMORY_ENABLED`,默认true并广播变更;此键本身不能证明完整技能学习算法。
|
||||
7. **手动调用不等于模型自动调用**:X `isUserInvocableSkill`2305518与 `isSkillModelInvocationDisabled`3716422分开;toggle显示的是 `disableModelInvocation`,并保留 `disable:false`。复刻时不能简单从输入列表删掉所有被关闭自动调用的技能。
|
||||
8. **引用和实际加载**:X `buildSkillBlock`1667403产生 `skill://<skillId或name>` resource_link,附 type/mentionType=skill、displayText、skillId、可选autoAttached。`parseSkillBlock`4345867;Genie分支 `skillBlockToGenieMarker`4346116有专有 `<supplementary>--intergration ...</supplementary>`,不是所有transport通用文本。H `getAvailableCommands`508810合并产品配置命令、插件命令、workspace projectCommandsList,并使项目同名命令覆盖。X `waitForLocalSkillRuntimeReady`4525570在下载后按session/cwd查询真实命令,200ms开始、倍增最多1秒、默认超时10秒,响应aborted/timeout;只有下载成功不等于会话加载成功。
|
||||
9. **工具结果与内核边界**:X `SkillToolAdapter`5311343、`SkillRenderer`5311825把真实Skill工具调用展示为技能加载;这是渲染器,不是加载器。实际prompt拼接、SKILL.md/辅助文件读取、权限/脚本执行、内核reload和沙箱行为在daemon/agent一侧,本次renderer证据尚不足以证明全部实现。YCode的 OMP 内核选择需实测是否支持同等显式技能输入、项目/用户优先级、热更新、禁用和工具事件,不能凭模型回复“用了技能”验收。
|
||||
|
||||
## 与YCode当前基线的差距
|
||||
|
||||
只读搜索 `src`:已有技能相关源词典、输入placeholder/context usage标签、历史 `Skill→use_skill` alias;未发现生产技能目录管理facade、安装/扫描/权益服务或技能市场组件。现有自定义模型、workspace、聊天和通用工具并不自动补齐这些能力。OMP可能有独立原生技能机制,需要核对实际已有RPC/CLI能力,而不是由这些UI词条推断已经接入。
|
||||
|
||||
推荐由主上下文按以下九个有界包推进;这是建议顺序,不是在本次评估中修改架构或默认授权安装。
|
||||
|
||||
| 包 | 边界与交付 | 验收条件/前置 |
|
||||
| --- | --- | --- |
|
||||
| S0 领域与宿主契约 | 独立shared skill domain、main registry/service、preload/API、renderer adapter;身份/source/presence/调用开关/扫描/权益明确区分 | 用自有fixture验证schema、cwd/用户/空间隔离、状态不串;主上下文确定OMP加载能力与存储根 |
|
||||
| S1 市场与已安装UI外壳 | 有限恢复M的顶部、分类、网格/卡片、骨架、错误/空态、installed和批量UI;保持共享专家/技能/连接器导航 | 固定REA同viewport/state的DOM属性、字体、几何、SVG与截图;真实数据adapter unavailable必须如实error/empty |
|
||||
| S2 详情 | 恢复D的header/overview/搜索/语言/示例/metrics/菜单/开关与路由返回;复用已有markdown渲染和SourceSelect/Popover等源组件 | 本地和多source详情;长文、搜索命中、loading/race、Esc返回;无源动作不得伪成功 |
|
||||
| S3 本地导入和管理 | 真实文件夹/zip/SKILL.md元数据、冲突/更新/用户修改确认、启停/删除/export、原子提交/失败回滚;不要与渲染器直接FS耦合 | 独立userData和自有目录fixture;取消无安装、失败无残留、重启保留、跨空间隔离、真实文件读回;具体路径/zip规则先补daemon证据 |
|
||||
| S4 输入与slash | +技能picker、搜索、置顶/最近、按账户/transport/cwd过滤、结构化skill block、手动与自动调用分离 | 选择引用真正进入发送上下文;切换任务/空间不串;键盘、source过滤、recent排序与实体缺失状态均实测 |
|
||||
| S5 内核执行 | 对接OMP实际技能发现/显式加载/热更新与工具事件;fallback如需有独立可信实现,不能只拼提示词 | 用自有无副作用SKILL.md和受控模型验证其内容/辅助文件确实参与、只有允许的workspace、启停生效、取消、真实Skill事件及结果;与原运行链另对标 |
|
||||
| S6 扫描和安装策略 | 恢复原扫描UI/state/轮询/风险地图;接真实扫描backend和策略(如无等价backend,明确 unavailable) | safe/risk/black/suspicious/pending/error/timeout、取消与后台通知;不允许mock结论冒充产品扫描 |
|
||||
| S7 远程目录、升级与云同步 | 真实目录provider接口,collection/search/detail/install版本关系、企业过滤、cloud-only下载、上传配额/覆盖/失败重试/可选云删除 | 服务授权/资源可用后以真实受控资源验证;禁止硬编码原账号目录或静态下载数冒充在线目录 |
|
||||
| S8 付费/授权与全状态验收 | 商品/权益真实adapter、已购/过期/续费/退款UI和可见性;最终整链same-state像素/动效回归 | 原商品服务不可复刻为本地假购买;先用明确测试权益验证UI,再在授权可用服务上验流程;完整对标之后才能宣称整个技能部分1:1 |
|
||||
|
||||
S1/S2可在S0最小只读接口确定后先推进;S3与S5是真正“技能能用”的本地闭环。S6/S7/S8不是因为本次不安装/购买就从最终目标删掉,而是证据、服务和后续操作范围独立。
|
||||
|
||||
## 具体未知与需补的REA证据
|
||||
|
||||
- **原版全部状态像素**:目前有V市场、VI稳定installed及VA部分有效的add dropdown帧;仍需import dialog、详情、不同tab/分类/搜索/空错态、窄窗/暗色与动效。静态源码可分析未出现分支,不能把它写为已实际交互验收。
|
||||
- **installer/daemon实现**:精确安装根、优先级、zip路径规范/链接/大小限制、原子覆盖、manifest/辅助文件、watcher/reload。需要后续REA定位daemon/主进程对应实现或授权自有测试技能的行为取证;本次不直接读取原技能文件夹或执行安装来补结论。
|
||||
- **扫描等价性**:appKey/服务器判定、病毒引擎/命中与认证、离线/组织策略;客户端poll源码不能还原服务判定。
|
||||
- **云目录/组织/商品**:真实各source API response/schema/签名下载URL、动态tab、visibility、账户权益、license、支付/退款。客户端facade明确但成功服务未被本任务调用验证。
|
||||
- **模型调用/内核**:显式技能block在各transport转换、daemon技能tool的加载内容、被禁用后的手动使用、不同session版本同步;原helper等待runtime-ready和实际WorkBuddyAdapter命令合并之间的完整能力链尚需进一步确认。
|
||||
- **资源**:纯功能SVG可从模块恢复;目录头像、示例图/视频和README内资源需经REA显式资源取证,不能绕过REA直接下载或假造。
|
||||
|
||||
## 查证与交接
|
||||
|
||||
`node scripts/audit-skills-reference.mjs` **PASS**:R339脚本全SHA、S根身份及两个选中文件SHA、L329加载脚本全SHA、选用CSS SHA、V/VI/VA三张PNG SHA一致;实际市场JS在S/L一致。解析不执行原脚本,生成有限函数/class/host method与完整M/D可读审查副本。V/VA整体failed已保留在报告中,没有改成passed。没有生产变更,故不为这次评估运行生产build或声称技能业务测试通过。
|
||||
|
||||
产物:本文件、`scripts/audit-skills-reference.mjs`、`.tmp/skills-audit-20261016/report.json`、`.tmp/rea-skills-market-selected-20261016.json`。下一步由主上下文选择有界实施包,并保持“源码已恢复、真实宿主已接、真实功能已验、同状态像素已验”四种结论分别记录。
|
||||
@@ -0,0 +1,76 @@
|
||||
# 空间与右侧工具栏评估(2026-10-15)
|
||||
|
||||
本轮只评估,没有修改生产代码。结论:这两块需要补组件结构、状态与本地宿主能力,不能靠继续微调现有 CSS 完成。YCode 的空间仍为 mock;右栏主要是自制运行统计占位。现有真实资源读取和产物预览可复用,但不等于原版完整详情面板。
|
||||
|
||||
## 当前 YCode 实现
|
||||
|
||||
| 范围 | 当前实际行为 | 与 1:1 目标的差距 |
|
||||
| --- | --- | --- |
|
||||
| 空间列表 | `Sidebar.tsx` 使用 `MOCK_SPACES`;可展开/收起;点击、新建、紧凑按钮仅显示未实现提示 | 没有真实工作区集合、任务归属、创建、导入、重命名、删除、排序及视图切换 |
|
||||
| 工作目录 | `stores/settings.ts`、`main/config.ts`、`workspace:choose` 提供一个全局目录,能调用系统目录选择器并持久化 | `SessionMeta` 没有 workspaceId/cwd;不同会话没有各自工作区。新增空间会触及会话/IPC/OMP/资源读取契约,不能只给侧栏加列表 |
|
||||
| 默认右栏 | `RightSidebar.tsx` 展示真实当前配置、消息数和工具数;可切换主题/字号;可用工具名单为固定两项,并明确标注占位 | 内容结构、入口及标签体系与原版详情面板不同 |
|
||||
| 右栏容器 | `App.tsx` 控制显示/隐藏与拖拽宽度,宽度全局持久化,320–900 px,默认 647 px | 缺少原版窄屏抽屉、均衡宽度、全屏、开闭状态机、会话独立的面板恢复及左右栏协同 |
|
||||
| 资源预览 | `ResourcePreview.tsx` 能显示文本行号/选中范围、目录、图片、产物;图片可大图及下载 | 文本/目录还是 YCode 自制宿主适配。没有原版完整文件树、文件编辑、统一多标签、标签排序/关闭策略、修改状态提示 |
|
||||
| 资源桥接 | `main/resources.ts` 真实读取工作目录内文件;文本 2 MiB、图片 20 MiB、目录最多 500 项;行窗口、图片解析和下载已接 IPC | 当前资源 store 仅一个 `path/resource`,不能表达会话独立的多文件/浏览器/终端标签;资源读取仍依据全局目录 |
|
||||
| 产物内容 | 已有 `ArtifactHostPreview`,部分类型使用恢复的原版实现(包括 Pierre Diff) | 应单独验收内容与外壳;现有单资源壳不具有原版产物导航、变更清单、统一标签和面板布局 |
|
||||
|
||||
源码审阅范围:`src/renderer/src/components/{Sidebar,RightSidebar,ResourcePreview}.tsx`、`App.tsx`、`stores/{settings,resources,chat}.ts`、`src/shared/{types,ipc,resources}.ts`、`src/main/{config,sessions,ipc,resources}.ts`。没有读取或输出真实密钥。
|
||||
|
||||
## 原版证据与代码入口
|
||||
|
||||
所有原版结论来自已经由 REA 导出的固定脚本/CSS;本轮未通过其他渠道读取原版。下面是静态代码结论,不表示对应交互已经实测。
|
||||
|
||||
- WorkBuddy 5.8.2;ASAR SHA-256 `035254bc76310ea46317433e4840602094543ef323d2d5c5aff7c131729de918`。
|
||||
- 脚本 Evidence:`ev_717fa5e846e64d67ac19c8925d121bff632c0d3aefb3603b10858559cabb2dcb`,保存于 `.tmp/rea-runtime-scripts.json`。
|
||||
- CSS Evidence:`ev_377c8790468b3c67dad8577aabb327f98d3140659f0fffdbabfcff5a40cc9e94`,固定清单 `.tmp/rea-css-recovered/manifest.json`。
|
||||
- 下表偏移为导出 JS 字符串中的 0 起始字符位置,用于重新定位,不是源文件行号。
|
||||
|
||||
| 原版模块 / SHA-256 | 锚点 | 已确认的静态行为 |
|
||||
| --- | --- | --- |
|
||||
| `contexts-BMeWSUHk.js` / `5f35b7489b107e21ef452c8ee88a95265756f6fc444841eef869228bbc44768b` | `sidebarConvToGroupingInput` 2632798;`deriveGroupedFolders` 2633426;`useSpaceSubfolderOrder` 2925299 | 空间下有 workdir、project 等不同分组;本地 cwd 归一、worktree 源 cwd 映射、活动排序、展开/可见数量状态,不能用知识库空间代替 |
|
||||
| 同上 | `CreateWorkspaceModal` 2944462;`startWorkspaceTask` 2981392;`WorkspaceBlockSectionInner` 2981990 附近 | 创建框宽 480,名称 trim 后允许确认,自动聚焦,Enter 有 IME 保护;宿主 `workspaces.generate({name})` 创建;从工作区新建任务先检查目录存在 |
|
||||
| 同上 | `WorkspaceBlockSectionInner` 2981990 附近;`SectionContextMenu` 3009070 附近;`getWorkspaceDeleteTaskStats` 3017747 | 工作区菜单按能力显示打开文件夹、CodeBuddy、重命名、删除;菜单边界修正、Esc 关闭;删除提示计入关联/置顶任务。尚不能据此断言会删除磁盘文件 |
|
||||
| 同上 | `useWorkspaceInputHost` 4576700 附近;`useHostWorkspaceInputCapabilities` 4577970 附近 | 创建目录与打开本地文件夹是两个宿主入口;取消返回空;重复提交和过时请求有保护 |
|
||||
| 同上 | `resolveDetailDrawerWidth` 2181121;`resolveDetailPanelLayoutWidths` 2181508;`useDetailPanelMotion` 2187304 | 面板宽度受可用会话区和最小宽度约束;宽屏分栏/窄屏抽屉;开 200 ms、关 150 ms;原生 reduced-motion 时直接落稳 |
|
||||
| `src-DwHViF_l.js` / `1bae5ee8385485c61494aae6f09828a0cb1bb867b761a0761330ceb30aaff60d` | `SidebarNext` 62090 附近;`useUnifiedTabs` 45881;`restoreSidebarSessionState` 61575 | 新版右栏统一文件、产物、浏览器、终端、quickAsk 及视图标签;有会话标签所有权、排序、最近关闭、预览标签池校验、切换恢复、固定/临时展开与折叠 |
|
||||
| 同上 | 73200–77100;`useCloseTabShortcut` 31285;`resolveSidebarMode` 77927 | 新标签入口按能力显示浏览器/工作区文件/修改/终端;关闭其他/右侧标签;Ctrl/Meta+T/W 由面板作用域处理;可全屏;存在 legacy/next 模式,默认回退 next,但实际运行所选模式仍需 REA 验证 |
|
||||
| `src-Cng7axVa.js` / `5ce8649e3bfac10aec1e63afee726ab45abaafc5aa7cc372892e20f3eba18c8b` | `FileChangesSidebar` 334385 附近;`SidebarNavContent` 384816;`NewTabLanding` 440500 附近;`DetailPanel` 483745 | 原版变更清单、目录树、产物分类/过滤、新标签首页和内容路由;文件树有懒加载、刷新、折叠路径、选中文件、双击打开等宿主契约 |
|
||||
| `detail-panel-wrapper-DkXYIOHM.js` / `35099e6a9294923f3cb413629ff47a65e5d545a7ff9226eff97675ae2dd5f906` | `DetailPanelWrapper` displayName;`usePreviewTabOwnership`;82911 附近 | 适配当前会话的文件、预览/浏览器标签、Office 窗口、文档预览、MCP App 面板等实际宿主能力,不只是视觉容器 |
|
||||
| `space-library-picker-D2BL85X8.js`(同脚本 Evidence) | `useSpaceLibraryData`、`fetchSpaces`、`fetchProjectSpace`、`searchSpaceNodes` | 团队/个人文档空间选择器是另一套云端知识库功能;不能与左侧本地工作目录空间混为一项 |
|
||||
|
||||
固定 CSS 中已找到相关真实选择器:`contexts-BkjwYSZT.css`(SHA `50cbd673f7f35fc7f966bdddc6c9f5677fdfe944cb904888d214619fca259380`)、`src-DYMqy4oz.css`(`420035cb969d5577ca19bf6d7b4e44f670580b51ec8987b6138728eb0416e060`)、`src-BPUOynUo.css`(`02a85e652dd1be508ab2bcf1b67880c3673d4c47e50b2caea24ac205bfe8f879`)。包括工作区菜单、空间分组、`sidebar-next` 和顶部标签操作。应带层级和 media 完整迁移,不能只拷贝选择器声明。
|
||||
|
||||
## 本地与云端边界
|
||||
|
||||
可以本地实现并严格对照的部分:工作区集合和目录创建/选择、会话工作目录归属、空间分组/排序/折叠/重命名/移除、从空间新建任务、文件树、文件内容/图片/产物/变更预览、面板多标签/拖拽/关闭/全屏/宽度/窄屏/会话恢复。没有证据表明这些必须使用 WorkBuddy 服务端。
|
||||
|
||||
需要另外补本地宿主能力的部分:终端进程/PTY、可编辑文件保存及脏状态、真实浏览器标签和导航、文件监听、Git 变更读取、独立窗口。它们是工程工作,不应伪装成原版按钮已完成。是否本阶段实现到完整操作能力由主任务统一范围;不能因其涉及宿主能力而自动排除 1:1。
|
||||
|
||||
按此前用户指示暂后且不能声称等价的部分:团队项目协作、云端文档/知识库、分享发布、企业文档认证、Office/文档云预览、云沙盒、MCP 服务授权、子代理调度。可对齐客户端入口与可用/不可用状态,但不接原版服务端、不伪造业务成功。
|
||||
|
||||
## 开工前应补的 REA 实测
|
||||
|
||||
本次评估未执行原版原生点击或截图,没有新增实时 Evidence ID。长任务第一批应通过 REA 保存以下状态,固定同版本、同视口、同字体、同数据,记录 hover/focus/disabled/空/加载/错误状态与恢复步骤。
|
||||
|
||||
1. 左侧空间默认形态:本地空空间、含 1/6/多条任务、长路径、选中任务与运行中任务、紧凑/卡片视图切换。
|
||||
2. 新建空间:空白、空格、有效名称、Enter/IME、Esc/遮罩取消、创建失败、重复提交;打开已有目录、系统选择器取消、目录不存在。
|
||||
3. 空间菜单:hover 和右键、屏幕边缘定位、重命名确认/取消、删除包含普通/置顶/运行中任务的提示与实际副作用。未经专用临时目录证据,不假定会删磁盘文件。
|
||||
4. 右侧默认到底使用 next 还是 legacy;逐个真实可见入口定位。所有 capability/账号/平台条件需记录,静态注册过的入口不等于当前用户可见。
|
||||
5. 面板空态、顶部标签、文件/图片/产物/变更、内容长短及加载失败;打开同文件是否复用标签、关闭最后标签、关闭其他/右侧、标签重排与快捷键范围。
|
||||
6. 固定/临时展开/收起、全屏、拖拽极限/双击恢复、窗口缩窄/放大、会话 A/B 切换恢复;reduced-motion 和开关被中途反转的动画。
|
||||
|
||||
## 建议的实现批次和验收
|
||||
|
||||
先建立统一 `workspace -> session -> panel session` 数据归属,再接组件;这是避免空间切换后文件预览/OMP 仍读旧全局目录的关键。具体类型/API 由主上下文统一决策。
|
||||
|
||||
| 批次 | 可交付与本地验收标准 | 主要依赖 |
|
||||
| --- | --- | --- |
|
||||
| A:REA 状态基线 | 上述各入口有截图、DOM/CSS、源状态规则和副作用证据;标清不可达分支 | 原版运行窗口与 REA |
|
||||
| B:空间真实化 | 创建/选择目录→新任务绑定 cwd→重启恢复;改名/移除不串空间;任务排序/计数/折叠与原版状态一致;本地故障回归 | shared/main/store 跨模块改动 |
|
||||
| C:面板框架 | 原版外壳/图标/标签/布局;每会话独立状态、复用/关闭/排序、快捷键、全屏/窄屏/动效;原版截图逐态比对 | B 的会话归属;固定源 CSS |
|
||||
| D:工具内容 | 文件树懒加载/刷新、文件定位、图片、产物、变更清单接现有真实资源桥;编辑/终端/浏览器按已确定能力接宿主 | 主进程资源/Git/PTY/浏览器能力 |
|
||||
| E:整体验收 | 同一导入对话打开文件/产物后左右两侧对应状态;长会话与跨空间并行任务不串数据;重启恢复;误差图逐类收敛 | A–D |
|
||||
|
||||
验收必须分开记录「组件已实现」「宿主真实可用」「对照截图通过」「行为序列通过」。不能以产物内容已恢复、CSS token 相同、构建通过代替右侧栏整体完成。当前没有足够基线给出可靠的全模块像素完成百分比或固定小时工期;可以据上面批次启动持续长任务,并逐个交付明确状态。
|
||||
|
||||
本轮验证仅为源码与固定 REA 导出审阅;没有运行构建/测试,因为未改生产代码。剩余风险是原版实际当前模式/权限条件、删除副作用、默认标签与窄屏行为尚需实时 REA 证据。
|
||||
@@ -0,0 +1,112 @@
|
||||
# 新建任务与自定义模型评估(2026-10-15)
|
||||
|
||||
本次只评估,不修改生产代码。用户要求新建任务交互和自定义模型添加体验对标 WorkBuddy,不使用 WorkBuddy 服务端模型。结论:可继续源码级对齐客户端,但目前两个模块均存在状态与数据能力缺口,工作量显著超过 CSS 调整;不能以已有会话导入、输入框外观或单一网关设置代表完成。评估中已追加获取模型设置主体 JS/CSS,表单源码缺失这一阻碍已解除。
|
||||
|
||||
## 证据范围
|
||||
|
||||
本子任务仅分析保存的 REA 导出和主上下文追加采集的 REA 证据;没有绕过 REA 连接原版 CDP、执行原版 evaluate、直接读取安装文件或使用旧 `wb-*` 工具。主上下文已新增模型列表运行时画面;静态分支不等于动态已验证,尚无这两个模块的双端像素验收。
|
||||
|
||||
- WorkBuddy 5.8.2;安装包 SHA-256 `035254bc76310ea46317433e4840602094543ef323d2d5c5aff7c131729de918`。
|
||||
- JS:`.tmp/rea-runtime-scripts.json`,Evidence `ev_717fa5e846e64d67ac19c8925d121bff632c0d3aefb3603b10858559cabb2dcb`。以下锚点为 `items[].source.artifact.text` 的 JavaScript 字符偏移(不是字节或行号)。
|
||||
- CSS:`.tmp/rea-css-recovered/manifest.json`,Evidence `ev_377c8790468b3c67dad8577aabb327f98d3140659f0fffdbabfcff5a40cc9e94`。仅说明当时已加载样式的范围,不覆盖全部 lazy 页面。
|
||||
- 模型设置主体:`.tmp/rea-assessment-model-source.json`,Evidence `ev_25f013c9fd2ad66153046eec06e94fb6128bfacc1e87e57aa90db6bc419075ec`,REA 对相同 ASAR 根摘要选择性导出两个成员。
|
||||
- 模型列表画面:`.tmp/rea-assessment-models/frame-000.png`(900×680),Evidence `ev_40da6df0424193923bae64a8ccb6fca97ea67813d7de671986d4d7e154b848c1`;REA 原生点击进入模型设置并等待,不运行模型请求。画面显示自定义模型卡片、两个已有模型、添加/编辑/测试/删除入口。本次没有读取或展示真实密钥。
|
||||
|
||||
| 原版文件 | SHA-256 | 相关函数/锚点 |
|
||||
| --- | --- | --- |
|
||||
| `home-CC-czDJL.js` | `121d5a07acccb09e48f20f3a94f9fac8b10770e4a82bca1916d2cccd333f8d14` | `useCreateHomeTask` 43266–51436;`useHomeInputSendHandler` 81136–85362;`useHomeInputProviders` 74819–80388;`useBuddyHomeInputPersistence` 13205–14363 |
|
||||
| `contexts-BMeWSUHk.js` | `5f35b7489b107e21ef452c8ee88a95265756f6fc444841eef869228bbc44768b` | `buildDefaultModelFormValue` 4036703–4037412;`resolveLocalCustomModelSettingsConfig` 4033903–4034815;`useModelSelector` 4097539–4112154;`useCustomModelEntry` 4115869–4116529;`saveNewTaskModel` 4088062、`loadNewTaskModel` 4088234 |
|
||||
| `workbuddy-provider-DkH2YFYM.js` | `b588e875c469978f216beec86bdf4b6c33a31c0266f9bf996881b8dbf37b5dc7` | `getLocalCustomModels`、`saveLocalCustomModel`、`deleteLocalCustomModel`、`testLocalCustomModel`、`checkLocalCustomModels`,567600–568800 附近 |
|
||||
| `home-D6iylhBV.css` | `bb1aa03bc4ac4e18072461e7b493ab5cd6aeab3deb5b77e059dc075b55a720d5` | `.wb-home-route`、`.wb-home-page`、首页输入/推荐/页脚等 |
|
||||
| `home-CyzXSQsx.css` | `0661cfef3bf9372f4d3ebad7de35b8c023178c3aae6d4e1b61d7f9a841197f60` | 同一固定 CSS 集中的另一首页样式 |
|
||||
| `ModelsSettingsPanel-Dn7mp8BK.js` | `739ab43ee521d8ef6e5b5b7731bb4e71b51454b2865f44a1228d7fcc2700149c` | 52007 B;`ModelsSettingsPanel` 22133–51116;校验/构造 payload 回调 `J` 27210–29304;保存 `Y` 29305–29739;提交 `Ke` 29740–30143;测试 `qe` 30144–30810;删除 `Je` 31340–31710 |
|
||||
| `ModelsSettingsPanel-FfiX-Du7.css` | `cd80b01d04589227a3c2db5dbe67b6c83b019bef18d3dba68ae5486448651018` | 18989 B;完整模型设置列表、编辑覆盖层、字段网格、测试反馈、删除弹窗样式 |
|
||||
|
||||
先前固定导出未包含模型设置 lazy chunk;主上下文随后经 REA 选择性补齐以上 JS/CSS。本报告已据新增正文修订字段、校验、覆盖确认、连接测试和删除流程。实际请求层的协议映射/能力处理与所有动态失败状态仍需进一步核对,不再把“拿不到表单源码”列为阻碍。
|
||||
|
||||
## 当前 YCode 真实能力及缺口
|
||||
|
||||
| 能力 | 当前状态与源码 | 与已知原版的差距 |
|
||||
| --- | --- | --- |
|
||||
| 新建入口 | `Sidebar.tsx:159` 调用 `newSession`;`stores/chat.ts:67` 调用真实 IPC 创建并切换;`main/ipc.ts:299` 实际存储 | 原版首页 `useCreateHomeTask` 在首条提交才调用 `conversations.create`,同时带任务配置。YCode 点击即产生持久空会话;首页又用 `messages.length === 0` 判定,缺独立新任务草稿/创建阶段 |
|
||||
| 首页内容 | `ChatPane.tsx:151` 渲染标题、三场景、胶囊和推荐;数据来自 `mock.ts` | 当前场景点击直接写固定提示词;原版具有场景配置、模板选择、输入草稿同步、推荐/选择状态,不是同一状态机。历史“实测”注释不能充当本次 REA 验证 |
|
||||
| 首次发送 | 输入框通过真实 `send`/IPC/内核运行;附件、资源、权限、语音已有宿主接入 | 创建 payload 没有 model/cwd/interaction mode/scene 的任务快照;原版创建携带这些字段,提交前还检查工作区、模型能力和创建并发 |
|
||||
| 草稿 | `ChatPane.tsx:32` 组件内按 session ID 保存文本/附件/资源 | 组件内状态没有持久首页草稿;原版 `useBuddyHomeInputPersistence` 有作用域与 500 ms 持久化等分支。重启、导航和场景切换具体行为需实测确认 |
|
||||
| 工作目录 | 全局目录真实可选、落盘;首页按钮打开设置 | 原版首页提供任务目标/cwd/worktree 的输入 provider、有效性检查及本地目录记忆。YCode `SessionMeta` 无 cwd;当前目录全局变更影响后续会话执行,不能模拟每任务绑定 |
|
||||
| 模型按钮 | `ChatPane.tsx:126` 只打开设置;展示 OMP 首模型或网关名 | 没有原版模型下拉、分组、当前项、搜索/编辑入口、思考设置、上下文选择。新任务模型偏好与每会话选择未贯通 |
|
||||
| 模型设置 | `SettingsDialog.tsx:180` 是单一旧网关的 baseUrl/model/key/temperature 表单,配置真实保存,密钥不回传渲染器 | 没有多模型列表、provider 分组、添加/编辑/删除/连接测试/能力设置;OMP 可用时该表单对实际对话不生效。这是功能断点,不能只换表单外观 |
|
||||
| 模型持久化 | `main/config.ts:15` 一个 `StoredConfig`;`updateConfig` 真正保存并 safeStorage 加密 key | 当前不是自定义模型注册表,缺稳定模型 ID、多记录与选择引用、导入旧配置迁移,以及按模型维护密钥的接口 |
|
||||
| 模型运行时 | `main/omp.ts:154` 读取 profile 首个 provider/model;构造器支持 modelOverride;`main/ipc.ts:126` 创建内核时未传 override | 首模型解析/显示不等于选择生效。必须打通 UI 选择→任务记录→实际 OMP 请求/内核模型→重启恢复。已有实例仅按 cwd 判定复用,需要评估模型切换时的行为 |
|
||||
|
||||
账号、云端模型、企业策略、收费/推荐请求属于原版存在的额外分支。本次用户已排除原版服务端模型;自定义 provider 配置可采用明确的本地数据来源,不能因此保留“选中模型实际仍跑固定 OMP 首模型”的断点。无需取得 WorkBuddy 服务端才能完成自定义模型客户端交互与用户自己的上游调用。
|
||||
|
||||
## 原版静态实现已明确的行为
|
||||
|
||||
新任务 `useCreateHomeTask` 有创建锁、空内容拒绝、creating/worktreePreparing 状态,创建配置包含标题、cwd、welcomeMode、mode、model、expert、permission、promptContentBlocks 等;成功后导航新会话,并清理对应草稿/准备上下文。`useHomeInputSendHandler` 会先筛掉 failed blocks,检查本地工作目录可用性,处理 before-send 拒绝和创建错误,失败路径可回滚已准备状态。这里只列可从源码确认的分支,不代表所有分支都需要同时实现云端依赖。
|
||||
|
||||
自定义模型 `buildDefaultModelFormValue` 明确返回:providerId、modelId、endpoint、apiKey、supportsToolCall、supportsImages、supportsReasoning、onlyReasoning、canDisableThinking、defaultEffort、supportedEfforts、useCustomProtocol、maxInputTokens、maxOutputTokens。provider 配置还明确区分 authMode(apiKey/none)、endpointMode(readonly/editable)、modelInputMode(select/selectOrInput/input)、advancedConfigMode、savePolicy 和能力默认值。
|
||||
|
||||
原版 selector 把 configurable/custom 标签或 `custom-local:` ID 识别为自定义模型;自定义入口支持设置 `models/new`、`models/edit/<id>`。新任务偏好保存 id/isThinking/reasoningEffort/contextWindow,并按用户/应用作用域读取。模型调用适配器有真正 list/save/delete/test/check 接口,说明“添加一个输入框”无法覆盖其生命周期。
|
||||
|
||||
## 补齐表单后的确切约束
|
||||
|
||||
以下来自新增 REA 模型主体正文,已经能直接指导实现;动态表现仍需同输入验收。
|
||||
|
||||
| 项目 | 原版规则与源码锚点 |
|
||||
| --- | --- |
|
||||
| 打开/关闭/编辑 | 新建回调 `K` 24640–24819 重置表单/测试错误/密码可见性;编辑 `q` 25093–26214 回填模型、endpoint、apiKey、能力和 reasoning/token 字段;Escape 关闭编辑覆盖层。切换 provider 重新采用该 provider 默认值并清除当前编辑对象 |
|
||||
| provider | 按配置分组;provider 总数大于 6 显示搜索。readonly endpoint 隐藏输入并用 provider tooltip 显示;editable 显示地址输入与即时 error 状态 |
|
||||
| 校验顺序 | `J`:选择 provider → trim 后 modelId 必填 → endpoint 必填 → editable endpoint 必须是 URL 且为 http/https → authMode=apiKey 时 key 必填且字符合法;失败 toast 后终止,没有新增记录 |
|
||||
| API Key | `sanitizeApiKeyInput` 19991–20052 删除全部 Unicode 空白;允许字符为 `^[\x21-\x7E]+$`(ASCII 可打印非空格)。表单密码/文本切换;实时字符错误和测试错误共用反馈区。authMode=none 隐藏输入且保存 payload 的 apiKey 为 undefined。编辑会回填已有 key,不能把 YCode 旧表单“留空保持”当成原版行为 |
|
||||
| 模型输入 | 当 provider.modelInputMode=selectOrInput 且有候选时用模型下拉,候选数大于 6 显示搜索;当前非候选值会加入选项。其余分支使用文本输入。模型选择可更新能力与 reasoning 默认值 |
|
||||
| 重复 ID | `Ke` 29740–30143 检查与当前编辑对象不同的同 ID 记录;出现覆盖确认,确认后才保存。不是直接拒绝或静默覆盖 |
|
||||
| 保存 | `Y` 调用 `adapter.saveLocalCustomModel({model,previousId,visible:true})`;成功更新列表/文件路径,发出 `agent-ui:custom-models-updated`,关闭编辑。失败普通 toast 并可继续编辑;企业策略拒绝分支会关闭编辑 |
|
||||
| 能力/协议 | provider.showCapabilitiesInForm 控制工具、图片、推理、自定义协议开关;支持推理后才显示仅推理、允许关闭思考、默认 effort、支持 effort 复选组。关闭推理会清除其附加状态;保存 reasoning 空对象时为 undefined。useCustomProtocol 是保存的布尔字段,其真实请求协议效果尚未由本表单证明 |
|
||||
| provider 自动策略 | savePolicy=autoFromModel 时以模型选项自动产生能力/推理默认值;手动能力分支保留表单选择。不能所有 provider 都用同一组默认 checkbox |
|
||||
| 高级区域 | advancedConfigMode 非 hidden 时出现标题与内容;该 JSX 没有折叠展开按钮。需纠正把它预设为可折叠区域的推断 |
|
||||
| tokens | 输入为 number/min=0/step=1;空字符串保存为 undefined,非空由 `parseInt(...,10)` 且 finite 判定。该函数没有正数、安全整数、上下文上限或输入输出大小关系校验,不能凭 UI min 属性声称服务层已有约束。输入快捷值 32768/65536/131072/262144(32/64/128/256K),输出 8192/16384/32768/65536(8/16/32/64K) |
|
||||
| 表单连接测试 | `qe` 30144–30810 复用上述 `J` 校验,只调用 `testLocalCustomModel(model)`,不调用保存;testing 中取消/保存按钮 disabled,测试按钮在 saving 或 testing 时 disabled。成功 toast;失败按 errorCode 映射到本地化反馈,无匹配用 defaultError;异常也落默认错误 |
|
||||
| 列表连接测试 | `X` 30811–31339 同时仅允许一个已有模型测试;失败给行标记,成功移除。编辑该失败项也移除失败标记;不是保存配置失败状态 |
|
||||
| 删除 | 点击显示含模型名的确认弹窗,遮罩/取消可关闭;`Je` 31340–31710 调用 `wb.models.deleteCustom(id)` 后 `wb.models.customs()` 刷新,再发 `agent-ui:custom-model-deleted` 并关闭。失败 toast,弹窗保留。表单层没有证明删除选中运行模型后的内核行为 |
|
||||
|
||||
表单 runtime bridge 是 `adapter-context` 提供的 adapter(保存/测试/读取),删除走 `wb-singleton` 的 models facade。已有 `workbuddy-provider` 将 save/test/list 交给 daemonClient 对应方法;当前证据仅证明客户端调用,不证明 daemon 内部 OpenAI/Responses/其他协议构造。YCode 无需调用这些原版服务,但自己的接口必须覆盖这些生命周期状态,并把选择实接用户上游/OMP。
|
||||
|
||||
## 建议采集与验收矩阵
|
||||
|
||||
每行应同时留原版 REA 截图/布局/交互证据和 YCode 相同输入证据;光暗主题、相同窗口和字号是对比条件。危险或联网状态可先用隔离用户上游和本地测试 fixture 验证 YCode,不改原版真实密钥或发送真实消耗请求。
|
||||
|
||||
| 组 | 必采/必验状态 | YCode 行为判据 |
|
||||
| --- | --- | --- |
|
||||
| 首页进入 | 从已有任务点新建;重复点击;初次启动无任务 | 首次发送前是否创建记录按原版实测定稿;不会不断堆积空会话;既有运行不会被误停止 |
|
||||
| 首页草稿 | 输入后导航返回;场景切换;切回;重启恢复;附件选取未完成时切走 | 与原版相同保留/清理范围;不会把 A 的附件/草稿挂到 B |
|
||||
| 首页布局 | 三场景及各展开子项;推荐有/无;窄窗口;长中文路径/长模型名;空输入和多行输入 | 原版组件结构、尺寸、字体、间距、滚动区域、图标及焦点表现逐状态对照 |
|
||||
| 创建 | 空/纯文本/附件;Enter/Shift+Enter/IME;快速重复提交;创建中;创建失败重试 | 一次操作一次创建;失败保留可重试输入;错误、禁用、loading 与原版一致 |
|
||||
| 任务配置 | 本地 cwd 选取/取消/不存在;mode/permission 选择;有/无模型 | 首轮真实使用提交时配置快照;与其他任务隔离,重启仍可还原 |
|
||||
| 模型入口 | 下拉关闭/打开;零个/一个/多个自定义模型;选中/悬停/键盘;进入新建/编辑 | 选择项与实际使用的 provider/model 一致;新任务和已有任务选择范围明确 |
|
||||
| 添加表单 | 默认 provider;custom provider;auth none/apiKey;模型选择/手填;高级显示/隐藏;推理条件字段 | 按原版字段条件和默认值显示,不把服务端模型写死为本地假项 |
|
||||
| 校验 | 必填空白;重复 ID 覆盖/取消;非法 URL;key 空白/非法字符;输入/输出 token 边界;能力组合;取消未保存 | 按已知校验顺序和数据结果验证;未声明的 token 服务层约束单独采证,不用自造规则代替原版 |
|
||||
| 编辑/删除 | 编辑已配置 key;清空 key 后提交;切换密码显示/遮罩;删除确认/取消;删除选中模型 | 编辑与密钥处理按原版可见行为设计并保护采集数据;引用被删除时行为待实测定稿,错误不静默 |
|
||||
| 连接测试 | 未填/就绪/测试中/成功/鉴权失败/超时/不可达/重复点击 | 测试走选定用户上游;状态可取消/重试,输入与执行目标一致,不误保存 |
|
||||
| 持久与运行 | 新增重启;编辑后重启;首轮/后续轮选择;运行中切换;回退内核 | UI、持久 ID、OMP/native provider 请求均一致;重建/切换不丢已有上下文 |
|
||||
|
||||
原版下一轮采集至少需要:首页本地目标(不会真实发送)、场景切换、目录 picker、模型 selector,以及设置新建/provider 切换/高级条件/删除确认。模型列表已有单状态画面,模型主体 JS/CSS 已补齐;后续采集聚焦各状态,而非继续停留在获取这两份正文。编辑、校验与网络失败可优先用隔离模型数据/假上游回归 YCode。账号/企业限制分支不等于用户范围内的自定义 API 能力,不能从代码里看到分支就要求用户接入原版后端。
|
||||
|
||||
## 实施依赖和拆分建议
|
||||
|
||||
以下是模块依赖,整体架构和排期由主上下文决策。
|
||||
|
||||
1. ModelsSettingsPanel 源码/CSS 已固定;补齐可复现首页/模型各状态画面、所用 selector 控件/弹窗依赖与运行时协议证据。
|
||||
2. 明确新任务草稿与已创建会话的边界,任务的 model/cwd/mode 绑定及旧会话迁移策略。此项同时影响空间和右侧栏,应由主上下文统筹。
|
||||
3. 自定义模型本地 CRUD、密钥和连接测试 IPC;模型 UI 与原版 selector/设置布局并行实现需要共享稳定数据契约。
|
||||
4. 将选择接入 OMP;说明运行中的切换时机/内核复用规则,验证多轮及重启。不能把旧网关表单改名后作为模型添加完成。
|
||||
5. 恢复首页输入 provider、场景与创建状态,再做完整状态回归和逐画面像素/动效对比。
|
||||
|
||||
可明确拆为“证据补全、任务草稿/配置、模型数据与 IPC、模型设置与 picker、OMP 选择贯通、首页交互、双端验收”七个有独立产出的工作包;其中数据契约和内核接入是实质依赖。当前证据不足以给精确工时或可信百分比。
|
||||
|
||||
## 本次检查结果及限制
|
||||
|
||||
- 修改文件:仅本文。
|
||||
- 检查方式:读取 YCode 源码;对保存 REA JSON 的目标 source 做关键词检索和 Babel AST 函数边界检查;使用 Node crypto 计算上述选中正文 SHA-256,与固定 manifest 中 CSS 身份对应。
|
||||
- 没有修改生产代码,未运行构建或测试;本次不是功能验收。
|
||||
- 已分析主上下文新增的原版模型列表运行时画面和表单完整 lazy JS/CSS;表单字段/校验/覆盖确认/测试与删除客户端流程已明确。网络请求协议、服务层 token 约束、删除选中模型行为、运行中模型切换、首页重复点击/重启细节仍待采证据。
|
||||
- OMP 自定义协议与原版 useCustomProtocol 等效性需单独确认;用户自己的上游可替代服务来源,但不可声称所有协议/能力组合已经等价。
|
||||
@@ -0,0 +1,82 @@
|
||||
# 统一能力中心与专家页面实施(2026-10-16)
|
||||
|
||||
本子任务只新增能力中心、专家页面、源码恢复资产/样式/工具及独立 QA;App、Sidebar、主进程、IPC、preload、聊天内核由 root 接线,SkillsPage 与 ConnectorsPage 由其他 worker 实施。未安装专家、未启用 WorkBuddy 服务、未操作用户数据或原版界面。
|
||||
|
||||
## 已实现
|
||||
|
||||
- `CapabilityCenter.tsx` 默认导出包含 `cwd/onBackToChat/onUseSkill/onCreateSkill/onFindSkill/onCreateExpert` 的约定接口,另支持 `initialTab` 初始化及 prop 变化。三 tabs 专家/技能/连接器使用原 `UnifiedMarketHeader` 源体。中心只有一个顶栏,页面通过 `CapabilityToolbar` portal 提供搜索/管理动作;`CapabilitySubpageHeader` 恢复“我的专家”的返回导航。
|
||||
- 通过源 token 的 Electron desktop 条件获得64px顶栏;主题跟随当前 document dataset 变化。中心填满现有主视图,样式限定 `.yc-capability-center`。480px窄窗换行是明确的 YCode host 适配,未声称是原版同宽行为。
|
||||
- 专家页默认明确“在线专家目录尚未接入”,不会把原版云端目录当作 YCode 已拥有专家。用户可选择查看缓存参考目录;9条是从已核验 REA 截图的可见文字转录,使用 `rea-reference-*` 独立引用 ID,禁用召唤/激活。头像原资产没有取得,使用原 `ExpertCardAvatar` 的文字 fallback。
|
||||
- 专家参考卡使用完整原 `ExpertCard$1` 源体、头像/加载 hooks、locale/格式/标签/搜索纯函数。源码中的 `useCount` formatter 用于重现截图显示数字:输入值由已显示的 `w` 数字反推,只用于只读归档展示,**不是精确后端计数,也不是实时统计**。原 metadata 结构令卡片恢复156px高。
|
||||
- 搜索框使用原 `ExpertSearchBar` 源体,300ms debounce、composition期间暂停提交、compositionend提交。分类、专家/专家团、排序按钮可操作;未归档分类/排序显示“此归档未保存”,不会编造结果。详情使用源外框/内容 class,展示仅已保存摘要和标签;未安装包不能召唤。详情关闭、Escape、焦点恢复及 Tab 限制已接。
|
||||
- 我的专家采用源 `ec-my-panel/toolbar/tabs/empty` DOM、真实空态 SVG、“搜索我创建的专家”、源返回/加号/我的专家 SVG。创建只调用 root 的对话入口回调;不是普通prompt CRUD,也不假称 expert-manager 包已工作。原“我创建的/我购买的”segmented 可切换,购买目录未接时明确不可用。
|
||||
- 模块不请求 WorkBuddy CDN、商店、账号或模型服务,不加载原 contexts 的 app 初始化;React/JSX使用 YCode 自身同一实例。
|
||||
|
||||
## 源码与证据
|
||||
|
||||
目标 **WorkBuddy5.8.2**;ASAR固定SHA:
|
||||
`035254bc76310ea46317433e4840602094543ef323d2d5c5aff7c131729de918`。
|
||||
|
||||
旧 runtime归档:`ev_717fa5e846e64d67ac19c8925d121bff632c0d3aefb3603b10858559cabb2dcb`(339正文);当前归档:`ev_e91787b1d4dea651582c6cf12827775b9068b0ee8b80c68ba08d4c1d87d94e90`(329正文),相关同名JS SHA一致。每次恢复先核验源文件SHA。
|
||||
|
||||
| 源文件 | SHA-256 / 用途 |
|
||||
| --- | --- |
|
||||
| `contexts-BMeWSUHk.js` | `5f35b7489b107e21ef452c8ee88a95265756f6fc444841eef869228bbc44768b`;UnifiedMarketHeader2420000附近、ExpertSearchBar3546674、ExpertCard3531248、class maps及纯函数 |
|
||||
| `src-DPDj7_qD.js` | `747e41d215375e1214c366213aea7e077d85421923029c61cbb6e9562be58de0`;专家/技能/连接器/返回/加号/我的专家6个源SVG |
|
||||
| `contexts-BkjwYSZT.css` | `50cbd673f7f35fc7f966bdddc6c9f5677fdfe944cb904888d214619fca259380`;页面、主题、卡片、详情、空态、分类排序 |
|
||||
| `tokens-Df-i-zsO.css` | `13f2bf82c96e5167a7d7098e36950c6c22c475b3337dbb8bb29ad2fe79cde696`;源颜色/字体/间距/尺寸/动效token;root与dark条件映射到本地scope |
|
||||
| `src-Bh3YZ35H.css` | `88dbdc1cd3f59d0e8b75824512a465a2be714bc7af481d790fe3a9484f85e01a`;真正的WB Input/Button/Segmented基础组件规则,保留媒体条件 |
|
||||
| `src-CBaV_A3S.css` | `2090ed21045c8f8b0fc388d76424c8751bf18fcd065cbbd5d0ef485163a2e36c`;已有REA原样式中的补充组件规则 |
|
||||
|
||||
CSS Evidence:`ev_377c8790468b3c67dad8577aabb327f98d3140659f0fffdbabfcff5a40cc9e94`。完整恢复索引 `capabilities/assets/recovery-manifest.json` 记录 **32源体**、**1256 CSS记录**、原文件/UTF-16 offset/源体SHA/输出SHA及显式 host adaptations;CSS声明/顺序、keyframes、媒体条件保留,选择器加scope。标题/搜索/卡片及搜索高亮原主体没有转写为自创 JSX。
|
||||
|
||||
空态 SVG 经 public REA `export-selected-artifact-binary`、固定根pin导出:
|
||||
`renderer/assets/empty-created-expert-BOI6XYXm.svg`;Evidence
|
||||
`ev_e5515aa84117724605f73439d065222c2e23b6ab8226be5d03f1ee0c7b387a9b`;SHA
|
||||
`157f07ef40d6cdf5f3aed362509861151fbdde0a8a9c89c98c26de6f35f664b7`。
|
||||
仅保存到本项目assets,不安装原版包。
|
||||
|
||||
页面参考:`.tmp/rea-expert-entry-static-20261016`,Evidence
|
||||
`ev_20de2f04c99b1c27bc39b61f5e2f5a430c3c7029b09afb76b363652eb4fadc89`,PNG SHA
|
||||
`e49ce30072a11898f3114b73dd3b941fe93fc0da46eee6fb15cb765635c5591a`。
|
||||
我的专家参考:`.tmp/rea-my-experts-static-20261016`,Evidence
|
||||
`ev_6f00d8b339cb4baf0af2a68f797e93dd6b5ce3ab18da2b43aa63ec09952c1d93`,PNG SHA
|
||||
`8b4c7ca84a4475131f5f43c7d746e6a7376a46a68b90adace60f774476a95f9b`。
|
||||
本 worker 只读 Root 的这些 REA 归档;未新增原版 runtime 动作。
|
||||
|
||||
## 宿主替换与未完成部分
|
||||
|
||||
- 原 tooltips采用本地 title、不接原遥测;source header visible-tabs由本地固定三项提供,原远端产品flag/覆盖icon尚未接。source search input通过匹配DOM合同的 React input 绑定,真实原primitive CSS已接。
|
||||
- 缓存详情是按源 DOM/CSS组织的本地只读视图,不是全部 `ExpertDetailContent` 源体;相关案例、团队成员、购买/退款、完整简介与快捷提示未取得该条目数据,未造值。
|
||||
- 专家市场推广横条的照片/动态布局资料尚未取得原图片资源,本轮不拼截图假装可交互组件。默认不可用态和缓存参考页因此不能宣称与原在线市场首屏全图像素一致。
|
||||
- 分类/其他排序/团队的归档为空;真实市场加载、分页/失败重试/企业权限和账号布局未接。
|
||||
- 本地 daemon handler、plugin/agent/skill包schema、expert-manager技能正文、安装/导入/导出、真实运行时绑定与专家执行仍待证据与宿主实现。原选择路径涉及激活、会话配置、craft模式、recents/pins和依赖检查;当前root创建只做到对话入口。详见 `assessment-experts-2026-10-16.md`。
|
||||
- 云同步、分享、扫描服务、配额、付费、专家团调度未实现/未验证。没有以UI或source hash通过宣称整项1:1完成。
|
||||
|
||||
## 验证记录
|
||||
|
||||
`node scripts/rea/recover-capability-center.mjs --check`:源体/资产/输出可重现,PASS。
|
||||
`npx tsc --noEmit -p tsconfig.web.json`:包含三个worker页面的合并类型检查,PASS。
|
||||
源组件 SSR 试渲染 header/search/empty/card,无缺失全局标识或无效值,PASS。
|
||||
|
||||
真实隔离生产App QA脚本 `scripts/verify-capability-center.cjs` 不伪造IPC、不发消息、不安装能力,只浏览测试profile并点击真实UI。第一轮 `.tmp/capability-center-SPgt1f/report.json` **23/23 PASS**:源header64px、tab宽60/60/78与gap24、默认目录不可用、9条只读引用/无召唤按钮、搜索过滤/清理、详情Escape、初始tab路由更新、三个tab、480px无溢出、创建仅草稿且0会话保存、HTTP0、renderer errors0。这个结果属于补齐segmented基础CSS之前的构建。
|
||||
|
||||
随后对原版我的专家布局定位真实差异:icon/title分别Y468.5/544.5,较源472.5/548.5提前4px;原因是缺失原segmented基样式令toolbar只有24px,原版32px。失败报告 `.tmp/capability-center-627u1I/report.json` 保留,未调整容差。已从正确 REA CSS文件补全基础规则,并移除不准确的手写Input/Button样式;另补创建按钮遗漏的源 `topbarActionBtn` class,恢复原16px水平padding与108px宽。
|
||||
|
||||
**最终统一build后的真实生产App扩展验收:33/33 PASS**,报告 `.tmp/capability-center-k6vN5H/report.json`,包含6张PNG与对应布局。除首轮项外,还验证:空态icon `[776.125,472.5,64,64]`、title `[745.125,548.5,126,22]`、toolbar32、创建按钮108px宽/14px字号、右侧动作区300px宽;原卡片动画结束后height156;真实DOM composition期间不筛选/end立即筛选;真实native appearance窗口深浅主题同步。HTTP请求0、renderer errors0、浏览及创建入口保存会话0。卡片曾在原fade动画中测得156.000015,最终测量等待原动画finished,没有放宽容差。
|
||||
|
||||
宽度前提是1336×901、YCode保存sidebar284.25;原版保存sidebar284.28125。最终my-experts空态icon/title坐标与原样本精确一致;header右侧宽300一致,其X1012与原X1011.984375有保存宽度/取整差异。参考卡为9项且无推广横条、头像包、完整目录或原版长列表滚动条,首卡宽322.578125;原在线长列表样本宽319.234375,**没有把这两个不同数据/滚动状态宣称为完整网格像素1:1**。窄窗只证480px无文档横向溢出,不宣称原版同宽布局已对比通过。
|
||||
|
||||
本轮不进行全页像素零差异、全动效/hover、完整云端行为等价验收。
|
||||
|
||||
## 修改文件
|
||||
|
||||
- `src/renderer/src/capabilities/CapabilityCenter.tsx`
|
||||
- `src/renderer/src/capabilities/ExpertsPage.tsx`
|
||||
- `src/renderer/src/capabilities/{capability-center-source,expert-source}.css`
|
||||
- `src/renderer/src/capabilities/assets/{source-ui.mjs,source-ui.d.mts,source-classes.json,recovery-manifest.json,empty-created-expert.svg}`
|
||||
- `scripts/rea/recover-capability-center.mjs`
|
||||
- `scripts/verify-capability-center.cjs`
|
||||
- 本文;`.tmp/rea-expert-empty-asset-evidence-20261016.json` 与独立QA报告/截图。
|
||||
|
||||
未修改App/Sidebar/shared/ipc/preload/main或其它worker文件。边界内后续source恢复以生成器为准,禁止直接改生成CSS再误称原体未变。
|
||||
@@ -0,0 +1,98 @@
|
||||
# 已创建专家:源码恢复与宿主边界
|
||||
|
||||
日期:2026-10-16。原版版本:WorkBuddy 5.8.2。
|
||||
|
||||
本次只恢复组件文件、局部样式、恢复工具与本文;没有修改 App、ExpertsPage、CapabilityCenter、IPC、主进程或共享数据模型。生产页面与真实专家注册表由主上下文接入。生产代码没有填充专家样例,没有模拟安装、删除或召唤成功。
|
||||
|
||||
## 证据身份与观察范围
|
||||
|
||||
原版读取全部来自已保存 REA 结果,没有原版运行时操作,没有直接读取安装包。
|
||||
|
||||
- 安装包 root pin:`035254bc76310ea46317433e4840602094543ef323d2d5c5aff7c131729de918`。
|
||||
- JavaScript:`.tmp/rea-runtime-scripts.json`,Evidence `ev_717fa5e846e64d67ac19c8925d121bff632c0d3aefb3603b10858559cabb2dcb`。
|
||||
- CSS:`.tmp/rea-css-recovered/manifest.json`,Evidence `ev_377c8790468b3c67dad8577aabb327f98d3140659f0fffdbabfcff5a40cc9e94`。
|
||||
- 空态 SVG:Evidence `ev_e5515aa84117724605f73439d065222c2e23b6ab8226be5d03f1ee0c7b387a9b`,原路径 `renderer/assets/empty-created-expert-BOI6XYXm.svg`;本地 `assets/empty-created-expert.svg`,SHA256 `157f07ef40d6cdf5f3aed362509861151fbdde0a8a9c89c98c26de6f35f664b7`。
|
||||
|
||||
恢复工具先核验全文 SHA,再用 AST 选择组件和纯函数。没有执行原模块初始化。
|
||||
|
||||
| 模块 | SHA256 |
|
||||
| --- | --- |
|
||||
| contexts-BMeWSUHk.js | `5f35b7489b107e21ef452c8ee88a95265756f6fc444841eef869228bbc44768b` |
|
||||
| src-DPDj7_qD.js | `747e41d215375e1214c366213aea7e077d85421923029c61cbb6e9562be58de0` |
|
||||
| src-0FGg1seX.js | `f2c6dbae949041b4e2bb456e8a23ae2837f2d7893ac24bf471485f77c7b15178` |
|
||||
| contexts-BkjwYSZT.css | `50cbd673f7f35fc7f966bdddc6c9f5677fdfe944cb904888d214619fca259380` |
|
||||
| src-Bh3YZ35H.css | `88dbdc1cd3f59d0e8b75824512a465a2be714bc7af481d790fe3a9484f85e01a` |
|
||||
| src-CBaV_A3S.css | `2090ed21045c8f8b0fc388d76424c8751bf18fcd065cbbd5d0ef485163a2e36c` |
|
||||
|
||||
以下 offset 为 UTF-16,下界包含、上界不包含。完整 25 个函数体、273 个 CSS 记录及原始/适配 SHA 在 `assets/created-expert-source-manifest.json`。
|
||||
|
||||
| 原函数 | 模块与范围 | 函数体 SHA256 |
|
||||
| --- | --- | --- |
|
||||
| CreatedExpertCard | contexts `[3836312,3843963)` | `ecbaba2a34fe1e6afdb608845bf52e3d1e58518c17f8f7108d4ef43b865d3128` |
|
||||
| CreatedExpertsPanel | contexts `[3845690,3851495)` | `73d81b6f1c3205fa1b8c67639fa821af60f0b29d236be4d2260406a75f579e47` |
|
||||
| CreatedExpertDeleteDialog | contexts `[3605118,3606196)` | `8043033f6a107e1fbdb950df72dae9c28675ea6123262e977ea89eb948657ad4` |
|
||||
| Dropdown | src-DPD `[824745,827584)` | `2d96b1bb76d33a59f1e8ecfe040bd40fc05255b9c4ff1831ab33a0f00cc8cbc1` |
|
||||
| DropdownMenuList | src-DPD `[791722,795284)` | `bea2f5ed3c5c42cb6dd9599dfc6027bf2a29b5fa18526b6b18cb63d7a0c84a1e` |
|
||||
| ConfirmDialog | src-0FG `[551341,554641)` | `25a5264f2a876512ef2d0a6217dbdceeb6246ed03d225795f5875af0b980d421` |
|
||||
| Ku(cb Button) | src-0FG `[137355,138067)` | `a6bac5d42f03b0f4756d879228a2e24c35a7221fd6c6af8da7d9e7b1a94a656e` |
|
||||
|
||||
CreatedExpertsPanel 只有一个源码文字变更:静态 SVG 地址改成本地同 SHA SVG。原/适配函数体哈希分别记录。原卡片复用此前恢复的 ExpertCard;源图标还原了原 createIcon/bn 的 16px 默认尺寸,而非只复制 SVG path。
|
||||
|
||||
## 可接接口
|
||||
|
||||
`assets/created-expert-source.mjs` 具名导出:
|
||||
|
||||
```ts
|
||||
CreatedExpertSourceProvider({ host?, children? })
|
||||
CreatedExpertCard({ expert, onUse, onDelete?, onEdit?,
|
||||
isMenuOpen?, onToggleMenu?, highlightKeyword? })
|
||||
CreatedExpertsPanel({ createdExperts, activeTab, onTabChange,
|
||||
onUse, onDelete?, onEdit?, searchKeyword?, toolbarExtra? })
|
||||
```
|
||||
|
||||
`activeTab` 是 `expert | team`。Panel 保留原组件单一打开菜单 ID;独立 Card 必须由宿主维护 `isMenuOpen/onToggleMenu`。
|
||||
|
||||
- `onUse(id, initPrompt?)`:调用真实会话启动;预览的原 `onSummon(id, unused?, initPrompt?)` 保留参数位置。
|
||||
- `onEdit(expert)`:把原专家对象交回对话驱动编辑入口。
|
||||
- `onDelete(id)`:返回 `false` 或 reject 都保持原删除框。reject 只显示通用失败提示;等待中禁用确认、屏蔽关闭。返回 `true/void` 才按原组件成功分支关闭。
|
||||
- `host.openPath(rootDir)`:必须由受控 IPC 实现。返回非空错误字符串或 reject 会显示原打开失败文案;组件不接触 fs。
|
||||
- `host.resolveAssetUrl(value)`:可选本地头像解析器。默认只允许 image data/blob/file/ycode 协议,不自动请求 HTTP 头像。
|
||||
- `host.renderPreview({expert,onClose,onSummon})`:宿主真实包详情。组件隔离 React 事件传播,避免关闭按钮冒泡到源 article 后重新打开。未提供时仅显示本地标题和描述,不能代替完整 TeamDetail。
|
||||
- `host.notify(message,type)`、`host.locale: zh | en`:局部消息和原归档文案。
|
||||
|
||||
需要外层能力中心的源 token/主题样式。Provider 创建一次绑定,后续 host 对象更新只更新 ref,避免每次渲染重新挂载卡片/丢失弹窗状态。React、JSX 与 ReactDOM 均来自 YCode singleton。
|
||||
|
||||
卡片使用原字段:`id/name/displayName/profession/description/displayDescription/expertType/expertRootDir/avatar/version/updatedAt/tags/useCount`。`name` 是本地包字符串;displayName/profession/description 支持原 zh/en 文案结构。字段含义、包来源和激活由真实注册表负责。
|
||||
|
||||
## 宿主适配与未恢复内容
|
||||
|
||||
云开关 `ic/oc` 明确关闭;公开 facade 不接收 share/cloud callbacks。原服务 hooks 不执行、未导出。源卡片中保留的云分支不可由公开接口触发;不可把这部分声明为已实现。
|
||||
|
||||
原 Dropdown、菜单列表、文字、确认框、按钮、图标函数体保持。Popover 是本地宿主:使用已有 Floating UI 定位、4px offset、flip/shift、门户、外点关闭、Escape/方向键。仅验收当前本地平面菜单;没有宣称完整原 Popover、子菜单、tooltip 和动效逐帧等价。Tooltip 当前使用原文字的 native title。
|
||||
|
||||
cb 组件原依赖全局主题变量。本次恢复 src-CBa 原 cb token 声明并局部映射浅/深主题,向 ConfirmDialog 传宿主实际主题。缺少原 IDE 动态变量的错误前景/背景,通过明确适配桥接到已恢复 WB error/danger token。桥接不是原运行时颜色比对结论。
|
||||
|
||||
源 geometry 有条件:本地没有 useCount 时,ExpertCard 使用 centerCardWithoutMetadata,高度 auto;本次 128px。市场含 usage 卡片的固定 156px 不适用于此状态。CreatedExpertsPanel 文本 tabs 自身 24px;带 32px toolbarExtra 时整个 toolbar 自然 32px。
|
||||
|
||||
## 验证
|
||||
|
||||
```powershell
|
||||
node scripts/rea/recover-created-experts.mjs --check --native-qa
|
||||
npx tsc --noEmit -p tsconfig.web.json
|
||||
node scripts/rea/recover-capability-center.mjs --check
|
||||
```
|
||||
|
||||
恢复与旧能力中心源码审计通过;web TypeScript 通过。最终独立原生验证 **34/34 PASS**,报告 `.tmp/created-expert-source-H0svkz/report.json`。`--native-qa` 自带可重复的隔离 fixture:创建自身 `.tmp/created-expert-source-*` 目录与三份测试 manifest,生产 React bundle、真实 Electron 窗口,不假造 IPC、不发送消息、不使用用户目录、不操作原版。
|
||||
|
||||
最终报告目录见命令输出,`report.json` 含原生断言、geometry、renderer error/HTTP 列表,六张 PNG 保存卡片、菜单、浅/深删除框、空态与 480px 窄页。覆盖:原菜单四项与 16px 图标、24px more、32px item、4px anchor gap、单一菜单、Escape、编辑/目录/召唤参数、预览关闭不重开、删除 false/reject/pending/success、搜索与 team 分类、host 更新不卸载、明暗主题、窄屏长标题和 0 外部 HTTP/renderer error。
|
||||
|
||||
独立 fixture 通过不等于完整生产 App 流程通过,也不是原版全状态像素验收。真实注册表、对话驱动创建/编辑、删除/召唤及完整原版截图比较由主上下文继续验收。
|
||||
|
||||
## 文件
|
||||
|
||||
- `src/renderer/src/capabilities/assets/created-expert-source.mjs`
|
||||
- `src/renderer/src/capabilities/assets/created-expert-source.d.mts`
|
||||
- `src/renderer/src/capabilities/assets/created-expert-source-manifest.json`
|
||||
- `src/renderer/src/capabilities/created-expert-source.css`
|
||||
- `scripts/rea/recover-created-experts.mjs`
|
||||
- 本文与 `.tmp` 隔离验收报告。
|
||||
@@ -0,0 +1,78 @@
|
||||
# 输入框已选专家标签:源码恢复(2026-10-16)
|
||||
|
||||
已新增独立 `SourceActiveExpert`,未编辑 App、ChatPane、ComposerControls、stores 或主进程。原版仅分析已保存 REA 脚本、CSS 与被动布局;本轮没有操作原版 UI。
|
||||
|
||||
## 证据与源码身份
|
||||
|
||||
WorkBuddy 5.8.2,REA 安装包基线 root SHA `035254bc76310ea46317433e4840602094543ef323d2d5c5aff7c131729de918`。
|
||||
|
||||
| 来源 | Evidence / SHA |
|
||||
| --- | --- |
|
||||
| `.tmp/rea-runtime-scripts.json` | `ev_717fa5e846e64d67ac19c8925d121bff632c0d3aefb3603b10858559cabb2dcb` |
|
||||
| `src-DbE1_mgM.js` | `6c6ce63c93854783270e855572797d75e536e3b8d4548410e31fe9d147e1feb4` |
|
||||
| `src-CyXHA0IC.css` | `a5e26b537bb50323aefbf25abddad52e288dd3868598be8d255d70886fe77cfe` |
|
||||
| `src-CBaV_A3S.css`(颜色/主题变量) | `2090ed21045c8f8b0fc388d76424c8751bf18fcd065cbbd5d0ef485163a2e36c` |
|
||||
| 当前原版被动截图/布局 | `ev_7e9604adb87a3d21570eb7a371001e48b3d316ee0388a03a97e2cb564d03aff7`,`.tmp/rea-expert-usage-current-20261016/` |
|
||||
|
||||
恢复脚本在解析前验证脚本和 CSS SHA。生成的 `SourceActiveExpertManifest.json` 完整保留30个原函数的源码字符区间和 body SHA,以及输出 SHA/字节。源区间为 `[start,end)`,不是行号:
|
||||
|
||||
| 函数 | 原字符区间 |
|
||||
| --- | --- |
|
||||
| `ExpertChip` | `[1693365,1695005)` |
|
||||
| `ExpertAvatar` | `[1695006,1695726)` |
|
||||
| 可显示判断、准备中匹配、team头像解析 | `[1692572,1693249)` |
|
||||
| fallback seed 与确定性颜色 | `[1146532,1146927)` |
|
||||
| `ChipCloseIcon` | `[471321,471715)` |
|
||||
| `LoadingSpinnerIcon` | `[406658,407080)` |
|
||||
| `Tooltip$1` | `[377803,380607)` |
|
||||
| `TooltipLayer` | `[373215,375023)` |
|
||||
|
||||
初次找到的 `wb-status-chips-BkgUUbOl.js` 是另一套 `_1udom_` 实现。当前被动画面实际使用 `cr-*` 类,因此最终恢复上表 `src-DbE1_mgM.js` 的组件,没有混用旧组件的 avatar 或 tooltip 逻辑。
|
||||
|
||||
## 原版行为与宿主适配
|
||||
|
||||
- 标签优先显示 `profession.trim()`,其次为非 id 的 `name.trim()`。头像/名称尚未 hydrate 完整时沿用最近可展示的选择;显式 null 清空缓存。
|
||||
- 外层是 `role=status` 静态标签。**没有点击标签打开菜单的源码行为**;专家菜单仍由输入工具栏的 + 入口负责,故这里不添加 `onOpenPicker`。
|
||||
- hover/focus-within 时头像位置换成原16px ×图标。清除按钮 stopPropagation,乐观清空选择,再 await provider.onChange(null);拒绝时恢复。
|
||||
- 原 provider 的 selected-id effect 会 silent summon;`suppressAutoSummon` 可跳过。YCode 真实选择/召唤由根上下文负责,标签 adapter 对非 null silent 通知不再次激活,避免重复 runtime 初始化。
|
||||
- preparingExpertId 匹配 id 或 marketExpertId,原样显示 `aria-busy`、头像透明度与 spinner。坏图片回退到 profession/name/id seed 首字符及源8色确定性背景;team 可使用 assistantDisplayName/Profession/AvatarUrl。
|
||||
- compact 仅保留32px圆形标签并给职业 tooltip;普通模式文字最大140px,只有截断时显示完整 tooltip。恢复原 Tooltip、TooltipLayer、150ms transition、200ms hover delay、3px arrow、键盘 focus 判断和按压抑制 helpers。
|
||||
- `scopeKey` 是宿主额外边界,切换时重挂载缓存;旧清除失败不能覆盖新会话或新选择。`disabled` 是额外忙碌状态:禁用按钮并保留头像。原源码此标签没有完整 disabled 参数,这部分明确是 YCode host 适配。
|
||||
- React/JSX 与 `@floating-ui/react` 使用 YCode 单例/已pin宿主依赖;没有声明等同原版打包依赖版本。源码 JSX namespace 绑定替换、CSS选择器限定作用域、tooltip portal包裹作用域;原 CSS 声明值保留。主题增加 YCode `data-theme` 到原 light 规则的宿主映射。
|
||||
|
||||
## 接口与集成
|
||||
|
||||
```tsx
|
||||
import SourceActiveExpert from './capabilities/SourceActiveExpert'
|
||||
|
||||
<SourceActiveExpert
|
||||
expert={expert ? {
|
||||
id: expert.id,
|
||||
name: expert.name,
|
||||
profession: expert.profession,
|
||||
avatarUrl: expert.avatarUrl
|
||||
} : null}
|
||||
scopeKey={actualOwnerKey}
|
||||
disabled={busy}
|
||||
preparingExpertId={preparingExpertId}
|
||||
onRemove={async () => { await persistActualDeselection() }}
|
||||
/>
|
||||
```
|
||||
|
||||
`onRemove():void|Promise<void>` 必须执行真实清除;失败应 reject,不要先吞掉错误,组件才能按源回滚。父组件负责更新 controlled expert 与会话持久化。可选 `compact`。`ActiveExpert` 还支持 marketExpertId、expertType、assistantDisplayName、assistantProfession、assistantAvatarUrl、suppressAutoSummon。
|
||||
|
||||
## 文件与验证
|
||||
|
||||
新增模块:`SourceActiveExpert.tsx`、`SourceActiveExpertRuntime.tsx`、生成 `SourceActiveExpertRecovered.mjs/.d.mts`、`SourceActiveExpertSource.css`、`SourceActiveExpertManifest.json`。恢复脚本 `scripts/rea/recover-active-expert.mjs`,原生验证 `scripts/rea/test-active-expert-native.mjs`。
|
||||
|
||||
```powershell
|
||||
node scripts/rea/recover-active-expert.mjs --check
|
||||
node scripts/rea/test-active-expert-native.mjs
|
||||
npm run typecheck
|
||||
```
|
||||
|
||||
结果:恢复一致性 **30函数/3源通过**,typecheck通过;原生 Electron **38/38通过**,报告 `.tmp/active-expert-native-yS4h06/report.json`,截图 normal/hover/preparing/compact-tooltip。
|
||||
|
||||
固定原文“高级算法工程师”在同字体环境中:原 `[458.125,463.5,127,32]`,fixture `[100,100,127,32]`;位置由测试容器决定,尺寸一致。头像16×16、文字91×20、间隙4、左右padding8、13px/500/20px文字、圆角、颜色、transition等16项选定计算值与保存的REA布局完全相同。其余检查覆盖名称优先级、坏头像/team头像、准备中、长文本、紧凑模式/tooltip、真实 Enter 清除、失败恢复、异步切换选择和owner隔离。
|
||||
|
||||
本次 avatar 测试使用受控本地 fixture 图片;未将它当作原专家头像像素。原版 hover、preparing、tooltip 动态没有新增实时取证,只能确认其源实现已恢复并经本地执行。尚未验收整应用布局、原头像同状态像素、自然 Tab 遍历可达性和全状态动效;这些不能由编译/局部几何通过替代。
|
||||
@@ -0,0 +1,120 @@
|
||||
# 专家本地包契约与 REA 原文恢复(2026-10-16)
|
||||
|
||||
本轮已取得 WorkBuddy 5.8.2 本地专家扫描、激活、依赖、安装/导出实现,以及完整 expert-manager 技能、4 份规范和 5 个 Python 脚本。11 份技能资源已逐字恢复,另提供可静态 import 的 JSON;未运行原版技能/Python、未安装或启用原版专家。YCode host/环境适配与实际 backend 验收是后续独立工作,不能算本次原文导出已验证。
|
||||
|
||||
## 身份、范围与文件
|
||||
|
||||
固定根 ASAR SHA `035254bc76310ea46317433e4840602094543ef323d2d5c5aff7c131729de918`。版本依旧以已存 REA package.json(`ev_2caae424199a38371af743ef9111db835504c2dae54c1f02e1f9e5511032cc6b`)的 5.8.2 为准。起点为 `.tmp/rea-workbuddy-takeover-2026-10-15.json` 的 relevant-file inventory,Evidence `ev_df8468f8f31100525395ec493367a16770371db119cce47ca3ce19aacfd89eb7`。未重新全量分析;路径定位、原包读取均经 public REA CLI,未直接读取安装目录/用户目录、手写 ASAR extractor 或 CDP/evaluate。
|
||||
|
||||
| REA Evidence | 定向成员 | SHA-256 |
|
||||
|---|---|---|
|
||||
| `ev_81de6f628a156599f26ca795f6747ad3f8ec108de66fdba6e3723705905716f3` | `main/module.app-server.js` | `281666dbf81b76d64f95162a19dd2d02a41b35ec54239e0efc4e8e52419eb125` |
|
||||
| 同上 | `main/runtime-handlers.js` | `6567dd0f9ffdc78fd22a540e993590aa47190be6b6a9501a5fd0115392b0f5cf` |
|
||||
| `ev_75c9f1cb7975a8d61135abe7d4348024f305be540b10ba789094b0729a20358f` | `main/server.js` | `7e2a95d0615cce057e3076c57730f713bd42b63b146702f14cbf04d8671b7bef` |
|
||||
| `ev_1b2c1146db5458f4e7e163150512ece87e656c09dba5cffaa5d4cee367525ccc` | `main/tar.js` | `e252bf614cb59ffa96e16ad0ab8cfd8796f5ab920289ca9bd67376e1d9836cf3` |
|
||||
| `ev_c3df29dcb19c5fcaa9e458b1b9acff92e8c75ac935791e0c81900733e61b6282` | daemon bootstrap/main/entry、expert-manager metadata、builtin marketplace | 每项 SHA/bytes 在同名 `.tmp/rea-expert-package-ev_*.json`;daemon-main SHA `a3b9d6f3ca17954a89d4e442137348b230c8ea9c74181625556bfae2ffe98154` |
|
||||
| `ev_3cba49fcb15fefc59f54c7691500ad1121a937edb55e606addae17e4186ebfef` | `resources/plugins/workbuddy-builtin/skills/expert-manager/SKILL.md` | `18b0655c3e7573fe9402fd00a605d2dc94918c9eecd028f9f3923e74da17bc45` |
|
||||
| `ev_a4b0f399496f62f4dc41998e8327fb219ab84f3dca536ec6554553605b106735` | `references/plugin-json-spec.md` | `14e1a6b99c74815c22772a54725ba6d34750a6c9db4c75746c1188e31d2504f3` |
|
||||
| 同上 | `references/agent-md-spec.md` | `ec7373578a5f84d73ba16dcc71e73755e57aa4170cb07cd9bf379627c0f9c007` |
|
||||
| 同上 | `references/team-spec.md` | `1400af007c6b1179429c6d8c856dc1d45ae25dae63645097ddbc801d25d324f9` |
|
||||
| 同上 | `references/avatar-spec.md` | `0b42762e05e311632b2f89af35f34458f851a03cce3fcc0300ca0a75e9f8890e` |
|
||||
| `ev_25ded03a70790361a3f4fef21a3bd2466d5f7d3d118b7b7aada33b07efcf5cf8` | `scripts/register_expert.py` | `b2dd1a0141c2dc88ed7203246335fd261eca97a17f91f4e280d3ce8b10a65b1e` |
|
||||
| 同上 | `scripts/init_expert.py` | `742fe9b70085a31850caf327d83f416ff19e9ee7482053e7aa99bd9b780206e4` |
|
||||
| 同上 | `scripts/validate_expert.py` | `6e85c716af94d6ee2ffc86a24a7230d15cd675a0fbaaf45a8980fd51d9c1c6fd` |
|
||||
| 同上 | `scripts/package_expert.py` | `e3d82044fd5fc7b749d65c178af0bed18bbc0375a952b878cfa019b09e04d8fb` |
|
||||
| 同上 | `scripts/batch_create.py` | `c926d7b8721c4ec4179a3d481271bdb01d41764c3301e01cdafd9e96c37e154c` |
|
||||
|
||||
恢复目录 `src/main/capabilities/assets/expert-manager/` 含上述 SKILL、refs、scripts、`.codebuddy-plugin/plugin.json`。metadata 的 SHA 为 `6908b9cd71687525e342c2500fa9d32a847f72e3e263190655ca9347402cb389`,声明 `name:skill-expert-manager`、category skill、workbuddy.kind builtin-skill、legacyResourceName expert-manager 与 bundleSegments。该 metadata 是技能资源包装,不是用户创建专家的 plugin schema。
|
||||
|
||||
`rea-source-manifest.json` 逐文件记录原 member/Evidence/SHA/bytes/export;目录外 `src/main/capabilities/assets/expert-manager-source.json` 为 `{files:Record<relativePath,string>}`,11 份原文共 82,929 bytes,方便打包时静态导入。完整正文已读;原文没有替换路径、工具、ImageGen 或业务语义。Root 后续 adapter 会明确处理 YCode config/session/受控工具和不可用的头像生成。
|
||||
|
||||
## Handler、扫描与会话 marker
|
||||
|
||||
所有下列 JS offset 为 UTF-16 code units、end exclusive。`.tmp/rea-expert-package-contracts.json` 为 SHA-verified AST 定义索引,含有限函数正文与函数体 SHA,可直接 review。
|
||||
|
||||
`main/server.js` `createExpertServiceObject` `[226652,230495)` 绑定真实服务;`registerExpertServiceHandlers` `[231650,231794)` 与 registerExpertHandlers `[231794,232500)` 注册 expert 通道。它把 scan/get/delete/addUser/clearMarker 转给 ExpertDesktopService.custom,把 fromPath/fromUrl 转给 package manager,把 activate 交给 ExpertPluginService。不能只凭 renderer 的 API 名判断本地实现不存在。
|
||||
|
||||
`main/module.app-server.js`:
|
||||
|
||||
| 定义 | offset | 已观察行为 |
|
||||
|---|---|---|
|
||||
| ExpertCustomRuntime.doScanCustomExperts | 58588–60184 | 读取 `plugins/marketplaces/my-experts/.codebuddy-plugin/marketplace.json` 的 plugins;不任意扫描未注册目录。source 去 `./plugins/`,拒绝含分隔符/上级路径的 ID,忽略缺目录/manifest,修复 trailing comma 与陈旧索引。可按 user ID 清单过滤。 |
|
||||
| readCustomExpertFromDir | 65233–66184 | plugin manifest 展开;tags/quickPrompts/triggerPrompts 兼容 locale-array,members/connectorIds/bin/references 归一;补 version=1.0.0、id/name/目录名、expertRootDir、isCustomExpert、marketplace。成员缺 id 可从 agent 字段补。 |
|
||||
| addUserExperts / getUserExpertsJsonPath | 62525–62912 / 64072–64169 | 用户已收录 ID 数组存 `experts/custom/<userId>/experts.json`。不存在返回 null,扫描不强制过滤;现存空数组会过滤掉全部。 |
|
||||
| archiveCustomExpertSessionMarker | 63187–63574 | `.created-by-session` rename 为 `.pending-preview-session`,清 DTO cache。 |
|
||||
| clearCustomExpertSessionMarker | 63574–63996 | 删除这两种 marker,清 DTO cache。 |
|
||||
| readPluginManifestAsync | 58204–58352 | 顺序尝试 `.codebuddy-plugin/plugin.json`、`.workbuddy-plugin/plugin.json`。 |
|
||||
| deleteCustomExpert | 61604–62525 | 删除磁盘专家、用户索引/marketplace条目并 deactivate;原版行为需与 host 安全校验单独对照。 |
|
||||
|
||||
`createdBySession` 从 `.created-by-session` 优先,否则 `.pending-preview-session` 读取 trim 后纯文本。`main/server.js` createCustomExpertWatcher `[203613,205817)` 采用 marker 收录用户专家、archive marker 并广播变化;renderer 预览消费后再 clear。因此 marker 不只是短暂 Toast 标记。
|
||||
|
||||
## 激活与依赖
|
||||
|
||||
ExpertPluginService.activateExpert `[80288,81496)` 根据身份/缓存映射解析 bundle;my-experts 直接本地目录,官方包可能下载;要求可读 plugin manifest,expertType 缺省 skill。agentName 优先 manifest.agentName,team fallback teamInfo.leadAgent,否则从 agents 路径/Markdown frontmatter匹配。它增量注册 marketplace、移除旧自动 agent override、记录 active set、通知 runtime config 变化,并返回 `{success,expertType,agentName,localPath,pluginRegisteredName}`。这是本地准备/注册的契约,不等于 OMP 已有等价插件运行时。
|
||||
|
||||
ExpertBundleRuntime.updateMarketplaceManifest `[51566,52437)` 写 `{name,description,plugins:[{name,source:'./plugins/<bundle>',description}]}`,按 name/source 去重,保留其他项。resolveAgentMarkdownFiles `[88525,88876)` 支持声明数组的目录或 `.md`,无声明时列 agents/*.md。具体 session switch 在同文件 SessionPluginSwitcher,通过 session host 插件端点启停,不能从返回 localPath 推断指令已注入。
|
||||
|
||||
ExpertDependencyRuntime `[67977,70095)`:
|
||||
|
||||
- `dependencies.connectors` 是非空字符串 ID 数组,产生 `{type:'connector',id}`。
|
||||
- MCP 声明优先 `dependencies.mcpServers`,再 `manifest.mcpServers`,无声明才用 `.mcp.json`。可为相对 JSON 文件、多个文件路径(后者覆盖同名)、或 object;JSON 同时接受 `{mcpServers:{...}}` 与直接服务器 map。
|
||||
- 输出 `{type:'mcp',name,displayName,description,icon,config,workbuddy}`;`x-workbuddy` 本地化包括 auth.tokenSchema 标题/说明/字段 label/placeholder。
|
||||
- `resolveExpertMcpLaunchConfig` `[67472,67614)` 仅处理 args:以 `./` 起始且 resolve 后仍在插件根内的参数转绝对路径,其他值保留。并非把任意 command/cwd 自动改写。
|
||||
- 相对图标在插件根内解析,特殊 local-file 协议元数据被去除;http/data/file 分支分别处理。这里没有真实连接/授权执行。
|
||||
|
||||
## 本地导入、打包
|
||||
|
||||
`main/tar.js` installExpertZipFromPath `[42138,44806)`:在临时目录解 ZIP,接受根 manifest 或唯一顶层目录的 manifest;manifest.name 优先确定最终 ID,规范化旧展示数组。最终 ID regex `^[a-zA-Z0-9._-]+$` 且排除 `.`/`..`,目标必须在 my-experts/plugins 内。重复未 overwrite 时返回 duplicate_expert,同时补 marketplace 索引;overwrite 会先删除旧目录再移动新目录,不能将其称为已证实原子回滚。成功 touch manifest、写 marketplace,finally 清理临时目录及按 cleanupZip 选择清 ZIP。
|
||||
|
||||
`main/module.app-server.js` BundleRuntime 的下载路径是另一实现:downloadAndExtract `[53066,55378)` 有旧目录备份恢复;extractZipArchive `[56027,56753)` 校验 zip-slip;normalizeExtractedPluginRoot `[56753,57120)` 允许单层包装。应区分市场下载和本地 import 的覆盖语义。
|
||||
|
||||
源 Python package_expert.py 先完整 validate,再 ZIP;entry 含 `<expert-dir-name>/` 前缀。除 `.codebuddy-plugin` 外隐藏文件/目录、node_modules、__pycache__ 和常见垃圾文件排除,session marker 不分享。daemon exportExpertZip `[39906,40498)` 使用独立 collectExpertPackageEntries/export,不能假称两个 exporter 完全同一实现。
|
||||
|
||||
## expert-manager 创建、编辑与校验
|
||||
|
||||
SKILL v2.0 的真实流程:收集角色信息/资料转化 → init → 填 Agent/manifest/可选 skills → 头像生成 → validate → register → package。修改保持 name、agentName、目录名和 Agent 文件名身份,修改后仍 validate/register。Team prompt 要求真实 TeamCreate/Agent/SendMessage,不允许模拟多角色;本轮未实现或运行该调度。
|
||||
|
||||
init_expert.py 只允许固定 config/my-experts/plugins 路径、kebab-case 名、agent/team;同名目录拒绝。Agent 模板创建 `.codebuddy-plugin/plugin.json`、agents/<name>.md、avatars/.gitkeep、README;Team 增加主理人/成员占位与 settings.json。模板 TODO 必须后续生成填充。batch_create.py 是流程范例,**明确没有内容生成逻辑**,不是可以一键生成成品的实现。
|
||||
|
||||
plugin-json-spec 与 full validator 存在严格程度差异,应分别保留:
|
||||
|
||||
| validator 核心 | 实际 error / warning |
|
||||
|---|---|
|
||||
| name/version/description | 检查 key 存在;name 非空时 regex至少2字符。version 未真正校验 semver。 |
|
||||
| expertType / agentName | 只 agent/team;agentName 必须对应 agents/<name>.md,禁止通用 team-lead。 |
|
||||
| i18n 展示 | displayName/profession/displayDescription/defaultInitPrompt 必须 object、en/zh 非空。 |
|
||||
| tags / quickPrompts | 若为数组要求各3个;原 validator 对错误的非数组类型并未全面报错,不应夸称完整 schema parser。 |
|
||||
| 中文描述/首次提示/头像/README | 40–50字、defaultInitPrompt与首条一致、头像存在、README推荐均 warning,不能当原版已做硬拦截。 |
|
||||
| team | teamInfo与members必需、memberAgents不含lead、members含role=lead;settings.json必需,存在agent时须匹配agentName。 |
|
||||
| 结构 | fullvalidate只认.codebuddy-plugin/plugin.json;不许hooks/commands/.lsp.json;agents/skills/bin/avatars不能放metadata里。声明agents存在,skills含SKILL.md。 |
|
||||
| Agent Markdown | 简单frontmatter regex/key:value抽取,源码承认不解析完整YAML;name若提供须同文件名,description缺失warning,tools字段error。 |
|
||||
| 固定位置 | 专家目录须在WORKBUDDY_CONFIG_DIR(fallback ~/.workbuddy)my-experts/plugins下。 |
|
||||
|
||||
register_expert.py 另有 completeness 检查:两种 metadata 都可;name/description/expertType、displayName 不能留 TODO,agents 目录至少一份文件的 TODO 数≤2。它不是直接调用 full validator;所以 fullvalidate 与 register 必须分别验收。session ID 优先 `--session-id`,否则 CODEBUDDY_SESSION_ID,空值/未展开变量忽略。marketplace 可显式指定或从目录推断,按 source/name 更新,写 `.created-by-session`,无 session 时注册成功也提示未必自动进入当前用户列表。
|
||||
|
||||
Avatar 规范要求真实 ImageGen 及文件落盘,生成失败要说明需手补并提供 prompt。本轮没有头像生成服务,不能沿用原文收尾语伪称头像已生成。Root host adapter 将明确表达此限制。
|
||||
|
||||
## REA 扩展与验证
|
||||
|
||||
正式本地 `SelectedArtifactText` adapter 增加 `.md/.txt/.yaml/.yml/.py`,仍只接精确 canonical member、固定根 SHA、strict UTF-8、每文件8MiB/合计16MiB/最多16项、校验 declared size/SHA;Python仅作为文本,不执行。`prepare-css-runtime.mjs` 将正式 patch装入隔离 runtime;全局 REA/registration 不变,没有旁路 extractor。
|
||||
|
||||
验证命令:
|
||||
|
||||
- `node scripts/rea/expert-package-text-regression.mjs`:自有真实 ASAR public CLI **9/9 PASS**,`.tmp/rea-expert-package-fixture-SNFddk/report.json`,Evidence `ev_bd82287b057029647c8c15910ee079b59bd2616158a7deb2d2b97c3d92468275`;5种新后缀 bytes/SHA、根pin、路径、UTF8、预算、缺member/重复及未选缺unpacked。未执行Python。
|
||||
- `node scripts/rea/selected-artifact-text-regression.mjs`:原有JS/CSS/JSON/binary、声明SHA tamper、预算、未选unpacked回归 PASS。
|
||||
- `node scripts/rea/css-runtime-contract-regression.mjs`、`node scripts/rea/css-runtime-integrity.mjs`:PASS,19模块校验、对应global文件未变。
|
||||
- expert-package-inventory/export/contracts/recover:所有选中正文 SHA、对应已存 inventory SHA 和恢复 bytes核验 PASS;原文bundle逐字等价,manifest提供完整复查链。
|
||||
|
||||
未知边界:原版实际创建/编辑/安装运行仍未执行;市场/安全扫描/付费/企业/cloud均有服务依赖;两种包导出器完整排除规则、第三方包兼容和原版所有异常未逐一执行;YCode的真实专家backend/会话模型指令/tool/team能力需另行测试。本轮不把“源码取到”称为功能1:1完成。
|
||||
|
||||
## 后续独立 YCode backend QA
|
||||
|
||||
Root 实施 `src/main/capabilities/experts.ts` 后,本 worker 新增 `scripts/test-experts-backend.mjs`,没有编辑该生产 service。该测试使用真实 Electron app.getPath(userData) 与真实磁盘包/草稿/marketplace,数据目录、sessionData、OMP home 都在新建 `.tmp/experts-backend-*` 下;不读写真实用户注册表、不调用模型或原版。
|
||||
|
||||
`node scripts/test-experts-backend.mjs` 最终 **73/73 PASS**:exercise **59/59**、全新 Electron reload-remove **14/14**,`.tmp/experts-backend-XllrUB/report.json`。被测 service SHA `6ba3fe0b9d489635b2f7c9846aabbe1f3f43206a9beaf150e8d497ca452a0dd3`,独立 esbuild module SHA `10ddff6ea9ef70f5a51c5928d8acc2eb9b4765b623fe170648a9f6f8e2a22806`。
|
||||
|
||||
真实链路覆盖 write→validate→register→source-shaped marketplace→list→read Agent prompt→activate identity→编辑/声明 skill preload→重启→remove。另验证二进制资源在文本编辑中保留、null 删除文档、marker、TODO 拦截、Windows/上级路径/会话ID越界、伪造 marker、单文件限额、YAML/tools拒绝、描述长度 warning、可校验 Team 包但明确拒绝激活、目录 junction/包内junction拒绝且外部目标未改,以及完整11份 manager源资源 SHA。
|
||||
|
||||
QA 曾捕获真实 stale edit bug:初次 read 不保存 baseHash,两个会话先 read 后编辑时旧用户视图可覆盖新包;`.tmp/experts-backend-QMunm2` 记录 FAIL,不能算通过。Root 修复 read 持久草稿与显式 `refresh:true` 后,最终同一反例拒绝陈旧 register;refresh 丢弃旧草稿、取得最新包后成功编辑并保留先前 Agent 变更。首次修复版 `.tmp/experts-backend-1WVd0H` 为55+14 PASS,最终新增 refresh闭环与source/build SHA后以XllrUB为准。
|
||||
|
||||
这是 YCode 后端模块的独立验证。没有驱动完整生产 preload/IPC/UI→真实 OMP 创建专家、图片生成、第三方 ZIP 导入、所有资源执行或专家团调度;这些跨模块/产品验收仍归 Root。REA 源恢复与自有 backend PASS 分开记账。
|
||||
@@ -0,0 +1,74 @@
|
||||
# 专家输入选择器恢复(2026-10-16)
|
||||
|
||||
本轮恢复原专家子菜单的实际组件体、搜索输入、选中/check/pin/召唤更多结构和 CSS,接入有类型的真实列表宿主。没有硬编码参考专家为可激活项目,不调用不存在的专家 API。主上下文负责专家 registry、会话激活、OMP 接线及主输入入口;本 worker 不改 ChatPane、ComposerControls、shared、main 或 App。
|
||||
|
||||
## 宿主接口
|
||||
|
||||
`src/renderer/src/capabilities/SourceExpertPicker.tsx` 默认导出泛型组件,导出 `ExpertPickerItem` 与 `SourceExpertPickerProps<T extends ExpertPickerItem>`:
|
||||
|
||||
```ts
|
||||
interface ExpertPickerItem {
|
||||
id: string
|
||||
name: string
|
||||
profession?: string
|
||||
avatarUrl?: string // 浏览器可用的 http(s)/blob/data:image URL
|
||||
description?: string
|
||||
disabled?: boolean
|
||||
searchText?: string // 若提供,按源契约为已经小写化的搜索缓存
|
||||
}
|
||||
interface SourceExpertPickerProps<T extends ExpertPickerItem> {
|
||||
items: readonly T[]
|
||||
selectedId?: string | null
|
||||
busy?: boolean
|
||||
error?: string
|
||||
onSelect(item: T): Promise<void>
|
||||
onManage(): void
|
||||
onClose(): void
|
||||
anchor: HTMLElement | null
|
||||
scopeKey: string
|
||||
}
|
||||
```
|
||||
|
||||
传给 `onSelect` 的是当前宿主 `items` 中实际对象,保留额外 registry 字段,不从显示文字反造专家。重复 ID 只展示首个。名称严格使用原 `profession || name || id`;原搜索用小写 keyword 匹配 `searchText` 或显示名称,不额外发明 description 搜索。根可通过 `expertText` 把多语言字段投影为字符串。
|
||||
|
||||
原版是“+菜单→专家行→右侧子菜单”。`anchor` 应优先传专家菜单行,源码定位契约为 `right-start`、offset4、flip `left-start/right/left`、shift padding8。当前独立宿主传 composer 按钮也可运行,但入口位置是否与原版一致由根另验。依赖使用宿主已安装的 `@floating-ui/react 0.27.20`,原版包精确版本未知。
|
||||
|
||||
## 固定原版证据
|
||||
|
||||
WorkBuddy **5.8.2**,ASAR SHA-256 `035254bc76310ea46317433e4840602094543ef323d2d5c5aff7c131729de918`。本轮仅读取已保存 REA 导出,不操作原版窗口,不直接读取原版文件系统或 CDP。
|
||||
|
||||
JS 来源:`.tmp/rea-runtime-scripts.json`,Evidence `ev_717fa5e846e64d67ac19c8925d121bff632c0d3aefb3603b10858559cabb2dcb`。CSS 来源:`.tmp/rea-css-recovered/manifest.json`,Evidence `ev_377c8790468b3c67dad8577aabb327f98d3140659f0fffdbabfcff5a40cc9e94`。
|
||||
|
||||
| 文件 | 固定 SHA-256 | 恢复范围 |
|
||||
| --- | --- | --- |
|
||||
| wb-input-add-B045GnIg.js | `7842fa4321d5351bf6c822bbd0253e0d6d6e68cc9cfae3f2470b3d493c23daf4` | ExpertsSubmenu `[47192,49898)`、ExpertRow `[49899,50767)`、ExpertAvatar、SummonMoreIcon、显示名称和搜索 helpers |
|
||||
| contexts-BMeWSUHk.js | `5f35b7489b107e21ef452c8ee88a95265756f6fc444841eef869228bbc44768b` | `wV` 原搜索 forwardRef `[4205837,4206556)`、`CheckIcon$2` `[4196249,4196837)`、`_V` base class map |
|
||||
| zh-cn-Dfzn8myY.js | `05bdf17cc76e1c2547e84a2754d249405366eb5559149b1661837c9687e6efab` | 10 个 `input.wbAdd.experts.*` 中文原文,含暂无可用专家/未找到专家/召唤更多专家 |
|
||||
| contexts-BkjwYSZT.css | `50cbd673f7f35fc7f966bdddc6c9f5677fdfe944cb904888d214619fca259380` | `_1mrhu_` 搜索/base 声明 |
|
||||
| wb-input-add-CDNucW11.css | `07566131dac43d1854af1ecb973bf9736a63723a0786ba0d2d5287ed6f45f2f6` | `_14qob_` 专家子菜单声明 |
|
||||
|
||||
恢复脚本 `scripts/rea/recover-expert-picker.mjs` 先按上述固定 SHA 验证,再 AST 定位组件体、class map、中文字段。输出 `expert-picker-source.mjs/.d.mts`、`expert-picker-classes.json`、`expert-picker-source.css` 和 `expert-picker-manifest.json`。manifest 记录 10 个原体的 UTF-16 offset/body SHA 和所有生成文件 SHA。复用已经恢复的 `SkillSourceIcons` 中 Pin/Unpin/Search/Clear 字面 SVG,不改技能组件或样式。
|
||||
|
||||
## 保留与适配
|
||||
|
||||
保留 ExpertsSubmenu 的输入可见值与已提交查询两个状态、composition ref、composition end 提交、pin 事件 stopPropagation、选中正常条目只关闭、查询模式独立 selected 状态、空/加载失败/搜索失败状态、源搜索 Escape 清空并阻止外层关闭、check 和召唤更多结构。CSS 声明保持原值,仅加 `.yc-expert-picker` scope;原 panel 为 **240px**,条目 **32px**,avatar **16px**,搜索 **32px**,滚动列表 max-height **338px**。
|
||||
|
||||
原 normal 列表是 pinned + recent + 服务推荐补位,source qa=5、Ja=10。本机适配为真实可用 pinned + 最多5个额外 recent/宿主顺序条目,超过10行使用原 scrollList;搜索遍历全部真实 host items。没有云目录请求或填造推荐结果。原搜索 hook 的150ms timer仅用于网络 preload;本机已完整加载 registry,所以搜索过滤仍按源立即完成,不添加无意义网络延迟。
|
||||
|
||||
pin/recent 使用 `ycode.experts.menu.v1:<scopeKey>`。根须把实际账户/空间/会话边界编码入不透明 scopeKey;不自行推测账户。未知/移除 ID 不产生可激活的 unresolved 假行。读取 memory 验证数组和字符串,localStorage 不可用不会阻断激活。
|
||||
|
||||
原正常条目的 onSelect 为同步后立即 close,搜索召唤可异步。本机真实 activation 是 Promise,因此只在成功后关闭;同步 ref 阻止双击、busy 和 disabled 条目,失败显示明确宿主错误并保留重试。scope 或组件销毁后,旧 Promise 不写新 scope memory、不关闭新选择器。宿主本身仍负责激活事务/取消和实际会话所有权;组件无法撤销已经发给宿主的任务。
|
||||
|
||||
原 ExpertsSubmenu/父 WbInputAddMenu 没有 Arrow 上下行遍历;父浮层处理 Escape,搜索自己处理非空 Escape。本机直接宿主补 tabindex、禁用行跳过、上下/Home/End、Enter/Space、打开聚焦搜索及关闭返回 anchor,明确列为 host adaptation。`ExpertRow.disabled` 增加 item.disabled;source body 此外只替换运行时绑定。源子菜单 CSS 自身没有动画;父“+”菜单有 `.18s` pop-in。本轮不把父动画误加为子菜单独立动效,不声称整个输入菜单动效已等价。
|
||||
|
||||
Avatar 底层是浏览器安全 URL/首字母 fallback,Tooltip 为原生 title;两者不是原版通用 primitive 的完整恢复。暗色、云推荐、完整+菜单入口、头像 fallback paint、tooltip 动画/延迟、触屏边界与极小视口仍需继续 REA 对标。
|
||||
|
||||
## 验证与交付
|
||||
|
||||
- `node scripts/rea/recover-expert-picker.mjs`:恢复;`--check`:固定 **5 个源 SHA、10 个原体、10 个中文 label、5 个输出** 检查通过。
|
||||
- `node scripts/rea/test-expert-picker-native.mjs`:**39/39 PASS**,`.tmp/expert-picker-native-iFW4nG/report.json`;1052×901普通可见 Electron + SwiftShader,真实组件和受控 typed host,不用 fake IPC,也不访问原版。
|
||||
- `npm run typecheck`:node/web 全通过;根负责生产 build 和实际 registry/OMP 集成。
|
||||
|
||||
原生局部尺寸:anchor `[400,600,100,32]` 时 panel `[504,600,240,273]`,row32、avatar16、search `[224,32]`;全池12项查询滚动高度338;右边缘 anchor x900 时翻转 panel x656、width240。验证还覆盖 selected 不重复激活、disabled、大小写/IME/两段 Escape、scope pin/recent、typed item 附加字段、延迟成功关闭、防重复、失败保留、旧 scope Promise 隔离、busy、召唤更多与空/错误原文。
|
||||
|
||||
这些几何断言根据固定源 CSS/源码计算并验证宿主生效,**本轮没有原版同状态 runtime 截图或像素比较**,不宣称整个专家菜单或全状态 1:1 完成。原生截图和失败状态截图在上述报告目录,原版源码体与生成 SHA 在 manifest。
|
||||
@@ -0,0 +1,78 @@
|
||||
# 自定义 MCP 后端与连接器页面实施(2026-10-16)
|
||||
|
||||
本轮已实现 YCode 自有 stdio/Streamable HTTP MCP host、凭据加密、配置批准、服务/逐工具启停、连接释放、稳定工具快照以及可用的连接器/MCP 管理界面。受控真实 SDK、独立 Electron 重启和实际 App UI 验证通过。**没有实现 WorkBuddy 云目录、账号 OAuth、内置 QQ 邮箱等业务服务,也没有完成连接器全状态像素 1:1 验收。**
|
||||
|
||||
## 修改文件与边界
|
||||
|
||||
- `src/main/capabilities/mcp.ts`:自有 host/registry、凭据和运行连接/工具快照。
|
||||
- `src/renderer/src/capabilities/ConnectorsPage.tsx`:连接器内容页与 toolbar portal、详情、MCP 管理、单服务 JSON/Monaco 编辑、批准/开关/工具/删除/重连。
|
||||
- `connectors-source.css`:固定 REA 源规则正文,增加页面作用域;`connectors-adapters.css`:YCode 宿主/错误/可用性/编辑适配。
|
||||
- `ConnectorSourceIcons.tsx`:隔离的原 SVG/静态图标正文;`connectors-helpers.ts`:单服务 JSON 解析、凭据 metadata 占位与原图标颜色规则。
|
||||
- `package.json`、`package-lock.json`:增加 `@modelcontextprotocol/sdk@1.32.1`、`yaml@2.9.1`、`fflate@0.8.3`,后两项由技能实施共享使用。普通 npm install 遇既有 electron-vite 5/Vite 8 peer 范围冲突,采用 `--legacy-peer-deps`,没有降级现有版本;全项目 typecheck/统一 build 另验。
|
||||
- `scripts/test-mcp-server.mjs`、`test-mcp-backend.mjs`、`test-mcp-helpers.mjs`、`test-mcp-source-ui.mjs`、`test-mcp-native-ui.mjs`;本报告。
|
||||
|
||||
Worker 未编辑 shared capabilities/IPC/preload/App/chat runtime。Root 负责注册上述后端函数、startup initialize、能力中心统一顶栏、会话工具快照/审批/真实内核接线。Root 随后在 snapshot 上补了 `describe(name) → {serverName,toolName}`,将 identity 放入 tool metadata,审批与已有 REA `mcp_call_tool` 专用视图使用可读 server/tool 名;稳定 namespace 和 generation 检查保留。该跨模块集成为 Root 工作,不能算 worker 独立 fixture 已覆盖。
|
||||
|
||||
## SDK 与原版依据
|
||||
|
||||
实施前查询了官方 [TypeScript SDK v1 Client](https://ts.sdk.modelcontextprotocol.io/client)、[Server](https://ts.sdk.modelcontextprotocol.io/server) 和 [v1 protocol source](https://github.com/modelcontextprotocol/typescript-sdk/blob/v1.x/src/shared/protocol.ts)。本轮使用已安装 1.32.1 的 Client、StdioClientTransport、StreamableHTTPClientTransport 与 request signal;没有以手写假 MCP 协议替代 SDK。
|
||||
|
||||
所有原版观察来自 WorkBuddy **5.8.2** 的 REA 归档,不直接读取原版安装路径或 CDP/evaluate。完整源码锚点见 `assessment-connectors-2026-10-16.md`。主要证据:
|
||||
|
||||
- JS:`ev_717fa5e846e64d67ac19c8925d121bff632c0d3aefb3603b10858559cabb2dcb`,`skills-panel-CvMlV3m8.js` SHA `b30c43c11ec476db639d6be58065d927411845487d34b0ea8e839d1c6eb7a238`。McpConfigEditor UTF-16 offset 20816,McpPanel 27216,ConnectorPanel 62950。
|
||||
- CSS:`ev_377c8790468b3c67dad8577aabb327f98d3140659f0fffdbabfcff5a40cc9e94`,`skills-panel-CsnIUki4.css` SHA `c1d5c5de51554a886fde0399c5202cd45063fa091b213b842014bea91dbb69a0`;源规则正文保留,selector 作用域为 `.ycode-connectors`。共享 button/input/CB search 原规则来自 4 份已校验样式,记录在 `.tmp/mcp-source-ui/recovery.json`。
|
||||
- 商店静态:`ev_e91bdc6e46275f4460985cfff25fd7f7bc334afc45f49fac1935de1249f4cb22`,`.tmp/rea-market-connectors-static-20261016`;原 pencil SVG 为 node 821。
|
||||
- 稳定 MCP 管理:`ev_b89281177f6a1cf2e4697887d576b8ddf7d811a8fa2d1148b7024a4ec898906f`,`.tmp/rea-custom-connectors-static-20261016`;用于 modal 几何、add/Hub/close/search/clear SVG 和样式依据。最初半透明过渡帧未用作稳定基线。
|
||||
- QQ 邮箱详情:`ev_b898a87832d1e800810d391145a6ec6c6999e98b5cea6c7f382a3fc19aa7b3ac`,操作 steps 完成、cleanup failed,整 probe 为 partial;没有授权/连接。这里只提供详情结构参照。
|
||||
|
||||
恢复脚本只解析固定工作区 REA export 的 CSS/AST/SVG,不执行原版全局初始化。源样式包含 640×700 最大尺寸、list/search/tools/trust/error/warning/toggle/modal 动效;这不等于所有原版交互已逐一实测。
|
||||
|
||||
## 后端行为
|
||||
|
||||
Registry 为隔离 app userData 下 `mcp-servers.json`,串行更新、临时文件 rename 持久化;同名服务拒绝覆盖、输入字段校验。服务 env/headers 合并规则是:未提供 map 保留,显式 map 的已有空值保留,省去某 key 可移除;环境变量和 Headers 只经 Electron safeStorage 密文保存,无法安全加密时拒绝写入,**不采用明文 fallback**。IPC view 只返回 key 名,不返回值;错误字符串不透传上游 URL/凭据,stdio stderr 丢弃,工具结果/metadata 中的已知配置凭据回显会屏蔽。
|
||||
|
||||
configHash 覆盖实际配置与凭据。新配置未批准;变更 command/args/cwd/name/url/env/headers 会清除 trust 和已发现工具并关闭旧连接。读取外部手改的 registry 时重新规范化与计算 hash,不能保留旧 hash 假装批准;未知字段不会进 IPC view。批准携带 hash,陈旧批准被拒绝。没有实现原版企业策略或 OAuth 授权。
|
||||
|
||||
stdio 用 SDK 启动 command/args/cwd,只继承 SDK 默认环境与明确配置 env,不把主进程所有变量灌给服务;Streamable HTTP 保留完整 MCP endpoint,固定配置 origin 并禁止重定向携带凭据。`listTools` 读取所有页、去重工具/重复 cursor 拒绝,最多 10,000 工具;握手和单页请求超时 20s、tool call 超时 120s。连接状态来自真实生命周期,disconnect/disable/remove/config 变更会关闭 SDK client,HTTP 会 best-effort terminateSession。
|
||||
|
||||
服务与工具 enabled 持久化;开启服务先要求当前配置已批准。`initializeMcpServers()` 在 startup 后台重连已启用且批准的服务;`snapshotMcpTools()` **只取当前 connected 连接,不等待不可用 MCP 握手**,普通发送不会因为坏服务停在不可取消的 preflight。
|
||||
|
||||
每个 supplier tool name 为 `mcp_<截断清理工具名>_<serverID+toolName hash>`,长度不超过 64、无跨服务碰撞,重连不改 namespace。快照捕获具体 client/generation/configHash;execute 再验证同连接、同配置、当前 trust/enabled/tool enabled。配置/连接变化使旧调用失败,不自动把旧回合映射到新服务/新密钥。
|
||||
|
||||
取消保持区别:**外部 turn signal abort 才抛 AbortError**;运行中 disable/remove/config 关闭 runtime 返回 `ok:false` 配置/连接变化错误。两条路径都有受控实际服务验证。普通 tool isError/上游异常也按 tool failure 返回。
|
||||
|
||||
## 界面行为与已知差异
|
||||
|
||||
统一三 tab 属于 Root CapabilityCenter,页面搜索/管理按钮 portal 到其 toolbar;MCP/detail portal 到 `.yc-capability-center .expert-center-page`,继承 scoped light/dark tokens,避免 body portal 丢颜色/尺寸。
|
||||
|
||||
没有 WorkBuddy 目录服务时显示实际可用性状态与自有 MCP 卡片,不画出已成功连接的 QQ 等内置业务。MCP 列表使用真实 host 返回值,支持搜索、状态点、展开工具、逐工具开关、信任审批、超 80 工具提示、重连、复制安全错误、删除确认;Hub 链接使用归档 source 公共 fallback URL。没有伪造插件 readonly 来源、OAuth 已授权或安装成功。
|
||||
|
||||
单服务编辑仍使用原 `mcpServers` JSON 形状,实际复用已恢复 Monaco source wrapper 的 editable/onChange;已有 env/header 仅 key+空值占位,保留契约明确。保存仅更新这一个服务,不隐式删除其他配置。与原版全配置路径/批量原子保存仍有差异,这是当前 McpApi 范围,Root 已确认先稳定单服务编辑。
|
||||
|
||||
Monaco 的 `webContents.insertText` 属于 typing/IME 路径,可能自动括号/缩进;不能当真实 paste 验收。本轮自身 QA 用 native focus/Ctrl+A 后受控 ClipboardEvent+DataTransfer 走真实 Monaco paste handler,未直接改 model/store、未触系统 clipboard;没有关闭自动补全来迁就测试。加载编辑器失败才使用 textarea fallback。
|
||||
|
||||
## 验证结果
|
||||
|
||||
| 命令 / 证据 | 实际范围与结果 |
|
||||
|---|---|
|
||||
| `npm run typecheck` | node/web 均退出 0 |
|
||||
| `node scripts/test-mcp-source-ui.mjs` | 源 SHA 复验、10 个隔离函数 SVG 与 6 个 DOM SVG、4 份 primitive sheet 恢复;PASS |
|
||||
| `node scripts/test-mcp-helpers.mjs` | 12/12 PASS,`.tmp/mcp-helpers-NuJUou/report.json`;单服务/rename/凭据占位/JSON/type/args/headers/multi-server/empty 防误删 |
|
||||
| `node scripts/test-mcp-backend.mjs` | `.tmp/mcp-backend-7PNwXc`:exercise **36/36**、全新 Electron reload **7/7**、外部配置 tamper **2/2** PASS |
|
||||
| `node scripts/test-mcp-native-ui.mjs` | `.tmp/mcp-native-ui-PWWVz4/report.json` **13/13 PASS**;真实 App/preload/IPC、主题 portal、源几何、Monaco 粘贴保存,无模型/上游请求 |
|
||||
| Root `.tmp/capability-flows-ZJYiyj/report.json` | main **13/13** + restart **6/6** PASS;真实 App UI → OMP → 受控 supplier → MCP +技能,属于 Root 跨模块集成验证 |
|
||||
| Root `.tmp/capability-gateway-QNP0Ek/report.json` | **16/16 PASS**;Root 后续补可读 MCP identity/tool view 后的真实 Gateway 验收 |
|
||||
|
||||
Backend 受控服务均使用真实官方 SDK:stdio 为真实子进程、HTTP 为 loopback stateful StreamableHTTP,真实两页 list、callTool、鉴权存在/匹配、SDK cancellation notification 到达服务、HTTP DELETE session 释放。运行中 wait 时 disable/remove 返回 tool failure;外部 turn signal 取消在两个 transport 中均为 AbortError。服务关闭/重连/变更后旧快照不能再次调用,新快照使用新 generation。重启检验 tools/disabled/approval/secret metadata,外部改 args 保留旧 hash 也会失信。
|
||||
|
||||
Native UI 稳定 modal bounds 为 **[348,115.5,640,700]**,与 V4 modal 几何一致;light background `rgb(255,255,255)`、dark `rgb(31,31,31)`,原 secondary button foreground `rgba(0,0,0,0.9)`,两主题按钮高 **32px**。报告没有宣称所有 computed properties 相等;modal 容器继承 text color 当前 light rgb(0,0,0),原归档部分祖先为 rgb(59,59,59),仍应按实际叶节点/同内容继续比对。截图/报告保留在目录,原版 dark 动态像素没有对应新证据。
|
||||
|
||||
Native UI 报告 build SHA `53b6eb3d586aa0bca613507761a5943fd67953ad113e82cbe73ea27bb0210774` 是当前 UI 的已测构建;最后 runtime failure-vs-cancel 语义修正经独立后端回归,Root 将统一最终 build/OMP/restart 复验,不把旧 build hash 当作新构建已经验收。脚本父进程检查实际 report 存在、非空 checks 与 PASS,不能仅凭 Electron exit 0。
|
||||
|
||||
早期 `.tmp/mcp-backend-4VPd0j` 的 CLI argv 错把 switch 当 phase,只有错误命名的 exercise 报告,不能用于重启结论;已修 phase 取最后参数和强制每阶段报告,最终以 7PNwXc 三阶段为准。Native UI 首次测到 transform 入场中的缩小尺寸,改为等待实际 animation.finished 后测稳定原几何,没有改生产动效。
|
||||
|
||||
## 剩余边界
|
||||
|
||||
尚未实现:WorkBuddy 官方/企业动态目录、内置业务连接器、OAuth/device-code/QR 授权、Token schema 特殊表单、包分发/自动安装、旧 HTTP+SSE、MCP prompts/resources/resourceTemplates 与 MCP Apps/Widgets 运行时。当前 JSON 编辑不是原版全文件原子 bulk;现有接口不含 plugin readonly/enterprise policy/source metadata。健康状态为连接生命周期/操作结果,未实现原版所有自动修复/授权刷新策略。
|
||||
|
||||
受控 MCP 成功不代表任意第三方 server 可用、真实账号授权成功或原版 daemon 等价。完整目录/详情/错误/信任/所有工具/窄宽/暗色/hover/动效/字体的同内容像素验收仍未完成。Root 后续可读 identity 专用视图也需继续做 source 实测,不能以函数/编译/通路通过代替全量 1:1。
|
||||
@@ -0,0 +1,84 @@
|
||||
# 自定义模型 Select 恢复评估(2026-10-16)
|
||||
|
||||
可以恢复为原组件结构与状态行为,当前阻碍不是拿不到源码。本次只做原版REA取证和只读评估,没有修改ModelSettingsPanel/Select生产代码。
|
||||
|
||||
## 固定来源
|
||||
|
||||
- WorkBuddy5.8.2、ASAR SHA `035254bc76310ea46317433e4840602094543ef323d2d5c5aff7c131729de918`。
|
||||
- ModelsSettingsPanel JS/CSS:REA `ev_25f013c9fd2ad66153046eec06e94fb6128bfacc1e87e57aa90db6bc419075ec`,`.tmp/rea-assessment-model-source.json`。JS SHA `739ab43ee521d8ef6e5b5b7731bb4e71b51454b2865f44a1228d7fcc2700149c`,CSS SHA `cd80b01d04589227a3c2db5dbe67b6c83b019bef18d3dba68ae5486448651018`。
|
||||
- 共享Select/Popover/SVG:REA `ev_717fa5e846e64d67ac19c8925d121bff632c0d3aefb3603b10858559cabb2dcb`,`.tmp/rea-runtime-scripts.json` 的 `src-DPDj7_qD.js`,SHA `747e41d215375e1214c366213aea7e077d85421923029c61cbb6e9562be58de0`。
|
||||
- 共享CSS:REA `ev_377c8790468b3c67dad8577aabb327f98d3140659f0fffdbabfcff5a40cc9e94`,`src-Bh3YZ35H.css`,SHA `88dbdc1cd3f59d0e8b75824512a465a2be714bc7af481d790fe3a9484f85e01a`。
|
||||
- 当前原provider dropdown:REA `ev_7f4bada062e5643e7866e0dbe8a35f2ab5903421c94b5084ab710dbe77b3ab19`,`.tmp/rea-model-select-provider-static-20261016/`。
|
||||
- 当前原model dropdown:REA `ev_a6b221d6a364c9f2db118a9dde18b9a3bc4a7c051663a6a0ccafb99c33c76237`,`.tmp/rea-model-select-model-static-20261016/`。
|
||||
|
||||
原版本次仅从首页模型菜单进入设置、打开provider/model dropdown,随后取消未保存编辑并关闭设置窗,没有保存/连接测试/发送消息。原设置窗900×680。关闭设置窗导致REA最终capture返回`protocol_error`;随后REA discovery仅剩main target,证明设置窗已关闭。main仍在首页。关闭过程诊断保存在 `.tmp/model-select-audit/settings-close-result.json`。
|
||||
|
||||
首次进入设置后编辑器已经自动打开;第一次probe试图点击背后的add按钮被REA遮挡校验拒绝,没有产生修改。有效provider证据来自随后只点已打开编辑器的provider按钮。
|
||||
|
||||
## 与当前adapter的具体差异
|
||||
|
||||
当前适配器位于 `ModelSettingsPanel.tsx` 的local `Choice`/`Select` 段,样式为 `model-settings.css` 中 `model-ui-*`。字段CRUD和密钥生命周期不是本评估替换范围。
|
||||
|
||||
| 项目 | 原版实现 | 当前adapter差异 |
|
||||
| --- | --- | --- |
|
||||
| Trigger DOM | `wb-select--medium/--full-width/--open/--empty/--disabled/--invalid`,value/placeholder区分,caret/loading/clear专用class | 只有`wb-select`、value和下箭头,缺状态class及原caret class/旋转;placeholder也复用provider提示 |
|
||||
| provider数据 | options为嵌套group对象;label为含原vendor图标的ReactNode;searchText为中文+英文displayName | Choice仅label/value/group字符串;没有provider图标/双语searchText,分组只按相邻字符串插标题 |
|
||||
| 搜索结构 | `wb-select__search > wb-input-wrapper--small --filled`,14px搜索SVG、allowClear、原input/prefix/suffix结构 | 独立带边框`model-ui-search`,缺搜索图标与清除按钮;provider也使用模型专用placeholder,原provider为“搜索” |
|
||||
| 分组DOM | `li.wb-select__group[role=presentation] > group-label + ul.group-list[role=group]` | div包裹group标题和button,原group CSS无法完整命中 |
|
||||
| Option DOM | `li.wb-select__option[role=option][tabIndex]`,OptionLabel,选中加两个状态class,原绿色check class/SVG | button节点,缺`__option-label`与完整selected class;generic check没有`__option-check`。自建`font:inherit`还覆盖源选中weight600 |
|
||||
| model输入语义 | 候选存在时用普通WBSelect;已有非候选modelId注入Qe首项;无候选时用文本Input | `editable`让query无匹配时新增可选项并Enter选用。原WBSelect没有allowCreate分支,不能将`selectOrInput`名称直接解释成下拉搜索可创建 |
|
||||
| Search条件 | provider数>6;model原候选数Z>6 | 当前`searchable || editable`会让<=6模型的下拉也出现搜索;应按调用条件恢复 |
|
||||
| 定位 | 原Popover offset8,inline absolute;Floating UI offset/flip/shift/size/autoUpdate,按clipping ancestors与8px padding约束 | body fixed portal,offset4,只在打开时读rect;只按window剩余高度,缺ancestor裁剪、flip、自动更新 |
|
||||
| 展开/退出 | expand preset、原placement class、150ms退出保留,初次activation next tick防误选 | 直接mount/unmount,缺expand DOM状态/退出、activation guard |
|
||||
| 键盘/焦点 | 搜索时manageFocus和initialFocus;option原Enter/Space;触发器由原Popover绑定 | 当前自建上下箭头active/clamp与Enter选中;不能未经证据宣称与原焦点/键盘等价 |
|
||||
| 溢出与tooltip | 字符串option用ResizeObserver检测ellipsis后显示原Tooltip | 没有检测/tooltip;当前文字/图标布局也不相同 |
|
||||
|
||||
源代码的模型创建/保存/上游测试可以继续使用YCode现有真实宿主;无需调用WorkBuddy服务端模型。
|
||||
|
||||
## 原版当前几何
|
||||
|
||||
| 元素 | provider dropdown | model dropdown |
|
||||
| --- | --- | --- |
|
||||
| trigger | `[154,136,592,32]` | `[154,304,592,32]` |
|
||||
| popover | `[154,176,592,306]` | `[154,344,592,216]` |
|
||||
| panel | `[163,177,574,304]` | `[163,345,574,214]` |
|
||||
| search区 | `[163,177,574,48]` | `[163,345,574,48]` |
|
||||
| filled search input wrapper | `[163,185,574,32]` | `[163,353,574,32]` |
|
||||
| list | `[163,225,580,256]` | `[163,393,580,166]` |
|
||||
| option | 高32、相邻y步进34、radius8 | 高32、相邻y步进34、radius8 |
|
||||
|
||||
原editor-body `[130,104,640,464]`,底边568;model popover底边560,正好留下原8px clipping padding。当前只看window高度的portal会进入footer区域。Provider selected项背景rgb247、check16px绿色;原provider option同时渲染16px vendor图标。上述是同一900×680原状态,不混入YCode较早截图的测量。
|
||||
|
||||
## 恢复边界建议
|
||||
|
||||
建议一个独立、有界的实现任务:
|
||||
|
||||
1. 新增 `SourceSelect.tsx`、`source-select-recovered.css`、`source-select.css`、`SourceSelectIcons.tsx` 和恢复脚本。承接ReactNode label、searchText、OptionGroup、source条件class、搜索Input、选中check、empty/disabled、源键盘/焦点行为。共用在provider/model/effort三个callsite。
|
||||
2. 恢复私有 `SourceSelectPopover`(可单文件内)与其定位/焦点/activation/exit依赖,保留原inline策略和clipping。原PopoverLayer使用Floating UI;当前仓库没有`@floating-ui/react`。依赖选择、版本与新增package范围由主上下文决定;不要直接执行完整原共享bundle的初始化。应恢复有限纯组件/辅助函数,并用原900×680截图验收。
|
||||
3. 新增 `SourceProviderIcon.tsx`、必要真实vendor资源;将provider label/render与列表row icon映射恢复。当前catalog已带icon字段,无需主进程/存储修改。原Tencent/OpenRouter/Ollama三张PNG已是REA脚本内data URI,可从固定导出解码,无须新取原安装包;其余是可提取的纯SVG。
|
||||
4. 只接 `ModelSettingsPanel.tsx` 的imports、local Choice/Select段、三个Select调用与provider label/row icon;`model-settings.css`只移除对应`model-ui-select/search/options/group/active`覆盖。不改CRUD、测试、密钥、保存策略、main/preload/store。主上下文正在新增的`createRequest`路由hook与begin后effect保持不动。
|
||||
|
||||
共享源码可直接恢复的范围已经固定:
|
||||
|
||||
| 定义 | offset | 源长度 |
|
||||
| --- | ---: | ---: |
|
||||
| isOptionGroup / flattenOptions / defaultFilter | 836748 / 836806 / 836915 | 58 / 109 / 214 |
|
||||
| OptionLabel / OptionStringLabel | 837129 / 837295 | 166 / 459 |
|
||||
| Select | 837754 | 5860 |
|
||||
| usePopoverActivation | 759107 | 1589 |
|
||||
| PopoverLayer | 761887 | 4211 |
|
||||
| useExitTransition / Popover | 766474 / 766808 | 334 / 1027 |
|
||||
|
||||
原CSS可恢复Select69条、Popover24条、Input107条,另模型CSS的Select2条/provider3条,必须保留media父条件与token闭包;无需凭截图另写一套尺寸。
|
||||
|
||||
原vendor内嵌PNG:Tencent `Kkt` offset4016979、1190B、SHA `5fd576ec40a7682780b2ef3b83f51cf2de41b960cc351c9a40edf951c8a797dd`;OpenRouter `Wkt` offset4014335、1945B、SHA `f66f19c8b7c99bb9f37c0239b6575cd01803112050161c0ba5275928f2db0194`;Ollama `Hkt` offset4011891、1797B、SHA `8f38edfb007d7b74f03d2ad7a57c023daa678031795ad11836df593970764a0b`,均来自固定contexts脚本。
|
||||
|
||||
## 数据与仍需证据的状态
|
||||
|
||||
本次原runtime provider16项/4组、默认Tencent Token Plan model15项;当前静态catalog domestic13项/4组、该provider模型8项。它是数据差异。原 `useLocalCustomModelSettingsConfig` offset4066587通过adapter.getProductConfiguration获取customModelSettingsUrl,允许显式local override/fallback URL,再fetchWithCache载入配置。当前静态catalog不是这个实时配置的完整快照;不能填造ID或假造WorkBuddy云端模型服务。可保留YCode自己的静态provider库并明确数据来源,同时让组件按源客户端规则分组/过滤/展示。
|
||||
|
||||
入口另有已证实差异:原 `useCustomModelEntry` offset4115869,在footerAction=`openSettingsAndCreate`时调用 `openSettings('models','new')`。原首页“配置自定义模型”直接打开添加overlay;当前旧入口只打开设置列表。已交主上下文修正路由,不由Select子任务覆盖。
|
||||
|
||||
尚需原版状态证据:搜索输入/清空/no-result、<=6模型无搜索、当前非候选modelId、切换provider、popover flip/滚动/窄窗、暗色和退出动效。当前REA probe schema没有任意文本输入action,故未对原输入查询;搜索过滤规则已有源码,任意文字行为实测需先由REA补明确输入能力,不能直接CDP输入替代。未保存/测试/发消息是本次取证范围,不构成自定义模型后续功能缩减。
|
||||
|
||||
可复现评估:`node scripts/audit-model-select-reference.mjs`。结果 `.tmp/model-select-audit/report.json`、shared-select-readable.js、models-provider-readable.js、own-select-readable.tsx与有限CSS正文,源SHA校验通过。原生provider/model截图与全部layout保留;当前阶段未进行新Select实现、YCode dropdown像素对比或完整1:1通过声明。
|
||||
@@ -0,0 +1,126 @@
|
||||
# OMP 与 Pi(pi agent)对比调研
|
||||
|
||||
- 日期:2026-10-17
|
||||
- 范围:公开仓库与官方文档调研(非 WorkBuddy 实现观察,不涉及 REA 渠道)
|
||||
- 结论先行:**两者是同一血统的两条路线**——`pi agent`(Pi)是 Mario Zechner 的极简可扩展 agent 工具链/上游项目;`omp`(oh-my-pi)是它的 fork,由 Stencil Labs 改造成"电池全包"的终端编码 agent。YCode 当前内核用的 omp.exe 就是这个 fork。
|
||||
|
||||
---
|
||||
|
||||
## 1. 身份与亲缘关系
|
||||
|
||||
| 项 | omp | pi(pi agent) |
|
||||
|---|---|---|
|
||||
| 全称 | oh-my-pi | Pi(pi-mono 项目,CLI 名 `pi`) |
|
||||
| 官网 | omp.sh | pi.dev |
|
||||
| 仓库 | github.com/can1357/oh-my-pi | github.com/earendil-works/pi(原 badlogic/pi-mono) |
|
||||
| 作者/维护 | Can Bölük(can1357)· Stencil Labs | Mario Zechner(badlogic,libGDX 作者)· Earendil Works |
|
||||
| npm 包 | `@oh-my-pi/pi-coding-agent` | `@earendil-works/pi-coding-agent` |
|
||||
| 当前版本 | **18.11.2**(2026-10-16 提交) | **1.3.0**(2026-10-15 发布,全仓 lockstep 版本) |
|
||||
| 本机在用 | `C:\Users\Administrator\AppData\Local\Ygent\omp.exe`,**18.6.3**(YCode 现内核) | 未安装 |
|
||||
|
||||
**命名澄清(容易混淆的点)**:omp 是 fork,所以它的包名、Rust crate 名都保留 "pi" 前缀(`@oh-my-pi/pi-coding-agent`、`pi-shell`、`pi-natives`、`pi-tui` 等)。"pi agent" 指上游 Pi 本身,不是 omp 内部某个组件。
|
||||
|
||||
---
|
||||
|
||||
## 2. 一句话差异(定位)
|
||||
|
||||
- **Pi**:*"a minimal, extensible agent harness that you can make your own"*——刻意做小,自带 4 个工具、约 300 词 system prompt;子代理、计划模式等"重功能"故意不做,靠 TypeScript 扩展/技能/包让使用者自己加。它是**平台**:`pi-ai`、`pi-agent-core`、`pi-coding-agent`、`pi-tui` 每层可独立引入(OpenClaw 就是直接 import SDK 而非跑子进程)。
|
||||
- **omp**:*"The Pi you love, with batteries included"*——把 Pi 故意留白的部分**全部内置**:31 个工具、LSP/DAP、子代理、计划模式、审批、记忆、协作、浏览器/桌面控制,外加约 8 万行 Rust 原生核心。它是**产品**:装上直接干活,而不是给你一堆积木。
|
||||
|
||||
---
|
||||
|
||||
## 3. 对比总表
|
||||
|
||||
| 维度 | omp(oh-my-pi) | pi(pi agent) |
|
||||
|---|---|---|
|
||||
| 定位 | 电池全包的终端编码 agent(fork 产品化) | 极简可扩展 harness / 分层工具链(上游) |
|
||||
| 技术栈 | TypeScript + ~80k 行 Rust 原生核心(N-API,随二进制内嵌 shell/ripgrep/glob/tokenizer);单个 Bun 打包二进制 | 纯 TypeScript(Node ≥ 22.19);工具进程外调用 |
|
||||
| 内置工具 | **31 个**:read/write/edit/ast_edit/grep/glob/bash/eval/lsp/debug/task/browser/computer/web_search/memory 等;14 个 LSP 操作、28 个 DAP 操作 | **4 个**:read / write / edit / bash(另有 find/grep/ls 工厂可显式启用) |
|
||||
| System prompt | 大而全(自带能力全覆盖) | 极简(约 300 词) |
|
||||
| 子代理 | 一等公民:`task` 分发到隔离 worktree,类型化结果,Agent Hub | **无**(官方建议自己用扩展/tmux 实现) |
|
||||
| 计划模式 | 内置 `/plan` | **无**(官方建议把计划写成文件) |
|
||||
| MCP | 内置(`/docs/mcp`,含 `mcp://` 读取方案) | 1.x 起已内置:`mcp.json`、`pi mcp add/list`、exposure 四档(codemode/deferred/direct/hidden)、OAuth;**"无 MCP"的说法已过时** |
|
||||
| 权限/审批 | 内置 approvals 体系 + `ask` 结构化提问 + ACP `session/request_permission` 门控 | **无内置权限系统**(默认 YOLO,按进程权限运行);官方建议容器化(Gondolin/Docker/OpenShell) |
|
||||
| 会话 | JSONL 树(resume/branch/fork/compact/steer/share),`~/.omp/agent` | JSONL 树(entry 带 id/parentId,`/tree` 导航),`~/.pi/agent` |
|
||||
| 上下文压缩 | 自动/手动压缩 + snapcompact(上下文渲染成像素字体 PNG,无需模型调用) | 自动/手动 compaction(`/compact`),历史保留在 JSONL |
|
||||
| 嵌入方式 | TUI / one-shot / **SDK** / **RPC** / **rpc-ui** / **ACP**(编辑器如 Zed) | TUI / print / JSON 事件流 / **RPC** / **SDK** |
|
||||
| RPC 协议 | NDJSON over stdio;启动先发 `ready`(带 protocolVersion 协商);`--mode rpc-ui` 增加 UI 扩展事件 | NDJSON over stdio;命令/response/事件/extension_ui 四类记录;等待 `agent_settled` 判定回合彻底结束 |
|
||||
| 模型接入 | 60+ providers、9 种角色(default/smol/slow/plan/commit/vision/task/advisor/tiny)、fallback 链、凭据轮换 | 20~30+ providers,统一 API(pi-ai),支持订阅 OAuth(Claude Pro/Max、ChatGPT、Copilot 等)与跨供应商中途切换 |
|
||||
| 平台 | macOS/Linux/Windows 原生单二进制(明确强调 Windows 不用 WSL) | macOS/Linux/Windows(Node 安装器 + npm/Nix) |
|
||||
| 许可证 | MIT | MIT(pi-mono 时代)→ MIT(现行) |
|
||||
| 治理/节奏 | 社区 fork,激进迭代(31k+ commits,版本号 18.x) | 上游主项目,lockstep 发版(v1.3.0),组织化治理(含安全供应链加固) |
|
||||
|
||||
---
|
||||
|
||||
## 4. 分维度详解
|
||||
|
||||
### 4.1 血统:fork 关系是理解一切差异的钥匙
|
||||
|
||||
omp README 自述:*"omp is a fork of pi-mono by Mario Zechner, extended with a batteries-included coding workflow."* 因此:
|
||||
|
||||
- 两者**设计语言同源**:会话为 JSONL 树(id/parentId)、`--no-session` 临时模式、`prompt` RPC 命令、`message_update`/`assistantMessageEvent`/`text_delta` 事件、NDJSON over stdio 等都一脉相承。YCode 的 `src/main/omp.ts` 注释描述的协议形态与 pi 官方 RPC 文档几乎同构。
|
||||
- 分化点在于 **"要不要替使用者做决定"**:Pi 把子代理、计划模式、权限弹窗、todo 等统统砍掉("features confuse models"是它的原话逻辑);omp 则逐项内置,还加了 Pi 没有的原生核心、审批、协作等。
|
||||
|
||||
### 4.2 内核实现:性能路线分道扬镳
|
||||
|
||||
- **Pi**:纯 TS,工具逻辑跑进程外命令(bash 调用系统 shell / rg 等),安装即 npm 包,跨平台一致性依赖环境。
|
||||
- **omp**:把 bash(brush-shell)、coreutils、ripgrep、glob walker、tree-sitter AST、PTY、图像解码、BPE 计数等全部编进 Rust N-API 单二进制,"no fork/exec on the hot path";官方宣称 hashline 内容哈希编辑让 Grok 4 Fast 在同一任务上少花 61% 输出 token、MiniMax 通过率翻倍。代价是仓库体量和与上游的偏离度大。
|
||||
|
||||
### 4.3 功能面:一个做减法,一个做加法
|
||||
|
||||
- **Pi 的减法**(官方明示):无子代理、无计划模式、无内置权限系统、无内置 todo。补充方式:扩展(TS 模块,可注册工具/拦截 tool_call)、技能(Markdown+README)、prompt 模板、npm/git 分发包。
|
||||
- **omp 的加法**(21 项扩展,摘关键):持久 Python/Bun `eval` 并回调自身工具、写文件即过 LSP、驱动真实调试器、流规则(TTSR)、子代理+worktree、第二模型 advisor、`/collab` 加密共享、`/review` P0–P3 代码审查、hashline 编辑、GitHub 即文件系统(`pr://`、`issue://`)、自维护记忆(retain/learn/recall)、继承 Cursor/Cline/Codex/Copilot 既有配置、浏览器与桌面控制。
|
||||
|
||||
### 4.4 嵌入与协议:对 YCode 最相关的一节
|
||||
|
||||
- 两者都提供 **stdio NDJSON RPC** 作为宿主嵌入方式,命令都用可选 `id` 关联响应;turn 结束判定都涉及 `agent_end`(omp 另有 `isTerminal` 语义、pi 有 `agent_settled` 全静默语义)。
|
||||
- **差异点(需实测确认)**:
|
||||
- omp 启动后先写 `ready` 帧(含 `protocolVersion: 1`、`supportedProtocolVersions: [1,2]`、`maxFrameBytes: 1048576`);pi 文档未描述 ready 握手帧。
|
||||
- omp 有 `--mode rpc-ui`(UI 能力标记 + 扩展 UI 桥),Ygent/YCode 侧历史上用过;pi 的对应物是 RPC Extension UI 记录族。
|
||||
- omp 拒收 `@file` 命令行参数(同 pi),文件引用走 prompt。
|
||||
- **嵌入 SDK**:omp 暴露 `ModelRegistry`/`SessionManager`/`createAgentSession`;pi 有官方 TypeScript SDK + `RpcClient`。两者都支持"进程外 RPC"和"进程内 SDK"两档集成。
|
||||
- **编辑器协议**:omp 提供 ACP(Zed 等);pi 侧公开文档未见 ACP 一等支持(以 RPC/SDK 为主)。
|
||||
|
||||
### 4.5 版本与维护
|
||||
|
||||
- omp:fork 后自主版本线(18.x),节奏极快(README 数据 31,158 commits、910 tags);本机 18.6.3 落后上游约 5 个 minor(18.11.2)。
|
||||
- pi:上游按 lockstep 发全包 1.3.0;供应链加固(精确锁版本、min-release-age、安装锁、CI 审计)明显更工程化,说明其定位偏"被依赖的平台"。
|
||||
|
||||
---
|
||||
|
||||
## 5. 对 YCode 的含义(不预设结论)
|
||||
|
||||
1. **现内核归属与版本**:YCode 用的 `omp.exe 18.6.3` 是 omp(oh-my-pi),不是 Pi 上游。记录内核版本时可直接标注 "omp (oh-my-pi) 18.6.3",避免与上游 Pi 混淆。
|
||||
2. **协议同源 ≠ 能力等价**:omp 适配层(`src/main/omp.ts` + `agent/omp-turn.ts`)与 pi 的 RPC 形态高度相似,若未来评估"内核可替换性/双内核",pi 是迁移成本最低的候选;但按 `AGENTS.md`,等价性必须按工作包逐项验证,不能由协议相似直接推论。
|
||||
3. **功能对齐视角**:WorkBuddy 侧的能力面(计划、子代理、技能、MCP、审批/问答、压缩续写)与 omp 的"全内置"路线匹配度更高;换成上游 Pi 则这些都需要宿主自建(扩展/Docker 化权限等),反而是额外工作量。
|
||||
4. **版本差**:本机 18.6.3 与上游 18.11.2 的差异清单未做;升级属内核变更,需要单独验证回合语义/事件兼容性。
|
||||
|
||||
---
|
||||
|
||||
## 6. 未验证项(需另行取证)
|
||||
|
||||
- [ ] 本机 omp 18.6.3 与上游 18.11.2 的具体差异(未逐项 diff changelog)。
|
||||
- [ ] pi 1.3.0 的 RPC 与 omp 18.x 的 RPC 逐帧差异(ready 帧、版本协商、事件命名、终态语义)未做真实对照实验。
|
||||
- [ ] omp 对 pi 扩展生态的兼容程度(fork 后 diverge 深度)未核查。
|
||||
- [ ] 两者"子代理/计划/审批"具体行为对 YCode 复刻 WorkBuddy 语义的等价性未评估。
|
||||
- [ ] 星标数等社区指标:omp ~3.6 万(GitHub 2026-10-16 抓取);pi 侧第三方报道约 5.5 万,未以 GitHub 页面直证,仅作量级参考。
|
||||
|
||||
---
|
||||
|
||||
## 7. 来源
|
||||
|
||||
| 来源 | URL | 采集日期 |
|
||||
|---|---|---|
|
||||
| omp 官网首页 | https://omp.sh | 2026-10-17 |
|
||||
| omp CLI 参考 | https://omp.sh/docs/cli | 2026-10-17 |
|
||||
| omp RPC 模式 | https://omp.sh/docs/rpc | 2026-10-17 |
|
||||
| omp 文档总览 | https://omp.sh/docs | 2026-10-17 |
|
||||
| omp GitHub(fork 说明、21 项特性、Rust 核心、v18.11.2) | https://github.com/can1357/oh-my-pi | 2026-10-17 |
|
||||
| Pi 仓库 README(极简定位、跳过项、权限模型、包列表) | https://github.com/badlogic/pi-mono(重定向至 earendil-works/pi) | 2026-10-17 |
|
||||
| Pi RPC 模式 | https://pi.dev/docs/latest/rpc | 2026-10-17 |
|
||||
| Pi MCP 支持 | https://pi.dev/docs/latest/mcp | 2026-10-17 |
|
||||
| npm:pi-coding-agent 1.3.0 | https://registry.npmjs.org/@earendil-works/pi-coding-agent/latest | 2026-10-17 |
|
||||
| npm:oh-my-pi 18.11.2 | https://registry.npmjs.org/@oh-my-pi/pi-coding-agent/latest | 2026-10-17 |
|
||||
| 第三方 Pi 深度拆解(4 工具、循环语义) | needhelp.icu / yeyulingfeng.com / 0bserver07.github.io/chimera | 2026-10-17 |
|
||||
|
||||
> 注:社区指标与第三方文章仅作背景参考;凡引用均以官方仓库/文档为准,未验证项已列于第 6 节。
|
||||
@@ -0,0 +1,173 @@
|
||||
# SOP:WorkBuddy AI 运行时调试与对话区参照采集
|
||||
|
||||
> 历史 SOP。YCode 自 2026-10-15 接手起,查看 WorkBuddy 实现统一经 REA;以下直接 CDP、evaluate 和采集脚本不再作为执行入口。当前 REA 已提供 `list_electron_targets` / `inspect_electron_page`,支持原版 file 页面。原始测量只作待复核参照。
|
||||
|
||||
验证日期:2026-10-08。已验证环境:Windows、WorkBuddy AI 5.7.6、Node 24.21.0。
|
||||
项目脚本要求 Node 22+,使用内置 `fetch` 和 `WebSocket`,无需额外 npm 依赖。
|
||||
|
||||
目标:通过 WorkBuddy 内置 Chromium DevTools Protocol(CDP)读取实际对话页面的
|
||||
DOM、computed style 和截图,为 Ygent 对标提供可重复采集的依据。
|
||||
这套流程不依赖 computer-use 或内存 hook,也不修改 WorkBuddy 安装包。
|
||||
|
||||
## 1. 调试入口与适用范围
|
||||
|
||||
安装包 `main/index.js` 的 `applyCliCommandLineSwitches` 读取
|
||||
`WORKBUDDY_REMOTE_DEBUGGING_PORT`,并调用 Chromium 的 `remote-debugging-port` 开关。
|
||||
此开关仅在启动时生效;WorkBuddy 有单实例锁,启动第二个实例不会给旧实例开启调试。
|
||||
|
||||
本次端口为 `9223`,已验证监听地址是 `127.0.0.1`。
|
||||
端口提供页面调试能力,保持本机使用,不做公网转发。
|
||||
捕获脚本只读取页面,不发送对话、不执行工具、不读取 cookies 或 localStorage。
|
||||
|
||||
## 2. 准备环境
|
||||
|
||||
以下命令在 PowerShell 中执行。切换到项目目录,检查 Node 与安装路径:
|
||||
|
||||
```powershell
|
||||
Set-Location 'C:\Users\Administrator\code\ygent'
|
||||
node --version
|
||||
Test-Path "$env:LOCALAPPDATA\Programs\WorkBuddyAI\WorkBuddyAI.exe"
|
||||
```
|
||||
|
||||
Node 应为 22+,安装路径应返回 `True`。如果 WorkBuddy 安装在其他位置,替换后续启动路径。
|
||||
完成正在运行的任务,保存输入框草稿,然后通过应用的“退出”菜单或托盘退出应用。
|
||||
只关闭窗口可能留在托盘,不能视为进程已退出。
|
||||
|
||||
```powershell
|
||||
Get-Process -Name WorkBuddyAI -ErrorAction SilentlyContinue |
|
||||
Select-Object Id, MainWindowTitle
|
||||
Get-NetTCPConnection -LocalPort 9223 -State Listen -ErrorAction SilentlyContinue |
|
||||
Select-Object LocalAddress, LocalPort, OwningProcess
|
||||
```
|
||||
|
||||
确认主应用已退出且端口可用。若端口已被当前 WorkBuddy 的 CDP 占用,可直接进入第 4 步;
|
||||
若被其他程序占用,选择其他空闲端口,并同步修改启动环境变量和采集命令。
|
||||
|
||||
## 3. 开启调试并启动
|
||||
|
||||
环境变量只用于此次启动,不通过 `setx` 永久写入。启动后恢复当前终端原有值:
|
||||
|
||||
```powershell
|
||||
$wbSopPreviousPort = $env:WORKBUDDY_REMOTE_DEBUGGING_PORT
|
||||
try {
|
||||
$env:WORKBUDDY_REMOTE_DEBUGGING_PORT = '9223'
|
||||
Start-Process "$env:LOCALAPPDATA\Programs\WorkBuddyAI\WorkBuddyAI.exe"
|
||||
} finally {
|
||||
if ($null -eq $wbSopPreviousPort) {
|
||||
Remove-Item Env:WORKBUDDY_REMOTE_DEBUGGING_PORT -ErrorAction SilentlyContinue
|
||||
} else {
|
||||
$env:WORKBUDDY_REMOTE_DEBUGGING_PORT = $wbSopPreviousPort
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
等待主窗口完成加载。本次重启后原会话“处理大文件”恢复;若没有自动恢复,手动打开目标会话。
|
||||
|
||||
## 4. 验证调试入口
|
||||
|
||||
```powershell
|
||||
Invoke-RestMethod 'http://127.0.0.1:9223/json/version' |
|
||||
Select-Object Browser, 'Protocol-Version'
|
||||
Invoke-RestMethod 'http://127.0.0.1:9223/json/list' |
|
||||
Select-Object id, title, type
|
||||
Get-NetTCPConnection -LocalPort 9223 -State Listen |
|
||||
Select-Object LocalAddress, LocalPort, OwningProcess
|
||||
```
|
||||
|
||||
验收条件:版本接口返回 `Browser` 和 `Protocol-Version`;目标列表包含 WorkBuddy 的
|
||||
`page`;监听地址为本机回环地址。本次返回 `Chrome/138.0.7204.251` 和协议版本 `1.3`。
|
||||
`/json/list` 的原始 URL 可能包含账号快照,不把完整 URL 输出贴入仓库或报告。
|
||||
|
||||
## 5. 采集当前页面
|
||||
|
||||
在应用里定位到要比对的正文、表格、代码块或工具行。需要比对工具细节时先展开相关过程。
|
||||
每次采集使用独立目录,避免后一次覆盖前一次:
|
||||
|
||||
```powershell
|
||||
$wbSopCapture = Join-Path $env:USERPROFILE (
|
||||
'.ygent\imports\workbuddy-debug-' + (Get-Date -Format 'yyyyMMdd-HHmmss-fff')
|
||||
)
|
||||
node scripts/wb-cdp.mjs "$wbSopCapture" 9223
|
||||
Get-ChildItem -LiteralPath $wbSopCapture | Select-Object Name, Length
|
||||
```
|
||||
|
||||
输出应包含 `connected: true`,并生成以下文件:
|
||||
|
||||
| 文件 | 内容 |
|
||||
|---|---|
|
||||
| `dom-styles.json` | 页面标题、视口和 DPR、已挂载正文、相关类名统计,以及指定选择器的 HTML、坐标和 computed style |
|
||||
| `workbuddy.png` | 当前视口截图,不是整段会话的长截图 |
|
||||
|
||||
脚本自动排除带 `windowKind` 的辅助页面,避免把独立搜索窗口当成主对话页面。
|
||||
DOM 和截图先后读取,采集稳定内容能减少两者之间的差异。
|
||||
文件含真实对话,保存在用户私有目录;项目仓库只保存脚本、SOP 和整理后的规格。
|
||||
|
||||
## 6. 检查样式并建立对标记录
|
||||
|
||||
```powershell
|
||||
$wbSopSnapshot = Get-Content -LiteralPath (
|
||||
Join-Path $wbSopCapture 'dom-styles.json'
|
||||
) -Raw -Encoding utf8 | ConvertFrom-Json
|
||||
$wbSopSnapshot.viewport
|
||||
$wbSopSnapshot.samples |
|
||||
Where-Object count -gt 0 |
|
||||
Select-Object selector, count
|
||||
($wbSopSnapshot.samples |
|
||||
Where-Object selector -eq '.cr-markdown p').samples |
|
||||
Select-Object text, rect, styles
|
||||
```
|
||||
|
||||
逐项记录“会话与内容位置、截图目录、视口、DPR、主题、应用缩放、选择器、样式值、Ygent 差距”。
|
||||
两侧使用同一段已导入内容,保持窗口尺度、主题及缩放一致再比较。
|
||||
需要取得另一处表格或工具行时,在 WorkBuddy 中定位并重新采集。
|
||||
|
||||
当前脚本的采集边界:
|
||||
|
||||
- 每个指定选择器最多保存前三个节点;单节点文本最多 1500 字符、HTML 最多 18000 字符。
|
||||
- `visibleText` 最多 40000 字符,来自 `body.innerText`,可能包含已挂载但不在屏幕内的内容。
|
||||
- 历史列表会按视口挂载,`count` 是当前 DOM 节点数,不能当作全会话数量。
|
||||
- 默认没有覆盖所有工具行类名。若要采集其他组件,先查看 `classCounts`,定位实际节点,
|
||||
再扩展 `scripts/wb-cdp.mjs` 中的 `selectors`;使用哈希类名时要注意版本变化。
|
||||
- computed style 应结合实际节点、继承关系、缩放和截图解释,不能直接作为通用设计 token。
|
||||
|
||||
## 7. 关闭调试
|
||||
|
||||
通过应用菜单或托盘正常退出 WorkBuddy,然后确认当前终端没有调试变量,再正常启动:
|
||||
|
||||
```powershell
|
||||
Remove-Item Env:WORKBUDDY_REMOTE_DEBUGGING_PORT -ErrorAction SilentlyContinue
|
||||
Start-Process "$env:LOCALAPPDATA\Programs\WorkBuddyAI\WorkBuddyAI.exe"
|
||||
Get-NetTCPConnection -LocalPort 9223 -State Listen -ErrorAction SilentlyContinue |
|
||||
Select-Object LocalAddress, LocalPort, OwningProcess
|
||||
```
|
||||
|
||||
确认 WorkBuddy 不再监听该端口。若仍监听,检查是否旧实例未退出,或变量在用户/系统环境中另有配置。
|
||||
只删除终端变量不会关闭已经运行的 CDP;必须退出调试实例。
|
||||
|
||||
## 8. 常见问题
|
||||
|
||||
| 现象 | 处理 |
|
||||
|---|---|
|
||||
| 连接拒绝 / 请求超时 | 确认启动时设置了变量、旧实例已退出、主窗口已加载、端口一致 |
|
||||
| 端口被占用 | 查询 `OwningProcess`,换空闲端口;不结束不明进程 |
|
||||
| `WorkBuddy renderer target not found` | 检查主窗口是否仍在加载;升级后检查主页面 URL 与脚本筛选条件 |
|
||||
| `WebSocket is not defined` | 升级到 Node 22+,检查 `Get-Command node` 是否指向预期版本 |
|
||||
| 选择器 `count` 为 0 | 确认已定位到相关内容,检查 `classCounts`;可能是折叠、虚拟列表或类名变化 |
|
||||
| 截图显示搜索窗口 | 检查是否使用最新脚本;主页面筛选应排除带 `windowKind` 的辅助目标 |
|
||||
| 重复采集后旧文件消失 | 同一输出目录会覆盖两个文件;按第 5 步创建带时间戳的新目录 |
|
||||
| 脚本超时或断连 | 等待页面稳定后重新采集;连接超时为 10 秒,单个 CDP 请求为 20 秒 |
|
||||
|
||||
## 9. 本次实测发现与相关资料
|
||||
|
||||
当前 WorkBuddy AI 页面实际使用 `.cr-markdown`、`.cr-self-message`、`.cr-input-box`。
|
||||
已挂载的 DOM 没有旧资料中的 `.cb-markdown` 和 `.cb-task-tool-item-inner`。
|
||||
在本次 1200 × 762、DPR 1 的快照中,正文段落的 computed style 约为
|
||||
`15.0001px / 26.2502px`。这是该环境下的实测值,不应概括为所有版本和缩放状态的固定规格。
|
||||
|
||||
因此 `lib-chat-ui` 中仍存在的旧样式只作为辅助资料;当前对话区的对标依据是实际 DOM 和 computed style。
|
||||
本次验证了调试与采集能力,Ygent 的 1:1 对齐需要逐项实现和验收。
|
||||
|
||||
- [真实对话数据转换与导入](workbuddy-reference-import.md)
|
||||
- [历史静态分析与 ASAR 提取方式](reference/workbuddy/chat-tool-fold.md)
|
||||
- [运行时采集脚本](../scripts/wb-cdp.mjs)
|
||||
- [对话区对标路线图](ygent-chat-parity.md)
|
||||
@@ -0,0 +1,131 @@
|
||||
# WorkBuddy 对话区前端布局实测
|
||||
|
||||
> 2026-10-08补充:[最新原生内层文字与布局审计](ygent-workbuddy-render-audit-2026-10-08.md)。下文外层用户气泡13px、输入容器14px不是实际文字字号;本机Slate内层两处实际均15px,应以最新审计为准。
|
||||
|
||||
验证对象:WorkBuddy AI 5.7.6、Windows、主窗口 1200 × 762 CSS px、DPR 1。
|
||||
证据来自真实页面 CDP computed style、元素矩形、内联样式及安装包 CSS。
|
||||
这是一个窗口与会话下的实测,不代表所有分辨率和用户字号设置。
|
||||
|
||||
## 字体规则
|
||||
|
||||
对话正文不是每级字号各自写死 `px`。Markdown 先接入根字号和行高 token,再由段落与标题按相对比例排版;运行时显示出来的像素值只是当时 token 的计算结果。输入框属于另一套控件样式,当前 CSS 确实单独声明了 `14px`。
|
||||
|
||||
| 元素 | 运行时实测 | CSS 规则 |
|
||||
|---|---:|---|
|
||||
| Markdown 根节点 | 当前解析为 17.143px / 30px | `font-size: var(--cr-md-root)`;行高 `var(--cr-md-line-height, 1.75)` |
|
||||
| Markdown 段落 | 当前解析为 15px / 26.25px | `font-size: .875em`,继承 1.75 行高 |
|
||||
| Markdown 一级标题 | 由 token 控制 | `font-size: var(--cr-md-h1-font-size, 1.25em)` |
|
||||
| Markdown 行内代码 | 按父级字号 | `font-size: 1em` |
|
||||
| Markdown 表头 | 当前解析为 15px / 26.25px,字重 600 | 单元格横向 padding 12px;浅色表头实测 `#f7f7f7` |
|
||||
| 输入区 | 当前解析为 14px / 21px | `.cr-input-box` 声明 `font-size:14px; line-height:1.5` |
|
||||
| 输入编辑器 | 高度 64px,padding 横向 16px | `.cr-input-editor-host` `min-height:64px; overflow-y:auto` |
|
||||
|
||||
Markdown 组件声明 `--cr-md-root: var(--cb-md-root, 16px)`,当前主题解析为
|
||||
`--cb-md-root: 17.143px`。HTML 根字体为 16px,页面 zoom 和 visual viewport scale 均为 1。
|
||||
本次 15px 段落是根字号乘 `.875em` 的计算结果,不能反推为源码把段落固定写成 `15px`,
|
||||
也不能归因于 viewport 缩放。字号变量的上游已在组件 bundle 中找到,具体的六级调节规则见下节。
|
||||
|
||||
实际正文段落间距为 12px;代码块实测使用 monospace、12.857px / 22.5px 行高、
|
||||
横向 padding 16px,并限制内部滚动。Ygent 当前默认档的 Markdown 根字号、段落比例、
|
||||
行高与代码字号已按上述规则设置;用户气泡仍单独采用 13px / 19px。
|
||||
|
||||
## 全局字号控制
|
||||
|
||||
`renderer/assets/ui-docs-viewer-veG3wQhz.js` 中有统一的字号级别管理器,作用超过 Markdown:
|
||||
正文、标题、说明文字、代码、按钮文字和按钮高度都接入它。
|
||||
|
||||
级别保存在 `localStorage` 的 `agent-ui-font-size-level:v2`,并同步到
|
||||
`config.preference.fontSizeLevel`。有效级别为 1 到 6;没有有效保存值时默认为 2。
|
||||
每级同时更新根 Markdown 字号和全局偏移量:
|
||||
|
||||
| 级别 | 根字号 token `--cb-md-root` | 全局字号偏移 |
|
||||
|---:|---:|---:|
|
||||
| 1 | 16px | -1px |
|
||||
| 2(默认) | 17.143px | 0px |
|
||||
| 3 | 18.286px | +1px |
|
||||
| 4 | 20.571px | +2px |
|
||||
| 5 | 22.857px | +2px |
|
||||
| 6 | 26.286px | +2px |
|
||||
|
||||
`--wb-font-body-size`、`--wb-font-caption-size`、标题和代码等设计 token 用各自的 base size
|
||||
加全局偏移计算。全局 token 偏移夹在 -1 至 +2px,避免级别 5、6 把紧凑控件撑大过多;
|
||||
按钮高度再按更新后的行高和垂直 padding 重算。
|
||||
|
||||
旧 CSS 中直接写为 `font-size: 13px` 的规则也会参与字号调节。管理器扫描可读的样式表,
|
||||
按级别注入 `max(8px, calc(13px + var(--cb-font-size-offset) * 1px))` 覆盖规则。
|
||||
它保留 `@media` 分组,观察后续新增的样式表,并排除 `.cb-font-size-fixed` 及其子孙节点,
|
||||
以便明确声明固定字号的控件不随全局级别改变。
|
||||
|
||||
Windows 上可用 `Ctrl+-` 降一级、`Ctrl++` 升一级、`Ctrl+0` 恢复默认。级别限制在 1 到 6。
|
||||
切换时派发 `cb-font-size-change` 和 `cb-font-size-level-change` 事件,让组件刷新。
|
||||
源码会同时出现字体 token、相对 `em` 和少量固定 `px`:全局设置更新设计 token,
|
||||
并兼容旧组件里的固定字号。
|
||||
|
||||
## 宽度与主布局
|
||||
|
||||
在当前 1200px 窗口中,左侧栏为 280px,主内容区为 920px。对话历史和输入区各自在主内容区居中,并使用相同的 832px 上限:
|
||||
|
||||
- `.cr-message-list__content` 运行时内联 `max-width: 832px`,源码使用 `width:100%; max-width:100%; margin-inline:auto`。
|
||||
- 对话内容区左右 padding 为主题变量 `--cr-message-list-content-inline-padding:40px`。832px 外框扣除 80px 后,消息正文列为 752px。
|
||||
- 输入区外框上限同为 832px,外框左右各 padding 24px,输入控件宽度为 784px。
|
||||
- 小于 832px 的可用主列时,`width:100%` 收缩外框,正文与输入仍分别保留自己的横向 padding。布局跟随内容区宽度,不依靠 viewport 单位设定字体。
|
||||
- 对话主列是 flex 布局。消息列表 `flex:1; min-height:0; overflow-y:auto`,输入区 `flex-shrink:0` 固定在底部;这样滚动发生在历史列表内部,长内容不会把输入区挤出窗口。
|
||||
- 输入编辑区设置最小高度,并通过纵向滚动承载增长内容;工具栏单独 flex 布局、`flex-shrink:0`,操作项不会跟着编辑内容收缩。
|
||||
|
||||
Ygent 对应使用同一内容列:在 1200 × 762 窗口、280px 侧栏和 10px 消息滚动条下,832px 对话外框居中后,消息正文列落在 `x=359..1111`(752px)。助手头像行、回答正文和用户气泡均对齐这条列;输入框外框落在 `x=348..1132`(784px),其编辑器和工具栏分别保留 64px 与 56px 高度。窗口窄于内容上限时,消息列跟随可用宽度收缩,窄屏左右内边距为 16px。
|
||||
|
||||
实测 DOM 层级中,对话列和输入区都受 832px 居中容器约束,但消息、输入和工具栏是独立组件。这个边界让两边 padding 与窄窗收缩策略各自清晰。
|
||||
|
||||
## 响应策略
|
||||
|
||||
- 主列采用 `width:100% + max-width + margin:auto`;用可用宽度与最大宽度自然收缩。
|
||||
- `.cr-message-list` 声明 `container-type:inline-size`,具备查询容器的能力。当前对应 CSS 文件没有 `@container` 规则,不能仅凭声明推断对话区已有完整的容器断点体系。
|
||||
- 对话输入工具栏有 `width <= 320px` 的局部断点,在极窄宽度下隐藏次要 context-usage 标记,给常用操作留空间。
|
||||
- 主内容 CSS 的另一个欢迎页容器 `.chat-container--welcome` 默认上限 848px,在 viewport 至少 1681px 时扩到 1008px;这是不同容器的规则,不能跟本次运行页面的 832px 对话列混为一谈。
|
||||
- 组件 CSS 使用 `prefers-reduced-motion` 减少消息列表进出动画。
|
||||
|
||||
## 消息气泡、widget 与输入区
|
||||
|
||||
同一窗口的当前会话快照实测:
|
||||
|
||||
| 元素 | 运行时规格 |
|
||||
|---|---|
|
||||
| 助手头部 `.cr-agent__header` | 752px 内容宽;24.5px 高;24px 圆形标识、10px 间距;名称 14px / 24.5px、字重 600;下方间距 12px |
|
||||
| 完成状态 `.cr-collapse__header` | 文案 `已完成 3m2s`;15px / 26.25px、三级文字色、宽度随内容;12px 箭头与 8px 间距 |
|
||||
| Markdown 根 `.cr-markdown` | 字号 17.143px / 行高 30.0002px(当前 2 级);段落按 `.875em`,实测 15.0001px / 26.2502px |
|
||||
| 列表 `.cr-markdown ul` | 15.0001px / 26.2502px;左缩进 21.4502px;列表后间距 16px;列表项间距 4px |
|
||||
| 表格单元格 `.cr-markdown th/td` | 15.0001px / 26.2502px;padding `8px 12px`;表头底色 `#f7f7f7` |
|
||||
| 代码块 `.cr-markdown pre` | 12.8573px / 22.5002px;padding `12px 16px` |
|
||||
| 用户气泡 `.cr-self-bubble` | 13px / 19px;`#f2f2f2`;padding `8px 12px`;圆角 `16px 16px 0`;最小宽 40px、最大宽 100%、最大高 310px,内部滚动 |
|
||||
| 用户消息工具栏 `.cr-toolbar` | 相对用户气泡框架绝对定位在底部;默认透明;时间 14px / 20px,含复制和编辑按钮 |
|
||||
| 表格操作 `.cr-message-quote-table-menu` | hover 时显示于表格右上角;菜单 116×38px,按钮 106×28px;点击把原表格 Markdown 加入输入草稿 |
|
||||
| widget 卡 `.cr-widget-card` | 正文列宽 752px;边框 `1px solid #ebebeb`、圆角 16px、纵向 margin 8px |
|
||||
| widget 内容 `.cr-widget-body` | padding `12px 16px`;当前 iframe 宽 718px,高度随内容变化 |
|
||||
| widget iframe | `sandbox="allow-scripts"`,不含 `allow-same-origin`;CSP 允许内联脚本与指定 CDN |
|
||||
| 输入容器 `.cr-input-container` | `x=348, y=592, 784×134px`;白底、`1px solid #e6e6e6`、24px 圆角、两层轻阴影 |
|
||||
| 输入编辑区 `.cr-input-editor-host` | `x=349, y=605, 782×64px`;横向 padding 16px;字号 14px / 21px |
|
||||
| 输入工具栏 `.cr-input-toolbar` | `x=349, y=669, 782×56px`;padding 12px;按钮 32px |
|
||||
| 禁用发送按钮 | 32px 圆形;图标圆底填充 `rgba(0,0,0,.2)` |
|
||||
|
||||
widget 的高度由 iframe 内容决定。SVG 根据自身 viewBox 呈现比例,HTML 图表按内部容器高度扩展;iframe 向父层报告尺寸,宿主验证来源并限制最大值。
|
||||
|
||||
## 对 Ygent 的参考价值
|
||||
|
||||
1. 给对话消息和输入区一个共享的居中最大宽度,再分别配置内边距。避免消息列与输入框在宽屏各自漂移。
|
||||
2. 用 `min-width:0`、`min-height:0`、flex shrink 和列表内部 `overflow-y:auto` 明确滚动容器。窄窗或长内容时,输入区仍留在底部。
|
||||
3. 把 Markdown 基准、段落倍率、行高、输入区字号做成角色明确的 token。Ygent 的默认 Markdown 规则与本次实测一致;用户气泡和输入区按各自控件规格管理。全局字号应明确级别、上下界、持久化、组件更新方式及固定字号例外。Ygent 六档根字号跟随 WorkBuddy,常规控件偏移在第 5、6 档封顶为 +2px。
|
||||
4. 在真正受限的控件上做局部响应。窄宽时优先收起次要工具标记,别先整体缩小所有字号。
|
||||
5. 以运行时 computed style 验收主题变量、Electron zoom 和实际像素;只读静态 CSS 很容易漏掉主题宿主注入的 token。computed `px` 是实测结果,不是 token 定义本身。
|
||||
|
||||
## 证据与局限
|
||||
|
||||
- 运行时快照与截图保存在用户私有目录 `%USERPROFILE%/.ygent/imports/workbuddy-debug-20261008/`,不放进仓库。
|
||||
- 主要组件 CSS:`renderer/assets/lib-chat-ui-B-axvvx6.css`。
|
||||
- 字号管理器:`ui-docs-viewer-veG3wQhz.js`,包括级别表、存储键、快捷键和旧式 `px` 样式覆盖。
|
||||
- 正文段落规则:`.cr-markdown` 使用主题根字号和 1.75 行高,`.cr-markdown p` 使用 `.875em`,标题也使用相对字号 token。
|
||||
- 输入布局规则:`.cr-input-box` 14px / 1.5;编辑器最小高 64px;输入容器运行时 inline `min-height:96px`。
|
||||
- 当前会话主体宽度 832px 来自运行时 inline style;CSS 文件里 `.cr-message-list__content` 只声明 `max-width:100%`。具体控制该 inline 值的组件逻辑尚未追踪。
|
||||
- DOM 是虚拟列表,仅包含当前已挂载部分。离开视口的消息矩形可以是负坐标,不能按快照节点数估算完整会话。
|
||||
- 点击窗口不同宽度进行重复采样前,先另建输出目录。复测时同时记录 viewport、DPR、Electron zoom、主题与相关主题变量。
|
||||
|
||||
采集过程见 [运行时调试 SOP](workbuddy-cdp.md),可续接会话数据见 [对话导入说明](workbuddy-reference-import.md)。
|
||||
@@ -0,0 +1,70 @@
|
||||
# WorkBuddy 输入框:添加文件与专家参照
|
||||
|
||||
采集日期:2026-10-08。本文记录实际运行界面与安装包源码,不代表 Ygent 已实现附件或专家。
|
||||
|
||||
## 证据与范围
|
||||
|
||||
通过 WorkBuddy 原生 Electron CDP 9223 获取 DOM、计算样式和矩形,通过 app.asar 读取组件逻辑;未使用 computer-use。实测视口 1334×888、DPR 1。真实对话 DOM 仅保存在用户私有目录 `~/.ygent/imports/hello-layout-20261008/`,不提交。
|
||||
|
||||
主要源码:`renderer/assets/wb-status-chips-CEdDJaZl.js`,包含统一添加菜单、文件来源子菜单、专家选择面板。当前专家子菜单实际显示“暂无可用专家”,因此选中后的页面呈现、实际专家执行及附件发送链路尚未实测,不能根据组件源码宣称闭环通过。
|
||||
|
||||
## 统一入口
|
||||
|
||||
输入框左下角“+”是“更多操作”,不是直接打开文件选择器。当前主菜单:
|
||||
|
||||
1. 添加文件。
|
||||
2. 分隔线。
|
||||
3. 模式。
|
||||
4. 专家。
|
||||
5. 技能。
|
||||
6. 连接器。
|
||||
|
||||
鼠标进入条目即打开二级菜单,支持在主菜单和二级菜单之间移动。源码对子菜单离开采用 120ms 延迟收起,触屏通过 pointer down 选择。关闭主菜单会清空当前子菜单。菜单项是否展示取决于调用方是否提供对应功能;源码还存在引用文件、应用入口,但当前界面未展示。
|
||||
|
||||
## 布局测量
|
||||
|
||||
以下为当前字号下的实测值,位置仅用于定位此次采集,不应硬编码到 Ygent:
|
||||
|
||||
| 元素 | 位置 / 尺寸 | 样式 |
|
||||
|---|---|---|
|
||||
| +触发器 | x428、y807,32×32 | 圆形;展开背景 rgb(242,242,242),图标16×16 |
|
||||
| 主菜单 | x428、y602,200×197 | 内边距8,圆角16,白底 |
|
||||
| 普通条目 | 宽182、高32 | 水平内边距8,圆角8,14px / 22px |
|
||||
| 文件子菜单 | x623、y611,200×186 | 内边距8,圆角16 |
|
||||
| 专家空态子菜单 | x623、y690,240×50 | 内边距8,圆角16 |
|
||||
|
||||
条目字体为 `"PingFang SC", -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif`。菜单阴影为 `0 6px 24px rgba(0,0,0,.04), 0 4px 6px rgba(0,0,0,.04)`。主菜单向上展开,子菜单向右并沿相应条目定位;不是全屏居中的弹窗。Ygent 应接入现有六档字号管理,不能把此处实测14px作为全局固定字号。
|
||||
|
||||
## 添加文件
|
||||
|
||||
当前二级菜单实际包含:本地文件、项目资产、腾讯文档、ima、乐享知识库。
|
||||
|
||||
源码提供独立来源回调:本地文件、腾讯文档、ima、乐享,另外可由调用方注入额外来源;当前项目资产属于界面提供的额外来源。点击来源调用相应回调,然后关闭添加菜单。来源选择与文件选择/导入分层,云服务不能等同于本地上传。
|
||||
|
||||
本轮没有选择真实文件或连接外部服务。文件类型限制、数量/大小上限、导入进度、草稿附件显示与失败重试尚未验收;当前 DOM 没有 `input[type=file]`,不能据此推断不支持多选或没有限制。
|
||||
|
||||
Ygent 当前差距:普通对话的 + 仅显示“附件上传:M4 落地”,新建任务显示“附件上传:开发中”。两个入口都没有真正文件选择、草稿附件和发送数据链路,不能只替换弹出菜单就称为上传完成。
|
||||
|
||||
建议首期实现本地文件与项目文件引用;腾讯文档等入口在对应连接器真正可用后增加。先明确“上传副本”与“引用现有项目文件”的区别,不因添加到草稿就隐式移动文件或扩大执行目录。
|
||||
|
||||
## 专家
|
||||
|
||||
当前界面空态为“暂无可用专家”。以下为同一组件源码确认的能力,受调用方配置限制,不保证当前页面全部启用:
|
||||
|
||||
- 专家使用 `selectedExpertId` 单选;选中项显示勾选,再选同一专家仅关闭菜单,不重复触发选择。
|
||||
- 行结构是16px头像、名称与右侧操作。名称优先使用 profession,其次 name、id;不是直接显示原始文件名。
|
||||
- 可选搜索框支持中文输入法组合事件;搜索具有加载、不可用、无结果等独立状态。
|
||||
- 普通列表由置顶、最近使用、推荐项合并去重;推荐补足目标5项,超过10项启用滚动。置顶点击阻止冒泡,不触发选择专家。
|
||||
- 搜索结果走独立召唤回调;回调返回 false 时不关闭菜单。普通列表走选择回调,选择后关闭。
|
||||
- 调用方可提供“更多专家”入口,也可关闭推荐和搜索。因此当前只有空态不能作为完整专家面板的样式参照。
|
||||
|
||||
Ygent 当前差距:专家管理与选择未实现;Skill/MCP 已有能力登记与会话选择,但不是专家本身。专家执行仍按 `ygent-capability-integration-plan.md` 的 P3 处理,不能用角色标签冒充指令、依赖和回合快照已经接入。
|
||||
|
||||
## Ygent 后续落地顺序
|
||||
|
||||
1. 共用一个 Composer 添加菜单组件,覆盖新建任务、项目内输入及已有对话;将现有技能和连接器选择整合到统一 + 入口,保留其真实能力选择逻辑。
|
||||
2. 实现本地文件选择、草稿附件移除、提交/失败恢复、对话重载与分支引用,以及后端实际读取/图片输入合同。项目文件引用独立记录来源,不能只有一个显示用标签。
|
||||
3. 按 P3 实现专家登记、依赖校验、选择和指令注入;非空会话切换专家按既定方案新建分支/聊天,不能静默替换已有历史的角色。
|
||||
4. 验收菜单的悬停迁移、键盘/Escape、点击外部、边缘避让、六档字号,以及生成中操作对当前回合不产生影响。附件发送与专家执行必须使用私有测试会话验证实际后端链路。
|
||||
|
||||
上述为最初参照调查。后续已落地统一添加菜单与本地附件,具体已实现行为和真实验收边界见 [输入框菜单与附件进度](ygent-attachments.md);专家、项目资产和云来源仍未实现。
|
||||
@@ -0,0 +1,79 @@
|
||||
# WorkBuddy 无项目归属对话实测(2026-10-08)
|
||||
|
||||
## 1. 环境与检查范围
|
||||
|
||||
应用为 WorkBuddy.exe 5.7.6,通过原生 Electron CDP 9223 检查真实侧栏、既有独立对话、新建任务页、工作空间选择菜单和“保存到工作空间”弹窗。另只读检查本地 SQLite 与安装包对应处理代码。
|
||||
|
||||
未发送消息、执行工具、保存工作空间、移动任务、归档或删除数据。打开的保存弹窗已取消;结论区分实际 UI/数据观察和未执行的代码路径。
|
||||
|
||||
## 2. 无项目归属不代表无目录
|
||||
|
||||
本地 `sessions` 分别保存:
|
||||
|
||||
```text
|
||||
project_id 项目归属,可为空
|
||||
cwd 实际本地工作目录
|
||||
is_playground 区分自动目录的独立任务与工作空间任务
|
||||
transport 本地/云端执行来源
|
||||
group_id 另一种分组字段,不能等同于 project_id
|
||||
```
|
||||
|
||||
当前未删除的样本共有 15 条本地会话,10 条 `project_id IS NULL`:
|
||||
|
||||
| 类别 | 数量 | 实测结果 |
|
||||
|---|---:|---|
|
||||
| 自动目录独立任务 | 9 | is_playground=1;cwd 为用户 WorkBuddy 根目录下的时间戳目录 |
|
||||
| 已有目录工作空间任务 | 1 | is_playground=0;cwd 为已有本地目录,project_id 仍为空 |
|
||||
|
||||
检查的目录均存在;不是靠一个隐藏的项目 ID 为这些任务兜底。当前 Ygent 的独立任务绑定隐藏 task 级项目,与这个本地会话模型不同。
|
||||
|
||||
## 3. 侧栏按任务形态展示
|
||||
|
||||
- 自动目录独立任务显示在“任务 (9)”分组;当前 DOM 挂载前 5 条,另有“查看更多 (4)”。挂载数不能当作总数。
|
||||
- 已有目录工作空间任务放在“空间”分组的目录名称下面。
|
||||
- 两个真正有项目 ID 的项目也显示在“空间”分组中,因此“空间”不是“所有会话都有项目归属”的证据。
|
||||
- 侧栏没有为无项目归属任务显示一个“未归类项目”。
|
||||
|
||||
## 4. 新建任务如何取得目录
|
||||
|
||||
新建任务页的输入区默认显示“选择工作空间”。展开后可以选择已登记目录、新建工作空间或打开本地文件夹。
|
||||
|
||||
静态代码确认:未选择目录时,前端将 selectedCwd 留空并使用 isPlayground=true;选择目录时使用该目录并设 isPlayground=false。
|
||||
|
||||
后端的 `workspaceGenerateDefaultCwd` 解析默认根目录,再创建以 `YYYY-MM-DD-HH-mm-ss` 命名的目录;同名时尝试其他时间戳,确保新目录唯一。默认根目录可来自应用配置,通常位于用户主目录的品牌文件夹下。
|
||||
|
||||
这个自动创建路径与现有会话目录吻合。本次没有新发消息触发创建,故不把创建的准确时点、失败交互或工具运行过程记为动态实测通过。
|
||||
|
||||
## 5. “保存到工作空间”不是“归入项目”
|
||||
|
||||
既有独立任务的右键菜单实测含:置顶、重命名、分享任务、在独立窗口中打开、保存到工作空间、打开文件夹、批量操作、归档和删除任务。
|
||||
|
||||
“保存到工作空间”弹窗要求填写工作空间名称,并说明可持续使用对话和文件、同时开展多个任务。
|
||||
|
||||
对应代码路径:
|
||||
|
||||
1. 校验名称及重名/系统保留名。
|
||||
2. 调用 conversations.move(taskId, 原 cwd, transport)。
|
||||
3. 为原 cwd 设置工作空间显示名。
|
||||
4. 将前端任务 isPlayground 更新为 false,刷新列表。
|
||||
|
||||
这里没有传入目标 projectId,也不是选择云端项目的归类弹窗。调用仍传入原 cwd;本次没有点击保存,未实测 move 的所有后端文件副作用。
|
||||
|
||||
在当前独立本地任务菜单中没有看到“归入项目”入口,不能据此断言其他来源或版本绝对不存在该能力。
|
||||
|
||||
## 6. 持久化与清理边界
|
||||
|
||||
独立任务已有本地 SQLite 会话记录,工作目录真实存在,旧任务能重新打开。“未保存到工作空间”不能解释成“不保存聊天”或“关闭立即清除文件”。
|
||||
|
||||
清理周期、归档/删除是否清理目录、任务恢复时的全部执行状态、本地任务归入云端项目等路径均未实测。
|
||||
|
||||
## 7. 给 Ygent 的参考与后续落地
|
||||
|
||||
以下来自调研建议。后续已在 [项目概念约定](ygent-project-space.md) 和 [实施方案](ygent-project-implementation.md) 明确 Ygent 自身规则,包括归属调整保留实际目录;这些实现选择不属于 WorkBuddy 实测结论。
|
||||
|
||||
- 无项目归属对话可以保留 projectId=null,显示在“任务”列表,不必制造“未归类”项目或展示隐藏项目。
|
||||
- 未指定目录时为该任务准备独立托管目录;任务本身持久化,项目归属与实际 cwd 分开记录。
|
||||
- 以后归入 Ygent 项目时,应单独定义是否沿用原目录、项目指令从何时生效、文件如何处理,不能只改 projectId 就暗中搬文件或切换执行目录。
|
||||
- 当前不必照搬 WorkBuddy 的“保存到工作空间”产品入口;Ygent 已采用 [项目+工作目录定义](ygent-project-space.md),需要保持术语简单。
|
||||
|
||||
原始采集及静态片段位于用户私有 `.ygent/imports/render-audit-20261008/`。参见 [WorkBuddy 项目概念](workbuddy-project-concept-2026-10-08.md)。
|
||||
@@ -0,0 +1,46 @@
|
||||
# WorkBuddy 本地对话参照导入
|
||||
|
||||
2026-10-08 已确认:WorkBuddy AI 的会话正文保存在本地,并非只能从云端获取。
|
||||
此前参照文档只检查了 AppData 下的 WorkBuddy 目录,遗漏了 `.workbuddy-ai`。
|
||||
|
||||
## 数据位置
|
||||
|
||||
- `%USERPROFILE%/.workbuddy-ai/workbuddy.db`:`sessions` 表保存标题、工作目录及会话 ID。
|
||||
- `%USERPROFILE%/.workbuddy-ai/sessions/<pid>.json`:运行进程对应的会话 ID。
|
||||
- `%USERPROFILE%/.workbuddy-ai/projects/<目录键>/<sessionId>.jsonl`:正文及工具调用记录。
|
||||
|
||||
无需 UI 自动化或内存 hook;读取这些文件不会修改 WorkBuddy。
|
||||
|
||||
## 转换
|
||||
|
||||
```powershell
|
||||
python scripts/import-workbuddy.py '<会话 JSONL 完整路径>'
|
||||
python scripts/import-workbuddy.py '<会话 JSONL 完整路径>' --apply
|
||||
```
|
||||
|
||||
默认只预检。`--apply` 先通过 SQLite backup API 备份 Ygent 数据库,再以事务创建独立任务及消息,逐字段回读验证。
|
||||
同一 WorkBuddy 会话已有导入任务时跳过,避免重复;此脚本不增量同步。
|
||||
转换文件和数据库备份放在 `%USERPROFILE%/.ygent/imports/`,不写入代码仓库。
|
||||
默认标题从 WorkBuddy `sessions` 表读取(优先 `custom_title`);无来源数据库时回退到 JSONL 的 `ai-title`,也可用 `--title` 覆盖。
|
||||
|
||||
映射规则:
|
||||
|
||||
- 用户消息提取 `<user_query>`,过滤系统注入与纯恢复提示。
|
||||
- 助手消息保留可见正文,不导入内部推理正文、模型凭据或 provider 元数据。`reasoning`事件仅记录存在及相邻可见消息的位置,写入`render_meta.reasoningBefore`;没有可公开展示的摘要时只呈现事件标题,不提供空的展开按钮。
|
||||
- 行内代码在消息来源cwd下能识别为真实文件/目录时,保存标签、路径和类型;代码文本不改写,原始正文仍用于搜索/复制。普通新对话由共享路径组件通过真实IPC在所属会话工作目录下识别,不按参照会话ID或标题硬编码。
|
||||
- 工具按 `callId` 匹配结果,在调用位置插入工具行,保留原参数、输出和可用的 description。
|
||||
- 保留消息时间;没有结果的调用注明“此调用没有执行结果记录”。
|
||||
- `show_widget` 的 HTML 保留在工具参数中,并在独立 sandbox iframe 内渲染。
|
||||
|
||||
## 当前显示限制
|
||||
|
||||
2026-10-08补齐呈现元数据:更新版本首次启动迁移到v10后,运行`python scripts/import-workbuddy.py '<源JSONL完整路径>' --enrich --apply`。仅处理已导入且逐条role/content/fn/result与来源完全一致的参照会话;不匹配即拒绝。先备份数据库,再事务更新render_meta并回读验证,保留消息ID、内容、工具数据及顺序。本次829条已验证,新增374个事件位置标记和7个路径关联。来源文件与推理正文均不改写/导入。
|
||||
|
||||
“深度思考”当前仅恢复事件位置标题,未恢复内容展开或真实模型的思考阶段流式事件;仍不能作为动态思考行为对标通过。路径标签已支持键盘/点击打开,原生验收只执行只读路径分类,未自动启动外部文件应用。
|
||||
|
||||
这是一份参照快照,不会恢复 WorkBuddy 内核上下文。不要把导入记录当作可续接的原内核会话。
|
||||
Ygent 已按导入顺序呈现正文、工具和权限事件,并只折叠连续的工具调用;工具结果仍主要显示单行摘要。
|
||||
本次源会话的五份 HTML 制品已在 sandbox iframe 中渲染;其中一份 SVG 的 iframe 高度仍比 WorkBuddy 少 5px。图片附件、内部推理、审批交互和完整工具结果查看器尚未完整呈现。
|
||||
|
||||
本次导入的源会话为 `05c73f5f-e3ac-452e-bfde-fd5be036e588`,当前 WorkBuddy 标题和 Ygent 参照任务标题均为“处理大文件”。
|
||||
转换结果为 26 条用户消息、254 条助手正文、549 条工具调用,其中一条调用没有结果记录。
|
||||
@@ -0,0 +1,48 @@
|
||||
# 输入框菜单与附件进度
|
||||
|
||||
2026-10-08:已将技能、连接器从输入框底栏合并到 WorkBuddy 风格的“+”二级菜单。新建任务、普通对话和项目内输入使用相同添加菜单与附件组件。专家仍按能力接入方案 P3 实施,当前菜单不显示未实现的专家操作。
|
||||
|
||||
2026-10-09:添加列表进一步统一为12px圆角、36px行高和线条图标;文件来源子菜单收窄至200px,两级菜单间隔4px,首行内容沿父条目对齐。技能/连接器的重复标题移除,勾选控件统一置于行右侧,空态和管理入口采用相同间距。原生9335验证三种子菜单在六档字号下均位于视口内,位置仍随内容尺寸与窗口边界调整;本轮实际列表为空,未新增安装或修改会话能力选择。
|
||||
|
||||
## 当前行为
|
||||
|
||||
- + → 添加文件 → 本地文件,调用系统多选选择器;也支持拖入输入框。拖到侧栏等输入框以外位置不添加。
|
||||
- 一次/一条消息最多8个附件,单文件不超过20MB。草稿展示名称、大小和移除按钮;可不填写文字直接发送,使用“请查看附件”作为请求。
|
||||
- 导入时将原文件复制到 Ygent 数据目录 `attachments/<独立ID>/`,保留文件扩展名,原文件不移动、不修改。相同名称独立保存,源文件随后改变不影响已保存副本。
|
||||
- 附件元数据由后端按ID解析,与用户消息在同一SQLite事务内保存到 render_meta;正文仍为用户输入,不混入附件路径和文件内容。显示、重载和分支使用此元数据。
|
||||
- OMP 请求加入附件副本路径;UTF-8文本内联前128KB,超过部分明确标注截取,工具可继续读取副本。图片/其他二进制保留真实扩展名和副本路径,由模型的文件工具读取;不能宣称所有文档格式均已支持。
|
||||
- 直连模式只支持128KB以内、不含NUL的UTF-8文本附件;不支持的二进制/大文本在发送前明确报错,不产生用户消息。直连后续请求重新从真实副本恢复历史附件上下文。
|
||||
- 发送后立即清空草稿;失败恢复文字和附件。切换会话/页面清理当前附件草稿,文件选择期间切换页面不会把旧选择落到另一输入框。生成中不改动当前回合附件。
|
||||
- 技能与连接器仍使用原会话选择逻辑,菜单显示已选数量,生成中不能修改选择;管理入口进入相应的技能/连接器标签页。
|
||||
|
||||
## 已验证
|
||||
|
||||
环境为真实Tauri WebView2、CDP9335,视口1335×916、DPR1。使用独立临时对话和本地测试文件,未在参照会话发送测试消息。
|
||||
|
||||
1. 真实IPC导入UTF-8文本,OMP模型回答附件中的验证口令。
|
||||
2. 在新建任务页面通过受控Tauri拖入事件触发前端导入,再点击实际发送按钮;模型正确读取,重新载入会话后附件名称/大小仍存在。
|
||||
3. PNG附件通过真实OMP `read` 工具读取,模型正确回答图片主色;不是仅将图片名称作为文字传入。
|
||||
4. 真实数据库回复分支包含两条用户消息的附件元数据。
|
||||
5. 用直连模式发送PNG,消息数不变,前端文字及附件恢复,显示明确限制提示。
|
||||
6. 1至6档真实原生DOM测量,菜单字号为13/14/15/16/16/16px,子菜单没有内部横向溢出,位于视口内。主菜单的scrollWidth包含向右定位的子菜单,不把此正常外部定位当作内部文字溢出。
|
||||
7. Rust 33项测试、前端构建、对话回归通过;附件测试覆盖副本独立性、路径越界拒绝、二进制直连拒绝与OMP引用。
|
||||
|
||||
证据位于用户私有目录 `~/.ygent/imports/hello-layout-20261008/yg-attachment-*` 和 `yg-add-fonts.json`,不提交真实消息/截图。测试对话已从可见列表删除,恢复原会话5、OMP及字号第2档。
|
||||
|
||||
## 验收边界与后续
|
||||
|
||||
系统文件选择器使用真实后端Dialog API,但本轮没有自动操作Windows原生文件选择窗口;受控拖入事件验证的是前端处理和真实导入链路,不等同于真实鼠标拖拽验收。项目内输入复用同一组件和发送合同,项目对话附件专项尚未单独发送模型测试。
|
||||
|
||||
尚未接入项目资产选择、云文件来源、附件内容预览、图片缩略图、OCR/文档转换及自动清理未发送的副本。二进制解析能力取决于当前OMP工具/模型;本轮明确实测UTF-8文本与PNG,不承诺PDF/Office等类型全部可读。当前副本保留用于历史与分支,移除草稿不会删除源文件或历史副本。
|
||||
|
||||
## 调试操作
|
||||
|
||||
按 `ygent-debug.md` 启动9335,打开临时对话;使用原生DOM和IPC采集,禁止用浏览器模拟IPC代替桌面验收。日常验证命令:
|
||||
|
||||
```powershell
|
||||
npm run build
|
||||
npm run check:chat
|
||||
cargo test --lib --manifest-path src-tauri/Cargo.toml
|
||||
```
|
||||
|
||||
真实模型验收分别发送含唯一口令的文本和具有明确主色的PNG,检查模型响应、工具调用、render_meta、重载及分支;失败路径检查消息未误发送、正文/附件恢复。恢复原会话与字号,清理临时对话,不改用户参考消息。
|
||||
@@ -0,0 +1,47 @@
|
||||
# 对话授权与问题回答:实现及验收(2026-10-09)
|
||||
|
||||
## 对标依据
|
||||
|
||||
读取本机 WorkBuddy 5.7.6 的 app.asar,定位 lib-chat-ui 的 InterceptCard(1n5vt)、QuestionFloating(ggdxn)和 QuestionAnswerDisplay;通过 WorkBuddy 原生 CDP 9223 读取真实主题变量。没有发送 WorkBuddy 消息或更改其会话。当前 WorkBuddy 没有待处理交互卡,因此本次依据为组件源码、原生主题和 Ygent 动态实测,未宣称完成两端同场景动态逐像素验收。
|
||||
|
||||
| 位置 | 对齐内容 |
|
||||
| --- | --- |
|
||||
| 输入区域:待授权 | 原输入框隐藏但保持挂载,24px 圆角白色卡片;标题 16/25、命令摘要 14/28,超长省略并保留悬停全文;拒绝、本对话允许、允许依次排列 |
|
||||
| 授权选项 | 40px 行高、12px 圆角、24px 数字底块、8px 间距,选中/悬停灰底,右箭头反馈;默认高亮拒绝,但不自动提交 |
|
||||
| 输入区域:待回答 | 24px 圆角,最大高度 min(60vh,520px);标题 14/24,页码/关闭入口,描述与选项同排,32px 圆形提交按钮,0.2 秒淡入上移 |
|
||||
| 回答方式 | 原始选项值回传,支持自由输入、确认问题和明确跳过;自由输入保留原始文字,空白禁用,中文输入法回车不误提交 |
|
||||
| 消息时间线 | 灰色紧凑入口,回答后显示“提问”;展开为 16px 圆角灰色问答卡,问题 15/25、回答 15/22;授权结果区分允许、拒绝、取消 |
|
||||
| 助手下方 | 等待回答/等待授权与实时耗时;完全访问不能隐藏实际收到的待处理请求 |
|
||||
| 中断与异常 | 保留停止生成入口,提交锁防止重复点击,失败提示且可重试;结束/取消后删除待处理请求,迟到回执被拒绝 |
|
||||
|
||||
上述字号为基准,文字统一叠加六档全局字号偏移;几何尺寸保留参考组件规则。共享组件适用于普通会话、历史回显和实时生成,不依赖会话身份。主页面继续沿用用户指定的渐变设计。
|
||||
|
||||
## 实际执行链路
|
||||
|
||||
OMP rpc-ui 的工具授权与问题回答分开管理。工具授权保留原网关、会话白名单和审计;问题由独立 pending_questions 保存会话、运行请求、问题 ID、方法及选项,不能被完全访问或授权白名单自动回答。答案通过真实 stdin extension_ui_response 回传,验证当前运行与选项,写入成功才移除问题。
|
||||
|
||||
本机 OMP 18.6.3 的 ask 使用 select;选择 Other 后再次发出 editor。前端将其作为同一道问题,保留消息 ID,允许中间插入工具事件;请求 ID 变化后,旧提交确认不能覆盖新输入状态。问题/答案写入 render_meta,重载恢复;进程已失效的历史 pending 请求仅显示取消记录。
|
||||
|
||||
MCP 宿主授权不展示尚不支持的会话放行选项。其他内核未纳入本次问题回答验收。当前 OMP 每次发送一个 select/editor/confirm,页面显示 1/1 并禁用翻页;批量问题、多选、选项 preview 尚未接入,不能把单题实现当作完整批量对标通过。
|
||||
|
||||
## 调试与回归 SOP
|
||||
|
||||
1. 按 [原生调试 SOP](ygent-debug.md) 停止正常实例,使用独立数据目录与 9336 启动调试构建;绝不使用测试库覆盖用户库。
|
||||
2. 在隔离数据库设置 interaction_native_test=1,确认真实 WebView2 的 window.__TAURI_INTERNALS__ 和 window.__yg 存在。
|
||||
3. 执行 `node scripts/chat-interaction-native-check.mjs 9336 <用户私有输出目录>`。脚本拒绝没有隔离标记的数据库,使用受控本地模型服务、真实 Tauri IPC 和真实 OMP;只在隔离库创建测试渠道/会话,命令仅为 echo。
|
||||
4. 核查 result.json、原生截图、六档字体的 DOM 几何;截图等待入场动画完成。源码/模拟 IPC 回归作为补充,不代替原生验收。
|
||||
5. 关闭测试实例,移除进程级数据目录变量,以 9335 恢复正常库与原会话。
|
||||
|
||||
本次原生 WebView2 视口 1335×916、DPR 1,通过:完全访问下仍等待真实回答、选项回传、数据库重载、Other→editor 自由回答及单条记录、跳过、允许执行、拒绝不执行、取消与迟到回答隔离;六档字号均保持 40px 选项行、24px 卡片圆角,无卡片横向溢出。原生脚本汇总 7 项检查。测试数据与截图位于用户私有 `.ygent/imports/interaction-native-20261009/`,不提交。
|
||||
|
||||
辅助验证:`npm run check:chat`、`npm run build`;后端 `cargo test --lib -- --test-threads=1`。新增回归覆盖选项不自动提交、重复提交、失败重试、Other→editor 先于 IPC 确认且插入工具事件、答案持久化及过期问题重载。
|
||||
|
||||
## 回答后的展开体验补充
|
||||
|
||||
回答记录保留受回合控制的展开状态,内容使用 grid 高度与透明度过渡,收起后高度归零;减弱动态效果时取消动画。箭头常驻淡显并随展开旋转,键盘焦点可见,按钮关联详情区域且收起内容不暴露给读屏。问题浅灰、答案深色,跳过/取消补充明确结果,长文本换行且可选择复制,输入答案保持原始内容。
|
||||
|
||||
原生隔离验收在回答落库、重新打开会话、展开完整时间线后展开“提问”,测得卡片圆角 16px、内边距 12px 16px、问题/答案行高 25px/22px,内容宽度与滚动宽度均为 752px;再次收起详情高度为 0。证据为私有目录的 answer-expansion.json 与 question-answered-expanded.png;7 项真实 OMP 交互检查及 check:chat、TypeScript 检查通过。
|
||||
|
||||
### 按 Ygent 整体风格调整颜色
|
||||
|
||||
按用户后续要求,用户消息与历史问答卡不再使用 WorkBuddy 的实心中性灰底,改为共享聊天表面变量:用户气泡 68% 白色、历史问答 48% 白色,配 64% 白色内描边,透出页面蓝紫渐变。问题/答案分别使用全局 t2/t1,取消/跳过说明用 t3。此项属于用户指定的产品视觉调整,保留前述布局及交互。原生 1335×916、DPR 1 下只读检查真实会话,用户气泡和问答卡宽度/滚动宽度一致,截图位于私有 chat-color-20261009.png。
|
||||
@@ -0,0 +1,16 @@
|
||||
# 编辑消息与重新生成
|
||||
|
||||
2026-10-10:编辑并重发改为当前对话内重新生成,不创建新的 Ygent 对话。
|
||||
|
||||
- 保留 sessionId、项目归属和实际工作目录。编辑位置之前的消息不变;编辑消息及后续可见时间线由新回合替换。编辑提示说明替换范围。
|
||||
- OMP 先通过真实消息 entryId 回退内核历史,再原子更新当前对话的消息及内核文件指针。内核内部可能产生新的会话文件,该文件继续绑定原 Ygent 对话,不出现在侧栏作为新对话。映射/回退失败保留原时间线和编辑草稿。
|
||||
- 直连模式从回退后的消息重新组装请求;两种模式都不能把已经替换的消息或回复送给模型。
|
||||
- 替换前的消息与旧内核文件指针存入本机 `session_edits` 修订记录,当前未提供修订切换 UI。编辑不会撤销此前 Shell、文件、网络等已经产生的实际操作。
|
||||
- 删除被替换回合的待整理任务,清空过期上下文占用快照。消息 ID 使用持久高水位,避免删除后重复分配导致来源证据/工具事件串到新消息。失去有效证据的自动记忆沿用现有检索过滤规则。
|
||||
- 前端准备编辑期间禁止并发发送;等待取消屏障和消息写入结束。成功回退后清除本会话的终态回合缓存,再读取真实记录,避免旧回复在重载时复活。
|
||||
- 如果回退成功而新的发送未被接受,输入草稿保留,继续在原对话发送即可;旧时间线保存在本地修订记录。
|
||||
- 只有“分支到新聊天”入口才创建新的 Ygent 对话,继续沿用独立的分支逻辑。
|
||||
|
||||
验证:构建通过,Rust 83 项通过、1 项官方网络测试跳过;`npm run check:chat` 回归通过。
|
||||
|
||||
真实桌面 SOP:使用 `docs/ygent-debug.md` 的隔离数据库启动方式,数据中设置 `activity_test_mode=native-isolated`,运行 `node scripts/chat-edit-native-check.mjs 9336`。该脚本通过实际编辑按钮/输入框/发送按钮发起操作,使用真实 OMP 和直连、受控本机 SSE 上游,校验上游历史已回退、会话数不增加、前缀消息 ID 不变、标题/cwd 不变、重载无旧回复,以及显式分支仍创建新对话。不得对用户日常数据库运行该测试。
|
||||
@@ -0,0 +1,204 @@
|
||||
# 对话区动态交互对标与验收
|
||||
|
||||
> 阶段状态(2026-10-08):按用户要求,对话区在本阶段收尾,暂不继续修改。[当前进度汇总与剩余优先项](ygent-chat-stage-summary-2026-10-08.md)作为恢复入口。本文保留各批次证据;历史实现描述以后续修正为准,不能当作双端原生流式1:1已完成。
|
||||
|
||||
用户于 2026-10-08 明确:目标包括后续真实流式交互的效果一致,不仅是历史对话静态外观一致。本文件与 [原生渲染差异清单](ygent-workbuddy-render-audit-2026-10-08.md) 同时使用;静态修复不代表动态完成。
|
||||
|
||||
## 通用组件路径补查(2026-10-08)
|
||||
|
||||
后续品牌统一:按用户要求移除source_app驱动的助手名称/头像切换;所有会话统一显示Ygent及其图标。来源元数据仅用于数据溯源。
|
||||
|
||||
新增全会话入口核验:普通会话2(12条消息)与参照会话5(829条)在真实1335×916 WebView2切换比较,工具摘要共同命中15px/26.25px、rgba(0,0,0,.5)、border-left:0。source_app仅用于来源溯源,不选择独立对话渲染器,也不切换助手名称/头像。普通完成/多工具组与特殊取消仍有不同过程容器及间距规则,不据此宣称所有状态已对标完成。
|
||||
|
||||
路径标签通过共享Markdown代码组件实现:来源关联元数据用于参照快照,普通对话使用所属会话工作目录下的真实IPC批量分类;不存在的路径保持普通代码,迟到查询不会污染另一个会话/代码标签,增量追加保留路径控件。原生IPC核实普通会话可识别真实`.agent`目录并排除不存在的候选;同一参照标签`ygent`与WB均68.25×20、15px/22.5px、padding1px 4px,图标15×15。内部推理正文未导入,仅恢复有来源事件的“深度思考”标题;无内容不提供假的折叠交互。未来模型的公开思考摘要/阶段事件仍未接入。
|
||||
|
||||
“运行命令”上下样式遗漏修复后,继续检查同一组件在不同容器/阶段的路径。新增确认并修复4项:
|
||||
|
||||
| 位置/触发 | 问题 | 修复及验证 |
|
||||
| --- | --- | --- |
|
||||
| `TurnBlock`取消状态按钮 → `.turn-history` | 收起父层直接卸载历史,工具/意图展开状态和结果节点丢失;下方ProcessGroup已保留 | 历史首次展开后保持挂载,hidden隐藏。组件回归和真实1335×916 WebView2均验证结果节点与两级展开状态保留;还原操作前展开状态 |
|
||||
| `renderSegment`单工具 → 同段第二条工具增量 | ToolCard变成FoldGroup,第一条工具被重挂载,已打开详情关闭 | 单工具与多工具共用稳定FoldGroup边界,单条不显示组标题。组件回归检查节点身份和意图展开状态;未新增真实模型/WB流式验收结论 |
|
||||
| `FoldGroup`多个独立工具组 | 每组标题使用全回合toolCallCount,两个2条组均显示4 | 摘要仅计本组seg.items.length;两个工具组的组件回归通过 |
|
||||
| `getCancelledTurnLayout`含show_widget的末段 | 特殊取消布局把可视化工具传入ToolCard,绕过WidgetArtifact | 初次修复回退正常时间线;后续锚点分段保留产物/权限为独立visible段,不进入普通工具过程折叠;正常→取消及锚点布局回归确认iframe和权限操作仍存在 |
|
||||
|
||||
后续取消布局修复:工具摘要、意图/结果和工具组展开状态改由TurnBlock所属回合持有,以回合ID、消息ID及层级作为键;ToolCard/FoldGroup/ProcessGroup共享状态入口,跨父容器重新挂载时恢复原选择。自动折叠依据的上一次shouldFold/processExpanded也随组保存,普通增量或重新挂载不会再次覆盖手动选择;真正触发条件变化仍遵循现有自动折叠逻辑。回归覆盖多工具历史组和末段工具从流式→取消、手动打开组/详情、明确关闭另一条详情、取消后结果更新;全部通过。真实1335×916 WebView2的历史收起/重开仍通过。跨取消布局迁移的验证来自组件回归,没有向参考会话发送请求或注入状态,不声称双端原生动态验收完成。状态限定于当前回合组件生命周期,不写入数据库;迁移会重新创建DOM,此次未保证文字选择或结果面板滚动位置保持。
|
||||
|
||||
残留项:通用工具组与“过程消息”组的语义和箭头显示规则不同,不能直接统一所有行为。通用组的色彩、箭头方向及标题到内容的留白已按下节修正;摘要分类、子项间距、非命令工具取消时的图标语义仍待核实。
|
||||
|
||||
验证:`pnpm check:chat`、`node scripts/fe-check.mjs`、`pnpm build`通过。以上是路径一致性修复,未表示S04完整通过。
|
||||
|
||||
## 第一批动态P0实现结果(2026-10-08)
|
||||
|
||||
### 共用折叠样式与源码分组补查(2026-10-08)
|
||||
|
||||
依据当前安装的WorkBuddy产物`renderer/assets/lib-chat-ui-BAUBpUwu.js`中的`UJ`、`$Jn`、`tYn`及`lib-chat-ui-B-axvvx6.css`中的`_metaFold*_9ymy5_*`,仅分析渲染规则,没有读取或展开内部推理正文。以下明确区分源码证据和原生验收。
|
||||
|
||||
| 位置 | 本轮结果 / 下一步 |
|
||||
| --- | --- |
|
||||
| 通用多工具组标题`.mf-head` | 从蓝灰改为黑50%,字号仍使用六档统一变量,默认15px/26.25px。 |
|
||||
| 标题末尾`.mf-arrow` | 原来收起时向下、展开时向上且离开鼠标隐藏;现在收起向右,展开向下并保持可见。通用组SVG16×16、margin-left:-4px;“过程消息”保留自身12×12及始终向下规则。 |
|
||||
| 标题底→首个工具`.meta-fold > .mf-body` | 外层gap由8px改0,折叠体上下padding各2px。子项gap8px及相邻工具margin尚未对标,不将整个工具组间距标为完成。 |
|
||||
| 折叠后的可见正文`getTurnFoldLayout` | **完成/取消已共用锚点规则**:按trim后正文长度保留所有并列最长非空正文及最后正文,首个锚点前归历史、锚点之间归过程。不再要求至少三段或恰好两段可见正文;规则不依赖会话身份。双端动态折叠时机尚未完整验收。 |
|
||||
| 通用组摘要`FoldGroup` | **动作摘要文字已接入**:按动作分类、参数对象、相邻正文及状态生成摘要;离线与当前安装WB纯函数1760组对照一致。组头图标、推理事件参与分组及双端原生流式标题切换仍待补验;不把任意工具意图直接拼成摘要。 |
|
||||
|
||||
原生Ygent9335、1335×916、DPR1:会话5检测到130个通用组,本轮对首个组实测收起opacity0/rotate(-90deg),展开opacity1/transform:none,16×16、组gap0、body padding2px 0px,随后恢复展开状态及原会话。普通会话2没有通用多工具组,仅验证入口,不能算多工具验收通过。WorkBuddy9223当前可见区域没有通用MetaFold;展开两条已完成状态仍未出现该组件并已还原,此处通用组样式目标依据当前安装源码,尚缺同一通用组双端运行时对照。
|
||||
|
||||
验证:`pnpm check:chat`通过,覆盖增量、单→多工具、结束折叠、取消迁移及手动展开保留;没有向真实会话发送请求。原始源码和运行时记录保存在私有目录`.ygent/imports/render-audit-20261008`。
|
||||
|
||||
### 正文锚点分段实现与验收(2026-10-08)
|
||||
|
||||
本节记录最初取消回合实现;下节“完整时间线/摘要统一”取代仅打开前段历史的入口行为。
|
||||
|
||||
`CancelledTurnLayout`由固定firstReply/process/lastReply改为anchor/process/visible段序列;中间短正文与普通工具可共同进入过程折叠,多个最长锚点可产生多个过程组。权限和widget保留专用渲染器,位于过程之间时在原顺序显示,不当普通工具处理;历史首次展开后保留挂载。没有历史内容时显示静态取消状态,避免提供空历史折叠按钮。工具/意图展开选择仍由所属回合按稳定消息ID保存。
|
||||
|
||||
最后正文之后的真实工具保留在正文之后,不移到正文之前或丢失。WB源码`tYn`仅枚举锚点之前/之间的内容,本轮没有真实WB晚到工具事件对照,因此尾部事件策略仍待动态验收。既有导入快照中没有执行结果的占位调用保持不冒充已执行命令;数据库原消息不删除。权限/widget的折叠位置也需双端补验。
|
||||
|
||||
组件回归新增:最长在最前、并列最长(含前后空白)、单正文之前有工具、两正文之间有工具、空白正文、短正文夹在过程、widget/权限控件、末段之后真实工具顺序及导入无结果占位。原有运行→完成、运行→取消的组/工具/意图手动展开保留回归全部通过。
|
||||
|
||||
原生YG WebView2/CDP9335,1335×916、DPR1,真实参照会话5:目标取消回合保持2段可见正文、1个过程组;历史5段正文/5条工具、过程1条工具。父过程关闭隐藏结果面板、重开保留相同面板节点与意图展开状态、历史关闭保持挂载,3项通过,操作后恢复原会话及展开状态。记录为私有`anchor-layout-native-check.json`。未发送模型请求、未注入假数据;其他锚点排列来自组件回归,不能宣称已完成WorkBuddy双端流式验收。
|
||||
|
||||
### 完整时间线/摘要统一(2026-10-08)
|
||||
|
||||
`getTurnFoldLayout`不再限定取消状态。`TurnBlock`在回合结束后使用共用分段,运行中持续显示完整时间线;完成/取消状态按钮均切换完整时间线和锚点摘要,展开时不再只是补前段历史或强制打开所有工具组。无隐藏历史/过程时不提供无意义的整体展开按钮。待确认权限仍在时跳过整体折叠,保持操作可见。
|
||||
|
||||
依据当前WB源码`D5n`:整体折叠时渲染anchor/process,展开后恢复通常的内容/MetaFold段;不能把整体展开理解为每条工具详情都展开。Ygent完整时间线`.turn-history`和摘要`.turn-folded`互斥显示,首次挂载后以hidden保留节点;已在流式阶段挂载的时间线在完成后仍保留同一结果面板。两种呈现的工具/意图状态共享稳定消息ID;完成后的最终输出增量不会重置手动整体展开,摘要中的过程组选择也在整体往返后保留。新增`.folded-layout`统一终态布局样式,原`.cancelled-layout`不再作为专用呈现分支。
|
||||
|
||||
组件回归新增运行→完成的整体自动收起、完整时间线/结果节点身份、工具详情状态、最终输出更新、摘要过程展开及整体往返,完成/取消纯分段结果一致。`pnpm check:chat`及`pnpm build`通过。
|
||||
|
||||
原生YG9335、1335×916、DPR1:普通会话2的完成回合、会话5的完成/取消回合共3项样本,分别验证摘要与完整时间线互斥、关闭隐藏完整时间线、重开同一时间线与结果节点、意图状态保留,全部通过。会话5完成样本摘要1段/完整3段,取消样本摘要2段/完整7段;普通样本摘要/完整均1段,隐藏的是工具历史。证据私有`full-turn-fold-native-check.json`。WB9223同视口对“已完成11m33s”及“已取消4m28s”状态按钮往返,collapsed类正确切换并还原;本轮未获得可排除祖先裁剪/推理标记的可见正文计数,不据此宣称两端计数相等。
|
||||
|
||||
剩余:WorkBuddy活动回合资格/自动整体折叠触发时刻、模型底座真实流式终态、末段后事件策略、组头图标、组内间距及滚动锚点。工具动作摘要见下节。当前保留两种呈现的DOM会增加历史展开后的挂载量,超长会话性能待专门验收;不把节点保留直接等同于文字选择/滚动位置已通过。
|
||||
|
||||
### 工具动作摘要(2026-10-08)
|
||||
|
||||
`src/lib/toolSummary.ts`实现已安装WB的`mJn/IJn/VJn`规则,`toolSummaryRules.ts`记录40种动作及别名/简体中文词汇。对象按字段优先级在参数、嵌套结果、结果中查找;路径缩为末级名称、URL缩为主机名、中日文最多16字符、其他语言最多6词。命令不采用command内容作为摘要对象;同组动作聚合,混合组按数量取主要两阶段,有对象时优先对象、没有时使用经过前缀/后缀及泛词过滤的相邻正文主题;超过3类且没有主题时显示操作类别数量。未知工具使用“继续处理任务过程”,空摘要才走统计兜底。
|
||||
|
||||
运行中给可修饰摘要加“正在”,计划退出/提问按实际工具状态显示等待;全部取消保留取消状态。失败不再给动作标题追加“几个错误”,原toolError、失败图标、退出码和输出仍保留在工具层。`computeTurnFold`把本组摘要及后/前相邻正文交给通用`FoldGroup`;不同会话使用同一规则。标题单行,最大520px并以省略号裁剪,默认15px/26.25px且继续跟随六档字号。
|
||||
|
||||
验证分层:私有`summary-oracle-check.mjs`在离线隔离VM中仅执行安装产物的纯摘要函数(不执行整包、不读取内部推理),40种动作/别名、混合组合、完成/运行/取消、前后主题共1760组,与Ygent结果逐项一致。仓库`tool-summary-check.mjs`另覆盖命令正文排除、失败保留、未知动作、等待、URL、结果回退、非法增量JSON等17个场景;已纳入`pnpm check:chat`。组件回归确认“正在运行命令”→“运行命令”更新保留同一组头、手动展开及同一结果面板。
|
||||
|
||||
原生YG9335,1335×916、DPR1,真实会话5展开一条完整时间线后取3个组:6/5/18条工具对应README.md/App.tsx/lib.rs主题;实测15px/26.25px、max-width520px、ellipsis。折叠往返组头节点保留,通过;操作后还原原会话及状态。私有证据`tool-summary-native-check.json`。没有向参照会话发送请求或注入delta。纯函数一致不等同于真实WB原生流式标题切换通过,推理事件的组成员、组头图标、当前模型底座工具命名适配仍需单独补验。
|
||||
|
||||
S01、S02、S06的主链路已修改。以下为实现与验证状态,不表示双端WorkBuddy动态对照完成。
|
||||
|
||||
- `src/lib/chatRun.ts`按请求/稳定块ID管理正文;工具切开正文,后续文字创建新块。工具start/update/end原位合并,并行工具按创建顺序排列,空结果进入完成态。
|
||||
- SQLite先按块创建顺序插入,再原位更新;写队列合并尚未写出的增量。v9增加tool_state,保存完成/取消;启动时恢复中断工具。切会话缓存保留未落库的块,重载依据行顺序。保存失败提示用户并保留内存。
|
||||
- OMP用messageId:contentIndex定位正文,独立消费工具更新、保留完整输出;prompt_result.id关联提交命令。sessionSettled:false时保留绑定直到session_settled;同步本地命令依据agentInvoked:false结束。依据为项目内docs/reference/omp/rpc.md;旧版缺字段时使用单请求串行回退。
|
||||
- Codex用thread/turn/item ID定位,outputDelta追加、aggregatedOutput替换最终快照。记录已完成turn和OMP message归属,拒绝旧通知;进程代次隔离旧reader。
|
||||
- 两种底座和直连统一携带request_id/session;取消保留正文、终结工具及授权,关闭请求拒绝所有迟到事件。新请求等待取消IPC返回,OMP还须等待旧请求settled。ack超时不等于拒绝,保留绑定直到终态;没有终态时需恢复内核,不允许混叠发送。
|
||||
- 直连SSE按字节缓存完整行后解UTF-8,中文/emoji跨HTTP包不再被逐包lossy解码损坏。
|
||||
|
||||
验证:pnpm check:chat通过(组件/模拟IPC事件回归);cargo test --lib共16项通过(含完整输出、块ID、未settled阶段、数据库交错完成顺序、请求写入前取消)。pnpm build通过,既有bundle大小提示仍存在。
|
||||
|
||||
原生YG端到端:真实Rust/Tauri IPC/WebView2,1335×916、DPR1,独立数据目录、本机受控SSE。跨包中文/emoji、代码容器身份、内容落库、取消标记、新请求不混旧流、重载内容一致,6项通过。时间线记录时刻、pending、文字长度和滚动尺寸;私有证据在 `.ygent/imports/render-audit-20261008/native-stream-check.json`。HTTP模型服务是受控测试服务,未替换IPC;不声称真实OMP/Codex或WB动态过程通过。
|
||||
|
||||
[不含会话正文的验收结果与时间线](reference/workbuddy/stream-p0-2026-10-08.json)。
|
||||
|
||||
正式会话5(829条)未发送测试请求。隔离实例与SSE服务关闭,正常YG调试实例恢复9335。
|
||||
|
||||
剩余:WB的阶段序列/动画/自动展开策略,真实OMP/Codex原生验收,reasoning、单工具升级成组的双端原生动态验收、异步高度/滚动锚点、队列和操作栏。单工具升级的组件节点/展开状态回归已通过,不再列为未实现。崩溃恢复完整请求、保存失败自动重试、超大OMP分片协议尚未实现。
|
||||
|
||||
## 验收对象
|
||||
|
||||
同一输入、相同视口/字号/展开状态,比较两端从提交到结束的状态序列。模型输出内容和网络速度不同,不能据此要求每个 token 的墙钟时间一致;比较对应事件后的显示位置、块顺序、更新方式、折叠、滚动和操作反馈。具体动画时长、节流频率、自动展开策略须从当前 WorkBuddy 原生运行时取得,不凭旧产物或猜测设定。
|
||||
|
||||
不在参考历史会话内发送测试消息或执行工具。自动化回放应使用隔离测试会话和限定事件序列;组件回归及模拟事件只验证实现,不能作为两端真实流式验收。验收报告区分:源码确认、组件回归、YG原生实测、WB原生实测、双端对照通过。
|
||||
|
||||
## P0:先解决事件和渲染状态
|
||||
|
||||
| ID | 位置及触发序列 | 当前确认的问题/状态 | 通过条件 |
|
||||
| --- | --- | --- | --- |
|
||||
| S01 | `src/stores/chat.ts`,正文A → 工具开始 → 工具结束 → 正文B | `chunk` 都追加至 `streamingId` 的同一节点,未按正文块边界创建后续节点;旧快照的多个正文块不证明真实流式正确 | A、工具、B保持事件顺序,各块ID稳定;持久化/重载保持该顺序,无复制或丢字 |
|
||||
| S02 | `src-tauri/src/sidecar/omp.rs` → `src/stores/chat.ts`,工具 start → 多次 update → end | OMP update 被归为 start/done,没有独立 update 映射;前端类型虽有 update,分支未消费;可能创建重复卡或过早完成。OMP结果还截为300字符 | 相同工具ID原位更新;进度更新不表示结束、不新增卡;完整输出保留,成功/失败/空输出正确 |
|
||||
| S03 | `src/components/Markdown.tsx`,未闭合代码块持续追加,最后闭合 | 已去除随文本长度变化的key,并更新表格引用闭包依赖;组件回归通过。当前WB增量解析、动画、节流仍待实测 | 增量不重挂载稳定容器;复制/选择/横滚不被清空;未闭合围栏、表格、公式、mermaid的中间态按WB逐项验收 |
|
||||
| S04 | `src/lib/turnFold.ts`、`TurnBlock.tsx`,工具1 → 工具2 → 后续正文 → 回合结束 | 单→多工具、终态折叠、完整/摘要往返、手动展开及节点保留已有回归;动作摘要纯函数1760组对照一致。组头图标、DOM选择/横滚、WB自动折叠时机及双端原生流式摘要仍待核实 | 自动折叠触发与WB一致;用户手动展开不被无关delta打回;组形态变化不丢内部状态;统计仅算本组,不用全回合计数 |
|
||||
| S05 | `ChatView.tsx:269`附近,贴底 → 增量变高、上翻 → 增量变高 | 仅监听messages/atBottom;异步公式、widget及子组件展开引起的高度变化未统一处理,40px跟随阈值未与当前WB核对 | 贴底跟随;主动上翻不被拉回;回底重新跟随;展开/图片加载/字体变化不误判用户离底;记录scrollTop、scrollHeight、阅读锚点 |
|
||||
| S06 | `chat.ts`的事件监听与全局streamSid/streamingId,取消 → 迟到事件 → 新请求 | chunk/done/error缺少一致的请求身份过滤;工具事件未在取消后统一终结;任务切换时只有单套全局缓冲 | 取消即时停止,已有内容保留;迟到事件不污染新回合;未完成工具有明确终态;切会话不混流;恢复历史与即时显示一致 |
|
||||
| S07 | 思考、首字等待、耗时、停止按钮及错误入口 | YG有等待动效、光标和pending按钮,但未取得WB对应动态序列;reasoning数据类型未接入 | 首字前、思考中、文字中、工具中、完成、错误、取消每一阶段的可见元素与参考一致;不伪造推理正文/模型/消耗 |
|
||||
|
||||
S01、S02、S06先于进一步像素微调;上表保留修复前基线,主链路结果见本文开头,双端动态证据尚未取得的部分仍未完成。
|
||||
|
||||
## 当前已验证的局部交互
|
||||
|
||||
- `ProcessGroup`:过程、运行命令、意图、结果四层。意图独立折叠;关闭工具或过程再打开,保留意图和结果状态;第一次打开前不创建结果DOM,打开后隐藏而不卸载。
|
||||
- 真实YG WebView2 CDP9335、1335×916、DPR1、默认2档、真实会话5:意图关闭仅隐藏结果、工具往返保留意图、父过程关闭隐藏子层、父过程往返保留子层、结果节点身份稳定,5项均通过。
|
||||
- 当前WB参考回合:同条件的状态dy36.5、过程dy140.25、运行命令dy168.5、意图dy198.75、面板dy227.25,与YG一致;面板752×198.75。此处只验证已有回合和折叠交互,不代表生成中策略一致。
|
||||
- `node scripts/chat-render-check.mjs`:增量Markdown保留代码容器和复制按钮;嵌套折叠往返;结果更新原位保留;多工具组运行→结束自动折叠→手动重开保留状态。脚本为组件测试,使用合成数据、无CSS、不调用后端。jsdom优先读取项目安装,未安装时沿用现有fe-check的本机workspace回退路径;跨机器需自行提供jsdom。
|
||||
|
||||
## 执行顺序
|
||||
|
||||
1. 获取当前WB流式事件到DOM的映射及时间序列,补齐未知策略;同时修YG的正文分块、工具update和请求身份过滤。实现需以稳定turn/block/tool ID为依据,不能靠历史样本最后两段的排列模拟实时状态。
|
||||
2. 建立隔离、可重复的事件回放回归:逐字与批量delta、交错工具、并行工具、空输出、错误、取消、迟到事件、切会话和重载;验证内存和数据库都保持顺序、内容和终态。
|
||||
3. 用真实原生YG与WB执行受控交互,采集MutationObserver时间线、节点身份/rect、折叠状态、滚动量及必要的短录屏。比较事件后的阶段效果,组件回放通过后仍须原生验收。
|
||||
4. 再收敛动画、图标、回合操作栏和布局细节;每次结构调整复测流式/滚动/取消,避免为历史静态画面破坏实时行为。
|
||||
|
||||
## 必测序列
|
||||
|
||||
| 序列 | 必须记录的阶段与位置 |
|
||||
| --- | --- |
|
||||
| 发送与首字 | 输入草稿清理、用户气泡出现、助手等待、停止按钮、首字替换等待 |
|
||||
| 正文流式 | 短delta、跨行、代码围栏半截、表格半行、公式、mermaid;正文尾部光标、布局跳动与已完成块节点身份 |
|
||||
| 工具流式 | start/update/end、空结果、失败、两工具交错;摘要/意图/结果每层可见性、图标状态及输出累计方式 |
|
||||
| 折叠 | 单工具升级为组、出现后续正文、done自动收起、手动展开后继续delta、父层关闭再打开 |
|
||||
| 滚动 | 底部跟随、上翻不跟随、回底、展开变高、图片/widget/字体异步变高 |
|
||||
| 结束与恢复 | 正常完成、停止、失败、重试、切会话、应用重启;耗时、操作栏、按钮终态、消息数量/顺序/内容 |
|
||||
|
||||
完成定义:这些序列获得双端原生对照证据,未验证项为零;当前静态清单中已修复项目不计作动态验收通过。
|
||||
|
||||
## 2026-10-08:生成过程工具列表刷屏修复
|
||||
|
||||
真实原生 Ygent 的 hello 会话在生成时连续展示 45 次 read/grep/todo 调用,正文尚未出现时工具组一直展开。用户确认优先问题是生成过程被工具列表刷屏。本次将连续两个及以上工具调用默认收成动作摘要和数量;生成中额外显示正在执行的工具动作,没有运行工具时显示“正在思考”。这行提示不带转圈图标,“正在思考”文字使用从左到右的扫光,减少动态效果设置下使用静态文字。单个工具不增加分组层级。已知工具使用共享中文动作/对象摘要,长标签省略显示。
|
||||
|
||||
组和工具详情仍使用所属回合的稳定消息 ID 保存展开选择。手动展开、收起不会被普通增量或完成事件重置;单工具升级为组时,用户已打开的结果也保留。消息数据和结果没有删除,点击摘要可查看全部调用。
|
||||
|
||||
活动提示进一步统一:原首字等待的三个圆点和“正在思考…”已移除。首字等待与工具间隙共用回合底部的 Thinking 组件,每回合最多一处活动提示,且不依赖工具组是否展开。“正在思考”四字使用 2.2 秒循环的逐字扫光/上浮,每字错开 0.14 秒,上浮最大 1px;执行工具时短动作前缀扫光(命令显示“正在执行命令”),对象文字静态。正文正在流式输出时沿用尾部光标,权限待确认时不显示思考提示,完成/取消/失败终态移除活动提示。减少动态效果下取消动画。
|
||||
|
||||
此次新增回归覆盖空正文与工具同时存在时提示去重、单工具执行、组展开保留活动提示、正文/授权/终态切换。原生 WebView2 辅助挂载组件检查实际字号、动画关键帧、逐字延迟、静态文件名、展开状态与提示数量,结果通过;未修改真实会话/IPC,也没有发送新的模型请求。证据为私有 activity-check.json。完整 check:chat、类型检查和构建通过;不将辅助挂载结果当作真实 OMP 流式端到端验收。
|
||||
|
||||
随后修复单工具升级为多工具组时的瞬时展开:原实现沿用单工具 open 状态渲染组头及列表,再由 useEffect 自动收起;现在分组策略变化时在本次渲染直接计算正确 open,effect 只同步持久状态。用户主动展开及已打开的子详情仍保留。组件与原生 WebView2 辅助 MutationObserver 回归检查升级过程没有出现组头 aria-expanded=true 后又自动收回的瞬态;真实用户刚才的瞬态没有录制,不能断言只存在这一种原因。私有证据为 flash-check.json。
|
||||
|
||||
按用户对动效质感的反馈,活动提示最终改为稳定文字和柔和整行扫光:取消逐字拆分、上浮和蓝色高光,使用次级灰色到弱化灰色的渐变,3秒一轮;12%前和72%后保持静止,光带连续从左到右经过整段动作文字。思考和工具动作共用同一效果,对象仍静态。原生 WebView2 辅助样式采样确认整个周期文字坐标、宽高稳定、无 transform,动画时长3秒且保留停顿;证据为私有 soft-shimmer.json。组件回归、类型检查和差异检查通过,未发送真实模型请求。
|
||||
|
||||
用户继续反馈思考上方闪出工具行/列表,补齐另一处切换策略:第一条实时工具原先直接展示 ToolCard,第二条才升级摘要。现生成中的单工具也直接使用摘要入口,后续增量复用同一组头节点,避免独立工具行先出现又被收回;本次运行中建立的摘要在完成后保留。已存在且未经过实时显示的历史单工具仍使用原来的直接工具卡。手动展开和取消布局迁移保持原行为。组件及原生 WebView2 辅助检查验证首条工具无独立工具行、1→2组头节点稳定、没有瞬时展开;未发送新真实模型请求。临时只读 flash audit 仅记录当前页面的状态/尺寸/类型,保存在页面内存,不采集正文。
|
||||
|
||||
首字衔接试验(已撤回,以下仅保留阶段记录):空的最新流式回复在自己的 ReplyText 容器中显示“正在思考”,首字到达后同一容器立即渲染原始 Markdown,同时进行120ms交叉淡入淡出;思考残影绝对定位、对辅助技术隐藏、不占第二行。后续 delta 不重新入场、不延迟正文、不模拟逐字播放。无空回复占位的等待及执行工具仍沿用原活动提示,工具分组/状态/存储/滚动代码未修改;历史已存在正文不新增入场动画,减少动态效果时直接切换。
|
||||
|
||||
组件回归验证首字前后容器稳定、增量代码节点保留、残影清理、后续增量不重播;既有发送/权限/工具分组/完成/取消回归通过。原生 WebView2 辅助采样确认等待与首段正文起点同为y=156.5,首段文字立即可读,后续段落节点稳定且动画停止;证据为私有 reply-handoff.json。没有发送新的真实模型请求,真实长回合滚动及双端动态对照仍待验收。
|
||||
|
||||
### 当前有效规则:整个生成期间固定播报
|
||||
|
||||
用户明确期望是“正在思考”后面像字幕一样过流式内容,并在整个生成期间保留。已撤回 ReplyText 淡出替换及相关 CSS,恢复原来的正文 Markdown 渲染。新增独立 StreamingActivity 展示层,放在助手回合正文上方;左侧固定思考扫光,右侧将该回合正文纯文本及工具动作按消息顺序组合为单行播报,隐藏代码围栏正文/表格行及 Markdown 标记。短内容直接显示,超长内容左移,达到已收内容末尾后停止且保留,新增内容继续推进;展开工具、正文输出和等待授权都不移除栏,授权提示在右侧说明。结束后移除栏,沿用原来的完成/取消/失败呈现。
|
||||
|
||||
播报只保留最近4000字符作为视觉缓冲,速度80~320px/s,过多积压跳到距末尾约两屏的位置;截掉旧内容时继续靠近新内容。减少动态效果下直接显示末尾;尺寸变化重新检查溢出,组件卸载清理 RAF/ResizeObserver/媒体监听。右侧不加入逐字辅助技术播报,避免与正常正文重复。工具分组和展开状态、发送/事件/数据库、正文流式速度与滚动逻辑未改动。
|
||||
|
||||
完整 check:chat 和类型检查通过;组件回归验证左侧持续挂载、正文增量独立更新、间隙保留内容、工具展开和授权不消失、终态移除。原生 WebView2 辅助播报测试验证 scrollLeft 连续增长、追到末尾后保持不动、新增内容恢复移动、栏和正文节点保留以及正文立即完整显示;证据为私有 broadcast-check.json。没有发送新的真实模型请求,真实长回合的阅读/滚动体验与双端动态对照仍待验收。
|
||||
|
||||
用户指出上述动作/文件名摘要仍经过整理,现播报数据源改为当前消息事件的原始字段:agent.text、工具 fn/toolArgs/toolIntent/result、权限 text,按消息顺序以换行连接。撤掉 summarizeTools、文件名缩短、Markdown 清理和代码/表格替代文字;显示区域仍为单行,所以换行仅作为视觉空白,DOM文本保留原始换行。最近4000字符的视觉缓冲、固定思考标签、暂停/续播机制和正常正文/工具卡均不变。“原始”限于现有接入事件的内容字段,不宣称接入网络协议帧或模型隐藏推理。组件回归及原生 WebView2 辅助检查确认代码围栏、完整路径、JSON参数和工具输出逐字保留,证据为私有 raw-broadcast-check.json;没有发送新的模型请求。
|
||||
|
||||
随后按用户要求缩短可见播报窗口:最大18em(当前字号实测270px),滚动速度改为240~720px/s,仅提高视觉播放速度,不改变模型输出速度或原始内容。原生辅助检查300ms内scrollLeft推进144px,完整参数仍保留;私有证据为 fast-broadcast-check.json,类型及差异检查通过。
|
||||
|
||||
位置及运行耗时修正:播报栏已从回合顶部移回正常正文/工具时间线下方,生成期间持续保留。助手头像/名称下方的既有状态位置新增“进行中+耗时”,使用本回合 startedAt(缺失时使用首条事件时间),独立组件每秒更新,流式暂停也计时;终态卸载定时器并保留原有完成/取消耗时逻辑。组件回归验证无delta时计时推进、播报位于时间线之后、终态不残留计时器组件;原生 WebView2 辅助检查确认status位于头像下方、播报位于history下方、25s→26s推进以及取消后保持“已取消25s”,私有证据为 live-time-check.json。未发送新的真实模型请求。
|
||||
|
||||
### 运行状态文案参考 WorkBuddy
|
||||
|
||||
当前安装的 WorkBuddy 5.7.6 产物 zh-cn-CEs_4LQ3.js 的 progress.phase.* 定义了“准备中”“等待模型响应”“生成回复中”“处理结果中”“调用工具中”及分工具动作、“等待授权”“等待回复”“重试中”等。workbuddy-provider-cuZEv46I.js 的 nu 根据 phase/toolName/streamingToolName/pendingInputKind 选择对应文案;这些状态来自事件,而不是耗时阈值。原生当前页面只处于终态“已完成6s”,未发送WorkBuddy请求采集这些阶段的实时序列。
|
||||
|
||||
Ygent 新增 liveTurnStatus,共享同一耗时位置,根据可观测消息状态切换:空回复或工具结束后等待后续事件为“等待模型响应”,最新正文正在streaming为“生成回复中”,running工具优先显示“正在读取文件/列出目录/写入文件/编辑文件/搜索文件/搜索内容/执行命令”,未知工具为“调用工具中”,pending权限优先为“等待授权”。文案参考WorkBuddy,但分类映射使用Ygent/OMP工具别名。耗时仍为本回合总耗时,不因阶段变化清零;底部固定思考/原始播报规则不变。
|
||||
|
||||
目前没有可靠事件区分准备、模型工具参数生成、重试、模型结束后的处理/快照同步,故没有伪造这些状态。用户问题/计划退出工具采用“等待用户确认”,更细的授权类型需额外事件字段;不能仅由参数文字猜测。组件回归与原生 WebView2 辅助检查覆盖等待→正文→读取→命令→再次等待→授权、同一播报节点和耗时保留;证据为私有 status-phases-check.json 和本机 asar 源码片段,check:chat与类型检查通过。尚不宣称双端原生状态序列已完成1:1验收。
|
||||
|
||||
验收:真实 Tauri WebView2 CDP 9335、1335×916、DPR 1,会话 7 的 45 次工具调用在完成后折叠为 26.25px 高的摘要行;展开后显示中文动作,再收起正常。组件回归覆盖 45→46 次调用、当前动作、节点身份、详情保留、手动收起与终态;npm run check:chat 和 npm run build 通过。此次没有发送新的真实 OMP 请求,生成中策略由组件增量回归验证,不能据此宣称双端原生流式对标全部完成。真实截图和 DOM 证据保存在用户私有 .ygent/imports/hello-layout-20261008/,不提交会话内容。
|
||||
## 回复操作栏(2026-10-08)
|
||||
|
||||
已结束的助手回合底部统一显示复制、分支到新聊天和回复模型。复制整个回合的回复正文,沿用已复制/复制失败反馈。分支包含所选回合最后一条助手回复及其之前的上下文,不包含后续消息;OMP 使用原生 fork 和真实会话文件,直连使用数据库上下文。生成期间不显示该操作栏,生成中禁用其他回复的分支操作。
|
||||
|
||||
模型在请求开始时记录并随消息持久化,历史未记录的模型显示“模型未记录”,不使用当前选择冒充。回复时间紧跟模型名称,间距 10px;悬停助手回复区域或键盘聚焦操作栏时显示,提示中包含完整日期时间。
|
||||
|
||||
验证:组件回归覆盖整回合复制、复制反馈、末条回复分支、历史模型缺失和生成期间隐藏;Rust 回归覆盖包含助手回复的分支边界、元数据保留、重复文本与活动路径映射。类型检查、check:chat、Rust 25 项测试与前后端构建通过。真实 Tauri WebView2 9335(1335×916)使用临时受控 OMP 转录文件验证原生 fork、数据库前缀复制、模型元数据读写、时间位置和显隐;测试会话已删除,原会话未发送模型请求。这是原生分支/渲染验收,不代表真实模型流式或 WorkBuddy 双端对照已完成。
|
||||
|
||||
|
||||
## UI 优化回归补充(2026-10-10)
|
||||
|
||||
原生受控 Responses 回归发现等待空块在 text-end 被移除、首个工具事件尚未到达时,回合会短暂消失;首条消息 ID 随之变化也会重建整个回合。展示 key 现使用前置用户消息 ID;运行中最后一行只有用户消息时保留同一空回合,工具/正文按实际事件到达,展开作用域也使用稳定回合身份。无用户消息的历史回合仍使用原事件 ID。
|
||||
|
||||
真实 WebView2 + 实际 OMP 验证思考、参数、工具和正文之间播报节点保持身份、26.25px 状态行高稳定;原生滚轮上滚后不抢回阅读位置。完成、取消、HTTP 400 失败均清除播报;思考增量不写入历史。脚本 `scripts/chat-activity-native-check.mjs`,私有证据 `.ygent/imports/ui-final-20261010/stream-final/`。本轮也验证了问题选项键盘移动不提交、Enter 回传精确选项、回答重载/展开及授权拒绝/取消;不是 WorkBuddy 双端实时序列的全量 1:1 验收。
|
||||
@@ -0,0 +1,162 @@
|
||||
# Ygent ↔ WorkBuddy 对话区对标清单
|
||||
|
||||
> 对话区于2026-10-08按用户要求阶段收尾。[最新阶段进度](ygent-chat-stage-summary-2026-10-08.md)汇总已实现、证据边界及剩余工作;本文路线图中的历史状态不能替代当前实现和双端动态验收。
|
||||
|
||||
> 用户要求包含后续流式交互效果一致。当前优先处理 [动态交互P0](ygent-chat-interaction-parity.md):正文分块、工具增量和取消/迟到事件。旧静态分析及下文路线图不能代替当前版本的双端动态验收。
|
||||
|
||||
> 最新原生验收依据:[2026-10-08精确渲染差异清单](ygent-workbuddy-render-audit-2026-10-08.md)。下文“已实现/可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 变更。内嵌浏览器、终端、富文档与来源区尚未完成,详见 [工作台进度](ygent-workbench-parity.md) |
|
||||
| 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.*`) | 商业化限流逻辑 |
|
||||
|
||||
---
|
||||
|
||||
## 建议的推进顺序
|
||||
|
||||
按「投入产出比」排(✅ = 已完成):
|
||||
|
||||
1. ✅ **工具折叠与时间线保序** —— 普通工具折叠,widget 作为独立段保持原位
|
||||
2. ✅ **mermaid + KaTeX** —— 均按需动态加载
|
||||
3. ✅ **工具改动 diff**(write/edit 卡)—— 使用工具帧 `args`
|
||||
4. ⚠️ **消息工具栏与 widget** —— 编辑后分支重发已接;仍需真实窗口截图核对 widget
|
||||
5. ⚠️ **消息编辑 + 回退**(接 `branch`/`fork`)—— 编辑重发已接;任意历史点回退与分支切换待做
|
||||
6. ⬜ **忙时排队**(接 `steer`/`follow_up`)—— **内核已验证可用,但前端有前置依赖,见下**
|
||||
7. ⬜ **对话内系统事件流**(压缩 / 模型切换 / 会话边界)—— 需要新概念,建议单独设计
|
||||
|
||||
### 第 6 项的前置依赖(实测发现)
|
||||
|
||||
内核侧**已经可用**。探测结果:流式进行中再发一条
|
||||
|
||||
```json
|
||||
{ "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` 的原始帧:
|
||||
|
||||
```json
|
||||
// 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 }
|
||||
```
|
||||
|
||||
由此得到三条:
|
||||
1. **`args` 可做代码 diff** —— `write` 有 `content`(整份新增),`edit` 有 `old_string`/`new_string`
|
||||
2. **`isError` 可准确区分成功/失败** —— 之前靠「result 是否为空」推断是错的(见 `toolState` 那次修复)
|
||||
3. **`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、积分、敏感保护、媒体生成)。**
|
||||
@@ -0,0 +1,98 @@
|
||||
# 对话区对标阶段进度(2026-10-08)
|
||||
|
||||
## 2026-10-09:删除对话确认浮层
|
||||
|
||||
通过 WorkBuddy 9223 CDP 打开真实会话菜单的「删除任务」,仅采集并取消,未删除会话。参考实际组件为 `wb-popconfirm`:无全屏遮罩,贴会话行右侧、8px 间隔及小箭头;宽 240px、内边距 16px、边框 #dedede、圆角 16px、两层轻阴影;标题 16px/24px、600 字重,说明 14px/22px、黑色 70% 透明度;正文与按钮区间隔 24px,按钮间距 12px、高 32px、圆角 8px,确认按钮 #e85c5c。
|
||||
|
||||
Ygent 删除入口改为共享的行锚定浮层,侧栏和项目列表均使用相同组件;空间不足时左右翻转及纵向避让,随滚动/尺寸变化更新定位。文案按真实能力显示「删除对话?」和「删除后,对话记录将被移除,且无法恢复。」,不照搬 WorkBuddy 的所有设备同步承诺;后台删除规则与工作目录保留行为不变。初始焦点放取消,支持 Escape、外部点击关闭、Tab 焦点循环及关闭后焦点恢复;提交期间禁用操作并防重复提交,失败保留浮层与原有错误提示。重命名入口保留原交互。
|
||||
|
||||
真实 Ygent WebView2 1335×916、DPR 1 实测浮层 240×166,文字/按钮尺寸、颜色、间距、边框与阴影匹配参考;WorkBuddy 视口为 1334×919、DPR 1,未为采集修改用户窗口。原生验证取消、Escape、焦点循环与恢复,未实际删除用户数据;构建通过。截图保存在用户私有目录 `~/.ygent/imports/session-delete-native.png`。提交中/失败保护通过实现审阅确认,本轮未触发真实删除请求。
|
||||
|
||||
## 2026-10-09:工具状态图标补齐
|
||||
|
||||
按当前本机 WorkBuddy 前端包的 `ToolHeader`、`ToolExpandable` 和工具图标注册表核对,Ygent 的 ToolCard 改为工具类型图标,不再将普通成功状态统一替换为绿色勾。读取、写入、命令、搜索、目录、网页、技能、计划、Agent、浏览器和通用工具采用核实的向量路径;Ygent 内置任务/浏览器/技能及 OMP 别名映射到对应类别。
|
||||
|
||||
图标为 14×14,中性灰;失败/取消使用参考组件的灰色感叹号。命令外层摘要保留终端图标,意图层显示异常标记。执行中普通工具隐藏图标,文字采用参考组件 2.2 秒扫光;写入工具保留图标并以 1.2 秒周期改变透明度,减少动态效果时静态显示。成功、失败、取消的原始数据和输出保留,状态在可访问名称及悬停说明中区分。权限回执移除装饰性勾叉;下拉选中标记和复制反馈不受影响。
|
||||
|
||||
验证:构建及对话回归通过;组件矩阵覆盖 14 种工具/别名的完成、运行、失败、取消与手动展开保留。真实 Ygent WebView2 1335×916 下核验当前普通会话的浏览器成功与失败工具:SVG 几何匹配参考包,实际图标 14×14、颜色 rgba(0,0,0,0.5),无逐工具旋转图标。当前 WorkBuddy 页面没有工具行,本轮参考来自已安装源码与此前命令原生采集,未声称完成所有类别的 WorkBuddy 双端实时流式验收。原生证据保存在用户私有 imports 目录。
|
||||
|
||||
## 阶段状态
|
||||
|
||||
按用户要求,对话区工作在此阶段收尾,暂不继续修改。当前状态为:主要字体规则、工具呈现、折叠状态和流式事件管线已实现并分层验证;**尚未完成 WorkBuddy 双端原生流式 1:1 验收**。本页是恢复工作时的当前进度入口,详细证据与历史基线保留在关联文档中。
|
||||
|
||||
目标仍是流式交互效果一致,包括块顺序、工具增量、自动/手动折叠、滚动、完成/失败/取消和重载恢复。所有会话共用呈现规则,不能按会话标题、ID或导入身份修补。产品名称与头像统一为 Ygent;名称字体、头像尺寸和间距参考 WorkBuddy,品牌内容按用户要求保留 Ygent。
|
||||
|
||||
## 已完成的实现与验证范围
|
||||
|
||||
| 模块 | 当前实现 | 已取得的证据与边界 |
|
||||
| --- | --- | --- |
|
||||
| 调试与参照数据 | 原生 Tauri WebView2/CDP 调试、WorkBuddy CDP/打包源码分析、真实本地对话导入及元数据补齐 SOP;规则写入 AGENTS.md | 对话界面修改以真实 DOM、计算样式、几何及状态验收,截图作为补充。原始会话/源码采集保存在私有目录,不入库 |
|
||||
| 窗口与六档字体 | 对齐窗口基准1335×916;设置滑杆、快捷键和持久化共用六档;正文/UI采用不同缩放规则,名称、Markdown代码、终端代码分别管理字体族 | 两端默认及六档原生测量:108组字号/行高、18组几何对比一致。此为当时指定9个位置的结果,不能外推所有组件;本机系统字库依赖仍存在 |
|
||||
| 工具基础外观 | 历史、过程、实时回合共用 ToolCard;命令摘要/意图/输出分层,修正颜色、竖线、缩进、滚动条和长命令断行 | 同一失败命令的原生面板文本、换行及尺寸与WB匹配;失败摘要保留灰色终端图标,意图层有失败标记,输出保留非零退出码。其他工具类型状态图标尚未全面验收 |
|
||||
| 路径与阶段元数据 | 共用行内路径组件;普通会话通过真实IPC识别路径,导入会话补齐来源元数据;只恢复有来源事件的“深度思考”标题 | 参照路径标签几何匹配,普通真实目录可识别、不存在候选不变成链接;增量保留控件。路径实际打开的完整行为、文件图标和公开思考阶段仍待补验;内部推理正文未导入 |
|
||||
| 正文锚点与整体折叠 | 完成/取消共用“全部并列最长正文+最后正文”;中间短正文进入过程;整体展开显示完整时间线,权限/产物保留专用渲染器,末段后真实事件不挪到前面 | 组件覆盖最长位置、并列、一/两段、空白、混合过程、权限/widget及尾部工具。原生完成/取消3个样本验证完整/摘要互斥和节点/详情状态保留;WB自动折叠资格和时机尚未完整对照 |
|
||||
| 展开状态与增量稳定性 | 按回合/消息ID持有组、工具、意图状态;单工具升级为组保持边界;完整时间线与摘要首次挂载后隐藏而不卸载;普通增量不重置手动选择 | 运行→完成/取消、最终输出更新、父层往返、明确关闭的详情、代码容器/复制按钮/路径控件均有回归;原生历史样本往返通过。文字选择、面板滚动位置及超长会话性能不能据此算通过 |
|
||||
| 工具动作摘要 | 40种动作/别名按参数对象、动作组、相邻正文和状态生成标题;运行/等待/未知动作有对应文案,不把命令正文或工具意图任意拼成标题 | 与安装WB纯摘要函数离线对照1760组一致;17个独立语义场景及标题更新不重建节点回归通过;原生3组检查字号/省略与往返。组头图标、推理参与分组、底座命名适配和双端真实流式标题切换待验收 |
|
||||
| 流式事件与持久化 | 请求/会话/块/工具ID隔离;正文按工具边界分块,工具start/update/end原位合并;按创建顺序串行落库;取消拒绝迟到事件;SSE按完整字节行解码 | 组件/模拟IPC事件回归及先前16项Rust测试通过;YG真实Rust/Tauri/WebView2+隔离受控SSE的6项端到端检查通过。受控HTTP服务不是实际OMP/Codex模型,也不是WB双端动态验收 |
|
||||
|
||||
## 阶段末的验证记录
|
||||
|
||||
- 最新前端实现通过 `pnpm check:chat`,包含事件隔离、渲染/折叠保留及17个摘要语义场景;`pnpm build`通过,仍有既有大bundle提示。
|
||||
- `node scripts/fe-check.mjs`在整体折叠统一后通过;先前Rust16项测试和隔离SSE6项记录属于对应批次验证,没有在纯文档收尾时重复运行。
|
||||
- 原生对话实测以1335×916、DPR1、默认2档为主要条件,普通会话和导入参照会话均有检查。不同尺寸、所有消息类型、所有工具底座并未全面覆盖。
|
||||
- 正式参照会话没有发送测试请求;未替换真实IPC或向正式会话注入delta。原生历史往返、组件合成事件、离线源码对照和隔离SSE测试分别记录,不能互相替代。
|
||||
|
||||
私有证据目录为 `C:/Users/Administrator/.ygent/imports/render-audit-20261008/`,关键记录:`full-turn-fold-native-check.json`、`tool-summary-native-check.json`、`summary-oracle-check.mjs`、`native-stream-check.json`。其中早期`anchor-layout-native-check.json`对应仅展开前段历史的旧入口,当前整体入口已改为完整时间线/摘要切换;不能直接沿用旧选择器和计数验收新实现。
|
||||
|
||||
## 剩余工作及优先级
|
||||
|
||||
| 优先级 | 未完成项 | 下次验收位置/通过条件 |
|
||||
| --- | --- | --- |
|
||||
| P0 | 滚动跟随与阅读锚点(S05) | ChatView的messages/atBottom逻辑,以及展开、字体、图片、公式、widget异步变高;贴底跟随,上翻不拉回,回底恢复,记录scrollTop/scrollHeight及锚点 |
|
||||
| P0 | 自动折叠时机与活动回合资格(S04) | WorkBuddy活动/非活动回合、后续正文、完成/取消和尾部工具;按事件采集双端时间序列,不能只比较终态截图 |
|
||||
| P0 | 实际OMP/Codex与WB动态链路(S01/S02/S06) | 隔离会话中真实工具增量、并行、空结果、失败、取消、迟到、切会话、重载;核对正文/工具顺序、完整输出及落库恢复 |
|
||||
| P1 | 公开思考/等待/错误阶段(S07) | 接入有依据的公开阶段/摘要,检查首字前、工具中和终态的可见元素;不伪造内部推理、模型或消耗元数据 |
|
||||
| P1 | 组头图标、组成员与局部间距 | 通用摘要头图标、推理事件是否参与分组、非命令工具状态图标;组内gap、reasoning包装与段落间距分别测量,不硬补整段高度 |
|
||||
| P1 | 回合尾部与更多交互 | 产物入口/操作栏、代码/表格/widget中间态、搜索命中展开、队列、附件与@/技能候选等,区分已有入口和真正接通/验收的行为 |
|
||||
| P1 | 长会话与跨环境 | 完整/摘要保留DOM的挂载量、829条及更长会话性能,窗口/右栏变化、六档扩大覆盖、系统字库缺失回退 |
|
||||
|
||||
原精确差异清单中的40项渲染差异、4项外围差异、5项交互缺口和15个待验收场景是**修复前及指定采集范围的基线**,不是当前剩余数量。部分已修、部分有后续修正、部分未验收,不能据此计算“完成百分比”,也不能把当前所有差异都归为未修代码。
|
||||
|
||||
恢复时建议先选择隔离测试会话与同条件双端样本,更新原生基线/展开状态,再处理S05滚动及S04触发时机,随后补真实底座动态验收。任何新结构调整都复测增量、手动展开、取消、顺序和重载;正式参照会话继续保持只读测试原则。
|
||||
|
||||
## 文档入口
|
||||
|
||||
- [动态实现与逐项验收记录](ygent-chat-interaction-parity.md):S01—S07、各批次实现、原生证据与必测序列。
|
||||
- [原生渲染差异基线](ygent-workbuddy-render-audit-2026-10-08.md):逐位置坐标、字体、几何及历史D/C/V项。
|
||||
- [六档字体验收](ygent-font-parity.md):缩放规则、实际字库和测量结果。
|
||||
- [Ygent调试SOP](ygent-debug.md)、[WorkBuddy调试SOP](workbuddy-cdp.md)、[参照数据导入SOP](workbuddy-reference-import.md)。
|
||||
- [旧路线图](ygent-chat-parity.md)及[工具折叠源码参考](reference/workbuddy/chat-tool-fold.md):用于追溯设计,不替代本页当前状态和动态验收记录。
|
||||
|
||||
## 对话页面背景调整(2026-10-08 补充)
|
||||
|
||||
按用户后续要求,对话页面外层采用与侧栏、项目页相同的连续背景:移除 `.main-chat` 的整块白底,工作台区块与分享区移除外层分割线,分享区底色透明。输入框、用户消息气泡和代码块保留内容层级。本次是页面设计语言调整,不计作 WorkBuddy 白底的逐像素一致性验收。
|
||||
|
||||
通过真实 Tauri WebView2 / CDP 9335 在 1335×916 视口检查普通对话、工作台展开和分享模式。主区域与分享区 computed background 为透明,工作台分割线与分享区上边框为 0;退出分享后输入框正常恢复。采集保存到私有 `.ygent/imports/chat-surface-20261008/`。
|
||||
|
||||
|
||||
## 与新建任务页统一视觉(2026-10-08 补充)
|
||||
|
||||
按用户最新要求,对话页沿用新建任务页的品牌渐变背景;两处输入框共用半透明白色表面、16px 圆角、轻描边、柔和阴影与蓝色聚焦环,发送按钮统一品牌蓝。共享输入表面变量集中于 tokens.css,避免页面分别维护后再次出现差异。停止按钮保留独立语义与危险色悬停反馈。
|
||||
|
||||
对话仍采用适合连续阅读的正文宽度和底部输入布局。此次调整为产品视觉选择,不代表 WorkBuddy 静态或动态对标项目全部通过。原生 Tauri WebView2 在 1335×916、DPR 1 下检查新建任务、普通对话、829 条消息的历史会话、输入框聚焦及工作台展开;背景和输入表面计算样式一致,未出现窗口横向溢出。此次没有新增流式执行验收。证据位于用户私有目录 `.ygent/imports/chat-newtask-style-20261008/`。
|
||||
|
||||
|
||||
## 发送输入反馈修复(2026-10-08 补充)
|
||||
|
||||
原输入框在 await onSubmit/send 返回后才清空,因内核确认或直连流式 IPC 等待导致已发送正文长时间残留。共享 Composer 与新建任务输入改为提交后立即清空;拒绝或异常时恢复原文,若用户已输入新草稿则同时保留两段,成功回执不清除新草稿。提交中的按钮禁用,与同步锁共同避免重复发送。此次仅调整输入反馈,不缩短内核响应耗时,也不修改请求接受或失败判定。
|
||||
|
||||
验证:在原生 WebView2 中额外挂载辅助 Composer,用可控异步回执检查立即清空、成功保留新草稿、失败恢复且不覆盖新草稿、字符串拒绝恢复及重复提交禁用;没有替换真实 IPC,没有发送实际消息,不能视为真实内核端到端验收。证据为私有目录 `chat-newtask-style-20261008/send-check.json`。
|
||||
|
||||
|
||||
## 右侧工作台开始接入(2026-10-08)
|
||||
|
||||
以当前 WorkBuddy 的标签工作台重新梳理范围,已接入真实目录、文本预览及 Git 读取,不再把文件变更入口实现为跳回对话。详情、真实原生验收和未完成范围见 [工作台进度](ygent-workbench-parity.md)。内嵌浏览器、富文档、终端、引用来源及完整流式刷新验收仍待完成。
|
||||
|
||||
## 对话授权与问题回答(2026-10-09)
|
||||
|
||||
输入区浮动卡、紧凑历史问答、真实 OMP 选项/自由输入/跳过回传已接入。修复完全访问隐藏问题、问题被误当授权、Other→editor 重复记录与旧回执覆盖新状态。原生隔离链路 7 项及六档字号检查通过,批量多选与双端同场景动态验收仍待补充。详见 [实现与 SOP](ygent-chat-approval-questions.md)。
|
||||
@@ -0,0 +1,165 @@
|
||||
# SOP:Ygent 真实桌面 WebView2 调试与渲染采集
|
||||
|
||||
## 隔离动态链路验收
|
||||
|
||||
调试构建支持 `scripts/ygent-debug.ps1 -ReuseFrontend -Port 9336 -DataDirectory <绝对路径>`。
|
||||
独立SQLite和托管项目目录位于该目录;进程变量为YGENT_DEBUG_DATA_DIR,脚本退出恢复原环境,发布构建忽略该变量。安装实例正在执行任务时,可用 `-ReuseFrontend`、独立数据目录与空闲端口并行启动调试实例,不能停止安装实例或共享其数据目录。脚本拒绝重复调试实例与正常数据目录;完成后只关闭本次测试 PID 和测试服务,不用测试库覆盖正常库。
|
||||
|
||||
可用本机受控SSE验证真实Rust/Tauri IPC/WebView2并记录DOM时间线。该响应属于测试数据,结果仅表示YG端到端通过,不能称为WB或真实模型对照通过。序列见[动态清单](ygent-chat-interaction-parity.md)。
|
||||
|
||||
开发句柄window.__yg包含真实chat/session/settings/channel store和flushChatWrites。隔离测试使用同一运行时句柄;Vite HMR带时间戳模块与不带时间戳的动态import可能产生第二套store,不能误当当前UI。普通采集仍只读,不调用send/abort或修改设置。
|
||||
|
||||
辅助回归:`pnpm check:chat`;后端:`cargo test --lib --manifest-path src-tauri/Cargo.toml`。不代替原生验收。
|
||||
|
||||
### 原生普通回合的刷新恢复
|
||||
|
||||
1. 用真实 `agent_live` 读取普通与协作运行,包括启动预留、冻结模型和原用户消息;`collaboration_live`只覆盖协作,空数组不代表所有工作停止。
|
||||
2. 只读采集运行requestId、会话、最后持久消息ID与DOM。页面刷新后核对同一requestId、原正文前缀、工具详情及pending授权身份,等待真实新增量;刷新不是重新发送。
|
||||
3. `agent_replay`返回有序快照及水位,思考活动不进入持久历史。宿主在页面不在场时继续保存正文/工具,页面以hostRunId和稳定块键对齐持久行,不重复写入。
|
||||
4. 完成/取消后核对真实终态、消息不重复、工具消息ID及展开作用域保持;停止准确绑定requestId。程序退出再启动仅标中断,不能把刷新重接理解为自动重放副作用。
|
||||
5. 实际员工“继续”同时核对team_user_continuations、原team_dispatches/messageId与当前runId、当前合同版本及经理结果路由;不要用普通手动回合绕过派发。测试不得给正在执行的正常库注入事件或直接SQL改状态。
|
||||
|
||||
适用环境:Windows、Tauri 2、WebView2、Node 22+。默认 CDP 端口 9335,前端端口 1420。
|
||||
本流程连接真实桌面窗口,使用真实 Rust IPC 和数据库,不依赖 computer-use、模拟 IPC 或 fixture。
|
||||
|
||||
已于 2026-10-08 在本机验证:WebView2 154.0.4258.62、CDP 9335 回环监听、视口 1335×916、DPR 1;恢复真实会话 5 的 829 条消息,并成功生成 DOM/样式 JSON 与原生截图。Rust `cargo build --no-default-features` 通过。
|
||||
|
||||
## 1. 启动前检查
|
||||
|
||||
在项目根目录执行。常规同数据调试需保存输入框草稿并退出旧 Ygent;安装实例正在工作时,改用上方独立数据目录方式,禁止为验收停止它。
|
||||
旧实例启动后不能补开调试端口;如果由 `pnpm tauri dev` 启动,也结束旧开发终端中的命令。
|
||||
|
||||
```powershell
|
||||
Get-Process ygent -ErrorAction SilentlyContinue
|
||||
Get-NetTCPConnection -LocalPort 9335 -State Listen -ErrorAction SilentlyContinue
|
||||
```
|
||||
|
||||
启动脚本遇到旧实例或占用端口会报错,不会自动结束其他进程。
|
||||
|
||||
## 2. 调试模式运行
|
||||
|
||||
常规开发(编译 Rust、启动 Vite、打开桌面窗口,终端保持运行):
|
||||
|
||||
```powershell
|
||||
pnpm debug:desktop
|
||||
# 或指定其他空闲端口
|
||||
powershell -NoProfile -ExecutionPolicy Bypass -File scripts/ygent-debug.ps1 -Port 9336
|
||||
```
|
||||
|
||||
如果 localhost:1420 的 Vite 已经运行且已有最新调试版可执行文件:
|
||||
|
||||
```powershell
|
||||
powershell -NoProfile -ExecutionPolicy Bypass -File scripts/ygent-debug.ps1 -ReuseFrontend
|
||||
```
|
||||
|
||||
复用模式不会重新编译 Rust;修改 Rust 后先 `cargo build --manifest-path src-tauri/Cargo.toml`,再启动隔离实例,或在无运行任务时使用常规开发模式。
|
||||
脚本仅对启动子进程设置 `YGENT_DEBUG_PORT=9335`,随后恢复当前终端原值,不使用 setx 或注册表。
|
||||
Windows debug 构建读取此变量,通过 Tauri 的 `additional_browser_args` 传入 `--remote-debugging-port`,保留默认浏览器参数;release 构建不启用此入口。
|
||||
本机实测仅设置 `WEBVIEW2_ADDITIONAL_BROWSER_ARGUMENTS` 未开放端口,不能把环境变量设置成功视为已连通。
|
||||
机制参考:[Tauri 参数接口](https://docs.rs/tauri/latest/tauri/webview/struct.WebviewWindowBuilder.html#method.additional_browser_args)、[Microsoft WebView2 调试说明](https://learn.microsoft.com/en-us/microsoft-edge/webview2/how-to/debug-visual-studio-code)。
|
||||
|
||||
## 3. 确认连接的是原生窗口
|
||||
|
||||
```powershell
|
||||
Invoke-RestMethod http://127.0.0.1:9335/json/version | Select-Object Browser, 'Protocol-Version'
|
||||
Invoke-RestMethod http://127.0.0.1:9335/json/list | Select-Object id, title, type
|
||||
Get-NetTCPConnection -LocalPort 9335 -State Listen | Select-Object LocalAddress, OwningProcess
|
||||
```
|
||||
|
||||
验收条件:端口仅回环监听,目标为 localhost:1420 的 page,页面同时具有 `window.__TAURI_INTERNALS__` 和开发调试句柄 `window.__yg`。
|
||||
仅有 localhost URL 不足以证明是原生窗口;采集脚本会检查两项句柄,不符合时拒绝采集。
|
||||
9334 的独立 Edge 参照页面与此原生端口不同,不能混用验收结果。
|
||||
|
||||
## 4. 采集真实渲染
|
||||
|
||||
打开待验收会话,设置对应字号,定位到目标消息,展开待比对的过程行,等内容稳定后执行:
|
||||
|
||||
```powershell
|
||||
$ygSopCapture = Join-Path $env:USERPROFILE ('.ygent\imports\ygent-debug-' + (Get-Date -Format 'yyyyMMdd-HHmmss-fff'))
|
||||
node scripts/ygent-cdp.mjs "$ygSopCapture" 9335
|
||||
$ygSopSnapshot = Get-Content (Join-Path $ygSopCapture 'dom-styles.json') -Raw -Encoding utf8 | ConvertFrom-Json
|
||||
$ygSopSnapshot.viewport
|
||||
$ygSopSnapshot.state
|
||||
$ygSopSnapshot.samples | Where-Object selector -eq '.thread-content' | ConvertTo-Json -Depth 8
|
||||
```
|
||||
|
||||
输出 `connected: true`、`runtime: native-tauri-webview2`,保存:
|
||||
|
||||
| 文件 | 内容 |
|
||||
| --- | --- |
|
||||
| dom-styles.json | DOM/HTML、最终计算样式、元素矩形、滚动尺寸、视口/DPR、活动会话与消息数量摘要 |
|
||||
| ygent.png | 真实 WebView 当前视口截图 |
|
||||
|
||||
采集不读取 cookies、存储、密钥或完整 store,不改动页面状态。正文和截图仍包含真实会话,应保存在上述私有目录。
|
||||
DOM 与截图先后采集,不是原子快照;流式生成期间需注明时间差。
|
||||
|
||||
## 5. 深入调试与对标
|
||||
|
||||
可在 Edge 的 `edge://inspect` 配置 `localhost:9335`,选择 Ygent page 的 inspect,使用 Elements、Computed、Console、Sources、Network。
|
||||
Console 中只读查询示例:
|
||||
|
||||
```javascript
|
||||
getComputedStyle(document.querySelector('.thread-content')).maxWidth
|
||||
document.querySelector('.thread-content').getBoundingClientRect().toJSON()
|
||||
window.__yg.useSessionStore.getState().activeId
|
||||
window.__yg.useChatStore.getState().messages.length
|
||||
```
|
||||
|
||||
读取不存在的元素前先检查选择器命中情况;新建任务页面可能没有对话节点。
|
||||
对标 WorkBuddy 参照 [WorkBuddy CDP SOP](workbuddy-cdp.md)。记录同一会话、字号档位、窗口/视口、DPR、滚动位置及展开状态,先比较结构和计算样式,再检查截图。
|
||||
不使用 Emulation 修改原生视口来代替真实窗口尺寸,不把模拟 IPC 的页面当作原生验收。
|
||||
|
||||
## 6. 退出调试与排错
|
||||
|
||||
- 退出 Ygent,再用 `pnpm tauri dev` 普通启动即可关闭本次 CDP。若终端外部本来设置了 `YGENT_DEBUG_PORT`,先移除该变量。
|
||||
- 端口不响应:检查是否启动了旧实例、WebView2 是否继承启动参数、可执行文件是否存在;不要仅重启 Vite。
|
||||
- 无目标:确认 Vite 1420 和原生窗口均已加载;本采集脚本针对开发页面,不针对安装版 tauri.localhost。
|
||||
- 缺少 `__yg`:确认是 Vite 开发版;缺少 Tauri 句柄:确认没有连到独立浏览器。
|
||||
- 采集无对话节点:先在真实窗口打开目标任务,再采集,不注入数据掩盖问题。
|
||||
|
||||
## 7. 对话路径 → 右侧工作台(2026-10-10)
|
||||
|
||||
- 对话正文中已识别的目录/文件路径默认在右侧工作台打开,支持点击、Enter 和空格;目录直接定位,文件复用已有标签(统一 Windows 路径分隔符)。收起后再次点击会重新展开。
|
||||
- 目录浏览、文本与 Markdown 预览沿用当前对话实际工作目录边界,不因项目导航切换扩大范围。目录外路径显示读取拒绝;二进制文件显示不支持文本预览;均不自动调用系统应用。工作台“系统打开”是显式外部入口,目录标签打开当前浏览目录。
|
||||
- 会话切换清除待打开路径,工作台标签仍按会话挂载隔离,不向新会话重放上个会话的请求。未新增图片/PDF/Office 预览;文本仍限制前 1 MB。
|
||||
- 本机真实 Tauri WebView2、CDP 9336、视口 1335×916、DPR 1 验证通过:目录定位、两级返回到根目录、JSON 实际内容、重复点击及目录条目/正文路径共用文件标签、Markdown 渲染/源码、Enter/空格、收起重开、外部目录/文件拒绝、二进制预览错误、错误后恢复和跨会话隔离。采集了实际 DOM、计算样式及矩形:工作台 x=809.015625、y=46、宽=525.984375、高=870,display=flex。
|
||||
- 验收使用独立测试数据库,通过真实宿主 IPC 持久化受控路径消息,再操作真实 DOM;没有模拟/替换 IPC,没有验证真实模型流式输出。截图保存在用户私有目录 `~/.ygent/path-workbench-smoke.png`。未改动已安装客户端,未进行 Mac/Linux 验收,未触发系统打开按钮。
|
||||
- 类型检查 `node node_modules/typescript/bin/tsc --noEmit` 和 `node node_modules/vite/bin/vite.js build` 通过;构建仍提示大 chunk。本机 pnpm 入口遇到 esbuild 构建脚本审批错误,因此直接执行已安装的本地工具,未调整依赖审批设置。
|
||||
- 同时运行已安装客户端时,独立调试窗口首次启动出现 WebView2 HRESULT 0x8007139F;为调试子进程临时指定独立 `WEBVIEW2_USER_DATA_FOLDER` 后成功,不修改系统环境变量或发布配置。
|
||||
|
||||
|
||||
|
||||
## 并行隔离验收的 WebView2 配置(2026-10-10)
|
||||
|
||||
调试构建同时设置 `YGENT_DEBUG_PORT` 与绝对路径 `YGENT_DEBUG_DATA_DIR` 时,主界面 WebView2 使用该数据目录下的 `debug-main-webview`。子浏览器仍按项目/对话使用原有独立 profile;发布构建不启用这个分支。
|
||||
|
||||
不要用 `WEBVIEW2_USER_DATA_FOLDER` 隔离含内置浏览器的整进程:它会覆盖子 WebView 的目录,主界面与浏览器使用不同启动参数时,WebView2 可能报 `0x8007139F`。本轮已在真实子视图创建时复现。仅修改当前启动命令的环境,不永久设置系统变量。
|
||||
|
||||
需要与用户运行窗口并行验收时,使用独立数据目录和未占用端口;回归脚本先校验 `activity_test_mode=native-isolated`。窗口尺寸以实际 DOM 为准;Win32 缩放/恢复前校验窗口 PID、标题和句柄,只操作验收进程。测试结束关闭自身标签、回环服务和进程,保留用户窗口。
|
||||
|
||||
## 编译缓存与磁盘占用
|
||||
|
||||
开发与测试共用 `Cargo.toml` 的 dev 配置:`debug = 1`、`incremental = false`,第三方依赖 `debug = 0`。保留 Ygent 自身回溯的文件/行号,不保留完整变量调试信息;需要调试第三方 Rust 依赖时临时启用其符号。WebView2 的 CDP、DOM 与流式调试不受影响。release 配置独立。
|
||||
|
||||
关闭增量缓存以减少长期磁盘占用,代价是 Rust 代码重编译更慢;依赖编译产物仍由 Cargo 复用。切换 profile 设置后的首次编译会重建受影响的依赖,不代表每次都全量编译。
|
||||
|
||||
旧缓存不会随配置变更自动删除。无 cargo/rustc 构建进程时,可清理 `src-tauri/target/debug/` 下的 `incremental`、`deps`、`build`、`.fingerprint`;这些是可重建的中间文件。保留顶部可执行文件、运行资源、sidecar 和 release 分发产物。清理后首次开发编译和测试须重建依赖。若运行中或正在构建,先停止对应任务再清理,不能一边编译一边删除。
|
||||
|
||||
## 长历史对话打开卡顿(2026-10-13)
|
||||
|
||||
用户反馈从团队打开成员执行对话时整个页面短暂无响应。真实正常库的Rust成员对话约2,000条消息、正文/工具/参数合计约600万字符。通过9335的真实WebView2连接,在执行同一 `openSession` → `showView('chat')` 路径前开启CDP `Profiler.enable/start`,打开后等待首轮渲染,再 `Profiler.stop` 保存CPU profile;同时使用 `PerformanceObserver` 记录 `longtask`。这些探针仅导航、读取和测量,不发送模型消息、替换IPC或注入消息数据。
|
||||
|
||||
诊断必须分别记录会话/消息IPC等待、历史合并、Markdown解析、首次布局及滚动恢复,不能把Promise等待当成JavaScript计算。此次既捕捉到首次Markdown/布局的长任务,也出现过打开等待22秒而渲染线程主要空闲的情况。相关同步IPC在原生窗口线程取数据库锁和读取,不适合继续放在UI线程;具体22秒内的持锁方未捕获,不能宣称已经定位到某个后台工具。
|
||||
|
||||
实现:
|
||||
|
||||
- `HistoryTurn` 仅在历史接近滚动视口时首次挂载正式 `TurnBlock`,挂载后持续保留,滚动离开不重置手动展开。当前生成、未处理问题/授权、搜索、分享和明确定位的历史立即挂载。原始消息仍完整保留,历史不截断、不按会话特殊处理。
|
||||
- 共用Markdown高亮转换器的语言登记,避免每个段落重复注册全部语言;正文、代码、公式及工具仍使用原组件。已显现历史通过content-visibility跳过离屏布局和绘制。
|
||||
- 真实消息行按ID/运行建立索引,合并活跃协作和历史不逐消息扫描整个历史。恢复滚动保存消息锚点及相对偏移,历史挂载改变高度时按真实跟随状态处理,用户上滚不会被强行拉回底部。
|
||||
- 会话/消息读取、团队成员/工作台、协作列表及任务实际运行查询改用 `spawn_blocking`;保持原数据库、项目/运行身份和返回内容,读库等待不占原生窗口线程。运行标记包含真实恢复派发,不能由持久in_progress推断。
|
||||
|
||||
验证:TypeScript、Vite构建、聊天增量/渲染/工具摘要回归通过;新增长历史索引、历史可见性切换及工具展开保留、共享高亮跨块不串内容检查通过。运行标记Rust3项、团队恢复9项通过,调试版 `cargo rustc --bin ygent -- -C extra-filename=-chat-read` 编译通过;没有重复旧全量LSP测试来替代员工当前整改验收。
|
||||
|
||||
真实1335×916、DPR1下,前一阶段首次打开长任务524ms;按需挂载后同路径长任务60ms、DOM节点约4,848→1,016。滚动历史后重入的锚点偏差0.125px,回到底部间距0;原生复测中没有异常。该原生脚本选中的历史段未包含可展开工具,工具手动展开保留由组件回归证明,不能据空结果宣称原生工具验收通过。最初1.5–1.7秒采样发生在144×19的最小化视口,与正常窗口数据分别保留,不直接作同尺寸提速比例。
|
||||
|
||||
前端更新已在现有开发窗口生效。Rust修复已编译,当前PID1964仍为旧调试内核,未重启/替换、未部署安装目录;异步IPC和运行标记需切换新构建后原生复验。用户当前工作及主动取消不因性能修复重新派发。CPU profile、原生DOM/时间和检查日志只保存于私有 `~/.ygent/imports/employee-chat-*`,不提交会话内容。
|
||||
@@ -0,0 +1,47 @@
|
||||
# Ygent 字体渲染对齐与验收(2026-10-08)
|
||||
|
||||
本轮对齐真实字库、字号继承、六档管理、行高和用户文字行框。两端真实视口1335×916、DPR1;WorkBuddy9223、YG原生WebView2 9335,同一真实会话。通过真实键盘快捷键逐档变化,测试后两端恢复默认2档;没有替换IPC或模拟会话。
|
||||
|
||||
## 统一管理
|
||||
|
||||
- 六档Markdown根字号:16、17.143、18.286、20.571、22.857、26.286px。
|
||||
- 普通UI偏移:-1、0、1、2、2、2px;用户文字、输入、折叠标题、取消提示采用15px基准,即14、15、16、17、17、17px。
|
||||
- 正文通过Markdown根字号的`.875em`缩放;不要用UI封顶规则覆盖Markdown正文。
|
||||
- `--yg-font-sans`显式加入Noto Sans SC,匹配本机WorkBuddy真实中文字体;Latin仍使用Segoe UI。
|
||||
- `--yg-font-agent`遵循参照名称栈,本机实际命中Arial Bold。
|
||||
- `--yg-font-markdown-code`使用SFMono-Regular/Consolas/Liberation Mono/Menlo;终端使用独立`--yg-font-terminal`,本机实际命中Courier New、中文回退NSimSun。
|
||||
- 本机Noto Sans SC为已安装系统字库,本轮没有把字体文件复制进项目;其他机器若缺少字库会回退,不能声称跨机器字形已经保证一致。
|
||||
- 字号变化由设置与Ctrl+-/Ctrl++/Ctrl+0共用Zustand/SQLite链路。没有新增运行时样式表扫描,现有组件通过CSS变量显式接入,剩余裸字号已清理;新增组件遵守AGENTS约束。
|
||||
|
||||
## 内层文字与行框
|
||||
|
||||
用户气泡外壳保持13px基准,内层15px/1.75;p为1.78行高、1.78em最小高度,内容span垂直居中,对齐Slate混合中英文的实际行框。没有为了对标引入Slate或改变消息数据。
|
||||
|
||||
输入textarea实际文字15px/1.75;过程/工具组摘要15px/1.75;取消提示15px、固定20px行高。命令与结果拆成两块:命令12px/1.6,stdout/stderr固定18px行高,块间4px。UI偏移只应用字号一次,结果行高不随字号变化,这是参照实测规则。
|
||||
|
||||
设置界面只显示字号档位,移除Markdown像素数值。普通行内代码和Markdown代码块保持Consolas族,不能一并换成终端Courier New。
|
||||
|
||||
## 原生验证结果
|
||||
|
||||
[两端六档原始测量摘要](reference/workbuddy/font-parity-2026-10-08.json)仅含字号、行高、字体族和几何,不含对话正文或凭据。
|
||||
|
||||
| 验收项 | 结果 |
|
||||
| --- | --- |
|
||||
| 六档根字号 | 两端全部一致 |
|
||||
| 9个位置×6档×字号/行高 | 108组对比全部一致:助手名称、正文、用户编辑器、用户p、输入、过程标题、取消、命令、输出 |
|
||||
| 用户文字宽度、p实际高度、名称宽度 | 每项六档均一致,共18组几何对比 |
|
||||
| 实际命中字库 | 中文Noto Sans SC及Bold、名称Arial Bold、终端Courier New/NSimSun;平台字体接口确认 |
|
||||
| 默认用户气泡 | 外框355.15625×44.59375,与参照一致,未硬编码宽高 |
|
||||
| 设置滑杆 | 原生输入ArrowRight:2→3,根17.143→18.286;ArrowLeft恢复2 |
|
||||
| 调试版桌面重启 | 原会话5、829条消息恢复;默认档从真实设置恢复,窗口1335×916 |
|
||||
|
||||
以上不等于整个对话区1:1通过。工具意图独立折叠、reasoning占位、回合尾部操作栏、滚动条等仍以原差异清单为准;第三方widget iframe的自带字体不在本轮9位置验收内。
|
||||
|
||||
## 重复验收
|
||||
|
||||
按[原生调试SOP](ygent-debug.md)连接两端,确认同一字号和视口。可通过DevTools的Computed查看内层实际文字,DOM/CSS接口读取`CSS.getPlatformFontsForNode`确认字库。先Ctrl+0回默认,Ctrl+-到1档,再连续Ctrl++采集1—6档,最后恢复原档。设置测试使用真实滑杆,不直接写style模拟字号。
|
||||
|
||||
测试时保存草稿,不发送对话。先记录原档位,验证后恢复;本轮原档为2。更新差异状态时须保留原测量记录并说明已修范围,不能删除未修的结构问题。
|
||||
|
||||
|
||||
2026-10-08 视觉优化补充:按用户要求,工作台与对话的 Markdown 围栏代码共同使用根字号 0.8125em、行高 1.7,取代原 0.75em;表格使用 0.875em、行高 1.65。六档仍由同一根字号管理,终端字体不受该 Markdown 样式影响。此调整优先可读性,不再代表这两个行高/比例与 WorkBuddy 原始值完全一致。
|
||||
@@ -0,0 +1,58 @@
|
||||
# 模型编辑、模型选择与上下文状态
|
||||
|
||||
## 对标依据
|
||||
|
||||
2026-10-09 通过 WorkBuddy 5.7.6 的真实渲染页 CDP、DOM、计算样式和安装包资源确认,未使用 computer-use。原始会话及采集资源只保存在用户私有目录。
|
||||
|
||||
- 模型入口高 32px,图标 16px、箭头 14px;弹层宽 280px、最大高 368px、圆角 16px、内边距 8px。列表按渠道分组,组标题高 28px,模型行基准高 32px;选中标记、悬停、滚动和键盘操作共用一个列表。
|
||||
- 上下文入口位于模型入口左侧,点击区域 32px,圆环 16px、线宽 2px。用量面板宽 280px、内边距 16px、圆角 16px,包含百分比、token 用量、占用条与分类图例。
|
||||
- WorkBuddy 的付费、Max 等专有功能没有对应的 Ygent 功能,不能添加无效入口。模型图标采用随包本地 SVG(Lobe Icons 1.95.1,保留 MIT 许可),按 canonicalId 模型归属匹配;未识别元数据时仅按已知模型名前缀回退,未知模型显示通用图形。模型按钮及列表共用组件,客户端不访问图标 CDN。
|
||||
|
||||
## 已实现
|
||||
|
||||
模型编辑恢复输入上下文、输出上限的选项按钮。输入提供 32K/64K/128K/256K,输出提供 8K/16K/32K/64K;精确模型上限作为独立选项,超出模型上限的预设不可选。默认不展示数字输入框,点击“自定义”后才能输入;保留元数据默认值、逐字段覆盖与恢复自动能力。
|
||||
|
||||
补充:两组均提供 128K/256K/1M,token 档位使用十进制 K=1000、M=1000000。模型声明在 1000000–1050000 的窗口归入 1M 显示档,但选中与保存采用模型的精确上限(例如 1050000),悬停显示准确 token 数。128000 对应 128K,不再因按 1024 换算而被误判超限。已有精确数字不重算。
|
||||
|
||||
自动输出预算直接使用元数据声明的输出上限(例如 gpt-6-luna 为 128000),不再统一限制为 8192 或上下文的一半;保留每字段手动覆盖,仅元数据未声明输出上限时兜底 8192。配置允许输出上限等于上下文上限,实际请求仍校验输入加输出预留是否超限。
|
||||
|
||||
对话模型菜单改为单层渠道分组列表,选择真实模型后关闭;支持方向键、Enter、Escape、外部点击关闭和焦点返回。当前模型的原生思考选项及预算仍可设置,配置入口打开模型设置。新建任务和对话复用同一模型组件。
|
||||
|
||||
对话输入区增加上下文圆环、悬停说明及点击详情。切换会话会清空旧显示,生成期间及面板打开时每两秒刷新;查询不启动、不切换、不重启 Agent。
|
||||
|
||||
## 用量语义与边界
|
||||
|
||||
- OMP 总量:读取已绑定当前会话的 `get_state.data.contextUsage`,标注“内核当前上下文估计”。读取最长等待两秒,操作冲突或失败使用本会话持久化快照。
|
||||
- 直连:读取实际 SSE 的最近请求输入计数,标注“最近请求的输入用量”。支持 Chat Completions、Responses、Anthropic Messages、Gemini;Anthropic 包含缓存读取与写入输入。
|
||||
- 不把各轮 token 累加作为上下文占用,不把输出或账单总量当成输入。没有真实计数/窗口时显示“—”,不能用运行时兜底窗口伪装模型实际上限。
|
||||
- OMP 分类:随包观测扩展读取主 Agent 的实际 `context` 输入与 `before_provider_request` 最终工具声明,通过 OMP 分词器本地计数;不是分类 RPC,也不按内核总量分摊比例。分类与内核当前总量是独立快照,可能不相等。
|
||||
- 分类包含系统提示词(扣除已识别的技能目录)、工具及子智能体的声明/调用/返回、对话正文、MCP 声明/调用/返回、技能目录及按需读取的正文。只计算当前主 Agent 实际输入中可见的内容,不推断子 Agent 的私有上下文。停用技能或连接器后,仍在输入历史中的调用和返回继续计入原分类。
|
||||
- 面板显示各类估计 tokens 及其占请求时上下文窗口的比例;悬停可查看精确估计数、快照时间、模型和请求身份。无法识别名称的工具声明列入“未归类”,仅非零时显示;供应商协议封装及未公开的隐藏输入不伪装成已分类内容。
|
||||
- 精度按真实计数路径标注“模型分词器”、`o200k_base` 或“UTF-8字节估算”。后两者及本地分类都不能当作上游账单实测值;没有请求快照、直连尚无可靠分类来源时继续显示“— / 暂无分类统计”,不以零补齐缺失数据。
|
||||
- 分类每次实际准备模型请求时替换,不累加;按宿主会话/请求/原生会话文件校验后持久化。取消保留已准备输入,拒绝取消后的迟到帧;重载和总量刷新保留同一分类快照。旧历史不反推分类,更新后的 OMP 进程产生新请求后才会有新统计。
|
||||
- 快照按会话持久化;直连数值是最近请求观察值,不代表用户编辑历史后已经重新计算;新请求开始清除旧的直连观察值。
|
||||
|
||||
## 验收
|
||||
|
||||
2026-10-09:后端 `cargo test --lib --quiet` 69 项通过、1 项忽略,包含各协议输入计数、覆盖而非累加、缓存计数、会话隔离和 OMP 字段解析。`npm run build`、`npm run models:check`、`npm run check:chat` 通过。
|
||||
|
||||
原生验收使用隔离数据库与真实 Tauri IPC,脚本 `scripts/model-context-native-check.mjs`;上游仅使用本机受控 SSE 服务,不操作用户正常会话,不替换前端 IPC。Windows WebView2 视口 1335×916、DPR 1:编辑器选项/精确上限/自定义/恢复自动、模型列表位置和方向键焦点、上下文面板/Escape、两轮输入 1250→2750 替换而非累加、跨会话隔离及重载恢复均通过;六档字号下两种面板均宽 280px,无横向截断。模型选择使用真实按钮激活验收,未将 CDP 的 Enter 默认行为计为已通过。
|
||||
|
||||
截图和 DOM 证据位于用户私有目录 `C:/Users/Administrator/.ygent/imports/model-composer-20261009/native`。OMP 实际返回的窗口可能是内核可用窗口,不能强制等于模型元数据最大窗口;以实际 `contextUsage.contextWindow` 为准。本次只实测 Windows,未声称 Mac/Linux 通过。
|
||||
|
||||
### OMP 输入分类验收(2026-10-10)
|
||||
|
||||
隔离数据库、真实 Tauri IPC / WebView2、OMP 18.6.3;模型上游为本机受控 SSE,技能通过真实安装及按需读取接入,MCP 通过真实 stdio 握手、工具发现及独立宿主授权调用。未替换 IPC、未注入前端分类数据,不把受控上游当成真实供应商计费验收。Windows 视口 1335×916、DPR 1;其他平台未实测。
|
||||
|
||||
八项场景通过:无请求时分类未知;技能与 MCP 调用后五类均有真实输入计数;刷新总量不覆盖分类;六档字号下 280px 面板无横向溢出、Escape 关闭并返回焦点;未启动的第二会话查询不创建内核会话文件且不串分类;下一请求替换而非累加并保留历史技能/MCP 输入;运行及取消保留已准备输入;真实 WebView 重载恢复同一快照且不产生新模型请求。DOM、计算字号/行高、边界及滚动尺寸与截图同时采集。
|
||||
|
||||
本次分词路径为 UTF-8 字节估算:首次内核总量 8,935,独立分类合计 9,383;停用扩展后的新请求分类合计 8,857,取消回合 8,878,重载后保持不变。分类没有缩放为内核总量,也没有把旧快照累加到新快照。
|
||||
|
||||
后端 `cargo test --lib --quiet --manifest-path src-tauri/Cargo.toml`:119 项通过、1 项忽略,覆盖分类和校验、溢出、会话隔离、旧请求/取消身份拒绝;`npm run build` 与 `npm run check:chat` 通过。构建仍有已有的大 chunk 和 `knowledge::context` 未使用警告,未扩展本轮范围处理。
|
||||
|
||||
证据:用户私有目录 `C:/Users/Administrator/.ygent/imports/context-categories-native-C7mOTZ`,含 `result.json`、真实上游请求、六档 DOM/计算样式及第 1/6 档截图。隔离进程与本机服务已关闭;临时验收脚本不留在仓库。
|
||||
|
||||
|
||||
## 本地图标验收
|
||||
|
||||
2026-10-09:14 个品牌 SVG 在真实桌面 WebView2 中均完成解码,模型按钮与列表图标为 16×16px,资源均为本地/内联资源。未知归属回退和 GPT 模型名回退已验证;类型检查、构建及 diff 检查通过。截图与 DOM 位于私有目录 `C:/Users/Administrator/.ygent/imports/model-icons-20261009`。
|
||||
@@ -0,0 +1,205 @@
|
||||
# Ygent 富内容渲染设计(HTML 制品 / 流程图 / 公式)
|
||||
|
||||
> 状态:设计提案,待确认
|
||||
> 背景:`docs/reference/workbuddy/chat-tool-fold.md` 已摸清 WorkBuddy 的实现与安全边界
|
||||
> 本文只讨论「对话区要支持哪些内容类型、怎么安全地渲染、分几步做」
|
||||
|
||||
---
|
||||
|
||||
## 1. 现状盘点
|
||||
|
||||
| 内容类型 | WorkBuddy | Ygent 现状 | 差距 |
|
||||
|---|---|---|---|
|
||||
| 段落 / 列表 / 引用 | ✓ | ✓(remark-gfm) | — |
|
||||
| 表格 | ✓ | ✓ | — |
|
||||
| 代码块高亮 | ✓ Prism | ✓ highlight.js | 可接受 |
|
||||
| 代码 diff(改文件时) | ✓ `tool-diff` | ✗ | 见 §7 |
|
||||
| 图片 | ✓ | ✓(react-markdown 默认) | — |
|
||||
| **流程图 / 图表** | ✓ mermaid | **✗** | 需新增 |
|
||||
| **数学公式** | ✓ KaTeX | **✗** | 需新增 |
|
||||
| **HTML 制品** | ✓ sandbox iframe | **✗** | 需新增 |
|
||||
| 内联 SVG(消毒) | ✓ DOMPurify | ✗ | 低优先 |
|
||||
|
||||
Ygent 当前渲染管线:`remarkGfm` + `rehypeHighlight`,**无 `rehype-raw`**(即不渲染 Markdown 里的裸 HTML)——这一点与 WorkBuddy 一致,是安全基线,**不要为了省事打开它**。
|
||||
|
||||
---
|
||||
|
||||
## 2. 两条进入路径(关键决策)
|
||||
|
||||
富内容有两种进入对话的方式,**建议两条都做,但优先级不同**:
|
||||
|
||||
### 路径 A:Markdown 内联(模型天然会用)
|
||||
|
||||
模型输出 ```mermaid 代码块或 `$$…$$` 公式,由渲染管线识别。
|
||||
|
||||
- 优点:**零工具改动**。模型不需要被教会调用新工具,它在别处已经习惯了这套写法。
|
||||
- 证据:WorkBuddy 的 mermaid 就是这条路径——存在 i18n 键 `markdown.mermaid.rendering`(渲染中占位文案),说明是代码块触发而非工具产出。
|
||||
- 适用:mermaid、KaTeX
|
||||
|
||||
### 路径 B:工具产出制品
|
||||
|
||||
专用工具(如 `show_html`)返回一段 HTML,以「制品块」形式呈现,带独立查看器 UI。
|
||||
|
||||
- 优点:有明确的类型边界,可以配查看器(切代码 / 复制 / 下载 / 导出图片)与独立的安全边界。
|
||||
- 证据:WorkBuddy 的 `show_widget` 工具 + `SYn = {show_widget, visualize:show_widget, visualizer:show_widget}`,走 `<iframe sandbox="allow-scripts">`。
|
||||
- 适用:HTML 制品(交互式页面、可视化)
|
||||
|
||||
---
|
||||
|
||||
## 3. 各类型的渲染方案与安全边界
|
||||
|
||||
### 3.1 mermaid 流程图(路径 A)
|
||||
|
||||
```
|
||||
```mermaid
|
||||
flowchart LR
|
||||
A[用户] --> B[内核] --> C[结果]
|
||||
```
|
||||
```
|
||||
|
||||
渲染:` ```mermaid ` 代码块 → 动态加载 mermaid → `mermaid.render()` → 得到 SVG → **消毒** → 注入。
|
||||
|
||||
**消毒是必须的**,直接照抄 WorkBuddy 已验证的配置:
|
||||
|
||||
```js
|
||||
DOMPurify.sanitize(svg, {
|
||||
USE_PROFILES: { svg: true, svgFilters: true },
|
||||
FORBID_TAGS: ["script", "foreignObject"],
|
||||
FORBID_ATTR: ["srcdoc", "formaction"],
|
||||
});
|
||||
```
|
||||
|
||||
要点:
|
||||
- **只开 SVG profile**(不含 HTML profile)——消毒结果只能表达图形,带不了 `<a>`/`<form>`
|
||||
- **禁 `foreignObject`**:它能把 HTML 塞进 SVG 里绕过 SVG profile
|
||||
- 渲染中显示占位(对应 `markdown.mermaid.rendering` 那种文案),失败时**回退显示原始代码**而不是空白
|
||||
|
||||
### 3.2 数学公式(路径 A)
|
||||
|
||||
`$inline$` 与 `$$block$$` → remark-math + rehype-katex → KaTeX 产出 HTML。
|
||||
|
||||
KaTeX 的输入是公式文本、输出是受控 HTML,**不需要额外消毒**(与 WorkBuddy 一致)。
|
||||
|
||||
### 3.3 HTML 制品(路径 B)
|
||||
|
||||
```jsx
|
||||
<iframe sandbox="allow-scripts" srcDoc={html} title="交互制品" />
|
||||
```
|
||||
|
||||
**不带 `allow-same-origin` 是整个方案的核心**:制品里的 JS 能跑(图表要动),但因为源是 opaque origin ——
|
||||
读不到 `localStorage`、拿不到父窗口 DOM、发不出带 cookie 的请求。
|
||||
|
||||
已确认的前提:Ygent 的 `tauri.conf.json` 里 `"csp": null`,**不会拦 iframe srcdoc**。
|
||||
若将来收紧 CSP,需为 iframe 放行(或在制品 HTML 内自带 `<meta http-equiv="Content-Security-Policy">`)。
|
||||
|
||||
查看器能力(参考 WorkBuddy 的 `widget.*` 文案):
|
||||
显示 UI ⇄ 查看代码、复制代码、下载到本地、导出为图片、加载中态、错误面板。
|
||||
|
||||
---
|
||||
|
||||
## 4. 数据模型
|
||||
|
||||
**不需要新增 `MsgKind`。** 制品就是工具产出,复用现有 `tool` kind:
|
||||
|
||||
```ts
|
||||
export type MsgKind = "user" | "agent" | "tool" | "perm"; // 不变
|
||||
|
||||
export interface ChatMessage {
|
||||
// …现有字段
|
||||
/** 制品:HTML 内容或落盘路径(见 §4.1) */
|
||||
artifact?: { kind: "html"; path: string; title?: string };
|
||||
/** 制品必须 keepVisible —— 折叠时不能被收走(否则制品整个消失) */
|
||||
keepVisible?: boolean;
|
||||
}
|
||||
```
|
||||
|
||||
`toolState` 已在本轮补上,制品卡直接复用「运行中 / 完成」两态。
|
||||
|
||||
### 4.1 制品内容存哪(待决策)
|
||||
|
||||
| 方案 | 优点 | 缺点 |
|
||||
|---|---|---|
|
||||
| 存 `messages.result`(TEXT) | 零改动 | 大 HTML 撑大 SQLite;`list_messages` 变重 |
|
||||
| **落项目工作目录 + DB 只存路径(建议)** | 符合「目录即项目」哲学;可被工具读回;DB 轻 | 需要文件生命周期管理 |
|
||||
|
||||
建议第二种:`.agent/artifacts/<message-id>.html`,DB 的 `result` 只存相对路径。
|
||||
删除会话时一并清理(或按「永不删除项目目录」的铁律只解除登记)。
|
||||
|
||||
---
|
||||
|
||||
## 5. 与「回合分组 / 折叠」的关系(容易踩坑)
|
||||
|
||||
这是 WorkBuddy 用 `isShowWidget` + `keepVisible` + `presentationGroupId` 解决的问题,Ygent 必须一起考虑:
|
||||
|
||||
1. **制品不能被折叠掉。** 回合结束时会把连续工具块收成一行摘要——制品必须 `keepVisible`,
|
||||
否则用户点了折叠,图表就没了。
|
||||
2. **制品要和它的解释文字绑在一起。** WorkBuddy 的做法是制品块向前找最近的正文块,
|
||||
共享 `presentationGroupId`。Ygent 目前用「回合」粒度分组(见 `ChatView.tsx` 的 `groupTurns`),
|
||||
如果制品总是出现在回合末尾,回合粒度暂时够用;一旦出现「文字→制品→文字」的结构,
|
||||
就需要下沉到块粒度。
|
||||
3. **制品高度不定**,不能像工具卡那样单行省略。需要 iframe 通过 `postMessage` 上报高度自适应,
|
||||
或给一个可拖拽/固定高度 + 内部滚动。
|
||||
|
||||
---
|
||||
|
||||
## 6. 体积代价(必须先决策)
|
||||
|
||||
| 依赖 | 体积 | 现状 |
|
||||
|---|---|---|
|
||||
| mermaid | **~2.8 MB**(WorkBuddy 的 `vendor-mermaid` chunk) | Ygent 前端 bundle 现在共 563 KB |
|
||||
| katex | ~300 KB(含字体) | — |
|
||||
| dompurify | ~45 KB | — |
|
||||
|
||||
**结论:一律动态 `import()`,按需加载,首次出现该内容类型时才拉。**
|
||||
|
||||
否则只为了偶尔一张流程图,就把首屏 bundle 撑到 3 MB+,冷启动明显变慢——这跟前面查到的「OMP 内核启动 1.31s」是同一类问题。
|
||||
|
||||
---
|
||||
|
||||
## 7. 顺带:代码 diff 视图(与富内容同级)
|
||||
|
||||
工具改文件时显示行级 diff,WorkBuddy 的 `tool-diff` 是现成参考:
|
||||
|
||||
- 输入 `oldCode` / `newCode` / `fileName`
|
||||
- 按扩展名推断语言(`ts/tsx/js/py/rs/go/java/kt/swift/c/cpp/cs/php/css/html/vue/sh/yml/sql/scala`)
|
||||
- Prism 懒加载该语言 + LRU 缓存,**语言不支持时回退 HTML 转义纯文本**(不要渲染空白)
|
||||
- 行渲染 `+/−` 号
|
||||
|
||||
Ygent 的 `edit` / `write` 卡目前只显示「项目/新增文档.md +15」徽标。
|
||||
要做 diff 的话,**必须用转义兜底**——文件内容绝不能当 HTML 注入。
|
||||
|
||||
---
|
||||
|
||||
## 8. 建议的分阶段落地
|
||||
|
||||
| 阶段 | 内容 | 成本 | 收益 |
|
||||
|---|---|---|---|
|
||||
| **P1** | mermaid 代码块(动态 import + DOMPurify SVG 消毒 + 失败回退原始代码) | 低 | 直观,模型零适配 |
|
||||
| **P2** | KaTeX 公式(remark-math + rehype-katex,动态 import) | 低 | 技术对话可读性明显提升 |
|
||||
| **P3** | 代码 diff 视图(`edit`/`write` 卡) | 中 | 直接改善现有工具卡 |
|
||||
| **P4** | HTML 制品(工具 + iframe 查看器 + 存储策略) | 高 | 能力上限最高,但需要先定 §4.1 和 §5 |
|
||||
|
||||
P1 + P2 可以在一个改动里做完(都是 Markdown 管线扩展 + 动态加载),建议作为第一步。
|
||||
|
||||
---
|
||||
|
||||
## 9. 待决策清单
|
||||
|
||||
1. **制品 HTML 存 DB 还是落项目目录?**(建议落目录,见 §4.1)
|
||||
2. **是否允许制品访问外网(CDN 脚本/字体)?** 现在 `csp: null` 允许;要不要收紧到白名单?
|
||||
3. **制品高度**:`postMessage` 自适应,还是固定高度 + 内部滚动?
|
||||
4. **mermaid 之外是否还要别的图表库**(如 ECharts)?WorkBuddy 的 `show_widget` 走的是「生成 HTML」而不是绑定图表库,这条路更通用但要制品能力先就位。
|
||||
5. **是否给制品加「导出为图片」**?WorkBuddy 有(`widget.downloadImage`),但需要额外依赖做 HTML→图片。
|
||||
|
||||
---
|
||||
|
||||
## 附:与 WorkBuddy 的差异(有意为之)
|
||||
|
||||
| 项 | WorkBuddy | Ygent 建议 |
|
||||
|---|---|---|
|
||||
| 高亮库 | Prism | 保持 highlight.js(已用,换库无收益) |
|
||||
| Markdown 裸 HTML | 未开启 | **同样不开启** |
|
||||
| 制品渲染 | iframe sandbox | 同 |
|
||||
| 内联 SVG 消毒 | DOMPurify SVG profile | 同(做 mermaid 时一并引入) |
|
||||
| 虚拟列表 | 有 | **不做**(Ygent 无此瓶颈) |
|
||||
| widget 分组 | 有(`presentationGroupId`) | **暂不做**,先用回合粒度;出现「文字→制品→文字」再下沉 |
|
||||
@@ -0,0 +1,13 @@
|
||||
# 对话标题规则与验收
|
||||
|
||||
2026-10-10:修复侧栏项目中新建空对话后,首条消息未更新默认标题的问题。
|
||||
|
||||
- 默认名称为“新对话”;宿主在用户消息落库时,用首条非空用户正文命名。连续空白合并,取前 24 个 Unicode 字符,超长添加省略号;不调用模型生成标题,不影响流式速度。
|
||||
- 独立对话和项目对话共用规则。前端发送后异步刷新页头、侧栏项目分组及项目详情列表,不等待模型完成。
|
||||
- `sessions.title_auto` 区分默认自动命名和手动命名。手动重命名关闭自动命名,即使用户主动命名为“新对话”也保留。后续用户、工具、助手消息不改变首条用户正文确定的标题。
|
||||
- 未被内核接受的首条消息撤回后恢复默认名称;重试使用实际保留的首条用户正文。取消或失败但已经被接受的回合仍保留标题。
|
||||
- v18 升级仅修复普通、非分支、无导入来源的旧默认名称(“新对话/新建对话/新任务”)。旧版本未记录命名来源,无法区分用户曾手动改为完全相同默认名称的情形;其他已有名称保持原样。新版本记录明确的手动命名来源。
|
||||
|
||||
验证:`npm run build`、`npm run check:chat`、`cargo test --no-default-features --manifest-path src-tauri/Cargo.toml --lib` 通过,Rust 82 项通过、1 项官方网络测试跳过。新增测试覆盖两个归属范围、空白消息、首条正文、后续消息、手动默认名称、Unicode 截断、拒绝发送回退及升级幂等。
|
||||
|
||||
真实桌面验收:隔离数据库的 WebView2 CDP 下运行 `node scripts/session-title-native-check.mjs 9336`,验证真实 IPC、页头/列表刷新、重载持久化和拒绝发送回退。未发送模型请求、未替换 IPC。主调试窗口重启后确认已有默认名称得到修复,恢复原查看对话;安装版未替换。
|
||||
@@ -0,0 +1,22 @@
|
||||
# 设置页风格对齐(2026-10-08)
|
||||
|
||||
参照 WorkBuddy 原生设置窗口(CDP 9223,windowKind=settings),通过 DOM、计算样式、元素尺寸采样;Ygent 在真实 Tauri WebView2(CDP 9335)验收。
|
||||
|
||||
## 已调整
|
||||
|
||||
- 设置区域从 760×600 调整为 900×680,与 WorkBuddy 设置窗口视口一致;小窗口限制最大宽高,内容单独滚动。
|
||||
- 使用 #f7f7f7 中性浅灰背景、白色 12px 圆角卡片,去掉导航分隔线和通用项逐行边框。颜色令牌仅作用于设置区域。
|
||||
- 顶部保留 32px 关闭栏;导航列 224px(含左右 12px 留白),导航项 200×34、间隔 2px、字号基准 14、常规字重,选中底色 #e6e6e6。
|
||||
- 内容区左留白 8px、右留白 30px;分组标题字号基准 14、灰色、常规字重,卡片内边距 12×16。通用分组宽 638px,内部行宽 606px。
|
||||
- 下拉框 120×32,标签字号基准 14、字重 500,描述使用弱化灰色。
|
||||
- 字号滑杆宽 224px、高 40px,细线六档刻度、8×16 滑块;“默认”对准第 2 档(20%),删除额外档位数字。沿用现有全局字号及持久化逻辑,所有文字依赖全局字号偏移。
|
||||
- 模型卡片、权限说明、授权/审计区域和空态使用相同中性卡片规则;导航改为可键盘操作的按钮。
|
||||
|
||||
## 验证与边界
|
||||
|
||||
- pnpm build、node scripts/fe-check.mjs 通过。
|
||||
- 原生 Ygent 主视口 1335×916,设置区域 900×680。通用的导航、分组、行高、下拉框尺寸及颜色与 WorkBuddy 采样匹配;通用三行高度为 44/70/52px。
|
||||
- 六档字号检查:标签实际字号 13/14/15/16/16/16,滑杆值同步,没有设置内容区横向溢出;三页切换及选中态检查通过。
|
||||
- 原生键盘右方向键使滑杆从第 2 档变为第 3 档;下拉展开、关闭设置检查通过,验证后恢复原字号并显示通用页。
|
||||
- 原生截图保存在用户私有调试目录,不提交真实会话数据。
|
||||
- 本次对齐设置的视觉体系和已有控件。WorkBuddy 使用独立原生设置窗口,Ygent 仍使用应用内弹窗;额外功能目录、独立窗口生命周期、所有嵌套编辑表单和小屏实测未列为已完成的 1:1 验收。
|
||||
@@ -0,0 +1,57 @@
|
||||
# Agent 命令执行环境
|
||||
|
||||
设置 → 通用 → 命令执行环境。当前接入 OMP 命令工具,独立于系统默认终端窗口;不修改 Windows Terminal、系统环境变量或其他软件的配置。
|
||||
|
||||
## 使用
|
||||
|
||||
1. 选择自动检测、Git Bash、PowerShell 7、Windows PowerShell、CMD 或自定义路径。
|
||||
2. 自定义模式填写 Shell 可执行文件的绝对路径,也可通过“浏览”选择。接受 bash、sh、zsh、pwsh、powershell、cmd;不接受 Windows Terminal 等窗口启动器。
|
||||
3. 选择后自动验证并保存;自定义路径在失焦、按 Enter 或浏览选择文件后保存。程序实际执行固定的验证命令,验证成功才持久化;路径不存在、无法启动、执行失败或超时会显示错误,保留原来的已保存配置。界面不显示额外保存按钮、正常状态说明或检测出的路径。
|
||||
4. 下一次发送消息时应用新的配置。运行中的回合继续使用启动时的 Shell,不因保存设置重启或中断。
|
||||
|
||||
自动检测依次尝试 Git Bash → PowerShell 7 → Windows PowerShell → CMD,跳过不存在或验证失败的候选。探测结果显示实际可执行文件路径;每次新回合还会检查是否可用。指定类型不可用时直接提示错误,不悄悄改用其他类型。
|
||||
|
||||
## 实现约束
|
||||
|
||||
- SQLite 设置键 `execution_shell` 存储模式和自定义路径;保存命令只写偏好,不触碰正在运行的内核配置。
|
||||
- 在 OMP 回合准备阶段解析 Shell,将实际路径/类型加入内核配置标识,变更时在空闲边界重启并恢复当前会话。
|
||||
- OMP 启动时加载 Ygent 私有的 `omp-profile/ygent-shell.yml`,追加实际 Shell 和语法的系统指令。关闭登录 Shell/PowerShell profile 加载,使探测与执行使用相同环境。
|
||||
- 本机 OMP 的普通 `bash` 工具实际使用内置 POSIX 解析器,单独设置 `shellPath` 无法执行 PowerShell 语法。因此显式加载 `ygent-shell-adapter.mjs`,在 `tool_call` 中将原始命令作为单个参数安全引用,再调用所选 Shell。仍走 OMP 原有执行、授权、流式输出、超时与取消链路,不另设绕过授权的执行工具。
|
||||
- Windows 可执行文件路径统一使用反斜杠,避免 OMP 对 CMD 正斜杠路径的错误解析。CMD 命令写入随机临时目录中的 UTF-8 `.cmd` 脚本,以保留引号、多行和中文;脚本在本次工具结果或会话关闭时清理。
|
||||
- 具名后台服务(`bash` 的 `name`)自身使用 `shellPath` 启动,不重复包装。其他工具与 Skill/MCP 调用不改写。工具详情可能显示包装后的实际执行命令。
|
||||
- 当前仅接入 OMP;直连模式及 Codex 底座不应用此选项。
|
||||
|
||||
## 验收 SOP
|
||||
|
||||
按 [原生调试 SOP](ygent-debug.md) 启动 WebView2 CDP 9335,在临时真实会话验收,完成后恢复原会话与设置。截图/会话输出放用户私有目录,不能提交凭证、真实聊天内容。
|
||||
|
||||
1. 在设置页检查六种选择、路径输入、验证反馈与重新打开后的持久化。使用无效路径确认保存失败且旧配置保留。
|
||||
2. 选择 PowerShell,在真实命令工具中执行 `$PSVersionTable.PSVersion` 和 `(Get-Process -Id $PID).Path`,核对实际版本/路径;不能用设置页“已验证”代替内核调用验收。
|
||||
3. 执行带等待的命令,在工具仍运行时保存另一种 Shell,确认 OMP PID 不变、当前命令仍返回旧 Shell 的输出。结束后下一回合检查新 Shell 的语法与实际输出。
|
||||
4. 自定义有效路径与对应预设应产生相同执行环境;自定义不存在的路径必须拒绝。Git Bash 未安装或损坏时显示失败。
|
||||
5. 检查六档字体的 computedStyle、控件矩形和 scrollWidth;长路径需换行,不得撑宽设置页。
|
||||
6. 编译前端、执行 Rust 测试并编译桌面程序。更换 OMP 二进制版本后重新验证工具 hook、参数引用及具名后台服务行为。
|
||||
|
||||
## 2026-10-09 验收记录
|
||||
|
||||
- 真实 Tauri WebView2:六种选项展示、Windows PowerShell 点击保存、无效自定义路径错误及旧偏好保留通过。六档字体无横向溢出。
|
||||
- 后续简化设置页:移除正常状态说明、路径展示和保存按钮,真实 UI 验证选择 Windows PowerShell 自动持久化、无效自定义路径保留旧偏好并显示错误、恢复自动检测成功。
|
||||
- 自动检测跳过本机损坏的 Git Bash 启动器,找到 PowerShell 7。真实 OMP 命令返回 PowerShell 7.6.5 的版本及进程路径。
|
||||
- Windows PowerShell 真实语法执行返回 5.1.26100.9444;等待 12 秒期间保存 CMD,OMP PID 保持不变,当前命令成功以原 Shell 完成。
|
||||
- 新回合使用 CMD,真实 OMP 工具返回 COMSPEC 和 Windows 版本;命令适配器搭配同版本 OMP 原生 Shell 验证环境变量、双引号、单引号、多行与中文,全部通过。具名服务及其他工具未被该 hook 包装。
|
||||
- 前端生产编译、TypeScript 检查、Rust 桌面编译及 35 个 Rust 测试通过。
|
||||
- Git Bash 本机安装缺少 `usr/bin/bash.exe`,未验收实际 Bash 命令;其验证失败路径已确认。具名后台服务不重复包装,但完整后台生命周期尚未单独验收。
|
||||
|
||||
## 2026-10-12:重复包装与失败重试修复
|
||||
|
||||
真实 bundled OMP 18.6.3 的隔离对照确认:普通 `bash` 仍经内置 POSIX 执行器,不能删除所选 Shell 的适配。原始 PowerShell 脚本经过一层包装可正常执行;把已包装的历史参数重新作为脚本提交会形成嵌套,并产生 `-NoLogo` 等意外标记错误。内存中的下一次模型请求仍保留原始参数,但持久会话恢复后,模型上下文会读到保存的执行包装。两种路径不能混为一谈。
|
||||
|
||||
修复入口为 `src-tauri/src/shell-adapter.mjs`,由 `shell::adapter_in` 写入每个隔离 profile,保留实际 Shell、取消、超时、输出和授权链路:
|
||||
|
||||
- 在通用 `context` hook 中,仅克隆并还原助手 `bash` 调用中与本回合 Shell/参数精确匹配的完整单参数包装。不修改持久审计文件、工具结果、其他工具或具名后台服务,不依赖渠道协议。
|
||||
- 工具启动前同样去除可严格验证的重复包装,最多还原八层,然后仅包装一次。不解析任意 Shell 表达式;带其他标志、管道或重定向的脚本不能被当作自身包装去除。
|
||||
- CMD 的历史包装指向已清理的临时脚本,无法据路径重建原始内容。明确要求重新提供原始 CMD 脚本,不能重放未知临时文件。正常 CMD 的中文、多行和结果后清理仍保留。
|
||||
- 同回合、同 cwd 的同一原始命令失败两次后,结果保留原错误并补充诊断提示;失败三次后拒绝第四次原样尝试。换用实际不同的诊断/修复命令仍可执行。计数按内核实例及回合隔离,成功清除相应失败计数,迟到和重复结果不累加。
|
||||
- 限次不代表任务完成、取消或通过,不新增人工授权。缺少前置条件时沿现有员工与经理协作处理。它只约束同一命令的重复失败,不宣称能识别所有等价命令或所有无效诊断循环。
|
||||
|
||||
回归入口:`cargo test --lib --manifest-path src-tauri/Cargo.toml shell::tests -- --test-threads=1` 检查实际生成模块;`scripts/shell-adapter-native-check.mjs` 使用隔离 profile、真实 OMP 与本机受控 SSE,验证原始命令、历史包装、上下文恢复、真实输出及非零退出。私有证据不进仓库;本节源码修复不表示已替换正在运行的用户进程。
|
||||
@@ -0,0 +1,24 @@
|
||||
# 左侧菜单:侧栏收起/展开对标(2026-10-08)
|
||||
|
||||
本轮范围是侧栏切换入口和收起/展开行为;对话区仍按阶段进度收尾,不继续修改其内部实现。
|
||||
|
||||
## WorkBuddy 原生参照
|
||||
|
||||
真实WorkBuddy 5.7.6、CDP9223、1335×916:入口在左上角,展开和收起时均保留同一个按钮,分别提示“收起侧边栏”/“展开侧边栏”。按钮位置(8,3)、24×24,图标16×16,圆角8px,文字/图标黑70%;使用面板分栏向量,没有方向箭头。hover/active背景#0000000f、图标#000000e6,100ms颜色/背景过渡。
|
||||
|
||||
实测展开时当前侧栏宽240px;点击后侧栏完全隐藏,主区宽度扩展到1335px,没有保留图标窄栏。入口仍在原位置,第二次点击恢复侧栏。采集后还原原展开状态。私有原生证据`sidebar-toggle-wb.json`,位于`C:/Users/Administrator/.ygent/imports/render-audit-20261008/`。
|
||||
|
||||
## Ygent 本轮修改
|
||||
|
||||
- 移除左侧菜单底部的“收起侧栏”文字入口;底部设置保留。
|
||||
- Titlebar左上固定一个原生button,展开/收起共用,切换提示和aria-expanded;aria-controls关联`ygent-sidebar`。
|
||||
- 使用WorkBuddy原生SVG的面板路径,位置(8,3)、24×24/16×16、颜色、圆角和hover/active规则按实测接入。
|
||||
- 侧栏继续通过隐藏容器收起,保留挂载;恢复时保留任务/项目展开状态,不切换会话或页面。切换按钮也不卸载,键盘焦点保留。
|
||||
|
||||
代码位置:`src/components/Titlebar.tsx`、`src/components/Sidebar.tsx`、`src/App.tsx`、`src/App.css`。未新增侧栏状态的重启持久化或快捷键,WB相应规则尚未核实。
|
||||
|
||||
## 验收与边界
|
||||
|
||||
真实Ygent Tauri WebView2、CDP9335、1335×916、DPR1:按钮在两态均为(8,3,24,24)、黑70%、圆角8;收起时host display:none、主区x0/w1335;按钮节点及焦点保持;恢复后侧栏为同一节点、当前会话/页面不变、底部不再出现旧入口。操作后还原原展开状态。私有证据`sidebar-toggle-yg-check.json`。前端编译检查随本轮执行。
|
||||
|
||||
本轮对齐的是入口和切换行为,不是整个左栏/标题栏已1:1:YG侧栏仍宽280px,WB当前实测240px;YG标题栏高40px,WB高30px,因此主区顶部分别y40/y30。左栏其他菜单、背景、项目层级、账号区域及窄窗响应另行对标,不能为此次入口修改直接外推。
|
||||
@@ -0,0 +1,18 @@
|
||||
# 思考与工具参数增量接入(2026-10-10)
|
||||
|
||||
当前 OMP 接入 `assistantMessageEvent.thinking_delta`、`toolcall_start` 与 `toolcall_delta`。真实二进制隔离探针确认:Responses 的 `response.reasoning_summary_text.delta` 转为 `thinking_delta`,`response.function_call_arguments.delta` 转为 `toolcall_delta`;后者 `partial.content[contentIndex]` 提供工具 ID 和名称。不读取 reasoning 的签名、加密内容,也不保证所有渠道/模型都公开思考摘要。
|
||||
|
||||
Rust 将这些帧转为 `agent://event` 的 `activity`,保留 delta、messageId/contentIndex、工具 ID/名称;原有会话/回合绑定与取消过滤不变。正文仍是 chunk,实际执行仍是 tool。结束快照不重复播报。
|
||||
|
||||
ChatRun 独立维护最近 4000 字符的原始事件播报,按到达顺序包含思考、参数、正文、工具输出和授权文字。已流式收到的工具参数不被执行开始时的完整参数重播。未闭合 JSON 仅用于播报,不解析执行,也不提前创建工具卡或放行授权。
|
||||
|
||||
播报是内存临时状态,切换会话隐藏,返回运行中的会话恢复,结束/取消/失败清空。思考不转为 ChatMessage,不写历史数据库,不进入项目记忆整理源;activity 事件不会触发消息落库。头像下的阶段随事件显示“正在思考/生成工具参数中”;实际执行、待授权/回答仍优先显示原有阶段。底部始终使用原有单一“正在思考”扫光与播报动效。
|
||||
|
||||
## 验证 SOP
|
||||
|
||||
1. `node scripts/omp-activity-probe.mjs <仓库外私有目录>`:独立 OMP、独立 profile、回环 Responses 服务,无用户凭据或远程模型;检查真实帧的 delta、顺序及工具 ID。
|
||||
2. `cargo test sidecar::tests --lib`、`npm run check:chat`、`npm run build`:检查解码、未完整参数不建卡、快照去重、取消和跨会话隔离、思考不落库,以及原有交互与折叠回归。
|
||||
3. 按 [原生调试 SOP](ygent-debug.md) 启动独立数据目录的真实 Tauri 调试窗口(9336)。仅在此独立数据库中设置 `activity_test_mode=native-isolated`,不能在用户正常数据库中设置测试标记;有正在使用的窗口时不要停止它。
|
||||
4. `node scripts/chat-activity-native-check.mjs 9336 <仓库外私有证据目录>`:通过真实 IPC 创建测试渠道和对话,真实 OMP 连接本地受控 Responses SSE。分别检查思考片段、未闭合参数、正常正文在终态前出现在 DOM,同一时间恰好一个播报栏,正常工具完成,思考不在持久化消息中,参数生成时取消后晚到 SSE 不恢复运行。
|
||||
|
||||
本机已通过真实 Tauri WebView2、真实 OMP 与受控 Responses SSE 验证。证据保存在用户私有 `~/.ygent/imports/activity-native-evidence-20261010/`,不提交。测试使用受控模型输出,不代表当前远程渠道一定提供增量,也不代表 WorkBuddy 双端流式对标、Mac/Linux 或其他内核已通过。安装版 0.01 不随源码/调试构建自动更新,须重新打包安装。
|
||||
@@ -0,0 +1,125 @@
|
||||
# Ygent UI 能否像素级对齐 WorkBuddy —— 可行性结论
|
||||
|
||||
日期:2026-10-14
|
||||
问题:是否可以和 WorkBuddy 的 UI / 交互做像素级对齐?
|
||||
|
||||
本文是**可行性结论**,不是实施方案,也不改变任何既有对标承诺。证据来自项目已有的对标记录(`ygent-workbuddy-render-audit-2026-10-08.md`、`ygent-font-parity.md`、`ygent-chat-interaction-parity.md`、`ygent-chat-stage-summary-2026-10-08.md`)与 `AGENTS.md` 的原生渲染调试约束。
|
||||
|
||||
---
|
||||
|
||||
## 0. 结论
|
||||
|
||||
1. **对话区(chat):可以,而且大部分已经做到。** 现有实测已把关键几何收敛到「同视口 / 同字号 / 同展开状态下 ≤1px 取整误差」,含 108 组字号/行高、18 组几何、多个回合成品尺寸完全一致。
|
||||
2. **外围壳层(侧栏 / 顶栏 / 左下 / 新建页):只能部分对齐。** 一部分是宿主结构差异,一部分是数据模型差异,还有一部分是平台商业入口——后者按项目约定不应复制。
|
||||
3. **「全局 100% 像素一致」不可能,也不需要。** 三类硬性不可消除:渲染引擎版本差、跨机器字库、数据驱动内容。
|
||||
4. **有一个前置取舍**:项目已按用户要求做了若干**品牌化偏离**(Ygent 名称/图标、品牌渐变背景、品牌蓝发送按钮、移除邀请卡/账号区),这些与"像素级对齐"直接冲突,需要明确取哪一边。
|
||||
|
||||
---
|
||||
|
||||
## 1. 技术上可行的前提(已全部具备)
|
||||
|
||||
| 前提 | 状态 | 证据 |
|
||||
|---|---|---|
|
||||
| 同内核族渲染 | WorkBuddy = Electron/Chromium;Ygent = Tauri/WebView2(Edge Chromium)。CSS 盒模型与亚像素布局算法同源 | `AGENTS.md` 原生渲染调试约束 |
|
||||
| 双端真实 CDP 对标通道 | 本机回环:WB 9223 / Ygent 9335 | `docs/workbuddy-cdp.md`、`ygent-debug.md` |
|
||||
| 读真实计算值与字库 | `getComputedStyle`、`getBoundingClientRect`、`CSS.getPlatformFontsForNode` | `ygent-workbuddy-render-audit-2026-10-08.md` §采集条件和坐标 |
|
||||
| 同条件可比 | 固定窗口/视口、DPR、字号档位、同会话位置、展开状态;用 `dy`(相对头像行)排除历史高度差 | 同上 |
|
||||
| 误差口径已定义 | 关键几何允许 ≤1px 取整误差;缺失结构/入口**不按像素误差豁免** | 同上 §修复顺序与完成标准 |
|
||||
| 字库已匹配 | `--yg-font-sans` 显式加入 Noto Sans SC;终端 Courier New;名称 Arial Bold;六档 108 组字号/行高一致 | `ygent-font-parity.md` |
|
||||
|
||||
---
|
||||
|
||||
## 2. 已经达到像素级的实测样例(不是空谈)
|
||||
|
||||
| 元素 | 两端共同值 |
|
||||
|---|---|
|
||||
| 正文列 | x359、w752、右边 1111 |
|
||||
| 命令结果面板 | w752、内容 720、圆角 16、padding 12×16、高 198.75 |
|
||||
| 用户气泡外壳 | 355.15625×44.59375(未硬编码,由内层文字推出) |
|
||||
| 输入外框 | (348,592,784,134)、1px #e6e6e6、圆角 24、同双层阴影 |
|
||||
| 发送按钮外框 | (1087,681,32,32) |
|
||||
| 头像行 | x359、头像 24×24、名称 x393、gap 10 |
|
||||
| 六档字号/行高 | 108 组全部一致;18 组几何一致 |
|
||||
| 删除确认浮层 | 240×166,圆角/边框/双层阴影/按钮尺寸匹配 |
|
||||
| 路径标签 | 68.25×20、15px/22.5、padding 1px 4px、图标 15×15 |
|
||||
|
||||
---
|
||||
|
||||
## 3. 不可对齐 / 只能部分对齐清单(按原因分类)
|
||||
|
||||
### A. 渲染引擎层(少量,需逐项适配)
|
||||
|
||||
- WebView2 的 Edge Chromium 版本与 Electron 内置 Chromium 版本不同 → 默认 UA 样式、原生滚动条伪元素、字体回退顺序可能不同。
|
||||
- 实证差异:滚动条 D39(WB 宽 6 / thumb 黑 20% vs Ygent 宽 10 / 蓝灰 14%)、D40(滚动条上下端小三角 `pseudo display` 不同)。
|
||||
- 结论:**绝大多数元素可在 1px 内对齐,少数宿主原生控件需专项处理**,不能机械复制 `display` 值。
|
||||
|
||||
### B. 字库层
|
||||
|
||||
- 本机已匹配,但 `ygent-font-parity.md` 明确:**字库是本机已安装系统字体,未复制进项目,其他机器缺少会回退** → 跨机器像素一致不成立。
|
||||
- 要对齐跨机器:可打包 Noto Sans SC(OFL 许可允许再分发);**但 Courier New 属微软系统字体,不可再分发**,只能依赖系统存在。
|
||||
|
||||
### C. 宿主结构层(不可消除)
|
||||
|
||||
- **X01 顶栏**:WB 菜单+全局图标(主顶栏 y30 h56)vs Ygent 品牌标题栏(y46 h40)——宿主 chrome 不同。但内部对话标题/五按钮坐标已一致,**不应为复制菜单破坏这些坐标**。
|
||||
- **X03 侧栏项目层级**:WB「项目→子项」vs Ygent 独立任务,同时含层级、导入归属和不同列表数据 → **不能硬移整个侧栏**。
|
||||
|
||||
### D. 数据与功能缺失层(必须先有数据,不是调 CSS)
|
||||
|
||||
以下不是像素偏移,而是**结构/数据缺失**:
|
||||
|
||||
- D25「深度思考」收起行 —— 需要 reasoning 事件数据。
|
||||
- D29「查看所有产物(5)」入口 —— 需要真实回合产物关联与计数。
|
||||
- D30 助手操作栏整行(复制/赞/踩/朗读/重试/分享 + 消耗/模型/时间)—— 需要真实消耗与模型元数据。
|
||||
|
||||
项目明确"不伪造消耗/模型数据或放无效按钮"。**补齐数据来源后才谈对齐;在此之前任何"像素级"都是假的。**
|
||||
|
||||
### E. 平台商业与品牌资产层(按约定不应复制)
|
||||
|
||||
- **X04 左下**:WB 邀请卡/账号区 vs Ygent 设置/收起侧栏 → 平台商业体系,不默认复制。
|
||||
- **品牌偏离(有意为之)**:Ygent 名称与图标、对话页品牌渐变背景、品牌蓝发送按钮 —— 均为用户要求的偏离,`ygent-chat-stage-summary-2026-10-08.md` 明确"不计作 WorkBuddy 白底的逐像素一致性验收"。
|
||||
- **图标资产**:现有 SVG 路径是逆向取值的 WB 图标(D08 分享箭头、D09 概览、D37 纸飞机仍有图形差),照搬其品牌资产涉及资产许可,建议自绘。
|
||||
|
||||
---
|
||||
|
||||
## 4. 真正的难点不是像素,而是动态交互
|
||||
|
||||
项目已定:**静态画面通过 ≠ 流式通过**(`ygent-chat-interaction-parity.md`)。像素级达标不解决以下问题,未完成项:
|
||||
|
||||
| 编号 | 未完成项 | 通过条件 |
|
||||
|---|---|---|
|
||||
| S01/S02/S06 | 正文分块、工具 start/update/end、取消与迟到事件 | 真实 OMP 隔离会话双端动态链路 |
|
||||
| S04 | 自动折叠触发时机与活动回合资格 | 按事件采集双端**时间序列**,不能比终态截图 |
|
||||
| S05 | 滚动跟随与阅读锚点 | 贴底跟随、上翻不拉回、回底恢复,记录 scrollTop/scrollHeight |
|
||||
| S07 | 公开思考/等待/错误阶段 | 不伪造内部推理、模型或消耗元数据 |
|
||||
|
||||
另:"同输入"无法要求 token 级墙钟一致,只能比较**对应事件后的显示位置、块顺序、更新方式、折叠、滚动和操作反馈**。
|
||||
|
||||
---
|
||||
|
||||
## 5. 建议的分级目标
|
||||
|
||||
| 级别 | 目标 | 可行性 |
|
||||
|---|---|---|
|
||||
| L1 几何对齐 | 同视口/同字号/同展开状态下关键锚点与尺寸 ≤1px 取整误差;字库匹配 | ✅ 对话区已基本达成,可继续收敛外围 |
|
||||
| L2 静态像素对齐 | L1 + 全部可见元素(图标路径、颜色、阴影、滚动条)一致 | ⚠️ 可达 90%+;宿主原生控件与品牌偏离项除外 |
|
||||
| L3 动态交互一致 | 事件序列、折叠时机、滚动、取消/恢复与 WB 同步 | ⏳ 未完成,**这才是真正目标** |
|
||||
| L4 全局 100% 像素一致 | 含宿主 chrome、平台入口、跨机器字形 | ❌ 不可能,也不建议 |
|
||||
|
||||
---
|
||||
|
||||
## 6. 需要明确的一个取舍
|
||||
|
||||
项目当前定位是「**对标布局与交互,但保留 Ygent 品牌**」:名称/头像/背景/按钮色已按用户要求偏离 WB。若坚持"像素级",需二选一:
|
||||
|
||||
- **选项 A(推荐,即现状方向)**:对齐到 L1 + L2 的**结构与几何**,保留 Ygent 品牌视觉;后续追加收敛图标路径、滚动条、剩余间距与缺失结构。
|
||||
- **选项 B**:连品牌视觉也照搬 WB(白底、WB 图标、WB 名称)→ 与既有产品决策冲突,且涉及资产许可,需单独确认。
|
||||
|
||||
---
|
||||
|
||||
## 7. 不做的事
|
||||
|
||||
- 不为对齐硬补高度(如 D26 的 45.77px)。
|
||||
- 不伪造消耗/模型/产物计数以凑齐视觉。
|
||||
- 不复制平台商业入口与无效操作卡片。
|
||||
- 不把任一端的绝对 y 差直接当作需要修复的 margin。
|
||||
- 不把静态像素通过宣称为动态交互通过。
|
||||
@@ -0,0 +1,165 @@
|
||||
# Ygent 与 WorkBuddy AI 实现对比及可实施项
|
||||
|
||||
日期:2026-10-14
|
||||
对比对象:[WorkBuddy-AI-实现分析报告](WorkBuddy-AI-实现分析报告.md)(对该报告所述 WorkBuddy 桌面版能力的静态逆向结论)× Ygent 代码库实际实现
|
||||
|
||||
状态说明:本文是**差距分析 + 可实施项评估**,不是实施方案,也不改动任何既有交付承诺。文中"已实现"以代码为据(附文件路径);`docs/*.md` 与 `AGENTS.md` 的目标描述不计为已实现。
|
||||
|
||||
---
|
||||
|
||||
## 0. 结论速览
|
||||
|
||||
1. **两者不是同类产品,不能逐项对齐。** WorkBuddy 是「自带 Agent 内核 + 云端多模型网关 + 自研 OS 沙盒」的一体化商业桌面端;Ygent 是「接入外部内核(OMP)+ 用户自带渠道(BYO Key)+ 宿主权限治理」的可控桌面端。**内核不是自己的**,这是最大的结构性差异。
|
||||
2. **Ygent 在六个方向的实现深度已超过 WorkBuddy**(团队/岗位 80+ 表、项目任务、资料库版本化、A2A 协作预算、LSP 自管、grants+审计),这些**不需要对齐**,属于反向优势。
|
||||
3. **真正值得补的差距集中在宿主层,且大部分不需要碰内核**:进程治理、删除安全、循环防护、预热、少量高频工具缺口、内置连接器预设。这批属于**低风险可直接做**。
|
||||
4. **唯一的大工程差距是 OS 级沙盒**(WorkBuddy 的 tsbx + shim 双层),但当前用户取向(2026-10-12「给全部的授权,现阶段不考虑在现实上做这么多工作」)与重型限制机制相反,**不建议现在做**,继续如实声明"规则隔离不是沙盒"。
|
||||
5. 报告本身是静态逆向,**提示词全文、服务端模型路由、鉴权细节本地不可见**,不能当作实现规格照抄。
|
||||
|
||||
---
|
||||
|
||||
## 1. 逐层对比
|
||||
|
||||
### 1.1 整体架构
|
||||
|
||||
| 层 | WorkBuddy(报告) | Ygent(实测) | 判定 |
|
||||
|---|---|---|---|
|
||||
| 桌面壳 | Electron + app.asar,含 workbuddy-editor-sdk(Office 编辑)、baas-v2 | Tauri 2 + React 18 + zustand 5(`package.json`) | **等价不同技术**,无需改造 |
|
||||
| UI↔引擎协议 | ACP(`@agentclientprotocol/sdk`),本地 HTTP `/api/v1/acp` | 自研 NDJSON RPC over stdin/stdout(`src-tauri/src/sidecar.rs:448-489, 667-726`) | 能力等价;除非要接第三方 UI,否则不必换 ACP |
|
||||
| Agent 内核 | 自带 `@genie/agent-cli`(Claude Code 血统,9.4MB bundle + 66 懒加载分块) | 外部 `omp-*-pc-windows-msvc.exe`,`--mode rpc-ui`(`sidecar.rs:506-544, 647`) | **结构性差异**:内核非自有 |
|
||||
| 模型接入 | 云端网关 `/plugin` 前缀 + Bearer + `X-User-Id`,服务端路由 | 用户渠道表 + 直连 OpenAI 兼容 / Responses / Anthropic Messages / Gemini(`commands/channel.rs`, `llm.rs`) | **BYO 渠道 vs 服务端托管**,各有取舍 |
|
||||
|
||||
### 1.2 内核与循环
|
||||
|
||||
| 项 | WorkBuddy | Ygent | 可实施性 |
|
||||
|---|---|---|---|
|
||||
| 循环原语 | `@openai/agents` + 自研 genie 工作区包 | 由 OMP 提供,宿主不自建循环 | ❌ 不建议(违反"不创建第二套聊天内核"约定) |
|
||||
| 死循环防护 | `CBC_LOOP_GUARD_CONSECUTIVE_THRESHOLD` / `_SEQUENCE_REPEATS` / `_DISABLED` | **未见实现** | ✅ 可在宿主对工具名/参数序列做重复检测 |
|
||||
| 进程守护 | `daemon-supervisor.cjs` + `windows-job.cjs`(Job Object 绑子进程树) | 仅 `buildtest/process_windows.rs:86-290` 用 Job Object(构建进程强杀),OMP 子进程未绑定 | ✅ 低成本高收益 |
|
||||
| 启动预热 | `cbc-prewarm`、`preload-lazy-chunks` | 有空闲回收 `trim_idle_processes(8)`(`collaboration_runtime.rs:263`),**无启动预热** | ✅ 可补 |
|
||||
| 低内存模式 | `codebuddy-lowmem`(RSS 阈值触发 heap snapshot) | 无 | ⚠️ 可选,Node 内核才有意义 |
|
||||
|
||||
### 1.3 工具系统
|
||||
|
||||
Ygent 的工具体系**不是更少,而是不同**:宿主侧有 `ygent_*`、`library_*`、`experience_*`、`collaboration_*`、`project_tasks_*`、以及大批 `team_*`(`team/*.rs`),前端标签字典 `src/lib/toolSummaryRules.ts` 头部注释标明「verified against installed WorkBuddy 5.7.6」——**字典里有 WorkBuddy 工具名,但后端并不产出**。
|
||||
|
||||
后端**确证缺失**的 WorkBuddy 侧高频工具:
|
||||
|
||||
- 联网:`web_search`、`web_fetch`
|
||||
- 规划:`enter_plan_mode` / `exit_plan_mode` / `plan_*`
|
||||
- 待办:`todo_write`
|
||||
- 交互:`ask_followup_question`(Ygent 有 `questions.rs` 问答机制,但非同名工具体系)
|
||||
- 可视化:`visualize:show_widget`、`widget_guidelines`(前端 `turnFold.ts:91-95` 能识别 widget 渲染,后端不产出)
|
||||
- 多媒体:`image_gen`(Ygent 完全无多媒体生成)
|
||||
- 静态检查:`read_lints`(Ygent 已有 LSP 自管 + `ygent_code_analysis`,基础具备)
|
||||
- MCP 侧:`mcp_call_tool` / `mcp_get_tool_description` / `fetch_mcp_resource`
|
||||
- 集成:`call_*_integration`、`automation_update`
|
||||
|
||||
文件类工具靠 OMP 原生 `read/write/edit/bash/grep/glob` 替代(`sidecar.rs:596`),**命名与 WorkBuddy 不同**,但功能覆盖。
|
||||
|
||||
### 1.4 模型层
|
||||
|
||||
| 项 | WorkBuddy | Ygent |
|
||||
|---|---|---|
|
||||
| 推理位置 | 云端网关(本地不推理) | 用户渠道直连(`llm.rs` 真流式 SSE) |
|
||||
| 协议 | OpenAI 兼容 `/chat/completions` + SSE | OpenAI 兼容 + Responses + Anthropic Messages + Gemini(`ygent-model-metadata-plan.md`) |
|
||||
| 降级/回退 | 有降级标记(如 `deepseek_flash_unavailable`) | 未见渠道级降级/回退路由 |
|
||||
| 多模态 | ASR(`wb-asr` / `gpt-4o-mini-transcribe`)、图像生成/编辑(`hunyuan-image-*`) | **无多媒体生成** |
|
||||
|
||||
### 1.5 沙盒与安全(**最大差距**)
|
||||
|
||||
| 层 | WorkBuddy | Ygent | 判定 |
|
||||
|---|---|---|---|
|
||||
| 策略/审批 | `@anthropic-ai/sandbox-runtime` + 权限提升桥 | 审批网关:内核恒 `--approval-mode always-ask`,宿主决定放行/弹卡(`sidecar.rs:648-650`) | ✅ 已有 |
|
||||
| 执行层沙盒 | 腾讯自研 `tsbx.dll` + `sandbox-center.exe` + `betterleaks.exe` + `tsbxldr.dll` | **无 OS 级沙盒**(无 seccomp/AppContainer/文件系统隔离) | ❌ 大工程 |
|
||||
| Shim 层 | `brokered-fs-shim`(fs 走 broker IPC)、`sitecustomize.py`、**`safe-delete`(删除进回收站 `GENIE_TRASH_DIR` + bulk-guard)**、`brokered-bin` 白名单命令目录 | 无 | ✅ **safe-delete 与命令白名单可移植** |
|
||||
| 授权模型 | 会话/账号级 | `grants` 表白名单(`fnv1a(method\|title)` 哈希)+ `audit_log` + 完全访问 + 经理只读白名单(`omp.rs:318-341`, `approval.rs:54-118`) | Ygent 更细 |
|
||||
|
||||
### 1.6 扩展体系
|
||||
|
||||
| 项 | WorkBuddy | Ygent | 缺口 |
|
||||
|---|---|---|---|
|
||||
| MCP | `@modelcontextprotocol/sdk` 1.29.0,配置文件驱动 | stdio + Streamable HTTP 自研(`connectors/client.rs`),协议协商 `2025-11-25→2024-11-05`,凭证进 Windows 保险库(`connectors/vault.rs`) | OAuth、SSE、CLI 适配器、resources/prompts、市场 |
|
||||
| Skills | SKILL.md(兼容 Anthropic Agent Skills) | SKILL.md 按需 `ygent_load_skill(id)`,SHA256 摘要 + 回合冻结快照 | ZIP/Git/市场导入 |
|
||||
| 专家 Expert | 专家包(plugin.json + agents/*.md)、专家团 | **无独立专家概念**:「专家」tab 实为团队岗位(`TeamRolePane.tsx`, `CapabilityCenter.tsx:41`) | P3 专家闭环待实现(方案 §9 已列) |
|
||||
| A2A | `@a2a-js/sdk` | 自研 collaboration 体系 + 80+ `team_*` 表,含预算/取消/恢复 | **Ygent 更强** |
|
||||
| IM 渠道 | `/api/v1/channels/wechat\|wecom` + 客服/群机器人 API | 无(`channels` 表是模型渠道,非 IM) | 可做,依赖连接器可用 |
|
||||
|
||||
### 1.7 部署与治理
|
||||
|
||||
| 项 | WorkBuddy | Ygent |
|
||||
|---|---|---|
|
||||
| 部署变体 | `product.json` 四变体(cloudhosted/selfhosted/ioa/internal),`ACC_PRODUCT_CONFIG_V2/V3` | 无(单机桌面) |
|
||||
| 认证 | 腾讯云账号 + Bearer + `X-User-Id` | 本机,无账号体系 |
|
||||
| 可观测 | `@tencent/galileo-node-sdk` + OpenTelemetry `/v1/traces` | `audit_log` 表;无 OTEL |
|
||||
| 资源分发 | COS 加速桶 | 本地 |
|
||||
|
||||
---
|
||||
|
||||
## 2. 可实现清单(按成本分档)
|
||||
|
||||
### A 档:宿主层、低风险、可直接做(不碰内核协议)
|
||||
|
||||
| # | 事项 | 依据/落点 | 收益 | 前置 |
|
||||
|---|---|---|---|---|
|
||||
| A1 | **OMP 子进程纳入 Windows Job Object**,进程退出时回收整棵子进程树 | 对标 `windows-job.cjs`;现 `sidecar.rs` 启动 OMP 未绑定 Job | 异常退出/崩溃不再残留 OMP 进程 | 无 |
|
||||
| A2 | **safe-delete:删除类操作进回收站 + 批量删除 guard** | 对标 shim `safe-delete` + `GENIE_TRASH_DIR` + bulk-guard;Ygent 完全无 | 直接降低误删不可逆损失 | 需用户确认(见 §4) |
|
||||
| A3 | **危险命令 / 危险路径黑名单拦截**(宿主 Shell 工具包装层) | 对标 `brokered-bin` 白名单;Ygent 有 grants 但无命令级策略 | 挡住高危命令 | 需用户确认 |
|
||||
| A4 | **工具调用死循环检测**(同名+同参序列阈值告警/中断) | 对标 `CBC_LOOP_GUARD_*`;Ygent 无 | 省 token、防卡死 | 无 |
|
||||
| A5 | **内核启动预热**(新对话页提前拉起/复用内核) | 对标 `cbc-prewarm`;Ygent 有回收无预热 | 缩短首字延迟 | 无 |
|
||||
| A6 | 补 **`read_lints`**(复用已有 LSP + `ygent_code_analysis`) | `lsp/*.rs`, `code_analysis.rs` 基础设施已具备 | 近乎白送的工具补齐 | 无 |
|
||||
| A7 | 补 **`web_fetch` / `web_search`**(可基于内置浏览器或直连 fetch) | 对标 WB 同名工具;Ygent 有 `ygent_browser` 可复用 | 联网研究类任务能力 | 需授权策略 |
|
||||
| A8 | 内置 **连接器预设扩充**(现仅 GitHub / DeepWiki) | `connectors/presets.rs:17-33` | 降低接入门槛 | 无 |
|
||||
| A9 | **前后端工具名对齐**:把 `toolSummaryRules.ts` 里已有但后端不产出的名字清点,避免"能渲染但不产出"的错位 | `src/lib/toolSummaryRules.ts` vs `sidecar.rs:973-1004` | 消除认知错位 | 无 |
|
||||
|
||||
### B 档:中等成本,需设计与验收
|
||||
|
||||
| # | 事项 | 说明 |
|
||||
|---|---|---|
|
||||
| B1 | **多媒体生成接入**:文生图 / 图生视频 / 音频转写,走现有渠道体系 | Ygent 目前**零多媒体生成**,是明显功能空白;参考 WB 的 `image_gen`、`AudioTranscribe` |
|
||||
| B2 | **专家(Expert)闭环 P3** | 方案 §9 已定;导入 WorkBuddy `.codebuddy-plugin/plugin.json` + `agents/*.md` 到 Ygent 模型(映射表见方案 §5)。当前"专家 tab = 团队岗位"需明确区分 |
|
||||
| B3 | **MCP 增强**:OAuth 授权流、CLI 连接器适配、`resources`/`prompts` 读取、`mcp_get_tool_description` 等价工具 | 现只支持 stdio + Streamable HTTP,无 OAuth/SSE/CLI |
|
||||
| B4 | **渠道级降级/回退路由** | 对标 WB 的降级标记(如 `deepseek_flash_unavailable`) |
|
||||
| B5 | **非完全访问时把 `write`/`edit` 纳入 cwd 范围校验** | 目前经理有只读路径校验(`approval.rs:95-118`),普通会话主要靠审批网关 |
|
||||
| B6 | **结构化 trace / OpenTelemetry 导出** | 在 `audit_log` 与已有渲染性能诊断之上,便于定位渲染长任务 |
|
||||
| B7 | **IM 渠道接入**(企业微信/微信机器人) | 依赖连接器可用;当前会话企业微信连接器为关闭状态 |
|
||||
|
||||
### C 档:大工程 / 不建议现在做
|
||||
|
||||
| # | 事项 | 不建议理由 |
|
||||
|---|---|---|
|
||||
| C1 | **OS 级沙盒**(tsbx 等价物) | Windows 需文件过滤驱动/内核态组件,成本极高;且与用户 2026-10-12「不做这么多现实工作」的取向相反。建议**保持规则隔离 + 审批 + 审计**,继续如实声明"不是沙盒"(`ygent-team-integration.md:91`) |
|
||||
| C2 | 自建 agent 循环 / 换自研内核 | 违反"不创建第二套聊天内核"约定,收益低 |
|
||||
| C3 | 改用 ACP 协议 | 现 NDJSON RPC 已满足;除非要接第三方 UI 或多内核 |
|
||||
| C4 | 市场 / 云同步 / 多设备 / 云资产 | 方案 §9 已列为后续,不在首期 |
|
||||
| C5 | 产品四变体配置 | 单机桌面场景价值低 |
|
||||
| C6 | 遥测上报(galileo 类) | 涉及隐私,桌面版不建议引入 |
|
||||
|
||||
---
|
||||
|
||||
## 3. 反向优势(Ygent 已超 WorkBuddy,不需要对齐)
|
||||
|
||||
- **团队 / 岗位**:80+ `team_*` 表,覆盖成员、岗位、计划、执行、复核、产出、恢复、调度(`team/*.rs`, `TeamOffice.tsx`)。
|
||||
- **项目任务**:版本化任务、验收/复核/续跑(`project_tasks.rs`, `ProjectTasks.tsx`)。
|
||||
- **资料库**:版本化物料 + 冻结引用 + 经验沉淀(`library.rs`, `knowledge.rs`);P0/P1 已接入。
|
||||
- **A2A 协作**:自研调度器 + 因果预算 + 取消归属 + `agent_live`/`agent_replay` 重放(`collaboration_runtime.rs`)。
|
||||
- **权限治理**:`grants` 白名单 + `audit_log` + 经理只读白名单 + 员工分级冻结,层次比报告所述更细。
|
||||
- **LSP / 代码分析**:宿主自管 LSP 生命周期,禁用 OMP 原生 LSP(`lib.rs:78-94`)。
|
||||
|
||||
---
|
||||
|
||||
## 4. 前置条件与冲突提醒
|
||||
|
||||
1. **内核范围**:`AGENTS.md` 明确"当前只使用 OMP 内核""Codex 内核适配和验收暂不纳入本轮"。涉及内核的改动只按 OMP 验收。
|
||||
2. **授权取向冲突(重要)**:用户 2026-10-12 明确"给全部的授权,现阶段不考虑在现实上做这么多工作",取代了逐工具授权方案。⇒ **A2 / A3(删除回收站、命令黑名单)属于新增限制性机制**,与"完全访问不逐次确认"的当前取向存在张力,**实施前必须与用户确认**。A1 / A4 / A5 / A6 / A8 / A9 与授权无关,可直接做。
|
||||
3. **报告不可当规格**:报告为纯静态逆向,提示词全文、服务端模型路由、鉴权细节本地不可见(报告 §9 自述);tsbx 内部行为、`product.json` 变体语义均无字节级证据。**只参考其架构分层与机制存在性,不照抄实现细节**。
|
||||
4. **不虚构能力**:本文 A 档各项均为"可实施",**不代表已实现**;落地时仍需按各域既有 SOP 完成真实验收(不支持项继续如实标注)。
|
||||
5. **不引入 WorkBuddy 数据依赖**:任何导入格式兼容都是配置适配,不写其他软件的配置、不复制其凭证。
|
||||
|
||||
---
|
||||
|
||||
## 5. 建议的下一步
|
||||
|
||||
1. 先确认 §4.2 的授权取向:**是否允许新增删除回收站 / 命令黑名单这类限制机制**。
|
||||
2. 若允许,按 A1 → A2/A3 → A4 → A5 → A6/A8/A9 顺序落地(A1 无争议可先做)。
|
||||
3. B 档单独立项:建议先做 **B1(多媒体)** 或 **B2(专家 P3)**,前者是功能空白、用户可感知,后者方案已定稿。
|
||||
4. C 档维持"不做",在相关文档中继续如实声明现有局限。
|
||||
@@ -0,0 +1,209 @@
|
||||
# Ygent ↔ WorkBuddy 原生渲染精确差异清单(2026-10-08)
|
||||
|
||||
> 阶段收尾与当前实现状态见[进度汇总](ygent-chat-stage-summary-2026-10-08.md)。下文40项为历史采集基线,不是当前未完成数量;后续通用样式、字体、完整时间线/锚点折叠及动作摘要修复以动态记录为准。
|
||||
|
||||
> 对标范围已明确包含真实流式交互。动态P0、必测事件序列和证据分级见 [动态交互对标清单](ygent-chat-interaction-parity.md)。本文件的历史画面通过不等价于流式通过。
|
||||
|
||||
> 后续过程修复:真实原生1335×916、DPR1、默认2档下,D11—D13、D16、D18—D20、D28、D31已修复并检查折叠往返;D15的尺寸/位置/颜色及D17文字色已对齐,图标path形状仍需核验。首命令面板dy227.25、752×198.75已匹配,D23通过此状态复测。最终正文仍因缺少reasoning及其包装留白提前48.25px,D25—D26未完成;不能硬补高度。详细结果见动态清单中的“当前已验证的局部交互”。
|
||||
|
||||
> 后续字体修复:[字体对齐验收](ygent-font-parity.md)。D01—D05、D14、D21—D24、D27、D32—D33涉及的字体/行高/文字行框已处理;此处40项保留为修复前基线,不能把其他层级、间距和操作栏缺失视为已修复。D23面板总高另需随着后续层级调整复测。
|
||||
|
||||
本轮确认 **40项对话区渲染、结构及折叠差异**,另列 **4项外围差异、5项源码交互缺口、15项待验收场景**。这是已检查范围的清单,不是整个产品缺口总数。仅梳理、采集和定位,本轮没有修改对话区实现。P0优先恢复当前同一对话的形态和交互,P1收敛细节,外围与复杂交互后置。
|
||||
|
||||
## 采集条件和坐标
|
||||
|
||||
- 均为真实原生渲染器:WorkBuddy CDP 9223,Ygent Tauri WebView2 CDP 9335。没有模拟IPC或fixture。
|
||||
- 同一“处理大文件”对话,锚点为移动项目请求后的最后一个取消回合。YG真实会话5,829条消息。
|
||||
- WB原视口1200×762,临时调整YG真实窗口到相同视口;DPR均1、scale均1、字号均默认2档。
|
||||
- A:过程收起;B:过程展开,首个运行命令和意图结果展开。等待动画稳定并贴底后采集。没有发送消息、执行工具、读取或展开深度思考正文。
|
||||
- `(x,y,w,h)`为页面视口CSS px;`dy`为元素顶部减头像行顶部,用于排除不同历史高度和滚动位置。负y表示在滚动区域上方,不表示CSS错误。
|
||||
- A头像行:WB y267.98,YG y322.69;B头像行:WB y-40.02,YG y52.69。两端均贴底;不能把绝对y差直接当作需要修复的margin。
|
||||
- 字体通过`CSS.getPlatformFontsForNode`检查实际命中字库,不只读取font-family。数值保留两位小数,0.1px以内取整不单列缺陷。
|
||||
- [整理后的几何、样式、字体证据](reference/workbuddy/render-audit-2026-10-08.json)。原始DOM和截图保存在私有目录`C:\Users\Administrator\.ygent\imports\render-audit-20261008`,不入库。
|
||||
- 主比较为1200×762;YG1335×916已单独采集,但WB1335同条件比较未完成,不将结论外推到所有尺寸。
|
||||
|
||||
## 需要纠正的历史判断
|
||||
|
||||
WB用户气泡外层声明13px,内部Slate实际文字是15px;输入容器声明14px,内层编辑器实际也是15px。此前仅看外层得到的规格不能继续作为验收目标。YG“过程消息”最终级联命中13px,即便某条源码规则已写参照值也不能算通过。
|
||||
|
||||
## D01—D10:字体、用户气泡和顶栏
|
||||
|
||||
| ID/优先级 | 具体位置 | WorkBuddy实测 | Ygent实测 | 差异、目标与代码定位 |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| D01 P0 | 助手中文正文`.cr-markdown p`↔`.md p`;对话标题 | 实际Noto Sans SC,强调使用Bold | 实际Microsoft YaHei,强调使用Bold | 同字号仍有字形/笔画/行框差。先匹配字库和回退;`src/styles/tokens.css:78` |
|
||||
| D02 P1 | 头像右侧名称,x393 | Arial Bold,14px/24.5px,宽78.31 | Segoe UI Semibold,14px/24.5px,宽74.67 | 文字短3.64px;头像和10px间距已一致,不能扩大整个头像行;`.assistant-name` |
|
||||
| D03 P0 | 命令/结果灰面板英文,x375,内容宽720 | Courier New,中文回退NSimSun | Consolas,中文回退NSimSun | 等宽字库不同导致换行字符不同;`src/styles/chat.css:763`、`:775` |
|
||||
| D04 P0 | 最新用户气泡的内部实际文字 | Slate15px/26.25px,内部p15px/26.7px | `.msg.me .txt`13px/19px | 少2px;不能以WB外层13px为参照;`src/styles/chat.css:436` |
|
||||
| D05 P0 | 最新用户气泡,右边均x1111 | x755.84、w355.16、h44.59 | x800、w311、h35 | 左边向右缩44.16、高度少9.59;padding8×12、底色/圆角已一致。修内层文字,不写死355.16宽度 |
|
||||
| D06 P1 | 左上“处理大文件”,(304,46),h24 | 黑色rgb(0,0,0) | rgb(31,35,40) | 坐标/16px字号/24px行高一致,颜色冷灰;`.chat-title` |
|
||||
| D07 P1 | 顶栏五按钮,x1012/1048/1084/1120/1156,y42,32×32 | 黑70% | #5b6472 | 坐标都一致,颜色偏蓝灰;不能再整体平移按钮组 |
|
||||
| D08 P1 | 第二个分享按钮,(1048,42) | 弯曲分享箭头 | 从托盘向上导出箭头 | 图形不同,应核对SVG/path;`src/components/ChatView.tsx:464` |
|
||||
| D09 P1 | 第四个概览按钮,(1120,42) | 纸张/文档轮廓 | 四块网格 | 外框一致,内部图形不同;`ChatView.tsx:485` |
|
||||
| D10 P1 | 对话标题旁的编辑入口 | 有“编辑标题”按钮,默认隐藏 | h1只有文字,无对应按钮 | 侧栏重命名不等价;已确认DOM缺失,hover后坐标待验收 |
|
||||
|
||||
## 路径标签及思考事件位置补齐(2026-10-08)
|
||||
|
||||
通用Markdown行内代码组件根据真实路径关联渲染文件/目录标签,其他代码不变。普通会话在自身工作目录下通过IPC只读分类;参照导入保留来源cwd下核实的路径关联。原生YG/WB同一`ygent`标签68.25×20、字号15/行高22.5、padding1px 4px、颜色#1470b4、背景#e9eef2、文件夹图标15×15已匹配;非按名字直接装饰的静态标签。标签键盘/点击接实际opener,未在参照采集中自动打开外部应用。
|
||||
|
||||
导入旧规则丢弃全部reasoning事件,现只保存存在和位置标记,不提取内部正文;相邻可见消息前通过通用组件呈现“深度思考”。标题15px/26.25px、灰色、包装padding2px 0。此为D25的数据/标题部分补齐,内容展开、真实思考流式阶段及D26上下层间距尚未通过,不能将标题出现等同于reasoning交互完整。
|
||||
|
||||
普通会话和参照会话共用TurnBlock/ToolCard/Markdown;本次工具摘要跨会话原生样式一致。仍需覆盖普通完成、单/多工具、特殊取消的分组标题、默认折叠和块间距,禁止按参照会话名称/ID加样式补丁。
|
||||
|
||||
## 失败命令显示规则修正(2026-10-08)
|
||||
|
||||
用户补充同一“检查目标位置与源目录”失败命令截图后,真实WorkBuddy CDP确认:外层“运行命令”摘要使用14px灰色终端图标,不因失败替换红叉;下方意图行`.cr-tool-head__icon--error`使用14px灰色圆形感叹号。失败数据与视觉位置独立,不能由Ygent自身的红叉规则推断参考行为。Ygent现保留toolError数据,按这一分层显示;终端图标/失败图标/箭头使用当前原生DOM核实的向量路径。
|
||||
|
||||
长结果面板宽752、高300、padding12px 16px,10px滚动条使文本可用宽710。命令12px/19.2px、输出12px/18px,pre-wrap且word-break:break-all。之前Ygent默认滚动条和overflow-wrap:anywhere导致长命令断行不同,现已修正。输出还遗漏非零Exit Code对应的`执行失败 (退出码: 1)`末行,已恢复。真实Ygent/CDP下同一命令高度95.9375、输出756,与WB一致;完整可见输出文本比较相同。
|
||||
|
||||
此结果覆盖该失败命令的局部显示,不代表整段完成:截图中的“深度思考”、路径标签及上层布局仍在原有待办中;未伪造推理内容。其他工具类别、运行中/取消/信号终止的图标策略仍须分别验证。此前补验中“失败红叉保留”仅是当时YG状态,以上修正取代该视觉规则。
|
||||
|
||||
## 取消历史工具样式补验(2026-10-08)
|
||||
|
||||
此前D20等工具样式修复只限定在`.process-fold`,遗漏了“已取消”展开后的`.turn-history`:同一ToolCard上方仍为2px竖线、4px左缩进、摘要负margin和蓝灰文字,下方已使用无边框的中性灰样式。现将共同规则移至基础`.tool`,移除父容器限定覆盖,历史/过程/实时回合共享基础外观;失败红叉与运行中状态独立保留。
|
||||
|
||||
真实Ygent WebView2、1335×916下,已核验同一取消回合中的5条历史命令和1条过程命令:边框/左缩进/摘要margin均为0,文字rgba(0,0,0,0.5)、15px/26.25px;逐条展开意图和结果,详情上间距4px,结果面板宽752px、padding12px 16px、左边缘对齐。2条失败命令仍保留红色状态图标。操作后恢复各工具原有展开状态;未发送消息或执行命令。这是Ygent两条渲染路径的一致性补验,未据此新增WorkBuddy失败图标或实时状态验收结论。
|
||||
|
||||
## D11—D20:回合间距、过程标题和工具层级
|
||||
|
||||
| ID/优先级 | 具体位置 | WorkBuddy | Ygent | 差异与代码定位 |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| D11 P0 | 头像行底→取消耗时行顶 | 12px;状态dy36.5 | 16px;状态dy40.5 | 下移4;头像margin12又叠加msg gap4;`.assistant-header`、`.msg` |
|
||||
| D12 P0 | 状态行底→首段正文顶 | 12px | 8px | 少4,抵消D11,所以首段dy都74.75;不能只看首段坐标;`.turn-body`与WB文本块margin |
|
||||
| D13 P0 | 首段正文底→过程消息顶 | 12px;过程dy140.25 | 8px;过程dy136.25 | 过程标题相对头像提前4;统一gap不能模拟所有局部间距 |
|
||||
| D14 P0 | “过程消息”标题 | 15px/26.25px,文字宽60;点击行76×26.25 | 13px/20.8px,文字宽52;点击行80×26.80 | 文字小2px但按钮反而更宽;`src/styles/chat.css:845`、`.mf-label` |
|
||||
| D15 P1 | 过程标题右侧箭头 | x423,12×12,黑50% | x419,14×14,#8a93a3 | 左移4、变大2,颜色/线形不同;`.mf-arrow`,连同标题字号/gap/padding修复 |
|
||||
| D16 P0 | 过程标题底→运行命令顶(B) | 2px;命令dy168.50 | 8px;命令dy171.05 | 命令相对头像晚2.55;需process-inner局部padding;`.mf-body` |
|
||||
| D17 P1 | 运行命令文字、意图和终端图标 | 黑50% | #5b6472 | 整体偏蓝灰;摘要15px/26.25已一致;`.fn`、`.tool-intent`、`.tool-ico.command` |
|
||||
| D18 P0 | 意图“切换工作目录后重试移动”左侧 | x359有独立14px终端图标,文字x381 | 文字x381,但本层图标缺失 | 不是第一层运行命令图标能代替;`TurnBlock.tsx:190` |
|
||||
| D19 P0 | 工具意图及邻近右箭头 | 独立可点击/折叠;文字宽154,标题主区192,有箭头 | `.tool-intent`普通div,宽730,无箭头/折叠 | WB“过程→运行命令→意图→结果”,YG少一层;需结构和状态共同补齐 |
|
||||
| D20 P0 | 展开工具左边x≈359 | 无贯穿意图/面板的竖线 | 旧工具卡border-left仍形成竖线 | 检查`.tool`border-left/padding和`.tool-row`负margin,不能用白色遮盖 |
|
||||
|
||||
## D21—D31:命令结果、深度思考和回合尾部
|
||||
|
||||
| ID/优先级 | 具体位置 | WorkBuddy | Ygent | 差异与代码定位 |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| D21 P0 | 灰面板命令结束→stdout | 独立`__command`与`__output`,块间4px | 一个pre拼接命令/输出 | 缺分块,无法独立设行高;`formatToolResult`、`ToolCard` |
|
||||
| D22 P0 | stdout正文,WB(x375,y283.98)(B) | 12px/18px,当前5行高90 | 同命令共用12px/19.2px | 每行多1.2;命令本身19.2已一致,不应全部改18 |
|
||||
| D23 P1 | 命令灰面板(B),x359,w752 | h198.75,dy227.25 | h200.69,dy231.80 | 高多1.94,顶部晚4.55;圆角16、padding12×16、内容宽720已对齐,不写死高度 |
|
||||
| D24 P1 | bash标签与代码文字 | 黑90% | #1f2328 | 冷灰字色;背景同为#f2f2f2,不再调整背景 |
|
||||
| D25 P0 | 结果面板后、最终正文前(B) | reasoning外框h30.25、dy440;标题dy442,15px/26.25 | 整段缺失 | 缺“深度思考”收起行;normalized数据未映射该段,需要数据/时间线联合处理。本轮未读取正文 |
|
||||
| D26 P0 | 过程组底→最终正文(B) | 12px,最终正文dy486.25 | 8px,最终正文dy440.48 | 最终正文提前45.77,含D25及过程高度差;不能硬加45.77margin |
|
||||
| D27 P0 | “用户已取消” | 15px/20px,内容宽75 | 13px/20.15px,外框拉伸752 | 少2px且渲染类型不同;`chat.css:527`、`TurnBlock.tsx:471` |
|
||||
| D28 P0 | 最终正文底→取消提示 | 0px | 8px | YG多统一gap;需取消状态局部规则,不能清零所有回合间距 |
|
||||
| D29 P0 | 取消提示下所有产物入口 | x359;B y504.48,129.83×25,15px/25,“查看所有产物(5)” | 无本回合尾部入口 | 顶栏概览不等价;需真实回合产物关联和计数,不硬编码5 |
|
||||
| D30 P0 | 所有产物下助手操作栏 | B(359,537.48,547.59,38.25);复制/赞/踩/朗读/重试/分享/更多,消耗/模型/时间 | 助手回合整行缺失;MessageToolbar只用于用户 | 缺整行,不是像素偏移;入口、排列和后台能力分别验收,不伪造消耗/模型数据或放无效按钮 |
|
||||
| D31 P1 | 关闭过程再重新展开 | 本轮首命令/意图展开状态保留 | ToolCard卸载后open重置false | 相同点击看见不同内容;本轮往返操作与useState/条件挂载已确认;需状态存放策略 |
|
||||
|
||||
## D32—D40:输入编辑区、提示和滚动条
|
||||
|
||||
| ID/优先级 | 具体位置 | WorkBuddy | Ygent | 差异与代码定位 |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| D32 P0 | 输入实际文字,左上(365,605) | Slate15px/26.25;空p高28.38 | textarea14px/21 | 少1px、行高少5.25;外框64px一致不代表文字一致;`chat.css:1105` |
|
||||
| D33 P1 | 输入占位 | 实体span15px/26.25,黑90%×opacity.5 | ::placeholder14px/21,黑40% | 字号见D32;深浅不同;YG问号与@之间多一个空格;Composer placeholder |
|
||||
| D34 P1 | 权限项文字及警告图标 | 文字(x429,y687,h20),#b42c3f,13px/20;盾牌感轮廓 | (x430,y688.5,h17),#d5304f,13px/normal;圆圈叹号 | 右移1、下移1.5、行框少3,图形/颜色不同;`Chips.tsx:43` |
|
||||
| D35 P1 | 右下模型选择 | 品牌图标+模型名+6×3箭头,文字黑90% | 品牌图标缺失、蓝灰文字、15px caret外框 | 当前Deepseek与gpt-6-luna最高是配置差异,不强改模型;对齐真实模型的图标槽/字体/箭头 |
|
||||
| D36 P1 | 模型项左侧圆环,中心约(885.27,697) | 有上下文/用量类指示控件 | spacer空白 | 控件缺失;准确语义/tooltip待验收,不用常驻loading伪装 |
|
||||
| D37 P1 | 发送按钮,均(1087,681,32,32) | 白实心纸飞机/上行形状 | 细线向上箭头,路径约8.4×10 | 内部轮廓不一致,外框无需移动;Composer SEND |
|
||||
| D38 P1 | 框下免责声明 | 外框(348,726,784,36),12px/20,黑30%,内部padding定位 | (348,736,784,14),12px/14,#8a93a3 | 外框含padding,不能把y差10直接当文本偏移;颜色/行高不同,需对内部基线;`.composer-hint` |
|
||||
| D39 P1 | 历史最右滚动条 | 宽6、thumb黑20%、圆角3 | 宽10、thumb蓝灰14%、圆角4 | 粗4且颜色不同;改宽会影响可用宽度和居中,应联动复测正文;`chat.css:373` |
|
||||
| D40 P1 | 滚动条上下端小箭头 | 当前截图可见原生小三角,pseudo display inline | 未呈现同样箭头,pseudo display block | 宿主可能影响外观,需匹配可见效果和点击/滚动表现,不机械复制display |
|
||||
|
||||
## 精确定位:相对回合头像行
|
||||
|
||||
A过程收起,除头像名称x393外,以下锚点x359。
|
||||
|
||||
| 锚点 | WB绝对y | YG绝对y | WB dy | YG dy | 说明 |
|
||||
| --- | ---: | ---: | ---: | ---: | --- |
|
||||
| 头像行 | 267.98 | 322.69 | 0 | 0 | h24.5一致 |
|
||||
| 取消耗时 | 304.48 | 363.19 | 36.5 | 40.5 | YG相对晚4 |
|
||||
| 首段正文 | 342.73 | 397.44 | 74.75 | 74.75 | 上下间距抵消,不能误判 |
|
||||
| 过程消息 | 408.23 | 458.94 | 140.25 | 136.25 | YG提前4 |
|
||||
| 最终正文 | 446.48 | 493.73 | 178.5 | 171.05 | YG提前7.45 |
|
||||
| 用户已取消 | 472.73 | 527.98 | 204.75 | 205.30 | 近似同起点但字号/前间距不同 |
|
||||
| 所有产物 | 504.73 | 缺失 | 236.75 | — | 实际入口缺失 |
|
||||
|
||||
B过程、首命令、意图结果展开。
|
||||
|
||||
| 锚点 | x | WB绝对y | YG绝对y | WB dy | YG dy |
|
||||
| --- | ---: | ---: | ---: | ---: | ---: |
|
||||
| 头像行 | 359 | -40.02 | 52.69 | 0 | 0 |
|
||||
| 首段正文 | 359 | 34.73 | 127.44 | 74.75 | 74.75 |
|
||||
| 过程消息 | 359 | 100.23 | 188.94 | 140.25 | 136.25 |
|
||||
| 运行命令 | 359 | 128.48 | 223.73 | 168.50 | 171.05 |
|
||||
| 意图文字 | 381 | 158.73 | 255.98 | 198.75 | 203.30 |
|
||||
| 灰面板 | 359 | 187.23 | 284.48 | 227.25 | 231.80 |
|
||||
| bash标签 | 375 | 199.23 | 296.48 | 239.25 | 243.80 |
|
||||
| 命令文本 | 375 | 222.42 | 319.67 | 262.44 | 266.98 |
|
||||
| stdout | 375 | 283.98 | 没有独立块 | 324.00 | — |
|
||||
| 深度思考标题 | 359 | 401.98 | 缺失 | 442.00 | — |
|
||||
| 最终正文 | 359 | 446.23 | 493.17 | 486.25 | 440.48 |
|
||||
| 用户已取消 | 359 | 472.48 | 527.42 | 512.50 | 474.73 |
|
||||
| 所有产物 | 359 | 504.48 | 缺失 | 544.50 | — |
|
||||
| 助手操作栏 | 359 | 537.48 | 缺失 | 577.50 | — |
|
||||
|
||||
## 已对齐的基准,不应继续盲调
|
||||
|
||||
| 元素 | 两端共同值(1200×762) |
|
||||
| --- | --- |
|
||||
| 主区/历史视口 | 主区x280,w920;滚动视口(280,86,920,506) |
|
||||
| 正文列 | x359,w752,右边1111 |
|
||||
| 标题/顶栏按钮 | 标题(304,46),16px/24;五按钮位置和32×32尺寸一致 |
|
||||
| 头像行 | x359,头像24×24,名称x393,gap10,h24.5 |
|
||||
| Markdown默认字号 | 根17.143/30.0002;段落15.0001/26.2502;首段h53.5、最终段h26.25 |
|
||||
| 普通inline code | Device or resource busy宽197.69、高18、字号15.0001 |
|
||||
| 用户气泡外壳 | #f2f2f2、padding8×12、圆角16且右下直角;实际文字另见D04 |
|
||||
| 输入外框 | (348,592,784,134),1px #e6e6e6,圆角24,同一双层阴影 |
|
||||
| 编辑宿主/工具栏 | 宿主(349,605,782,64),左右padding16;工具栏(349,669,782,56),padding12 |
|
||||
| 发送按钮外框 | (1087,681,32,32),圆形灰底;内部图形未齐 |
|
||||
| 命令面板壳层 | w752、内容720、圆角16、#f2f2f2、padding12×16 |
|
||||
|
||||
## 4项外围壳层差异,另行记录
|
||||
|
||||
| ID/位置 | 差异 | 范围说明 |
|
||||
| --- | --- | --- |
|
||||
| X01 顶部 | WB菜单与全局图标,主顶栏(280,30,920,56);YG品牌标题栏,主顶栏(280,46,920,40) | 宿主结构不同,但内部对话标题/按钮坐标一致;不应为复制菜单破坏这些坐标 |
|
||||
| X02 左栏x0—280 | WB中性浅灰;YG冷色背景及顶部渐变 | 整窗视觉仍不同;核心对话优先 |
|
||||
| X03 当前选中任务 | WB项目ygent下子项,文字约(48,417)、条h31;YG独立任务,文字约(20,240)、条h35 | 同时含层级/导入归属/不同列表数据;不能硬移整个侧栏 |
|
||||
| X04 左下y626—744 | WB邀请卡、头像账号;YG设置与收起侧栏 | 外围产品入口;不默认复制平台商业体系 |
|
||||
|
||||
## 5项源码确认的交互缺口,未发送消息实测
|
||||
|
||||
| ID/位置 | YG已确认实现 | 与目标的关系 |
|
||||
| --- | --- | --- |
|
||||
| C01 左下+按钮(361,681,32,32) | Composer.tsx:115仅showToast附件上传M4落地 | 不是可用附件入口,需添加/展示/删除/提交链路 |
|
||||
| C02 编辑器@与/ | 普通textarea onChange/Enter,未接候选菜单 | 占位提示承诺的上下文/技能交互未接通;菜单、chip、键盘导航待做 |
|
||||
| C03 生成中发送 | Composer.tsx:68 pending直接return,按钮变停止 | 暂无忙时队列UI/编辑删除立即发送;需真实流式测试 |
|
||||
| C04 字号设置/快捷键 | 六档滑杆与token表已实现;设置旁暴露Markdown px;未找到对应全局Ctrl+-/Ctrl++/Ctrl+0处理 | token参数一致不等于设置形态/快捷键/持久化/全覆盖一致 |
|
||||
| C05 长会话与系统事件 | 当前全量829消息;分页、回退、队列、模型切换/压缩事件未全部接通 | 旧“几十条消息无需虚拟列表”的规模假设失效;两端DOM总高不能直接推出性能结论 |
|
||||
|
||||
## 15项待验收场景,暂不声称一致或确定差异
|
||||
|
||||
| 编号 | 精确验收状态/位置 | 需要检查 |
|
||||
| --- | --- | --- |
|
||||
| V01 | 两端1335×916 | 正文/输入上限、换行、贴底;本轮仅YG该尺寸已采集 |
|
||||
| V02 | 窄窗、最小980×640 | padding切换、模型权限挤压、横向溢出、标题省略 |
|
||||
| V03 | 六档1—6实际设置 | 正文、用户文字、过程、代码、输入、按钮行框;操作后恢复原档 |
|
||||
| V04 | 设置滑杆 | 轨道刻度thumb颜色、键盘/点击调节、重启持久化 |
|
||||
| V05 | 用户气泡hover | 时间/复制/编辑坐标、出现时机、hover间隙、键盘焦点 |
|
||||
| V06 | 顶栏搜索打开/有命中/无命中 | 输入宽高、计数、导航、高亮、折叠命中与滚动定位 |
|
||||
| V07 | 分享模式 | 选择框、底部操作条、复制导出;与平台分享链接分开 |
|
||||
| V08 | 最近任务/概览popover | 锚点、行距、最大高、外部关闭、产物计数/跳转 |
|
||||
| V09 | 右工作台打开 | 两列变化、主列收缩、工具和产物列表、空态 |
|
||||
| V10 | 真实表格 | 字体、padding、横滚、添加到对话hover位置/引用内容 |
|
||||
| V11 | Markdown代码块 | 与命令面板分开:语言栏、复制、字库、背景、横滚、最大高 |
|
||||
| V12 | 真实widget/SVG | iframe高度、前后间距、响应尺寸、产物链接;不沿用模拟页结论 |
|
||||
| V13 | 流式/失败/取消/重试 | 文案、耗时、按钮状态、错误、重复丢消息、折叠稳定 |
|
||||
| V14 | 上翻后新消息/展开变高 | 阅读锚点、自动跟随条件、回底按钮位置/appearance |
|
||||
| V15 | 图片附件引用路径长文本 | tooltip/图标/点击、加载尺寸、复制、310px长气泡、输入增长/IME |
|
||||
|
||||
## 修复顺序与完成标准
|
||||
|
||||
用户明确动态目标后的优先顺序:先处理 [S01/S02/S06事件管线](ygent-chat-interaction-parity.md),建立增量、折叠、滚动与取消的双端验收,再继续下列静态细节;不能只沿像素微调顺序推进。
|
||||
|
||||
1. 先修真实文字和字库:D01—D05、D14、D27、D32。重测六档,不仅核对font-size数值。
|
||||
2. 恢复过程真实层级:D11—D23、D25—D28、D31。摘要、意图、命令、输出、reasoning应有独立可测间距和状态,移除旧工具卡干扰。
|
||||
3. 补当前回合尾部:D29—D30。真实产物关联、操作栏及有依据的元数据,分项接通交互。
|
||||
4. 收敛图标颜色滚动:D06—D10、D24、D33—D40。改尺寸后重新核对正文与输入,避免引入全局偏移。
|
||||
5. 扩展V01—V15验收矩阵和C项;明确外围X项是否纳入同轮,平台能力不阻塞核心对话区。
|
||||
|
||||
每项完成需提供同条件原生采集,记录字库、字号档位、视口/DPR、展开状态、rect/样式及行为结果。字库差先消除;关键几何允许不超过1px取整误差,缺失结构/入口/错误交互不按像素误差豁免。无法获取的元数据和未操作场景明确标记,不伪造数据、不以“组件存在”标记已完成。
|
||||
@@ -0,0 +1,269 @@
|
||||
# 岗位与项目团队方案
|
||||
|
||||
日期:2026-10-11。版本:方案 v0.6(首版已接入,长期方向继续讨论)。
|
||||
|
||||
最新管理设计见 [数字员工项目管理落地方案](ygent-team-management-plan.md),制度依据见 [项目管理调研](project-management-research-2026-10-11.md)。后续责任领域、参与式规划、任务承接与人员交接按新方案讨论和分阶段实施;当前尚未接入这些新增流程。员工实施统一暂停,早期自动承接说明仅保留历史背景;真实行为以 [进度及 SOP](ygent-team-integration.md) 的最新阶段为准。
|
||||
|
||||
历史首版状态:按用户要求已接入创建岗位 → 项目入职 → 分配范围 → 自动承接明确任务 → 多轮协作 → 提交验收的 OMP 首版,实际范围与证据见[进度及 SOP](ygent-team-integration.md)。首期采用规则隔离,操作系统沙盒留作后续选项。本文保留后续方向,不代表所有建议已实现;自动承接须用户明确分配任务并启用成员设置,不扩大原有操作权限。
|
||||
|
||||
## 1. 目标与已明确的需求
|
||||
|
||||
将当前「专家」改名为「岗位」,支持用户按实际需要定义岗位。各岗位有不同职责、技能及默认模型;项目可以分配岗位,通过「入职」确定其负责内容,再承接和推进工作范围内的任务。
|
||||
|
||||
希望构建能持续协作的团队,覆盖销售、开发、交付与售后。项目不局限于代码仓库,工作目录也可包含文档、图片及业务材料。成员之间应能多轮提问、补充、交付和返工。
|
||||
|
||||
必须防止 Agent 为完成自己的目标而越界代做其他岗位的工作。成员在职责范围内完成交付;依赖其他岗位的工作,通过协作请求、任务依赖和交接推进,不能自行扩大负责范围。
|
||||
|
||||
### 讨论状态
|
||||
|
||||
| 内容 | 当前状态 |
|
||||
|---|---|
|
||||
| 专家改名为岗位,配置职责、技能和模型 | 首版已接入,范围见进度及 SOP |
|
||||
| 项目分配岗位,通过入职确定负责范围 | 首版已接入,范围见进度及 SOP |
|
||||
| 形成销售、开发、售后协作团队 | 用户明确提出的目标 |
|
||||
| 岗位模板与项目成员分开,复用任务和对话 | 已获整体方向认可的建议;细节可调整 |
|
||||
| 按事件自动承接任务,交付后验收 | 首版按明确负责人及完整条件自动承接,默认关闭;人工验收 |
|
||||
| 防止越界,表达跨岗位依赖和交接 | 用户明确要求;首期采用规则隔离 |
|
||||
| 文件、Shell、连接器的强制隔离 | 留作后续增强,首期不依赖沙盒;尚未实现 |
|
||||
|
||||
## 2. 概念保持简单
|
||||
|
||||
| 概念 | 职责 | 生命周期 |
|
||||
|---|---|---|
|
||||
| 岗位 | 可复用的职责、方法、技能、连接器需求和默认模型 | 全局定义,可供多个项目选用 |
|
||||
| 项目成员 | 某个岗位在一个项目中的具体安排 | 入职后持续存在,可暂停或退出项目 |
|
||||
| 项目任务 | 目标、负责人、范围、依赖、进展与验收 | 复用现有项目任务,不随一轮对话结束 |
|
||||
| 执行对话 | 某项工作的讨论、工具调用和执行证据 | 可多轮继续,绑定真实成员、任务和运行 |
|
||||
| 临时子 Agent | 协助成员处理边界明确的局部工作 | 复用现有协作机制,责任仍归原成员 |
|
||||
|
||||
界面主要呈现「岗位」「项目成员」。不新增部门、职级或组织架构。按用户新增要求,每个项目默认一位项目经理,专职审核职责、拆解和分配任务,不参与编码,不具备文件修改权限。经理不出现在全局岗位列表,不能删除或禁用;可在项目内修改名称、职责、模型、推理强度和技能,各项目配置独立。
|
||||
|
||||
项目成员不绑定某个发起对话的寿命。关闭一个对话或结束某次委派,不等于成员离职;暂停成员与取消当前执行应有明确区分。具体取消归属还需结合现有子 Agent / 平级对话机制设计,不能直接照搬子 Agent 的父级取消规则。
|
||||
|
||||
## 3. 岗位定义
|
||||
|
||||
建议包含以下配置:
|
||||
|
||||
- 名称、说明与职责:能处理哪些工作,如何判断交付质量。
|
||||
- 技能引用:从已安装技能中选择,复用稳定组件 ID,不重复复制安装。
|
||||
- 连接器需求:声明所需服务和工具能力;凭证与实际操作授权独立管理。
|
||||
- 默认模型:选择已有渠道、模型及其支持的思考配置;渠道决定请求协议。
|
||||
- 工作要求:输出、验证、交接和需要提出澄清的问题。
|
||||
|
||||
同一岗位可以加入多个项目,但项目中的任务、记忆、对话、授权和运行状态不能因此互通。岗位模板调整应记录版本,并在下一回合边界采用;运行中的模型、目录与能力快照保持稳定。项目是否允许覆盖岗位默认模型、模板更新是否需要成员确认,留作下一轮讨论。
|
||||
|
||||
长期成员不等于永久运行的模型进程。空闲时保留身份、任务和上下文索引,需要工作时再恢复执行。
|
||||
|
||||
## 4. 项目入职
|
||||
|
||||
项目详情增加「团队」,用户选择岗位后安排:
|
||||
|
||||
1. 负责范围:业务领域、模块、客户群体或明确产物。
|
||||
2. 参考资料:项目概况、相关资料、工作目录和已有任务。
|
||||
3. 协作与验收:向谁交付、依赖哪些成员、由谁验收。
|
||||
4. 接任务方式:人工分配,或自动承接归属明确的任务。
|
||||
|
||||
建议入职后进行一次有边界的熟悉工作:读取相关概况与任务,按需检索资料,形成职责理解、可承接任务和待澄清问题。不一次性装入整个仓库、全部资料或所有聊天历史。
|
||||
|
||||
入职本身不授权执行所有未完成任务。自动执行依据用户设置的工作范围、接任务方式和操作权限;存在歧义时提出建议,避免自行扩大业务目标。
|
||||
|
||||
## 5. 任务分配与自动推进
|
||||
|
||||
复用现有任务状态:「待办/进行中/阻塞/待验收/已完成/已取消」。负责人和自动调度是新增能力,不能以已有任务状态代替实际运行。
|
||||
|
||||
建议每个任务有一个主要负责人,可有多个协作成员。确定交付责任后,由宿主原子领取和排队,防止重复领取或重复执行。用户调整任务仍使用版本校验,Agent 不能覆盖较新的人工修改。
|
||||
|
||||
工作循环:
|
||||
|
||||
```text
|
||||
任务新增 / 依赖解除 / 收到协作消息
|
||||
→ 检查负责范围、前置条件、暂停状态与执行额度
|
||||
→ 明确归属的任务领取并排队
|
||||
→ 执行、记录进展、验证、提交验收
|
||||
→ 通过后完成;需要修改时继续原任务
|
||||
```
|
||||
|
||||
- 归属不清或多人范围重叠:提出分工建议,不让多个成员竞相处理。
|
||||
- 任务拆解:围绕已有目标,明确子任务的范围和验收;不按每条工具调用建任务。
|
||||
- 缺少信息:记录阻塞原因和解除条件,向对应成员或用户提问。
|
||||
- 任务等待期间:释放运行占用,可处理其他已具备条件的任务;避免反复请求模型询问进度。
|
||||
- 完成判定:保留交付结果、验证依据和未验证项,遵守子任务与依赖检查。回复结束不是任务完成。
|
||||
- 用量控制:并发、轮次和预算由宿主执行;具体默认值另行确定,不在本稿直接扩大现有并发。
|
||||
|
||||
自动推进由事件触发,事件需要去重和可恢复的工作状态。首版建议以应用运行期间为边界,最小化继续运行。退出应用后的持续执行需要单独的后台服务,不属于现有能力。重启可检查待办队列,但结果不确定的中断操作不能直接重放。
|
||||
|
||||
## 6. 多轮协作、上下文与交付
|
||||
|
||||
成员使用既有协作消息处理请求、补充、提问、回复、结果和通知,以稳定关系和 replyTo 追踪往来,不为每次回复新建成员。消息处理与任务领取需关联去重,避免一项工作同时经消息和任务触发两次。
|
||||
|
||||
任务记录责任、依赖和验收;消息记录交流;执行对话保留完整过程。三者相互关联,不以聊天正文解析结果直接替代任务事实。
|
||||
|
||||
成员可调用临时子 Agent,委派范围不能超过成员当前任务范围;结果由原负责人核对。角色说明、协作消息和子 Agent 自报身份均不能扩大权限或代替用户授权。
|
||||
|
||||
建议成员保留职责、经确认的项目知识和任务索引,具体任务使用可多轮继续的执行对话,避免所有工作永久堆入一个无限增长的聊天。资料采用已有项目范围及版本机制,运行时冻结引用,后续撤销仍优先;待定判断不得写成已确认事实。
|
||||
|
||||
通用业务示例:渠道拓展记录客户需求及来源 → 建立需求任务 → 开发成员澄清并拆解 → 实现和验收 → 售后准备说明并跟进。销售、售后使用各自的技能、连接器和交付条件,不强制依赖代码目录。对外发送、发布和退款等操作依照明确授权范围执行。
|
||||
|
||||
## 7. 职责边界与越界处理(首期采用规则隔离)
|
||||
|
||||
### 7.1 统一岗位、入职与任务规则
|
||||
|
||||
首期以明确规则引导 Agent 分工,配合任务依赖、协作交接与交付检查。暂不接入操作系统沙盒,也不以完成命令隔离研究作为岗位功能的启动条件。规则隔离属于行为约束,不能保证任意 Shell 或脚本在系统层面无法越界;已有授权、项目范围校验和连接器确认继续适用。
|
||||
|
||||
建议由宿主从岗位模板、项目入职安排和当前任务组装一份范围说明,在执行对话开始、恢复、上下文压缩后以及新回合使用有效版本;稳定职责保持稳定,不反复塞入全部历史。规则至少包含:
|
||||
|
||||
- 负责什么:业务领域、模块、客户范围和交付结果。
|
||||
- 可以参考什么:资料、交付约定和相关目录;可以读取不代表可以修改。
|
||||
- 可以修改或创建什么:明确目录、文件或业务对象,必要时列出例外。
|
||||
- 不负责什么:禁止代做的其他岗位职责与操作。
|
||||
- 依赖谁:前置交付、协作对象和解除阻塞的条件。
|
||||
- 怎样完成:可核对的产物、验证方式和验收人。
|
||||
|
||||
实际范围由岗位、项目入职安排、本次任务和用户授权共同约束,不能简单相加。成员按范围领取与拆解任务;范围缺失、冲突或归属不清时澄清,不能默认获得整个项目的职责。检查与执行共用当前上下文,不为每次工具调用额外启动一次模型审查。
|
||||
|
||||
新文件按创建位置和用途判断是否属于本岗位工作,不采用“只要是自己创建就永久归自己”的规则。公共类型、共享配置和锁文件应明确负责人或修改约定,不能因为编译报错就顺手修改其他成员负责的内容。业务负责范围与工具操作授权分开:配置连接器不等于拥有全部账号操作权限;普通操作确认也不默认扩大职责。
|
||||
|
||||
Agent 不得通过改任务负责人、创建子任务、切换模型或调用另一种工具扩大范围。临时子 Agent 继承原成员的限制,再叠加本次委派范围;平级岗位之间发送请求时,接收方仍按自己的职责和任务条件判断。协作消息、技能或文件中的文字均不能自动扩大职责。允许跨范围时,由用户明确调整具体范围并记录版本;已有能力快照仍遵守回合边界约定,撤销不能仅靠下一次提示词提醒。
|
||||
|
||||
### 7.2 任务依赖与交接
|
||||
|
||||
任务依据实际工作需要配置依赖和交付条件,不预设岗位类型、固定工作阶段或执行顺序。
|
||||
|
||||
成员可以独立交付已满足条件的工作;依赖尚未满足的部分保持等待,并记录所需交付和负责成员。等待期间可处理其他职责范围内、具备执行条件的任务,不能代做依赖方的工作。
|
||||
|
||||
交接至少要说明需要什么、由谁交付、产物或版本在哪里、如何验证、何时满足条件。收到“已完成”的消息不等于自动证明依赖可用;核对交付后才能解除对应阻塞。交付不符合约定时反馈给负责人,约定变化时通知受影响的任务与成员。
|
||||
|
||||
### 7.3 通用越界流程
|
||||
|
||||
```text
|
||||
发现范围外问题
|
||||
→ 记录事实、影响与所需协助
|
||||
→ 发送给负责成员,关联任务与约定
|
||||
→ 需要等待的部分记录阻塞;可独立部分继续
|
||||
→ 收到可核对交付,检查解除条件
|
||||
→ 恢复原任务
|
||||
```
|
||||
|
||||
没有负责人、范围冲突或需要扩大范围时交给用户决定。首版不额外设计多级审批组织;是否允许指定协调成员处理部分分工,后续再讨论。
|
||||
|
||||
若执行后才发现越界,停止继续扩大改动,报告具体文件或对象、影响与交接建议。不得擅自回退其他成员或用户的修改,也不因为测试通过就隐去越界事实。提交验收时汇总实际改动、验证证据、依赖与未完成项;代码项目可结合 diff 检查,非代码工作按实际交付和操作记录核对。
|
||||
|
||||
### 7.4 首期范围与后续增强
|
||||
|
||||
| 层次 | 首期建议 | 能力边界 |
|
||||
|---|---|---|
|
||||
| 任务元数据 | 负责人、依赖、版本及领取条件由宿主校验 | 职责描述仍需 Agent 理解,不能用关键词匹配证明归属 |
|
||||
| 文件读写 | 将参考范围和可修改范围写入执行规则 | 不宣称已在文件系统层强制拦截 |
|
||||
| Shell / 脚本 | 命令的预期副作用也须遵守相同范围规则 | 不增加脆弱的命令字符串黑名单,不宣称沙盒隔离 |
|
||||
| 连接器 | 规则描述业务对象与允许行为,保留已有确认 | 岗位规则不自动扩展服务端账号权限 |
|
||||
| 交付 | 核对实际改动、结果、验证和依赖 | 事后检查可以发现问题,不能防止已发生的副作用 |
|
||||
|
||||
首期不新增独立权限语言、通用审批引擎或强制每个岗位使用独立工作副本。使用当前任务、消息、对话和授权机制完成分工闭环,并记录发生过的越界与交接问题,作为后续改进依据。
|
||||
|
||||
后续如果需要系统层强制限制,再对文件、命令、子进程和宿主连接器逐项选择并验证隔离方式。普通 worktree 与规则字段本身都不构成安全边界;沙盒技术选型暂缓。
|
||||
|
||||
## 8. 页面与操作建议
|
||||
|
||||
- 全局入口改为「岗位 · 技能 · 连接器」;岗位页用于创建、配置、复制与停用。
|
||||
- 项目详情增加「团队」,展示成员、负责范围、当前任务与真实状态。
|
||||
- 入职以渐进表单安排职责、资料、模型和接任务方式,不塞入执行层术语。
|
||||
- 任务列表及看板增加负责人和筛选;任务详情展示交接条件、依赖和阻塞原因。
|
||||
- 成员详情可以发要求、看任务与往来、暂停接任务、打开执行对话。
|
||||
- 执行对话复用现有流式、工具、授权、问题回答和工作台;不另造一套执行界面。
|
||||
- 范围外请求明确展示“需要谁处理”和影响;缺少职责配置时引导补齐,避免静默失败。
|
||||
|
||||
界面沿用现有六档字体和布局语言,具体交互待功能边界确定后设计;真实桌面验收要求仍按项目约束执行。
|
||||
|
||||
## 9. 当前基础与待实现能力
|
||||
|
||||
截至本稿,已核对现有代码与进度文档:
|
||||
|
||||
| 能力 | 现状 |
|
||||
|---|---|
|
||||
| 技能、连接器、回合快照 | 已有基础,具体支持范围以原进度文档为准 |
|
||||
| 项目任务、依赖、历史、验收字段 | 已实现;首版补充成员负责人和明确条件自动承接 |
|
||||
| 多轮子 Agent / 对话协作、排队、因果关联 | OMP 已实现;首版项目团队复用其多轮、队列与等待机制 |
|
||||
| 原专家入口 | 已改为岗位,支持真实职责、技能和模型配置 |
|
||||
| 岗位、项目成员、入职 | OMP 首版已接入;每成员持久执行对话 |
|
||||
| 任务负责人、领取、事件驱动承接 | 明确分配、自动承接开关、依赖与子任务检查、持久队列已接入;不支持智能抢单 |
|
||||
| 岗位职责、任务范围与交接规则 | 每回合注入职责规则,子 Agent 继承;任务字段及人工验收由宿主校验,非沙盒 |
|
||||
| 文件、Shell 等强制隔离 | 后续选项,首期暂不接入 |
|
||||
| 应用退出后的持续工作 | 尚无后台服务 |
|
||||
|
||||
复用现有任务、消息、对话和能力机制。角色与调度合同由宿主管理,首期验证现有 OMP;其他基座另行适配。首版数据库表、IPC 与工具参数见[进度及 SOP](ygent-team-integration.md),不增加第二套聊天内核或通用工作流框架。
|
||||
|
||||
## 10. 建议实施顺序与验收
|
||||
|
||||
以下为整体演进顺序;用户已授权并实施最小闭环,未落地能力及尚未验证的场景以进度及 SOP 为准:
|
||||
|
||||
1. 定清岗位、项目入职和任务规则的组合、继承、变更与越界交接方式。
|
||||
2. 岗位定义、模型与能力配置、项目入职和成员身份持久化。
|
||||
3. 任务负责人、领取、依赖交接和成员多轮协作。
|
||||
4. 在明确的职责和任务条件内加入事件触发、队列、暂停、预算与中断恢复。
|
||||
5. 使用职责不同的岗位跑通跨岗位协作闭环,验收覆盖代码与非代码工作,不绑定具体岗位组合。
|
||||
|
||||
首个完整闭环:创建岗位 → 项目入职 → 指定范围 → 承接明确任务 → 协作和等待依赖 → 实际验证 → 提交验收。
|
||||
|
||||
关键验收场景:
|
||||
|
||||
- 同一岗位加入两个项目,资料、任务、cwd 和授权不串线。
|
||||
- 岗位使用实际配置的模型;配置变更在正确回合生效。
|
||||
- 成员完成职责内交付后不代做依赖方的工作;依赖经核对满足条件后,才恢复对应任务。
|
||||
- 两个成员不会重复领取;忙碌、暂停、重复事件不会重复执行。
|
||||
- 跨岗位问题可多轮澄清,交接保持任务与消息来源。
|
||||
- 普通执行、恢复对话、上下文压缩和子 Agent 委派均保留有效范围规则;协作消息不改变职责。
|
||||
- 对范围外文件修改、命令副作用、连接器操作及职责外代做的测试请求,成员按规则交接;记录实际表现,不把行为测试通过等同于系统层强制隔离。
|
||||
- 共享资源职责冲突、撤销范围、交付约定变化均有可见处理结果。
|
||||
- 取消、异常退出和重启不把未知结果当成成功,也不重复外部操作。
|
||||
- UI 状态来自真实队列和运行;空闲成员不会为了显示在线而持续调用模型。
|
||||
|
||||
## 11. 下一轮待讨论
|
||||
|
||||
1. 规则配置如何保持简单:业务描述、参考范围、修改范围和依赖如何安排?
|
||||
2. 首版由用户明确分配、自动承接默认关闭;后续是否支持范围重叠时的协调分配?
|
||||
3. 哪类任务允许依据检查自动验收,哪类必须人工验收?
|
||||
4. 共享资源的责任归属和任务重分配如何处理?
|
||||
5. 模型覆盖、岗位模板升级、成员长期上下文如何管理?
|
||||
6. 规则变更、上下文恢复和长期成员如何同步有效职责,避免旧规则继续影响任务?
|
||||
7. 实际用量如何计费展示与限额,预算耗尽后如何恢复?
|
||||
|
||||
讨论后在对应章节原地修订,记录已确定结论和仍待决定的问题,避免把建议自动升级成项目约束。
|
||||
|
||||
## 12. 文档维护与关联资料
|
||||
|
||||
本文件作为持续讨论的源文件,以文件来源接入「ygent 项目 → 资料库 → 资料」。后续修改同一路径,由资料库刷新生成新版本;必要时手动刷新。修改文件不会直接替换已开始回合冻结的旧版本,已删除或撤销资料仍按现有规则处理。
|
||||
|
||||
只关联这一份方案文件,不因此登记整个工作目录。资料库条目 ID 与版本属于本机用户数据,不写入仓库。本文进入项目资料库供讨论引用,不额外写成“已确认”的项目记忆。
|
||||
|
||||
- [原专家、技能、连接器方案](ygent-capability-integration-plan.md):技能与连接器基础继续复用,岗位首版与后续方向见本文及进度 SOP。
|
||||
- [协作方案](ygent-collaboration-plan.md)与[实际进度](ygent-collaboration-progress.md):多轮消息、运行与恢复边界。
|
||||
- [项目任务方案](ygent-project-tasks.md):任务状态、验收、版本与宿主工具。
|
||||
- [资料库方案](ygent-library-plan.md)与[接入进度](ygent-library-integration.md):归属、来源与版本规则。
|
||||
|
||||
修订记录:
|
||||
|
||||
- 2026-10-10,v0.1,整理岗位与项目团队整体方向,补充职责边界和交接规则,标明执行隔离等未决项;仅交付文档。
|
||||
- 2026-10-11,v0.2,按用户选择改为首期规则隔离,补充范围组合、新文件归属、子 Agent 继承和越界交接;移除沙盒作为首期前置条件,同步实施顺序与验收边界。仅更新方案,功能尚未实现。
|
||||
- 2026-10-11,v0.3,移除具体岗位分工示例,将目标、依赖交接、实施顺序和验收项统一为通用规则,不将讨论中的例子固化为产品流程。
|
||||
|
||||
- 2026-10-11,v0.4,按用户授权实施 OMP 最小闭环:岗位配置、项目入职、职责规则、明确任务自动承接、多轮协作和人工验收;关联实际进度与原生验收 SOP,保留尚未接入的长期建议。
|
||||
|
||||
- 2026-10-11,v0.5,按用户要求增加默认项目经理、入职职责审核与任务分配;经理只读协调、普通成员审核通过后执行,最终用户验收。具体交付和证据以进度 SOP 为准。
|
||||
|
||||
- 2026-10-11,v0.6,增加普通项目对话向既有岗位成员发要求、持续多轮返回;岗位编辑直接取消,统一模型选择面板;经理配置项目独立且不可删除/禁用。
|
||||
|
||||
## 已落地补充:经理自主组队
|
||||
|
||||
项目经理可以按用户明确需求复用现有岗位或创建项目专用岗位,办理入职、审核职责范围、分配完整任务并协调交付。新建岗位默认继承经理模型和推理配置,可调整;经理创建成员默认开启自动承接,但审核、范围、验收条件及依赖仍是执行前提。项目岗位只属于本项目,只有用户显式操作才能复制为全局岗位。经理不能扩大自身执行权限或代用户验收。具体工具、界面、边界与本机验收证据见[实施进度及 SOP](ygent-team-integration.md#经理自主组队2026-10-11)。
|
||||
|
||||
|
||||
## 当前执行阶段:入职审核与任务规划
|
||||
|
||||
按最新约定,员工暂不执行。入职审核后,经理必须查看现有任务,根据当前岗位和负责范围复用、调整或拆分,明确任务负责人、依赖及验收,再提交完整当前版本规划。规划完成只代表分工确认,不代表开始执行;后续开放执行需单独确定,不加入本轮。
|
||||
|
||||
岗位职责或成员范围变化使规划重新待办。经理未完成规划时可显式重试,不由员工主动接任务补齐流程。具体实现与验收见[进度及 SOP](ygent-team-integration.md#入职后任务规划与执行暂停2026-10-11)。
|
||||
|
||||
- 2026-10-11,v0.7,增加持久任务规划阶段及完整版本提交;本轮员工执行全局保持暂停,覆盖先前自动执行约定。
|
||||
|
||||
|
||||
- 2026-10-11,v0.8,补充经理移除空闲项目成员工具;先交接未结束任务,保留文件和对话历史,移除使规划失效,退出身份不可继续执行,经理不可移除。见岗位进度 SOP。
|
||||
@@ -0,0 +1,41 @@
|
||||
# Responses 真实 OMP 集成验收(2026-10-16)
|
||||
|
||||
结论:统一构建后的生产 Electron App/preload/IPC → **真实 OMP executable** → 受控 Responses HTTP/SSE 上游已通过 **28/28**。验证完整 `/v1/responses` 配置、两轮对话历史、禁工具、认证以及开放 SSE 取消。受控服务的成功不代表用户实际远程上游已恢复,也不代表 WorkBuddy 功能/视觉 1:1 验收。
|
||||
|
||||
## 修改范围
|
||||
|
||||
- 新增 `scripts/verify-responses-integration.cjs`。
|
||||
- 新增本结果文档。
|
||||
- 未修改 production/main/store/package;未读取或修改用户真实模型注册表,未调用真实用户上游,没有观察原版 WorkBuddy。
|
||||
|
||||
## 验证方法
|
||||
|
||||
脚本创建独立 `.tmp/responses-integration-*`,分别设置 userData、sessionData、YCODE_OMP_HOME;通过真实 preload `app.info()` 断言 configDir 必须等于该隔离 data 目录,之后才保存模型与创建空间/会话。真实模型明文密钥只在隔离进程生成,报告只记录 Authorization 存在及匹配布尔值;不保存任意 OMP stderr,不返回已有明文密钥。
|
||||
|
||||
服务只监听 `127.0.0.1` 随机端口,接收实际请求,没有替换 production IPC 或 OMP。真实 SSE 依次发送 `response.created`、`response.in_progress`、`response.output_item.added`、`response.content_part.added`、`response.output_text.delta`、`response.output_text.done`、`response.content_part.done`、`response.output_item.done`、`response.completed`,完成响应包含 usage。第三轮发送真实 partial delta 后保持连接开放,调用 production chat.cancel 检查终态。
|
||||
|
||||
如果真实 OMP 首轮进入 error,脚本会停止,并在 report 中保留 preload 的实际 events/messages/error;不会切换成 Chat 协议绕过失败。
|
||||
|
||||
## 命令与结果
|
||||
|
||||
- `node --check scripts/verify-responses-integration.cjs`:退出 **0**。
|
||||
- Root 统一 `npm run build` 完成后,`node scripts/verify-responses-integration.cjs`:退出 **0**,**28/28 PASS**。
|
||||
- 机器报告:`.tmp/responses-integration-UbxGhB/report.json`。
|
||||
- 受测 production `out/main/index.mjs` SHA-256:`3bb668280e3a6b5386e787517afc6dfea466006400f1e64fc01a4687b2c6d462`。
|
||||
|
||||
| 真实请求 | 路径 | stream | 模型 | tools | max_output_tokens |
|
||||
|---|---|---|---|---:|---:|
|
||||
| production models.test | `/v1/responses` | false | `responses-fixture` | 0 | 16 |
|
||||
| OMP 首轮 | `/v1/responses` | true | `responses-fixture` | 0 | 1234 |
|
||||
| OMP 第二轮 | `/v1/responses` | true | `responses-fixture` | 0 | 1234 |
|
||||
| OMP 取消轮 | `/v1/responses` | true | `responses-fixture` | 0 | 1234 |
|
||||
|
||||
四个请求的受控 Authorization 均存在且精确匹配测试密钥,没有 endpoint 双拼。models.test 返回连接测试成功,耗时 37ms。首轮与次轮分别进入 done,实际内容精确为服务的两个不同 reply 标记。第二轮真实 input roles 为 `user,assistant,user`,包含首轮 user prompt、首轮真实 assistant reply 和第二轮 prompt。
|
||||
|
||||
第三轮实际收到 `RESPONSES_CANCEL_PARTIAL` 后取消,持久消息状态为 cancelled,partial 内容保留,preload terminal events 恰好一个 `cancelled`,没有混成 done/error。两轮正常终态均为 `text → done`。
|
||||
|
||||
真实 OMP transcript 已写入隔离 `data/omp-sessions/session-*.jsonl`。实际生成 profile 选择 `api: openai-responses`,baseUrl 为受控服务 `/v1` 前缀,模型 `responses-fixture`,contextWindow 8192、maxTokens 1234、input `[text]`、reasoning false;密钥配置为环境变量名 `YCODE_MODEL_API_KEY`,YAML 不含受控明文密钥。
|
||||
|
||||
## 范围与未验项
|
||||
|
||||
本轮覆盖网络失败/取消要求中的**取消**分支,没有重复发送网络失败轮。真实用户 endpoint 的网络可达性、鉴权和供应商协议兼容性仍需在用户已授权的真实重试中单独确认。未覆盖 Responses function tool、图片、reasoning、复杂多 output item、服务端错误格式及 interrupted stream 后重试。没有以受控 Responses fixture 代替真实上游成功结论。
|
||||
|
After Width: | Height: | Size: 105 KiB |
|
After Width: | Height: | Size: 40 KiB |
|
After Width: | Height: | Size: 55 KiB |
|
After Width: | Height: | Size: 90 KiB |
|
After Width: | Height: | Size: 96 KiB |
|
After Width: | Height: | Size: 74 KiB |
|
After Width: | Height: | Size: 67 KiB |
|
After Width: | Height: | Size: 36 KiB |
|
After Width: | Height: | Size: 33 KiB |
@@ -0,0 +1,69 @@
|
||||
# 本地技能实施与验收(2026-10-16)
|
||||
|
||||
本次实现可实际使用的本地技能库:导入目录/ZIP、读取说明、启停、覆盖、卸载、导出,以及当前空间的技能发现和手动/自动调用上下文。技能页接入真实 SkillsApi。在线市场、云端同步、付费权益和安全扫描服务尚未接入;没有伪造在线卡片、安装量、扫描通过或购买状态。本报告不宣称技能整体 1:1 已完成。
|
||||
|
||||
## 文件与边界
|
||||
|
||||
- `src/main/capabilities/skills.ts`:本地存储、包校验、发现、生命周期和模型上下文。
|
||||
- `src/renderer/src/capabilities/SkillsPage.tsx`:默认导出技能页;Props 为 `{cwd?, onUseSkill?, onCreateSkill?, onFindSkill?}`。
|
||||
- `skills-source.mjs` / `skills-source.d.mts` / `skills-source.css` / `skills-source-manifest.json`:固定 REA 源码恢复产物。
|
||||
- `skills-host.css`:宿主容器、可访问交互、本地状态和原版没有对应服务的提示。
|
||||
- `scripts/test-skills-reference.mjs`:固定 SHA 校验及恢复(`--write`);不读原版安装目录,不操作原窗口。
|
||||
- `scripts/test-skills-files.mjs`、`scripts/test-skills-ui.mjs`:隔离真实文件系统与原生 Electron 控件验收。
|
||||
|
||||
共享契约、IPC、preload、App、ChatPane、CapabilityCenter、包依赖和生产 out 均由主上下文接线;本 worker 未修改这些文件。复用主上下文导出的 `CapabilityToolbar` / `CapabilitySubpageHeader`,右侧动作通过 portal 使用唯一共享顶栏。
|
||||
|
||||
## 主进程契约与语义
|
||||
|
||||
导出 `listSkills(cwd?)`、`importSkill(path, overwrite=false)`、`readSkill(id,cwd?)`、`setSkillEnabled(id,enabled,cwd?)`、`removeSkill(id)`、`exportSkill(id,destination)`。UI 的 `SkillsApi.importPath(undefined,overwrite,kind)` 委托根 IPC 展示文件夹或 ZIP picker,不新增手填系统路径流。
|
||||
|
||||
存储根为 `app.getPath('userData')/capabilities/skills`:`registry.json` 保存注册/禁用状态,`packages/<24hex>/` 保存导入副本。`user:<name-hash>` 保持同名覆盖身份稳定;空间 ID 基于实际包路径,不把两个空间同名技能混为一个。发现当前 cwd 下 `.agents/skills` 与 `.claude/skills`,不枚举其他空间。空间包可禁用但不能由卸载 API 删除;导入源始终保留。UI 共享 slash 菜单的 cwd 作用域 pin memory key,保留其他 memory 字段。
|
||||
|
||||
SKILL.md 必须为 UTF-8、含 YAML name/description;使用 YAML core schema,支持 folded 字段、版本数值和受限 alias,拒绝重复键及把字符串 `"false"` 误当布尔值。支持 `enabled`/`disable`、`user-invocable`/`userInvocable`、`disable-model-invocation`/`disableModelInvocation`。未知前置元数据保留于原文件,不重写包内容。
|
||||
|
||||
- `buildSkillContext(ids,cwd)`:显式手选,只允许 enabled + userInvocable;手动专用技能允许注入。
|
||||
- `buildAvailableSkills(cwd)`:输出真实 `{id,name,description}` JSON 目录,只含 enabled 且未 disableModelInvocation 项。
|
||||
- `loadSkillContext(id,cwd)`:模型自动加载遵守 enabled + !disableModelInvocation。
|
||||
- `readSkillResource(id,relative,cwd)`:仅当前可用包的受限相对 UTF-8 文本,最大 1MB。根工具桥另行约束回合 allowedIds,不能仅凭 model 给出的任意 ID 放行。
|
||||
|
||||
单个上下文文档限制 65,536 字符,手选总计 131,072 字符。没有直接执行包内脚本;真实模型可以通过根已有工具执行任务,是否与原版内核同义还需独立验证。
|
||||
|
||||
损坏、缺失、被重定向或 YAML 无效的注册包按条目返回 `error`、`enabled:false`,保留 ID/name/path 以定位和卸载;不让无关损坏包阻断普通聊天的空选 context 或可用技能目录。空间坏包同样显示不可用。主索引自身损坏仍为明确错误,不静默覆写丢失注册状态。
|
||||
|
||||
## 路径与安装事务
|
||||
|
||||
导入目录、SKILL.md 和 ZIP 都先校验;包最多 2,000 文件、展开总量 50MB,ZIP 输入最多 20MB,SKILL.md 最大 1MB。不跟随技能存储祖先、源目录、包或资源中的 symlink/junction。拒绝绝对路径、盘符、反斜杠、dot traversal、Windows 设备名、控制字符及大小写/NFKC 重复 ZIP 路径。ZIP 中央目录预检拒绝多卷/ZIP64/加密/设备/链接;再每 4KB 输入分块解压,核对每项实际输出与声明大小,防止只信声明大小的膨胀包。
|
||||
|
||||
使用同级 stage/backup + rename 安装替换,索引原子写入,提交失败回滚。覆盖需要明确 overwrite;UI 勾选“替换已导入的同名技能”。导出以 `wx` 创建 ZIP,不覆盖已有文件或技能存储。卸载先重命名隔离再提交索引,缺失目录可清理注册,注册路径已被替换为 junction 时只移除链接本身,不触及指向目录。目录遍历防护不承诺抵御具有同等文件权限的进程在所有 lstat/read 间恶意竞态。
|
||||
|
||||
## 原版来源与恢复范围
|
||||
|
||||
WorkBuddy **5.8.2**,ASAR SHA-256 `035254bc76310ea46317433e4840602094543ef323d2d5c5aff7c131729de918`。所有原实现信息来自已经保存的 REA 导出;先验证 SHA 再解析。
|
||||
|
||||
| 来源 | REA Evidence | 固定 SHA / 范围 |
|
||||
| --- | --- | --- |
|
||||
| skills-market-Cwf-NvXV.js | `ev_e8faf60b3d22b99ede302f2d0efdfb3145f53f59789d4a345f5892dc13a589a4` | `f1434cadabf5ed3762f00fc2a356bc7418b0b4aab27db62dc9fbbe5add6f6dfb`,CardFrame UTF-16 `[10076,13702)` 原函数体 |
|
||||
| standalone-skill-detail-modal-Bi5X8CZ4.js | `ev_717fa5e846e64d67ac19c8925d121bff632c0d3aefb3603b10858559cabb2dcb` | `ee7de2a7123f94110aa01258d3d6b3fcc3ce48f2ec5fd8f91cb3367c817a0f01`,8 个字面 SVG 函数,精确 offset/body SHA 见 manifest |
|
||||
| skills-market-d_hn_qWB.css | selected Evidence 同上 | `935d55effde68d03b2fbc2529ec94b19a6cd7210d9bc79febd6d115b115f60b6` |
|
||||
| standalone-skill-detail-modal-fe_BFVdd.css | `ev_377c8790468b3c67dad8577aabb327f98d3140659f0fffdbabfcff5a40cc9e94` | `7967df52bacb7594f934b32d8d5fb24854dbc8c47d0217d4677c7d7da0655f49` |
|
||||
| src-Bh3YZ35H.css | CSS Evidence 同上 | `88dbdc1cd3f59d0e8b75824512a465a2be714bc7af481d790fe3a9484f85e01a`,button/input/switch/dropdown/popover |
|
||||
| contexts-BkjwYSZT.css | CSS Evidence 同上 | `50cbd673f7f35fc7f966bdddc6c9f5677fdfe944cb904888d214619fca259380`,skill-upload + 对应 keyframes |
|
||||
|
||||
CSS 声明、顺序、media 和 keyframes 保留;选择器限制到 `.yc-capability-center`,原 skill-market 顶栏祖先适配到共享 portal。CardFrame 原体仅替换 JSX runtime 引用;React singleton、Tooltip/Avatar/批量 checkbox、原服务数据为显式宿主适配。详情的 header/view/scroll/intro/overview/file 结构由已导出源重新接本地数据,并非整个原详情组件原体复用。导入结构依据 `contexts-BMeWSUHk.js` 的 SkillUploadModal `[4365603,4372182)`;文件夹/ZIP native picker 取代原宿主 facades。没有拖拽和 web FileList fallback。
|
||||
|
||||
原 runtime 对照:市场 `ev_c827c8dc7dee0c67c7870f6bf8417b87ec7b4d90d507ecc5dc592b5878579f10`;稳定已安装 `ev_9d8628a28fed60291e628cebaec55537bfb8274d4b6c8f746bffadcbc277d3fb`;添加菜单 `ev_ddef9315aaf0ff534cf02573212e205ba70e5b69dfc1b3dcf555b430920faf22`。市场和菜单各自 cleanup cancelled,只有动作帧有效;不能宣称 probe 全通过。原已安装 5 个市场/套件数据与本机自定义技能不是同数据集,不作全画面像素相等断言。
|
||||
|
||||
## 验证
|
||||
|
||||
- `node scripts/test-skills-reference.mjs --write`:6 个固定源码/CSS SHA、9 个函数恢复、4 个输出生成;再不带参数可验证未漂移。
|
||||
- `node scripts/test-skills-files.mjs`:**59/59 PASS**,`.tmp/skills-files-iAkonv/report.json`。实际临时 FS,唯一 Electron stub 是隔离 userData 路径。覆盖生命周期、持久化、空间隔离、metadata flags、ZIP roundtrip/traversal/碰撞/symlink/虚报解压大小、损坏/缺失/重定向注册包容错和卸载。
|
||||
- `node scripts/test-skills-ui.mjs`:**37/37 PASS**,`.tmp/skills-ui-fR8rWr/report.json`。普通可见 Electron + SwiftShader,1052×901 内容区;真实 main 模块、preload/IPC 和隔离 FS,仅 OS picker 使用受控路径。以鼠标/键盘点击完成目录/ZIP导入、重复冲突、覆盖、搜索、开关、批量、pin、详情 markdown、使用回调、导出、卸载/取消、损坏包 UI、焦点循环/恢复及3秒提示消失;截图同目录。预期冲突/损坏 IPC reject 有日志,不计为 renderer 未处理异常。
|
||||
- `npm run typecheck`:node + web 全通过。主上下文负责统一生产 build 与完整应用 OMP/MCP/重启集成验收,本 worker 没有重复写生产 out。
|
||||
|
||||
原生局部实测:受管卡片 padding `20px`、radius `16px`、shadow `rgba(0,0,0,.03) 0px 4px 12px`,medium switch `26px`。这些验证了恢复声明在宿主生效,不能替代同数据/同状态的原版像素比较。
|
||||
|
||||
## 遗留差异
|
||||
|
||||
未接在线推荐/SkillHub/套件目录、URL 导入、云端同步、更新下载与权益/购买流程;当前对应目录显示服务不可用,查找/创建由根真实草稿回调处理。没有安全扫描引擎或风险报告伪造。原版详情的搜索命中、翻译、远程示例/案例、动态价格和权益尚未接入;avatar 为本机名称字母 fallback,Tooltip 使用宿主原生 title,尚未恢复原 tooltip 延迟/浮层。包内图片未通过文字资源 API 越界读取,详情仅渲染可用 markdown 文本及文件清单。暗色及所有状态像素/动效还未完整验收。这些须继续按 REA 证据补齐,不能把本轮本地功能闭环称为技能 1:1 完成。
|
||||
|
||||
最终集成由主上下文报告:`.tmp/capability-flows-ZJYiyj/report.json`,完整应用 UI→真实 OMP 两轮 + MCP + 重启 PASS。该结果属于主上下文验收,不替代本报告的原版像素与未知项边界。成功 notice 是3秒自动消失、不占文档流的宿主 status;已存 REA CSS 未找到可直接恢复的 wb-toast primitive,未声称原版 toast 等价。
|
||||
@@ -0,0 +1,59 @@
|
||||
# 对话产物入口有限 QA(2026-10-16)
|
||||
|
||||
结论:当前 `SourceArtifactLink` 的原版归档范围内 DOM、四组几何和 168 项 computed style 已对齐;自身 hover、native click、真实焦点下 native Enter 和空计数隐藏通过。严格像素尚未对齐:默认按钮 ROI 的 3,614 个像素中仍有 1,018 个不同,SVG 区域无差异,文字存在灰阶与 LCD 彩边差异。不得把本报告称为完整 1:1 验收。
|
||||
|
||||
## 修改范围
|
||||
|
||||
- 新增 `scripts/artifact-link-ui-regression.cjs`:仅打包当前生产组件到隔离的 YCode fixture,生成机器报告与 PNG;没有修改生产组件、CSS、GPU 设置或原版窗口。
|
||||
- 新增本报告。运行产物在 `.tmp/artifact-link-ui-regression/`。
|
||||
- Root 已将生产按钮文案改成单一 template 字符串;本 QA 直接读取当前生产组件验证,没有代写该改动。
|
||||
|
||||
## 原版证据
|
||||
|
||||
WorkBuddy **5.8.2**,归档环境 Electron **37.10.3** / Chromium **138.0.7204.251**,截图 **1336×901**。仅使用此前 REA 保存的实现、DOM、computed styles、SVG、截图和 GPU 元数据;本任务没有重新观察原版。
|
||||
|
||||
- 运行时证据:`ev_d6e6920ff4e47f73a182fac5312c5f02393366a035445d18c8a6733a8c8a11ed`,文件 `.tmp/rea-assessment-initial/layout.json`、`workbuddy.png`。PNG SHA-256 `4bd92ea8c0e3677edcecbe26da4e62eaf853d0111638e2a0995e8f8470a3506a`,脚本先校验其与 REA artifact hash 一致。
|
||||
- CSS:原 `artifact-slot-panel-BsA1UFez.css` SHA-256 `15c68a5a7c663776036feabff7126bbb8a4b1445cbf6b65ba3d82044289a513d`;`contexts-BkjwYSZT.css` SHA-256 `50cbd673f7f35fc7f966bdddc6c9f5677fdfe944cb904888d214619fca259380`,来源记录保留在生产 `source-artifact-link.css`。
|
||||
- 主进程有限证据:`.tmp/rea-selected-main-render-flags.json`,`ev_3de1f34ca809cd2e4f98dfac960b1913db75e43cd88957d3e4f82b3b16f47fbf`;原 `main/index.js` SHA-256 `6cc9d3079aca910b7c14c37a0a3b6f6af03f2b319d5625625926dbf5ad61aec8`。字符偏移 312856 的 `applyGpuDegradationIfNeeded` 仅在 `shouldDisableGpu` 为真时调用 `disableHardwareAcceleration` 并设置 `disable-gpu`、`disable-gpu-compositing`。本文件中未发现 `disable-lcd-text`、`use-angle`、`font-render`、`force-color-profile`;该观察不能排除其他模块、启动器、驱动或环境配置,不能推定原版采用某个字体开关。
|
||||
|
||||
## 几何、DOM、样式
|
||||
|
||||
Fixture 加载生产 typography tokens、主题 tokens、app CSS、conversation source styles/adapters 与组件自身 CSS;在 `chat-pane cr-theme` light 宿主下复用原 footer x/y/width、display-contents slot、actions margin-top 12。只复现按钮入口,未补造 footer 的其他 feedback 行,因此不比较整个 footer 高度。
|
||||
|
||||
| 节点 | REA node_index | 原版与当前 bounds `[x,y,w,h]` |
|
||||
|---|---:|---|
|
||||
| actions | 1644 | `[324.28125,614.578125,138.15625,25]` |
|
||||
| button | 1645 | `[324.28125,614.578125,138.15625,25]` |
|
||||
| chevron | 1647 | `[446.4375,619.078125,16,16]` |
|
||||
| SVG | 1648 | `[451.65625,622.46875,5.546875,9.21875]` |
|
||||
|
||||
四节点合计 168 项归档 computed style 全部相等,包含字体栈、15px/25px、字重 400、gap 2、padding 0、颜色、display 与 SVG display block。原 SVG attrs 为 width `5.5523`、height `9.219`,与实际量化 bounds 区分;viewBox、fill、path d 均精确一致。文本 `查看所有产物 (13)` 为单个直接 text node,与原 node 1646 一致。修正前分段 React text node 曾导致按钮宽度多 `0.015625px`;当前该差异已消除。
|
||||
|
||||
## 像素结果与限制
|
||||
|
||||
采用可见隔离 Electron 窗口、SwiftShader 和软件合成;没有添加 `disable-lcd-text`,没有改生产 GPU 参数。采集的 GPU feature status 与归档逐项相等,但这不足以证明字体栅格化条件完全相等。
|
||||
|
||||
ROI:`x324,y614,width139,height26`,严格 RGB tolerance **0**。
|
||||
|
||||
| 指标 | 结果 |
|
||||
|---|---:|
|
||||
| 总像素 | 3,614 |
|
||||
| 不同像素 | 1,018 |
|
||||
| 最大单通道差值 | 77 |
|
||||
| 平均 RGB 差值 | 4.798930086699871 |
|
||||
| SVG 区域不同像素 | 0 |
|
||||
|
||||
参考 crop SHA-256:`1511ef946540c0f80cb86348c427273f9825cd2583dcdc6501a01803ab9dec2b`。当前 crop SHA-256:`b88b306136e6768b4f1bf4c5583ce11820fe6d819443638b831d0a67ef45460e`。文件为 `reference-roi.png` 与 `candidate-roi.png`;机器报告保留前 12 个 RGB 差异样本,例如原灰阶 `[249,249,249]`、当前彩边 `[238,255,254]`。证据支持文字栅格差异这一现象,未证实原版具体成因或启动开关。
|
||||
|
||||
## 交互与验证
|
||||
|
||||
命令:`node scripts/artifact-link-ui-regression.cjs`,退出码 **0**,**184/184 PASS**,机器报告 `.tmp/artifact-link-ui-regression/report.json`。该 PASS 仅指报告中 geometry/styles/own interactions 检查;`pixel.fullPixelParity` 明确为 **false**。
|
||||
|
||||
- 原生 mouse move 后按钮与 chevron 均变为 `rgb(0,0,0)`;native click 回调恰好一次。
|
||||
- `win.focus()`、`webContents.focus()` 后分别确认窗口、webContents、实际按钮均有焦点,完整 native `keyDown Return → char CR → keyUp Return` 激活一次。只发送 keyDown/keyUp 不产生 Chromium 默认 char activation,未将该不完整输入序列当成生产缺陷。
|
||||
- count 0 不渲染入口;无 renderer error。
|
||||
- 当前组件 SHA-256 `cc589f276ba8c6c0b1c66df2ce066569ac864ce8b242a8d78e44586d4b7601c6`;当前 CSS SHA-256 `ac3593ad9e11ef4fb347b26fbb273add80db068e85089248583149c4c475d1e9`。
|
||||
|
||||
另读取 Root 已有 `.tmp/panel-integration-Capd62/report.json`:**66/66 PASS**,范围为真实隔离 YCode App/preload/IPC/native filesystem、overview 与标签保留,无上游调用。该报告与本 fixture 分开:本 fixture 回调是计数器,不能单独证明生产 overview 行为;integration PASS 不能证明原版像素相同。
|
||||
|
||||
原版 hover/键盘操作画面没有对应归档,仅有源 CSS hover 规则,仍未做原版动态像素验收。默认文字差异未解决;未修改 GPU 参数来伪造原版配置。
|
||||
@@ -0,0 +1,92 @@
|
||||
# 对话顶部栏恢复与验收(2026-10-16)
|
||||
|
||||
已新增独立 `SourceChatHeader.tsx`、SVG/词典引用、原CSS与adapter;未修改 ChatPane/App。主上下文负责生产接线。
|
||||
|
||||
## 来源与行为
|
||||
|
||||
原版版本5.8.2,Windows,1336×901,现有“开始新会话”会话。全部原版操作均由本地REA public CLI执行:点击已有会话、收起右栏、打开搜索、标题hover/edit/Escape、恢复首页。没有发送消息、输入原标题新值、保存设置或测试原上游。
|
||||
|
||||
| 状态 | REA Evidence | 保存位置 |
|
||||
| --- | --- | --- |
|
||||
| 会话/right open稳定 | `ev_ab07d4f968450f9756929b9b1d222b7ab577061b6a758543cbd02addb358ba5e` | `.tmp/rea-chat-header-static-20261016/` |
|
||||
| 收起右栏、打开搜索 | `ev_36d8218d7eea31c60378195344a4b6cf30d68a8add12bbeb6dc5815c42b4c80d` | `.tmp/rea-chat-header-actions-20261016/` |
|
||||
| 搜索稳定主图、标题hover/editor帧、Escape取消 | `ev_f500fa72e1dd63e3bfa44ca550866653b70f5031100075f3bae25b6baa36ce19` | `.tmp/rea-chat-header-title-20261016/` |
|
||||
| right closed稳定主图、恢复首页帧 | `ev_38cca1ac66606ab07fb495035e3509f5c4d8ec3e5e2b74d0fdcfcfadb120da3b` | `.tmp/rea-chat-header-final-20261016/` |
|
||||
|
||||
REA视觉结果的主PNG/layout是probe前状态,`frame-*`才是动作后状态;恢复首页使用最后一个probe frame,不能将其主图当作首页。
|
||||
|
||||
原版稳定会话顶部栏不含设置齿轮。right open时只有搜索、分享(各32×32,gap4,共68×32);right closed时增加右栏按钮(共104×32)。主栏高64px,原token文件 `:root` 的56px被 `body[data-electron-desktop=true]` 的64px覆盖;恢复脚本保留了桌面token覆盖与height<=400px时的40px规则。
|
||||
|
||||
标题hover显示真实编辑SVG;输入自动选中;Enter/blur提交trim后的非空新值;Escape取消。原源码 `WorkBuddyTopBar` 还有受环境/会话条件控制的编辑器、协作项目、历史提问入口,不能全部默认显示。当前源会话没有编辑器或历史提问入口;本组件只在显式提供promptList时显示历史提问,不把本地workspace cwd当作协作项目breadcrumb。
|
||||
|
||||
搜索是**当前对话内容搜索**,不是会话列表搜索。原版展开300×32输入框,初始无counter;keyword非空显示一基计数,零命中0/0;Enter下一项、Shift+Enter上一项、Escape关闭。搜索结果实际扫描/滚动/高亮由主上下文接入真实消息宿主;组件只负责受控UI,不伪造命中。
|
||||
|
||||
## 文件与接口
|
||||
|
||||
- `src/renderer/src/components/SourceChatHeader.tsx`:默认导出组件,导出 `SourceChatHeaderProps`、`SourceChatHeaderSearch`、`SourceChatHeaderPromptList`。
|
||||
- `SourceChatHeaderIcons.tsx`:8个原SVG纯定义,无原模块初始化。
|
||||
- `source-chat-header-reference.ts`:13个原中文labels。
|
||||
- `source-chat-header-recovered.css`:178条原规则,保留顺序与media父条件;独立desktop token闭包。原 `.cb-chat-search-hit` 规则保持可供消息宿主使用。
|
||||
- `source-chat-header.css`:原版继承字体/13px/normal/antialiased与原生input字体的有限adapter。
|
||||
- `scripts/rea/recover-chat-header-reference.mjs`:仅消费固定REA脚本/CSS,验证SHA后生成上述引用;manifest在 `.tmp/chat-header-reference/manifest.json`。
|
||||
- `scripts/rea/probe-chat-header-*.json`:本次原版受控动作。
|
||||
- `scripts/verify-chat-header-parity.cjs`、`scripts/compare-chat-header-pixels.py`:独立原生fixture和校准像素对比。
|
||||
|
||||
基础Props为 `title`, `rightVisible`, `onToggleRight()`;`onOpenSettings?`保留父接口兼容,但不生成原版不存在的齿轮。`workspaceName?`为归属元数据,不主动改成项目breadcrumb。
|
||||
|
||||
```ts
|
||||
onTitleChange?: (nextTitle: string) => void | Promise<void>
|
||||
onShare?: () => void | Promise<void>
|
||||
shareLabel?: string
|
||||
onActionError?: (error: unknown) => void
|
||||
search?: {
|
||||
open: boolean; keyword: string; hitCount: number; activeIndex: number // 0基
|
||||
onOpen(): void; onClose(): void; onKeywordChange(keyword: string): void
|
||||
onPrev(): void; onNext(): void
|
||||
}
|
||||
```
|
||||
|
||||
未配置真实search/share宿主时按钮禁用。若分享只支持本地导出,应传诚实的 `shareLabel`,不能冒充WorkBuddy云端分享。标题保存错误可reject并由onActionError交给宿主;组件退出编辑、重置草稿,不谎报保存成功。可选promptList含真实items/requestId与必需onJumpToMessage;没有数据不显示入口。
|
||||
|
||||
原搜索高亮来自 `src-CBaV_A3S.css`:普通background `#c5eee0`、foreground `#1f8c67`;current background `#4ecba0`、foreground `#fff`、glow `0 0 0 2px #4ecba04d`。这些都保留原 `--cb-search-*` 变量。CSS Highlights只能等价承接bg/fg;原mark的radius2、padding0 1px、glow与transition不能直接通过Highlight伪元素完整重现,应另记差异。
|
||||
|
||||
恢复来源:脚本REA `ev_717fa5e846e64d67ac19c8925d121bff632c0d3aefb3603b10858559cabb2dcb`,CSS REA `ev_377c8790468b3c67dad8577aabb327f98d3140659f0fffdbabfcff5a40cc9e94`。具体JS/CSS文件SHA、SVG绑定和offset均在生成manifest中固定。
|
||||
|
||||
## 原生几何与像素结果
|
||||
|
||||
原生fixture使用真正DOM pointer/keyboard事件;所有host回调由隔离fixture控制,不能把本测试当作生产搜索/rename/share业务已通过。
|
||||
|
||||
closed/open/search/edit状态几何与固定原版逐项一致:
|
||||
|
||||
- closed topbar `[284.28125,30,1051.703125,64]`;open `[284.28125,30,691.703125,64]`。
|
||||
- 标题 `[308.28125,50,80,24]`,16px/600/24px/#000,声明字体一致。
|
||||
- closed actions `[1215.984375,46,104,32]`;open `[891.984375,46,68,32]`。
|
||||
- search `[947.984375,46,300,32]`,input194×32、nav/close24×24。
|
||||
- 原标题editor `[308.28125,50,203,24]`。
|
||||
|
||||
根据既有原REA `ev_af6ce1805f575a49d9b37b7d391a07a77a90219a12eb2148cb25930a00da963c` 的渲染环境证据,增加唯一校准模式:普通窗口 `showInactive`、任何await前disableHardwareAcceleration、`use-angle=swiftshader`、`disable-gpu-compositing`、`Page.captureScreenshot(fromSurface:true,captureBeyondViewport:false)`。本机实际GPU复核为 `ANGLE_SWIFTSHADER`、`(gl=egl-angle,angle=swiftshader)`、`gpu_compositing=disabled_software`。
|
||||
|
||||
| 固定区域 | 比较像素 | 不同像素 | 最大通道差 |
|
||||
| --- | ---: | ---: | ---: |
|
||||
| 标题 | 1920 | **0** | **0** |
|
||||
| 搜索按钮 | 1056 | **0** | **0** |
|
||||
| 分享按钮 | 1056 | 21 | 15 |
|
||||
| 右栏按钮 | 1056 | 27 | 5 |
|
||||
| 整个稳定topbar声明区域 | 67264 | 48 | 15 |
|
||||
| search(只mask原生caret列72px;空query无counter) | 9560 | **0** | **0** |
|
||||
| editor已选中原标题 | 4896 | **0** | **0** |
|
||||
|
||||
校准后标题和editor字形已零差,不能再将这些区域差异笼统归因于字体环境。首次search差异来自pointer停在展开后的close按钮造成hover;匹配REA的neutral pointer状态后归零。剩余48像素集中在分享/右栏SVG曲线与transform边缘;原SVG路径/transform恢复自固定源码、颜色/控件几何一致,**边缘采样差异原因尚未确证**,没有调容差、替换原像素或宣称整栏零差。
|
||||
|
||||
原图/候选SHA、具体差异坐标与RGBA、diff图在 `.tmp/chat-header-native-swiftshader-20261016/{report.json,pixels.json,*-diff.png}`。普通offscreen图也保存在 `.tmp/chat-header-native-20261016/`,不与校准模式混算。
|
||||
|
||||
执行结果:
|
||||
|
||||
```powershell
|
||||
node scripts/rea/recover-chat-header-reference.mjs
|
||||
node_modules/.bin/electron.cmd scripts/verify-chat-header-parity.cjs --visible-swiftshader
|
||||
& 'C:/Users/Administrator/.cache/codex-runtimes/codex-primary-runtime/dependencies/python/python.exe' scripts/compare-chat-header-pixels.py
|
||||
npx tsc --noEmit
|
||||
```
|
||||
|
||||
均通过,原生console errors0。余项:48个SVG边缘像素、原自绘tooltip/快捷键提示(目前使用native title)、promptList原运行时、Mac/compact/dark、协作项目和条件性编辑器入口,以及生产集成后的全状态验收。
|
||||
@@ -0,0 +1,92 @@
|
||||
# 模型设置 Select 恢复与验收
|
||||
|
||||
2026-10-16:供应商、模型、推理强度三个 Select 已替换旧简化 body portal。恢复原 Select/Input/Checkbox/Tooltip 的有限纯定义、CSS、SVG;表单 CRUD、createRequest/onCreateHandled、保存/测试策略保持现有宿主实现。本报告只声明下面列出的组件状态;不声明整个模型设置页或 WorkBuddy 云端目录已完整 1:1。
|
||||
|
||||
## 原版来源与身份
|
||||
|
||||
WorkBuddy 5.8.2,REA 6.5.0-visual.3。安装包根 SHA-256 `035254bc76310ea46317433e4840602094543ef323d2d5c5aff7c131729de918`。原版静态文件、图标、运行时窗口、输入和截图全部经 REA;没有直接原版 CDP/FS/evaluate。
|
||||
|
||||
| 证据 | 内容 |
|
||||
| --- | --- |
|
||||
| `ev_717fa5e846e64d67ac19c8925d121bff632c0d3aefb3603b10858559cabb2dcb` | 固定运行脚本,`.tmp/rea-runtime-scripts.json` |
|
||||
| `ev_25f013c9fd2ad66153046eec06e94fb6128bfacc1e87e57aa90db6bc419075ec` | 精确选取 ModelsSettingsPanel JS/CSS |
|
||||
| `ev_377c8790468b3c67dad8577aabb327f98d3140659f0fffdbabfcff5a40cc9e94` | 固定 CSS 与 token 来源 |
|
||||
| `ev_53e6d36c2409b0548cc9bccc36ecbf68cbdec2b37069f50a0d85da2855516b92` | REA 定向导出 `renderer/assets/kimi-DiLyRSiJ.svg` |
|
||||
| `ev_7f4bada062e5643e7866e0dbe8a35f2ab5903421c94b5084ab710dbe77b3ab19` | 900×680 原供应商 dropdown 静态几何 |
|
||||
| `ev_a6b221d6a364c9f2db118a9dde18b9a3bc4a7c051663a6a0ccafb99c33c76237` | 900×680 原模型 dropdown 静态几何 |
|
||||
| `ev_62882f0ba55ecd91b735fe4af31a61363835f86138c4f5337058764a43c90001` | 原供应商 CUSTOM 查询,最终图为 `frame-000.png` |
|
||||
| `ev_35a2e7ad47bdec37b656f994d095e5204d2269677c3bd426b5b3f19ac5986070` | 原供应商“腾讯”查询,最终图为 `frame-000.png` |
|
||||
| `ev_54fe936186511f4cf8e8b4234589abd7354362d61975a7c77f701874d21c2ca6` | 原供应商无结果查询,最终图为 `frame-000.png` |
|
||||
| `ev_ed745c60674e32c2ab72f9987e743eefdef172c88febd38aa8cd29cf3989a240` | 原清空查询恢复列表、minimax 模型查询;最终图分别 `frame-000/001.png` |
|
||||
|
||||
上述搜索采集使用 REA 新增的受限单行 text action。capture-css 顶层截图/layout 在 probe 前采集,因此搜索结果应读取 `probe.frames` 的图与 regions,不能误用顶层初始画面。原版添加窗口结束时已关闭,REA list 确认只剩原首页 target。关闭目标后的最终截图请求出现 protocol_error,故没有声称该次关闭截图成功;没有保存配置、测试上游或发送消息。
|
||||
|
||||
关键源 SHA-256:
|
||||
|
||||
- `src-DPDj7_qD.js`:`747e41d215375e1214c366213aea7e077d85421923029c61cbb6e9562be58de0`。
|
||||
- `contexts-BMeWSUHk.js`:`5f35b7489b107e21ef452c8ee88a95265756f6fc444841eef869228bbc44768b`。
|
||||
- `floating-ui.react-dom-BDD8Fyfd.js`:`94036e3ed41ddb907b010cedbdb628a57e26e0585e2a9be45c9cbecfdd6ec978`。
|
||||
- `src-Bh3YZ35H.css`:`88dbdc1cd3f59d0e8b75824512a465a2be714bc7af481d790fe3a9484f85e01a`。
|
||||
- `tokens-Df-i-zsO.css`:`13f2bf82c96e5167a7d7098e36950c6c22c475b3337dbb8bb29ad2fe79cde696`。
|
||||
- `ModelsSettingsPanel-FfiX-Du7.css`:`cd80b01d04589227a3c2db5dbe67b6c83b019bef18d3dba68ae5486448651018`。
|
||||
- Kimi SVG,129,220 B:`2615b35b9dc747f5a453ca300a2a7e8b39c1298c11f5249979768c018157e7b7`。
|
||||
|
||||
Tencent/OpenRouter/Ollama PNG 来自固定 contexts 脚本的 data URI;其 SHA、字节数、offset 和所有纯定义位置记录于 `.tmp/source-select-recovery/manifest.json`。恢复脚本逐项校验源身份,再写 UI 文件;不会初始化原 bundle。
|
||||
|
||||
## 文件和宿主适配
|
||||
|
||||
新 `src/renderer/src/components/source-select/`:
|
||||
|
||||
- `SourceSelect.tsx`:有类型的单选接口,display:contents scope;不引入定位盒。
|
||||
- `RecoveredSelectCore.tsx`:原 Select、group/filter、OptionLabel、Input、Checkbox 等纯定义,保留激活延迟、条件 class、Enter/Space、搜索与清空规则。仅给触发按钮增加宿主 aria-label。
|
||||
- `RecoveredSelectTooltip.tsx`:原 Tooltip、截断测量、延迟、arrow、hover/press guard、退出状态;React 19 ref 访问与 CSS scope portal 作宿主适配。
|
||||
- `SourceSelectPopover.tsx`:原内联 absolute 策略、offset→flip→shift→size 顺序、焦点管理、150ms/减弱动效1ms退出状态;Escape 在捕获阶段消费,避免同时关闭表单。
|
||||
- `SourceFloatingPlatform.ts`:保留原旧版裁切祖先判断,用宿主 platform 计算最终矩形。新版 DOM 库会持续排除静态祖先,造成模型框306px并伸入footer;源算法每层更新 lastStyle,保留 editor-body,使模型框216px。没有硬编码 popup 高度或给表单添加 position。
|
||||
- `SourceSelectIcons.tsx`、`SourceProviderGlyphs.tsx`、`SourceProviderIcon.tsx`、`provider-assets/`:源 SVG 路径/变换、原 PNG/SVG 资产。
|
||||
- `source-select-recovered.css`:原规则、顺序、media 条件与 token 依赖闭包,含 Tooltip 源码 style 引用的 `--wb-tooltip-z-index=10200`。
|
||||
- `source-select.css`:只处理 scope/display:contents 和图标 flex。
|
||||
|
||||
只在 `ModelSettingsPanel.tsx` 接 imports、替换 local Select、三个 callsite、provider label/row icon、既存非候选 modelId 注入;删除 `model-settings.css` 对应 model-ui dropdown 覆盖。根新增入口 intent hooks 未覆盖。没有修改 App/main/preload/store/package。
|
||||
|
||||
`@floating-ui/react 0.27.20` 由主上下文安装并固定,是 YCode 宿主依赖;原包精确版本未知,不声称版本相同。原 CSS/纯组件源码与宿主定位适配的来源和责任区分明确。
|
||||
|
||||
## 验证结果
|
||||
|
||||
`scripts/verify-source-select.cjs` 在独立 userData 的真实 900×680 Electron 原生窗口、软件合成/SwiftShader 环境运行真组件,加载生产 tokens.css/app.css。原版 UI 从未由此脚本操作。
|
||||
|
||||
30项通过,包括精确 popup/trigger 几何、内联归属、4组 DOM、真实 vendor mark、大小写过滤、清空、No options、禁止搜索创建项、第一次 Escape 只关 popup、模型列表裁切、Enter/Space 选择、disabled tabIndex、body portal/flip、当前非候选模型仅注入一次、<=6候选不展示搜索、Tooltip/arrow/zIndex,以及自定义 Input 测试不保存→保存→编辑→删除回调。
|
||||
|
||||
| 同一900×680状态 | 原版/当前精确矩形 |
|
||||
| --- | --- |
|
||||
| provider trigger | `[154,136,592,32]` |
|
||||
| provider popup | `[154,176,592,306]` |
|
||||
| model popup | `[154,344,592,216]` |
|
||||
| model list | `[163,393,580,166]` |
|
||||
| CUSTOM唯一结果 popup | `[154,176,592,120]` |
|
||||
| 无结果 popup | `[154,176,592,96]` |
|
||||
|
||||
同状态整块 popup RGB 像素比对,无 mask、无容差:
|
||||
|
||||
| 状态 | 像素数 | 不同像素 | 最大通道差 |
|
||||
| --- | ---: | ---: | ---: |
|
||||
| CUSTOM查询,含搜索框/文字/分组/原自定义SVG/列表/边框 | 71,040 | 0 | 0 |
|
||||
| NO_SUCH_PROVIDER_1,无结果含搜索/文字/No options/边框 | 56,832 | 0 | 0 |
|
||||
|
||||
结果 `.tmp/source-select-native-20261016/report.json`(30/30)、`pixels.json`、原生PNG与 crop/diff。它是组件和有限状态像素验收;fixture CRUD 使用受控 callbacks,不冒充后端或 OMP 验收。真实 App 多窗口入口/持久化/OMP 由主上下文的 production product-flow 单独验收。
|
||||
|
||||
可复现:
|
||||
|
||||
```powershell
|
||||
node scripts/rea/recover-select-reference.mjs
|
||||
npm run typecheck
|
||||
npx electron scripts/verify-source-select.cjs
|
||||
C:/Users/Administrator/.cache/codex-runtimes/codex-primary-runtime/dependencies/python/python.exe scripts/compare-source-select-pixels.py
|
||||
```
|
||||
|
||||
恢复输出:25项定义来源记录、16项 SVG 来源记录、4个资源、3个 CSS SHA。typecheck 两项目通过。主上下文负责最后统一 production build;本任务没有并发改写 out。
|
||||
|
||||
## 差异与未验证
|
||||
|
||||
原 runtime 16 providers、Tencent默认15模型;当前静态 domestic13 providers、默认8模型。保留当前实际静态目录,不填造额外源服务数据;因此默认全列表的大面积文字/数据不能声称像素全等。custom provider 的自由输入仍是真 Input;Select 搜索不会创建不存在模型,已有非候选值按照源客户端规则注入。
|
||||
|
||||
暗色、完整 hover/focus组合、长标题 Tooltip 的原版运行时截图、不同窗口/滚动组合、逐帧退出动效尚未全面对比。相关规则与 Tooltip 纯定义已恢复,宿主关键状态已测;源码恢复或本次两状态像素全等不替代其余状态验收。Kimi完整源SVG已取得,不能再把图标未知写成剩余阻碍。
|
||||
@@ -0,0 +1,65 @@
|
||||
# 表格字形与滚动层诊断(2026-10-16)
|
||||
|
||||
归档的滚动层、大位移和裁剪结构已在 YCode 自有 fixture 中复现,但没有消除 3330 个差异像素。当前未证实这些 wrapper 缺失是生产字形差异的原因,也未证实原版使用 `disable-lcd-text`。
|
||||
|
||||
本轮只改 `scripts/table-ui-regression.cjs` 和本文;输出位于 `.tmp/table-ui-regression`。没有修改生产 UI、GPU 开关或用户配置,没有新增原版窗口操作。
|
||||
|
||||
## 原版依据
|
||||
|
||||
WorkBuddy 5.8.2 的归档 `.tmp/rea-assessment-initial/layout.json`、`workbuddy.png`,Evidence:`ev_d6e6920ff4e47f73a182fac5312c5f02393366a035445d18c8a6733a8c8a11ed`。本轮读取的是 REA 保存的布局、样式和文本,没有通过其他渠道查看原版。
|
||||
|
||||
祖先规则来自固定 REA `src-CyXHA0IC.css`,SHA-256:`a5e26b537bb50323aefbf25abddad52e288dd3868598be8d255d70886fe77cfe`,CSS Evidence:`ev_377c8790468b3c67dad8577aabb327f98d3140659f0fffdbabfcff5a40cc9e94`。fixture 读取前校验该 SHA。
|
||||
|
||||
## 已验证的几何与环境
|
||||
|
||||
完整 `source-scroll-flow` 场景对以下七个祖先逐项断言 bounds 与归档完全一致:
|
||||
|
||||
| 节点 | x / y / width / height |
|
||||
| --- | --- |
|
||||
| 772:viewport | 284.28125 / 94 / 526.703125 / 639 |
|
||||
| 773:scroll | 284.28125 / 94 / 526.703125 / 639 |
|
||||
| 774:content | 284.28125 / -15153 / 516.703125 / 15886.828125 |
|
||||
| 775:document | 324.28125 / -15153 / 436.703125 / 15886.828125 |
|
||||
| 776:spacer | 324.28125 / -15153 / 436.703125 / 15886.828125 |
|
||||
| 777:flow | 324.28125 / -3933 / 436.703125 / 4666.828125 |
|
||||
| 1545:末尾 item | 324.28125 / 256.328125 / 436.703125 / 477.5 |
|
||||
|
||||
scrollTop 为 `15247`,flow 的 computed transform 为 `matrix(1, 0, 0, 1, 0, 11220)`。完整场景保留 `container-type: inline-size`、原 scrollbar / overflow 规则和两层无名 flow 包裹。前置内容用等高空区表达,目标 markdown 使用 REA 中可见的前段和表格内容。
|
||||
|
||||
表格 inner/table/th/td/code 的 bounds 和 70 项选定 computed style 均匹配;行高为 `42.75 / 44.25 / 43.75`。引用按钮的原生 hover/click、表内路径解析与点击、横向滚轮边界检查继续通过。
|
||||
|
||||
fixture 使用 SwiftShader、禁用 GPU compositing;`app.getGPUFeatureStatus()` 与归档的每项 `feature_status` 一致。GPU metadata 不包含原版完整启动实参或原始 compositor 图层树,不能证明所有文本绘制条件一致。
|
||||
|
||||
## 严格像素结果
|
||||
|
||||
ROI 固定为 `x=324, y=385, width=438, height=134`,共 58,692 像素,RGB 容差为零。
|
||||
|
||||
| 场景 | 差异像素 | 最大通道差 | 结论 |
|
||||
| --- | ---: | ---: | --- |
|
||||
| baseline:大 translate、无 scroll | 3330 | 109 | 未通过完整像素 |
|
||||
| source-scroll-flow:完整归档链路 | 3330 | 109 | 未通过完整像素 |
|
||||
| source-scroll-no-container:去掉 container-type | 3330 | 109 | 未通过完整像素 |
|
||||
| source-clip-flow:手工相同位移及 overflow hidden | 3330 | 109 | 未通过完整像素 |
|
||||
| baseline + 禁用 LCD 的负对照 | 1 | 2 | 不是原版配置证据 |
|
||||
| source-scroll-flow + 禁用 LCD 的负对照 | 327 | 1 | 不是原版配置证据 |
|
||||
|
||||
前四个场景的 ROI PNG SHA 完全相同:`b2f6ea6b7d07fabea3fa3d920eea325e73e382f86e641f8cdf2eaf3a224f0398`。因此,已复现的滚动、大位移、裁剪和 container-type 组合没有改变该区域的实际绘制。
|
||||
|
||||
常规场景的 3330 个差异中,3329 位于归档文字 bounds 外扩 1px 的范围内;另一个位于 inline-code 圆角,坐标 `(508,460)`,原版 RGB `(244,244,244)`,fixture `(242,242,242)`。禁用 LCD 的负对照说明文本栅格模式能解释主要差异,但完整滚动链路下仍有 327 个通道差 1 的像素。不得将负对照写成原版 GPU 配置已恢复或完整 1:1 通过。
|
||||
|
||||
## 命令与产物
|
||||
|
||||
```powershell
|
||||
$env:YCODE_TABLE_LAYER_CASE='source-scroll-flow'
|
||||
node scripts/table-ui-regression.cjs
|
||||
$env:YCODE_TABLE_LAYER_CASE='source-scroll-no-container'
|
||||
node scripts/table-ui-regression.cjs
|
||||
$env:YCODE_TABLE_LAYER_CASE='source-clip-flow'
|
||||
node scripts/table-ui-regression.cjs
|
||||
```
|
||||
|
||||
负对照额外设置 `YCODE_TABLE_DISABLE_LCD_EXPERIMENT=1`。该变量只影响启动的隔离 fixture。脚本退出成功代表几何、样式及交互断言通过;像素结论必须读取报告的 `fullPixelParity`,当前各场景均为 `false`。
|
||||
|
||||
主要产物:`report-source-scroll-flow.json`、`report-source-scroll-no-container.json`、`report-source-clip-flow.json`、`report-source-scroll-flow-lcd-disabled-experiment.json` 和对应 `candidate-roi*.png`。
|
||||
|
||||
当前缺少原版 compositor 图层 / 绘制状态及完整文本栅格配置证据。现有结果支持继续保留源码级表格修复;没有形成因字形问题修改生产 wrapper 或全局 GPU 开关的建议。后续采集范围和生产架构由主上下文决定。
|
||||
@@ -0,0 +1,86 @@
|
||||
# 首页视觉审查与机器人可见参考(2026-10-16)
|
||||
|
||||
本次只新增审查脚本、证据派生资源和报告,没有修改 App、ChatPane、SourceHome 或既有 CSS。以下比较基于固定截图/fixture,不能宣称当前生产首页或全部场景已经 1:1。
|
||||
|
||||
## 固定证据与范围
|
||||
|
||||
| 对象 | 来源 | 范围 |
|
||||
| --- | --- | --- |
|
||||
| 原版首页 | REA `ev_4fd56b4f30ca87b4d7012c80195becea384ffa95582b059558a16b8d871d57a8`;`.tmp/rea-home-static-20261016/{workbuddy.png,layout.json}` | 2026-10-15T16:48:52.506Z;截图可见 WorkBuddy V5.8.2;1336×901;办公、未选空间、GLM-5.3 Flash、允许完全访问、空输入、focused input |
|
||||
| 原版场景采集 | REA `ev_dcf614287152ff2d723fb4ac89f60be7162ec7f446eb81c52e466fea69cba80a`;`.tmp/rea-home-scenes-20261016/` | 2026-10-15T16:51:53.215Z;1336×901;包含已有场景连续图,本次不将其与办公 fixture 混为同一状态 |
|
||||
| YCode 冻结 fixture | `.tmp/home-native-ui/index.html`;原图 `.tmp/source-home-native.png`;新增采样 `.tmp/home-visual-audit-20261016/{native.png,native-layout.json}` | 1336×901;已有冻结 bundle,保留左侧280px空间,但没有绘制实际侧栏;办公、自定义模型、未选空间、空输入、非 focused input |
|
||||
| YCode 旧生产图 | `.tmp/ycode-live-main/{screen.png,layout.json}` | 1335×916,时间和状态更早,仅供历史观察;不据此给当前像素通过率 |
|
||||
|
||||
首页原图 SHA256:`360b076811ef19381f0670c314b24b06252310bf24fdc245f529f4894cfd7241`。场景主图 SHA256:`7e4ba766334049096df2c7b87becf1820b60184f3f070530c735db39710335c0`。脚本固定验证首页图 SHA,避免静默比较错图。
|
||||
|
||||
## 几何与字体残差
|
||||
|
||||
表中矩形为 CSS px,`[x,y,w,h]`。新 fixture 的主要纵向布局已与固定原版相同;可观察差异集中于横向基准、字体继承和绘制状态。
|
||||
|
||||
| 元素 | 原版 | fixture | 结论 |
|
||||
| --- | --- | --- | --- |
|
||||
| 标题容器 | `[405.125,158.5,800,42]` | `[403,158.5,800,42]` | 横向 -2.125,其他相同 |
|
||||
| 标题文字 | `[666.375,158.5,277.5,42]` | `[664.25,158.5,277.5,42]` | 同字号30、weight600、line42、字体声明;颜色不同 |
|
||||
| 场景切换外框 | `[693.125,216.5,224,36]` | `[691,216.5,224,36]` | 尺寸相同,横向 -2.125 |
|
||||
| quick actions 容器 | `[405.125,316.5,800,32]` | `[403,316.5,800,32]` | 高度、padding-right120、gap8相同 |
|
||||
| 制作PPT按钮 | `[675.125,316.5,81.234375,32]` | `[673,316.5,77.03125,32]` | 按钮窄4.203125;后续3项累计横向 -6.328125 |
|
||||
| 输入 slot | `[405.125,364.5,800,184]` | `[403,364.5,800,184]` | 宽高和纵向相同 |
|
||||
| 输入白色容器 | `[405.125,364.5,800,144]` | `[403,364.5,800,144]` | 宽高和 padding-top12相同 |
|
||||
| 机器人外框 | `[1085.125,286.5,120,120]` | `[1083,286.5,120,120]` | 原几何已恢复,图像内容不同 |
|
||||
| 机器人 img | `[1065.125,276.5,140,140]` | `[1063,276.5,140,140]` | 原几何已恢复,图像内容不同 |
|
||||
| 推荐容器 | `[405.125,600.5,800,236]` | `[403,600.5,800,236]` | 纵向、宽高相同;文字数据不同 |
|
||||
|
||||
原版中心为805.125,fixture中心803;原版侧栏分界284.25,fixture保留280。4.25px侧栏差使主内容中心差2.125px。应在真实 App 的侧栏宽度/分配契约处校正,避免给首页所有元素添加补偿偏移。
|
||||
|
||||
原版 quick-action 按钮计算字体是 **Arial / 14px / 400 / normal**;fixture 是 **`"PingFang SC", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", sans-serif` / 14px / 400 / 22px**。已有 `source-home.css` 中 `.quick-actions__item{font-family:inherit}` 与该证据相冲突。中文纯文本按钮宽度恰好均82,不足以证明字形相同;混合拉丁字符的“制作PPT”直接暴露宽度差。
|
||||
|
||||
主标题声明字体、尺寸和文字宽度相同,但原版 `color:rgb(0,0,0)`,fixture继承 `rgba(0,0,0,0.9)`,白底下文字较浅。多处祖先字号/行高也不同(原13px/normal,fixture14px/22px),这些不是所有子控件的实效字号;修复应限定原版选择器,不能直接全局改字号。当前 REA 首页证据没有实际平台字体采样,所以不能将“CSS字体一致”写成“字形一致”。
|
||||
|
||||
## 绘制、数据与状态应分别验收
|
||||
|
||||
- 输入框:原版节点848带 `cr-input-container--focused`,border-top-color 为 `rgba(0,0,0,.15)`;shadow 为 `rgba(0,0,0,.06) 0px 16px 32px -8px, rgba(0,0,0,.1) 0px 2px 4px -4px`。fixture非 focused,border `rgb(230,230,230)`,shadow `none`。需在真实 UI 点击输入框,使状态相同后再判 focused 样式。非 focused 原版在本次固定图中未观察。
|
||||
- 空输入 send:原版禁用灰色;冻结 fixture 显示黑色可发送。这是 fixture 的 `onSend`/disabled 交付契约差异,应验证真实 App 的空输入禁用逻辑;不能用截图中黑色按钮替原版禁用状态验收。
|
||||
- placeholder:原版“今天帮你做些什么? @ 添加上下文,/调用技能与指令”;fixture“发送消息...”。这是可直接对齐的展示文本契约。
|
||||
- model:GLM-5.3 Flash 与自定义模型属于数据差异。自定义模型应保留真实名称;图标、箭头、字体、间距应在相同控件状态下另测。
|
||||
- voice:fixture常显“语音转写服务不可用”,原版只有mic图标。服务不可用是能力/状态差异;具体失败文案显示时机需原版对应失败态证据,不能把未观察失败态当成原版默认 UI。
|
||||
- 推荐任务:两边文案不同,因此各行宽度不同不直接等于 CSS 错误;列表容器、行间距、胶囊边框和箭头可在统一文案后比较。原版真实数据来源/刷新规则未在本次运行时验证。
|
||||
- 侧栏账号、任务、空间、增长卡和原生标题栏:冻结 fixture没有绘制,不能据此判断生产组件缺失;旧生产截图也不作当前通过依据。
|
||||
- 场景/hover/键盘/动画/暗色:已有原版场景证据可继续逐状态测试;本次只量化办公稳定帧,不宣称开发、设计、切换动画、hover或暗色已验收。
|
||||
|
||||
局部像素诊断记录在 `.tmp/home-visual-audit-20261016/audit.json`。将 fixture 向右平移2整数像素仍剩0.125px raster phase,因而这些像素差只能用于定位,不能用于“零差通过”。标题区域12470像素中4228不同,RGB平均绝对差8.56;首chip区域2706中665不同,平均差16.63;直线输入框顶边7440中1240不同,平均差1.17。标题颜色、chip字体和输入focused状态分别已有计算样式证据解释,不能把整页差异都归于抗锯齿。
|
||||
|
||||
## 黑色机器人:已取得什么、尚未取得什么
|
||||
|
||||
已导出的 `default-miao-BlTmPevf.png` 是360×360透明灰/银猫(有青色单眼/星形另一眼),与原版首页截图中黑猫双竖眼不同。它是真实 fallback 源资产,不是本次运行时黑猫资产。
|
||||
|
||||
选中二进制导出证据:`ev_60a03f3376f0e0c04e16d12c7798e25401d1e697f33b39e4b5f7027794b09223`;ASAR root SHA `035254bc76310ea46317433e4840602094543ef323d2d5c5aff7c131729de918`;文件 `renderer/assets/default-miao-BlTmPevf.png`;资源 SHA `d164ac0e6e54438ea2a26a26e8ef622de3d911a674f55086d465ce10b011641d`。本次没有再次读取原版安装目录。
|
||||
|
||||
原版已由 REA 导出的 `contexts-BMeWSUHk.js`(证据 `ev_717fa5e846e64d67ac19c8925d121bff632c0d3aefb3603b10858559cabb2dcb`,SHA `5f35b7489b107e21ef452c8ee88a95265756f6fc444841eef869228bbc44768b`)说明:
|
||||
|
||||
1. `Wwn` 赋值从字符offset7018348开始,为 `new URL(default-miao-BlTmPevf.png,import.meta.url)`。
|
||||
2. `GrowthBuddy` 所在代码从offset7027087开始,读取 `data.buddy.thumbnail_url`、`base_animated_url`;有thumbnail且没有img error时使用thumbnail,否则Wwn。hover时播放video、离开暂停,img/video opacity切换0.2s ease。
|
||||
3. `useGrowthBuddy` 从offset4295749开始,使用 adapter `getGrowthBuddy()`;`pickCachedBuddy` 从4295216开始,只缓存thumbnail和animated URL。数据可能来自adapter响应或用户缓存,本次未观察具体返回值。
|
||||
|
||||
因此已定位资源选择逻辑,但**实际黑猫 thumbnail URL/视频URL还没有取到**。固定 REA layout 的IMG attributes为空;本地 REA视觉实现刻意未输出URL attributes,不能从该JSON逆推出URL。后续应由 REA增加明确的选中IMG src/currentSrc及已加载资源导出证据;如果指向ASAR,用REA `export-selected-artifact-binary` 定向取;如果指向远程/个性化资源,由REA读取已加载资源并记录媒体类型、SHA和来源,不走直接CDP/原版FS。
|
||||
|
||||
已提交可立即对比的最小参考:
|
||||
|
||||
- `src/renderer/src/components/source-home-assets/workbuddy-home-buddy-visible-reference.png`:**120×78静态可见片段**。
|
||||
- 同名 `.json`:证据、原始截图SHA、原布局节点、crop、偏移、alpha推导、SHA和限制清单。
|
||||
- 原crop `[1085,286,1205,364)`;原growth wrapper `[1085.125,286.5,120,120]`;片段相对wrapper偏移 `[-0.125,-0.5]`。alpha非零包围盒 `[21,25,79,78)`,即可见图像源坐标 `[1106,311,1164,364)`。
|
||||
- 原输入框从y364.5开始,row364可能混有边缘/覆盖;**整个row364及以下均不包含**。不能补画被遮挡身体,也不能把该片段标为完整黑猫源图。
|
||||
- alpha只去掉从crop边缘连通的纯白255背景,保留其他RGB及封闭的白色高光。6891像素透明,白底重新复合与原crop **0像素差**。这是白背景上成立的可见参考;不是恢复真实半透明alpha。抗锯齿边缘仍含白色matte,暗底未知。
|
||||
- 若用于当前UI临时对标,应作为独立120×78片段按上述offset放入120×120wrapper,避免套140×140/top-10的原始img规则。它不含hover、动画或完整身体;使用后仍需明确记录这些未完成项。
|
||||
|
||||
## 验证与下一步
|
||||
|
||||
执行:
|
||||
|
||||
```powershell
|
||||
node_modules/.bin/electron.cmd scripts/audit-home-native-geometry.cjs
|
||||
& 'C:/Users/Administrator/.cache/codex-runtimes/codex-primary-runtime/dependencies/python/python.exe' scripts/audit-home-visuals-20261016.py
|
||||
```
|
||||
|
||||
结果:YCode fixture采样17个元素、console errors0;原版截图SHA通过;机器人白底复合零差、资源/manifest生成成功;geometry审查17项。脚本只读取既有REA导出、YCode fixture,并写入本次报告/新资源。
|
||||
|
||||
主上下文可先修:真实主界面侧栏宽度中心基准、chip Arial/normal、标题纯黑、空输入placeholder/send契约,再在相同focused状态下验输入shadow/border;机器人可见片段可以先静态接入,完整源缩略图/动效仍需REA补证。重拍必须使用真实生产UI并固定尺寸、DPR、权限、模型、空间、输入焦点、菜单状态和同一文案数据。一次办公截图通过不能代替全部状态验收。
|
||||
@@ -0,0 +1,147 @@
|
||||
# Workbench 文本预览与编辑源码评估(2026-10-16)
|
||||
|
||||
结论:普通文件树打开的 text/code 预览,原版就是 **只读 MonacoEditor**,不是一个需要保存按钮的通用文件编辑器。当前 YCode 的只读方向与该入口一致,但 `<pre>` 远未等价于原 Monaco 渲染、查找、折叠、选择和主题。现有 REA 已保存完整 Monaco 包装组件与核心引擎源码,能够按源码恢复;目前缺的是完整引擎依赖闭包的本地接线与运行时验收,不能概括为“拿不到源码”。原 Monaco npm 精确版本仍未证实,不应根据 CDN 字符串安装猜测版本。
|
||||
|
||||
评估阶段只读现有 YCode、既有 REA Evidence;追加检查只通过已有 REA `export-selected-artifact-text` 对固定 ASAR 的明确 metadata 路径导出,未操作原版页面、未安装依赖。后续经 root 授权的只读代码预览实现与真实验收记录见文末。offset 均为对应原始 JS 字符串的 **零起点 UTF-16、半开区间**,不是重排后代码行号,也不是 UTF-8 文件字节偏移。
|
||||
|
||||
## 原版入口与实际行为
|
||||
|
||||
| 入口 | 源码实际实现 | 编辑/保存边界 |
|
||||
| --- | --- | --- |
|
||||
| 文件树普通 text/code | `FileViewer → FileViewerContent → MonacoEditor`,lazy `codeEditor-D3P9alks.js` | `readOnly:true`,没有此分支的 `onChange`/磁盘保存。不要添加原版不存在的 save UI。 |
|
||||
| 文件树 Markdown rendered 模式 | `FileViewerMarkdownPreview → MarkdownEditorCore` | 这里同样 `readOnly:true`;提供相对图片解析、文件链接、zoom。原条件是 rendered 且文件名以 `.md` 结尾。 |
|
||||
| media artifact 的 CodePreview | 同一个 MonacoEditor | `readOnly:true`,**fontSize14、minimap:true**;不能与普通文件的 13px/minimap:false 混用。 |
|
||||
| custom artifact `contentType:'code'` | `ArtifactContentRenderer → MonacoEditor` | 传 `readOnly:!artifact.enableEdit`。该调用片段没有传 `onChange` 或 save,故不能据 enableEdit 宣称已支持磁盘持久化。 |
|
||||
| media Markdown 编辑 | `markdown-editor-C1Uvzy8a.js` 的 `MarkdownEditor`,默认 readOnly:false,使用 `MarkdownEditorCore` | 完整文档编辑、dirty/save/source 注册、外部文件变化订阅;支持 in-process 与 isolated iframe guest 两条路径。独立于普通 text 预览。 |
|
||||
| 较早 custom Markdown 分支 | `src-Cng7axVa.js` 的 `MarkdownViewer/MarkdownEditor` | 能看到 LexicalComposer 与 SavePlugin;这不能用来替代当前 media Markdown SDK 实现。 |
|
||||
| code diff / file-change | `PierreDiffEditor` | 与 MonacoEditor 同一打包文件导出,但底层是 Pierre diff;不是普通文本编辑器。YCode 已有 recovered-pierre 引擎。 |
|
||||
| HTML 编辑 | 独立 `onEditHtml/isHtmlEditing/onExitEditHtml` 与 browser/document preview 路由 | 不属于普通 text/code 分支;本次未证明完整 HTML 编辑宿主/save 协议,不借此扩展通用文件编辑需求。 |
|
||||
|
||||
普通预览核心调用确切为:
|
||||
|
||||
```tsx
|
||||
<MonacoEditor value={content || ''} language={getLanguageFromFileName(filename)}
|
||||
readOnly={true} minimap={false} lineNumbers="on" wordWrap="on"
|
||||
fontSize={13} height="100%" />
|
||||
```
|
||||
|
||||
位置:`media-preview-DMz4TW4q.js` offset 201964(props 的 readOnly 位于 201991);`FileViewerContent` 起点 194277;lazy Monaco import 位于 186752。CodePreview 的 14px/minimap:true 在 205633 附近。custom artifact code/diff 路由分别在 `src-Cng7axVa.js` 411051、411458;diff lazy 导出 `PierreDiffEditor` 在 394785。
|
||||
|
||||
普通入口是 renderer 内的 Monaco DOM 编辑控件:完整 `editor.api2/editor.main` 与 React loader 调用链可见,**没有证据将其称为 CodeMirror 或外部原生 VS Code 编辑宿主**。此结论只限上述入口,不推断全应用从未使用其他编辑器。
|
||||
|
||||
## 已拿到的包装组件与依赖
|
||||
|
||||
`codeEditor-D3P9alks.js` 原末尾直接导出 `re as MonacoEditor, No as PierreDiffEditor`。Monaco 组件赋值 `re` 在 **[14737,21221)**,6484 字符,原体 SHA-256:`6d7aeb7714f2f52fd86c37957a12c5774be029b31e96f39a50b7e8e6ec11b9a8`。自定义搜索组件 `ee` 在 **[11624,13951)**,2327 字符,SHA:`e8030c9dd9bb94e12f4a3e4816362ec53e52b4380b348c38b42627ff37dbfac4`。这两段均已保存在静态 shipped-artifact Evidence 中;runtime 的 339 项集合没加载该 lazy 文件,不等于源码缺失。
|
||||
|
||||
包装层已确证的行为:
|
||||
|
||||
- 字体 `'Menlo', 'Monaco', 'Consolas', 'Courier New', monospace`;普通入口 13px,包装默认 lineHeight20/tabSize4;字体最终值 `max(8, fontSize + --cb-font-size-offset)`,监听 `cb-font-size-change`。
|
||||
- `automaticLayout:true`、`scrollBeyondLastLine:false`、纵横 scrollbar10px/useShadows:false、folding:true、glyphMargin:false、contextmenu:true、links:true、colorDecorators:true、括号及缩进 guides。
|
||||
- 只读时 `renderLineHighlight:'none'`、`matchBrackets:'never'`、`selectionHighlight:false`、`occurrencesHighlight:'off'`。
|
||||
- 自定义 Ctrl/Cmd+F 搜索;大小写、整词、regex、匹配计数、prev/next、Escape,Monaco decoration 标记与 `revealLineInCenter`。这不是对话区的 CSS Highlight 搜索。
|
||||
- SharedThemeManager 从源主题/CSS 构造 `custom-dark/custom-light`,订阅主题变化;模型/编辑器/decoration 有卸载释放逻辑。`onChange` 只是包装层回调能力,不是保存文件实现。
|
||||
|
||||
源码依赖链为 `MonacoEditor → monaco-init → React Monaco loader / editor.main → editor.api2 + monaco.contribution + workers + 动态语言模块`。不能直接 import 整个 `codeEditor` 原入口:它混有 Pierre 引擎、应用 UI imports 与模块初始化;应像既有 Pierre recovery 一样抽取所需 closure,并将 React/i18n/UI primitives 与宿主入口显式绑定。
|
||||
|
||||
现有 Pierre recovery 已明确拒绝 `./src-0FGg1seX.js`、`./monaco-init-CE4MbM4x.js` 进入其闭包。因此 `recovered-pierre/engine.mjs` 不能当成已经恢复了 Monaco 的证明;可复用的是它的 AST closure/hash/资源复制工作方式。
|
||||
|
||||
`monaco-init` 优先导入本地 `editor.main-POO0Vbhx.js`。其 `configureMonacoEnvironment` 在 window 尚无 MonacoEnvironment 时设置 **no-op worker**(offset16148/16626),注释日志明确为 CSP compatibility。`workers-BAt3Re_d.js` 也有标准 getWorker/getWorkerUrl/createWorker 路径。不得无证据新增“原版已运行完整 TS language server”的结论。
|
||||
|
||||
`editor.main` 静态依赖的核心模块已在 runtime Evidence;但它声明的 **92 个动态 import 在该 runtime 集合中均未捕获**,包括 `cssMode-Z-o80aSY.js`、`htmlMode-BDZbYlMj.js`、`jsonMode-DdQpkp6D.js`、各 Monarch 语言模块。这是采集覆盖缺口,不是包中不存在。后续可用固定 ASAR 的 REA selected export 补齐闭包,不需原版 live UI。Pierre/Shiki 的语言模块文件即使已保存,也不能自动顶替 Monaco 对应模块。
|
||||
|
||||
Markdown SDK 另有真实 `smart-doc-convert` module worker:`markdown-editor-core` offset84806 引用 `worker-impl-DwAbHlUk.js`,当前 runtime 集合无此 worker。core 还依赖 `dist-CnSZIDKe.js` 的 block/contenteditable SDK 等模块。其 guest bridge有 requestSave/requestContent/requestDirty/saveResult;这条编辑链比只读 Monaco 预览大得多,不是“抽出一个 contenteditable div”即可还原。
|
||||
|
||||
## 精确版本能否确认
|
||||
|
||||
WorkBuddy 版本确认为 **@genie/workbuddy-desktop 5.8.2**,固定 ASAR SHA 为 `035254bc76310ea46317433e4840602094543ef323d2d5c5aff7c131729de918`。
|
||||
|
||||
**Monaco npm 精确版本未确证。** 已查到的三个不同标记必须区分:
|
||||
|
||||
| 标记 | 原模块/offset | 能证明什么 |
|
||||
| --- | --- | --- |
|
||||
| `monaco-editor@0.55.1/min/vs` | monaco-init 6631 | 内嵌 loader 的默认 CDN 路径;不是本地 ESM 构建版本证明。 |
|
||||
| `monaco-editor@0.45.0/min/vs` | monaco-init 17250、17850附近 | 本地导入失败时自定义 fallback 路径;与上项不同,更不能据此定本地版本。 |
|
||||
| `Code - OSS Dev`、`version:'1.104.0-dev'` | editor.api2 399559 | 内嵌 VS Code 产品 metadata;不是 Monaco 包的 semver。 |
|
||||
|
||||
已保存 root `package.json` 没有 Monaco/React-Monaco 的直接版本。补充通过 public REA root-pin selected export 检查以下五个明确路径,均返回“Selected path is absent from the ASAR inventory”:`node_modules/monaco-editor/package.json`、`node_modules/@monaco-editor/react/package.json`、`node_modules/@monaco-editor/loader/package.json`、`node_modules/@genie/workbuddy-desktop-sdk/package.json`、`node_modules/@genie/workbuddy-core/package.json`。执行记录在 [.tmp/rea-editor-package-metadata-report.json](C:/Users/Administrator/code/YCode/.tmp/rea-editor-package-metadata-report.json)。这是这些路径的缺失,不能外推为整个打包应用绝无 lockfile/元数据。
|
||||
|
||||
两种实现路线的判断:
|
||||
|
||||
| 路线 | 当前可实施性 | 限制 |
|
||||
| --- | --- | --- |
|
||||
| 原版 wrapper/CSS + 原版 ESM chunks | **推荐**。构建内容由原 SHA 固定,避免猜包版本;需 REA 导出动态语言闭包及 YCode 本地 loader 适配。 | 资源体积/模块环、动态路径、CSP、主题和卸载必须验证。单纯复制文件不等于运行通过。 |
|
||||
| 原版 wrapper/CSS + npm 安装同版本 Monaco | **暂不能称为“同版本”**。需先有可信 package/lock/notice/source-map 等版本证据。 | 0.55.1 或0.45.0目前都只是 CDN 路径;即使版本证实,也还要验证原 bundle 是否有补丁。 |
|
||||
|
||||
不需要为只读预览先解决 npm semver:原 ESM chunks 已给出了更精确的实现身份。不要为了“更新到最新版”更换引擎。
|
||||
|
||||
## 评估时 YCode 的差异基线
|
||||
|
||||
当前代码位置:[WorkbenchResourceBody.tsx](C:/Users/Administrator/code/YCode/src/renderer/src/workbuddy/workbench/WorkbenchResourceBody.tsx)、[workbench-adapters.css](C:/Users/Administrator/code/YCode/src/renderer/src/workbuddy/workbench/workbench-adapters.css:41)、[resources.ts](C:/Users/Administrator/code/YCode/src/main/resources.ts:73)。
|
||||
|
||||
| 项目 | 原普通文件预览 | YCode 当前 |
|
||||
| --- | --- | --- |
|
||||
| 排版/文本引擎 | Monaco 的真实字形测量、virtualized editor、gutter、selection/scroll/fold | `<pre>` 内逐行 div+span;13px/**22px**,固定48px行号 gutter,自定义padding;无法视为相同布局。 |
|
||||
| 语言/颜色 | 按文件扩展名映射语言、Monarch tokenization、源主题配色 | 普通文本分支无语法 token、语言识别或编辑器主题。 |
|
||||
| 查找 | 独立 editor CtrlF/大小写/整词/regex/计数/导航/decoration | 普通 `<pre>` 无该实现。 |
|
||||
| 浏览交互 | fold、context menu、链接、字符/词/行选择、键盘移动、括号/缩进 guides | 仅浏览器文本选择与滚动;range 高亮是宿主新增样式,不是已恢复 Monaco decorations。 |
|
||||
| 内容范围 | FileViewer 向 Monaco 传当前完整 content | resources.read 默认约400行,range窗口,最多2000行;截断文本不能当作完整 Monaco model。 |
|
||||
| 读取上限 | 源 size-limit 按类别:txt50MiB、md30MiB、html50MiB,未知类别默认1GiB;检查集合含code,判断为size>=limit | 所有文本统一2MiB;二进制NUL拒绝;UTF-8读取。这些策略尚不等价。 |
|
||||
| Markdown/HTML | 原 viewMode与专用SDK/browser路线 | 当前按扩展名直接送 ArtifactHostPreview,不等于源文件树的 source/rendered 模式及编辑路由。 |
|
||||
| 磁盘保存 | 普通code预览不需要;Markdown编辑的 onSaveFile→local writeFile 或sandbox写入是另一条能力 | 当前 resources API只有read/readText/download等,没有通用编辑写回契约;Artifact cache update也不是写盘。 |
|
||||
|
||||
现有 `ArtifactPierreDiff` 已接 recovered-pierre,可继续独立验收。它不是只读文件 `<pre>` 的替代品,也不提供普通文件保存。YCode `ArtifactCode` 的 RecoveredCodeBlock 同样不是 MonacoEditor。
|
||||
|
||||
## 最小真实接入边界与后续证据
|
||||
|
||||
第一步只替换 **普通 text/code 只读预览**:保留真实 session/workspace 资源读取与 owner 隔离,恢复 `getLanguageFromFileName`、MonacoEditor/SearchWidget/CSS 与必要主题构造器;使用完整 `resources.readText` 内容建立 model,按源 props 接入 font13/line20/minimapfalse/wrapon/readOnlytrue。不要为该入口新增 save,不改成 code diff,不把400行窗口静默当全文。
|
||||
|
||||
加载与 worker 由独立 YCode host adapter 承担:本地 ESM 地址、CSS、动态 grammar import、CSP、主题事件和 model/worker卸载必须指向 YCode 自有资源。保留源 no-op worker 的事实;要启用真正语言 worker 则需新的功能证据和单独验收,不能把“worker包存在”当作原版已启用。源码恢复应保留body/hash及明确的React/翻译/主题接口适配记录,避免执行原应用全局初始化。
|
||||
|
||||
可以先单独恢复的低依赖纯源码:
|
||||
|
||||
| 源体 | offset | 依赖边界 |
|
||||
| --- | --- | --- |
|
||||
| `getLanguageFromFileName` | media-preview [191107,192191) | 扩展名 literal map,纯函数;SHA `666dfd63d32a89ed66020d0a4fb6d1a41c25be41692c3538e6b167c157fa1465`。 |
|
||||
| `isUnsupportedBinaryPreview` | media-preview [186118,186398) | 纯判定+已知5项内容类型常量;SHA `e9f2e71fbfc9d3d5cb650d47cddf72f08ffc84e9b082b18b758120aedd6e0b49`。 |
|
||||
| `getMonacoLanguage` | codeEditor [13985,14121) | 纯函数+语言alias map;SHA `3cd971a3042c0c9e504356e9e5b987161675e781c08000b28903fb9d10cf612a`。 |
|
||||
| `resolvePreviewSizeCategory/Limit`、`resolveOversized`、`formatBytesHuman` | preview-size-limit 模块 | 纯策略与常量;可原体恢复,需保留>=边界和类别差异。 |
|
||||
| SearchWidget、loading/binary/oversized视觉片段 | 上述组件与media CSS | React+源icons/buttons/i18n可隔离恢复;SearchWidget真正导航仍需Monaco实例。不是完整低依赖编辑器。 |
|
||||
|
||||
第二步才单独评估 Markdown 编辑:补 `worker-impl` 和block SDK/guest依赖,通过YCode主进程实现真实全文写回、dirty/revision冲突、文件变化订阅、保存错误、关闭前未保存处理;接 source `onSaveFile` 协议后再谈与原编辑能力等价。原 local链在 `detail-panel-wrapper` offset56030 使用 `writeFile(sessionId,path,text,{allowedDirs:[path]})`,云侧 offset58522 为 `writeSandboxFile`,offset135434将选出的能力传作onSaveFile。不得把cache callback或export下载冒充写回。
|
||||
|
||||
还需取得或验收的证据:
|
||||
|
||||
1. 通过REA静态 selected export补齐Monaco dynamic grammar/mode依赖图、可能字体/worker资源;保持ASAR root pin。若必须安装npm版,再找精确版本及补丁来源证据。无需占原版页面完成静态闭包导出。
|
||||
2. 原版实际普通代码文件的light/dark、长行wrap、行号gutter、CtrlF三种选项、折叠、复制/选择、空文件、多tab切换的REA runtime layout/截图/动作记录。目前静态props已证实,但这些状态尚未在本次验证。
|
||||
3. YCode真实production App验收完整读取、中文/Latin字形、长文本/范围定位、搜索/复制/主题、快速切tab后的model释放;sourceGPU环境做定点像素比较。编译通过不等于1:1。
|
||||
4. Markdown编辑另采dirty/save/外部修改/关闭确认/guest协议,不能使用普通只读代码截图替代。
|
||||
|
||||
## 可复核 Evidence 与文件哈希
|
||||
|
||||
| 保存证据 | 内容/身份 |
|
||||
| --- | --- |
|
||||
| `.tmp/rea-selected-editor-evidence.json`,`ev_eff23685a08fc8c5ed6ad542c21b24337ed3d7a7c9a483628762ae17828b5d36` | `codeEditor-D3P9alks.js` SHA `5e9a16dca97c102afc3c73cd7dd32ba63daf5e7ddff12707ee1ea63e7a427b19`;`codeEditor-Bxmo_AI3.css` SHA `1c8f2210c731a25f9051088df0db78b9de5b087c802b3a9e36828c1b6b54c353`。 |
|
||||
| `.tmp/rea-selected-package-plugin-evidence.json`,`ev_2caae424199a38371af743ef9111db835504c2dae54c1f02e1f9e5511032cc6b` | package.json SHA `a295ae602e936abda5ae45f7a5c21fc481014989d2cf369182d3ce5d9dd400c2`;确认产品5.8.2。 |
|
||||
| `.tmp/rea-runtime-scripts.json`,`ev_717fa5e846e64d67ac19c8925d121bff632c0d3aefb3603b10858559cabb2dcb` | 本文运行时JS来源,共339项;是有界已加载集合。 |
|
||||
| media-preview-DMz4TW4q.js | SHA `e8c19693ac7d8d06b45b531de405cc23c071fa19ebd5543b483a43dbdfce8111`。 |
|
||||
| monaco-init-CE4MbM4x.js | SHA `3cfc0aab23c1d7e100ae094bd058c0b794b3ef933eb5873011ad45368350f13a`。 |
|
||||
| editor.api2-dPwET-7w.js / editor.main-POO0Vbhx.js | SHA分别 `8aa5a0e62e8f97673ade05dd05098782bb4f457c3ef6d2f6e67cf3ac0404bea7` / `a7321a42627d1814bc74385b647e21248cb23a1cd3a5daeaeb1ef7670dd08f37`。 |
|
||||
| workers-BAt3Re_d.js | SHA `c502bc2291877793f68723fc7519ef587c1388f3ca4aed8603fed3372edc6dda`。 |
|
||||
| src-Cng7axVa.js / detail-panel-wrapper-DkXYIOHM.js | SHA分别 `5ce8649e3bfac10aec1e63afee726ab45abaafc5aa7cc372892e20f3eba18c8b` / `35099e6a9294923f3cb413629ff47a65e5d545a7ff9226eff97675ae2dd5f906`。 |
|
||||
| markdown-editor-C1Uvzy8a.js / markdown-editor-core-CH4mirps.js | SHA分别 `03c659e7a50e011db1f03b50dd80af5b99c435e6ddaf9321dee1d5fdbe579861` / `63a120cb404c65d621e4ac1489f4c6d6178d7789cd9f9e1ac2d39b4d52553477`。 |
|
||||
| preview-size-limit-BPMUeizf.js | SHA `a35b8b9877f689a4e0ac3d346efc58e7e4e71bb70a1123766ebc596416123c0a`。 |
|
||||
| `.tmp/rea-css-recovered/manifest.json`,`ev_377c8790468b3c67dad8577aabb327f98d3140659f0fffdbabfcff5a40cc9e94` | editor-gwlzV742.css SHA `90a835b8c3b45dbf7d2f2c699876b393f0564a657e7639cc916daa506e1685b3`;media-preview-Dvr0Ekj9.css SHA `36758fadd61577145a3b46dd12bcd966c662ea0cfaa4e62dc3e31ba4bf7f5fb8`;markdown-editor-core-DOOI2-AG.css SHA `351d38dab5173c10da28b2d2962bdd21e20c44ce13dc8c65ae84667d8c919f85`。 |
|
||||
|
||||
评估阶段验证:已重新计算上述10份runtime JS的SHA-256,全部匹配;selected codeEditor JS/CSS与root package导出文本的SHA/size匹配;Babel AST核对wrapper/SearchWidget/纯函数原体offset与hash;运行现有 public REA export明确记录metadata路径缺失。
|
||||
|
||||
## 后续授权实现与真实 App 验收
|
||||
|
||||
已通过 [recover-source-code-preview.mjs](C:/Users/Administrator/code/YCode/scripts/rea/recover-source-code-preview.mjs) 补齐 **101 个固定 shipped assets**,包含完整当前入口依赖闭包、Monaco模式/语言模块、4个语言worker入口、codicon.ttf。8份新增 root-pin REA Evidence 保存在 `.tmp/rea-monaco-chunks-000.json` 至 `007.json`;逐文件Evidence/hash、依赖graph与原体hash在 [source-code-assets/manifest.json](C:/Users/Administrator/code/YCode/src/renderer/src/workbuddy/workbench/source-code-assets/manifest.json)。没有安装猜测版本的Monaco包。
|
||||
|
||||
[SourceCodePreview.tsx](C:/Users/Administrator/code/YCode/src/renderer/src/workbuddy/workbench/SourceCodePreview.tsx) 已替换 WorkbenchResourceBody 最后普通text的pre分支,其他文件类型路由保留。恢复了原6484字符Monaco包装体、2327字符SearchWidget与原类名/CSS/语言映射/close SVG;YCode React单例、原生input/button绑定是显式宿主适配。原引擎保留源no-op worker设置,资源均来自YCode本地。
|
||||
|
||||
必要构建适配有明确记录:原打包器`__vite__mapDeps`预加载表改为YCode的空预加载adapter,由当前Vite负责实际import与CSS地址,防止保留旧URL及Vite保留名重声明;本地导入失败的两条CDN fallback改为本地错误,失败显示原缓存文本。其余未适配资产保持逐字节SHA相同。不能据这些适配声称搜索栏全部宿主控件已经逐像素相同。
|
||||
|
||||
全文通过真实`resources.readText`读取;按现有上限仍是2MiB。range使用一个Monaco decoration并reveal,450→20→无range保持同一500行model URI;root的store仅对已有成功text资源更新range,避免上层loading卸载editor。现有打开model不会自动响应外部文件变化;range重开保留缓存;关闭面板卸载后重开会重新读全文。文件watch、显式刷新语义、超2MiB策略、Markdown/HTML编辑写回仍待独立接入,普通只读文件没有新增save。
|
||||
|
||||
已验证:`npm run build`(含node/web typecheck)、`node scripts/source-code-recovery-regression.mjs`(101资产、完整闭包、9个原体hash、无原app/React全局依赖)、`node scripts/verify-source-code-preview.cjs`(真实隔离production App/文件树/IPC)。最终报告:[source-code-preview-Su4EM3/report.json](C:/Users/Administrator/code/YCode/.tmp/source-code-preview-Su4EM3/report.json)。覆盖500行全文、源只读13px/20px/wrap/scrollbar/tabSize、真实彩色Monarch token、500个搜索命中、450→20→无range同model、深色、两会话同名文件隔离、真实临时文件删除后的错误及原文fallback。HTTP请求与renderer error均为空。原版live未操作;没有进行原版普通代码窗口的完整像素/动效验收。
|
||||
@@ -0,0 +1,145 @@
|
||||
# 专家使用逻辑:REA 源码核对
|
||||
|
||||
2026-10-16;WorkBuddy 5.8.2。只读已保存 REA 导出,没有操作原版 UI、召唤、发消息或修改生产代码。下述是固定版本源码的控制流结论;未用行为实测覆盖所有并发、失败和窗口状态。
|
||||
|
||||
核心结论:**没有按 expertId 搜索并任意复用历史会话的逻辑**。市场默认召唤准备首页草稿;显式携带 `targetConversationId` / `targetSessionId` 才绑定指定会话。新输入框加号通过独立 provider 流程切换当前输入上下文,与市场共用 `wb.experts.summon` 底层,但不是同一个 React 入口。
|
||||
|
||||
## 证据与可复核锚点
|
||||
|
||||
已对以下两个 REA JSON 的全部文本重新计算 SHA-256:
|
||||
|
||||
- `.tmp/rea-runtime-scripts.json`:339 模块;Evidence `ev_717fa5e846e64d67ac19c8925d121bff632c0d3aefb3603b10858559cabb2dcb`。
|
||||
- `.tmp/rea-expert-runtime-scripts-20261016.json`:329 模块;Evidence `ev_e91787b1d4dea651582c6cf12827775b9068b0ee8b80c68ba08d4c1d87d94e90`。
|
||||
|
||||
两个导出中本报告使用的同名模块 SHA 一致。原包基线 root SHA 为 `035254bc76310ea46317433e4840602094543ef323d2d5c5aff7c131729de918`。以下函数范围单位均为已导出 JS 的 **UTF-16 code unit,start 包含/end 不包含**,不是文件行号;以 Babel AST 核对具名函数范围。
|
||||
|
||||
| 模块简称 | 原 `renderer/assets` 文件 | SHA-256 |
|
||||
|---|---|---|
|
||||
| C | `contexts-BMeWSUHk.js` | `5f35b7489b107e21ef452c8ee88a95265756f6fc444841eef869228bbc44768b` |
|
||||
| P | `workbuddy-provider-DkH2YFYM.js` | `b588e875c469978f216beec86bdf4b6c33a31c0266f9bf996881b8dbf37b5dc7` |
|
||||
| H | `home-CC-czDJL.js` | `121d5a07acccb09e48f20f3a94f9fac8b10770e4a82bca1916d2cccd333f8d14` |
|
||||
| I | `src-DbE1_mgM.js` | `6c6ce63c93854783270e855572797d75e536e3b8d4548410e31fe9d147e1feb4` |
|
||||
| D | `desktop-sdk-setup-C2AUiJmx.js` | `ac3bdeb6d81776491e175ddfae262e64f77d3dc9c0821d6075a91bf1b889dc23` |
|
||||
| L | `wb-input-add-B045GnIg.js` | `7842fa4321d5351bf6c822bbd0253e0d6d6e68cc9cfae3f2470b3d493c23daf4` |
|
||||
|
||||
## 市场召唤与会话目标
|
||||
|
||||
`C.useExpertSummon$1 [3909983,3917240)` 先调用 expert API 获取已准备的专家(`createExpertApi [3560992,...]` 明确 `summonExpert => getExperts().summon`),合并本地化名称、职业、默认提问、头像、plugin/agent/runtimeIdentity/source 等资料。随后按以下顺序分流:
|
||||
|
||||
| 目标 | 确切行为 |
|
||||
|---|---|
|
||||
| 合法 Office 返回目标 | 校验 conversation ID、`window:office:` window ID、`returnConversationCreated` 布尔值。新创建目标先 bind;通过 window message 投递带 `suppressDefaultInitPrompt:true` 的专家,再 focus 返回窗口。不会降级成任意其他会话。 |
|
||||
| `targetConversationId` | `returnExpertToConversation` 绑定该 ID,导航回此会话并发布 `prepare-input`,`preserveBlocks:true`,expert 带 `suppressDefaultInitPrompt:true`。没有查找“以前和同专家聊过的会话”。 |
|
||||
| 无 target session/conversation | `conversations.prepareInput({target:{type:'new'},contentBlocks,expert,...})`;SDK 导航 home、发布输入意图,**不在此创建会话或发送**。 |
|
||||
| `targetSessionId` 字符串 | `session.prepare({targetSessionId,context:{expert...}})`,成功后导航指定 ID。`C.useAdapterSession [4306763,4308361)` 在 `expert && targetSessionId` 时调用 `setSelectedExpertForSession`,返回同一 ID。 |
|
||||
|
||||
`C.bindExpertToConversation [3907799,3908569)` 要求 `conversations.get(id)` 找到目标,否则抛错;经 UI config 或 core config 设置专家、来源与 runtime identity,然后将非 craft 模式改为 craft。`returnExpertToConversation [3908569,3909521)` 的普通返回带 `expertSummonReturn`,包含 expertId、defaultInitPrompt、inputSnapshotToken,之后以 preserveBlocks 发布输入选择。
|
||||
|
||||
`C.readExpertSummonReturnIntent [3919686,3920377)` 只读取导航 state 中明确给定的返回 ID;非法 Office 返回信息会丢弃 conversation target。`C.useExpertSummonFlow [3920501,3924917)` 将这些目标原样下传;没有“按 expertId 复用历史”的候选列表/匹配算法。
|
||||
|
||||
`D.prepareInput [375609,378110)` 对 `target:new` 导航 home。对当前 active conversation 的 `submitMode:none` 有专门就地更新输入分支;对非当前 conversation 携带 expert 的普通 prepareInput 则明确报“不支持”。市场返回现有会话通过独立 bind+input-intent 流程,不是绕过这项限制偷偷创建另一个会话。
|
||||
|
||||
`H` 首页创建回调 `[43600,49000)` 是后续按发送才调用 `wb.conversations.create` 的地方,携带 expert/tag/locale/mode 等;创建并配置成功后按发送前捕获的 revision 清 new-task expert,preparedContext 也只在对象仍是原对象时清除。不能把“已准备专家草稿”当成“已创建专家会话”。
|
||||
|
||||
## 新加号、旧加号与共享底层
|
||||
|
||||
新输入框 `I.ExpertsSubmenu [1574199,1579192)` 中普通列表和搜索结果都调用同一个 `onSelect(expert,{position})`。selected 只决定勾选显示,**该函数没有相同 ID 点击短路**。同步传输中/`cloudStatus:checking` 禁用行;搜索有 debounce、IME composition、失败重试;置顶与搜索列表都不改变召唤会话目标。
|
||||
|
||||
`I.AddMenu` 专家分支 `[1603400,1604590)`:
|
||||
|
||||
1. 保存旧 draft expert;需要 local/cloud transfer 时,先等待 provider.onChange 返回准备好的专家,才放入 draft。
|
||||
2. 普通选择先设置 `{...expert,suppressAutoSummon:true}` 并关闭菜单,再 await provider.onChange;失败恢复保存的旧 draft expert。
|
||||
3. “召唤更多”调用 provider.onSummonMore,不自动发消息。
|
||||
|
||||
连接路径是 `C.useSharedWbInputProviders [4601705,...] → useWbExpertProvider [3957662,3961924) → useExpertSummon [3951518,3954856)`。会话输入将 conversationId/onExpertChange 传给 provider;首页不传现有 conversationId,而由首页 selection owner 持有选择。`useSharedWbInputProviders` 还在非 silent 操作调用 `shouldBlockExpertChange`;被 team guard 拒绝会抛 `Expert change blocked`。
|
||||
|
||||
旧 `L.ExpertsSubmenu [46657,约50700)` 确实存在另一条路:普通最近项用 `onSelect`、点击已选 ID 只关菜单;搜索项用 `onSummonSearchResult`,返回 false 不关菜单。`C.useExpertSearchSummon [4311266,4314603)` 属于此类 legacy main-content 召唤流程,默认将当前 conversationId 作为 targetSessionId,失败按 summonTimestamp 恢复 ref/专家模式。
|
||||
|
||||
**不能用旧菜单“已选项直接返回”规则替代新 cr 菜单;也不能用旧搜索独立入口推断新菜单搜索一定走市场 React flow。** 本轮没有查看原版 UI,具体正在显示哪一个菜单实例需由运行时 REA 证据确定;源码中两套路径和新 home/conversation 接线均已明确。
|
||||
|
||||
## 默认提示词、用户草稿与清除
|
||||
|
||||
默认文本由输入 owner 的 onChange/applyPrefill 处理。`I.ExpertChip [1693259,约1695700)` 只负责显示/准备中状态、silent hydrate 和清除专家;它本身不写默认提示词。
|
||||
|
||||
| 场景 | 源码行为 |
|
||||
|---|---|
|
||||
| 市场默认进入首页 | `C.createExpertSummonInputSnapshot [3886918,3887267)` 将文本判成 user / expert-default / empty。user 文本原 blocks 保留并加 suppressDefaultInitPrompt;其余情况保留非文本资源并置入新默认提示词。无新 default 时保留原 snapshot blocks。 |
|
||||
| 首页直接选择 | `H.useHomeExpertSelection [61126,64079)` 设置 expert/craft;允许 default 且没有非文本 block 时调用 applyPrefill(default)。存在非文本 block 时不会用该调用覆盖整组 blocks。 |
|
||||
| 首页清除 chip | 同一函数的 `expert=null` 分支设置 expert 空并 dismiss dependencies,**没有 applyPrefill(null)**。`setExpert` reducer 只修改 selection,因此不能宣称首页清专家必清默认文本。 |
|
||||
| 会话直接选择 | `C.ConversationInputImpl` 的 `be [7073311,7074328)` 将模式改 craft、写 config expertId;未 suppress 时 applyPrefill(default 或 null)。 |
|
||||
| 会话清除 chip | be 收到 null,清 config expertId、依赖 gate,并 applyPrefill(null);此调用仍受输入是否已由用户编辑保护。 |
|
||||
| 已有会话/持久化恢复 | `suppressDefaultInitPrompt:true` 用于避免恢复绑定时重新填默认文本;同一专家 hydrate 保留现有 suppression 标志。 |
|
||||
|
||||
`I.createInputBoxApi [1298488,1300741)` 的 applyPrefill 有具体保护:`canAutoFill = draftEmpty || !userEditedFlag`;用户 setText/appendText 或 origin:user 的 setBlocks 更新该标志。传 null 时只在可自动填情况下去除 text blocks,保留非文本资源;用户输入返回 `skipped-not-autofilled`。传新 blocks 时用户已编辑返回 `skipped-user-input`。这是输入来源状态机制,不能仅凭字符串等于 default 就认定可覆盖。
|
||||
|
||||
首页 scope 恢复则 `suppressDefaultInitPrompt:true,suppressAutoSummon:true`,不主动重新填默认文本。市场回现有 conversation 虽显式 suppress,**另有一次性的 return-intent 消费流程负责决定该填什么,不能一概不填 default**:`C.ConversationInputImpl [7079170,7081100)` 读取 `expertSummonReturn`,校验 snapshot.sourceSessionId(不匹配则消费 token/清导航 state、停止),按 `conversationId:expertId:snapshotToken` 防重复。用户文本 snapshot 原 blocks 恢复;empty/expert-default/无 snapshot 时有新 default 则保留 snapshot 非文本 blocks 并 applyPrefill 新 default;无 default 但有 snapshot 则恢复 snapshot blocks。最后消费 snapshot token、清 return state。绑定与输入恢复是两个步骤。
|
||||
|
||||
旧 main-content return-state 默认填充还检查当前文本是否已经是同一 default;不能将这一 legacy 检查当成新 ConversationInput be 或上述 return effect 的唯一规则。
|
||||
|
||||
## 同专家重复选择、并发与回滚
|
||||
|
||||
`C.useExpertSummon [3951518,3954856)` 的去重 key 是 `conversationId 或 account scope : id : marketExpertId : updatedAt`:
|
||||
|
||||
- 相同 key 正在召唤:await 进行中的同一个 promise,不重复发起。
|
||||
- `silent:true` 且 lastSuccessfulKey 相同:跳过;silent 会加 suppressDefaultInitPrompt。
|
||||
- **普通用户再次选择同 ID,即使上一轮成功,也不按 ID 永久跳过**;继续 summon。updatedAt、market ID、scope 改变同样影响 key。
|
||||
- `silent && applicationId && !conversationId` 有特殊仅更新当前选择、不做底层召唤的分支。
|
||||
- cloud transport 直接 await onChange 并写 cloud recents;local transport 乐观更新选择,再 summon、归一化数据、写 recents、await owner.onChange,最后提交。
|
||||
|
||||
每次选择/清除递增 generation;结果应用、loading 清理与 local failure 回滚先检查是否仍是最新 generation。clear 先使旧请求过期、清 preparing/last-success key,await owner.onChange(null),仅最新操作清 provider selection。没有看到此 hook 主动 AbortController 中断已在执行的 summon;它主要抑制旧结果应用,不等于取消下载/后台请求。
|
||||
|
||||
local 正常召唤 500ms 后仍未完才出准备 toast;成功后 preparing 状态延迟 400ms 清除,错误清 preparing、恢复调用前 selectedExpert 并 toast。相同 key 的并发请求复用、不同 key 的并发请求以最新 generation 为准;不是把整个产品所有状态做成原子事务。
|
||||
|
||||
边界必须如实保留:AddMenu catch 和 Chip clear catch 直接恢复捕获的旧 draft expert,没有在该组件层检查 generation;provider 有 generation 保护不证明任意 owner 切换/快速连点都绝对安全。召唤中 recents 写入也不属于选择回滚的事务。`useHomeExpertSelection` 的失败 snapshot 只覆盖 appExpert/storeExpert/storeMode,没有完整 blocks 快照。
|
||||
|
||||
首页另有独立 generation 防旧依赖结果覆盖新选择;依赖失败时仅当前操作恢复选择和模式,并显示警告。scope 切换会递增 generation、dismiss gate;team 选择在 cloud 首页会改 local task target 并保留 incoming expert。具体依赖授权由 gate 处理,不以“select 完成”冒充授权完成。
|
||||
|
||||
## provider hydrate、持久化与发送前检查
|
||||
|
||||
新任务专家持久状态 `C [613922,619317)`:按 account scope(user/enterprise/account type)隔离,并且 local/cloud 分槽。内存 cache+串行 storage write;无效存储项删除。加载请求带 load generation 和 mutation generation,晚到的旧读不能覆盖期间新选择。同 ID hydrate 合并元数据但保留 suppressDefaultInitPrompt/suppressAutoSummon,**不增加 selection revision**;普通 selection 改变增加 revision。clear-if-revision 同时核对 accountScope/revision,避免发送结束误清之后的新选择。
|
||||
|
||||
`H.useRuntimeScopedExpertSelection [59422,60323)`:general scope 用上述持久状态;非 general scope 用按 selectionScopeKey 的内存 Map;切 scope 保存/恢复各自选择。`isSameExpert` 比较 id 和 localPath,不能据此宣称元数据、default 文本或活动 backend 都完全相同。
|
||||
|
||||
目录 hydrate `C.useExpertDirectory [869768,874949)` 同时处理 selected、recent、本地自定义与别名;selected official get 和 local custom get 通过 Promise.allSettled,official 成功优先、local fallback(`resolveSelectedExpert [863201,863725)`)。异步目录 cleanup 标志防旧 effect 应用;按 id/marketExpertId 留住当前选中,不因部分列表加载暂时丢失。这个过程补 display/meta,与发起新召唤分开。
|
||||
|
||||
实际 runtime 另由 `P` 维护 `selectedExpertBySession` + `__pending_expert__`:
|
||||
|
||||
- `setSelectedExpertForSessionInternal [612975,614938)` 保留同 ID 激活元数据,补齐可用指令;session 级 selection update 串行。不同注册插件先 disable 旧插件,再更新 craft/expert/runtimeIdentity;相同 craft/id/runtimeIdentity 可省 launchConfig 更新。这是 runtime 更新去重,**不是新菜单普通点击去重**。
|
||||
- `setSelectedExpertForSessionIfEmpty [612787,612975)` 在 hydration 前后都检查 session 是否已有 selection;expectedConfig 防覆盖。clear-if-current `[615109,615331)` 使用 expected expertId。
|
||||
- `hydrateSelectedExpertForRuntime [431496,433326)`:my-experts 优先本地 get;否则按 source/enterprise/locale 拉 getExpert,补显示与 runtime identity。既无 legacy prompt、无 activation meta、也不是有效 custom root 时才 activatePlugin,最终仍无可用 instructions 抛错。
|
||||
- `ensureUsableExpertForSelection [430965,431496)` 的 hydration 错误在已有 name/profession 时有降级为该文本 prompt 的分支。因此仅 chip 显示成功不能证明原专家完整指令加载成功。
|
||||
- 加载已有会话 `[388000,389700)` 按持久化 expertId 恢复,2 次重试+初次,间隔500ms;isCurrentLoad 防旧 load 落地。失败记录 warning 并设 ID 文本 fallback,不能称原角色能力已完整恢复。
|
||||
- 发送方法在 `[400400,...] / [406143,...]` 先 await selection update,再 ensure launch config。`ensureSessionLaunchConfigBeforePrompt [434623,...]` hydrate 默认 3 次重试+初次,间隔500ms;失败时若已有 usable binding 保留,否则清无效 expertId/runtimeIdentity。该降级行为不同于直接在 UI 假显示绑定成功。
|
||||
|
||||
清除现有会话 `P.clearSelectedExpertForSessionInternal [615331,615919)` 删除选择、通知监听、disable session 插件、清 launch expert/locale/runtimeIdentity,随后 best-effort deactivate。模式仍写 craft;清 expert 不等于退回其他模式,也不清会话历史。
|
||||
|
||||
## team、确认与取消
|
||||
|
||||
市场 `useExpertSummonFlow` 的 team/金融风险确认取消仅关闭 dialog、清 pending,不调用底层召唤。team 确认可按用户 scope 持久 suppress;金融确认是当天 suppress 或旧 forever 标志。原版确认逻辑包括 automation 的独立分支,不能默认所有入口均创建聊天。
|
||||
|
||||
`C.useTeamExpertSwitchGuard [6065611,6066278)` 检查该会话已使用 team 或有 team 历史;换到不同的非空 expertId 才阻止。clear(null) 不匹配这个换专家条件。召唤更多在已用 team 时同样要求确认。
|
||||
|
||||
确认后的 `confirmTeamExpertSwitchAction [6064556,6064853)` 清 preparedContext;有新 expert 则准备新首页专家 context/default,然后 goHome;召唤更多再导航 experts。它不在原 team 会话里直接替换专家。确认弹窗 `closeOnEscape:false`;取消不执行该动作。此处阻止“同一已使用团队会话任意换另一个专家”的行为,是与普通 agent 会话的重要差别。
|
||||
|
||||
## 对 YCode 对齐的具体约束与未验证项
|
||||
|
||||
1. 市场默认准备新草稿、picker 的召唤更多显式带返回 owner、返回只绑定该 ID,与源码匹配;不做按 expertId 搜索历史复用。直接侧栏打开市场是否带 return target 取决于入口导航 state,不能一概处理。
|
||||
2. 如产品 store 将“同 ID”全部短路,尚缺原版普通重召唤和 updatedAt/runtimeIdentity 变化的恢复路径;至少区分 user/silent/inflight,以及内容版本和已激活状态。
|
||||
3. 提示词使用 owner/applyPrefill 状态处理;首页 clear 与会话 clear 源码不同。用户输入、附件、已自动填默认、无 default 的情况都要分别验收。
|
||||
4. 选择、依赖准备、backend runtime 激活、消息发送是不同状态。保留 source/runtimeIdentity 和逐会话绑定,旧请求晚到不能串 owner;不宣称原版所有组件回滚都已完全竞态安全。
|
||||
5. 本报告只静态核对已保存原版代码。未新增原版运行时证明:current UI 路由每个 legacy/new 分支、极速切换/账号切换、失败时默认文本最终画面、Office/云同步、team 确认后的全部 state 均仍需独立 REA 场景验收。未验证模型实际遵循专家角色。
|
||||
|
||||
建议以以下状态矩阵做自身产品回归,再用正式 REA 取得原版同场景行为;目前此矩阵仅验收建议,未声称全部运行:
|
||||
|
||||
| 操作 | 需核对的状态 |
|
||||
|---|---|
|
||||
| 侧栏直接进市场后召唤 | 首页草稿;0 次发送;不任意导航历史同专家会话 |
|
||||
| 会话 picker 召唤更多再返回 | 指定原 conversationId;user blocks 保留;expert-default 换新 default;附件保留 |
|
||||
| user 点击当前专家 / silent hydrate | user 可重召唤;silent 相同成功 key 去重;updatedAt 改变需要准备新内容 |
|
||||
| 清 chip | 首页/会话两种 owner;空文本/自动default/用户编辑/附件组合;clear 后晚到召唤不复选 |
|
||||
| A慢→B快 / A慢→clear / A失败→B | 最新选择成立;不恢复过时owner;loading/toast/依赖gate和错误事实一致 |
|
||||
| 首页 local/cloud 或账户切换 | selection 槽隔离;旧load不覆盖新选择;发送后revision保护 |
|
||||
| 重启恢复会话 | source/runtimeIdentity/Agent/Skill绑定可恢复;不可只显示chip而失去原指令 |
|
||||
| 已用 team 换专家/召唤更多 | 确认后新首页;取消不变;同专家和clear边界单独测 |
|
||||
|
||||
修改文件仅本报告。验证为:339+329 模块 SHA 全部匹配、相关具名函数 Babel AST 范围核对、调用点/参数/分支逐项阅读;未运行生产测试或修改原版/YCode 状态。
|
||||
@@ -0,0 +1,51 @@
|
||||
# 专家使用逻辑对齐
|
||||
|
||||
2026-10-16,用户要求“对齐一下使用专家的逻辑”。本轮按 WorkBuddy 5.8.2 的 REA 证据修正使用交互与技能预加载,未将其宣称为完整 Agent 运行时 1:1。
|
||||
|
||||
## 原版证据
|
||||
|
||||
ASAR SHA256:`035254bc76310ea46317433e4840602094543ef323d2d5c5aff7c131729de918`。源代码仅分析已经通过 REA 保存并复核 SHA 的导出;新增原版观察仅为被动画面,没有输入、召唤、发送或修改原版任务。
|
||||
|
||||
- 原版使用状态机:[REA 核对](专家使用逻辑-REA核对-20261016.md),列出 `ev_717fa5e846e64d67ac19c8925d121bff632c0d3aefb3603b10858559cabb2dcb` 等 Evidence、模块 SHA、函数范围和新旧 UI 分支差异。
|
||||
- 当前原版首页/算法专家标签:`ev_7e9604adb87a3d21570eb7a371001e48b3d316ee0388a03a97e2cb564d03aff7`,1336×901;留有未发送默认提问。归档 `.tmp/rea-css-evidence/ev_7e9604adb87a3d21570eb7a371001e48b3d316ee0388a03a97e2cb564d03aff7.json`。
|
||||
- 标签:原 `src-DbE1_mgM.js` ExpertChip/ExpertAvatar,源 SHA 与范围见 `src/renderer/src/capabilities/SourceActiveExpertManifest.json` 和 [恢复说明](expert-active-source-20261016.md)。组件局部几何和16项计算属性与上述原版观察一致;不代表整页面逐像素验收。
|
||||
- 技能规范、四份原包、主进程插件切换:[运行语义核对](专家运行语义核对-20261016.md),包含原版版本、Evidence、文件 SHA 和未证明项。
|
||||
|
||||
## 已实施行为
|
||||
|
||||
| 操作/状态 | 当前 YCode 行为 |
|
||||
| --- | --- |
|
||||
| 首页选择/召唤专家 | 激活成功后绑定当前未发送草稿,不创建空会话,不自动发送 |
|
||||
| 从已有会话直接进入侧栏专家中心并召唤 | 准备独立新任务,继承模型和空间;原会话绑定保持 |
|
||||
| 会话输入框“召唤更多专家”后返回 | 明确携带原 owner,绑定原会话;不按专家 ID 搜索任意历史会话 |
|
||||
| 用户已经输入问题/修改默认文本 | 保护当前用户文本、附件、引用和技能;激活完成时再次依据当前输入判断 |
|
||||
| 空输入或仍未编辑的专家默认提问 | 按新专家默认提问预填;非文本独立输入不被普通预填覆盖 |
|
||||
| 会话换到没有默认提问的专家 | 清除旧的未编辑自动预填,保留用户文本 |
|
||||
| 首页移除专家 | 保留当前输入;移除能力绑定 |
|
||||
| 会话移除专家 | 只清未编辑自动预填;用户输入和历史消息身份保持 |
|
||||
| 重复选择当前专家 | 普通选择重新激活;同一专家正在进行的激活共享请求 |
|
||||
| 快速切换、离开当前任务 | 版本与 owner 校验阻止旧激活结果覆盖新选择/新草稿;会话写入排队 |
|
||||
| 依赖/激活/磁盘写入失败 | 保留原绑定和草稿;源标签移除失败回滚;展示实际错误 |
|
||||
| 激活元数据 | 默认提问和绑定由同一份已验证文档返回,取消并行 activate/read 的版本混用 |
|
||||
| 输入工具栏标签 | 使用恢复的原头像/职业名/截断提示/hover移除;标签是 status 控件,没有虚构点击菜单 |
|
||||
| 技能加载 | plugin.skills 注册目录;Agent YAML skills 按真实 SKILL.name 唯一匹配预加载。PM/UI按需读取,C++/算法各预加载一个声明技能 |
|
||||
|
||||
新选择器暂沿用恢复的 legacy 菜单视图,并以 manifest 明示的 `reselectSelected` 宿主适配接入当前 cr 的同 ID 重激活行为;未声称整套新 cr AddMenu 已原体替换。
|
||||
|
||||
## 验证
|
||||
|
||||
- `npm run build`:通过;日志 `.tmp/expert-usage-build-20261016.log`。
|
||||
- `npm run test:expert-usage`:**50/50**,真实 production Zustand 状态与草稿策略、受控 IPC;包含失败、迟到选择、owner切换、运行中禁止原会话切换等,不请求模型。
|
||||
- `node scripts/verify-expert-flows.cjs`:**61/61**(50+11),报告 `.tmp/expert-flows-c7J65f/report.json`。实际生产 renderer/preload/IPC → 实际 OMP → localhost 受控上游;创建/召唤/角色上下文/编辑/会话返回/移除/预填/新进程恢复。模型注册清空隔离迁移项,所有发送前要求模型地址为127.0.0.1。新增交互验证没有增加用户消息。
|
||||
- 选择器原生 **42/42**,`.tmp/expert-picker-native-cxKfqC/report.json`;标签原生 **38/38**,`.tmp/active-expert-native-yS4h06/report.json`。两份恢复脚本 `--check` 通过。
|
||||
- 技能预加载 **15/15**、四包 **370/370**(197文本原 SHA保持)、真实后端 **73/73**、快照 **15/15**,报告路径见运行语义核对文档。
|
||||
- `npm run test:chat` 与 `npm run test:conversation`:通过。
|
||||
- `node scripts/verify-live-imported-experts.mjs`:真实用户 YCode 四位专家原生鼠标召唤通过,197文本/四头像 SHA 保持,0次发送、0渲染异常;报告 `.tmp/live-imported-experts-XhbL3D/report.json`。根上下文查看算法专家召唤画面,标签已位于工具栏并显示原头像/职业名。
|
||||
|
||||
## 用户应用与限制
|
||||
|
||||
最终构建已正常更新用户 YCode;更新前确认无运行回合,保留并恢复原选中会话 `b54d80bd-ff69-4ec8-9bb1-e21b31b2b9a9`。没有修改用户模型配置、原专家包内容或历史消息。
|
||||
|
||||
最终进程 PID 59560,renderer `index-Cm10d3yD.js`,main SHA256 `d54ff8aa3c837690df61144a6d8770661ddfda3761ead689f45ded449b53ab17`。实机验证后恢复原会话并打开“我的专家”;输入为空,无运行回合。
|
||||
|
||||
仍未对齐:独立系统层专家角色、Agent maxTurns、原 CLI 插件/Agent 切换生命周期、团队调度、所有失败/动效状态与整个页面像素验收。当前专家角色仍通过 capability 文本进入模型 user 上下文;原版实际采用插件/Agent override。原 CLI 最终模型消息层级与计数器还需 REA 证据,不能将本轮交互验收替代它们。第三方工具的运行时/API/CLI依赖保持真实状态。
|
||||
@@ -0,0 +1,91 @@
|
||||
# 专家、技能、连接器:复刻拆解(2026-10-16)
|
||||
|
||||
本轮完成原版实拍与源码评估,未修改 YCode 生产代码。观察对象为 WorkBuddy 5.8.2,全部通过 REA;没有安装、启用、授权或保存任何原版能力,也没有向原版发消息。取证结束已恢复原版首页。
|
||||
|
||||
结论:该入口包含统一管理页面、三套能力生命周期,以及与输入框、会话和运行时的联动。YCode 当前侧栏入口仍为占位,历史消息中的工具卡或词典不能算这些能力已经实现。
|
||||
|
||||
## 功能边界
|
||||
|
||||
| 部分 | 原版已确认内容 | 实际运行所需 |
|
||||
| --- | --- | --- |
|
||||
| 统一入口 | 侧栏三项菜单、顶部专家/技能/连接器 tabs;各自搜索、主题、滚动、窄布局与返回导航 | 页面状态管理;切换页面保留会话、草稿与右栏状态 |
|
||||
| 专家 | 市场推广、分类、专家/专家团、综合/最热/最新、详情/案例、我的专家及创建/购买分类 | 专家目录与包;本地/云状态;激活、依赖检查、会话身份与助理显示快照 |
|
||||
| 技能 | 精选、推荐/SkillHub/套件、分类搜索、详情、已安装及批量管理;查找/上传/创建菜单 | 技能扫描/安装/升级/删除/启停、内容与资源读取、运行时刷新;用户调用与模型自动调用的开关语义 |
|
||||
| 连接器 | 商店、详情、示例、连接状态、Token/OAuth/device-code 配置;自定义 MCP 管理 | 目录与连接状态服务、凭据/授权、服务器生命周期、工具发现/开关/调用/重连/取消 |
|
||||
| 会话联动 | 输入框选择专家、技能、连接器;recent/pin、引用块、依赖提示、错误/安装进度与调用结果 | 会话级配置、持久化、回合配置快照、OMP/备用内核的上下文与工具适配 |
|
||||
|
||||
三部分各自有不同契约:专家可以激活插件并带入技能与连接器依赖;技能提供可加载的指令、资源与流程;连接器向运行时提供外部能力。不能统一缩成同一种列表和一个 installed 布尔值。
|
||||
|
||||
## 专家拆分
|
||||
|
||||
1. 市场与详情:推广场景、分类、搜索排序、专家/专家团、头像标签、案例与召唤入口。
|
||||
2. 我的专家:创建/购买来源、本地与云状态、编辑、导入导出、删除、同步、覆盖确认与空态。
|
||||
3. 对话式创建/编辑:原版通过 `expert-manager` 技能与提示词返回首页,监听会话产出的专家包再刷新列表。需要恢复该技能正文、包格式与发现机制,不能先换成普通 prompt 编辑表再宣称等价。
|
||||
4. 激活与会话绑定:调用 summon/插件激活,检查依赖,保存运行时身份与助理显示快照;切换失败回滚,处理草稿/会话并发。
|
||||
5. 专家团:成员展示可以单独恢复;实际团队调度、各成员执行及云服务仍需额外证据和单独验收。
|
||||
|
||||
关键事实:选择专家不只是修改输入框标签;创建入口也不只是新增一条 JSON 记录。精确函数、字段、IPC 与未知见 [专家评估](assessment-experts-2026-10-16.md)。
|
||||
|
||||
## 技能拆分
|
||||
|
||||
1. 市场与详情:推荐、SkillHub、套件、分类、搜索、文档/文件树、资源预览、安装/使用入口。
|
||||
2. 本地注册表:来源、路径、版本、可用性、启用状态、套件成员、安装来源;读取技能正文与随包资源。
|
||||
3. 安装生命周期:文件夹/ZIP/URL导入、同名覆盖与更新、修改检测、卸载及文件变化刷新。
|
||||
4. 扫描与权益:扫描中、失败、风险确认、阻断、超时;付费、已购、授权、云端仅存在等状态。这些状态已有源逻辑,真实扫描/权益结果不能由本地假成功替代。
|
||||
5. 调用:输入框添加、slash/引用块、最近与置顶;区分用户可调用、模型可自动调用、是否已在当前运行时就绪。安装完成后还需等待运行时命令刷新。
|
||||
|
||||
当前原版账号实拍为五个已安装条目,包含套件徽标;这只是账号当前状态,不作为写死的产品规格。具体源码与九个有界任务见 [技能评估](assessment-skills-2026-10-16.md)。
|
||||
|
||||
## 连接器拆分
|
||||
|
||||
1. 商店与详情:搜索、列表加载与分页、已有/可添加状态、企业目录条件、详情、使用示例、工具信息。
|
||||
2. 连接状态机:未连接、连接中、已连接、待授权、未授权、错误及修复;连接、取消、重授权、断开与删除有不同语义。
|
||||
3. 授权:Token多字段配置、OAuth外部跳转与回调、device-code 倒计时和轮询;具体应用各自有服务要求。
|
||||
4. 自定义 MCP:服务器添加配置、健康状态、搜索、工具计数、整服务与逐工具启停、编辑、删除、信任审批和工具过多提示。
|
||||
5. MCP host 与会话注入:配置读取不等于工具可调用。需要实际连接/发现/调用,处理工具名称映射、取消、断线重连、进程释放与会话配置隔离。
|
||||
|
||||
实拍确认卡片主体打开详情,加号是独立连接动作;QQ 邮箱详情收到 Escape 后仍打开,应按它自己的关闭规则恢复。官方账号解绑、自定义 MCP 删除、临时断开不能合并成一个删除动作。详细状态矩阵和A–G任务见 [连接器评估](assessment-connectors-2026-10-16.md)。
|
||||
|
||||
## YCode 当前基线
|
||||
|
||||
| 可复用的现有能力 | 当前缺少的部分 |
|
||||
| --- | --- |
|
||||
| 真实模型管理与两种 API 协议、OMP/备用网关、preload/IPC、会话持久化、回合配置快照、工作空间、工具执行/审批与结果渲染 | 专家/技能/连接器页面路由与数据服务、三个注册表、包安装器、专家包激活、MCP client/host与授权管理、输入引用/选择与会话能力配置 |
|
||||
| 原版已采 JS/CSS/SVG 与 REA 画面;当前 theme/layout/host adapter 的恢复经验 | 原版完整 daemon 行为、专家包 schema、`expert-manager` 正文、真实扫描/授权/云目录与同步服务、完整响应式与全状态像素验收 |
|
||||
|
||||
源码依据:`src/renderer/src/mock.ts` 的 experts 项仍 `implemented:false`;Sidebar 非新任务入口只显示未实现提示;Composer 的添加菜单当前提供文件和路径引用,未接专家/技能/连接器。YCode现有工具展示不能证明能力管理已实现。
|
||||
|
||||
## 推荐实施顺序与验收
|
||||
|
||||
以下是 YCode 的实现建议,不冒充原版内部架构。最终目标仍是完整复刻;云服务与团队调度按用户此前安排分后续阶段。
|
||||
|
||||
| 阶段 | 有界工作包 | 完成标准 |
|
||||
| --- | --- | --- |
|
||||
| 0 | 补专家包/技能目录/daemon 契约证据,确定三个能力注册表与会话接口 | 未知字段显式列出;包格式、状态与scope有证据,现有模型/空间/对话不被覆盖 |
|
||||
| 1 | 原版统一页面、三类列表/搜索/详情、我的/已安装视图和弹层 | 恢复源DOM/CSS/SVG/状态逻辑;真实路由可切换;数据占位和功能实现分开记录 |
|
||||
| 2 | 本地技能管理与运行时加载 | 临时工作空间真实导入/启停/升级/卸载;下一回合确实加载/卸载技能,文件变化与scope隔离正确 |
|
||||
| 3 | 自定义 MCP host 与管理页 | 实际受控 MCP 服务可连接、列工具、执行、取消、重连和释放;禁用工具不再发给模型,凭据不进正文 |
|
||||
| 4 | 专家本地创建/编辑/导入、依赖与会话激活 | 对话产生真实专家包、被发现并显示;选用后改变实际执行;身份/依赖/切会话/重启恢复正确 |
|
||||
| 5 | 三类输入框选择、slash/引用、recent/pin、状态与工具反馈 | 明确引用发送到正确会话与空间;失败回滚、重复点击、安装中调用和运行中切换均实测 |
|
||||
| 6 | 应用连接器、云目录/同步/扫描/权益、企业功能和专家团 | 使用自有/获授权服务完成真实端到端验收;源码接口或相似界面不能替代服务结果 |
|
||||
| 7 | 全状态1:1验收 | 固定版本/视口/主题/渲染环境;正常、loading、空态、搜索无结果、失败、安装/授权/连接中、禁用、更新、窄窗、键盘与动效逐项对照 |
|
||||
|
||||
页面恢复可以与本地能力服务并行;专家功能链路依赖技能和连接器的能力,建议先落实后两者的运行时接口再集成专家。不要将所有数据和状态放进聊天 store;建议三类服务各自管理生命周期,由会话层保存稳定引用与回合快照。
|
||||
|
||||
## 原版证据与本轮限制
|
||||
|
||||
WorkBuddy 5.8.2,ASAR SHA `035254bc76310ea46317433e4840602094543ef323d2d5c5aff7c131729de918`。静态源码以 REA `ev_717fa5e846e64d67ac19c8925d121bff632c0d3aefb3603b10858559cabb2dcb` 与本轮 `ev_e91787b1d4dea651582c6cf12827775b9068b0ee8b80c68ba08d4c1d87d94e90` 为主,相关脚本SHA已核对;各模块报告保留具体SHA、UTF-16 offset与证据范围。
|
||||
|
||||
| 实拍范围 | REA Evidence |
|
||||
| --- | --- |
|
||||
| 专家市场稳定页面 | `ev_20de2f04c99b1c27bc39b61f5e2f5a430c3c7029b09afb76b363652eb4fadc89` |
|
||||
| 我的专家空态稳定页面 | `ev_6f00d8b339cb4baf0af2a68f797e93dd6b5ce3ab18da2b43aa63ec09952c1d93` |
|
||||
| 技能市场动作帧(partial) | `ev_c827c8dc7dee0c67c7870f6bf8417b87ec7b4d90d507ecc5dc592b5878579f10` |
|
||||
| 已安装技能稳定页面 | `ev_9d8628a28fed60291e628cebaec55537bfb8274d4b6c8f746bffadcbc277d3fb` |
|
||||
| 添加技能菜单动作帧(partial) | `ev_ddef9315aaf0ff534cf02573212e205ba70e5b69dfc1b3dcf555b430920faf22` |
|
||||
| 连接器市场稳定页面 | `ev_e91bdc6e46275f4460985cfff25fd7f7bc334afc45f49fac1935de1249f4cb22` |
|
||||
| QQ邮箱详情与Escape动作帧(partial) | `ev_b898a87832d1e800810d391145a6ec6c6999e98b5cea6c7f382a3fc19aa7b3ac` |
|
||||
| 自定义MCP稳定页面 | `ev_b89281177f6a1cf2e4697887d576b8ddf7d811a8fa2d1148b7024a4ec898906f` |
|
||||
| 取证结束恢复首页稳定页面 | `ev_57f37739095ddd23938918a3cb0e299186b1febc05a002be1468ee7cfa0cb9a8` |
|
||||
|
||||
部分 action 的原生点击/等待及PNG已成功,但末尾 neutral-pointer cleanup 被取消,REA probe整体标failed;保留该失败,不说整条场景通过。对应帧只证明图中的操作后画面,顶层layout仍是操作前;另采静态页才作为稳定布局证据。验证命令 `node scripts/audit-capability-runtime.mjs`,输出 `.tmp/capability-assessment-20261016/runtime-index.json`。本轮未实现功能、未做YCode像素比较,也没有真实安装/扫描/授权/专家执行验收。
|
||||
@@ -0,0 +1,54 @@
|
||||
# 专家本地创建、编辑与会话激活
|
||||
|
||||
2026-10-16。本轮继续实现专家模块。技能/MCP 的上一轮基线见《能力中心与本地能力接入-2026-10-16.md》。此处的功能通过不等于全状态 UI 1:1 通过。
|
||||
|
||||
## 原版证据与恢复
|
||||
|
||||
原版为 WorkBuddy 5.8.2;安装包 SHA-256 `035254bc76310ea46317433e4840602094543ef323d2d5c5aff7c131729de918`。所有原版查看均经过 REA。
|
||||
|
||||
- `main/module.app-server.js`:`ev_81de6f628a156599f26ca795f6747ad3f8ec108de66fdba6e3723705905716f3`,SHA `281666dbf81b76d64f95162a19dd2d02a41b35ec54239e0efc4e8e52419eb125`。确认本地包、marketplace 索引、会话标记及激活身份。
|
||||
- `expert-manager/SKILL.md`:`ev_3cba49fcb15fefc59f54c7691500ad1121a937edb55e606addae17e4186ebfef`。另恢复四份 references、五份 Python 管理脚本及插件 metadata,共 11 份原文。逐文件 SHA 和 Evidence 见 `src/main/capabilities/assets/expert-manager/rea-source-manifest.json`。
|
||||
- 隔离 REA 文本 provider 正式增加 Markdown/Python 等文本后缀;自有 ASAR fixture、原回归和完整性检查通过。没有改全局 REA,也没有执行原包 Python。
|
||||
- 恢复 CreatedExpertCard、CreatedExpertsPanel、菜单、删除框等 25 个源码体及 273 条 CSS;恢复专家选择器 10 个源码体/中文文案及样式。原几何和宿主适配范围分别见《created-expert-source-20261016.md》《expert-picker-source-20261016.md》。
|
||||
|
||||
## 已实现
|
||||
|
||||
“创建专家”采用原默认提示词并引用 `skill://expert-manager`;“修改专家”采用带专家 ID 的原编辑提示词。两者进入新的管理任务,保留空间/模型,解除当前专家角色绑定。
|
||||
|
||||
管理器使用恢复的完整正文与资源,经过明确的 YCode 宿主适配调用 `ycode_expert_package`:read → write → validate → register。包结构继续采用 `.codebuddy-plugin/plugin.json`、Agent MD、skills 和同级资源。主进程接管固定目录、marketplace 索引与会话标记;不会写入 WorkBuddy 数据。
|
||||
|
||||
专家包存储在 YCode userData 下的 `plugins/marketplaces/my-experts/plugins/<id>`。草稿按会话隔离;注册前校验必填展示字段、三标签/提示词、Agent YAML 与真实资源。原版建议项保留为警告。编辑保留未修改文件及二进制资源;固定 name/agentName,冲突必须 refresh 重读。目录/资源拒绝越界及符号链接;注册采用临时目录和备份,删除先改名再提交索引。
|
||||
|
||||
“我的专家”接真实注册目录及源码卡片,支持搜索、预览、召唤、编辑、打开目录和删除。删除失败保留原弹窗。输入框+菜单接源码专家选择器,支持搜索、置顶/最近、选择当前专家、异步失败保持与任务作用域隔离。
|
||||
|
||||
会话保存 expertId。回合开始读取一个一致的包快照,注入真实 Agent 正文及技能资源,并为助手消息保存专家展示身份;后续切换不会重命名旧回复。移除专家后明确恢复默认助手角色。MCP 依赖检查已连接/受信任及相应命令、参数、传输和目录;快照先取连接代次,配置替换会使旧执行失效。
|
||||
|
||||
首次发送创建会话后,将输入、附件、资源和技能迁移到新会话 owner;主进程 preflight 拒绝时保留,成功时才清空。专家资源读取使用包内自有文本键,不允许命中对象原型。
|
||||
|
||||
## 验证
|
||||
|
||||
- `npm run build`:包含 node/web TypeScript,通过。日志 `.tmp/expert-build-20261016.log`。
|
||||
- `node scripts/test-experts-backend.mjs`:73 项(59 操作、14 实际新 Electron 进程恢复/删除)通过。最终重验 `.tmp/experts-backend-LSzrsZ/report.json`。
|
||||
- `node scripts/rea/recover-created-experts.mjs --check --native-qa`:34 项,0 HTTP/renderer error,`.tmp/created-expert-source-H0svkz/report.json`。
|
||||
- 专家选择器原生验证:39 项,`.tmp/expert-picker-native-iFW4nG/report.json`。
|
||||
- `node scripts/test-capability-gateway.mjs`:17 项通过,`.tmp/capability-gateway-GsHx96/report.json`。
|
||||
- OMP 生命周期、Chat、Persistence、Conversation 回归通过。持久化 fixture 将取消触发条件改为首行文本,以覆盖附带能力上下文的真实 prompt;未删除 partial/disk/cancel 断言。
|
||||
- 整应用 UI → preload/IPC → 实际 OMP → localhost 受控上游验证:创建/资源读取/写包/校验/注册、原生 hover 召唤、专家指令和身份、编辑、实际新进程恢复已通过 39 项。`.tmp/expert-flows-pR6WCR/README.md` 是首轮完整结果;最终新增无模型 preflight 草稿保留验收另记于下方。
|
||||
|
||||
最终构建整应用验收:`node scripts/verify-expert-flows.cjs`,**51/51 通过**(40 主阶段、11 新进程恢复),`.tmp/expert-flows-2nE9Bc/report.json` / `README.md`。主进程构建 SHA `16b15106c73c25ba04ae6e679b655c77bb8e7cefd33c7735dc1d9d53effe8b51`,两阶段一致。真实 UI 先在无模型状态发送,确认新会话 owner 下原文/技能保留、0 消息;随后配置本地受控模型,在同会话不重填草稿重试成功。整个成功流程 13+1 次 localhost 请求。早期错误 QA 前置未清除默认模型,收到远程 401;失败事实留在 `qa-history.json`,未算作通过或远程效果证据;最终脚本清空默认 profile 且发送前检查只允许 127.0.0.1。
|
||||
|
||||
独立快照/事务故障注入 **15/15 通过**:`.tmp/expert-review-snapshot-HDKwX1/report.json`。覆盖同回合单文档、MCP 参数 gate、提交/清理失败、回滚、坏索引与原型资源键。该测试的 MCP 状态为受控 fixture;真实 SDK 代次失效的覆盖来自已有能力网关测试。
|
||||
|
||||
最终构建已重启更新用户 YCode(PID 59256),更新前确认无运行回合、无附件/能力引用草稿、设置窗口关闭;文本草稿与会话 owner 经过备份/恢复/再检查。没有将隔离 QA 专家写进用户目录,也未改变用户模型配置。
|
||||
|
||||
独立审查发现并修复了旧编辑覆盖、同回合身份/正文竞态、英文搜索、MCP 参数匹配、删除事务、原型资源键及首次发送草稿丢失。未将测试工具的成功返回替代真实磁盘或模型输入验证。
|
||||
|
||||
## 尚未完成的等价性
|
||||
|
||||
本轮 OMP 使用宿主能力上下文和工具适配专家包,尚未证明等同于原版原生 agent/plugin 注册、切换及工具发现。Python 生命周期由主进程受控工具适配,不能称为原样运行原版 daemon。
|
||||
|
||||
专家团可显示/编辑/校验包;调度未接入,激活明确拒绝。ImageGen 未接入,不能宣称已生成头像。当前工具写入文本包,新增二进制头像自动复制/生成尚未打通。云端专家市场、购买、OAuth/云连接器仍未接入。
|
||||
|
||||
预览详情、Popover/Tooltip、完整+菜单入口和已选专家首页布局仍有宿主适配;创建完成后的原版右侧专家产物自动预览及外部文件实时 watcher 尚未完成。组件源码恢复和局部几何通过,不代表同状态截图、所有主题/极窄窗口/动效/字体字形已通过像素验收。
|
||||
|
||||
受控上游证明产品链路,不证明任意模型均能按规范产出专家包。原版云端账号与数据未修改。
|
||||
@@ -0,0 +1,129 @@
|
||||
# 专家运行语义核对
|
||||
|
||||
日期:2026-10-16。范围:四份 REA 恢复专家包、已保存的原版规范/daemon/renderer 导出,以及 YCode 专家、能力工具与 OMP 接线。原版观察全部来自 REA;没有重新操作原版运行时,没有直接读取原版目录。本轮未发模型请求、未运行专家业务脚本。
|
||||
|
||||
**结论:已修正“plugin.skills 被当成启动预加载”的语义差异。角色消息层级、maxTurns 和原 CLI 插件/Agent 切换仍未对齐,不能把当前可选专家、资源可读宣称为原运行时等价。**
|
||||
|
||||
## 证据身份
|
||||
|
||||
原宿主 WorkBuddy 5.8.2,ASAR root SHA `035254bc76310ea46317433e4840602094543ef323d2d5c5aff7c131729de918`。所有读取的归档正文先校验其 SHA。
|
||||
|
||||
| 证据 | 文件 / SHA256 | 本次使用范围 |
|
||||
| --- | --- | --- |
|
||||
| `ev_a4b0f399496f62f4dc41998e8327fb219ab84f3dca536ec6554553605b106735` | expert-manager `references/agent-md-spec.md`,`ec7373578a5f84d73ba16dcc71e73755e57aa4170cb07cd9bf379627c0f9c007` | Agent YAML skills 启动预加载、maxTurns 规范 |
|
||||
| 同上 | `references/plugin-json-spec.md`,`14e1a6b99c74815c22772a54725ba6d34750a6c9db4c75746c1188e31d2504f3` | plugin.skills 为 Skill 目录路径资源声明、agentName 为主 Agent 名称 |
|
||||
| `ev_81de6f628a156599f26ca795f6747ad3f8ec108de66fdba6e3723705905716f3` | `main/module.app-server.js`,`281666dbf81b76d64f95162a19dd2d02a41b35ec54239e0efc4e8e52419eb125` | 原会话插件切换与 Agent override |
|
||||
| `ev_c3df29dcb19c5fcaa9e458b1b9acff92e8c75ac935791e0c81900733e61b6282` | `main/daemon-app-server-main.js`,`a3b9d6f3ca17954a89d4e442137348b230c8ea9c74181625556bfae2ffe98154` | 专家包解析、准备、插件启用和会话绑定 |
|
||||
| `ev_717fa5e846e64d67ac19c8925d121bff632c0d3aefb3603b10858559cabb2dcb` | runtime 导出 `workbuddy-provider-DkH2YFYM.js`,`b588e875c469978f216beec86bdf4b6c33a31c0266f9bf996881b8dbf37b5dc7` | renderer hydration 的真实选择元数据与发送前配置准备 |
|
||||
|
||||
四包的证据保存在各自 `evidence-manifest.json`,原始正文由逐文件 retainedExport 定位:
|
||||
|
||||
| 专家 | 包 root SHA256 | Agent MD SHA256 / Evidence |
|
||||
| --- | --- | --- |
|
||||
| C++ 超级专家 | `b90023e9622bd74c55d583051bee3625eb491b552baeea17ae10ac792a352498` | `93306e405cb7e0c4fc94514179031a8fc3d7f25f06a095a728a2dfa4a34da154` / `ev_f06dd5bf43984bec8520feadaf2d9b24f7fb6e96acd34de5f91469aa6e561c1f` |
|
||||
| 高级项目经理|关德豪 | `304805c85b87e8266294fb3aaf283d45fc71d7977af064fcb1eed1199e9389e6` | `d9187e37363679e5bb56879d35cdbdb73b319c0344ca157619d1f602db3c5bec` / `ev_7faf6a7a38f49bf647382424d3e814639dfddd232458326090df4c2729b438fe` |
|
||||
| UI设计师|像素君 | `c9c83df190f0f0f871706d52b7e372f20b7ad63fde739f59cf9181ace1d08afa` | `d6e54ca64ab54c6d3122ff0114a46d3820cedd1f05a5a14c541afa6a55e654aa` / `ev_a7ec53f363a1aa9621ef324f4e20a74f0fcc58bb6bac88e129a5b908bd3b6053` |
|
||||
| 高级算法工程师|小算 | `44ed0738d809fe492a36c697b0edd53b72ed75549f5b773291d05f9cf4a6c66f` | `e383e97fda6cff3ebb15c420d0218bbdafa84d0b74d0acf45040866b1361a42c` / `ev_b55ad8135706d337f9c3f844d5324e154a56aad7f81fcf090d214754f0374d18` |
|
||||
|
||||
## skills:资源注册与启动预加载
|
||||
|
||||
原 `agent-md-spec.md` UTF-16 offset 368 起明确给出 `skills: [{skill-name}]`,说明是“启动时预加载的 Skill”。`plugin-json-spec.md` offset 757 附近把 `skills` 放在资源声明表,类型为 Skill **目录路径**数组。这是两个不同字段,不能按同一数组处理。
|
||||
|
||||
| 专家 | plugin.skills 注册目录 | Agent YAML skills | Agent maxTurns |
|
||||
| --- | --- | --- | --- |
|
||||
| C++ | cpp-mastery | cpp-mastery | 50 |
|
||||
| PM | minimax-docx | 未声明 | 未声明 |
|
||||
| UI | impeccable、frontend-dev、browser-use | 未声明 | 未声明 |
|
||||
| 算法 | algorithm-engineering-playbook | algorithm-engineering-playbook | 100 |
|
||||
|
||||
修复前 `expertTurnContext` 无条件把 plugin.skills 下的所有 SKILL.md 完整正文附在专家 prompt 后。PM/UI 因而在普通回合中提前加载所有 Word/设计/浏览器指令,与上述规范字段含义不符。
|
||||
|
||||
现在的 Agent 分支:
|
||||
|
||||
1. plugin.skills 只注册包内目录,解析每份 SKILL.md 的真实 frontmatter name 和 description,输出按需加载目录。
|
||||
2. 只有选定 Agent YAML skills 中的名称,且能唯一匹配已注册 SKILL.name,才预加载完整正文。名称与目录 basename 可以不同;不按文件夹名猜测。
|
||||
3. 无 skills / 空 skills 均不自动加载所有正文。重复选择去重;非法、未注册、歧义名称明确报错。
|
||||
4. 全部文本资源仍可通过 `ycode_expert_resource` 按路径读取,原文 SHA 保持。目录提示模型在实际需要技能时先读取完整 SKILL.md。
|
||||
|
||||
本地名称检查是显式宿主校验:1–128 位字母/数字起始,后续允许字母、数字、点、下划线、连字符;这不是对所有原版技能命名方式的完整证明。非 agent manifest 的运行语义未在此次扩展,未据此给 skill/plugin 类型新增“可用”结论;现有本地 activation/validation 边界保持。
|
||||
|
||||
这次对齐的是**预加载选择规则**。当前仍每回合生成 capability context,并未实现原插件引擎“Agent 启动一次”的生命周期;不能把选择规则通过称为完整技能调度等价。原版 PM/UI 在真实 CLI 会话何时按需加载技能,本次没有新的运行时 trace,只能依据规范与包字段给出预期。
|
||||
|
||||
## 角色与消息层级
|
||||
|
||||
核对时的 YCode 链路:
|
||||
|
||||
- `expertTurnContext` 去掉 Agent YAML 外壳,取角色正文和选定技能,形成 active-expert/skill-directory/package-host context。
|
||||
- `createCapabilitySnapshot` 合并该 context 与可用技能信息。
|
||||
- `ipc.ts` 将用户 text、附件说明、资源引用和 capabilitySnapshot.context 拼为 promptText。
|
||||
- OMP 分支将 promptText 交给 `OmpKernel.prompt`,发送 `{type:'prompt',message:...}`;没有独立专家 system 参数。
|
||||
- Gateway fallback 也将同一 promptText 放入 user 消息;其 system 仍是通用 YCode coding assistant 文本。历史 user capabilityContext 会继续参与回放。
|
||||
|
||||
因此当前**角色与技能是用户消息中的附加文本**,不是已证实的独立系统层配置;UI 助理头像/身份快照也不能证明后端 Agent 切换。
|
||||
|
||||
原版静态链路是包/Agent 运行配置:
|
||||
|
||||
- `assemblePreparedFacts` `[101864,102658)` 解析实际 Agent prompt 并形成 prepared facts;函数体 SHA `beac3fb7291ff761f0a8e8f8435ac6a18dcc6f6a40d7a21f443d9d39d2671d77`。
|
||||
- `applyPreparedExpertSettings` `[112541,113125)` 注入 enabledPlugins/marketplace 配置,函数体 SHA `bb5f347e4eec6e8d7a49544a801b15d4cd8e95ae816233257c059640e9eab60d`。
|
||||
- `activateExpertRuntimeForSession` `[122030,123704)` 以 pluginName/agentName/sourcePluginId 做会话绑定;函数体 SHA `debd8d43e02342b90958ffafb04672a02f08741be172b01cfa3fa0aad919ef0f`。
|
||||
|
||||
这证明原版会做插件/Agent override,**尚不能证明其最终上游请求具体使用 system/developer 哪个 role、如何保留基础系统指令、动态切换如何改写历史**。当前保存的规范/daemon 导出没有原 CLI 模型请求序列;不把普通增强提示或 handoff 的 systemPrompt 示例当作专家链路证明。
|
||||
|
||||
保存的 REA runtime provider 导出也做了复核:`hydrateSelectedExpertForRuntime` `[431496,433326)` 会读取本地/目录专家,保留 prompt、defaultInitPrompt、pluginRegisteredName、agentName、marketplace、expertRootDir;发送前 `ensureSessionLaunchConfigBeforePrompt` 还会等待会话配置更新并 hydrate。该字段链说明“选中专家”包含实际运行配置,不只展示名;仍不能据此推断上游 message role。本次查询脚本先核验了归档 339 项正文 SHA,没有操作原版 UI。
|
||||
|
||||
本机 YCode 使用的 OMP 只读检查:`--version` 返回 `omp/18.6.3`;`--help` 成功,stdout SHA `437cbc3126153d271efe7846653ff8577bd860c80f2c30bc1122531a59f6a107`,公开 `--system-prompt`、`--append-system-prompt`、`--system-prompt-template`,以及 `--no-skills/--skills`。当前 OmpKernel argv 未使用这些 system flags。**没有验证动态 RPC set_system_prompt,更不能猜一个新 RPC 命令就宣称成功。**
|
||||
|
||||
可修方向是把当前专家角色与普通用户正文分离,在有证据和真实受控请求验收后接入宿主系统上下文;需要同时验证同会话切换/移除、历史分支、重启恢复及 Gateway fallback。此轮没有改 IPC、OMP 或 role 层级。
|
||||
|
||||
## agentName、maxTurns 与插件切换
|
||||
|
||||
`agentName` 当前用于选择 `agents/<agentName>.md` 和生成 expert-v2 runtimeIdentity。算法包尤其需要区分:plugin.name 是 `senior-algorithm-expert`,Agent 文件/YAML name 是 `senior-algorithm-engineer`。现有文件定位与身份映射通过了真实四包验证。
|
||||
|
||||
但 OMP 启动参数只有 mode/profile/model/cwd/no-tools/session-resume;未把该 agentName 注册为 OMP 主 Agent。help 的 `omp agents` 管理 bundled task agents 也不能被解释为已经支持原版主 Agent override。
|
||||
|
||||
`maxTurns` 当前可从 YAML 读到,但没有交给 OMP,也没有映射到原 agent 循环预算。C++ 50、算法 100 均尚未生效;Gateway 的 maxToolRounds 是另一套配置,不能冒称等价。原规范 normal 默认50、team建议150–200,不足以确定 maxTurns 在原 CLI 内精确计数的是哪种事件,也不能直接用用户消息数或工具次数代替。
|
||||
|
||||
原 `switchExpertPluginForSession`(module.app-server `[70565,73626)`,函数体 SHA `71c39f763eb4880951c1f48cf256c70608e79c548d4ff04a8c42307622b78cac`)会:
|
||||
|
||||
- 找到真实会话 endpoint,注册 marketplace、检查/materialize 版本,禁用遗留专家插件。
|
||||
- POST `/api/v1/plugins/switch`,`persist:false`,含 enable/disable、agentName、sourcePluginId。
|
||||
- 自建 my-experts 特例先启用插件,再发第二次 Agent override refresh。
|
||||
|
||||
当前 YCode 是专家 ID 的会话持久化、真实包读取/资源工具与角色文本适配;没有复刻这套原 CLI 插件状态机。OMP kernel 复用依据当前 cwd/model fingerprint,expertId 改变并不是独立 Agent runtime 重建条件。当前更新会话专家会拒绝正在运行的会话,下一回合重取新包,但旧 OMP transcript 中的 user 角色指令仍存在;只有文字层变更尚不能证明干净切换。
|
||||
|
||||
## 已实现与待接证据
|
||||
|
||||
| 项目 | 状态 |
|
||||
| --- | --- |
|
||||
| 角色原文、文件/头像/技能资源 SHA | 已验证 |
|
||||
| Agent YAML skills 选择性预加载 | 本轮修正并验证 |
|
||||
| PM/UI 技能按目录可发现、全文按需读取 | 本轮验证 |
|
||||
| 激活 defaultInitPrompt 来自同一 validated document | 保留根上下文新接口,四包验证 |
|
||||
| 独立系统层角色注入与动态移除 | 未对齐;未猜 RPC |
|
||||
| Agent maxTurns | 未对齐;没有假预算映射 |
|
||||
| 原 CLI 插件/Agent 生命周期与切换 | 未对齐;有静态 switch 契约,缺 OMP 等价证明 |
|
||||
| 非 agent / 专家团调度 | 本轮未扩展,不能由四包 agent 测试外推 |
|
||||
|
||||
下一步所需证据:原 CLI 的 Agent YAML loader/skill preload实现及计数器;受控原版专家首回合/第二回合/切换/移除的消息层级与运行事件;OMP 系统上下文可用接口的官方/本机 RPC 契约与受控 loopback 请求验证。本轮没有通过其他渠道补采原版。
|
||||
|
||||
## 验证与修改文件
|
||||
|
||||
实际结果:
|
||||
|
||||
- `node scripts/test-expert-preloading.mjs`:**15/15 PASS**,报告 `.tmp/imported-expert-qa-preloading-KuCSlK/report.json`。包含不存在/空/选择性/重复/非法/未注册/歧义/目录别名等边界。
|
||||
- `node scripts/test-imported-expert-resources.mjs`:**370/370 PASS**,四个真实导入包、197 个资源全文 SHA、54 个 UI 字体和两份 BOM csproj 保持;PM/UI 无全文预载、C++/算法各预载唯一声明技能。报告 `.tmp/imported-expert-qa-Q43MkK/report.json`。
|
||||
- `node scripts/test-experts-backend.mjs`:真实隔离 Electron **59+14=73/73 PASS**,`.tmp/experts-backend-OQBtJR`。旧 fixture 改成真实 SKILL frontmatter 和 Agent skills 声明,保留全文预载断言,没有放宽新规则。
|
||||
- `node scripts/test-expert-integration-snapshot.mjs`:**15/15 PASS**,`.tmp/expert-review-snapshot-TDMUIy/report.json`。
|
||||
- node/web TypeScript 均通过。没有构建用户正在运行的 out、没有业务脚本/模型 API 验收。
|
||||
|
||||
四包测试源快照:`experts.ts` SHA `26de0cd06964b84f9b0f029ea01eb3c998d86a098b519a99738fd388a808ae2a`;`runtime.ts` SHA `3237e650a2941019968168efe54ce164e2351cdd7fd17bbd829427607f5f8750`。测试报告还记录其余被测源码及 bundle SHA。
|
||||
|
||||
本子任务修改:
|
||||
|
||||
- `src/main/capabilities/experts.ts`:仅 expertTurnContext 的技能目录/预加载逻辑。
|
||||
- `scripts/test-imported-expert-resources.mjs`:按真实 Agent YAML 校验选择性预加载,兼容并验证原子激活返回 defaultInitPrompt。
|
||||
- 新增 `scripts/test-expert-preloading.mjs`。
|
||||
- `scripts/test-experts-backend.mjs`:修正技能 fixture 格式和显式预加载声明。
|
||||
- 本文与隔离 `.tmp` 测试报告。
|
||||
|
||||
未改 activateExpert、shared activation 类型、IPC、OMP、runtime.ts、页面或用户目录。根上下文另行同步导入 helper 的 Agent YAML 校验,该修改不归本子任务所有。
|
||||
@@ -0,0 +1,160 @@
|
||||
# 当前 cr 加号菜单:REA 源码核对
|
||||
|
||||
2026-10-16;WorkBuddy 5.8.2。只读已保存 REA JS/CSS,未操作原版 UI、未修改生产代码。本报告区分源码控制流、实际可恢复组件及仍须原版运行时确认的行为,不将 ARIA/函数存在等同于键盘全状态已验收。
|
||||
|
||||
## Evidence、SHA 与范围
|
||||
|
||||
JS 来自 `.tmp/rea-runtime-scripts.json`,Evidence `ev_717fa5e846e64d67ac19c8925d121bff632c0d3aefb3603b10858559cabb2dcb`;同版本后续 `.tmp/rea-expert-runtime-scripts-20261016.json` Evidence `ev_e91787b1d4dea651582c6cf12827775b9068b0ee8b80c68ba08d4c1d87d94e90`。原 ASAR root SHA `035254bc76310ea46317433e4840602094543ef323d2d5c5aff7c131729de918`。本轮重算所用 JS SHA,并用 Babel AST 定位具名函数。
|
||||
|
||||
| 简称 | `renderer/assets` 原文件 | SHA-256 |
|
||||
|---|---|---|
|
||||
| I | `src-DbE1_mgM.js` | `6c6ce63c93854783270e855572797d75e536e3b8d4548410e31fe9d147e1feb4` |
|
||||
| C | `contexts-BMeWSUHk.js` | `5f35b7489b107e21ef452c8ee88a95265756f6fc444841eef869228bbc44768b` |
|
||||
| H | `home-CC-czDJL.js` | `121d5a07acccb09e48f20f3a94f9fac8b10770e4a82bca1916d2cccd333f8d14` |
|
||||
| L | `wb-input-add-B045GnIg.js` | `7842fa4321d5351bf6c822bbd0253e0d6d6e68cc9cfae3f2470b3d493c23daf4` |
|
||||
|
||||
CSS 来自 `.tmp/rea-css-recovered/manifest.json`,Evidence `ev_377c8790468b3c67dad8577aabb327f98d3140659f0fffdbabfcff5a40cc9e94`,本轮逐 SHA 核对:
|
||||
|
||||
- `src-CyXHA0IC.css`:`a5e26b537bb50323aefbf25abddad52e288dd3868598be8d255d70886fe77cfe`。
|
||||
- `desktop-sdk-setup-Bh0rg_xP.css`:`b2ee58c0caf560eeddc4eb8c91d86cabddbec634b8d37ed5d6b85d0644c0e142`。
|
||||
|
||||
函数 offset 均为导出 JS 的 UTF-16 code units,start 包含/end 不包含。
|
||||
|
||||
## 当前组件图与状态
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
A[InputToolbarImpl] --> B[AddMenuImpl / memo AddMenu]
|
||||
B --> C[useAddMenuItems: provider条件与顺序]
|
||||
B --> D[Popover: 点击主入口]
|
||||
D --> E[PopoverLayer: fixed定位/portal/外点击/退场]
|
||||
E --> F[Menu + MenuItem + MenuDivider]
|
||||
F --> G[SubMenu: hover计时/焦点/嵌套锁]
|
||||
G --> H[Files / ReferenceFiles / Mode]
|
||||
G --> I[Experts / Skills / Connectors]
|
||||
H --> J[自身host实际能力回调]
|
||||
I --> J
|
||||
```
|
||||
|
||||
`I.InputToolbarImpl [1704717,1709947)` 在 toolbar 左侧第一个位置渲染 memo 后的 `hU(AddMenuImpl)`,此处直接 `<hU />`,没有向 AddMenu 传额外 disabled/onAction。主组件 `[1601493,1605376)` 有三项 state:`isOpen`、`activeSubmenuId`、trigger tooltip open;各项来自 input providers。
|
||||
|
||||
- 主入口 click toggle Popover。打开时关 tooltip,调用 skill.onAddMenuOpen,触发 expert.loadRecentExperts(错误吞掉);关闭时将 activeSubmenuId 清空并调用可选 onClose。
|
||||
- 主菜单为 controlled `Popover(open=isOpen)`;同一时刻仅 activeSubmenuId 对应的受控 SubMenu open。进入另一项将 ID 换成新项;旧项迟到 close 回调只有 ID 仍匹配时才清,不会把新项一并清掉。
|
||||
- 任意 item 若没有可见 children,handleItemClick 调用 onAction 并关闭;有 children 则主项 click 不执行子项动作,展开主要靠 SubMenu hover/touch/key handler。
|
||||
- connector 子菜单首次展开还调用 connector.onEntryOpen('add_menu') 与 onAddMenuOpen;这里 map 回调中的局部 `C` 是“该项为connectors”的布尔值,不要误读成外层主菜单 isOpen。同一 provider 内有自己的 deferred catalog 加载 guard。
|
||||
- tooltip 默认 200ms hover;主菜单已开时 disableInteractions,并以受控状态保持关闭。默认 trigger ghost/medium/circle/iconOnly;aria-label 为 `chatInput.addMenu.title`,打开时加 open class。
|
||||
|
||||
## 入口顺序、显隐和分隔
|
||||
|
||||
`I.useAddMenuItems [1599779,1601311)` 严格按下表顺序追加,没有另一个固定“始终显示五项”的数组:
|
||||
|
||||
| 顺序 | ID | 进入主菜单条件 |
|
||||
|---|---|---|
|
||||
| 1 | `add-files` | attachment 存在,且任一 pick handler / extraItems 非空 / process 存在 |
|
||||
| 2 | `reference-files` | referenceFiles.onSelect 存在且 items.length > 0 |
|
||||
| 3 | `mode` | mode provider 存在且 presentation 为 `add-menu` |
|
||||
| 4 | `experts` | expert provider 非 null(最近列表可空) |
|
||||
| 5 | `skills` | skill provider 存在(列表可空) |
|
||||
| 6 | `connectors` | connector.onSummonMore 存在(列表可空) |
|
||||
|
||||
主菜单最后一个 files/reference-files 项与后面的非文件项之间插一个 divider;files 与 reference-files 两项之间不插这一分隔。空 skills/connectors 用隐藏 placeholder 保持入口,AddMenu 按 provider 特判仍渲染各自空态子菜单。所有项不可用时 AddMenu 返回 null。
|
||||
|
||||
因此未选工作目录时原首页可以只出现 files/mode/experts/skills/connectors;自身已有 cwd 且引用 provider 得到可用结果时出现 reference-files 符合源码条件。仅“选了 workspace”不保证有该项,还要求 provider enabled、结果非空和插入 handler。
|
||||
|
||||
## 定位、跨缝与浮层生命周期
|
||||
|
||||
`I.Popover [384214,385129)`、`PopoverTrigger [385129,385791)`、`PopoverContent [385791,386466)`、`PopoverLayer [381695,383678)`:
|
||||
|
||||
- AddMenu 主层 `placement:top-start`、offset 8、strategy fixed;offset→flip(padding8)→shift(padding8)→size(padding8)。size 将 `availableHeight-10` 与 maxHeight320 比较,下限160px。
|
||||
- 默认 trackReferenceMove=true,使用 autoUpdate(animationFrame:true),不是仅窗口 resize 时算位置。anchor 为点击按钮 ref。
|
||||
- `FloatingPortal` 将实际浮层从 toolbar DOM 中分离;显式带 `cr-theme`、data-cr-theme/data-theme,不能依赖原 toolbar 的继承主题仍自动存在。
|
||||
- `useFloatingLayer [372662,373108)` 按全局 group stack 分配 z-index:默认 base9990、step10;子层同样登记,不是随意写固定 z-index。
|
||||
- 主层 retained mount 用 150ms opacity transition。关闭先走可见性/transition,再 onExited 清 layerMounted;AddMenu 不直接零延迟卸掉主层。
|
||||
|
||||
`I.SubMenu [393807,398417)` 是关键复用组件:
|
||||
|
||||
- 通用默认 openDelay80/closeDelay150;**AddMenu 显式覆盖 openDelay0/closeDelay120**。
|
||||
- placement right-start、offset4、fixed;flip 只指定 fallback left-start;shift padding8/crossAxis:true。size 限宽 `[160,480]`,高 clamp 到默认 max480,默认最低120;available size 更小时按源码 clamp 处理,不能自行换 legacy200下限。
|
||||
- 主 trigger pointerenter 取消 close timer 并打开;pointerleave 取消 open timer,若 open 且没有 lock/输入焦点才计划 close;进入 floating 取消 close timer;离开 floating 同样计划关闭。
|
||||
- **此 cr SubMenu 不调用 safePolygon**。跨4px缝的容错靠120ms close timer;不能把常见 safePolygon 行为当已证实现。
|
||||
- pa context 的 `lock()` 对父子嵌套子菜单计数;子菜单展开时锁住父层,归零才重新尝试 scheduleClose。
|
||||
- 如果 activeElement 是文本输入、textarea 或受支持 contenteditable,且位于 trigger/floating 内,不因 pointerleave 计划关闭。select/button 等并不在该输入匹配表中。
|
||||
- touch pointerdown preventDefault、打开并设 touch latch;touch 模式不因 pointerleave 关闭;后续 mouse pointermove 重置 latch。
|
||||
- 默认 destroyOnClose=true;主菜单关闭卸掉 SubMenu 会清 timer。destroyOnClose=false 才 retained DOM/display:none;AddMenu 没启用该分支。
|
||||
|
||||
## 外点击、Escape 与键盘:避免误抄 ContextMenu
|
||||
|
||||
父 Popover.useDismiss 在 outsidePress 中明确排除 `[data-cr-submenu-overlay=true]` 和 `.cr-sub-menu__overlay`。SubMenu 同时输出新旧两个 data 属性 `data-cr-sub-menu-overlay` / `data-cr-submenu-overlay`,它自己的 outsidePress 也排除任意这些 submenu overlay。缺少标记会造成点击子菜单被父层当外部点击关闭。
|
||||
|
||||
PopoverLayer 还有 capture pointerdown 分支处理存在 `[data-floating-ui-inert]` 的情况:点击其自身、anchor、submenu overlay 或更高 stacking z-index 不关闭;其它目标才 requestClose。这属于主层/其它浮层协作,不是简单 document.click。
|
||||
|
||||
SubMenu useDismiss 明确 `referencePress:false,ancestorScroll:true,escapeKey:true`;祖先滚动会关 child。父 Popover 的普通 useDismiss 没启用 ancestorScroll,主层可继续跟踪位置。一般外部 pointerdown 最终关父层和子层。输入法 composition 下通用 useDismiss 有 Escape 抑制,但下面组件级 handler 不能据此声称全部 IME 键盘路径一致。
|
||||
|
||||
| 位置 | 源码处理 |
|
||||
|---|---|
|
||||
| 主按钮 | 原生 button 支持 click/Enter/Space;PopoverTrigger clone 点击事件并 toggle,role combobox/aria-expanded/listbox。 |
|
||||
| 父 Menu | `I.Menu [386573,386815)` 仅布局/role。MenuItem `[393251,393766)` tabIndex=-1;**没有父菜单 focus-first 或 Up/Down roving**。 |
|
||||
| SubMenu trigger | ArrowRight/Enter/Space preventDefault+stopPropagation,打开并 queueMicrotask 尝试 focus 首个未禁用 role=menuitem。 |
|
||||
| SubMenu overlay | ArrowLeft/Escape 关当前 child、尝试 focus 父 row;Up/Down/Home/End 轮转 query 得到的 menuitem。没有通用 Enter/Space click 分支。 |
|
||||
| SearchInput | `[399641,400205)` 非空 Escape 先清词并 stopPropagation;空输入 Escape 才到 SubMenu/useDismiss。技能/连接器默认autoFocus=true,专家显式false。 |
|
||||
| 自定义子行 | SkillListItem 有 tabIndex 和 Enter/Space;files/experts/connectors 的部分 role=menuitem div 没有 tabIndex,通用 `.focus()` 尝试不等于实际一定可聚焦。 |
|
||||
|
||||
旁边 `ContextMenuPanel` 有完整主列表 focus-first/Enter/Space/上下键,**AddMenu 不使用它**。恢复时不能把那套当成已验证 cr 加号键盘实现。根将采实际 REA 场景;本轮仅明确代码分支,未声称上表所有焦点动作已产生实际效果。
|
||||
|
||||
## 子菜单动作与实际 host 契约
|
||||
|
||||
### files
|
||||
|
||||
`I.FilesSubmenu [1581651,1583408)` 过滤当前 provider 存在的 handler,固定原顺序:local-files、space-library、wecom-wedrive、netdrive(own组),然后 tencent-docs、ima、lexiang(third-party组);两组均非空时有 divider,随后追加 extraItems。handler 映射常量 `[1583472,...]` 分别为 onPickLocalFiles/onPickSpaceLibrary/onPickWecomWedrive/onPickNetDrive/onPickTencentDocs/onPickIma/onPickTencentLexiang。点击调用 handler,立即 onCloseMenu;不是在菜单里伪造已选文件。
|
||||
|
||||
`C.useWbAttachmentProvider [769231,772634)` 默认本地路径建立 `input type=file,multiple=true`;有 onPickLocalFilesOverride 则调用 override。选文件走 process/附件 block;有 store 时先 processing,再 completed/failed,数量上限50(扣已存在附件),并按 transport/文件类型处理大小和上传。各云 handler 来自 attachmentOverrides/宿主真实 picker;不存在就不出现,不可用本地 mock 成功冒充云端选取。
|
||||
|
||||
### reference-files
|
||||
|
||||
`I.ReferenceFilesSubmenu [1585923,1587169)` 展示 provider.items 的文件/目录图标、base/ext、路径 tooltip,点击 provider.onSelect(item) 后关菜单。没有 openPath 或自动读全文调用。
|
||||
|
||||
`C.useWbReferenceFilesProvider [4599343,4600657)`:enabled、cwd、host.searchFiles 可用且未指定外部items,才请求 `{cwd,options:{search:'',resultNum:100}}`;按 id 去重。另读该 cwd 下 `.workbuddy/applications.yaml`,把有效 wbapp_ locator 应用合并。provider 最终还要求结果非空、onInsertBlocks 存在。
|
||||
|
||||
`createReferenceFileBlock [4592574,4592870)` 返回 `resource_link`,含 file/folder mention、filePath/path/relativePath/fileName、displayAsPhrase:true/displayAsContext:false;保存为 block 的应用项使用 application:// URI。对 YCode 的最小适配是自身合法 cwd 文件搜索和真实上下文引用插入;应用 locator/云应用目录未实现时不能造一个“已打开应用”。
|
||||
|
||||
### mode
|
||||
|
||||
`I.resolveModeOptions [1563614,1563708)`:provider.options 优先;add-menu 默认 craft(default)/plan/ask;toolbar 默认 craft/plan/quick,不能混用。`ModeSubmenu [1583710,1584870)` 只渲染非默认模式的 toggle。当前模式来自 draft.selections.mode,缺省默认项;点击已选 plan/ask 回 craft,点击另一个选另一个;先 input.api.setMode({id,label}) 再 provider.onChange。**不关闭菜单**。description 跟随当前模式;provider.disabled 或无 onChange 时禁用;带提示的 ModeToggleRow tooltip 延迟1000ms。
|
||||
|
||||
H 首页 onModeChange `[95414,...]` 接受 craft/plan/ask/quick;plan/ask 清输入 expert、app expert 和依赖 gate。C 会话 `useWbModeProvider [6087096,6089698)` 调实际 config.setMode,并维护权限/quick模型快照、忙/已发首条后的模式约束和错误 toast。宿主需接已有真实模式机制,不能仅让 toggle 视觉改变而消息仍按原模式执行。
|
||||
|
||||
### experts / skills
|
||||
|
||||
`I.ExpertsSubmenu [1574199,1579192)` 使用新 provider search/recents/pins;选择关闭主菜单,再走 provider.onChange,失败恢复旧 expert。详细 summon/default/owner/generation 规则见 [专家使用逻辑核对](C:/Users/Administrator/code/YCode/docs/专家使用逻辑-REA核对-20261016.md)。
|
||||
|
||||
`I.SkillsSubmenu [1594691,1599386)` 点技能构造实际 skill block 插入当前 draft,记录 recent,并调用 provider.onSelect 后关闭;onBeforeSelect/prepareSelection 异步有 alive/generation/session-context guard,取消不插入。置顶/secondary action stopPropagation;新增/管理调用宿主后关菜单。不能把来源为插件的所有内部技能无差别塞入全局技能菜单;provider 的 installed 查询排除 plugin skills。
|
||||
|
||||
### connectors
|
||||
|
||||
`I.ConnectorsSubmenu [1568795,1573334)` 普通行用于连接与能力选择,**不插 resource_link/文字、不打开详情**:未曾连接则 onConnectItem;未曾连接但正在 connecting 且可取消则 onCancelConnect;已连接并非 repairing 则 onToggleItem(item,!isInputConnectorOn)。普通 connect/toggle/repair 不关菜单;管理 footer 调 onSummonMore 后关闭。
|
||||
|
||||
`C.useWbConnectorProvider [828180,847538)` 的具体 delegates:
|
||||
|
||||
- `Xe/onConnectItem [842292,843874)` 调 connectConnector;成功经 He 将 enabled selection 写给 owner,更新连接状态并 toast;needsAuth/connecting 保持 pending,而非假成功。
|
||||
- `He [840080,840405)` 维护 selected IDs Set,映射为含 enabled 的 items 调 onSelectionChange;不是上下文文件插入。
|
||||
- `$e/onToggleItem [845424,846209)` 的 selectionOnlyToggle 分支仅改变该会话能力选择;普通分支关闭时调用 disconnectMcpConnector,失败恢复选择并报错。不能把所有 toggle 都按全局卸载做。
|
||||
- `Qe/onRepairItem [844689,845423)` 调 repairConnector;`et/onCancelConnect [846210,846947)` 调 cancelMcpConnector;各自 opId guard 防旧结果落地。
|
||||
- `nt/onSummonMore [846966,847083)` 优先外部管理回调,否则 goto('/connectors')。
|
||||
|
||||
YCode 自定义 MCP 已有真实连接/逐工具能力时可映射这些宿主动作;QQ/微信/云连接器目录/授权服务缺失时,应保持不可用状态或不提供对应 provider handler,不能将它们显示为已连接。菜单恢复本身不授权账号、不安装外部 MCP。
|
||||
|
||||
## CSS 与最小恢复边界
|
||||
|
||||
固定源 CSS:主弹层 `.cr-add-menu__popover` width200、背景/边框/阴影清空、overflow visible;内部 `.cr-menu` padding8、radius16、边框0.5;row32px、font14/line22、radius8、图标16+右间距8;divider margin6px;open trigger 加背景、plus旋转45deg,transform过渡420ms cubic-bezier(.25,.8,.3,1)。SubMenu overlay 只有140ms ease-out opacity keyframe,无 scale 位移。
|
||||
|
||||
desktop CSS 还对 `body .cr-add-menu__popover .cr-menu` 和所有具体子菜单覆盖 dropdown background/border/shadow,使用 wb tokens。只复制 cr CSS 不加载该覆盖与主题变量不等于原版。实际几何/pixels还需 root 的同宽原生截图。
|
||||
|
||||
建议最小恢复单位为 AddMenuImpl/useAddMenuItems + Popover compound + SubMenu + Menu primitives + source CSS/主题/浮层stack,子菜单接受自身provider。子菜单必须保持两个overlay标记、portal主题和父activeSubmenuId;附件/MCP/专家/技能宿主函数在恢复UI之外接真实现有能力。不要整个执行源 bundle 初始化或以旧 WbInputAddMenu 代替新 cr 控制层。
|
||||
|
||||
legacy `L.WbInputAddMenu` 的 initializer `[73372,79654)` 使用独立 groups、onMouseEnter/onMouseMove、refs Map、mobile absolute/desktop fixed、多种fallback placement、relatedTarget包含关系、120ms close。它有 application 入口、新cr无该独立主入口;已选专家 click短路也属legacy。两套都无 safePolygon 文本,几何与生命周期不能互换。
|
||||
|
||||
## 验证和剩余状态
|
||||
|
||||
本轮仅新增此文档;未改代码/原UI。验证为模块 SHA、Babel AST函数范围、PostCSS精确选中规则+SHA和逐分支阅读。原版主菜单实际当前五项由主任务正在另采,本文不把收到的部分Evidence ID当完整已核验运行时记录。
|
||||
|
||||
建议 root REA 场景:单击开/关、hover相邻项、缓慢/快速跨4px缝、搜索聚焦后移开鼠标、非空Esc清搜索/空Esc回父、viewport右边/上方不足翻转、滚动child关闭、外点击及更高浮层点击、touch latch、mode留开/文件选择关全部/connector toggle留开;再比较已选cwd reference-files有结果/无结果两种。父menu及自定义row键盘是否实际聚焦、动画起止画面、每个本地picker取消返回都尚须实测。
|
||||
@@ -0,0 +1,63 @@
|
||||
# 对话加号菜单:实施与验收(2026-10-16)
|
||||
|
||||
本轮已将对话输入框的手写点击菜单替换为 REA 恢复的当前 WorkBuddy cr AddMenu/Popover/SubMenu。已构建并更新用户 YCode,保留原会话及草稿;实际窗口停在原会话、加号主菜单展开。没有向用户或原版会话发送新消息,没有修改用户模式或连接器状态。
|
||||
|
||||
## 原版证据与边界
|
||||
|
||||
WorkBuddy 5.8.2,Electron 37.10.3 / Chrome 138;原 ASAR SHA-256 `035254bc76310ea46317433e4840602094543ef323d2d5c5aff7c131729de918`。所有原版脚本、CSS、截图和输入动作均通过 REA;自身应用的源码、测试及调试不受该采集限制。
|
||||
|
||||
- 脚本:`ev_717fa5e846e64d67ac19c8925d121bff632c0d3aefb3603b10858559cabb2dcb`,`.tmp/rea-runtime-scripts.json`。恢复模块的 `manifest.json` 固定 5 份源 SHA、80 个函数正文的 UTF-16 区间及输出 SHA。
|
||||
- 父菜单稳态:`ev_330f3e738f84f51e0bc5beb5a2ee5647a8bd567407048d1ff239384929ba324f`,`.tmp/rea-add-menu-open-settled-20261016/`。
|
||||
- 文件子菜单:`ev_78bbf697548bfc8e683f189181aa6d230cef7e74c733102446d5e34ac1dcb1d1`;该次多步探测仅文件完成,不能作为全部动作通过。
|
||||
- 模式、专家、技能、连接器连续动作:`ev_ac997d470322973c2405b8b9ba56251354ec7c1ab5d8e8b9fed1319924de3f11`,`.tmp/rea-add-menu-all-20261016/`;11 步原生操作及清理完成,无发送、模式选择或连接操作。
|
||||
- 详细函数、入口条件及 provider 控制流见 [REA 源码核对](加号菜单-REA核对-20261016.md)。原首页无引用条目时五项,工作目录实际有引用结果时六项;不能用固定行索引跨页面判断。
|
||||
|
||||
探测期间用户在原版切换至已有任务,这是用户活动,本轮没有恢复旧页面、取消任务或提交旧草稿。原版键盘探测没有得到可靠子菜单展开画面,不能宣称自然键盘可达性已通过。
|
||||
|
||||
## 已接入行为
|
||||
|
||||
- 加号点击展开/收起主菜单;主层 top-start、间隔 8px、宽 200px、行高 32px、圆角 16px。悬停条目在侧边展开子菜单,保留父菜单;侧层 right-start、间隔 4px,空间不足翻至左侧。
|
||||
- 使用原 openDelay 0 / closeDelay 120ms、嵌套锁及输入聚焦保护。原当前组件没有 safePolygon,也没有父菜单 focus-first/roving;没有自行补成另一套交互。
|
||||
- 选择专家、技能、引用文件或本地添加文件后关闭菜单;连接器普通操作保留菜单,管理入口关闭后跳转。搜索输入保留 IME;非空 Escape 先清搜索,空搜索再交给父层关闭。
|
||||
- 专家和技能改为嵌入侧层,去掉原先重复 portal/定位和父菜单先关闭的流程。切会话、切空间和异步请求用 owner/epoch 保护,避免旧结果插入新草稿。
|
||||
- “计划 Plan / 仅问答 Ask”开关持久化会话模式;再次点已选模式回默认。Plan/Ask 清专家,选择专家回默认;失败会回滚显示,运行中禁止切换。
|
||||
- 模式接入实际 OMP 与备用内核工具列表和执行入口:Plan 可读、提问及维护计划,Ask 可读和提问;两者都拒绝写入、Shell、MCP 及专家包修改。它是 YCode 的本地宿主策略,尚未证明与原版引擎完全等价。
|
||||
- 引用条目来自实际会话/空间根目录 IPC,选择后插入路径资源;本地添加文件使用真实选择器;技能底部本地导入及管理入口可用。
|
||||
- 连接器读取已有 MCP 注册与真实状态;连接/启停/取消走实际后端,无自动连接或自动信任。未信任项需在管理页批准,本轮实际用户窗口只检查显示,不建立连接。
|
||||
|
||||
## 样式修复
|
||||
|
||||
原主题恢复器曾把 dark 条件摊平成无条件作用域,导致浅色开关被深色 token 覆盖。现保留每组原主题、平台、祖先和 at-rule 条件及局部变量,记录 105 组映射;独立 iframe 加载未改动的 REA 原 CSS 对照,浅色关闭开关 `rgb(230,230,230)`、暗色 `rgb(60,60,60)` 及按钮 token 一致。
|
||||
|
||||
真实窗口还发现旧专家/技能面板依赖 ChatPane 内的 cb 变量,移入浮层后丢失继承而背景透明。通过限定 embedded 面板的宿主变量桥接修复;实际背景白色、圆角 16px,专家宽 240px、技能宽 320px,均在视口内。此桥接属于宿主适配,不能称为当前 cr 内容的完整源码恢复。
|
||||
|
||||
父浅色阴影依据固定原版 computed 值适配,原运行时覆盖的生产者仍未定位;暗色和各子菜单阴影未完成逐像素验收。
|
||||
|
||||
## 验证
|
||||
|
||||
最终 `npm run build`(含 node/web typecheck)通过,日志 `.tmp/composer-add-menu-build-20261016.log`。
|
||||
|
||||
| 检查 | 结果及报告 |
|
||||
|---|---|
|
||||
| 最终完整应用 UI→preload→IPC→真实 OMP→localhost 模型,含重启恢复 | 73/73,`.tmp/expert-flows-xEUhs2/report.json` |
|
||||
| 用户实际 YCode 原生鼠标、布局/背景、五子菜单、关闭和会话草稿保持 | 25/25,`.tmp/live-add-menu-5a9JkJ/report.json`;截图同目录 |
|
||||
| 原生父菜单与选定原版计算值 | 37/37,`.tmp/composer-add-menu-native-0lF563/report.json` |
|
||||
| 子视图及独立原 CSS 浅/深主题对照 | 35/35,`.tmp/composer-submenus-native-OfbSyV/report.json` |
|
||||
| 无 DOM 的 SSR | 5/5,`.tmp/composer-add-menu-ssr-m54vJZ/report.json` |
|
||||
| 模式持久化、资源根目录、OMP/Gateway/MCP 实际执行拒绝及默认模式允许 | 66/66,`.tmp/mode-policy-jrf3mc/report.json` |
|
||||
| 技能 embedded owner/搜索/生命周期 | 41/41,`.tmp/skill-picker-embedded-Kh6dnM/report.json` |
|
||||
| 连接器并发、取消、owner 与实际回调 | 41/41,`.tmp/composer-connectors-uPGtf6/report.json` |
|
||||
| 既有专家状态回归 | 50/50,`npm run test:expert-usage` |
|
||||
| 能力中心完整应用及重启 | PASS,`.tmp/capability-flows-ywE8CW/report.json` |
|
||||
|
||||
`npm run test:omp`、`test:conversation-ipc`、`test:conversation`、`test:chat` 已通过。最终源码恢复 `--check` 为 80 bodies / 5 sources / 4 outputs 一致。
|
||||
|
||||
为解决原版截图耗尽共用 30 秒预算而导致原生场景提前取消,修复了隔离 REA `CdpElectronVisuals.js`:基础采集和动作各自有界,仍继承上级取消,清理仍限 5 秒。自身 fixture 9 项预算/取消回归通过;20 个模块完整性及全局 REA 未修改检查通过。不是绕过 REA 的采集入口。
|
||||
|
||||
实际用户窗口更新后 PID 57576,原选中会话恢复;实窗验收发送 0 条消息、修改 0 次模式、修改 0 个连接器。窗口里已有历史连接错误不代表本轮产生了新错误。
|
||||
|
||||
## 尚未等价的内容
|
||||
|
||||
本轮完成加号主体及主要本地交互接线,没有完成全状态像素和动效 1:1 验收。专家/技能内容仍复用已恢复的旧 picker 并嵌入当前 cr 侧层,当前 cr 内容的所有状态尚未全部恢复;原云知识库/腾讯文档/ima/乐享及在线目录、授权未接入。引用文件当前是实际根目录前 100 项,尚不等同原递归搜索及 applications.yaml 规则。
|
||||
|
||||
专家系统层角色、maxTurns、原 CLI Agent/plugin 生命周期差异延续上一轮,见 [专家使用逻辑对齐](专家使用逻辑对齐-2026-10-16.md)。这些限制不能由本轮菜单通过推断为已解决。
|
||||
@@ -0,0 +1,134 @@
|
||||
# 原版实测与像素对齐(2026-10-15)
|
||||
|
||||
本轮已恢复 WorkBuddy 的 REA 调试采集,实际取得字体、连续截图、折叠过程与编辑器源码,并完成原版 Pierre Diff 的工程接入和运行验证。最新受控截图中,第一正文段落 39,909 像素零差异,气泡只剩圆角边缘 22 像素相差 1 个灰阶;对话区仍未通过完整 1:1 验收。云端服务、子代理调度继续按用户要求暂后。
|
||||
|
||||
## 采集边界
|
||||
|
||||
- 目标为 WorkBuddy 5.8.2,Electron 37.10.3,Chrome 138.0.7204.251。
|
||||
- ASAR SHA-256:`035254bc76310ea46317433e4840602094543ef323d2d5c5aff7c131729de918`。
|
||||
- 原版全部通过本地 REA public CLI/provider 观察,未用外部 CDP、evaluate 或手写 ASAR 提取器绕过 REA。
|
||||
- 用户“继续”授权恢复调试入口;REA 生命周期 provider 重启成功,Evidence `ev_1475f701415d443a2ebdfa1fe1ee009a36de18f0e89e05d0b2798f0ed2f920ef`。已观察既有对话,未发送新的模型请求。
|
||||
- 原版观察结束已回到此前“你好”对话。恢复点击、滚动与媒体覆盖的记录随各 Evidence 保留;不能撤销的业务动作不用于本轮采集。
|
||||
- 现有固定 CSS、JS manifest 保留原 Evidence,新增采集另存不可变归档,未以 latest alias 覆盖固定参考资产。
|
||||
|
||||
## 已落地的对话变化
|
||||
|
||||
### 完成折叠
|
||||
|
||||
`CompletedFold.tsx` / `completed-fold.ts` 已接入真实 `MessageBubble`:结束后默认收起过程,最长正文的全部并列项与最后正文保留在外,中间过程进入“过程消息”;前后过程进入“已完成/已取消”。有实际耗时时显示源码格式的耗时。
|
||||
|
||||
依据固定 JS Evidence `ev_717fa5e846e64d67ac19c8925d121bff632c0d3aefb3603b10858559cabb2dcb`,`src-DbE1_mgM.js` SHA-256 `6c6ce63c93854783270e855572797d75e536e3b8d4548410e31fe9d147e1feb4`:classifyPart 943121、formatDurationMs 946919、computeBodyAnchors 972808、applyCompletedFold 973182(UTF-16 offsets)。
|
||||
|
||||
`turnDurationMs` 从本地回合开始到终态写入消息、IPC 检查点和持久化;旧消息没有耗时则不补造。问答、可视化工具会拆开连续工具分组;分组头使用频次最高工具的原版图标,并列取先出现者。
|
||||
|
||||
限制:YCode 的 plan/task/artifact/image 等自有 part 仍保守保留在外,尚未证明等价于原版全部 widget 谓词、presentationGroup 和重排逻辑。完成折叠算法已对接不等于完整消息投影相同。
|
||||
|
||||
### 工具图标
|
||||
|
||||
阅读、终端、目录、搜索、网页、MCP、浏览器、电脑、技能、位置以及插件使用 REA 源 SVG。插件五种操作、三组别名共 15 个映射已接入;未知工具采用原版 Wrench fallback。
|
||||
|
||||
插件 Evidence `ev_2caae424199a38371af743ef9111db835504c2dae54c1f02e1f9e5511032cc6b`,`renderer/assets/plugin-icon-ri_n6wTH.js` SHA-256 `9f45b4709c3f10b181cadd7fb8fc1e082b99a049e4b6eae6c7c8b31e79534139`。SVG path 2176 字符,与原资产逐字一致;path SHA-256 `aba190972a2534646ec03f28a46fd240e67d41e96db5e230928fbad0aee0e55c`。
|
||||
|
||||
### 写入/编辑文件专用卡片
|
||||
|
||||
已移除旧 `WriteFileDetails` 泛型双正文,接入 `SourceWriteFileView`:创建/编辑状态、成功文件名链接、增删数或 edits 数、流式 500 行截断、完成内嵌行 Diff、120 行/edits 关闭动效规则。来源为同一固定 JS 的 convertWriteFile 1139197、WriteFileView 1140690、computeLineDiff 989785、aE 992254。
|
||||
|
||||
保留 YCode 文件工具字段适配和完整 `oldContent/newContent`,文件名回调携带真实完整工件。实际 Electron UI 已验证内嵌 Diff 文本、21px 行高(原版 12px × 1.75,20px 只是虚拟行估值)、无成功态错误告警,以及键盘打开完整 Pierre 预览且不触发折叠。共享 `SourceToolExpandable` 已补原版 expand 状态切换和 sticky auto-scroll(16px 底部阈值、用户向上滚动退出跟随、嵌套 auto-scroll)。本地 Chrome 138 实测支持 `interpolate-size:allow-keywords`;旧 renderer 的 JS 动画库 fallback 尚未恢复。
|
||||
|
||||
内嵌 Diff 的手写 ResizeObserver 虚拟化已替换为原包 TanStack `useVirtualizer`:从同一 REA export 的 `src-DPDj7_qD.js`(SHA-256 `747e41d215375e1214c366213aea7e077d85421923029c61cbb6e9562be58de0`)恢复 35 个绑定及必要 Rolldown 初始化,导入仅有 YCode React/ReactDOM,保留 estimateSize 20、overscan 12、initialRect 260 和原 `measureElement`。恢复脚本、源码锚点、输入/输出摘要与边界在 `recovered-virtualizer/manifest.json`。
|
||||
|
||||
实际 300 行写文件样本验证:初始与滚动末端各挂载 25 行;spacer 实测 6025px;滚动到底可见最后的 `value299`;大内容折叠过渡为 0s。`npm run test:tool-virtualizer` 另验证来源/输出摘要、导入边界、SSR 与源 Virtualizer 滚动范围。
|
||||
|
||||
限制:原版现代 write-file 文案键没有在现有 REA zh-CN 导出中找到精确翻译,保留原源码英文 fallback;错误正文提示为 YCode 的明确适配。原版条件审批 actions 尚未接入这一专用卡片,审批仍由现有消息交互呈现。TanStack 包独立版本未知,没有安装猜测版本;复杂换行、缩放和反向滚动尚未做原版同画面像素验收。
|
||||
|
||||
## 字体与像素
|
||||
|
||||
真实平台字体采集 Evidence `ev_0c67c7de9c421f01c5651a58450b2505e035093e7a67ae29c57243d7f13a3569`,保存于 `.tmp/rea-visual-ssh-final-fonts`。修复行内代码旧 `font-size:.75em` 导致的约 11.25px:按原版 `.cr-markdown code` 使用 `font-size:1em`、原 mono stack、3px 圆角和 4px inline padding,现约 15px。
|
||||
|
||||
| 实测类别 | 原版实际字形字体 | 本轮对比 |
|
||||
| --- | --- | --- |
|
||||
| 中文助手名 | Microsoft YaHei Bold | family、size、weight、PostScript 名与 glyph count 匹配 |
|
||||
| 中文正文(含拉丁字符) | Noto Sans SC + Segoe UI | 上述项目匹配 |
|
||||
| 用户气泡 | Noto Sans SC + Segoe UI | 上述项目匹配 |
|
||||
| 行内代码 | Consolas,15.0001px | 修复后上述项目匹配 |
|
||||
| 独立英文正文、块代码 | 本轮没有合格可见样本 | 未验证,整体报告仍为 incomplete |
|
||||
|
||||
真实字体报告 `.tmp/ycode-font-platform-report-ssh-source-fixed.json` 的非零退出表示缺少必需样本,不能当作全部字体验收通过。字形文件身份没有通过二进制摘要另行证明。
|
||||
|
||||
早期相同文本的隔离组件截图基于 greeting Evidence `ev_94c5d7b590c2c0654c3efee73c148c782e8b25ad1c51df14840f0f4192255b97`。使用真实 `MessageBubble` 与 `MarkdownContent`,只校准外层容器位置和可用宽度,没有强制目标字高或字号。下表是环境校准前的历史结果,最新结果见下节。
|
||||
|
||||
普通窗口 `showInactive()` 后通过 `Page.captureScreenshot(fromSurface:true)` 采集,完成后关闭窗口;仅操作 YCode 自有 fixture。两区域边界、字体计算属性已匹配,零容差仍不同:
|
||||
|
||||
| 区域 | 不同像素 / 总像素 | 比例 | 平均通道差 / 最大差 |
|
||||
| --- | --- | --- | --- |
|
||||
| “你好”气泡 | 337 / 2475 | 13.616% | 0.6875 / 46 |
|
||||
| 第一正文段落 | 6504 / 39909 | 16.297% | 0.9761 / 50 |
|
||||
|
||||
历史产物:`.tmp/rea-visual-greeting/ycode-message-parity-visible-debugger-{layout,manifest,capture-analysis}.json` 及同前缀 PNG/diff。两图 RGB8、1336×901、Skia iCCP profile 相同;仅改用原版同截图 API 当时没有使差异收敛。不同像素比例只属于这两个区域,不能换算为整项目还原百分比,也不能直接归因为“不可避免的抗锯齿”。
|
||||
|
||||
最新 REA 字体质量计算属性 Evidence `ev_fc29c47ef7b284267584efe1fcabe48345e37a0b03cf492b686faec7aa704324`:原版 `text-rendering:auto`、`-webkit-font-smoothing:antialiased`、`font-kerning:auto`、`font-synthesis:weight style small-caps`、`font-optical-sizing:auto`、`font-feature-settings:normal`、`text-shadow:none`、`zoom:1`。Chromium 不支持 `-moz-osx-font-smoothing` 的 DOMSnapshot 查询,已从采集属性列表去除;保留源码声明并不证明该属性生效。
|
||||
|
||||
### 最新渲染环境校准结果
|
||||
|
||||
中断后的 REA 进程查询 `ev_9962cbd2fef5e7871b066fd79db9c678538cd5ec4beb2163b007263426f7ed5f` 确认原版无存活进程。沿用已有授权,经 REA 重新启动调试实例,记录 `ev_616e35f1c0466daf77b93c7e199e00283eab5dd0f25004e76d691835c94b9a00`,仍观察原“你好”对话。
|
||||
|
||||
本地 REA 字体采集增加 browser-level `SystemInfo.getInfo` 的有限硬件元数据,不使用 renderer evaluate,不保留命令行或用户数据。新原版 Evidence `ev_af6ce1805f575a49d9b37b7d391a07a77a90219a12eb2148cb25930a00da963c` 显示活动设备为 ANGLE SwiftShader,`displayType=ANGLE_SWIFTSHADER`、`glImplementationParts=(gl=egl-angle,angle=swiftshader)`、`gpu_compositing=disabled_software`。
|
||||
|
||||
YCode 隔离 fixture 的 `visible-swiftshader` 模式采用软件渲染、SwiftShader 开关、普通可见窗口和相同截图 API。窗口显示后用 `app.getGPUInfo('complete')` 复核,活动设备/ANGLE 类型和上述合成状态相符。此前 `basic` 采样的 inactive/None 只是信息不足,不能据此认定没有 GPU process。该模式仅用于受控验收,没有把工程默认渲染强制改为软件模式。
|
||||
|
||||
| 最新零容差区域 | 不同像素 / 总像素 | 最大通道差 | 结论 |
|
||||
| --- | --- | --- | --- |
|
||||
| 第一正文段落 | **0 / 39909** | **0** | 该声明区域完全一致 |
|
||||
| “你好”气泡 | **22 / 2475** | **1** | 仅左上、右上、左下圆角轮廓,不包含字形像素 |
|
||||
|
||||
22 个像素均为候选 RGB 比原版暗 1、alpha 相同,原因尚未确证,没有调整 CSS 或放宽容差。原图 SHA-256 `58a4b4e5c5bc2e9df7096ab3aef7bc2a2a7a6234e8259824f833791625a1afa3`,候选 `04c8a45eb26c1df390a36c8fb42232b7aa45ea6a410ac055963547581d3f6e3f`。原图、候选、manifest、diff 图与坐标/RGBA 诊断在 `.tmp/rea-visual-render-environment/`;正文完全一致不能外推为整个聊天页面一致。
|
||||
|
||||
## 折叠动态证据
|
||||
|
||||
原版完成折叠展开 DOM:`ev_5743426dbec2ba8116957f5ba47d9e0305140b3d15e9b3b6f9bb504054e407f7`。
|
||||
|
||||
普通动效:`ev_21079d08279768898d6f030814034cc64abbc4739ed52bfda40af9b52e23a58c`,显式 no-preference 后点击,6 帧高度依次约 168.97、215.72、215.75px,最后稳定;恢复折叠、清除 media override 和归位指针均完成。
|
||||
|
||||
现场默认媒体设置:`ev_e7d6aa4edb00cbb04d95f194f62ba644f5ec7887d58c134b0186db8d7ac5fb15`,首采样已展开到 215.75px,computed transition 为 none。`environment_media.reduced_motion` 仍为 null,因此不能仅凭此认定系统 reduce 开启。
|
||||
|
||||
源码过渡包含 `.28s cubic-bezier(.33,1,.68,1)` 与 reduce 分支,已使用来源 CSS。PNG 顺序采样约 120ms 间隔,尚不足以验收完整 60fps 曲线、反向中断或所有动效。
|
||||
|
||||
## Diff 原版实现
|
||||
|
||||
已纠正旧文档的 Monaco Diff 假设:原版 Diff 使用 Pierre CodeView。REA Evidence `ev_eff23685a08fc8c5ed6ad542c21b24337ed3d7a7c9a483628762ae17828b5d36`:
|
||||
|
||||
- `renderer/assets/codeEditor-D3P9alks.js`,742606 bytes,SHA-256 `5e9a16dca97c102afc3c73cd7dd32ba63daf5e7ddff12707ee1ea63e7a427b19`。
|
||||
- `renderer/assets/codeEditor-Bxmo_AI3.css`,8663 bytes,SHA-256 `1c8f2210c731a25f9051088df0db78b9de5b087c802b3a9e36828c1b6b54c353`。
|
||||
|
||||
已补 REA 精确成员导出能力,使用既有 AsarArtifactReader、root 摘要、成员大小/摘要/UTF-8 校验;不再因不相关的缺失 macOS unpacked 文件阻断选中的 Windows UI 资产。后续闭包依赖 Evidence `ev_70fcd0703f1b25f160b82f291804d9b17b1a0279a3c47ce7477076a6cd33ffde`、`ev_42eb5b81c01f53e03689a0b6ecc0cb65e21dc1714355e8484c503d2361e9eae5`。
|
||||
|
||||
原版包含 split/unified 切换、word-alt 行内差异、bars 指示、line-info 分隔、pierre-light/dark、Shiki JS regex engine 和大文件 viewport highlighter。已用恢复的 Pierre 组件替换旧双 `<pre>`,通过 React.lazy 接入 `ArtifactHostPreview`。
|
||||
|
||||
恢复器 `scripts/rea/recover-pierre-diff.mjs` 取原 bundle 的 Babel scope 闭包,绑定 YCode React;未引入 WorkBuddy app-shared、Monaco、i18n 初始化副作用。原代码内所有 311 个动态 chunk 路径已分 20 批经 REA 导出,无缺失;生成 319 个资产,约 10.4MB,完整语言和主题注册表保留。每个 Evidence、源/输出摘要与变换记录在 `src/renderer/src/workbuddy/artifacts/recovered-pierre/manifest.json`。
|
||||
|
||||
运行集成已修复两项实际故障:Babel 绑定级重命名原 `__vite__mapDeps`,避免 Vite 再注入同名 helper 导致 SyntaxError;YCode CSP 增加 `worker-src 'self' blob:`,允许原版使用的本地 Blob 高亮 worker。
|
||||
|
||||
已按 REA runtime CSS `default-dark-CB7rPan2.css`(SHA-256 `6f1a5b770eceb591ca2e922d075335b170b59ae4e85b2828c176d9a1a5b479fe`)接入 `--vscode-diffCodeContent-background` 的 light `#fff` / dark `#070707`。该文件基于固定 CSS runtime Evidence,未额外宣称 ASAR 匹配。另将原产物专用 `.markdown-content` 映射为 `.artifact-markdown-content`,消除与 YCode 聊天 Markdown 同名导致的灰底及 16px padding 污染。
|
||||
|
||||
`npm run verify:pierre` 自启隔离本地服务器,已实际验证:split/unified 来回切换、Shiki 多色高亮、word spans、行号、+1/-1 统计、13px 字号/20px 行高、通过设置切换明暗主题、新增与删除、无差异 header-only 源码行为,以及聊天 Markdown 背景透明且 padding 0。控制台错误 0。报告 `.tmp/pierre-diff-ui-report.json`;截图 `.tmp/conversation-pierre-diff-2026-10-15.png` 与 `conversation-pierre-diff-dark-2026-10-15.png`。
|
||||
|
||||
限制:这些是 YCode 自有 fixture 的运行验证,尚无相同原版 Diff 画面的像素对照;大文件 viewport highlighter、所有语言的实际词法结果和复杂选择/滚动状态未逐项验证。standalone worker 可选 `shiki-wasm` 分支引用的另一个精确 chunk 未在原包找到,默认 `shiki-js` 路径已运行;不能因此称所有可选分支完整通过。
|
||||
|
||||
## 已执行验证
|
||||
|
||||
- `npm run build`,包含 typecheck:通过。
|
||||
- `npm run test:conversation`:专用工具、15 个插件 alias、fallback 图标、完成/取消/过程折叠、最长并列正文、空耗时折叠、可视化分组边界通过。
|
||||
- `npm run test:chat`、`test:conversation-ipc`、`test:persistence`:通过;回合耗时随终态保留。
|
||||
- 实际 Electron UI:完成折叠键盘展开、任务键盘折叠、命令结果 DOM 与行高/背景/间距、问答键盘提交、审批继续通过,控制台错误 0。
|
||||
- `npm run verify:previews`:HTML 子 frame 实际渲染、sandbox、异步 Markdown、过期读取丢弃、错误、图片缩放/旋转/镜像/切换/下载/Escape 通过,控制台错误 0。
|
||||
- `npm run test:rea-css`:采集 contract、输入预算、恢复、作用域、选择性成员导出、17 模块完整性与全局 REA 文件未改检查通过。
|
||||
- `npm run test:visual-pixels`:比较器自身回归通过。真实原版局部比较仍为 different。
|
||||
- `npm run test:pierre`、`npm run verify:pierre`:完整动态资产锁定、源解析/SSR 与实际高亮、视图切换、明暗、新增/删除/无差异检查通过。
|
||||
- `npm run verify:pierre` 的写文件链路:真实专用卡片内嵌 Diff、成功态无错误告警、键盘文件链接→完整 Pierre 旧新全文预览通过。
|
||||
- `npm run test:tool-virtualizer` 与 300 行真实 UI 滚动:原源码闭包及摘要、初始/末端虚拟范围、末行可见、大内容无动画通过。
|
||||
|
||||
字体祖先定位实验另用最新原版 Evidence `ev_fc29c47ef7b284267584efe1fcabe48345e37a0b03cf492b686faec7aa704324`:隔离容器加上已观察的 virtual-flow 单位 transform 后,YCode PNG 与未加该容器时摘要相同,未使差异收敛。最新原图气泡区域 338/2475 不同,正文仍 6504/39909;只是参考图更换后个别边缘像素变化,不能称取得像素验收进展。
|
||||
|
||||
临时文件:自动审批曾以 `blocked by policy` 拒绝删除三处 `ycode-visual-pixel-helper-*` Temp 目录,未绕过该拒绝;目录保留,不影响工程产物。比较器现对本次自己创建的 helper 采用 Windows EBUSY 重试,不重试此前被拒绝的目录。
|
||||
|
||||
上述离线、自有 fixture 和选择性原版观察的范围分开记录;全状态像素、所有工具/附件分支、完整消息投影及动效曲线仍未通过。
|
||||
@@ -0,0 +1,59 @@
|
||||
# 四位 WorkBuddy 专家迁入 YCode
|
||||
|
||||
2026-10-16,按用户指示将首席 C++ 架构顾问及高级项目经理关德豪、UI 设计师像素君、高级算法工程师小算迁入当前用户 YCode。所有原版包内容、清单和头像/字体读取均通过 REA;安装只使用已经导出并核对 SHA 的副本。
|
||||
|
||||
## 已安装的真实内容
|
||||
|
||||
| 专家 | 本地包 ID | 版本 | 功能文件 | 字节 | 实际技能与定位 |
|
||||
| --- | --- | --- | ---: | ---: | --- |
|
||||
| 首席 C++ 架构顾问/C++ 超级专家 | cpp-super-expert | 1.0.0 | 11 | 471,222 | cpp-mastery;标准、架构、并发性能、框架与排错,6 份参考文档 |
|
||||
| 高级项目经理/关德豪 | senior-project-manager | 1.0.1 | 81 | 1,879,324 | minimax-docx;真实 Agent 重点为站点规格分析、范围控制、拆解开发任务与验收,另有完整 Word 工具源码 |
|
||||
| UI设计师/像素君 | ui-designer | 1.0.1 | 143 | 6,249,920 | impeccable、frontend-dev、browser-use;设计系统、组件、可访问性、前端交付,含 54 个 TTF 字体及许可证 |
|
||||
| 高级算法工程师/小算 | senior-algorithm-expert | 1.0.0 | 20 | 112,272 | algorithm-engineering-playbook;约束建模、选型、证明、复杂度、实现和对拍,7 份参考文档、3 个模板与 Python 示例 |
|
||||
|
||||
共 **255 个功能/许可证文件,8,712,738 字节**。原始 Agent、Skill、知识文档、模板、源码脚本、头像及字体按字节保留;没有改写角色指令。原 WorkBuddy `.downloaded_at` 宿主时间标记及本地审计 manifest 没有混入 YCode 专家包。
|
||||
|
||||
实际路径为 `C:/Users/Administrator/AppData/Roaming/YCode/plugins/marketplaces/my-experts/plugins/<包ID>`,通过同级 `.codebuddy-plugin/marketplace.json` 注册。“我的专家”已显示四张真实卡片。
|
||||
|
||||
安装工具 `scripts/import-rea-expert.mjs` 读取恢复 manifest 的固定 Evidence/SHA/字节数,调用 YCode 生产校验、激活和回合上下文逻辑;临时目录写入后原子注册,并保留既有目录条目。若同名已存在会拒绝覆盖。用户配置下 `capabilities/expert-imports/<包ID>.json` 保留源证据与安装信息。
|
||||
|
||||
## 原版恢复依据
|
||||
|
||||
各专家的完整 Evidence、根摘要、逐文件摘要与恢复脚本分别见:
|
||||
|
||||
- [C++ 专家拆解](/C:/Users/Administrator/code/YCode/docs/首席C++架构顾问-拆解-2026-10-16.md)
|
||||
- [关德豪拆解](/C:/Users/Administrator/code/YCode/docs/高级项目经理-关德豪-拆解-20261016.md)
|
||||
- [像素君拆解](/C:/Users/Administrator/code/YCode/docs/UI设计师-像素君-拆解-20261016.md)
|
||||
- [小算拆解](/C:/Users/Administrator/code/YCode/docs/高级算法工程师-小算-拆解-20261016.md)
|
||||
|
||||
小算原先尚未在已知本地目录。主上下文通过 REA 确认用户当前详情为高级算法工程师/小算,再执行声明的原生“召唤”点击,触发正常下载;未发送消息。Evidence `ev_a2c119f8cb5c94b829ca71998d75ddf925c7a11e68cba8de4e4e7080dcdd77a6`。下载后的 cache 映射确认 `ex_tHvJiRTijDXQ → senior-algorithm-expert`。
|
||||
|
||||
隔离 REA 的正式目录 provider 补齐 HTML、C# 项目/源码、XML/XSD、Shell/PowerShell、LICENSE 与 TTF 导出。继续保留固定根、文件 SHA、UTF-8、路径/符号链接、字节预算检查;TTF 增加 SFNT 签名、表目录及范围检查。全局 REA 未改。
|
||||
|
||||
## YCode 必要适配
|
||||
|
||||
像素君完整包超过原 4MiB 上限,专家包总预算提升至 **16MiB**,文件数上限仍为 256。专家资源读取补齐 HTML/C#/XML/XSD/Shell/许可证等类型,并保留 UTF-8 BOM(关德豪两个 csproj 有原 BOM)。
|
||||
|
||||
回合上下文提供真实 YCode 本地包根目录和文本资源清单,按相对路径通过 `ycode_expert_resource` 读取。原包内脚本使用前仍需检查当前运行时、CLI、API 和工作区输入,不能把角色描述当作工具已经配置。
|
||||
|
||||
## 已完成的验证
|
||||
|
||||
- `npm run build` 包含 node/web TypeScript 通过,日志 `.tmp/imported-experts-build-20261016.log`。
|
||||
- 专家既有后端回归 73 项、新进程恢复/删除通过,`.tmp/experts-backend-1k38DT/report.json`;快照与事务回归 15 项通过,`.tmp/expert-review-snapshot-mbkHX8/report.json`。
|
||||
- 新目录资源 fixture 16 项、既有目录文本 13 项、PNG 二进制 11 项通过。
|
||||
- `node scripts/test-imported-expert-resources.mjs`:**356/356 检查通过**,四份包在隔离 YCode 目录实际安装;255 文件 SHA、197 文本资源 SHA、四个身份/头像/预加载技能、54 字体、模板脚本、BOM、越界拒绝均通过。报告 `.tmp/imported-expert-qa-bpXZQg/report.json`。该测试没有执行原专家脚本或调用供应商 API。
|
||||
|
||||
首轮 import helper 的 `skillPreloaded` 报告字段曾固定检测 cpp-mastery,其他包误报 false;字段已改为按各自 manifest.skills 检查。技能实际预加载由上述独立 356 项验证逐一确认,未把旧字段误报当成能力失败,也未改写旧报告冒充新验证。
|
||||
|
||||
- `node scripts/verify-live-imported-experts.mjs`:当前用户 YCode 的真实 preload/IPC 逐一验证四位专家、197 份文本和四张头像,全部 SHA 一致。通过真实鼠标 hover/click 分别“召唤”,确认对应 expertId 与原 defaultInitPrompt 进入新草稿;没有发送消息,renderer exception 为 0。完成后恢复用户原会话并显示“我的专家”。报告 `.tmp/live-imported-experts-0WdJlu/report.json`。
|
||||
- 首张卡片截图处于入场动画中,另补所有卡片 opacity=1、字体与动画稳定后的截图:`.tmp/live-imported-experts-0WdJlu/four-expert-cards-settled.png`。
|
||||
|
||||
当前用户 YCode 已更新(PID 58848)。主进程构建 SHA `d5db46b5a1f1e743a46e66ec01aed29294ab8a1029c7afe687791fae5817f6bd`;renderer `index-BkN1KZYz.js`。更新前确认无运行回合/附件引用草稿或设置窗口,恢复原会话;用户模型未变。
|
||||
|
||||
## 尚不能宣称已运行的专项能力
|
||||
|
||||
关德豪 Word 工具要求 .NET SDK 8+、NuGet 依赖,部分流程还需要 Bash、Pandoc 或 LibreOffice;当前 PATH 未发现这些命令。Agent 还引用使用者项目中的 `ai/memory-bank/site-setup.md`、`ai/agents/pm.md` 与截图脚本。原文 `run-script` 示例没有对应 CLI 注册,包内版本说明亦有差异,已在拆解报告指出。没有伪造这些输入或声称已生成 Word。
|
||||
|
||||
像素君媒体脚本要求 MiniMax key/baseUrl 与 Python requests,browser-use 要求独立 CLI,云模式另有 key;HTML 模板引用 p5.js CDN 与 Google Fonts。角色提及的 brand-guidelines、canvas-design 没有在原包中提供,未补造。源码及离线字体已迁入,但未配置这些外部服务。
|
||||
|
||||
小算的 Python 最短路示例与 C++ 专家知识文档均已迁入;本轮没有执行示例、训练模型或逐条验证知识事实。四位均已通过角色与资源激活/原生 UI 召唤验收;这不等于所有专项工具、任意回答质量或原版原生 Agent/plugin 运行语义已完成等价验收。
|
||||
@@ -0,0 +1,195 @@
|
||||
# WorkBuddy 复刻 TODO(2026-10-17)
|
||||
|
||||
本清单记录用户本轮提出的 20 项问题,作为后续逐项拆解、实现和验收的工作入口。编号与用户原始问题一致。本轮只建立清单,未开展新的原版采集或业务实现。
|
||||
|
||||
## 执行约定
|
||||
|
||||
- 查看 WorkBuddy 的源码、CSS、资源、页面及交互行为一律使用 REA。
|
||||
- 已有内容沿用 WorkBuddy 5.8.2 的有效 REA 证据;此前未覆盖的内容再采集,并注明实际版本、Evidence ID、观察范围及限制。
|
||||
- 每项依次记录:证据整理 → 差异与方案 → 实现 → 功能验证 → 视觉/交互验收。实现或构建通过不等于完成 1:1 验收。
|
||||
- 只有全部验收点通过才勾选完成;记录待拆解的模块保持未完成状态。
|
||||
- 优先保留用户会话、草稿、空间、模型配置和已有产物。回退、归档、删除应分别建模,不混用同一操作。
|
||||
- 消息时间沿用已确认规则:当天 `HH:mm`;本年非当天 `M月D日 HH:mm`;非本年 `YYYY年M月D日 HH:mm`。显示消息时间,不显示实时钟表时间。
|
||||
|
||||
## 对话与侧栏
|
||||
|
||||
### 01. 任务操作菜单
|
||||
|
||||
- [ ] 将侧栏对话条目后的直接删除按钮替换为原版任务操作入口。
|
||||
- [ ] 通过 REA 对齐菜单的入口、位置、顺序、图标、文案、悬停、关闭、禁用和确认状态。
|
||||
- [ ] 接入:置顶、取消置顶、重命名、独立窗口中打开、打开文件夹、归档、删除任务。
|
||||
- [ ] 验收:置顶顺序和重命名持久化;独立窗口打开正确任务;文件夹指向正确工作目录;归档与删除行为独立;涉及运行中任务时有明确处理。
|
||||
|
||||
状态:待 REA 对照与现有实现盘点。
|
||||
|
||||
### 02. 表格“添加到对话”及引用结果
|
||||
|
||||
- [ ] 对齐表格上方“添加到对话”按钮的字体、图标、背景、边距、出现条件及交互。
|
||||
- [ ] 对齐点击后输入区内引用表格的呈现,包括结构、预览、移除和与已有草稿的组合方式。
|
||||
- [ ] 对齐发送后用户消息中的表格引用显示。
|
||||
- [ ] 验收:引用正确表格内容,不丢失已有草稿;输入区、发送结果及历史重载三种状态一致。
|
||||
|
||||
状态:待 REA 对照。
|
||||
|
||||
### 03. 编辑已发送消息
|
||||
|
||||
- [ ] 拆解原版编辑入口、编辑容器、文本排版、按钮、焦点与键盘交互。
|
||||
- [ ] 对齐进入编辑、修改、取消、提交及失败状态。
|
||||
- [ ] 验收:编辑正确消息;取消恢复原内容;提交后的消息分支与产物处理符合已确认行为。
|
||||
|
||||
状态:待 REA 对照。
|
||||
|
||||
### 04. 用户消息悬停时间
|
||||
|
||||
- [ ] 为已发送用户消息补齐悬停显示时间。
|
||||
- [ ] 对齐出现位置、间距、字体、颜色和与操作图标的关系。
|
||||
- [ ] 复用三档时间格式;验证当天、同年异日、跨年、历史重载。
|
||||
|
||||
状态:待 REA 对照;时间格式已确定。
|
||||
|
||||
### 05. 用户消息回退操作与图标
|
||||
|
||||
- [ ] 移除已发送用户消息上的“重新发送”按钮。
|
||||
- [ ] 替换为“将对话及产物回退到此消息前”操作,图标、提示及交互通过 REA 对照。
|
||||
- [ ] 明确回退边界:该消息之前,而非该消息之后;对话记录与对应产物修改一起处理。
|
||||
- [ ] 验收:多轮对话、文件创建/修改、无产物、运行中禁用、取消确认、回退失败和重启后状态;不得只删除可见消息而保留应回退的文件修改。
|
||||
|
||||
状态:待 REA 对照与现有回退链路审查。
|
||||
|
||||
### 06. 对话区域滚动条
|
||||
|
||||
- [ ] 对齐宽度、颜色、轨道、圆角、悬停显隐、与内容边缘的间距。
|
||||
- [ ] 检查滚动条占位、长内容、流式跟随底部及用户手动上滚的行为。
|
||||
- [ ] 验收:浅色、深色、短对话、长对话、流式输出与不同窗口尺寸。
|
||||
|
||||
状态:待 REA 对照。
|
||||
|
||||
### 07. 侧栏最下一行
|
||||
|
||||
- [ ] 移除最下方不应存在的“收起菜单”入口。
|
||||
- [ ] 对齐最下一行的布局、高度、内边距、字体、头像、当前图标与悬停状态。
|
||||
- [ ] 验收:普通/窄侧栏、浅色/深色下均无残留入口或空白占位。
|
||||
|
||||
状态:待 REA 对照。
|
||||
|
||||
### 08. 新建任务发送后的立即切页与占位
|
||||
|
||||
- [ ] 盘点发送到创建会话、准备环境、接收首个事件之间的阻塞位置。
|
||||
- [ ] 对照原版发送后的页面切换时机与等待状态。
|
||||
- [ ] 发送后立即进入消息页面并显示用户消息;启动较慢时显示合适的助手占位/准备状态。
|
||||
- [ ] 验收:慢启动、正常启动、发送失败、停止、切换任务;不等到模型输出后才切页,不重复创建会话或丢失草稿。
|
||||
|
||||
状态:待 REA 对照与发送状态链路排查。
|
||||
|
||||
### 09. 账户菜单与页面
|
||||
|
||||
- [ ] 通过 REA 对齐点击当前登录账户后的入口、弹层位置、布局、交互及页面风格。
|
||||
- [ ] 内容按用户指定范围:头像与名称、套餐、余额、升级套餐、购买积分、设置、外观、记忆与进化、检查更新、退出登录。
|
||||
- [ ] 逐项盘点现有数据和功能,区分可直接接入、待实现与依赖服务端;不以虚构余额、套餐或成功提示代替真实能力。
|
||||
- [ ] 验收:已接功能实际生效,弹层关闭与导航返回正常,浅色/深色一致;内容不要求逐项照搬原版账户菜单。
|
||||
|
||||
状态:待 REA 拆解;菜单内容范围已确定。
|
||||
|
||||
## 设置
|
||||
|
||||
### 10. 通用
|
||||
|
||||
- [ ] 拆解原版通用设置页面的布局、控件和交互。
|
||||
- [ ] 将 YCode 当前已经支持的内容接入对应控件,记录暂未支持的差异。
|
||||
- [ ] 验收:控件反映真实配置;修改即时生效或明确提示生效时机,重启后持久化正确。
|
||||
|
||||
状态:待 REA 拆解与能力盘点。
|
||||
|
||||
### 11. 外观与浅色/深色主题
|
||||
|
||||
- [ ] 对齐原版外观页面及主题切换交互;当前只保留浅色、深色两种选择。
|
||||
- [ ] 梳理原版主题切换会改变的 token、样式、资源和组件状态。
|
||||
- [ ] 统一主窗口、设置窗口、独立任务窗口、弹层、输入区、对话、代码/表格/工具结果和右侧栏的主题响应。
|
||||
- [ ] 验收:即时切换、跨窗口同步、重启持久化;所有已接页面无浅深混色和不可读内容。
|
||||
|
||||
状态:待 REA 对照与主题覆盖审计。
|
||||
|
||||
### 12. 快捷键页面与真实功能
|
||||
|
||||
- [ ] 拆解页面布局、分组、按键显示、编辑/恢复默认等实际存在的交互。
|
||||
- [ ] 建立快捷键 → 命令 → 实际动作映射,按 REA 证据确认支持范围。
|
||||
- [ ] 验收:展示按键与实际绑定一致;输入框、编辑器、弹层、独立窗口中的作用域和冲突处理正确;可修改项持久化。
|
||||
|
||||
状态:待 REA 拆解与命令绑定盘点。
|
||||
|
||||
### 13. 个性化页面与真实功能
|
||||
|
||||
- [ ] 拆解原版页面、字段、说明、保存/启停等交互。
|
||||
- [ ] 将支持的个性化配置接入实际运行链路,确认在哪些新建/既有会话中生效。
|
||||
- [ ] 验收:修改与持久化有效;界面显示与实际行为一致;未接能力明确记录,不用占位控件宣称完成。
|
||||
|
||||
状态:待 REA 拆解。
|
||||
|
||||
### 14. 记忆与进化
|
||||
|
||||
- [ ] 记录待拆解:入口、页面、数据、读写机制、会话生效方式及生命周期。
|
||||
|
||||
状态:待拆解,本轮不自动展开实施。
|
||||
|
||||
### 15. 智能体页面:团队管理
|
||||
|
||||
- [ ] 拆解原版智能体设置页面,本轮仅对接“智能体团队管理”。
|
||||
- [ ] 根据 REA 证据梳理团队列表、详情及管理操作,将需要的真实存储/配置链路接入。
|
||||
- [ ] 验收:仅展示已确定范围;管理操作实际生效、重启后可恢复;团队管理与真实子代理调度的完成度分别记录。
|
||||
|
||||
状态:待 REA 拆解;范围限定为团队管理。
|
||||
|
||||
### 16. 移除助理与设备连接
|
||||
|
||||
- [ ] 移除设置中的“助理”“设备连接”导航和页面入口。
|
||||
- [ ] 清理默认选中、内部导航、深链接/旧配置回退中的无效目标。
|
||||
- [ ] 验收:设置中不再出现这两项,旧导航目标不会导致空白页。
|
||||
|
||||
状态:待实施;范围仅为用户指定的设置入口,不据此删除其他模块功能。
|
||||
|
||||
### 17. 移除数据管理与应用管理
|
||||
|
||||
- [ ] 移除设置中的“数据管理”“应用管理”导航和页面入口。
|
||||
- [ ] 清理相关无效导航与页面占位。
|
||||
- [ ] 验收:入口完全移除且其余设置导航正常;不删除已有用户数据或已安装内容。
|
||||
|
||||
状态:待实施。
|
||||
|
||||
### 18. 安装中心
|
||||
|
||||
- [ ] 记录待拆解:入口、页面结构、安装来源、安装/更新/卸载流程及与其他能力中心的关系。
|
||||
|
||||
状态:待拆解,本轮不自动展开实施。
|
||||
|
||||
### 19. 关于与获取帮助
|
||||
|
||||
- [ ] 通过 REA 复刻“关于”“获取帮助”的布局、字体、图标、间距和交互外观。
|
||||
- [ ] 不复制原版跳转链接;逐项标注 YCode 自有入口或尚未配置的跳转。
|
||||
- [ ] 验收:本应用版本等信息真实;没有误跳 WorkBuddy 官方账户、帮助或其他服务地址。
|
||||
|
||||
状态:待 REA 对照;布局纳入范围,原版链接排除。
|
||||
|
||||
## 后续模块
|
||||
|
||||
### 20. 定时任务、资料库、更多中的项目
|
||||
|
||||
- [ ] 定时任务:待拆解入口、页面、任务配置、触发/执行记录及生命周期。
|
||||
- [ ] 资料库:待拆解入口、资料组织、添加/读取/检索及会话引用方式。
|
||||
- [ ] 更多 → 项目:待拆解入口、项目组织、工作区/任务关系及管理操作。
|
||||
|
||||
状态:三个模块均待拆解,本轮不自动展开实施。
|
||||
|
||||
## 推进顺序
|
||||
|
||||
1. 对话与侧栏:01 → 02 → 03 → 04 → 05 → 06 → 07 → 08 → 09。
|
||||
2. 设置:先落实 16、17 的入口范围,再依次推进 10 → 11 → 12 → 13 → 15 → 19。
|
||||
3. 14、18、20 保留为待拆解,后续单独展开。
|
||||
|
||||
## 每项交付记录模板
|
||||
|
||||
- 当前状态:待拆解 / 证据已齐 / 方案已明确 / 实现中 / 已实现未验收 / 已验收 / 有阻碍。
|
||||
- 原版证据:版本、REA Evidence ID、观察范围、未覆盖状态。
|
||||
- YCode 差异与方案:具体问题、涉及模块、数据与交互边界。
|
||||
- 实现:修改文件、真实功能、占位或未接部分。
|
||||
- 验证:功能回归、实际窗口交互、浅色/深色、相关截图/几何/像素结果及限制。
|
||||
- 遗留:尚未解决的差异与下一步所需证据。
|
||||
@@ -0,0 +1,61 @@
|
||||
# WorkBuddy 复刻进展:对话正文与工具过程
|
||||
|
||||
> 本文保留第一批实现记录。后续已经从 REA 发布代码还原工程模块,替换自写 Markdown 渲染层并补齐数学、流式缓存等,最新记录见 [源码还原:对话渲染](源码还原-对话渲染-2026-10-15.md)。下文 CJK 插件、Unicode 6 字符提示、数学未实现等条目为当时状态。
|
||||
|
||||
目标仍是 WorkBuddy 5.8.2 的视觉、交互和功能 1:1。本轮完成一批可由现有证据支持的客户端实现;不以构建成功或离线样本代替原版逐场景验收。
|
||||
|
||||
## 原版依据与采集方式
|
||||
|
||||
所有 WorkBuddy 实现查看均通过 REA。本轮通过 `inspect_electron_page(include_script_sources: true)` 获取原版运行时脚本;返回内容超过 MCP 传输预算后,通过 REA 导出证据,再对导出结果进行本地筛选。没有直接读取 ASAR 业务代码,也没有用 CDP、浏览器 evaluate 或 computer-use 绕过 REA。
|
||||
|
||||
- REA Evidence:`ev_717fa5e846e64d67ac19c8925d121bff632c0d3aefb3603b10858559cabb2dcb`。
|
||||
- 选定脚本:`renderer/assets/src-DbE1_mgM.js`,SHA-256 `6c6ce63c93854783270e855572797d75e536e3b8d4548410e31fe9d147e1feb4`。
|
||||
- 完整导出 `.tmp/rea-current-evidence.json`;筛选结果 `.tmp/rea-runtime-scripts.json`;带来源、摘要与偏移的片段 `.tmp/rea-chat-reference.json`。这些是本地证据材料,不进入产品构建。
|
||||
- 目标身份、ASAR 摘要及完整性矛盾沿用接手与重新评估记录;没有将完整性不符推断为功能故障。
|
||||
|
||||
确认的静态实现包含:MarkdownIt 的 `html:false / linkify:true / breaks:true`,关闭模糊邮箱和域名识别,CJK 分隔规则,Prism,代码复制与 2000ms 成功反馈,特定代码语言别名,文件/行号 fence 元数据,表格源码切片与添加到对话动作,以及默认收起的工具过程组件。它们支持重建对应规则,但不证明所有动态路径与像素都已一致。
|
||||
|
||||
## 已实现
|
||||
|
||||
| 范围 | 实际行为 |
|
||||
| --- | --- |
|
||||
| Markdown 正文 | 标题、段落、换行、强调、删除线、行内代码、引用、分隔线、嵌套列表、禁用的任务复选框、表格和代码块;采用与证据相同的解析器和 CJK 插件 |
|
||||
| HTML 回退 | 普通标签移除并保留文本;危险容器及内容抑制;br 换行、u 下划线;代码中的 HTML 保留为字面内容 |
|
||||
| 代码块 | Prism 常用语言高亮,未知语言纯文本回退;js/ts/py/txt 显示名保留;仅归一化已确认的别名;复制保留 token 中的空白与结尾换行;2 秒反馈 |
|
||||
| 文件元数据 | 支持 `lang:start:end:path`、`start:end:path`、`lang:start-end:path`;Windows/Unix basename、完整路径 title、L 行号及扩展名推断;当前无文件跳转处理器,因此使用非点击 span |
|
||||
| 表格引用 | 保留对齐,横向滚动;添加到对话时取得解析器行范围对应的源码,CRLF 归一化为 LF,省略终止换行;追加到草稿并聚焦输入框 |
|
||||
| 流式正文 | 末尾最多 6 个 Unicode 字符的加载提示;不会把 fence 代码作为该提示处理 |
|
||||
| 消息顺序 | 新增 `MessagePart`,主进程与渲染器共用事件归约,保留文本→工具→文本顺序,保存和重新读取后顺序一致 |
|
||||
| 工具过程 | 默认收起,展开参数与完整文本输出,复制全文;保留 running/ok/error/cancelled、实际耗时和取消前输出;600 字摘要与全文分开存储 |
|
||||
| OMP 工具适配 | 根级 toolCallId/toolName/args、结构化文本结果、isError、仅 id 的更新/结束;partialResult 作为当前快照替换,空最终结果可清空旧进度 |
|
||||
| 发送与阅读 | 防重复发送;暂存 IPC 返回 runId 前的事件;失败恢复草稿;阅读上方内容时停止强制滚到底部;修正首条消息命名和回退循环历史快照 |
|
||||
| 会话保存 | 并发首次加载共享 Promise;写入按快照排队,唯一临时文件后原子替换;流式内容约 100ms 合并保存,终态等待在途保存后写入,完成事件在终态保存后发送;写入失败可恢复队列 |
|
||||
| 内核生命周期 | 每个 YCode 会话固定 `userData/omp-sessions/session-<encoded id>.jsonl`;指定 `--resume` 与 `--session-dir`;切换工作目录先释放旧进程;退出/错误清除当前实例;删除等待进程及回合收尾后仅移除所属 transcript;正常退出等待内核和回合保存 |
|
||||
|
||||
新模块为 `src/shared/message-parts.ts`、`src/main/message-checkpoint.ts`、`src/renderer/src/components/MarkdownContent.tsx` 和 `src/renderer/src/styles/markdown.css`;相关类型、IPC、内核、存储、对话状态和组件已集成。新旧 transcript 不做伪造转换:旧会话丢失的工具时序无法从合并正文恢复;旧 YCode-only 历史不会被拼成一条假用户消息灌入 OMP。
|
||||
|
||||
## 验证结果
|
||||
|
||||
| 命令或观察 | 结果及范围 |
|
||||
| --- | --- |
|
||||
| `npm run build` | 类型检查及主进程/preload/渲染器构建通过 |
|
||||
| `npm run test:markdown` | 30 项规则通过:结构、HTML、CJK、链接、表格源码、代码空白、标签、文件行号元数据等;SSR 验证,不验证真实系统剪贴板 |
|
||||
| `npm run test:chat` | 消息顺序、发送状态及 23 项工具输出适配检查通过;假内核/假上游 |
|
||||
| `npm run test:persistence` | 真实 IPC 和会话存储配合假内核通过;检查磁盘中的流式快照、全文、顺序、取消终态、首条标题及回退历史 |
|
||||
| `npm run test:sessions` | 并发创建/更新、磁盘 JSON 与 IPC 一致、冷加载、强制写入失败后的清理和恢复通过 |
|
||||
| `npm run test:omp` | 29 项回合终态、取消、错误、监听清理及 IPC 取消落盘检查通过;假内核 |
|
||||
| `npm run test:omp-session` | 10 项持久/临时启动参数、建目录、退出顺序、监听清理及 1500ms 强制结束检查通过;假子进程 |
|
||||
| `npm run smoke` | 17 项既有回退网关、工具与取消检查通过;本地假上游 |
|
||||
|
||||
YCode 自身使用离线 UI fixture 验证:默认收起/展开、1626 字工具输出末尾标记、复制反馈、文本/工具 DOM 顺序、表格添加到草稿与焦点、代码空白、表格对齐、任务复选框和 HTML 回退。复制由测试桥接记录,未改用户系统剪贴板。1334×901 与 960×640 视口未发现横向溢出;段落和列表字号一致。截图为 `.tmp/chat-parity-2026-10-15.png`,仅展示 YCode 离线数据;浏览器截图的缩放清晰度有限,不能用于像素差分。
|
||||
|
||||
## 明确未通过的部分
|
||||
|
||||
- **原版像素对照仍未通过。** REA 对原版 file 页面结构和脚本可观察,但截图调用被 `target_not_allowed` 拒绝;没有绕过限制获取原版截图。字体、颜色、间距、工具卡细节及动效尚不能宣称完整 1:1。
|
||||
- **OMP 真实恢复仍未通过。** 本机 OMP v18.6.3 在隔离、无提示词的测试中,指定不存在的 resume 路径可生成 450 字节、两条元数据的会话文件;未收到 ready,发送单条 get_state 探针也未收到帧。代码仍按既有协议等待 ready;未验证真实模型回合或重启后的上下文。没有读取或修改密钥/profile,也没有提交真实模型提示词。
|
||||
- Markdown 仍有未覆盖项:完整 Prism 语言集、数学公式、Mermaid/ECharts、原版图片桥接与图片交互、文件跳转等。当前 CSP 限制远程图片,失败显示回退内容;不将这些写成已完成。
|
||||
- OMP 多文本块之间暂按换行拼接,未知对象文本回退上限 16000 字符;二进制/图片不塞进文字输出。审批、提问、产物、子任务及全部未知协议分支仍需证据和适配。
|
||||
- 单运行会话限制、账号/通知/空间、侧栏导航、权限、语音和右栏占位等差距仍在完整 1:1 目标范围内。
|
||||
- 流式保存降低中断损失,不保证断电零丢失;异常退出可能只保存到最近快照,旧 streaming 状态的恢复策略尚待补齐。
|
||||
|
||||
没有重启当前 YCode 或 WorkBuddy 窗口。`out/` 已更新;当前运行的 YCode 主进程将在下一次正常启动时加载这些修改。下一批优先解决真实 OMP 就绪/恢复验证,并通过 REA 补齐审批、提问和文件产物的状态契约。
|
||||
@@ -0,0 +1,91 @@
|
||||
# 对话区四项 1:1 对接(2026-10-15)
|
||||
|
||||
本轮按用户指定推进工具专用视图/命令结果、附件/产物预览、字体/字形、全状态像素/动效四项。已有来源支持的组件结构、样式与向量已经接入;**尚未完成原版与 YCode 的全状态 1:1 验收**。云端服务与子代理调度暂后。
|
||||
|
||||
## 本轮落地
|
||||
|
||||
| 项目 | 已接入、已验证 | 尚未验收 |
|
||||
| --- | --- | --- |
|
||||
| 工具专用视图、命令结果 | 共享 `ToolHeader`/`ToolExpandable`;Read 文件名、行范围和文件打开 payload;命令原版 div 输出结构、stdout/stderr 合并、空输出完成态;文件列表/Web/MCP 的专用结果结构。恢复脚本校验 JS/CSS SHA,投影 105 条来源规则。完整输出及局部读取防误写回归通过。 | 原版 per-tool icon resolver、本地化文案;Write/部分工具 fallback 仍有宿主适配;所有工具状态均未完成原版实时像素比较。 |
|
||||
| 附件、产物预览 | 114 条来源样式;CSS module 映射、主题 token 和动效规则;媒体头部、HTML frame、图片遮罩/工具栏;可追溯的缩放、适配、镜像、旋转、下载、关闭图标。HTML 沙箱/尺寸、下载、Markdown 异步读取/过期读取、图片交互在本地 Electron 验证通过。 | Diff 仍使用宿主双栏文本视图,未接入原版 Monaco;Markdown 产物仍使用已有 React Markdown 适配,Lexical 相关选择器未全部作用于相同 DOM;专业文档、音视频等分支未全量实测;图库导航为已有宿主适配。 |
|
||||
| 字体与字形 | REA 增加实际平台字体采集,记录 familyName、postScriptName、custom 标记、glyphCount;YCode 相同文本五类探针对照脚本;校验原版归档 SHA、Evidence ID、目标与版本,缺样本必须 incomplete。 | 当前没有新原版实际 glyph Evidence。已存在的 5 个 font-family 字符串一致不代表实际字体一致。没有依据将编辑器 Source Code Pro 盲目接入聊天区。 |
|
||||
| 像素与动效 | REA 原生输入、连续 PNG、实测时间戳、区域 bounds、恢复记录;像素比较脚本支持默认零容差、差异图、状态覆盖缺失检查。隔离 Electron 实测取得五类字体、10 张 PNG,并恢复折叠及 viewport。 | 连续截图属于顺序采样,不是固定帧率录像;尚无相同内容、尺寸、主题、状态和时间基准的原版/YCode 成对记录,全状态像素及动效不能判通过。 |
|
||||
|
||||
主审额外修复了命令空 stdout 被误当 JSON 输出、成功结果 message 被误当失败,以及 HTML sheet 中宿主宽度塌缩。YCode 现在设置原版样式需要的 `data-electron-desktop` 和 `data-platform`,本地 Windows Electron 图片关闭区条件样式实际生效。
|
||||
|
||||
图片原版全览 `<img>` 没有错误/重试分支,本轮保持这一来源行为;Markdown 内联图片的 alt/source fallback 属于另一组件。图库和原生下载桥不作为原版等价的证明。
|
||||
|
||||
## 来源与观察范围
|
||||
|
||||
来源属于此前已识别的 WorkBuddy 5.8.2 / Electron 37.10.3 / Chromium 138 基线。下面 CSS/脚本 Evidence 自身没有单独记录产品版本,产品版本来自同一基线的目标观察;它们不是本轮重新观察当前原版所得。
|
||||
|
||||
- JavaScript:`ev_717fa5e846e64d67ac19c8925d121bff632c0d3aefb3603b10858559cabb2dcb`,`.tmp/rea-runtime-scripts.json`。
|
||||
- CSS:`ev_377c8790468b3c67dad8577aabb327f98d3140659f0fffdbabfcff5a40cc9e94`,`.tmp/rea-css-recovered/manifest.json`。原始规则正文经过固定摘要校验;禁止用新的 latest alias 覆盖该固定来源 manifest。
|
||||
- 既有原版画面:`ev_dbd7b4f6304305b0428d19c891088806a09d05b33a1b69d7e7df95e22f3914f4`,1336×901,`.tmp/rea-visual-reference/`。这张画面与本地 fixture 内容不同,不能直接作为全聊天区像素差异结论。
|
||||
- 工具视图:`src-DbE1_mgM.js`,SHA `6c6ce63c93854783270e855572797d75e536e3b8d4548410e31fe9d147e1feb4`;`src-CyXHA0IC.css`,SHA `a5e26b537bb50323aefbf25abddad52e288dd3868598be8d255d70886fe77cfe`。来源位置与规则选择在 `recover-tool-result-styles.mjs`。
|
||||
- 附件/产物:`recover-artifact-styles.mjs` 固定 5 份 CSS、4 份 JS、CSS module 映射和 ASAR 比对身份;输出 `.tmp/rea-css-recovered/artifact-projection.json`。
|
||||
- 图片向量:`image-preview-component-BgOcW3Xe.js`,SHA `6720317ba018215f96a87d966b08c0d0aa74c26d2298d5fd95f71e8ff2e04e59`;ZoomIn 与 Close 的导入/导出链另见 `PreviewIcon.tsx` 注释。11 个填充路径与两个关闭路径比对通过。
|
||||
|
||||
以上查看原版均沿用 REA 导出;没有使用历史 `wb-*`、直接连接原版 CDP、浏览器 evaluate 或其他旁路。
|
||||
|
||||
## 当前现场阻碍
|
||||
|
||||
此前 9223 调试端口已不可达,结束前复查仍是 REA `endpoint_unreachable`。
|
||||
|
||||
本轮通过新增的 REA Windows 进程元数据 provider 取得 Evidence:
|
||||
|
||||
`ev_053764eb174383f778c003b4d2a73180c801760f7cfd40fd5359f061671e4088`
|
||||
|
||||
归档:`.tmp/rea-workbuddy-process-metadata.json`。观察时 WorkBuddy.exe 仍有进程,记录中没有 `--remote-debugging-port`;其当时 6 个监听端口经 REA 目标发现都未返回有效调试接口。这里只能证明观察时无可用的已发现接口,不能推断当前任务已结束。
|
||||
|
||||
继续原版字体、全状态和动态画面验收需要恢复原版调试接口。用户此前说明原版正在执行任务,重启可能中断它;本轮未中断原版。
|
||||
|
||||
## REA 本地能力与复现命令
|
||||
|
||||
本地副本 `6.5.0-visual.2`,provider `1+visual-local.2`;16 个本地模块有摘要清单,全局 REA 文件未变更。源代码在 `scripts/rea/patches/`,准备脚本为 `prepare-css-runtime.mjs`。
|
||||
|
||||
```powershell
|
||||
npm run rea:css:prepare
|
||||
npm run test:rea-css
|
||||
npm run test:rea-visual-live
|
||||
npm run test:font-platform
|
||||
node scripts/rea/compare-visual-pixels.mjs --self-test
|
||||
```
|
||||
|
||||
隔离窗口实测文件:`.tmp/rea-visual-probe-self-test/verification.json`、`capture.json`、`frame-000.png` 等。它们标记为本地自检,**不是 WorkBuddy 字体或动效通过证据**。实测截图修复为 `fromSurface:true`,避免隐藏 offscreen 窗口在旧截图路径断开调试连接。
|
||||
|
||||
原版调试恢复后,先用仅字体的被动 probe;声明操作的 probe 会改变原版 UI 状态,应只选择当前许可范围内的折叠、hover 等目标,按 Evidence 的恢复结果检查。
|
||||
|
||||
```json
|
||||
{"include_fonts":true,"track_selectors":[],"actions":[]}
|
||||
```
|
||||
|
||||
将上面保存为 `.tmp/workbuddy-font-probe.json`,执行:
|
||||
|
||||
```powershell
|
||||
npm run rea:visual:capture -- --probe .tmp/workbuddy-font-probe.json --output .tmp/rea-visual-four-items
|
||||
node scripts/rea/verify-font-platform-parity.mjs
|
||||
```
|
||||
|
||||
`capture-css.mjs` 通过 REA 公共入口获取并归档真实 Evidence;新输出目录避免覆盖既有参考画面。字体报告自动写入 `.tmp/rea-font-platform-report.json`。`version=unobserved` 或五类中任意缺失都不能通过原版字体验收。
|
||||
|
||||
动态 probe 支持 hover、click、scroll、key、wait、viewport,最多 12 步/64 帧,声明等待/采样预算 15 秒。恢复为尽力执行:toggle 回点、反向滚轮、清除 viewport override、指针移至原点;键盘焦点、原先 viewport override 和其他业务副作用不能自动还原。选用前必须阅读结果中的 limitations,不能把恢复命令执行成功当成业务状态完全恢复。
|
||||
|
||||
像素比较 manifest 包含 `source.kind`、`requiredStates` 和 `pairs`,每对指定 `name/reference/candidate`,可指定整数像素 `region`;原版来源还必须指定 `referenceEvidence.id/archive`。运行:
|
||||
|
||||
```powershell
|
||||
node scripts/rea/compare-visual-pixels.mjs <manifest.json> --output <output-directory>
|
||||
```
|
||||
|
||||
不允许用不同消息内容直接计算整个对话区的差异率。动效另需比较相同触发动作后的实际时间和几何变化,不能把 frame 序号视为等间隔时间。
|
||||
|
||||
## 已完成验证
|
||||
|
||||
- `npm run build`(含两个 TypeScript 检查)通过。
|
||||
- `test:conversation`、`test:artifacts`、`test:media`、`test:resources`、`test:chat` 通过。
|
||||
- REA CSS/布局/PNG/字体/原生输入合约、公共 MCP 入口、16 模块完整性验证通过。
|
||||
- `test:rea-visual-live`、五类字体本地自检通过;像素比较器的相同/单像素变化/尺寸/缺状态/证据绑定自检通过。
|
||||
- 本地实际 UI:`npm run verify:previews` 通过,依赖已构建文件和 8789 fixture server。`.tmp/conversation-preview-qa.json` 记录 HTML 头 48px、frame 646×759、图片 stage 1256×701、toolbar bottom 40px、Windows 关闭区 top 40px/right 148px、零 console errors。
|
||||
- 原有对话 UI 验证继续通过:问答键盘选择、审批恢复、Task 键盘折叠、命令输出结构、28 项选定计算属性、5 个 font-family 字符串。上述有限检查不等于字体文件、字形或全状态像素通过。
|
||||
|
||||
本地画面:`.tmp/conversation-artifact-html-2026-10-15.png`、`.tmp/conversation-image-preview-2026-10-15.png`。它们用于检查 YCode 实际呈现。
|
||||
@@ -0,0 +1,62 @@
|
||||
# 对话区域八类对齐:实现、验证与未决项
|
||||
|
||||
> 后续源码级还原、富消息复制、原版 SVG/中文文案与 Artifact/Diff 的最新进展见 [源码级续对齐](源码级续对齐-2026-10-15.md)。下表保留本轮基线,后续已修复项以续对齐记录为准。
|
||||
|
||||
> CSS 采集更新:已通过本地 REA 修复取得 64 份已加载样式正文,当前组件 CSS 获取阻塞已解除;13 份与既有 ASAR 清单完全一致,2 份存在差异。详见 [REA CSS 采集修复](REA-CSS采集修复-2026-10-15.md)。此更新不表示下表八类已经完成样式集成或像素验收。
|
||||
|
||||
用户目标仍是 WorkBuddy 的视觉、交互和功能 1:1。本轮已把原先缺少的消息类型、组件入口和宿主回调接入工程;**八类尚未通过完整 1:1 验收**。源码契约恢复、YCode 功能联调与原版像素等价是不同结论。
|
||||
|
||||
## 原版证据与采集边界
|
||||
|
||||
- WorkBuddy 5.8.2,Electron 37.10.3;ASAR SHA-256:`035254bc76310ea46317433e4840602094543ef323d2d5c5aff7c131729de918`。
|
||||
- 原版业务实现使用 REA 已导出的脚本,Evidence:`ev_717fa5e846e64d67ac19c8925d121bff632c0d3aefb3603b10858559cabb2dcb`。本地解析、格式化和恢复这些导出内容,没有执行原版脚本。
|
||||
- `src-DbE1_mgM.js` 包含工具宿主、注册表、通用壳、TodoWrite、问答及 ExitPlanMode;`src-0FGg1seX.js` 包含 QuestionFloating、审批、计划、任务和输入实现;`contexts-BMeWSUHk.js` 包含复制、用户消息动作、助手 footer 与语音状态逻辑。
|
||||
- 三份基础 CSS 已经 REA 提取,并与当前 ASAR 清单匹配,Evidence:`ev_267e2188e816796acee76650153ab5a1c1f902e3a761d686979d2fe9926eed07`、`ev_97959691fb7cabf7c41f948b08332196924fec1fa8cb71e34dbafd65d912e637`。这些文件不足以覆盖新的对话组件样式。
|
||||
- 当前 `extract_artifact` 只能提取完整包,因缺失外平台 unpacked 成员而失败;Electron 观察对组件资源存在范围过滤,截图入口也未获得可用原版对照。没有制造缺失成员、改写 REA 或使用其他渠道采集原版。
|
||||
- 已将视觉缺口登记为 REA 未决项 `unk_7501f666de6716fa984de8a3135164da05d580ac8aa523e2770460329c892b39`,变更 Evidence:`ev_4027b93aa36ea7c54fa3fa1e27fb3ff83a4e4a77e2e47f91aec0961e792f5131`。
|
||||
|
||||
## 八类当前状态
|
||||
|
||||
| 类别 | 本轮工程实现与验证 | 完整 1:1 尚缺的内容 |
|
||||
| --- | --- | --- |
|
||||
| 1. 字体、间距、图标、提示与动效 | 延续 115 项已核验 token 和六档字体覆盖;输入区、消息动作、分组使用统一变量;复制/编辑图标路径来自 REA 导出。输入框自动增高、运行时可继续写草稿,目录和权限位于底部。 | 新组件 CSS、全部原版图标、tooltip 浮层、hover 和动效没有完整样式/像素证据;部分当前样式与文字是本地适配。 |
|
||||
| 2. 专用工具卡片 | 根据捕获的 49 项注册信息恢复分发,覆盖命令、读写编辑、列表/Glob/Grep、代码与工具搜索、网页、已知 MCP、技能、计划、任务、问题及未知工具。保留结构化 result 与完整 output;结构化摘要不能覆盖原文。恢复 TodoWrite 专用步骤视图,消除新消息重复计划卡。 | 动态 MCP 名称、原版完整 diff/编辑器、全部结果细节和像素样式仍不等价;分发覆盖不代表对应云端工具已经实现。 |
|
||||
| 3. 审批与问答 | QuestionFloating 的默认单选、多选、自定义、分页、跳过、提交与历史答案;审批选项和 pending/responding/answered/rejected/cancelled/error;宿主校验 run/id,拒绝过期、重复或无效提交。回答/审批后工具继续,取消时结束等待。 | WorkBuddy ACP、额度/高信用审批等服务端协议与真实服务结果尚未复现;当前有可用的 YCode 宿主桥接。 |
|
||||
| 4. 思考、计划、任务与产物 | thinking 增量与终态;PlanCreate/PlanUpdate/TodoWrite/Task/TaskOutput;计划查看、任务点击、下载和执行入口;任务审批接入现有 broker。ExitPlanMode 保留 session/id 去重及未落盘 content,直接打开内存中的 Markdown。 | 子代理任务调度、WorkBuddy 计划执行服务、完整 ArtifactContentRenderer/原生编辑器尚未等价。当前详细预览是 YCode 适配器;执行计划转换为真实新 prompt。 |
|
||||
| 5. 消息操作 | 用户复制 text/plain、text/html 和已确认的 `application/x-cb-chat-contentblocks` 版本化格式;助手复制请求范围 JSON,并走敏感内容/Quick QA 投影。用户编辑、重发、助手重新生成使用原生 user entryId 分支;旧分支归档。赞/踩真实保存到本地会话。完整受控写入有恢复入口、确认与文件冲突检查。 | 附件/资源等富内容的剪贴板 schema 尚未完整映射;赞/踩未连接 WorkBuddy 云端反馈服务;任意命令造成的文件改动不能承诺完整恢复。没有新增无证据的助手编辑或气泡选区引用。 |
|
||||
| 6. 图表、图片与文件 | 保留已有 Mermaid、图片预览、路径/行号、文件预览、下载实现;新增内存计划产物预览,避免文件尚未生成时丢失内容。相关既有回归通过。 | 原版全部媒体 CSS、依赖精确版本、原生文件编辑/符号跳转、完整产物详情与跨媒体行为仍待证据和对照验收。 |
|
||||
| 7. 附件、语音与权限输入 | 原生选文件、粘贴/拖放、20 MB 预检、暂存/移除与资源引用;已用于会话的附件保留,历史图片仍可恢复。图片通过 OMP 图像 content 或兼容网关 image_url 发送。PCM/WAV 录音、295 秒上限、会话切换/卸载取消、迟到结果丢弃;转写走真实兼容服务。两种原版权限值和 full-access 确认入口接通。 | 官方 ASR、云上传、PDF/Office 解析、各连接器及原版系统沙箱尚未等价。当前 default-sandbox 是宿主路径约束/写入审批策略,**不是完整操作系统沙箱**;命令执行需 full-access。 |
|
||||
| 8. 中断、重启、长对话与并行会话 | 按 session/run 路由事件;发送响应前的事件归属正确;后台运行不覆盖前台;过期加载不覆盖新会话;草稿按会话保存。冷加载把遗留 streaming 和运行工具恢复为已中断,并保留输出。OMP 每会话独立原生 transcript,文件恢复后的 pending branch 持久化重放。取消命令会终止自身 shell 子进程树。回退网关保留按顺序的 assistant/tool 历史。 | 原版长列表虚拟化、滚动锚点、极长历史性能、全部重连/并行子任务状态没有完成相同环境的原版对照。 |
|
||||
|
||||
## 原生内核验证与恢复
|
||||
|
||||
OMP 是 YCode 现有内核选择,协议验证不证明它与 WorkBuddy 的内核等价。
|
||||
|
||||
OMP 18.6.3 使用临时随机 profile、临时 transcript 和 loopback mock provider 实测:
|
||||
|
||||
- 显式传入正确的 `provider/model` 可以完成 ready;profile 名不能冒充 provider。
|
||||
- 默认 `--no-tools`,通过 `set_host_tools` 注册受控工具。真实 `host_tool_call` 使用 `id` 关联响应,字段为 `toolCallId`、`toolName`、`arguments`;YCode 与兼容网关共用同一执行入口。
|
||||
- 图片在支持图像输入的模型配置下到达上游 image_url;真实 thinking_delta、工具调用、最终 agent_end/prompt_result 已观测。
|
||||
- `get_messages`、`get_tree`、`get_branch_messages`、`branch`、`fork`、`switch_session` 经实测;`navigate_tree`、`navigate_to_entry`、`clear` 不可用。
|
||||
- **纯 branch/fork 不跨重启持久。** 编辑/重发/重新生成在 branch 后写入新 prompt;纯恢复则将 pending native branch ID 保存到会话,冷内核在下次发送前重放,确认新 native user ID 写入后清除标记。
|
||||
|
||||
恢复只接受拥有完整 before/after 记录的受控写入,先检查所有文件当前内容,再修改;遇到外部修改拒绝覆盖。旧消息分支保存到 `userData/session-branches/`。它不等同于任意 shell 操作的完整工作区快照。
|
||||
|
||||
## 验证范围
|
||||
|
||||
以下自动检查已通过:`build`、`test:chat`、`test:conversation`、`test:conversation-ipc`、`test:omp`、`test:omp-session`、`test:persistence`、`test:sessions`、`test:markdown`、`test:recovered`、`test:media`、`test:resources`、`test:font-size`。
|
||||
|
||||
新增测试区分了真实代码和替身:
|
||||
|
||||
- `conversation-runtime-regression.ts`:实际文件读写/冲突/恢复、符号链接边界、审批/问答/取消、命令子进程树停止、网关历史和 OMP 事件适配;其内核事件由 fake kernel 驱动。
|
||||
- `conversation-ipc-regression.ts`:真实 IPC/sessions/attachments/speech 模块、隔离临时目录、mock Electron/OMP、localhost multipart 语音服务;覆盖同会话并发、跨会话并行、分支顺序、归档、恢复失败回滚、冷启动重放、附件保留及语音失败。
|
||||
- `omp-protocol-probe.ts`:真实 OMP 可执行程序与 loopback provider;不使用真实凭据或外部模型服务。
|
||||
- `verify-ui.mjs?fixture=conversation-complete`:浏览器验证页使用明确的测试桥和测试数据;已点击问答提交、审批、附件移除、权限确认/取消、会话草稿切换、计划详情与未落盘产物。不是 WorkBuddy 原版截图对比。
|
||||
|
||||
页面截图位于 `.tmp/conversation-question-2026-10-15.png`、`.tmp/conversation-integrated-2026-10-15.png`、`.tmp/conversation-plan-artifact-2026-10-15.png` 和 `.tmp/conversation-final-2026-10-15.png`。第三张展示内存产物预览,其余展示输入交互。
|
||||
|
||||
最后补强了发送事务:用户消息、助手占位和所选 native branch marker 一起原子保存。中断发生在用户 entryId 回填之前时,重发会核对完整已绑定的用户前缀;原生已接受该输入则恢复对应 entryId,尚未接受则沿已确认的前缀发送,禁止猜测旧历史。新增 IPC 用例覆盖这两种情况,fake branch 也按真实协议排除目标 user 本身。
|
||||
|
||||
## 下一步验收入口
|
||||
|
||||
当前组件 CSS 已有可复用的 REA 采集入口和导出清单;下一步按组件接入这些真实样式,取得原版可控截图,核对尺寸、字体、间距、图标、tooltip、hover 和动效。原版服务、原生编辑器/系统沙箱和长会话虚拟化分别保留独立验收项;不能用通过本地构建或测试桥联调替代这些结论。
|
||||
@@ -0,0 +1,52 @@
|
||||
# 对话区域:图表、图片与文件
|
||||
|
||||
本轮将 REA 已取得的 Mermaid、Markdown 图片、路径检测与点击处理还原为工程模块,接入实际消息渲染。图表不再只有代码回退,图片能够打开预览,文件标题和行内路径能够调用本地文件预览。当前对话区域仍未完成全部 1:1 验收。
|
||||
|
||||
## 原版依据
|
||||
|
||||
原版为 WorkBuddy 5.8.2。所有原版实现仍只通过 REA 查看;本轮在既有 REA runtime Evidence `ev_717fa5e846e64d67ac19c8925d121bff632c0d3aefb3603b10858559cabb2dcb` 的完整导出上阅读、校验并进行 AST 分拆,没有直接读取原版安装文件,也没有执行捕获的 bundle。
|
||||
|
||||
主发布脚本 `renderer/assets/src-DbE1_mgM.js`,SHA-256 `6c6ce63c93854783270e855572797d75e536e3b8d4548410e31fe9d147e1feb4`。下表区间为 UTF-16、右端不含。
|
||||
|
||||
| 证据范围 | 工程落点 |
|
||||
| --- | --- |
|
||||
| 图片 URL 校验/解析 `[721231,721551)`,MarkdownImage `[721564,722288)` | `workbuddy/images/image-url.ts`、`MarkdownImage.tsx` |
|
||||
| 路径点击 `[722904,723374)`,路径检测 `[723580,724687)`,缓存/解析 `[724997,726485)`,InlineCode `[727268,728626)` | `workbuddy/paths/` |
|
||||
| SVG/PNG 导出 `[731747,733169)` | `workbuddy/mermaid/svg.ts` |
|
||||
| MermaidToolbar `[783052,784820)`、渲染器 `[787685,788850)`、render hook `[790284,792838)`、pan/zoom `[793017,794596)`、组件 `[795642,798306)` | `workbuddy/mermaid/` |
|
||||
| activation `[785013,785362)`、可见性 `[789143,789531)`、宽度发布 `[804434,805229)` | `mermaid/visibility.ts`、`width.ts` |
|
||||
|
||||
图片单文件查看器来自同次 REA 导出的 `image-preview-component-BgOcW3Xe.js`,SHA-256 `6720317ba018215f96a87d966b08c0d0aa74c26d2298d5fd95f71e8ff2e04e59`,提供适应/原始大小、缩放、拖动、镜像、左转、关闭和下载控件依据。保留的 339 份脚本中未找到 URL 列表图片查看器的完整实现;上一张/下一张及键盘切换是明确的本地适配。
|
||||
|
||||
`npm run recover:chat-reference` 的派生输出现有 541 个声明片段、164 个赋值定义;其输入必须是既有 REA 导出,不连接原版。本轮尝试 REA ASAR extraction 因缺少 unpacked companion `cli/node_modules/koffi/build/koffi/darwin_arm64/koffi.node` 失败,未用其他采集渠道绕过。
|
||||
|
||||
## 接入行为
|
||||
|
||||
- Mermaid:恢复源码清理、串行渲染队列、64 项/8 MiB 缓存、取消与过期结果处理、SVG ID 重映射、代码/图表标签、明暗主题、缩放/适应、SVG/PNG 导出,以及 300 ms 加载淡出。可见性观察保留 320px margin 和首次可见后保持激活;宽度首次发布或变化至少 16px,360 ms leading/trailing debounce 后由 rAF 发布。宽度相关图表保留 420 ms 重渲染等待。
|
||||
- 图片:恢复异步 URL 解析、取消过期请求、加载/失败替代文字、图片顺序与点击索引。预览提供缩放、适应/原始大小、拖动、旋转、镜像、下载、Escape 与切图;切图重置变换,下载失败显示错误。
|
||||
- 路径:恢复文件/目录/符号候选与 `#L4-L7` 行号解析、显示截断、请求缓存和并发去重。点击时再次向宿主确认实际类型,更新缓存/组件状态后打开;失败变为 unknown,阻止旧路径继续打开。保留原版检测边界,例如裸 `src/` 不匹配候选;`src` 可在宿主确认目录后高亮。
|
||||
- 宿主:新增 preload/IPC 资源契约,读取工作区文件/目录和图片,提供带行号的只读预览及 native save dialog 下载。代码标题直接传递文件和行号。文件读取检查解析后真实路径;文本上限 2 MiB、图片 20 MiB、通用下载 32 MiB。下载 MIME 接受原版 SVG 导出的 charset 参数。
|
||||
|
||||
文件预览面板、资源 IPC、URL 列表预览及其错误反馈是 YCode 宿主适配,并不等于恢复了原版编辑器实现。图表下载菜单保留捕获代码的 hover 开启、离开关闭、click toggle 组合;首次鼠标进入后点击会关闭菜单,这是现有源码的行为,没有擅自修正为另一种交互。
|
||||
|
||||
## 验证结果
|
||||
|
||||
| 验证 | 结果与范围 |
|
||||
| --- | --- |
|
||||
| `npm run build` | 类型检查与 main/preload/renderer 实际构建通过 |
|
||||
| `npm run test:media` | Mermaid 缓存/队列/取消/清理/SVG 引用,图片 URL/索引/失败下载,23 项路径检查通过 |
|
||||
| `npm run test:resources` | 真临时目录、行号、目录、file/local-file 图片、junction 越界拒绝、HTTP 图片读取通过;加载实际 IPC 注册函数,native dialog 替身下验证取消和 SVG/PNG 文件写入;SVG MIME 含 charset |
|
||||
| `npm run test:markdown`、`npm run test:recovered` | 集成渲染及 5 个源码恢复套件通过,包含 402 个流式前缀和 268 次缓存复用 |
|
||||
| `npm run test:chat`、`npm run test:persistence` | 消息/工具输出/状态与实际 IPC 到会话文件的持久化检查通过 |
|
||||
| 构建产物的离线浏览器 | 有效图表 ready、无效图表 error 后可看源码;zoom matrix 改变;主题切换;SVG 与 PNG 导出 payload(PNG 有正确文件头);第二张图片直接打开为 2/2,缩放/旋转/镜像、键盘切换重置、下载、Escape;行内路径及代码标题打开文件并高亮 4–7 行;目录项可打开文件 |
|
||||
| 默认 1280×720 / 960×640 | 无页面横向溢出;小窗口图表框 594px,图片预览索引正确;测试后恢复窗口尺寸 |
|
||||
|
||||
离线 fixture 为 `scripts/fixtures/dialogue-media.mjs`,假桥不请求模型、不读写用户会话。浏览器下载验证的是导出内容送达桥接的结果,native dialog 并未由浏览器调用;实际文件写入另由 IPC 回归测试覆盖。没有重启正在运行的 WorkBuddy 或 YCode 原生窗口。
|
||||
|
||||
截图:`.tmp/dialogue-media-2026-10-15.png`、`.tmp/dialogue-image-preview-2026-10-15.png`,均是自有构建产物,不能当作原版对照图。
|
||||
|
||||
## 尚需继续
|
||||
|
||||
原版像素采集仍受 REA `target_not_allowed` 限制,尚无并排像素验收。Mermaid 采用固定 11.17.2、svg-pan-zoom 3.6.2,原版这两个依赖的精确版本未知;Mermaid eager/lazy 的原版配置默认值未取得,当前默认 lazy。图标、tooltip、主题 CSS、native 文件编辑/符号跳转、URL 列表查看器仍有适配差异,observer 时序只验证了实现与可见渲染结果,没有测量毫秒级一致性。
|
||||
|
||||
敏感信息投影、全部工具/审批/产物状态及完整对话交互仍需补齐。OMP 真实 ready/重启上下文尚未通过,沿用前轮结论。以上已实现与验证范围不能用来宣称对话区域或整个应用已经 1:1 完成。
|
||||
@@ -0,0 +1,90 @@
|
||||
# 对话区模型选择器:源码级恢复与验收(2026-10-16)
|
||||
|
||||
对话区的模型列表已从 YCode 自写下拉换成 REA 恢复的 WorkBuddy 5.8.2 当前 cr `ModelSelector`。原版触发按钮、Popover、列表、分组、子菜单与键盘行为由恢复体自身所有,YCode 只提供模型目录并执行真实写入。已构建并更新用户 YCode;实窗停在原会话、选中 `gpt-6-luna`、草稿为空。
|
||||
|
||||
## 原版来源
|
||||
|
||||
WorkBuddy 5.8.2,安装包根 SHA-256 `035254bc76310ea46317433e4840602094543ef323d2d5c5aff7c131729de918`。全部原版脚本、CSS 与画面经 REA 固定导出读取,未直接访问原版文件系统,未运行原 bundle。
|
||||
|
||||
| 证据 | 内容 |
|
||||
| --- | --- |
|
||||
| `ev_717fa5e846e64d67ac19c8925d121bff632c0d3aefb3603b10858559cabb2dcb` | 固定运行脚本,`.tmp/rea-runtime-scripts.json` |
|
||||
| `ev_377c8790468b3c67dad8577aabb327f98d3140659f0fffdbabfcff5a40cc9e94` | 固定 CSS 与 token,`.tmp/rea-css-recovered/` |
|
||||
| `ev_1c3853a9a4dd6f99cf76d1874ad57af7ad6fb56c33e6b4e5c2a2e770f91f462e` | 1336×901 原版模型菜单展开态:触发按钮计算样式、340×368 菜单、选中行 |
|
||||
| `ev_330f3e738f84f51e0bc5beb5a2ee5647a8bd567407048d1ff239384929ba324f` | 同版本第二次触发按钮计算样式(用于交叉核对) |
|
||||
|
||||
关键源 SHA-256:`src-DbE1_mgM.js`(对话面板 chunk)`6c6ce63c93854783270e855572797d75e536e3b8d4548410e31fe9d147e1feb4`;`src-DPDj7_qD.js`(WB 原语)`747e41d215375e1214c366213aea7e077d85421923029c61cbb6e9562be58de0`;`src-CyXHA0IC.css` `a5e26b537bb50323aefbf25abddad52e288dd3868598be8d255d70886fe77cfe`;`src-CBaV_A3S.css` `2090ed21045c8f8b0fc388d76424c8751bf18fcd065cbbd5d0ef485163a2e36c`;`src-Bh3YZ35H.css` `88dbdc1cd3f59d0e8b75824512a465a2be714bc7af481d790fe3a9484f85e01a`;`contexts-BkjwYSZT.css` `50cbd673f7f35fc7f966bdddc6c9f5677fdfe944cb904888d214619fca259380`。
|
||||
|
||||
## 恢复范围
|
||||
|
||||
`scripts/rea/recover-composer-model-selector.mjs` 从固定导出抽取 **192 个正文定义**(含 UTF-16 区间与 SHA)与 **7 份源文件**,写出 `source.mjs` / `source.d.mts` / `source.css` / `manifest.json`,并对 3665 处标识符引用做未绑定审计(0 处未解析)。`--check` 幂等通过。
|
||||
|
||||
恢复体包含:`ModelSelectorImpl`、`ModelSelectPopover`、`ModelSubMenu`、`ModelItem`、`ModelGroupMenuItem`、`ModelTierBadge`、`ModelBadge`、`OverflowTitleSpan`、`ReasoningEffortPanel`、`ContextWindowPanel`、`collectModelOptions`、`resolveSelectedModelId/Label`、`buildGroupedModels`、`getDefaultIsThinking`、`isReasoningConfigurable`、`formatCredits`、`formatContextWindow`、`getSupportedContextWindows`、`createModelSelection`、`resolveModelIcon` / `getModelIconByName` 及 14 个厂商图标、所需 Menu/MenuGroup/MenuItem/SubMenu/Popover/Tooltip/ScrollArea/WB Switch 原语。
|
||||
|
||||
**6 处宿主接缝**(逐条记于 manifest `adaptations`,不是自造组件):输入框 store/selector、渲染诊断 sink、cr 配置 Context(从约 250 KB 各语言表裁到 `prefixCls/mode/locale/t`)、FloatingUI 走宿主固定版本 `@floating-ui/react 0.27.20`、DOMPurify 走宿主 `3.4.17`(原包内嵌 3.4.11,sanitize 配置逐项保留)、`FloatingPortal` 主题包装。
|
||||
|
||||
文案取自 `src-DbE1_mgM.js` UTF-16 offset 172945 的 zh-CN locale 字面量,26 条 `chatInput.modelSelector.*` 逐条解码。复核确认解码结果全为简体(`思考强度`/`开启`/`极致`),恢复器早先注释称其为繁体有误,已更正。
|
||||
|
||||
## 生产接线
|
||||
|
||||
新增 `src/renderer/src/workbuddy/composer/model-selector/`:
|
||||
|
||||
- `SourceModelSelector.tsx`:把 YCode `CustomModelProfile[]` 映射为源 provider 契约,并实现真实 `onSelect` / `onManage`。恢复体一次选择会同时调用 store 与 host `onChange`,适配层只让 store 做投影、由 `onChange` 执行写入,避免重复提交。
|
||||
- `source-adapter.css`:唯一一处宿主适配。WorkBuddy 文档没有全局 `button` 字体重置,触发按钮沿用 UA 默认 Arial;YCode `app.css` 的 `button{font-family:inherit}` 会让标签继承 PingFang SC 并改变度量,因此用 `font-family:revert` 还原到 UA 默认,而不是写死某个平台字体。
|
||||
- 类别图标不再强行套 provider 图标:不传 `icon`/`iconUrl` 时恢复体按模型名走品牌图标表(与截图一致)。
|
||||
|
||||
**推理强度子菜单已接线**:源实现在 `supportsReasoning` 时显示思考开关与强度档位。YCode 侧新增可持久化的会话级 `thinkingLevel`(`off|low|medium|high|xhigh|max`,见 `src/shared/workspaces.ts`),主进程经 `session:create` / `session:update-context` 透传,OMP 回合在 `setHostTools` 之后调用内核 RPC `set_thinking_level`(每回合应用,无需重启内核)。适配层把模型档案映射为源 provider 契约的 `supportsReasoning` / `onlyReasoning` / `canDisableThinking` / `defaultEffort` / `supportedEfforts`,源组件自身的开关与档位面板负责交互,写入由 `onChange` 上报后落到会话上下文。写入链路已端到端验证;`set_thinking_level` 到模型的真实推理档位变化属 OMP 内核行为,本轮只核到命令接线与 OMP 自身支持,未做真实回合的档位效果比对。
|
||||
|
||||
适配层对强度做逐项校验而非直接 `??` 回退:模型从未设置默认强度时档案里是 `defaultEffort: ''`,空串既不是合法档位、也会被主进程拒绝,因此只有落在五档白名单内的值才参与回退,最终回退顺序是「本次上报值 → 模型默认 → 模型支持档位首项 → `high`」。开启思考时源实现不携带强度(强度保存在它自己的按模型偏好里),此时回退到模型默认档位;若解析结果与当前持久化值相同则短路,重选已选中的行仍是空操作。
|
||||
|
||||
共享 cr 样式还依赖三条 shell 规则,已一并恢复并记录:`.wb-icon` 的 flex 基线、`.wb-home-composer__input-slot [class*=icon]` 的 50% 圆角、`.wb-home-composer__input-slot .cr-input-toolbar` 的 `--cr-text-primary` 桥接。前两条按后代关系落到 scope;第三条目标在 composer 工具栏(scope 的祖先),按 `\.cr-input-toolbar .yc-source-model-selector` 保留原元素关系。另修正 CSS 过滤器:此前漏掉裸 `.cr-menu-item__icon/__content/__extra`,导致 footer 图标没有 16px 盒与 8px 右边距。
|
||||
|
||||
`dompurify` 原为 mermaid 的传递依赖,已显式声明为 `3.4.17` 根依赖。`package.json`/`package-lock.json` 相应更新;`npm install` 在本仓库因既有 vite 8 与 electron-vite peer 冲突失败,属于既有问题,未用 `--force` 绕过。
|
||||
|
||||
## 验证
|
||||
|
||||
| 检查 | 结果 |
|
||||
| --- | --- |
|
||||
| 恢复幂等 | `node scripts/rea/recover-composer-model-selector.mjs --check` → PASS(7 sources / 192 bodies / 0 未解析) |
|
||||
| 组件原生(隔离 Electron) | 73/73,`.tmp/model-selector-native-pTsrpd/report.json`:新增 1336×901/DPR1 打开态与 hover 态逐元素 bbox/计算样式采样,含 popover、菜单、滚动列表、全部模型行/图标/文本 Range、footer;截图为 `open.png` / `hovered.png` |
|
||||
| 触发按钮 108 项计算属性 | 对 `ev_1c3853a9…` 原版节点逐项比对,**0 差异** |
|
||||
| 真实应用 product flow 两阶段 | PASS,`.tmp/product-flows-0r0i1O/`:UI→preload→IPC→真实 OMP 创建/编辑模型、主界面选择与持久化、重启恢复 |
|
||||
| 真实应用推理强度写入 | 三连切换往返一致(`off → max → off → max` 落库),`.tmp/verify-live-thinking-write.mjs`;切换中会话与草稿均未变 |
|
||||
| 用户实窗 | 340×91 菜单、行高 32、选中 `gpt-6-luna`、Escape 关闭(150ms 退场后卸载)、会话与草稿未变 |
|
||||
|
||||
实窗检查发送 0 条消息、增删 0 个模型。进程替换后 PID 69300,原会话 `c261f03b-2efa-4816-b07f-9245f8f7e2c7` 恢复、草稿为空。
|
||||
|
||||
## 打开态逐属性核对(2026-10-16)
|
||||
|
||||
YCode 隔离 Electron fixture 已按原版视口 1336×901、`devicePixelRatio=1` 采样。每次运行会在 `.tmp/model-selector-native-*/report.json` 保存 `openState`、`hoverState` 的计算样式、元素框与文字 Range 框,并保存 `open.png` / `hovered.png`。这次报告是 `.tmp/model-selector-native-pTsrpd/`,73 项通过。恢复 CSS 与 token 的依据为 WorkBuddy 5.8.2 的 REA Evidence `ev_377c8790468b3c67dad8577aabb327f98d3140659f0fffdbabfcff5a40cc9e94`;既有开态截图帧来自 `ev_1c3853a9a4dd6f99cf76d1874ad57af7ad6fb56c33e6b4e5c2a2e770f91f462e` 的 visual probe(帧 SHA-256 `ee80b6f2aee823de4ed48f7d7788ad01be059bdde981d51428c19fc3878da991`)。
|
||||
|
||||
本轮尝试对当前 WorkBuddy 窗口取新开态证据时,REA `list_electron_targets` 对 `http://127.0.0.1:9223` 返回 `provider_unavailable / endpoint_unreachable`;REA 原生窗口观察与场景操作返回 `target_unavailable`。因此没有在 WorkBuddy 中执行点击,也没有改变其窗口状态。现存 Evidence 的 viewport 为 1336×901,配套截图像素也为 1336×901(DPR 1 是据此推断);但它的最终 layout 在点击 footer 后采集,模型菜单已关闭,只含触发按钮的节点样式。下面的“原版”列将 REA 恢复的 CSS/token 与此前截图几何分开标记;它不代表本轮在原版打开态下取到了逐节点的运行时 computed style。
|
||||
|
||||
| 属性 | WorkBuddy 5.8.2 的 REA 来源 | YCode 打开态 fixture | 差异与判定 |
|
||||
| --- | --- | --- | --- |
|
||||
| viewport / DPR | 截图与 CSS viewport 1336×901;DPR 1 由两者像素尺寸相同推断 | 1336×901,`devicePixelRatio=1` | 对齐 |
|
||||
| Popover 容器 / 菜单高度 | 既有开态截图记录菜单 `340×368px` | popover 与菜单实际 `340×193px`,`max-height:368px`,固定定位 `translate(981px, 265px)` | 实际内容高度不同;YCode 当前 4 个模型,没有补造行来凑高度 |
|
||||
| 菜单宽度 / 圆角 / 内衬 | 恢复 CSS:340px / 16px / 8px | 340px / 16px / 8px | 对齐恢复样式 |
|
||||
| 菜单底色 / 边框 / 阴影 | 恢复的 light token:白底、`#e6e6e6` 边框、`--wb-shadow-popover` 为黑色 4% 的两层阴影 | `rgb(255,255,255)`、1 device px 的 `rgb(230,230,230)`、相同的 4% 两层阴影 | YCode 计算结果符合恢复 token;原版 open-state computed 值仍待 REA 动态采集 |
|
||||
| 滚动列表 / 行 | 恢复 CSS:列表 gap 2px;行高32px、圆角8px、左右内衬8px | 列表 322×134px、gap 2px;4 行均 322×32px、圆角8px、左右8px | 几何样式符合恢复 CSS;行数是目录数据差异 |
|
||||
| 模型图标 / 标签 | 恢复 CSS:图标16px;标签14px/22px,当前项600字重 | 4 个图标均16×16px;标签均14px/22px,选中项600;文字 Range 高19px | 字体度量与恢复规则一致;每个文本宽度由本地模型名决定 |
|
||||
| Footer | 恢复 CSS:32px 行高、圆角8px、14px/22px文字、16px图标和8px右边距 | 322×32px;16×16px图标、margin-right 8px;文本 Range 98×19px | 对齐恢复样式 |
|
||||
| Hover | 恢复 CSS 使用 light `--cr-item-hover-bg`(`#f2f2f2`) | 悬停的选中思考模型行为 `rgb(242,242,242)` | YCode 与恢复 token 一致;当前 WorkBuddy 的真实 hover 样式尚未采到 |
|
||||
|
||||
这轮没有发现能由 YCode 样式修复的偏差,所以没有改动恢复 CSS 或宿主样式;新增的采样与断言用于锁住菜单表面、边框/阴影、内衬、文字度量、图标、footer 和 hover 色。与 WorkBuddy 的菜单高度、模型名称/图标宽度、渠道分组、徽标、倍率和繁忙状态差异来自目录数据,保持为数据差异,不填造模型元数据。要完成原版逐像素验收,还需要 REA 能访问当前 WorkBuddy renderer 的打开态与 hover 态,并在菜单打开时返回 `.cr-model-selector__popover`、`.cr-model-selector__menu`、`.cr-model-selector__list`、每个 `.cr-model-selector__item` 及其图标/文字、footer 的 bbox 与 computed style。
|
||||
|
||||
## 未完成
|
||||
|
||||
- **上下文窗口子菜单**:恢复体自身逻辑已就位(`getSupportedContextWindows` 过滤排序 + `ContextWindowPanel`),但它要求选项带 `supportedContextWindows` 且 ≥2 项才渲染该行;YCode 模型档案只有单个 `maxInputTokens`,属数据形态差异,单窗口模型在原版同样不出现该行。要真正提供可切换窗口,还需先决定自定义模型如何声明窗口集合,并确认 OMP 侧是否存在运行时切换通道(RPC 命令表里未见 context-window 设置项,ACP 侧是 `session/set_config_option`)。
|
||||
- **推理强度未做像素验收**:思考/强度面板的结构与行为已对齐(开关、档位列表、当前项标记、回调写入),但没有对原版该面板做逐像素计算属性比对,与触发按钮那 108 项同级的证据尚缺。
|
||||
- **分组与营销元数据**:YCode 模型目录是本地自定义模型,没有 WorkBuddy 的渠道分组、折扣/企业徽标、倍率与繁忙度;恢复体对这些字段的支持已就位,但当前目录不产生这些行。因此菜单行数与内容天然不同,这部分是数据差异而非样式差异。
|
||||
- **原版打开态像素**:YCode 侧现已采集打开态和 row hover 态逐元素数据;当前 WorkBuddy 的 REA target 不可达,缺少原版菜单每个节点的实时 bbox/computed style 与 hover 帧,因此还未完成两侧逐像素比较。
|
||||
- **暗色与动效全状态**:仅验证 marker 与 Escape 退场路径,未做全状态像素比对。
|
||||
|
||||
可复现:
|
||||
|
||||
```powershell
|
||||
node scripts/rea/recover-composer-model-selector.mjs --check
|
||||
node scripts/rea/test-model-selector-native.mjs
|
||||
node scripts/verify-product-flows.cjs
|
||||
```
|
||||
@@ -0,0 +1,43 @@
|
||||
# 对话启动提示文案恢复(2026-10-16)
|
||||
|
||||
## 结论
|
||||
|
||||
可以从现有 WorkBuddy 5.8.2 REA 源码证据中恢复启动提示,不需要重新采集。用户看到的“正在启动对话环境”在源文案中完整写作“正在启动对话运行环境…”。同一资源还包含其余准备阶段和云端启动文案。
|
||||
|
||||
## REA 证据
|
||||
|
||||
| 项目 | 记录 |
|
||||
| --- | --- |
|
||||
| Evidence ID | `ev_717fa5e846e64d67ac19c8925d121bff632c0d3aefb3603b10858559cabb2dcb` |
|
||||
| 版本 | WorkBuddy 5.8.2 |
|
||||
| 源文件 | `renderer/assets/contexts-BMeWSUHk.js` |
|
||||
| SHA-256 | `5f35b7489b107e21ef452c8ee88a95265756f6fc444841eef869228bbc44768b` |
|
||||
| 范围 | REA 留存的 renderer JavaScript 源码;静态字符串和渲染选择逻辑,不代表逐次运行时的阶段顺序或持续时间。 |
|
||||
|
||||
## 已恢复的中文文案
|
||||
|
||||
| 阶段键 | 文案 |
|
||||
| --- | --- |
|
||||
| `chat.prepare.expert` | 正在准备专家能力… |
|
||||
| `chat.prepare.reading_conversation_settings` | 正在读取对话设置… |
|
||||
| `chat.prepare.resolving_system_prompt` | 正在生成系统提示词… |
|
||||
| `chat.prepare.configuring_model_and_tools` | 正在配置模型与工具… |
|
||||
| `chat.prepare.resolving_skill_requirements` | 正在整理技能配置… |
|
||||
| `chat.prepare.resolving_plugin_requirements` | 正在整理插件配置… |
|
||||
| `chat.prepare.preparing_environment` | 正在准备运行环境… |
|
||||
| `chat.prepare.mcp` | 正在整理连接器配置… |
|
||||
| `chat.prepare.checking_launch_config` | 正在检查启动配置… |
|
||||
| `chat.prepare.acquiring_runtime` | 正在启动对话运行环境… |
|
||||
| `chat.initializingCloudEnvironment` | 正在初始化工作环境… |
|
||||
| `chat.awaitingCloudResponse` | 等待云端响应… |
|
||||
| `chat.loadingText` | 思考中 |
|
||||
|
||||
## 源码确认的显示逻辑
|
||||
|
||||
`resolveConversationPrepareText(stage, translate)` 通过 `chat.prepare.${stage}` 取得阶段文案。流式状态栏从会话的 `prepareStatus.stage` 读取阶段;在进入终态、失败/终止、非 idle agent 阶段或收到真实 MCP 启动进度后,准备阶段提示会被隐藏。云端 bootstrap 使用两个独立阶段:`initializing` 显示“正在初始化工作环境…”,`awaiting-response` 显示“等待云端响应…”。其他情况下回退到“思考中”。
|
||||
|
||||
这段 renderer 代码证明了文案映射和选择条件;阶段的实际发出方、每次启动走过哪些阶段、阶段先后及持续时长仍需其对应运行时事件证据,不能仅凭字符串表推断。现有证据已足以支持后续按相同阶段键接入 YCode,无需重新查看 WorkBuddy 5.8.2。
|
||||
|
||||
## 与流式提示的区别
|
||||
|
||||
“思考中”旁边的技巧提示是另一组内容。那组提示及其 4 秒延迟、10 秒轮换和悬停暂停逻辑已在[流式回复状态栏对齐](流式回复状态栏对齐-2026-10-16.md)中恢复并接入;本记录只补充新会话启动期间的阶段文案映射。
|
||||
@@ -0,0 +1,32 @@
|
||||
# 对话审批与消息投影续对齐(2026-10-15)
|
||||
|
||||
继续按 WorkBuddy 5.8.2 对话区 1:1 目标推进。本文记录本轮新增实现;完整对话区尚未通过全状态像素验收。云端服务和子代理调度按用户要求暂后。
|
||||
|
||||
## 原版证据
|
||||
|
||||
原版实现仍全部来自 REA。复用固定 Evidence `ev_717fa5e846e64d67ac19c8925d121bff632c0d3aefb3603b10858559cabb2dcb` 的主脚本 `src-DbE1_mgM.js`,SHA-256 `6c6ce63c93854783270e855572797d75e536e3b8d4548410e31fe9d147e1feb4`。本轮只处理已保存的 REA 正文,没有绕过 REA 读取安装包或原版运行时。
|
||||
|
||||
## 已接入
|
||||
|
||||
- 恢复现代中文/英文词典各 971 键,AST 复核实际 locale map `zh-CN → ut`、`en-US → it`,默认 `zh-CN`。纠正此前“现代中文 key 不在采集产物中”的判断:中文在主脚本中以 Unicode 转义存在。写文件、命令、读取、文件搜索、网页、MCP、待办等已接入对应源文案。
|
||||
- 写文件审批使用源工具卡片内“接受 / 拒绝”,命令使用“运行 / 跳过 / 拒绝”,顺序、按钮 variant、提示文本和 pending gate 按源码恢复。工具 ID 绑定真实审批请求;展示层将待审批执行记录投影为 pending,不改存储执行态;有明确 once 选项时优先使用,绝不将接受映射到 allow_always。
|
||||
- 审批走既有 `onRespond → chat store → IPC`;responding 时禁用按钮,错误可重试。已绑定卡片不再重复渲染通用审批框,缺绑定、缺选项或不支持的工具保留通用入口。
|
||||
- 将原先“仅相邻工具”的分组改为源 foldable 连续组,包括 reasoning 与普通工具;至少两项才形成 summary。运行中仅折叠后面已有正文的组,尾部过程保持展开,终态再折叠。
|
||||
- 恢复 show-widget 与前一未关联正文的 presentation 关联、并列最长正文和末段锚点、queue-guidance 边界以及 widget 移动次序。未知的 YCode 专有 part 保留明确适配,不称完整原版消息类型覆盖。
|
||||
- 工具分组使用源 summary variant 和 4px 子项间距。折叠内容保持挂载并设置 aria-hidden/inert,使源高度/透明度过渡能实际生效。
|
||||
- 过程摘要恢复为原版 27 个纯函数、40 类 descriptor 及其 alias/canonical map,覆盖状态、对象压缩、相邻正文 topic 和中文模板。真实消息分组已使用恢复模块,不再以“几个工具调用”代替源摘要。恢复文件摘要 `645ea0848880aa7e89319af8e11440bdddd8c10783944736fd4f29b70e923a10`,源/生成 manifest 随模块保存。
|
||||
- 复核 ReadFileView/WriteFileView 后,移除原版不存在的额外结果 `<pre>` 和写文件错误展开区;读取全文仍保留在文件打开 adapter,错误按源头部图标体现。
|
||||
- 修复样式恢复器的实际错误:原先 `walkRules → output.append(rule.clone())` 丢失 at-rule 祖先,使 `prefers-reduced-motion:reduce` 的 `transition:none` 变成全局,关闭普通工具动画。改为递归投影保留 media/support 条件,并从固定 REA CSS 重生成。`test:tool-styles` 直接比较原版与投影后的 shell 规则、声明、条件和顺序,锁住三个 reduce-only 分支,防止回归。
|
||||
- 截图复核发现工具按钮 family 未纳入选取,已补六条原版 `.cr-tool-btn` 规则,包含 primary/danger 和 hover;验收高度 20px、min-width 52px、字号 12px、横向 padding 10px、绿色/红色/中性背景。summary 按原版保留所有成员,取消旧的 15 项分页适配。
|
||||
|
||||
## 验证范围与限制
|
||||
|
||||
`test:conversation`、`test:tool-approvals`、`test:modern-conversation-labels`、`test:fold-summary`、`test:artifacts`、`test:chat`、`test:conversation-ipc` 已通过。审批专测覆盖 metadata gate、按钮顺序/样式、禁用态、精确请求绑定及 allow_once 优先级。摘要专测覆盖 descriptor aliases、路径对象、命令不使用执行串作对象、等待/运行/回退、相邻正文 topic,常规对话测试也执行真实源中文摘要。
|
||||
|
||||
审批传输目前只有 `optionId`。命令“跳过”和“拒绝”在 UI 是独立操作,现有适配均发送 reject_once;原版 host 区分 skip/cancel 的后续语义尚未接入,不能称功能全等。`defaultExpanded` 按原版仅用于首次挂载,迟到的审批不会强制重开用户已折叠的命令卡片。
|
||||
|
||||
最终 `npm run build`(含 typecheck)、`test:tool-styles`、`verify:conversation-states` 已通过。真实 Electron fixture 的事件流验证:流式写入自动展开/成功收起、手动折叠不被同位置更新重开、用户上滚后停止跟随/回到底部恢复、命令运行/失败/空成功/取消、审批失败重试/防重复/once 优先/不同请求互不替代。控制台错误 0。
|
||||
|
||||
显式 no-preference 下普通工具实测 `height 0.28s cubic-bezier(0.33,1,0.68,1)`,收起到 0px;大文件与显式 reduce 均为 `transition:none`。报告 `.tmp/conversation-states-ui-report.json`,YCode fixture 截图 `.tmp/conversation-command-approval-2026-10-15.png`、`.tmp/conversation-file-approval-2026-10-15.png`。这些是自有 UI/fixture bridge 的实际验证,不证明真实 WorkBuddy host IPC 或全状态像素等价。
|
||||
|
||||
已有字体和局部像素结果见《原版实测与像素对齐》:第一正文段落 39,909 像素零差异,气泡 22 个圆角像素最大通道差 1;该结果仅属于所声明的画面区域,不能外推本轮所有工具状态。剩余仍包括所有专用视图/附件分支的相同原版状态对照、完整消息类型映射、全部实际字体样本与动效中断/逐帧像素验收。
|
||||
@@ -0,0 +1,59 @@
|
||||
# 对话样式与调试画面采集(2026-10-15)
|
||||
|
||||
本轮先补齐 REA 的画面、布局和 SVG 采集,再把取得的原版 CSS 与组件结构接入 YCode。工作范围为对话区域样式,云端服务和子代理调度按用户要求暂后。
|
||||
|
||||
## 原版证据与能力
|
||||
|
||||
- WorkBuddy 5.8.2 / Electron 37.10.3 / Chrome 138.0.7204.251;沿用调试端口 9223,唯一选定原版 renderer 文件页面。
|
||||
- 本地 REA 副本版本 `6.5.0-visual.1`,新增 `include_visuals`,默认关闭。公开入口 `npm run rea:visual:capture` 同时请求已加载 CSS 正文、PNG、计算样式及 SVG 几何属性。
|
||||
- 原版画面 Evidence:`ev_dbd7b4f6304305b0428d19c891088806a09d05b33a1b69d7e7df95e22f3914f4`,归档 `.tmp/rea-css-evidence/<Evidence ID>.json`;导出 `.tmp/rea-visual-reference/workbuddy.png` 和 `layout.json`。
|
||||
- 实际取得 1336×901 画面、828 个布局记录、189 个 SVG 节点(73 个 SVG 根)。布局记录含 27 个计算样式属性、节点关系和边界;不保留聊天正文和输入值。PNG 自身含原版当前可见对话,保留在本地。
|
||||
- 采集由 REA provider 内部执行 `Page.getLayoutMetrics`、`DOMSnapshot.captureSnapshot`、`Page.captureScreenshot`;包装脚本只调用公开 REA CLI。没有导航、点击、重载原版或执行 renderer JavaScript,没有绕过 REA。
|
||||
- 使用 view capture(`fromSurface:false`);surface capture 曾超时。采集有 30 秒超时。布局与截图是先后采样,不是原子快照,范围限当前可见页面,不代表全部交互状态。
|
||||
|
||||
CSS 沿用已校验的固定 Evidence `ev_377c8790468b3c67dad8577aabb327f98d3140659f0fffdbabfcff5a40cc9e94`。64 份正文共 5,946,566 字节;13 份匹配既有 ASAR 清单、2 份有差异,详情见 [CSS 采集修复](REA-CSS采集修复-2026-10-15.md)。生成器检查固定 Evidence、SHA 和选择器;不会把运行时正文冒称为与安装包逐字节相同。
|
||||
|
||||
## 已接入的变化
|
||||
|
||||
- 消息区域接回 `conversation-timeline`、`cr-message-list`、`cr-document` 和原版左右消息 frame 层级;限定 832px 列宽。用户气泡使用原版内容容器、段落样式和动作行定位。
|
||||
- `source-styles.css` 从三个已采集 CSS 文件选择 389 条规则,覆盖主题、消息 frame、助手/用户内容、思考折叠、工具展开、计划、审批和消息动作。保留相关条件规则及动画 keyframe;只映射选择器和宿主结构,规则正文沿用原版。
|
||||
- 思考与单个工具的展开内容保留在 DOM,通过原版 shell 的折叠样式切换,并为关闭区域补 `aria-hidden` 和 `inert`。计划接回标题、任务列表及状态图标的原版层级。
|
||||
- 输入区接回原版 24px 外层留白、编辑区、56px 工具栏、24px 容器圆角、边框、阴影及禁用状态;按钮顺序为添加、权限,右侧为模型、语音、发送。对话页移除额外工作目录 footer,目录设置仍可由顶部设置进入;首页保留该入口。
|
||||
- 问答浮层由 bundle 的 `ggdxn` CSS module 映射,共 79 条投影规则,恢复标题、分页、选项、复选框、自定义回答和 footer;放入 `conversation-input-area__custom-floating`,与输入框共用左右留白。选项恢复为原版 `div role="button"`,消除原生 button 默认居中;保留 Enter/空格激活,并用 `aria-pressed` 表达本地选中状态。
|
||||
- 消息动作使用源图标;发送、麦克风、权限和当前重新生成图标由 REA 画面采集中的实际 SVG 节点恢复。问答图标取自该组件真实引用的定义,保留 Evidence、源摘要和 UTF-16 范围。
|
||||
- 任务卡恢复 `TaskToolRenderer` 的 root/result/item/title/content 层级、默认展开状态和 40 条原版规则。清除 22 组旧 Task 选择器,避免旧 root 边框、子 span 的 12px/600 字重覆盖;键盘折叠与现有审批回调保留。该工作仅涉及卡片 UI。
|
||||
- 审批选项箭头恢复实际 `yo → pl → uc → lc` 图标绑定及 16px 默认尺寸,替换文字 `>`。源码为 `contexts-BMeWSUHk.js` 和 `src-DPDj7_qD.js`,恢复器校验固定 runtime Evidence、两份 SHA、调用与导出关系。
|
||||
- 命令视图定位到 `src-DbE1_mgM.js` 的 `ExecuteCommandView`(UTF-16 offset 1035987)及动态 `cr-` 前缀。命令标题、命令和合并 stdout/stderr 使用原版 div 结构及单色字体、换行、行高;本地包装用 `display:contents` 投射为原版内容容器的 flex 布局,消除旧 pre 背景和内边距。现有完整输出入口及 exit-code 提示保留,仍有结构扩展,未声称整体等价。
|
||||
- 六档字体控制继续生效。原版 Slate 编辑区声明投射到现有 textarea;没有伪造 Slate 编辑器。现有 textarea 的 200px 高度上限保留,原版长输入上限仍未实测。
|
||||
|
||||
生成入口:
|
||||
|
||||
```powershell
|
||||
npm run recover:conversation-styles
|
||||
npm run recover:conversation-icons
|
||||
node scripts/rea/recover-question-icons.mjs
|
||||
```
|
||||
|
||||
上述生成器只处理既有 REA 导出。不要直接以更新后的“最新证据”别名覆盖固定 CSS manifest;需要更换基线时先复核生成器引用及差异。
|
||||
|
||||
## 验证与验收边界
|
||||
|
||||
同为 1336×901、默认字号,在 YCode 本地 fixture 读取浏览器最终计算值,与 REA 原版记录逐项比较:**28 项选定属性一致**。包含列宽与内边距、助手标题间距、用户气泡字体/行高/圆角/背景、输入框边框与阴影、编辑区留白、工具栏留白与间距、语音按钮圆角。报告 `.tmp/conversation-style-metrics.json` 同时保存预期值、实际值及节点尺寸。
|
||||
|
||||
助手名称、助手内容、文本块、用户气泡、输入宿主的 **5 个计算字体族字符串一致**,记录 `.tmp/conversation-style-font-metrics.json`。这不证明各 fallback 实际使用了相同字体文件,也不替代文字像素对照。
|
||||
|
||||
这次比较使用不同消息内容,是属性与几何抽查,**不能当作同状态的全图像素差通过**。原版当前画面没有问答、审批等全部状态;这些状态采用源 CSS/组件证据与本地交互回归,尚待原版同状态画面对照。
|
||||
|
||||
本轮 `npm run build`、样式及图标来源校验、`test:conversation`、`test:artifacts`、`test:font-size`(57 项断言)和 `test:rea-css` 均通过。浏览器验证了思考展开与收起、工具组/单项工具/完整输出展开、问答提交后继续、审批后继续、字号调整和长输入。长输入实测高度 200px、内容 scrollHeight 525px。
|
||||
|
||||
中断后恢复本地预览服务,另用独立的隐藏 Electron 测试窗口复验最终构建:仅加载 YCode localhost fixture,通过真实键盘事件选择第二个问答选项,确认回答被提交且回合继续;再确认审批后继续。控制台错误 0。问答浮层与输入框实测同为 784px、x=416,选项高 40px,文字 `text-align:start`。该验证不连接 WorkBuddy,不执行真实模型或文件写入。记录 `.tmp/conversation-style-final-ui.json`;可复验脚本 `.tmp/verify-conversation-style-final.cjs`。
|
||||
|
||||
续验还确认任务标题高 32px、行高 16px、字重 500、root 没有多余边框,键盘 Enter 可折叠并重新展开;工具组标题恢复 15px。命令头显示实际命令,命令/输出节点为 div,输出行高 18px、内边距 0、背景透明,测试输出完整保留。
|
||||
|
||||
最终截图 `.tmp/conversation-style-aligned-2026-10-15.png`(为展示完整消息,将任务卡收起并滚到消息顶部;该卡原版默认展开已独立验证);问答状态截图 `.tmp/conversation-question-aligned-2026-10-15.png`。截图在有限动画完成及实际 paint 后保存,并已人工查看。
|
||||
|
||||
仍未完整验收的样式范围包括:各类工具专用结果 renderer、任务详情卡、附件与产物详情、所有 hover/焦点/错误/流式状态、深色和不同字号的原版同状态画面、动效逐帧及长列表虚拟化。YCode 名称和当前测试消息不是原版内容;原生富文本编辑器行为尚未等价。后续应按状态补对照,不能据此次 28 项抽查宣称对话区已全量 1:1。
|
||||
|
||||
其中一项已定位的具体结构差异:同一 runtime 脚本的 `ReadFileView`(offset 1081144)返回 header-only 的 `ToolHeader`,以文件名链接和行号展示、发出 `tool.file.open`;YCode 仍在可展开卡片内显示文件正文。文件读取不是“CSS 无法取得”,需要继续接回共享 ToolHeader 结构,同时保留当前完整输出与文件打开契约。Web/MCP、文件列表等正文也没有因套入通用工具容器就完成验收。
|
||||
|
||||
全局 REA、注册配置及原版文件未修改;本地修复 manifest 记录 12 个变更模块并验证对应全局文件摘要保持不变。
|
||||
@@ -0,0 +1,109 @@
|
||||
# YCode 接手状态(2026-10-15)
|
||||
|
||||
> 2026-10-17 用户新增 20 项对话、侧栏和设置对齐要求,已建立后续主清单:[复刻待办清单](复刻待办清单-2026-10-17.md)。本轮仅记录 TODO,尚未开展对应的新 REA 采集和实现;编号与用户原始问题一致,记忆与进化、安装中心、定时任务、资料库、更多中的项目保留待拆解。后续逐项记录证据、实现与验收,不能仅凭构建通过勾选完成。
|
||||
|
||||
> 2026-10-16 工具动作标题线上复核:此前截图取自 23:12 的旧构建;23:35 启动的旧调试进程仍占用 9237,导致先前重启检查没有连到新构建。重新构建并清理旧调试进程后,以 PID 86372 在 9237 启动最新版本;重新打开原来没有 `intent` 的真实会话 `2f93304e-a8d6-40ab-96d4-9e4b45511352` 并展开,DOM 与截图均显示 `List contents of src directory`、`Read file ... (lines ...)` 等动作标题。验证截图:`.tmp/ycode-tool-intent-session-2f-expanded.png`。`npm run test:conversation` 与 `npm run build` 通过。当前这项修复仅验证到历史工具记录和静态回归;流式进行中的视觉刷新仍由既有工具事件回归覆盖,未在本轮真实模型请求中复测。
|
||||
|
||||
> 2026-10-16 过程消息显示对照:用户提供的 YCode“看一下当前项目”内层展开截图,与 WorkBuddy 5.8.2 的 REA 原版截图显示相同的组织方式——已完成回合中按序展示“深度思考”、普通工具项和回复正文。静态源代码证据确认 reasoning 与普通工具可共同进入过程折叠;这不是同任务的逐像素对照,尚不能标记 1:1 完成。详见[过程消息展开与思考项对齐](过程消息展开与思考项对齐-2026-10-16.md)。
|
||||
|
||||
> 对话启动提示文案已从 WorkBuddy 5.8.2 的现有 REA 证据恢复:10 个准备阶段、2 个云端 bootstrap 阶段和“思考中”回退;原版状态栏读取会话阶段选择文案,阶段顺序/时长尚未由运行时事件证明。无需重新采集已有源码。详见[启动提示文案恢复](对话启动提示文案-2026-10-16.md)。
|
||||
|
||||
> 最新流式状态栏(2026-10-16):REA 恢复的 WorkBuddy `StreamingFooter` 已接入每个 `streaming` 回复,正文开始输出后仍持续显示扫光“思考中”;源提示按 4 秒延迟、10 秒轮换并在悬停时暂停,空正文旧光标已移除。加载提示和对应 CSS 均由 REA 固定 Evidence 导出生成,费用缺少真实数据所以不显示;完成态继续显示消息冻结模型名。`test:conversation`、`test:assistant-footer`、`typecheck`、`build` 均通过。源脚本来自 WorkBuddy 5.8.2,而当前 WorkBuddy 为 5.8.3;当前版本流式画面/计算样式仍未取到,另有一份运行时 CSS 与 ASAR 摘要不一致,故还不能标为逐像素完成。见[流式回复状态栏对齐](流式回复状态栏对齐-2026-10-16.md)。
|
||||
|
||||
> 最新模型选择器(2026-10-16):对话区模型列表已换成 REA 恢复的 WorkBuddy 当前 cr `ModelSelector`(192 个正文定义 / 7 份源文件,`--check` 幂等,0 处未解析引用)。触发按钮 108 项计算属性与原版证据逐项比对为 0 差异;组件原生 49/49、真实应用 product flow 两阶段通过,已更新用户 YCode 并保留原会话。**推理强度子菜单本轮已接线**:新增会话级 `thinkingLevel`(`off|low|medium|high|xhigh|max`)并贯通到 OMP 内核 RPC,真实应用三连切换往返落库一致;过程中修掉一个真实缺陷——模型未设默认强度时档案里是 `defaultEffort: ''`,空串会被主进程判为非法强度而拒绝写入,现已改为逐项白名单回退并加了回归用例。上下文窗口子菜单仍未接(OMP 无运行时切换命令,需先决定自定义模型如何声明窗口集合),渠道分组/营销徽标属数据差异,打开态像素、推理面板像素与暗色全状态未验收。见[对话区模型选择器对齐](对话区模型选择器对齐-2026-10-16.md)。
|
||||
|
||||
> 最新加号菜单(2026-10-16):已接 REA 当前 cr AddMenu/Popover/SubMenu 与文件/模式/引用/连接器视图,专家/技能嵌入悬停侧层;保留父菜单、120ms 延迟关闭和源搜索行为。模式持久化并接实际 OMP/备用内核工具限制,引用来自真实空间根目录,技能本地导入/MCP 回调可用。修复浮层背景变量丢失及深色条件覆盖浅色 token;最终完整应用73项、用户实际窗口25项通过,已更新并保留原会话/草稿。当前 cr 专家/技能全部内容、云入口、递归引用与全状态像素尚未完成,详见[本轮实施与验收](加号菜单交互对齐-2026-10-16.md)。
|
||||
|
||||
> 最新专家使用逻辑(2026-10-16):召唤/选择共享已验证激活,输入框“召唤更多”按owner回原会话;保护用户草稿、替换未编辑预填、区分首页/会话移除、处理重复选择与异步竞态。原ExpertChip头像职业标签已接工具栏;Agent YAML决定技能预加载,PM/UI改为按需目录。状态50项、完整实际OMP localhost应用61项、picker42项、chip38项、四包370项通过;用户应用已更新。系统层角色/maxTurns/原CLI Agent生命周期仍未对齐,详见[本轮实施与验收](专家使用逻辑对齐-2026-10-16.md)。
|
||||
|
||||
> 最新原版专家迁移(2026-10-16):首席C++架构顾问、关德豪、像素君、小算四份完整功能包已通过REA恢复并安装到用户YCode,共255原文件/197文本资源,54字体/四张原头像。356项独立检查与真实用户应用四次鼠标召唤通过;用户app已更新并打开“我的专家”。新增16MiB专家包预算、扩展模板/C#/XML/Shell资源与保留BOM;依赖和原包缺失项见[四位专家迁入记录](四位专家迁入YCode-2026-10-16.md)。所有专项工具实际执行和完整1:1仍未验收。
|
||||
|
||||
> 最新专家实施(2026-10-16):原 expert-manager 11 份源码资源、创建/修改提示词、My Experts 卡片/删除框及专家选择器已恢复并接真实本地包注册、编辑、会话激活与逐消息身份快照。最终 UI→实际 OMP→localhost 创建/召唤/编辑/重启及首发 preflight 草稿保留 51/51,通过独立后端73项、快照事务15项、卡片34项、选择器39项;最终构建已更新用户 YCode 并恢复原会话。原生 agent/plugin 切换、头像生成、右侧专家产物自动预览及全状态像素仍待对齐。详见 [专家本地创建与激活](专家本地创建与激活-2026-10-16.md)。下方“专家包创建/激活未完成”是上一轮历史。
|
||||
|
||||
> 能力中心已进入生产实现(2026-10-16):侧栏三页入口、本地技能导入/启停/覆盖/卸载/资源读取、自定义 MCP JSON 管理与真实 stdio/HTTP 工具运行、技能输入引用及 OMP/备用内核接线已实现。完整应用两轮工具调用及新进程恢复通过;最终构建已更新用户 YCode,并保留原会话/模型。源几何33项、本地技能59+37项、MCP后端45项等通过,但专家包创建/激活、第三方授权、在线目录与全状态像素仍未完成。见 [实施与最终验收](能力中心与本地能力接入-2026-10-16.md)。下方“仅分析/入口占位”是上一轮历史。
|
||||
|
||||
> 专家/技能/连接器拆解(2026-10-16):已通过REA补原版市场、我的专家、已安装技能、添加菜单、连接器详情及MCP管理画面,核对源码/宿主接口;形成 [总拆解](专家技能连接器拆解-2026-10-16.md) 及三份子模块评估。此轮仅分析,YCode该入口仍是占位;没有安装、启用、授权或修改生产代码。原版取证结束已返回首页。
|
||||
|
||||
> 最新真实对话验收(2026-10-16):当前用户 `gpt-6-luna` 的完整 `/v1/responses` 已兼容连接测试、OMP 与备用 Gateway;真实远程上游两轮回复、上下文回忆及磁盘保存通过,已返回用户原会话。原“远程 API 拒绝连接”只代表旧配置,不再是当前阻碍。详见 [验收记录](Responses协议与真实对话验收-2026-10-16.md)。UI 全状态1:1仍未完成。
|
||||
|
||||
> 当前实施进度:[持续复刻进度(2026-10-16)](长任务进度-2026-10-16.md)。模型修改/空间创建/对话真实链路与右栏浏览器/ConPTY已接入;受控上游整应用及重启通过,右栏66项、原版只读Monaco21项原生集成通过。模型下拉、直接添加入口、头像、表格及产物footer继续按REA原体恢复。当前真实供应商两轮对话已通过;Responses集成28项、备用Gateway30项及旧Chat实际OMP22项通过。全UI 1:1尚未验收,后面的“本轮只评估”等是历史状态。
|
||||
|
||||
> 历史任务评估:[1:1 长任务评估(2026-10-16)](1比1长任务评估-2026-10-16.md)。其中“本轮只评估”已由上方持续实施状态取代;保留当时观察和任务拆分作参照。
|
||||
|
||||
> 当前最新:[对话审批与消息投影续对齐](对话审批与消息投影续对齐-2026-10-15.md)。现代中英文词典、工具卡片内审批、reasoning/工具混合分组、源过程摘要已接入;补全真实消息事件的状态回归。1:1 全状态像素验收尚未完成。
|
||||
|
||||
> 当前最新:[原版实测与像素对齐](原版实测与像素对齐-2026-10-15.md)。原版调试入口已经 REA 恢复;行内代码字号、工具 SVG、完成/过程折叠与耗时、Pierre Diff 已接入。四类实际字体样本匹配;按原版软件渲染环境校准后,第一正文段落 39,909 像素零差异,气泡剩 22 个圆角像素各差 1。完整 1:1 尚未通过。旧文档“原版调试不可达”和 Monaco Diff 假设已过时。
|
||||
|
||||
> 当前最新:[对话区四项对接](对话区四项对接-2026-10-15.md)。工具专用视图与附件预览已继续接入固定 REA 源码/样式;REA 字体、连续 PNG、原生输入和恢复通路已通过隔离 Electron 实测。原版当前调试端口不可达,尚无新增原版 glyph 或全状态像素验收结论。
|
||||
|
||||
> 当前最新:[对话样式与调试画面采集](对话样式实对齐-2026-10-15.md)。本地 REA 已补 PNG、计算布局与 SVG 采集;原版 CSS 已实际接入消息、输入区、问答等组件。28 项选定计算属性一致,仍未通过全状态像素验收。云端服务与子代理调度按用户最新要求暂后。
|
||||
|
||||
> 最新采集进展:[REA CSS 采集修复](REA-CSS采集修复-2026-10-15.md)。当前已实际取得 64 份加载中的样式正文;后续使用 `npm run rea:css:capture`,仍全部经 REA。全局 REA MCP 未修改,正文入口在本地修复副本。
|
||||
|
||||
> 本文保留接手时的历史基线。最新实现、证据和限制见 [源码级续对齐](源码级续对齐-2026-10-15.md)、[对话区域八类对齐](对话区域-八类对齐-2026-10-15.md)、[统一字体与间距](统一字体与间距-2026-10-15.md)、[图表、图片与文件](对话区域-图表图片文件-2026-10-15.md)。下文“纯文本”“--no-session”等描述不代表最新源码。
|
||||
|
||||
## 目标与现行约束
|
||||
|
||||
可行性重新评估见 `1比1复刻重新评估-2026-10-15.md`:接受 1:1 目标不等于已证明全量可行;客户端可逐项严格验收,云端、原生与模型逐次结果有独立条件及未知项。
|
||||
|
||||
用户明确要求:借助 REA,1:1 复刻 WorkBuddy;所有查看原版实现的工作使用 REA。
|
||||
该要求覆盖视觉、交互和功能。历史文档中的 L4 不做、商业入口不做、用直接 CDP 绕过 REA 等条款不再作为缩减范围的依据。
|
||||
跨机器字体、宿主环境差异是需要控制的验收条件,不能用来提前宣称通过或排除功能。
|
||||
|
||||
当前目录没有 Git 元数据;接手时不重置、不覆盖 WorkBuddy 已有成果。
|
||||
|
||||
## WorkBuddy 任务交接
|
||||
|
||||
- 会话:`4653e36f-6b2a-446f-a9c9-3f2d2d04644e`,当前标题“开始新会话”,旧标题“探讨agent循环与腾讯沙盒”。
|
||||
- 10:46 的回复报告 OMP 文本和工具通路打通;这是前任自报,尚不代表原版行为一致。
|
||||
- 10:53 用户要求开始处理,后续集中在取消链路。
|
||||
- 11:04:33 定位 `ipc.ts` 无条件覆盖 `assistant.status = 'done'`,已将 OMP 分支改为采用返回终态。
|
||||
- 最后一项工具结果在 11:08:24,11:10:56 显示“Interrupted by user”。没有最终取消验收结论。
|
||||
- 接手检查发现 `runOmpTurn` 的常规结束路径未执行监听清理,且部分错误分支 reject 的是结果对象而非 Error;本轮修复并补回归验证。
|
||||
|
||||
## REA 原版基线
|
||||
|
||||
2026-10-15 11:13(北京时间)通过 REA 连接既有端口 `http://127.0.0.1:9223`,未重启、导航或点击原版。
|
||||
|
||||
| 项目 | 观察与范围 | Evidence |
|
||||
| --- | --- | --- |
|
||||
| 目标识别 | 当前端口为 WorkBuddy 5.8.2 / Electron 37.10.3 / Chrome 138.0.7204.251;目标是 `Programs/WorkBuddy/resources/app.asar/renderer/index.html` | `ev_161879543f20fc822f7fcc7bff3351b63dbd129f9b649d33958357e1fc315423` |
|
||||
| 被动页面观察 | 1872 个 DOM 节点,339 个脚本记录;未选择脚本正文,有资源范围过滤,未观察历史执行过程 | `ev_07b84c62b706541456e7415ae6d886bc0b3e8e98f1fbf3456e29ba12cb46db9b` |
|
||||
| 安装包身份/清单 | ASAR SHA-256 `035254bc76310ea46317433e4840602094543ef323d2d5c5aff7c131729de918`;仅选择 `package.json`,没有解析业务 JS,完整应用行为仍未知 | 父记录 `ev_df8468f8f31100525395ec493367a16770371db119cce47ca3ce19aacfd89eb7`;摘要 `ev_7664214bd3a9f3a37c1b95cc9d1807839dd676ed3527081b395a56564e9b98fd` |
|
||||
|
||||
旧报告“REA 不能观察 file:// 页面”已过时;当前 `list_electron_targets` / `inspect_electron_page` 可用。
|
||||
原版安装包首次静态分析因 unpacked `cli/bin/native/win32-x64/job-object.node` 的声明摘要与实物不符被拒绝。
|
||||
后续用 REA `integrity_policy: record-and-continue` 保留矛盾继续分析;不能将完整性不符推断成原版功能或故障原因。
|
||||
本轮完整 REA 记录已导出到 `.tmp/rea-workbuddy-takeover-2026-10-15.json`(4 条记录,约 200 MiB);保留本地供后续按证据 ID 分页读取,不要整包注入上下文。
|
||||
八个 `scripts/wb-*.mjs` 历史采集入口已加统一阻断,在连接原版前终止,避免误用旧 SOP;原始脚本内容保留。
|
||||
|
||||
## 真实完成度
|
||||
|
||||
- 已有:Electron/React 桌面壳、CSS token/六档字号、会话 JSON 存储、文本流、基础工具卡、侧栏/设置外观、OMP sidecar 与旧循环回退路径。
|
||||
- OMP 每会话进程使用 `--no-session`,YCode 保存消息;启动后历史恢复进 OMP 上下文尚未实现。
|
||||
- 助手正文仍是纯文本;没有 Markdown 富内容渲染。
|
||||
- 工具卡是简单的折叠组件;完整事件顺序、过程折叠、审批与提问未证明对齐。
|
||||
- 外围部分入口仍是 mock/临时提示。现有界面与 token 数据不能作为完整视觉或功能通过的证据。
|
||||
- 侧栏任务搜索能过滤真实会话;重命名虽有 IPC/preload 接口,尚未接渲染器。账号/通知/空间为固定 mock;侧栏导航除“新建任务”外均未实现,权限/语音与右栏内容也仍为占位。
|
||||
- 历史 API Key 未配置等阻塞说明已过时;本轮不读取、输出或改动真实密钥。
|
||||
|
||||
## 后续顺序与验收
|
||||
|
||||
1. 收尾 OMP 回合取消、错误和监听清理,验证取消终态经过 IPC 后持久化为 `cancelled`;离线回归与真实上游验收分开记录。
|
||||
2. 经 REA 逐项获取原版对话渲染、工具过程、取消/恢复、历史恢复的证据,建立同版本/同视口/同字号/同输入的对比样本。
|
||||
3. 优先补 Markdown/富内容、工具过程状态机和恢复会话上下文,再扩展外围入口;每项建立原版证据及 YCode 回归。
|
||||
4. 全部功能仍纳入 1:1 范围;暂未实现项进入差距清单,不自动降级目标。
|
||||
|
||||
## 本轮验证
|
||||
|
||||
| 验证 | 结果与范围 |
|
||||
| --- | --- |
|
||||
| `npm run build`(包含 typecheck) | 通过,主进程/preload/渲染器构建成功 |
|
||||
| `npm run smoke` | 通过,原自建网关/工具循环回归;使用本地假上游 |
|
||||
| `npm run test:omp` | 通过,正常结束、两条取消结束路径、错误/退出、监听清理、预先取消;真实 `ipc.ts` + 会话存储配合假 OMP,确认取消和错误终态及错误文本写入磁盘 |
|
||||
| `node scripts/wb-capture.mjs` | 按预期退出码 1,提示使用 REA;在任何 CDP 连接前阻断 |
|
||||
|
||||
上述 OMP 回归不启动真实 OMP/真实上游,也不验证原版动态等价;真实停止按钮→OMP→磁盘的端到端复核仍待执行。
|
||||
历史 `scripts/e2e-cancel.mjs` 只检查停止/发送按钮切换,不验证磁盘和内核,且选择端口中的首个页面并发送真实长提示;不能用它的成功输出代替取消持久化验收。后续真实端到端验证需使用隔离的 YCode 会话并明确选定目标。
|
||||
本轮修复只涉及 `src/main/agent/omp-turn.ts`;保留前任在 `ipc.ts` 已完成的取消终态修复。
|
||||
没有重启当前 YCode 窗口;构建产物已更新,正在运行的主进程需下一次正常启动才加载本轮修复。
|
||||
@@ -0,0 +1,247 @@
|
||||
# 本轮汇报与决策记录
|
||||
|
||||
> 历史报告。2026-10-15 接手后的现行约束及进度见 `接手状态-2026-10-15.md` 与根目录 `AGENTS.md`。本文“REA 不支持 file://、改用直接 CDP”已过时并停用;此前不实现条款不能缩减用户确认的 1:1 目标。
|
||||
|
||||
**时间**:2026-10-15 凌晨
|
||||
**执行方式**:用户休息期间自主推进 1:1 还原;需决策处按推荐执行并记录
|
||||
**约束**:涉及拆解或对比 WorkBuddy 时使用 REA
|
||||
|
||||
---
|
||||
|
||||
## 一、本轮完成
|
||||
|
||||
| # | 任务 | 状态 | 产出 |
|
||||
| --- | --- | --- | --- |
|
||||
| 1 | 用 REA 提取 WorkBuddy 完整 design token 表 | ✅ | `docs/视觉对齐实测.md` §11 |
|
||||
| 2 | YCode CSS 全面 token 化 | ✅ | 裸 px 从 **321 → 0**(仅注释保留实测说明) |
|
||||
| 3 | 全局字号档位(六档) | ✅ | `src/renderer/src/fontSize.ts` |
|
||||
| 4 | 右栏拖拽调宽 | ✅ | `App.tsx` + `.app-shell__resizer` |
|
||||
| 5 | REA 对比与工具边界勘察 | ✅ | `docs/视觉对齐实测.md` §12 |
|
||||
| 6 | 统一汇报 | ✅ | 本文件 |
|
||||
|
||||
### 详细
|
||||
|
||||
**1. Token 表(REA 拆解)**
|
||||
|
||||
- `open_binary` 打开 `app.asar` → `format=asar, kind=archive`
|
||||
- `inspect_artifact`(record-and-continue)→ **12253 节点 / 14476 文件 / 45 处完整性矛盾**
|
||||
- 提取到完整体系:间距阶、字号阶、行高阶、字重阶、控件尺寸阶、圆角阶、
|
||||
体例语义字号、**对话流(chatflow)独立一套**、六档全局字号机制
|
||||
|
||||
**2. Token 化**(用户的直接诉求)
|
||||
|
||||
- `tokens.css` 完整镜像对标体系,**`--yc-N` 编号与 `--wb-N` 一一对应**
|
||||
- `app.css` 全量重写:所有间距/字号/行高/尺寸/圆角/颜色改引用 token
|
||||
- 剩余 53 处一次性实测值(如 `24.5px`、`21.45px`、`324px`)提升为**具名常量**区
|
||||
- 结果:**声明中不再出现任何裸像素**
|
||||
|
||||
**3. 六档字号**
|
||||
|
||||
- 按对标机制实现:`--yc-font-offset-global` + `--yc-md-root`,`clamp(-1, ·, 2)`
|
||||
- 快捷键 `Ctrl+-` / `Ctrl++` / `Ctrl+0`,localStorage 持久化
|
||||
- 右栏新增档位控件(− / 6 点轨道 / +)
|
||||
- **实测验证**:档位 2 = 正文 14px/22px(与实测基线完全一致);
|
||||
1→6 档为 13→14→15→16→16→16 px,**+2 封顶**,与对标的夹取规则一致
|
||||
|
||||
**4. 面板拖拽**
|
||||
|
||||
- 绝对定位命中区(6px)贴合网格边界,不占网格列
|
||||
- 范围 320–900px,默认 647px,双击还原,localStorage 持久化
|
||||
- 拖拽中禁用两侧 `pointer-events` + 文本选中
|
||||
|
||||
---
|
||||
|
||||
## 二、自主决策记录
|
||||
|
||||
> 用户授权「有需要决策的你先推荐,记录下来,最后统一汇报」。
|
||||
|
||||
### D1 · 字号档位只走快捷键 + 右栏控件,**不加菜单项**
|
||||
|
||||
- **推荐做法**:`Ctrl+-/+/0` + 右栏「界面」面板控件
|
||||
- **理由**:实测对标的四个菜单是 `编辑/窗口/帮助/关于`,字号档位在那边是纯快捷键行为。
|
||||
往「窗口」里塞「放大字号」语义不通,新增「视图」菜单则偏离实测结构
|
||||
- **被否决**:① 新增「视图」菜单(偏离实测);② 塞进「窗口」菜单(语义错误)
|
||||
- **影响**:字号档位发现性略低,靠右栏控件补足
|
||||
- **如需变更**:告诉我加在哪,一行配置的事
|
||||
|
||||
### D2 · Token 化用「具名常量」而非硬写
|
||||
|
||||
- **推荐做法**:把 53 处一次性实测值提为 `--yc-*` 具名常量
|
||||
- **理由**:对标自身也硬写这些值(`padding:5px 12px`、`line-height:21px`),
|
||||
但它们在本项目应可检索、可统一替换;且能满足「声明里不出现裸像素」的诉求
|
||||
- **被否决**:① 原样保留(回到裸 px);② 强行套用标准阶(会改变实测渲染值,破坏 1:1)
|
||||
|
||||
### D3 · 字体族顺序按实测改为 `PingFang SC` 打头
|
||||
|
||||
- **理由**:实测 computed style 就是 `"PingFang SC", -apple-system, …`;
|
||||
我原先 `-apple-system` 打头会让中文走不同回退,**是真实渲染差异**
|
||||
- **被否决**:保持原顺序(视觉上会不一致)
|
||||
|
||||
### D4 · 等宽字体族改为 `ui-monospace` 打头
|
||||
|
||||
- **理由**:对标 `--wb-font-code-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace`
|
||||
- **被否决**:保留 `'SF Mono', Monaco, 'Cascadia Code', …`(Windows 上 `SF Mono`/`Cascadia` 非对标首选)
|
||||
|
||||
### D5 · 面板宽度的「最大值」口径
|
||||
|
||||
- **过程**:我先按「窗口 60%」,后对齐文档已记录的 **320–900px**
|
||||
- **最终采用**:320–900px(与既有记录一致,且与窗口尺寸解耦)
|
||||
- **被否决**:窗口比例制(窗口很宽时面板会过宽,偏离对标手感)
|
||||
|
||||
### D6 · 详情面板默认收起
|
||||
|
||||
- **理由**:实测对标默认态宽 **1px**(收起)
|
||||
- **影响**:首次打开看不到右栏,需点标题栏图标。若希望默认展开,改 `useState(false)` → `true`
|
||||
|
||||
### D7 · ~~不实现侧栏顶部导航排~~ → **已被用户推翻,改为全部实现(mock)**
|
||||
|
||||
- **原决策**:不实现(功能不存在,不摆空壳)
|
||||
- **用户新指令(2026-10-15 凌晨)**:「先把外围配齐,登录账号先用 mock 写死数据,通知、发现应用、
|
||||
收起、搜索、分类、设置等等等」
|
||||
- **现行做法**:导航项**全部渲染**(新建任务 / 助理 Beta / 专家·技能·连接器 / 定时任务 / 资料库 / 更多),
|
||||
尺寸按实测;未实现项点击给出 2 秒临时提示,**不伪造可用状态**
|
||||
- **记录原因**:决策被推翻,保留过程便于回溯
|
||||
|
||||
### D8 · ~~不实现输入区权限选择器~~ → 仍不实现(图标已备)
|
||||
|
||||
- 原因不变:权限模型未实现,放一个点了没用的开关是误导
|
||||
- 实测值已记录(`.cr-permission-setting` 132×32),需要时可直接接
|
||||
|
||||
### D11 · mock 数据的标注方式
|
||||
|
||||
- **推荐做法**:`mock.ts` 统一存放 + `MOCK_` 前缀 + **UI 上显式标注**为示例数据
|
||||
- **理由**:用户要求用 mock 先把外围配齐;但 mock 若不标注,后续极易被误认为已接入真实数据
|
||||
- **被否决**:不加标注(风险是假数据被当真的用)
|
||||
- **落实**:通知面板底部、设置→账号页、账号按钮 title 三处均有标注
|
||||
|
||||
### D12 · 搜索的落点
|
||||
|
||||
- **推荐做法**:放在侧栏导航下方,**真实过滤任务列表**(而非装饰性输入框)
|
||||
- **理由**:实测当前视图中对标未展示搜索框;但搜索必须是真功能,否则又是空壳。
|
||||
做成过滤任务列表,既有用又不偏离结构
|
||||
- **被否决**:① 不做搜索(用户明确要求);② 放全局搜索但无后端(空壳)
|
||||
|
||||
### D13 · 未实现入口的反馈方式
|
||||
|
||||
- **推荐做法**:点击后 2 秒临时提示,文案含「尚未实现」
|
||||
- **被否决**:① 完全无反馈(像坏了);② 做成可点但什么都不发生的假功能
|
||||
- **理由**:外围视觉要齐,但不能谎称有能力
|
||||
|
||||
### D9 · 图标暂用对标资产,已标注必须替换
|
||||
|
||||
- **现状**:`icons.tsx` 中 15 个图标为 CDP 采集的对标 SVG,文件头已写明「临时占位,发布前必须替换」
|
||||
- **依据**:`docs/reference/ygent-ui-pixel-parity-feasibility-2026-10-14.md` 同样指出
|
||||
「逆向取值的 WB 图标照搬涉及资产许可,建议自绘」
|
||||
- **建议替换源**:VS Code codicon(MIT,可长期使用)或 Lucide
|
||||
- **需要你决策**:正式发布前是否替换、用哪套
|
||||
|
||||
### D10 · 字体族跨机器一致性不做处理
|
||||
|
||||
- **理由**:`PingFang SC` 为 macOS/部分 Windows 系统字体,其他机器会回退到系统中文字体;
|
||||
对标自身也有同样问题(参考文档 §3.B)
|
||||
- **可选方案**:打包 Noto Sans SC(OFL 允许再分发);但会显著增大安装包
|
||||
- **被否决**:本轮不引入字体资产(需你确认体积预算)
|
||||
|
||||
---
|
||||
|
||||
## 三、验证结果
|
||||
|
||||
| 项 | 方法 | 结果 |
|
||||
| --- | --- | --- |
|
||||
| 类型检查 | `npm run typecheck` | ✅ 通过 |
|
||||
| 构建 | `npm run build` | ✅ 通过 |
|
||||
| 核心闭环 | `npm run smoke` | ✅ 18 项断言通过 |
|
||||
| 运行时 token | `scripts/verify-tokens.mjs`(CDP) | ✅ 见下 |
|
||||
| Token 化回归 | `scripts/pngdiff.mjs` 像素对比 | ⚠️ 见下 |
|
||||
| GPU | CDP `gpuRenderer` | ✅ `ANGLE (AMD Radeon RX 460, D3D11)` |
|
||||
|
||||
运行时 token 实测(档位 2,窗口 1334×901):
|
||||
|
||||
```
|
||||
titlebar 30px ✅ 对齐实测
|
||||
sidebar 280px ✅
|
||||
content-max 832px ✅
|
||||
content-pad 40px ✅
|
||||
input-max 784px ✅
|
||||
body 14px/22 ✅
|
||||
md-root 17.143px ✅
|
||||
```
|
||||
|
||||
**Token 化回归对比**(`ycode-empty.png` → `ycode-tokens.png`):
|
||||
变化像素 **2.673%**,最大通道差 230。
|
||||
|
||||
- 已定位的**预期变化**:`.chat-head` 上内边距 14px → token 的 12px(原 14px 是我自拟、非实测值)
|
||||
- 残余变化主要来自该位移引起的文字抗锯齿重绘
|
||||
- **已闭环**:本轮结束前补测了真实对话区顶栏 `.workbuddy-topbar` →
|
||||
**高 64px / `padding: 0 16px` / 两端对齐**,`.chat-head` 已按此改写。
|
||||
原先「12px 还是 14px」的悬置问题作废——两者都不是实测值,现取实测的 64px 方案
|
||||
|
||||
---
|
||||
|
||||
## 四、遗留与阻塞
|
||||
|
||||
### 阻塞(需要你)
|
||||
|
||||
1. **移动端/跨机器字体**:D10
|
||||
2. **图标资产替换**:D9
|
||||
3. **侧栏导航排是否列入路线图**:D7
|
||||
4. **API Key 未配置** —— **L3 动态交互对标的硬前置**。
|
||||
没有真实回合就跑不出事件时间序列,无法比对
|
||||
`docs/reference/ygent-chat-interaction-parity.md` 的必测序列
|
||||
|
||||
### 未完成(技术可继续,无需你介入)
|
||||
|
||||
- 正文字号驱动 Markdown 渲染的逐处核对(当前为纯文本 `pre-wrap`,未接 Markdown 渲染器)
|
||||
- 工具卡与折叠行的完整状态机(对标有 `.cr-collapse` 系列)
|
||||
- 助手操作栏(复制/赞/踩/朗读/重试)—— 按约定「不伪造消耗与模型元数据」,暂不做
|
||||
|
||||
---
|
||||
|
||||
## 五、REA 使用记录与边界
|
||||
|
||||
**已执行**:归档级拆解(`open_binary` + `inspect_artifact`),拿到结构清单与完整性证据。
|
||||
|
||||
**发现的工具边界(重要)**:
|
||||
|
||||
REA 的 CDP 浏览器 provider **只枚举 HTTP(S) 页面目标**。WorkBuddy 渲染器是 `file://`:
|
||||
|
||||
```
|
||||
list_browser_targets http://127.0.0.1:9223
|
||||
→ targets: [] excluded: { unsupported_url: 1 }
|
||||
```
|
||||
|
||||
→ **`inspect_web_page` / `capture_web_screenshot` / `compare_web_captures` 无法观察 WorkBuddy 主窗口。**
|
||||
要采集 WorkBuddy,仍须用本项目的 CDP 脚本(`wb-capture.mjs` / `wb-tree.mjs` / `wb-icons.mjs`)。
|
||||
YCode 开发态走 `http://localhost`,REA 浏览器工具对它可用。
|
||||
|
||||
同时,REA 的二进制 provider(Ghidra / IDA / Hopper)本机均未配置,且不接归档目标,
|
||||
因此没有字符串检索能力——token 表由归档内 CSS 直接提取。
|
||||
|
||||
**副产品发现**:45 处完整性矛盾,首条是 `cli/bin/native/win32-x64/job-object.node`
|
||||
(声明的 sha256 与伴随文件不符)。该模块正是**绑定子进程树的 Job Object 原生实现**,
|
||||
与「GPU 沙箱在受限进程树里创建不了子进程」的观察吻合,值得留意。
|
||||
|
||||
---
|
||||
|
||||
## 六、下一步建议(按优先级)
|
||||
|
||||
1. **配 API Key → 跑真实回合 → 录事件时间序列**(打通 L3 的前置,价值最高)
|
||||
2. 按 D9 替换图标资产
|
||||
3. 补 Markdown 渲染器(正文字号才能按实测逐级生效)
|
||||
4. 若确认侧栏导航排要做,先定义功能再接视觉
|
||||
|
||||
---
|
||||
|
||||
## 七、产物索引
|
||||
|
||||
| 文件 | 内容 |
|
||||
| --- | --- |
|
||||
| `docs/视觉对齐实测.md` | 全部实测数据 + token 表 + REA 证据(427 行) |
|
||||
| `docs/落地方案.md` | 架构与里程碑 |
|
||||
| `docs/reference/` | 24 份参照文档(含采集 SOP 与 L3 对标规范) |
|
||||
| `docs/screenshots/` | 三个阶段的界面截图 |
|
||||
| `src/renderer/src/styles/tokens.css` | token 层(编号对齐对标) |
|
||||
| `src/renderer/src/fontSize.ts` | 六档字号 |
|
||||
| `scripts/wb-*.mjs` | WorkBuddy 采集(capture / tree / icons) |
|
||||
| `scripts/pngdiff.mjs` | 无依赖 PNG 像素对比 |
|
||||
| `scripts/verify-tokens.mjs` | 运行时 token 校验 |
|
||||
@@ -0,0 +1,37 @@
|
||||
# 流式回复状态栏对齐(2026-10-16)
|
||||
|
||||
本轮把 WorkBuddy 的流式回复状态行接入 YCode。只要助手消息处于 `streaming`,无论正文尚未到达还是已经开始逐字输出,正文之后都会显示源样式的“思考中”扫光状态;移除了 YCode 原先只在空正文时显示的静态提示和光标。回复完成后该状态行卸载,既有消息 footer 继续显示本条消息冻结的模型名。
|
||||
|
||||
## REA 来源与边界
|
||||
|
||||
| Evidence | 内容与范围 |
|
||||
| --- | --- |
|
||||
| `ev_717fa5e846e64d67ac19c8925d121bff632c0d3aefb3603b10858559cabb2dcb` | WorkBuddy 5.8.2 的 `src-0FGg1seX.js` 恢复源码;SHA-256 `f2c6dbae949041b4e2bb456e8a23ae2837f2d7893ac24bf471485f77c7b15178`。其中 `StreamingFooter` 显示加载状态、可选费用和提示;`LoadingTip` 默认延迟 4 秒、每 10 秒轮换,悬停时跳过轮换;`getLoadingTips` 按 locale 选择提示并替换产品名。 |
|
||||
| `ev_377c8790468b3c67dad8577aabb327f98d3140659f0fffdbabfcff5a40cc9e94` | WorkBuddy 加载样式及 token。样式恢复器只投影运行时加载器用到的 CSS Modules 类、对应动画及 trailing-tip 规则,不改规则值。 |
|
||||
| `ev_1055bb2779161c24d008319ed167313b4ab1da7512f5e2232e5b30863a02` | WorkBuddy 5.8.3 的被动页面检查;当前脚本和资源正文受过滤,没有流式时截图或该状态的计算样式。 |
|
||||
|
||||
当前活动 WorkBuddy 记录为 5.8.3,流式 footer 的可恢复源码来自 5.8.2。`src-CBaV_A3S.css` 的 REA 运行时导出 SHA-256 为 `2090ed21045c8f8b0fc388d76424c8751bf18fcd065cbbd5d0ef485163a2e36c`;REA manifest 将这份运行时 CSS 与 ASAR 声明摘要比较为 `mismatch`,而 `contexts-BkjwYSZT.css`(`50cbd673f7f35fc7f966bdddc6c9f5677fdfe944cb904888d214619fca259380`)为 `match`。本实现保留运行时采集中的类规则,同时把该版本/资产身份差异作为待复核项。
|
||||
|
||||
因此,本轮对齐的是 **REA 恢复的 5.8.2 源结构、计时逻辑、提示数据和 CSS 规则**。当前 5.8.3 的真实流式画面、computed style 与同画面像素对照仍未取得,不能据此宣称流式区域逐像素验收通过。
|
||||
|
||||
## 接入与验证
|
||||
|
||||
- `StreamingFooter.tsx` 在流式全过程保持状态提示;加载 tips 使用 REA 恢复的中英文短句,英文/葡萄牙语/印尼语走英文表,其余走中文表。提示中的 WorkBuddy 品牌名按宿主产品名替换为 YCode。
|
||||
- 费用行只在原版提供 credit 数值时出现。YCode 当前没有这项数据,本轮不显示费用,也不生成占位金额。
|
||||
- `streaming-footer-source.css` 由 REA 导出的 CSS 资产按源类名自动筛选;`--check` 验证生成结果与证据仍一致。
|
||||
- 已增加流式 footer 回归:空正文与非空正文均有状态行;4 秒首次显示、10 秒轮换、悬停暂停、离开后恢复、卸载后定时器清理;终态隐藏状态行且保留冻结模型名。
|
||||
|
||||
验证通过:
|
||||
|
||||
```powershell
|
||||
node scripts/rea/recover-streaming-loading-tips.mjs --check
|
||||
node scripts/rea/recover-streaming-footer-styles.mjs --check
|
||||
npm run test:conversation
|
||||
npm run test:assistant-footer
|
||||
npm run typecheck
|
||||
npm run build
|
||||
```
|
||||
|
||||
## 后续像素验收
|
||||
|
||||
要关闭剩余差距,需要通过 REA 对 WorkBuddy 5.8.3 与 YCode 在相同视口、DPR、字体、主题和流式阶段采集同状态画面,并比较状态行 ROI。还需在 WorkBuddy 当前 5.8.3 运行版本重新确认提示文案、费用存在时的列宽以及扫光/提示渐显动画。费用数值的数据路径仍是 YCode 功能差异,只有真实接入该数据后才能做有值状态对照。
|
||||
@@ -0,0 +1,56 @@
|
||||
# 对话区源码级续对齐
|
||||
|
||||
> 最新工程进展:[对话样式与调试画面采集](对话样式实对齐-2026-10-15.md)。已补 REA 截图、布局和 SVG 能力,并接入选定原版 CSS;下文为此前阶段记录。
|
||||
|
||||
本轮继续还原已有 REA 证据中的客户端实现。以下是源码分支恢复、工程集成和本地验证结果,**不是完整 WorkBuddy 1:1 验收**。
|
||||
|
||||
> 最新:已通过本地修复版 REA 实际取得 64 份当前加载的 CSS 正文(5,946,566 字节),读取失败 0、无截断。采集入口、Evidence、原包比对差异与范围见 [REA CSS 采集修复](REA-CSS采集修复-2026-10-15.md)。下文工程实现记录保留,不代表这些新 CSS 已全部接入 YCode。
|
||||
|
||||
## 证据与范围
|
||||
|
||||
WorkBuddy 5.8.2 / Electron 37.10.3;ASAR SHA-256 `035254bc76310ea46317433e4840602094543ef323d2d5c5aff7c131729de918`。本轮只处理既有 REA 导出 `.tmp/rea-runtime-scripts.json`,不直接读取原版安装目录、不连接原版 CDP、不执行捕获的脚本。
|
||||
|
||||
REA Evidence:`ev_717fa5e846e64d67ac19c8925d121bff632c0d3aefb3603b10858559cabb2dcb`。
|
||||
|
||||
| 原版脚本 | SHA-256 | 本轮观察 |
|
||||
| --- | --- | --- |
|
||||
| `src-Cng7axVa.js` | `5ce8649e3bfac10aec1e63afee726ab45abaafc5aa7cc372892e20f3eba18c8b` | ArtifactContentRenderer、自定义内容读取、Diff 内容恢复、HTML 预览分支 |
|
||||
| `src-0FGg1seX.js` | `f2c6dbae949041b4e2bb456e8a23ae2837f2d7893ac24bf471485f77c7b15178` | 补丁依赖、计划/任务/思考图标、复制格式 |
|
||||
| `i18n-Cxy1Uuvv.js` | `1c7223b12cb9e4e4bcb448563c6bb707fc81fda1bff17c7e44e07f1f12c94dda` | 简体中文与英文词典;默认 zh-cn,原版可由 initLocale 改选 |
|
||||
| `preview-size-limit-BPMUeizf.js` | `a35b8b9877f689a4e0ac3d346efc58e7e4e71bb70a1123766ebc596416123c0a` | HTML 默认 50 MiB、达到上限即进入过大分支 |
|
||||
| `main-content-core-Dlaq72qt.js` | `998ada4969d1bf7af8d2dace15c0bc2a3ca5bf0ee9cf941823d85a66d6967991` | 上下文、文件、图片 content block 与元数据 |
|
||||
|
||||
`npm run recover:artifact-reference` 校验摘要,以 Babel AST 分拆指定定义到 `.tmp/rea-artifact-recovered`,manifest 保留 UTF-16 范围。`npm run recover:conversation-labels` 从已采集字典选择 20 条英/中文原文,生成工程里的类型化字典。两者只处理 REA 导出。
|
||||
|
||||
## 工程变化
|
||||
|
||||
| 项目 | 已接入内容 | 仍有差异 |
|
||||
| --- | --- | --- |
|
||||
| 产物分发 | 计划、概览、自定义 Markdown、文件 Diff、HTML、媒体及 code/diff 的分支优先级;task 返回空,扩展/子代理通过独立 renderer 契约 | 子代理详情、扩展应用、Office、音视频等 renderer 未完整接入 |
|
||||
| 自定义 Markdown | URI/缓存/读取优先级、加载与错误状态、按 URI 更新缓存;切换后丢弃迟到结果 | 原版 Lexical 编辑、自动保存、详情工具栏仍未还原;当前展示只读 |
|
||||
| Diff 内容 | 缓存优先、读取当前文件后反向应用统一补丁、失败时解析保留片段;多 hunk、偏移查找、CRLF、末尾换行处理 | 当前 Diff UI 为本地双列适配器,**不是原版 PierreDiffEditor**;异常补丁全边界未对照执行原包 |
|
||||
| 文件工具入口 | 识别宿主实际 `path` 参数及 success 状态;使用已持久化的完整 oldContent/newContent 构造产物,保留创建/清空文件 | 参数里的替换片段不充当完整文件;仅有片段时继续走文件读取 |
|
||||
| 宿主读取与下载 | 新增完整文本读取 IPC,保留工作目录/符号链接边界及 2 MiB 上限;修复 text/markdown 被下载格式校验拒绝 | 原版 agent URI、云文档读取协议未接通;2 MiB 是当前宿主限制,与原版媒体限额不同 |
|
||||
| HTML | 本地文件读取后 srcDoc 预览、原版 fallback 的 sandbox 能力列表、50 MiB 大小判断 | 原版 URL 解析、webview 分区、编辑/刷新/发布/分享工具栏仍未等价;本地读取先受 2 MiB 限制 |
|
||||
| 富消息复制 | 将 YCode 的文本、图片、附件、资源投影为已观察到的 content blocks;恢复 Context 摘要、phrase HTML、版本化自定义 MIME | YCode 分离字段到 content blocks 的映射属于适配;任意连接器块及输入框富粘贴全流程未完整还原;浏览器降级路径可能只写标准 MIME |
|
||||
| 图标与文案 | 计划、任务、思考、下载、状态、审批及展开/收起使用已采集 SVG;接入已确认中文原文,移除无源码依据的 Current/Task completed 标签 | 未恢复这些组件全部 CSS、tooltip 和动效;等待标记沿用原版空 span,本地缺少其 CSS;新增字典尚未恢复全应用 locale 初始化 |
|
||||
|
||||
PlanUpdate 的 `confirmed/finished/analyzed` 在原版组件中直接写为英文,未用计划编辑器的中文文案替换。图标按钮的辅助名称属于本地无障碍适配。
|
||||
|
||||
## 验证
|
||||
|
||||
已通过 `build`(含 typecheck)、`test:artifacts`、`test:conversation`、`test:resources`、`test:conversation-ipc`、`test:markdown`、`test:media`。
|
||||
|
||||
- Diff 回归:多 hunk、行偏移、CRLF、无末尾换行、无效缓存回退;完整写入投影覆盖新增、清空和空文件,拒绝把参数片段当作文件版本。
|
||||
- 加载回归:URI 必需、缓存跳过读取、强制刷新、读取失败回退;类型分支优先级及 HTML 大小边界。
|
||||
- 宿主回归:真实 IPC + 临时工作目录;完整读取 1000 行、拒绝越界/符号链接/二进制;Markdown 通过实际下载 handler 写到临时文件并核对内容。
|
||||
- 浏览器使用 `verify-ui.mjs?fixture=artifact-source` 的测试数据和测试桥,验证文件工具→完整 Diff、自定义 Markdown、缓存、HTML、读取失败、超时和空文件;300 ms 迟到读取没有覆盖随后打开的缓存预览。浏览器错误日志为空。
|
||||
- 桌面布局使用 YCode 默认窗口宽度 1335;列宽为 280 / 408 / 647。截图 `.tmp/artifact-source-alignment-2026-10-15.png` 是 YCode 测试页,**没有原版同状态像素对照**。
|
||||
|
||||
## 后续差异
|
||||
|
||||
历史阶段登记了原版组件 CSS 采集未知项 `unk_7501f666de6716fa984de8a3135164da05d580ac8aa523e2770460329c892b39`。现已用本地 REA 修复打通已覆盖样式正文,原先“当前组件 CSS 正文无法取得”的阻塞不再适用;这是项目状态更新,没有伪造原 REA 会话未知项的关闭记录。未加载样式、两个运行时/原清单摘要差异及截图仍有独立未知项。
|
||||
|
||||
修复前的调试路径复核纠正了阻塞归因:调试连接正常,不应把完整 ASAR 提取失败当作调试模式无法提供 CSS 的证明。REA `list_electron_targets` 再次确认 WorkBuddy 5.8.2,Evidence `ev_ce09402c0eef01ab6d3f60d2db5cc598d6edc9715fcde64ed35d6acebe880d06`。当时只读检查 REA 6.5.0 的 `CdpElectronInspection.js`,资源采集使用 `Page.getResourceTree`,仅返回路径/MIME/大小;DOM 快照的 `computedStyles` 为空,安装实现未发现 CSS 正文读取调用。具体缺口是该版本 REA 未暴露 CSS 正文导出。那次复核未修改 REA,记录位于 `.tmp/rea-css-debug-check-2026-10-15.json`;随后用户要求先解决采集问题,本次已在独立副本实现并实测 CSS 采集,详见上方修复记录。
|
||||
|
||||
下一阶段仍需补完整编辑器与产物媒体依赖、富输入粘贴、原版长列表/滚动、组件样式和相同状态运行对比。云端服务、子代理调度、原生宿主与系统沙箱保持独立未决项。此前八类清单见 [对话区域八类对齐](对话区域-八类对齐-2026-10-15.md)。
|
||||
@@ -0,0 +1,65 @@
|
||||
# 对话渲染:从发布代码还原工程模块
|
||||
|
||||
后续已补齐 Mermaid、图片和路径点击接入,本文件记录前一批次;最新实现、证据和剩余差异见 [图表、图片与文件](对话区域-图表图片文件-2026-10-15.md)。
|
||||
|
||||
本轮已将 REA 取得的 WorkBuddy 渲染实现还原成独立 TypeScript/TSX 模块,并接入 YCode 实际消息界面。上一轮约 600 行的自写 token→React 渲染器已被薄适配层替换;产品现在沿用原版的主要执行顺序:
|
||||
|
||||
`源码预处理 → MarkdownIt token/缓存 → HTML → React 组件替换 → 已完成内容分组缓存`。
|
||||
|
||||
## 原版证据
|
||||
|
||||
原版查看仍全部通过 REA。本轮复用 runtime Evidence `ev_717fa5e846e64d67ac19c8925d121bff632c0d3aefb3603b10858559cabb2dcb` 的完整导出,校验选定脚本 SHA-256 后,在导出内容上进行 AST 格式化与定义分拆。没有用本地脚本直接提取 ASAR,也没有执行捕获的原版 bundle。
|
||||
|
||||
新增 REA 静态分析仅选择 `renderer/assets/src-DbE1_mgM.js`:父记录 `ev_98115d00e9c653dfe18ef7e3a9b3027d0566f18f8f312035872ee78f90233462`,摘要 `ev_fa709aa1ea2f2e28b9fa6b5c9d21cd49835859dfe2abbac255dfe5190e16fb66`。该文件解析成功,读取 1968427 字节、遍历 415338 个 AST 节点,无解析失败。其余 11388 个来源文件未分析,语义图受 6000 节点预算限制;不能据此宣称完成全应用依赖恢复。ASAR 的已有完整性矛盾继续保留,未作原因推断。
|
||||
|
||||
脚本身份:`src-DbE1_mgM.js` / SHA-256 `6c6ce63c93854783270e855572797d75e536e3b8d4548410e31fe9d147e1feb4`。
|
||||
|
||||
| 原版定义或包含区间(UTF-16、右端不含) | 工程落点 |
|
||||
| --- | --- |
|
||||
| CJK `[624883,626500)` | `workbuddy/markdown/cjk.ts` |
|
||||
| metadata、raw HTML、linkify 的 Gf/ep 初始化器及 `[648032,649516)` | `code-fence.ts`、`html-fallback.ts`、`linkify.ts` |
|
||||
| `initMarkdownIt` `[656816,659240)` 及 math/Prism 包含初始化器 `[652022,659243)` | `parser.ts`、`languages.ts`、`math.ts` |
|
||||
| provider `[718666,718860)` | `context.tsx` |
|
||||
| CodeLikeBox 包含初始化器 `[718885,719202)`;Copy `[719311,720135)`;CodeBlock `[720136,721212)` | `components/CodeBlock.tsx` |
|
||||
| MathInline `[731414,731499)`;MathBlock `[731500,731728)` | `ReactMarkdown.tsx` |
|
||||
| OpacityText `[798343,798513)` | `ReactMarkdown.tsx` |
|
||||
| finished emphasis/XML helpers `[806993,809247)`;主 renderer 包含初始化器 `[818611,827154)` | `source-projection.ts`、`ReactMarkdown.tsx` |
|
||||
| boundary/cache 包含区间 `[812685,816842)`;grouping `[818332,818478)` | `incremental.ts` |
|
||||
|
||||
工程目录为 `src/renderer/src/workbuddy/`。模块接口、适配边界见其中 README;具体 assignment 的原始范围保存在 `.tmp/rea-chat-recovered/manifest.json`。该派生材料包含 309 个顶层声明片段和 90 个实际赋值定义,仅用作阅读依据,不进入产品构建。
|
||||
|
||||
REA 的自动 Wakaru 恢复工具要求 Linux x64,当前工作区是 Windows。本轮使用已由 REA 获取的代码,通过 AST 分拆和人工类型化完成工程还原,没有为此安装或切换宿主环境。
|
||||
|
||||
## 相比上一轮补齐或纠正
|
||||
|
||||
- CJK:原版扫描算法与当前 `markdown-it-cjk-friendly@3.0.0` 不同,已恢复原版算法并移除该插件依赖。
|
||||
- 标题:恢复只处理等号 Setext 标题的特殊 `lheading` 规则。
|
||||
- 流式提示:按原版先切最后 6 个 UTF-16 单元,再按字符生成 token;寻找最后一个符合条件的文字子 token,遇到末尾 fence 停止。OpacityText 使用 `0.1 × level` 固定透明度,移除上一轮推测的定时动画。
|
||||
- 内容处理:恢复模型协议 XML 清理、LaTeX `\[...\]` / `\(...\)` 转换、引号强调修正、完成后的 escaped/residual emphasis 修复。
|
||||
- 解析与缓存:恢复安全前缀边界、引用定义和数学块的禁用条件、map/id 重排、前缀 loadingDot 撤销及顶层分组缓存。
|
||||
- 代码:恢复原版 wrapper/header/content/pre 层级。复制接收原始代码,显示接收渲染后的 children,两者独立;语言 class 保留解析器实际输出。文件点击必须有 handler。
|
||||
- Prism:恢复 24 个懒加载入口、别名、依赖顺序与加载完成通知,包含 C++、PHP、TSX、Scala 等;加载完成后重渲染高亮。
|
||||
- 数学:原版 KaTeX 模块显示版本 0.16.47,已锁定该版本;补齐行内、块级、集合宏及 latex fence。文档型或无效 LaTeX 回退代码块。
|
||||
- 表格:使用原版 token 的 `data-content`,在末尾表格仍生成时禁用引用,完成后启用;保留 LF 和无终止换行规则。
|
||||
|
||||
## 验证
|
||||
|
||||
| 验证 | 结果与范围 |
|
||||
| --- | --- |
|
||||
| `npm run build` | 类型检查、实际渲染产物及懒加载 chunk 构建通过 |
|
||||
| `npm run test:recovered` | 5 个套件通过:还原 parser、21 项源投影、代码组件契约、流式缓存、数学/回退/状态规则 |
|
||||
| 流式缓存验证 | 9 种输入的 402 个逐字前缀;268 次缓存复用,与完整重解析的 HTML 和行号 map 一致,缓存前缀未被污染 |
|
||||
| `npm run test:markdown` | 30 项集成渲染检查通过;按源码修正 UTF-16、class、语言输出和静态 span 的预期 |
|
||||
| `npm run test:chat` | 消息顺序、发送状态、23 项工具适配检查通过,确认渲染器替换没有破坏共享契约 |
|
||||
| YCode 浏览器离线样本 | 3 处公式、1 个公式块、22 个代码高亮 token、文件 L12-L15、复制成功反馈、表格源码进入草稿并聚焦;模型协议 payload 不可见 |
|
||||
| 1334×901、960×640 视口 | 无页面横向溢出;小视口代码框宽 592px;未使用原版截图作对照 |
|
||||
|
||||
UI 样本位于 `scripts/fixtures/source-recovery.mjs`。截图 `.tmp/chat-source-recovery-2026-10-15.png` 为实际构建产物的离线样本。测试假桥不写入用户会话、不请求模型,也不改变系统剪贴板。浏览器测试还发现并修复了测试服务器使用字符串替换注入 fixture 时,将 `$$` 意外缩为 `$` 的问题;已改用 replacement callback,生产渲染器不涉及该注入路径。
|
||||
|
||||
## 尚未还原与未验证
|
||||
|
||||
工程还原已覆盖上述执行链和模块,尚未证明原作者的完整工程结构、全部依赖版本和全部渲染状态都已恢复。Mermaid 仍使用代码回退;敏感投影、图片桥接/预览、文件宿主操作、宽度感知、全部 tooltip/icon/theme CSS 等仍需继续逐项还原。
|
||||
|
||||
原版像素采集仍受 REA `target_not_allowed` 限制;组件 class 和层级有源码依据,当前样式中的 token、边框与几何还不能宣称像素 1:1。OMP 的真实 ready/重启上下文验证仍是上一轮记录的未通过项,本轮没有改变这一结论。
|
||||
|
||||
没有重启当前 WorkBuddy 或 YCode 原生窗口。`out/` 已更新;本轮浏览器验证使用独立临时服务器,生产数据未改变。
|
||||
@@ -0,0 +1,58 @@
|
||||
# 统一字体与间距
|
||||
|
||||
WorkBuddy 有统一的字体与间距处理。本轮将已核实的全局字号机制和标准 token 接入 YCode,修复原先只改两个变量、静态字号消费者不随档位变化的问题。本轮完成的是公共基础层,不是每个组件最终外观的像素验收。
|
||||
|
||||
## REA 证据
|
||||
|
||||
- 字号行为来自既有 REA runtime Evidence `ev_717fa5e846e64d67ac19c8925d121bff632c0d3aefb3603b10858559cabb2dcb` 的 `app-core-DN1jMv6r.js`,SHA-256 `e19055ad9feca6a9ccc2e60d00b191afac90c4cd3948113a81cb72196e66c260`。六档表约在 UTF-16 offset 21817;覆盖函数 `[23603,26434)`;应用与事件 `[26434,27496)`;快捷键 `[27703,28465)`;WB token 覆盖表 `[29292,30500)`。
|
||||
- 快捷键避让逻辑来自同一 REA 导出的 `browser-zoom-hotkeys-CInnb_kx.js`,SHA-256 `20c206bc9a675bfbf2d45818b35e94cb8539e42169dcb47cd030a208447d92b8`。它避让已注册且聚焦的浏览器预览缩放目标,并非排除输入框。
|
||||
- 通过 REA `extract_artifact` 重新读取本地历史资源 ZIP,Evidence `ev_267e2188e816796acee76650153ab5a1c1f902e3a761d686979d2fe9926eed07`。本轮只读取 REA 新输出目录中的文件,没有直接读取原版安装目录或旧手工提取目录。
|
||||
- 对当前 WorkBuddy 5.8.2 ASAR 重新执行 REA inventory,Evidence `ev_97959691fb7cabf7c41f948b08332196924fec1fa8cb71e34dbafd65d912e637`;ASAR SHA-256 `035254bc76310ea46317433e4840602094543ef323d2d5c5aff7c131729de918`。三份 CSS 的 artifact ID 与 ZIP 提取结果完全一致,原包 occurrence 均为 `hash_status: verified`。因此使用的 CSS 不仅有旧文件名依据,还有当前安装包的身份匹配。
|
||||
|
||||
本轮产品实际使用 `tokens-Df-i-zsO.css`,SHA-256 `13f2bf82c96e5167a7d7098e36950c6c22c475b3337dbb8bb29ad2fe79cde696`,artifact `art_a0886b61c79588910cdbcd7819dd236f5cc318b81430b31eabde93158982fc7d`。匹配的另外两份是 `contexts-BkjwYSZT.css`(SHA `50cbd673f7f35fc7f966bdddc6c9f5677fdfe944cb904888d214619fca259380`)和 `agent-chat-pane-F5lfde1Z.css`(SHA `a09e1806f1b3dbed21432858357c876ebb6b878ed499069361e7b42ef557421c`)。它们不包含当前 `cr-*` 对话组件全部样式,不能冒充完整组件 CSS。
|
||||
|
||||
## 公共机制
|
||||
|
||||
| 层 | 已确认的行为 |
|
||||
| --- | --- |
|
||||
| 基础 token | 字号、字重、行高、等宽字体、标准 spacing、控件字号/尺寸等统一定义 |
|
||||
| 六档字号 | Markdown 根字号为 16、17.143、18.286、20.571、22.857、26.286px;原始偏移为 -1、0、1、2、3、4 |
|
||||
| 控件偏移 | 消费时使用 `clamp(-1, globalOffset, 2)`;高档位继续放大正文,普通控件封顶 +2px |
|
||||
| 静态字号 | 扫描可读 CSSOM 的 px 与带 px fallback 的 `var()`,以 fallback 数值为基准生成 `max(8px, base + offset)`;保留原版 media 分支与去重语义 |
|
||||
| 固定区域 | `.cb-font-size-fixed` 及后代跳过静态字号覆盖,并还原 WB 语义 token 基准值 |
|
||||
| 动态样式 | 监听 head/body 直接新增的 style/stylesheet link,100ms 后重新构建覆盖;offset=0 移除覆盖 |
|
||||
| 标准间距 | 0、2、4、5、8、12、16、20、24、32、40、48、64px;它们不跟随字号缩放 |
|
||||
|
||||
## 工程变化
|
||||
|
||||
- `workbuddy/typography/tokens.css` 保留 115 个经 REA 验证的原版 root 声明,由 `scripts/rea/recover-typography-reference.mjs` 生成;脚本核对 REA 提取摘要及当前 ASAR artifact 身份后才读输入。
|
||||
- `styles/tokens.css` 中 59 个本地字号、字重、行高和间距定义改成原版 WB token 的别名,通用语义体例不再自行叠加第二份偏移。固定区域重新声明语义别名,避免 CSS 自定义属性在 root 提前求值后继承,导致固定区域仍放大。
|
||||
- `workbuddy/typography/font-size.ts` 恢复 px/fallback 扫描、原版 WB token override、固定例外、观察器和快捷键解析;`fontSize.ts` 保留 YCode 的存储与事件合同,同时补齐 CB/WB 兼容变量与事件。输入框聚焦时快捷键有效。
|
||||
- 现有静态字号消费者增加明确的 px fallback,让统一扫描器处理用户气泡、代码、菜单和资源预览等;根字号和已经动态处理的语义 token 使用无 fallback 的变量,避免重复调整。
|
||||
|
||||
YCode 存储键、初始化清理和兼容事件接线是本地适配。没有访问或迁移 WorkBuddy 用户偏好,也没有接入尚不存在的 WorkBuddy host preference、快捷键录制状态或浏览器预览目标。普通界面的 sans 字体回退链仍是当前实现;本轮原版 token 能直接证明等宽字体定义,不能证明当前机器最终选中的中文字体与原版一致。
|
||||
|
||||
## 验证
|
||||
|
||||
`npm run test:font-size`:57 项检查通过,覆盖六档映射、原版 fallback 数字解析、media 去重、静态字号下限、固定区域 token、注入/清理、后加载样式重建与快捷键。`npm run build`:类型检查和实际产物构建通过。
|
||||
|
||||
通过自有构建产物 `?fixture=typography` 在 Chromium 内实际按快捷键切换六档并读取计算样式。输入框保持焦点,检查非零档仅有两份 override,重复切档不累积;最大档刷新后仍为 6,Ctrl+0 回到标准档并移除 override;未出现页面横向溢出或控制台错误。
|
||||
|
||||
| 档位 | 正文 px(约值) | 用户气泡 px | 代码 px | 通用 body token px | 固定 body token px | 当前段落下边距 |
|
||||
| --- | ---: | ---: | ---: | ---: | ---: | ---: |
|
||||
| 1 | 14 | 12 | 11.857 | 13 | 14 | 12px |
|
||||
| 2 | 15 | 13 | 12.857 | 14 | 14 | 12px |
|
||||
| 3 | 16 | 14 | 13.857 | 15 | 14 | 12px |
|
||||
| 4 | 18 | 15 | 14.857 | 16 | 14 | 12px |
|
||||
| 5 | 20 | 15 | 14.857 | 16 | 14 | 12px |
|
||||
| 6 | 23 | 15 | 14.857 | 16 | 14 | 12px |
|
||||
|
||||
表中是 YCode 现有组件基准值接入统一机制后的实测,不是新采集的 WorkBuddy 计算样式。正文 root/比例及代码基准仍需组件 CSS 对照;本轮没有将所有字号和行高强行等比缩放。
|
||||
|
||||
样本 `scripts/fixtures/typography.mjs`,测量 `.tmp/typography-browser-measurements-2026-10-15.json`,截图 `.tmp/typography-default-2026-10-15.png`、`.tmp/typography-level-6-2026-10-15.png`。只使用离线假会话,未向模型发送消息;浏览器字号已恢复标准档。
|
||||
|
||||
## 剩余边界
|
||||
|
||||
标准 token 已统一;每个组件实际选用的 margin/padding/gap、正文嵌套样式、头像与正文距离、字体实际回退和逐像素布局仍需 REA 的组件样式/运行时证据。当前段落下边距 12px 只是已有组件选择,本轮验证了其来自标准 token,不等于完成原版段距验收。保留的本地间距 56px 和行高 26px 等扩展也不应声称是已核实的同名原版 token。
|
||||
|
||||
REA 原版截图仍有上一轮 `target_not_allowed` 限制。本轮没有绕过它,也未重启原版或正在运行的 YCode 原生窗口。
|
||||
@@ -0,0 +1,65 @@
|
||||
> 后续专家实施已推进:真实创建/编辑/注册/会话激活及整应用51项通过,见[专家本地创建与激活](专家本地创建与激活-2026-10-16.md)。本文原“专家未实现”保留为前一轮基线,完整1:1尚未验收。
|
||||
|
||||
# 能力中心与本地能力接入(2026-10-16)
|
||||
|
||||
上一轮拆解已进入生产实现:侧栏入口、统一管理中心、本地技能与自定义 MCP 已接入真实服务,并进入完整应用验收。本轮没有改动原版账号、技能、连接器或任务,也没有向原版发送消息。云端服务与专家团调度仍按用户要求后置。
|
||||
|
||||
## 已实现范围
|
||||
|
||||
| 部分 | 真实行为 | 验证边界 |
|
||||
| --- | --- | --- |
|
||||
| 管理中心 | 侧栏入口、专家/技能/连接器切换、搜索/管理/详情入口;切换保留聊天组件与草稿,右栏按原会话保存 | 原版源 tab、header、卡片、SVG、token、基础组件规则已恢复;全状态像素尚未通过 |
|
||||
| 本地技能 | 文件夹/SKILL.md/ZIP 导入、同名覆盖、启停、读取正文和资源、修改检测、导出、卸载;发现空间 `.agents/skills` 与 `.claude/skills` | 受管副本存于 userData;卸载保留导入源。空间技能只启停/读取,不能由受管卸载接口删除 |
|
||||
| 技能会话联动 | 输入框添加菜单与 `/` 打开技能选择;搜索、置顶、最近使用;按草稿 owner 保存选择,消息持久化 `skill://` 引用;编辑/重发保留引用 | 新回合读取真实技能指令。手动调用与模型自动调用的 metadata flags 分开处理;并非原版完整富文本编辑器恢复 |
|
||||
| 自定义 MCP | JSON/Monaco 编辑、配置 hash 批准、stdio 与 Streamable HTTP、分页发现工具、整服务/逐工具开关、重连、删除、取消与退出释放 | 实际 SDK client/server 往返;旧回合不能借配置变更调用新服务。第三方 Token/OAuth/device-code 尚未接入 |
|
||||
| 对话运行时 | OMP 与备用 Gateway 共享动态工具快照/分派;自动加载技能、受限技能资源读取、MCP 调用审批与真实结果 | 两个内核分别经过受控真实本地服务验证,不以此证明原版内核等价 |
|
||||
| MCP 消息视图 | 保留实际协议工具名;使用 server/tool 身份元数据投影到已有原版 `mcp_call_tool` 专用视图,审批显示可读名称 | 只改变展示投影,历史回传仍使用真实工具名;全状态像素未验收 |
|
||||
| 专家页面 | 源导航、我的专家空态、创建入口、搜索/分类;缓存参考条目明确只读且不可激活 | 创建按钮目前返回真实新草稿讨论职责/依赖;尚未创建、发现、导入或激活专家包 |
|
||||
|
||||
## 集成选择与修复
|
||||
|
||||
三类能力独立于聊天 store;`src/shared/capabilities.ts` 定义类型契约,preload 仅暴露受控方法。会话层保存技能稳定 ID/URI 和实际回合上下文,以恢复原生分支及备用内核历史。连接器凭据使用系统 safeStorage,只返回字段名;本地注册表和技能安装通过原子提交保存。
|
||||
|
||||
不可用 MCP 在启动时后台连接,普通发送不会等待它的网络握手。回合只捕获已连接工具、连接 generation 与配置 hash;禁用、删除和改配置使旧调用失败,只有用户回合 signal 才产生用户取消语义。受管技能损坏、缺失或 YAML 无效时保留可定位/卸载的禁用条目,避免无关坏包阻断普通聊天。
|
||||
|
||||
完整应用启动验收发现主进程使用 ESM 产物却依赖 `__dirname`;改为 `dirname(fileURLToPath(import.meta.url))`,sandbox preload 继续 CommonJS。弹层继承管理中心主题变量,避免 portal 脱离作用域。源码几何验收还补齐了 Input/Button/Segmented 基础规则,修正空态垂直偏移。
|
||||
|
||||
## 验证
|
||||
|
||||
完整应用脚本 `scripts/verify-capability-flows.cjs` 使用隔离 userData/OMP profile、生产 renderer/preload/IPC、实际 OMP、真实 SDK stdio 服务和受控 OpenAI 上游。覆盖草稿往返、技能真实安装、Monaco JSON 保存、hash 批准、四个工具分页发现、技能引用、聊天内工具审批、真实结果渲染、模型自动加载,以及全新 Electron 进程的持久化和后台重连。
|
||||
|
||||
文件选择只控制 OS picker 的返回路径;JSON 编辑走实际 Monaco paste 事件,未改模型或连接器的后台状态来伪造 UI 成功,也未触碰系统剪贴板。模型/空间测试数据通过生产 IPC 设置于隔离目录;原版未参与该运行验收。父测试进程检查每阶段报告存在且 PASS,防止 Electron `app.quit()` 退出码掩盖失败。此前失败的独立目录保留,不计入通过。
|
||||
|
||||
详细最终结果与本机更新状态见文末验收记录;模块证据和局部测试分别见 [专家/统一中心实现](capability-center-implementation-20261016.md)、[技能实现](skills-implementation-20261016.md)、[MCP 实现](mcp-implementation-20261016.md)。已有对话、取消、持久化回归也已运行。少数旧 Node 测试在捆绑 YAML 后需要 `createRequire` ESM banner,已修正测试加载方式,未 mock 新生产能力以绕过失败。
|
||||
|
||||
## 原版证据
|
||||
|
||||
目标 WorkBuddy 5.8.2;ASAR SHA `035254bc76310ea46317433e4840602094543ef323d2d5c5aff7c131729de918`。所有原版信息均经 REA,包括本轮补采空态 SVG;本地恢复脚本只解析保存的 REA 正文。
|
||||
|
||||
- 基准 renderer JS:`ev_717fa5e846e64d67ac19c8925d121bff632c0d3aefb3603b10858559cabb2dcb`。
|
||||
- 技能市场模块:`ev_e8faf60b3d22b99ede302f2d0efdfb3145f53f59789d4a345f5892dc13a589a4`。
|
||||
- CSS:`ev_377c8790468b3c67dad8577aabb327f98d3140659f0fffdbabfcff5a40cc9e94`。
|
||||
- 原版运行态截图、partial probe 限制和各模块 SHA/offset 见 [总拆解](专家技能连接器拆解-2026-10-16.md) 及模块恢复 manifest。
|
||||
|
||||
## 还需继续
|
||||
|
||||
1. 通过 REA 补 `expert-manager` 真正正文、专家包 schema、产出发现及 daemon 激活契约,接本地专家创建/编辑/导入、依赖与会话身份。当前角色咨询草稿不能算专家创建完成。
|
||||
2. 技能详情的完整资源预览、URL 导入、更新、原版 Tooltip/Avatar/富文本引用和输入选择细节。目录、扫描、云同步、权益与购买依赖服务,当前诚实显示不可用。
|
||||
3. 第三方应用连接器的 Token/OAuth/device-code、修复/取消/解绑及云目录;当前仅自定义 MCP 本地能力闭环。
|
||||
4. 固定相同数据、视口、主题、侧栏宽度与渲染环境,逐项验收正常/空态/加载/错误/授权/编辑/禁用/窄窗/键盘/动效。局部源码与几何一致不代表整页或整个模块 1:1 已完成。
|
||||
|
||||
## 最终验收与本机更新
|
||||
|
||||
| 验证 | 结果与记录 |
|
||||
| --- | --- |
|
||||
| 生产 build + node/web typecheck | PASS,`.tmp/capability-build-20261016.log` |
|
||||
| 完整应用 → 实际 OMP → 真实 MCP + 技能自动加载 → 新进程恢复 | 14 项主流程 + 6 项重启 PASS,`.tmp/capability-flows-n92g8Y/report.json`;包含结构化引用、实际工具身份、REA 专用 MCP renderer |
|
||||
| 生产备用 Gateway → 真实 MCP + 技能正文/资源 → 真实 HTTP 上游 | 17/17 PASS,`.tmp/capability-gateway-TxUvcv/report.json` |
|
||||
| 技能文件系统 / 原生局部 UI | 59/59 与 37/37 PASS,`.tmp/skills-files-iAkonv/report.json`、`.tmp/skills-ui-fR8rWr/report.json` |
|
||||
| MCP SDK host / 新进程恢复 / 篡改失信 | 36 + 7 + 2 项 PASS,`.tmp/mcp-backend-7PNwXc/`;另有13项原生管理 UI 与12项配置 helper 验证 |
|
||||
| 中心与专家源几何 / 原生交互 | 33/33 PASS,`.tmp/capability-center-k6vN5H/report.json`;源 header64、tabs60/60/78、gap24、我的专家空态Y472.5/548.5、创建108px/14px、右侧动作300px、稳定参考卡156px;IME/主题/480窄窗等已验 |
|
||||
| 既有聊天回归 | `test:omp`、`test:chat`、`test:persistence`、`test:conversation` PASS;OMP 生命周期/取消/磁盘终态保持 |
|
||||
|
||||
当前用户 YCode 已加载最终 renderer `index-C0lP5ThT.js`,技能/MCP API 和侧栏入口可用。更新前确认无运行回合、附件、资源引用、编辑消息或模型设置表单;测试安装/模型/MCP/会话均留在隔离目录,没有导入用户正式数据。一次更新助手的末尾 CDP 检查失败,保留恢复文件后单独确认最终构建已加载,再通过原会话行恢复 owner,验证原 owner 与空草稿完全一致才清理该恢复文件;最终记录 `.tmp/live-capability-update-20261016.json`。原模型及会话数据保留。
|
||||
|
||||
原版截图保存的侧栏宽为284.28125,本机独立验收默认280;该保存状态差异不拿来假定整页X坐标/像素相等。参考专家首卡宽度仍为322.578125,对照原在线长列表319.234375:缺少原长列表滚动条及推广/数据状态,尚有差异,明确保留后续验收。
|
||||
@@ -0,0 +1,185 @@
|
||||
# YCode 落地方案
|
||||
|
||||
> 历史初始方案。当前运行架构优先使用 OMP RPC sidecar,自建网关保留为回退;现行目标是借助 REA 进行视觉、交互与功能 1:1 复刻。实际完成度见 `接手状态-2026-10-15.md`;本文件旧里程碑和排除项不作为缩减范围的依据。
|
||||
|
||||
**日期**:2026-10-14
|
||||
**范围**:Electron 桌面应用 · 第一个里程碑 = 最小端到端闭环(能对话 + 能跑一个工具)· 自建 OpenAI 兼容网关
|
||||
|
||||
---
|
||||
|
||||
## 0. 前置决策(已确认)
|
||||
|
||||
| 项 | 决策 | 理由 |
|
||||
| --- | --- | --- |
|
||||
| 产品形态 | Electron 桌面应用 | 与对标形态一致,可复用同批开源 UI 栈 |
|
||||
| 首里程碑 | 最小端到端闭环 | 一次打通 UI ↔ Agent ↔ 网关 ↔ 工具,最快验证价值 |
|
||||
| 模型接入 | 自建网关(自有 API Key,OpenAI 兼容) | 协议可控、供应商可换、密钥不出主进程 |
|
||||
| 产物策略 | **clean-room** | 不复制对标产品的源码 / CSS / 资源,只用其公开架构与交互模式 |
|
||||
|
||||
---
|
||||
|
||||
## 1. 目标架构
|
||||
|
||||
```
|
||||
┌──────────────────────────────────────────────────────┐
|
||||
│ Renderer(React 19 + Zustand) │
|
||||
│ 对话区 · 右栏上下文 · 设置弹窗 │
|
||||
│ ⚠ 无 Node / fs / 网络能力 │
|
||||
└───────────────┬──────────────────────────────────────┘
|
||||
│ contextBridge(preload 白名单 API)
|
||||
│ invoke: config/session/chat
|
||||
│ event : chat:event(流式增量)
|
||||
┌───────────────▼──────────────────────────────────────┐
|
||||
│ Main(Electron 主进程 · ESM) │
|
||||
│ ├ ipc.ts 唯一对外边界 │
|
||||
│ ├ config.ts safeStorage 加密 Key │
|
||||
│ ├ sessions.ts 会话与消息持久化 │
|
||||
│ ├ agent/loop.ts Agent 循环(模型 ↔ 工具) │
|
||||
│ └ gateway/ 自建网关(OpenAI 兼容 + SSE) │
|
||||
└───────────────┬──────────────────────────────────────┘
|
||||
│ HTTPS Bearer(Key 只在此处出现)
|
||||
▼
|
||||
自有上游(OpenAI 兼容 /chat/completions)
|
||||
```
|
||||
|
||||
### 关键设计点
|
||||
|
||||
1. **单向分层**:`renderer → preload → ipc → agent → gateway → 上游`。反向只有 `chat:event` 一条流式通道。
|
||||
2. **密钥不出主进程**:渲染进程只能拿到 `{ hasApiKey, keyStorage }`,永远拿不到明文。
|
||||
3. **循环与工具解耦**:`loop.ts` 只管编排,工具是纯函数 `(args, ctx) => ToolResult`,新增工具只需改 `tools/index.ts` 注册表。
|
||||
4. **网关只管协议**:模型路由、上下文裁剪、重试策略不放网关,后续可独立演进。
|
||||
|
||||
---
|
||||
|
||||
## 2. 一次回合的完整链路
|
||||
|
||||
```
|
||||
用户按 Enter
|
||||
→ renderer: chat.send({sessionId, text})
|
||||
→ ipc: 落库用户消息 + 占位助手消息,返回 {runId, assistantMessageId}
|
||||
→ loop: 拼 system + 历史 + 本轮 → gateway.stream()
|
||||
→ gateway: POST /chat/completions (stream:true) → 解析 SSE
|
||||
├ delta.content → emit {type:'text'} → 界面逐字追加
|
||||
└ delta.tool_calls → 按 index 归并分片
|
||||
→ 若产生工具调用:
|
||||
emit tool_call → 执行工具 → emit tool_result
|
||||
→ 把 assistant(tool_calls) + tool(result) 回填上下文 → 继续下一轮
|
||||
→ 无工具调用 → emit done → 更新助手消息终态
|
||||
```
|
||||
|
||||
取消:`chat:cancel(runId)` → `AbortController.abort()` → 网关抛 `AbortError` → `emit cancelled`。
|
||||
|
||||
---
|
||||
|
||||
## 3. 里程碑拆解
|
||||
|
||||
### M1 · 最小端到端闭环(本次已落地)
|
||||
|
||||
- [x] Electron 壳(`contextIsolation: true` / `sandbox: true` / 无 `nodeIntegration`)
|
||||
- [x] preload 白名单 API(CJS,因为沙盒要求)
|
||||
- [x] 自建网关:OpenAI 兼容 + SSE 流式 + 流式工具调用组装
|
||||
- [x] Agent 循环:多轮工具调用、终止条件、取消
|
||||
- [x] 工具:`list_dir`、`read_file`(只读 + 工作区逃逸防护)
|
||||
- [x] 配置持久化:`safeStorage` 加密 Key,明文降级时 UI 告警
|
||||
- [x] 会话持久化 + 首条消息自动命名
|
||||
- [x] 界面:会话列表 / 对话区 / 右栏上下文 / 设置弹窗 / 明暗主题
|
||||
- [x] 类型检查 + 构建通过
|
||||
|
||||
### M2 · 体验与可靠性
|
||||
|
||||
- [ ] Markdown 渲染(代码高亮、表格、KaTeX)
|
||||
- [ ] 消息级操作:复制、编辑重发、重新生成
|
||||
- [ ] 工具卡分组折叠(连续调用合并成摘要)
|
||||
- [ ] 断流重试与错误分类提示
|
||||
- [ ] 会话搜索与重命名
|
||||
|
||||
### M3 · 能力扩展
|
||||
|
||||
- [ ] 工具扩展:`write_file` / `edit_file` / `run_shell`(带权限确认)
|
||||
- [ ] 审批流:写操作与命令执行需用户确认
|
||||
- [ ] MCP 客户端接入
|
||||
- [ ] Skill 加载(`SKILL.md` 约定)
|
||||
|
||||
### M4 · 平台化
|
||||
|
||||
- [ ] 迁移到 SQLite
|
||||
- [ ] 项目 / 工作目录多实例
|
||||
- [ ] 右栏真实面板(产物预览、文件树、任务)
|
||||
- [ ] 打包分发(electron-builder,Windows 优先)
|
||||
|
||||
---
|
||||
|
||||
## 4. 安全基线
|
||||
|
||||
| 风险 | 处置 |
|
||||
| --- | --- |
|
||||
| 渲染进程被注入后提权 | `sandbox: true`、无 `nodeIntegration`、CSP 限制 `script-src 'self'` |
|
||||
| 密钥泄露 | 只在主进程;`safeStorage` 加密;日志不打印 |
|
||||
| 工具越权读写 | 路径解析后做 `relative()` 逃逸检查,越界直接拒绝 |
|
||||
| 外链钓鱼 | `setWindowOpenHandler` 一律 `deny` + `shell.openExternal` |
|
||||
| 任意命令执行 | M1 **不提供** shell 工具;M3 引入时必须走审批 |
|
||||
|
||||
---
|
||||
|
||||
## 5. 视觉对齐依据(对标实测值)
|
||||
|
||||
配色与排版**不再自拟**,全部取自两项实测证据:
|
||||
|
||||
1. 真实 WorkBuddy 运行时布局实测 —— `docs/reference/workbuddy-chat-layout.md`(CDP computed style / 元素矩形)
|
||||
2. 安装包 token 表 —— `tokens-Df-i-zsO.css`、`contexts-BkjwYSZT.css`
|
||||
|
||||
### 调色板(浅色)
|
||||
|
||||
| 用途 | 值 |
|
||||
| --- | --- |
|
||||
| 正文 / 主文字 | `#000` |
|
||||
| 次级 / 三级文字 | `rgba(0,0,0,.7)` / `rgba(0,0,0,.5)` |
|
||||
| 主背景 / 次背景 | `#fff` / `#f2f2f2` |
|
||||
| hover / active | `#ebebeb` / `#e6e6e6` |
|
||||
| 边框(主/次/三级) | `#e6e6e6` / `#ebebeb` / `#f2f2f2` |
|
||||
| 品牌 / 成功 / 警告 / 危险 / 信息 | `#00c29a` / `#0cbf5b` / `#ff7800` / `#f64041` / `#3370ff` |
|
||||
|
||||
**注意:UI 主体是中性黑白灰,品牌绿只用于状态点缀**,不用于主按钮或大面积色块。
|
||||
|
||||
### 圆角与间距
|
||||
|
||||
- 圆角:`sm 4px` / `md 6px` / `lg 8px` / 气泡 `16px` / 输入框 `24px`
|
||||
- 间距基准 4px;对话内容列左右内边距 `40px`
|
||||
|
||||
### 字号
|
||||
|
||||
| 角色 | 值 |
|
||||
| --- | --- |
|
||||
| caption / body | `12px` / `14px`(行高 18 / 21) |
|
||||
| 用户气泡 | `13px` / 19px |
|
||||
| Markdown 根 | `17.143px`,行高 `1.75`;段落 `.875em` → 15px / 26.25px |
|
||||
| 代码块 | `12.857px` / 22.5px,padding `12px 16px` |
|
||||
| 表头 | 底色 `#f7f7f7`,单元格 padding `8px 12px` |
|
||||
|
||||
### 结构尺寸
|
||||
|
||||
- 左栏 `280px`;对话内容列 `max-width 832px` 居中,左右 `padding 40px`(正文列 752px)
|
||||
- 助手头部:`24px` 圆形标识 + `10px` 间距,行高 `24.5px`,名称 `14px/600`,下间距 `12px`
|
||||
- 用户气泡:`#f2f2f2`、padding `8px 12px`、圆角 `16px 16px 0`、`min-width 40px`、`max-height 310px`
|
||||
- 输入容器:`1px solid #e6e6e6`、圆角 `24px`、白底 + 双层轻阴影;编辑区 `min-height 64px`、横向 `padding 16px`;工具栏 `56px`、按钮 `32px`
|
||||
- 滚动:消息列表 `flex:1 + min-height:0 + overflow-y:auto`,输入区 `flex-shrink:0` 固定底部
|
||||
|
||||
> 落地方式:CSS 使用**自有类名**(`.msg--assistant`、`.bubble` 等),仅取实测数值,
|
||||
> 不复制对标产品的类名与样式表结构。
|
||||
|
||||
---
|
||||
|
||||
## 6. 与对标分析的关系
|
||||
|
||||
`docs/` 下三份分析报告(`WorkBuddy-AI-实现分析报告`、`WorkBuddy-AI-复刻可行性评估`、`WorkBuddy-UI复刻可行性评估`)用于**指导选型与交互模式**,不作为复制来源:
|
||||
|
||||
- 可用:组件划分思路、交互状态机、协议约定、开源库清单
|
||||
- 不可用:对方源码、CSS、图标与图片资源、文案
|
||||
|
||||
---
|
||||
|
||||
## 7. 首次运行清单
|
||||
|
||||
1. `npm install && npm run dev`
|
||||
2. ⚙ 设置:填 baseUrl / 模型名 / API Key;选工作目录
|
||||
3. 提问「列出工作目录里有哪些文件」→ 应看到工具卡出现、执行、结果回填、模型总结
|
||||
@@ -0,0 +1,662 @@
|
||||
# WorkBuddy 界面实测数据(YCode 视觉对齐依据)
|
||||
|
||||
> 历史实测参照,尚需通过 REA 复核。现行目标是视觉、交互与功能 1:1;本文旧版分级中的“不做/不可能”不能用于缩减范围。后续所有原版采集使用 REA,禁止直接运行 `wb-*` CDP 脚本绕过。接手记录见 `接手状态-2026-10-15.md`。
|
||||
|
||||
**采集方式**:CDP(`WORKBUDDY_REMOTE_DEBUGGING_PORT=9223`)+ `scripts/wb-capture.mjs` / `scripts/wb-tree.mjs`
|
||||
**采集环境**:WorkBuddy 37.10.3-42,Windows,视口 **1334 × 901**,DPR 1,zoom 1.000,浅色主题
|
||||
**采集时间**:2026-10-15
|
||||
**原始产物**:`%USERPROFILE%\.ycode\captures\`(含真实对话,不入库)
|
||||
|
||||
> 说明:以下均为**运行时 computed style 实测值**,不是静态 CSS 推断。
|
||||
> 换窗口尺寸或字号档位需重新采集。
|
||||
|
||||
---
|
||||
|
||||
## 0. 参照文档与对齐分级
|
||||
|
||||
同项目源头文档已复制到 `docs/reference/`,不必再跳到别的仓库:
|
||||
|
||||
| 文档 | 用途 |
|
||||
| --- | --- |
|
||||
| `workbuddy-cdp.md` | **采集 SOP**(开启调试端口、采集流程、边界与常见问题) |
|
||||
| `workbuddy-chat-layout.md` | 对话区布局实测(字号 token、宽度约束、滚动策略) |
|
||||
| `workbuddy-composer-reference.md` | 输入区专项参考 |
|
||||
| `ygent-ui-pixel-parity-feasibility-2026-10-14.md` | **像素级对齐可行性结论与分级目标** |
|
||||
| `ygent-font-parity.md` | 字体与六档字号对齐 |
|
||||
| `ygent-sidebar-parity.md` / `ygent-settings-parity.md` / `ygent-model-composer-parity.md` | 分区对齐记录 |
|
||||
| `ygent-workbuddy-render-audit-2026-10-08.md` | 40 项逐项差异审计(含坐标/字库/间距) |
|
||||
| `ygent-workbuddy-ai-gap-2026-10-14.md` | 能力差距盘点 |
|
||||
| `ygent-chat-parity.md` | 对话区对标路线图 |
|
||||
| **`ygent-chat-interaction-parity.md`** | **L3 动态交互对标与验收(必测序列、事件与渲染状态)** |
|
||||
| `ygent-chat-stage-summary-2026-10-08.md` | 分阶段汇总 |
|
||||
| `ygent-streaming-activity.md` | 流式活动播报 |
|
||||
| `ygent-chat-edit.md` / `ygent-chat-approval-questions.md` | 消息编辑 / 审批提问 |
|
||||
| `ygent-rich-content.md` / `ygent-attachments.md` | 富内容与附件 |
|
||||
| `ygent-session-titles.md` / `ygent-shell-settings.md` | 会话标题 / 壳层设置 |
|
||||
| `ygent-debug.md` | ygent 侧 CDP 调试 |
|
||||
| `workbuddy-independent-conversations-2026-10-08.md` / `workbuddy-reference-import.md` | 独立会话与参照导入 |
|
||||
| `ygent-岗位与项目团队方案.md` | 岗位/团队方案(后续扩展参考) |
|
||||
|
||||
### 对齐分级(直接采用其结论,避免重复踩坑)
|
||||
|
||||
| 级别 | 目标 | 可行性 |
|
||||
| --- | --- | --- |
|
||||
| **L1 几何对齐** | 同视口/同字号下关键锚点与尺寸 **≤1px** 取整误差 | ✅ 可达 |
|
||||
| **L2 静态像素对齐** | L1 + 图标路径/颜色/阴影/滚动条 | ⚠️ 90%+,宿主原生控件除外 |
|
||||
| **L3 动态交互一致** | 事件序列、折叠时机、滚动、取消/恢复 | ⏳ **真正的目标**,未完成 |
|
||||
| **L4 全局 100% 像素一致** | 含宿主 chrome、平台入口、跨机器字形 | ❌ 不可能,不做 |
|
||||
|
||||
### 明确不做(沿用其约定)
|
||||
|
||||
- 不伪造消耗 / 模型元数据 / 产物计数以凑齐视觉
|
||||
- 不复制平台商业入口(邀请卡、账号区)与无效操作按钮
|
||||
- 不为对齐硬补高度
|
||||
- 不把静态像素通过宣称为动态交互通过
|
||||
- 不把任一端的绝对 y 差直接当作要修的 margin
|
||||
|
||||
### 已知的跨宿主差异(不可消除)
|
||||
|
||||
- 渲染引擎版本不同 → 默认 UA 样式、原生滚动条伪元素、字体回退顺序可能不同
|
||||
- 系统字库为各机本地安装,不随项目分发 → 跨机器像素一致不成立
|
||||
- 顶栏 chrome 与侧栏数据层级属宿主结构差,**不应为复制而破坏已对齐的内部坐标**
|
||||
|
||||
---
|
||||
|
||||
## 1. 顶层布局
|
||||
|
||||
| 区域 | 实测 |
|
||||
| --- | --- |
|
||||
| 菜单栏 | 高 **30px**(`.codebuddy-menubar`) |
|
||||
| 左栏 | `.conversation-sidebar` x=0 y=30 **280 × 871** |
|
||||
| 主内容区 | 宽 **1054px**(1334 − 280) |
|
||||
| 右栏(详情面板) | `.detail-panel-container` **宽 1px** —— **默认收起** |
|
||||
|
||||
---
|
||||
|
||||
## 2. 左栏(侧栏)
|
||||
|
||||
| 元素 | 实测值 |
|
||||
| --- | --- |
|
||||
| 容器 `.conversation-list` | **280 × 871**,背景 **`rgb(247,247,247)` = `#f7f7f7`** |
|
||||
| 头部 `.conversation-list-header` | 279 × 288,`padding: 0 12px 20px`,`gap: 2px`,flex column |
|
||||
| 品牌行 `.conversation-list-logo-row` | 255 × **64**(min-height 40),`gap: 4px`,align center |
|
||||
| 品牌标题 `.logo-*-title` | **14px / 700**,行高 22px,色 `rgba(0,0,0,.9)`,左边距 12px |
|
||||
| 版本行 | 高 18,`padding-left: 12px`,`margin-top: -4px`,`gap: 6px` |
|
||||
| 版本徽标 | **10px**,行高 18,`letter-spacing: .2px`,色 `rgba(0,0,0,.5)` |
|
||||
| 次级按钮 `.wb-button--secondary` | 98 × **28**,`padding: 4px 6px 4px 8px`,`gap: 2px`,背景 `#f2f2f2`,色 `rgba(0,0,0,.7)`,边框 1px `#ebebeb`,**圆角 100px**,字号 **12px** / 500 |
|
||||
| 导航按钮 `.conversation-list-tab-button` | 255 × **32**,`padding: 5px 12px`,`gap: 8px`,**圆角 8px**,图标 **16 × 16**,标签 **14px** / 行高 22 |
|
||||
| Beta 徽标 | **10px**,大写,`padding: 0 5px`,边框 1px `#dedede`,圆角 100px,色 `rgba(0,0,0,.45)`,行高 16 |
|
||||
| 分组标签 `.conversation-section-label` | 255 × **30**,`padding: 5px 12px`,圆角 8,背景 `#f7f7f7`,`gap: 4px` |
|
||||
| 分组文字 | **12px / 600**,行高 20,色 `rgba(0,0,0,.5)`;形如「任务 (1)」 |
|
||||
| 分组折叠箭头 | 14 × 14,色 `rgba(0,0,0,.3)` |
|
||||
| 分组小按钮 | 20 × 20,圆角 4,色 `rgba(0,0,0,.5)` |
|
||||
| 会话项 `.conversation-item` | 255 × **31**;内层 `.cb-agent-card` `padding: 5px 12px`、**圆角 8px** |
|
||||
| 会话项标题 | **14px** / 行高 21,字重 400,色 `rgba(0,0,0,.9)`,左 24 |
|
||||
| 会话项时间 | **11px** / 行高 20,色 `rgba(0,0,0,.5)`,**右对齐**(同一行,非第二行) |
|
||||
|
||||
---
|
||||
|
||||
## 3. 对话区
|
||||
|
||||
| 元素 | 实测值 |
|
||||
| --- | --- |
|
||||
| `.cr-message-list` | x=280 y=94 **1054 × 639**,基础字号 13px |
|
||||
| `.cr-message-list__content` | **宽 832**(max-width 832),**`padding: 0 40px`** → 正文列 **752** |
|
||||
| `.cr-agent` | **752 宽**,flex column,色 `rgba(0,0,0,.9)`,13px / 行高 19 |
|
||||
| `.cr-agent__header` | 752 × **24.5**,**`margin-bottom: 12px`**,**`gap: 10px`**,align center |
|
||||
| `.cr-markdown` | **17.143px / 行高 30.0002px** |
|
||||
| `.cr-markdown p` | **15.0001px / 26.2502px**,`margin-bottom: 12px` |
|
||||
| `.cr-self-message` | flex row,**`justify-content: flex-end`**,align-items flex-start,**`gap: 8px`** |
|
||||
| `.cr-self-bubble` | `min-width: 40px`,`max-height: 310px`,**`padding: 8px 12px`**,**`gap: 4px`**,背景 **`rgb(242,242,242)`**,**`border-radius: 16px 16px 0`**,**13px / 19px** |
|
||||
| `.cr-collapse__header` | 高 **26.25**,`gap: 8px`,`max-width: 100%`,色 **`rgba(0,0,0,.5)`**,**15px / 26.25px** |
|
||||
|
||||
**主文字色是 `rgba(0,0,0,.9)`,不是 `#000`。**
|
||||
|
||||
---
|
||||
|
||||
## 4. 输入区(最容易做错的地方)
|
||||
|
||||
| 元素 | 实测值 |
|
||||
| --- | --- |
|
||||
| `.cr-input-box` | x=415 y=733 **784 × 134**,`z-index: 16` |
|
||||
| `.cr-input-box__main` | **`border-radius: 24px`**,`gap: 4px`,flex column |
|
||||
| `.cr-input-container` | **背景 `rgb(255,255,255)`(白底,不是渐变)**;边框 **1px `rgb(230,230,230)`**;**圆角 24px**;`min-height: 96px`;`padding-top: 12px` |
|
||||
| 阴影 | **双层**:`rgba(0,0,0,0.03) 0 16px 32px -8px, rgba(0,0,0,0.06) 0 2px 4px -4px` |
|
||||
| 聚焦态 | 边框色变 `rgba(0,0,0,.15)` |
|
||||
| `.cr-input-editor-host` | 782 × **64**(min-height 64),**`padding: 0 16px`** |
|
||||
| 输入文字 | **14px / 行高 21** |
|
||||
| `.cr-input-toolbar` | 782 × **56**,**`padding: 12px`**,`gap: 8px`,**`justify-content: space-between`**,min-height 32 |
|
||||
| `.cr-input-toolbar__right` | 286 × **32**,`gap: 4px`,背景 `#fff` |
|
||||
| `.cr-send-button` | **32 × 32**,**`border-radius: 50%`** |
|
||||
|
||||
几何关系:`12 (padding-top) + 64 (编辑区) + 56 (工具栏) ≈ 134` ✓;输入框 784 = 832 − 48。
|
||||
|
||||
> ⚠️ 注意区分两个 composer:
|
||||
> `--wb-bg-input-slot-gradient`(`linear-gradient(180deg,#ebebeb,#f5f5f5)`)属于 **`.wb-home-composer__input-slot`(首页新建对话)**;
|
||||
> **会话内输入框 `.conversation-input__box` 明确定义 `background: 0 0`(透明)+ 白底容器 + 描边**。两者不可混用。
|
||||
|
||||
---
|
||||
|
||||
## 5. 右栏:详情面板(展开态实测)
|
||||
|
||||
> 采集时视口变为 **1638 × 901**(用户展开面板后窗口更宽)。CSS 中 `.detail-panel-container` 为 `width: 100%`,
|
||||
> 实际宽度由外层布局决定,**面板可拖拽调宽**;本次实测宽 **647px**。
|
||||
|
||||
| 元素 | 实测值 |
|
||||
| --- | --- |
|
||||
| `.detail-panel-container` | 647 × 871,**`border-left: 1px solid #ebebeb`** |
|
||||
| `.sidebar-next` | 646 × 871,背景 **`#fff`**,**`border-radius: 12px 12px 0 0`** |
|
||||
| `.detail-layout` | flex column,白底 |
|
||||
| `.detail-layout__top` | 646 × **64**(min-height 64) |
|
||||
| `.sidebar-next-main-header` | 646 × 64,**`padding: 0 16px`**,**`justify-content: space-between`**,`gap: 4px`,白底 |
|
||||
| `.artifact-tabs` | 高 32,`gap: 4px` |
|
||||
| `.artifact-tab`(当前项) | 240 × **32**(min-width 80 / max-width 240),**`padding: 0 8px`**,`gap: 4px`,**背景 `#f2f2f2`**,**圆角 8px**,**14px / 600**,行高 22 |
|
||||
| `.artifact-tab__icon` | **16 × 16**,色 `rgba(0,0,0,.7)` |
|
||||
| `.artifact-tab__close` | **14 × 14**,色 `rgb(119,119,119)`,`border-radius: 999px` |
|
||||
| `.artifact-tabs__add` | **32 × 32**,圆角 8,图标 16 × 16 |
|
||||
| 顶栏右侧操作 | 两个 **32 × 32** 按钮(`gap: 4px`),圆角 **6px**,图标 16 × 16,色 `rgba(0,0,0,.7)` |
|
||||
| `.detail-layout__content` | 646 × 807 |
|
||||
| `.detail-main__body` | 背景 `#fff` |
|
||||
|
||||
---
|
||||
|
||||
## 6. 图标采集与替换
|
||||
|
||||
真实界面的图标都是内联 SVG(`<svg><path fill="currentColor">`),不是字体图标(codicon 类名只在少量 VS Code 继承处出现)。
|
||||
|
||||
**采集链路**:`scripts/wb-icons.mjs`(CDP 取指定节点的 SVG outerHTML → `icons.json`)→ `scripts/gen-icons.mjs`(生成 `src/renderer/src/components/icons.tsx`)。
|
||||
|
||||
| YCode 组件 | 来源 | 尺寸 |
|
||||
| --- | --- | --- |
|
||||
| `IconNewTask` | 侧栏「新建任务」 | 16 |
|
||||
| `IconChevronDown` | 「发现应用」下拉箭头 | 14 |
|
||||
| `IconFilter` | 侧栏顶栏筛选 | 16 |
|
||||
| `IconCompact` / `IconSectionAdd` | 分组操作 | 16 |
|
||||
| `IconPlus` | 输入区「+」 | 16 |
|
||||
| `IconShield` | 「允许完全访问」盾牌 | 16 |
|
||||
| `IconChevronSmall` | 模型选择器箭头 | 12 |
|
||||
| `IconMic` | 语音输入 | 16 |
|
||||
| `IconStop` | 停止(圆底 + 圆角方块) | 32 |
|
||||
| `IconTab` | 详情面板页签 | 13 |
|
||||
| `IconClose` | 页签关闭 | 14 |
|
||||
| `IconChevronRight` | 「查看所有产物」 | 8 |
|
||||
| `IconPanelCollapse` / `IconPanelRight` | 面板收起 / 右侧栏 | 16 |
|
||||
|
||||
> ⚠️ **来源与替换要求**:`icons.tsx` 中的矢量路径取自 WorkBuddy 运行时界面,
|
||||
> 属于第三方产品界面资产,**仅作为当前阶段 1:1 还原的临时占位**(用户明确要求"先用 workbuddy 的,先 1:1 还原,然后再改造")。
|
||||
> **正式发布前必须整体替换**为自有图标或开源图标集。
|
||||
> 对比:VS Code codicon 为 MIT 许可,可长期使用;本项目的 `icons-extra.tsx` 是自有矢量,可保留。
|
||||
|
||||
---
|
||||
|
||||
## 7. 标题栏与菜单栏(实测)
|
||||
|
||||
| 元素 | 实测值 |
|
||||
| --- | --- |
|
||||
| 顶部条带 | **高 30px**,通栏 |
|
||||
| 左侧操作区 | x=0 宽 **92px**(侧栏顶部操作) |
|
||||
| `.codebuddy-menubar` | x=92 宽 227,`padding-left: 4px`,flex row,align center |
|
||||
| 菜单按钮 `.menubar-menu-button` | 高 **30px** |
|
||||
| 菜单标题 `.menubar-menu-title` | 高 24,**`padding: 2px 8px`**,**圆角 4px**,**12px** / 行高 20,色 **`rgb(139,148,158)` = `#8b949e`** |
|
||||
| 菜单项 | **编辑(E) / 窗口(W) / 帮助(H) / 关于(A)** |
|
||||
| 右侧窗口控制区 | x=2422 宽 **138px**(约 46px × 3:最小化 / 最大化 / 关闭) |
|
||||
|
||||
> 这是**自绘菜单**(VS Code 风格),不是系统原生菜单。YCode 已改为
|
||||
> `frame: false` 无边框窗口 + 渲染进程自绘标题栏(`components/TitleBar.tsx`),
|
||||
> 菜单项均接真实行为(编辑用原生 role、窗口用 IPC、帮助/关于打开对应对话框)。
|
||||
|
||||
**无边框窗口注意**:条带设 `-webkit-app-region: drag` 负责拖动窗口,
|
||||
按钮与菜单设 `no-drag`;主进程需 `Menu.setApplicationMenu(null)` 去掉原生菜单。
|
||||
|
||||
---
|
||||
|
||||
## 8. 空态与免责声明(实测自 CSS)
|
||||
|
||||
> 说明:采集时 WorkBuddy 处于会话中,页面无空态元素,以下取自**安装包 CSS 规则**(非冒烟实测),
|
||||
> 待用户切到新建对话页后可做一次 `wb-tree` 复核。
|
||||
|
||||
### 空态 `.claw-agent-chat-pane .colleague-chat-empty--profile`
|
||||
|
||||
| 元素 | 实测值 |
|
||||
| --- | --- |
|
||||
| 容器 | flex column,居中,`gap: 24px`(spacing-7),`padding: 0 16px`(spacing-5),text-align center |
|
||||
| 头像 | **64px**(spacing-12),`border: 1px solid` 边框色 `--wb-color-border-secondary` = **`#ebebeb`**,**`border-radius: 18px`**(radius-lg 8 + md 6 + sm 4),`margin-bottom: 16px` |
|
||||
| 标题 | **24px / 34 / 500**,色 text-primary |
|
||||
| 说明 | **`max-width: 324px`**,**12px / 18**,色 text-tertiary |
|
||||
| 快捷提问容器 | flex column,`align-items: flex-start`,`gap: 16px`(spacing-5) |
|
||||
|
||||
### 快捷提问胶囊 `.conversation-embed-empty__quick-prompt`
|
||||
|
||||
`min-height: var(--wb-size-control-md)`、**`padding: 10px 16px`**、**`border-radius: 9999px`**、
|
||||
背景 `--wb-color-bg-primary-default` = gray-3 **`#f2f2f2`**、文字 `color-mix(text-primary 90%, transparent)`、
|
||||
**14px**、行高 21、`white-space: nowrap`、`border: 0`。
|
||||
|
||||
### 免责声明 `.claw-local-empty__disclaimer` / `.conversation-embed-empty__disclaimer`
|
||||
|
||||
`padding: 8px 0`、text-align center、色 `--wb-color-text-disabled` = **`rgba(0,0,0,.3)`**、
|
||||
**12px**、`line-height: 20px`、`user-select: none`、`pointer-events: none`。
|
||||
文案:**「内容由 AI 生成,请核实重要信息」**。
|
||||
|
||||
### 输入区(空态变体)
|
||||
|
||||
`.claw-local-empty__input-area`:`width: 100%`、`max-width: 832px`、`padding: 0 16px`、`margin: 0 auto`。
|
||||
`.conversation-embed-empty__input-area`:`--cb-input-content-radius: 22px`、`--cb-input-main-area-radius: 22px`、
|
||||
`--cb-content-background: transparent`。
|
||||
|
||||
---
|
||||
|
||||
## 9. 间距阶(编号已与对标对齐)
|
||||
|
||||
| 编号 | 值 | 编号 | 值 |
|
||||
| ---: | ---: | ---: | ---: |
|
||||
| spacing-1 | 2px | spacing-7 | 24px |
|
||||
| spacing-2 | 4px | spacing-8 | 32px |
|
||||
| spacing-3 | 8px | spacing-9 | 40px |
|
||||
| spacing-4 | 12px | spacing-10 | 48px |
|
||||
| spacing-5 | 16px | spacing-12 | 64px |
|
||||
| spacing-6 | 20px | | |
|
||||
|
||||
> YCode 的 `--yc-space-N` **编号与之一一对应**,翻译对方 CSS 时无需换算。
|
||||
|
||||
---
|
||||
|
||||
## 10. 与 YCode 的差距(本轮已修 / 待修)
|
||||
|
||||
### 已修正
|
||||
|
||||
- **空态**:改为「64px 圆角头像(18px 圆角 + 1px `#ebebeb` 边框) + 标题 24px/500 + 说明 12px/18 max-width 324px + 胶囊快捷提问(`padding: 10px 16px`、圆角 9999、底色 `#f2f2f2`)」
|
||||
- **输入区下方免责声明**:新增「内容由 AI 生成,请核实重要信息」(12px、居中、色 `rgba(0,0,0,.3)`、`padding: 8px 0`)
|
||||
- **间距阶**:`--yc-space-N` 编号对齐对标 spacing 阶(原实现整体错位一档)
|
||||
- **标题栏 + 菜单栏**:Electron 原生菜单 → **无边框窗口(`frame: false`)+ 自绘 30px 条带**;菜单 `编辑(E)/窗口(W)/帮助(H)/关于(A)`,12px / `#8b949e` / 标题 `padding: 2px 8px` / 圆角 4;右侧 46px×3 窗口控制
|
||||
- 主文字 `#000` → **`rgba(0,0,0,.9)`**
|
||||
- 侧栏背景 `#f2f2f2` → **`#f7f7f7`**
|
||||
- 输入框:错误地改成渐变 → **改回白底 + 1px `#e6e6e6` + 圆角 24 + 双层阴影**,宽度 832 → **784**,`min-height` 96
|
||||
- 侧栏列表项:`padding 8px 20px` + 13px + 两行堆叠 → **31px 单行,`padding 5px 12px`,圆角 8,标题 14px 左 + 时间 11px 右**
|
||||
- 侧栏结构:改为「品牌行(64px) + 版本行 + 导航项 + 分组标签(30px) + 列表项」
|
||||
- 右侧详情面板:默认显示 → **默认收起**(对齐真实默认态);展开态已按实测改为「顶栏 64px + 页签 32px/圆角8/底色 #f2f2f2/14px600 + 右侧 32×32 操作按钮(圆角6)」,面板白底 + 上圆角 12 + `border-left 1px #ebebeb`
|
||||
- **详情面板拖拽调宽**:新增 `.app-shell__resizer` 手柄(0 宽网格列 + 6px 命中区伪元素,hover/拖拽显示品牌色指示线);宽度状态在 `App.tsx`,以 `--yc-layout-right` 注入网格;范围 **320–900px**,默认 **647px**(对齐实测值)。面板收起时手柄一并卸载。已实测:左拖 150px → 797px、右拖收窄、越界夹在 320 / 900
|
||||
|
||||
### 待补(需要真实界面数据)
|
||||
|
||||
- 侧栏顶部完整导航项(助理 Beta / 专家·技能·连接器 / 定时任务 / 资料库 / 更多)—— YCode 目前只实现「新建对话」与「任务」分组,不伪造未实现入口
|
||||
- 权限选择器、麦克风等输入区工具项
|
||||
- 图标集:真实界面用 SVG 图标(16×16),YCode 已接入采集图标(见第 6 节,正式发布前需替换)
|
||||
|
||||
---
|
||||
|
||||
## 10.1 对话区顶栏(补充实测)
|
||||
|
||||
| 元素 | 实测值 |
|
||||
| --- | --- |
|
||||
| `.workbuddy-topbar` | 高 **64px**,**`padding: 0 16px`**,align-items center,**justify-content: space-between** |
|
||||
| `.workbuddy-topbar-options` | 高 32px,位于顶栏内部左右两端 |
|
||||
| 顶栏下方首行 | `.cr-collapse--summary`(「已完成 3m2s」行),字号 13px |
|
||||
|
||||
> 据此 YCode 的 `.chat-head` 由自拟的 `padding: 12px 20px 10px` 改为
|
||||
> **高 64px / `padding: 0 16px` / 两端对齐**,与实测一致。
|
||||
|
||||
---
|
||||
|
||||
## 11. 完整 design token 表(对标体系镜像)
|
||||
|
||||
来源:安装包 `tokens-Df-i-zsO.css` / `contexts-BkjwYSZT.css`。
|
||||
**YCode 的 `--yc-*` 编号与对标 `--wb-*` 一一对应**,翻译对方 CSS 时是机械映射。
|
||||
|
||||
### 11.1 间距阶 `--wb-spacing-N`
|
||||
|
||||
| N | 值 | N | 值 |
|
||||
| ---: | ---: | ---: | ---: |
|
||||
| 1 | 2px | 7 | 24px |
|
||||
| 2 | 4px | 8 | 32px |
|
||||
| 3 | 8px | 9 | 40px |
|
||||
| 4 | 12px | 10 | 48px |
|
||||
| 5 | 16px | 12 | 64px |
|
||||
| 6 | 20px | | |
|
||||
|
||||
### 11.2 字号阶 `--wb-font-size-N`
|
||||
|
||||
| N | 值 | N | 值 |
|
||||
| ---: | ---: | ---: | ---: |
|
||||
| 1 | 8px | 7 | 18px |
|
||||
| 2 | 10px | 8 | 20px |
|
||||
| 3 | 12px | 9 | 24px |
|
||||
| 4 | 13px | 10 | 28px |
|
||||
| 5 | 14px | 11 | 32px |
|
||||
| 6 | 16px | | |
|
||||
|
||||
行高:`4:16` `4-2:18` `5:20` `5-2:22` `6:24` `7:28` `8:32` `10:40`
|
||||
字重:`400` `500` `600` `700`
|
||||
|
||||
### 11.3 控件尺寸阶 `--wb-size-N`
|
||||
|
||||
| N | 值 | N | 值 |
|
||||
| ---: | ---: | ---: | ---: |
|
||||
| 3 | 12px | 9 | 36px |
|
||||
| 3-2 | 14px | 10 | 40px |
|
||||
| 4 | 16px | 11 | 44px |
|
||||
| 5 | 20px | 12 | 48px |
|
||||
| 6 | 24px | 13 | 52px |
|
||||
| 7 | 28px | 14 | 56px |
|
||||
| 8 | 32px | 17 | 68px |
|
||||
|
||||
语义别名:`control-sm 24` `control-ms 28` `control-md 32` `control-lg 40` `control-xl 48` `control-2xl 56`
|
||||
|
||||
### 11.4 圆角阶 `--wb-radius-*`
|
||||
|
||||
`none 0` `xs 2` `sm 4` `md 6` `lg 8` `xl 12` `2xl 16` `3xl 20` `4xl 24` `full 9999`
|
||||
|
||||
### 11.5 语义字号(体例)
|
||||
|
||||
| 角色 | 字号 | 行高 | 字重 |
|
||||
| --- | ---: | ---: | ---: |
|
||||
| body | 14 | 22 | 400 |
|
||||
| body-strong | 14 | 22 | 600 |
|
||||
| caption | 12 | 18 | 400 |
|
||||
| code | 13 | 20 | 400 |
|
||||
| h1 | 24 | 32 | 600 |
|
||||
| h2 | 20 | 28 | 600 |
|
||||
| h3 | 16 | 24 | 600 |
|
||||
| display | 32 | 40 | 700 |
|
||||
|
||||
### 11.6 语义字号(对话流 chatflow,对标独立一套)
|
||||
|
||||
| 角色 | 字号 | 行高 |
|
||||
| --- | ---: | ---: |
|
||||
| h1 | 21 | 37 |
|
||||
| h2 | 19 | 33 |
|
||||
| h3 | 17 | 30 |
|
||||
| h4 | 15 | 26 |
|
||||
| p1 | 15 | 26 |
|
||||
| p2 | 13 | 23 |
|
||||
| p3 | 11 | 19 |
|
||||
|
||||
### 11.7 全局字号档位(六档)
|
||||
|
||||
机制:级别存 localStorage,同时更新「Markdown 根字号」与「全局字号偏移」;
|
||||
偏移经 `clamp(-1, global, 2)` 夹取后作用于各语义 token。
|
||||
|
||||
| 档位 | `--cb-md-root` | 全局偏移 |
|
||||
| ---: | ---: | ---: |
|
||||
| 1 | 16px | −1 |
|
||||
| 2(默认) | 17.143px | 0 |
|
||||
| 3 | 18.286px | +1 |
|
||||
| 4 | 20.571px | +2 |
|
||||
| 5 | 22.857px | +2 |
|
||||
| 6 | 26.286px | +2 |
|
||||
|
||||
快捷键:`Ctrl+-` 降档、`Ctrl++` 升档、`Ctrl+0` 恢复默认。
|
||||
|
||||
> **YCode 的实现差异**:因组件样式已全部 token 化,**不需要**像对标那样扫描样式表注入覆盖规则;
|
||||
> 只改 `--yc-font-offset-global` 与 `--yc-md-root` 两个根变量即可全局生效。
|
||||
> 未实现对标的 `.cb-font-size-fixed` 例外类——目前没有固定字号的控件需要豁免。
|
||||
|
||||
### 11.8 字体族
|
||||
|
||||
- 正文:`'PingFang SC', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', sans-serif`
|
||||
- 等宽:`ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace`
|
||||
|
||||
### 11.9 实测常量(不在标准阶内,对标自身也硬写)
|
||||
|
||||
`scrollbar 6px`、`菜单最小宽 200px`、`窗口控制图标 10px`、`侧栏项高 31px`、`侧栏项纵向 padding 5px`、
|
||||
`行高 19 / 21 / 24.5 / 26.25`、`列表缩进 21.45px`、`气泡 max-height 310px`、`工具卡正文 max-height 320px`、
|
||||
`空态头像圆角 18px`、`空态说明 max-width 324px`、`输入 min-height 96px`、`选项卡 80–240px`、
|
||||
`对话框 560 / 420px`
|
||||
|
||||
---
|
||||
|
||||
## 12. REA 拆解证据与工具边界
|
||||
|
||||
### 12.1 归档级拆解(已执行)
|
||||
|
||||
```
|
||||
open_binary app.asar → format=asar, kind=archive
|
||||
sha256 035254bc…729de918
|
||||
inspect_artifact (record-and-continue) → 12253 节点 / 17356 occurrence / 14476 文件 / 2880 目录
|
||||
45 处完整性矛盾(观察值标记为 untrusted)
|
||||
```
|
||||
|
||||
**完整性矛盾**:首条为 `cli/bin/native/win32-x64/job-object.node`——声明的 sha256 与伴随文件不符。
|
||||
REA 指出这是常见现象(打包工具会在写入归档后对未打包的原生二进制签名或裁剪),
|
||||
但该模块正是**绑定子进程树的 Windows Job Object 原生实现**,与 GPU 沙箱受限环境的观察一致,
|
||||
值得单独留意。
|
||||
|
||||
### 12.2 工具边界(重要)
|
||||
|
||||
REA 的 CDP 浏览器 provider **只枚举 HTTP(S) 页面目标**。
|
||||
WorkBuddy 的渲染器是 `file://` URL,因此:
|
||||
|
||||
```
|
||||
list_browser_targets http://127.0.0.1:9223
|
||||
→ targets: [] excluded: { unsupported_url: 1 }
|
||||
→ limitations: "All page targets with supported HTTP(S) URLs are listed."
|
||||
```
|
||||
|
||||
**结论:REA 的浏览器类工具(`inspect_web_page` / `capture_web_screenshot` /
|
||||
`compare_web_captures`)目前无法观察 WorkBuddy 主窗口。**
|
||||
对 `file://` 渲染器的 Electron 应用,实测采集需要直接用 CDP(本项目的
|
||||
`scripts/wb-capture.mjs` / `wb-tree.mjs` / `wb-icons.mjs`)。
|
||||
YCode 开发态走 `http://localhost`,REA 浏览器工具对其可用。
|
||||
|
||||
同理,REA 的二进制 provider(Ghidra / IDA / Hopper)在本机均未配置,
|
||||
且不接归档目标("Ghidra v1 imports executable targets, not archive targets"),
|
||||
因此**无字符串检索能力**;token 表据以从归档内 CSS 文件直接提取。
|
||||
|
||||
---
|
||||
|
||||
## 13. 外围壳层完整结构(第二轮实测)
|
||||
|
||||
采集脚本:`scripts/wb-shell.mjs`(输出侧栏完整子树 + 外围元素清单)
|
||||
|
||||
> **重要发现**:侧栏宽度**不是常量**。两次采集分别为
|
||||
> **280px(@1334 窗口)** 与 **240px(@1276 窗口)**,说明该宽度本身可变(可拖拽或随窗口变化)。
|
||||
> YCode 取 280px 作为展开默认值,并支持收起为 44px 窄轨。
|
||||
|
||||
### 13.1 品牌区
|
||||
|
||||
| 元素 | 实测值 |
|
||||
| --- | --- |
|
||||
| `.conversation-list-logo-row` | 215×**64**(min-height 40),`gap: 4px`,align center |
|
||||
| `.conversation-list-brand-block` | flex column,align flex-start,`padding-top: 4px` |
|
||||
| `.conversation-list-brand-line` | 90×22,`padding-left: 12px`,`gap: 8px` |
|
||||
| 品牌标题 | **14px / 700** / 行高 22,色 `rgba(0,0,0,.9)` |
|
||||
| `.conversation-list-version-row` | 40×18,`padding-left: 12px`,`margin-top: -4px`,`gap: 6px` |
|
||||
| 版本徽标 | **10px** / 行高 18,`letter-spacing: .2px`,色 `rgba(0,0,0,.5)` |
|
||||
| 「发现应用」按钮 | 98×**28**,`padding: 4px 6px 4px 8px`,`gap: 2px`,背景 `#f2f2f2`,色 `rgba(0,0,0,.7)`,边框 1px `#ebebeb`,**圆角 100px**,**12px / 500** / 行高 20 |
|
||||
| └ 左侧图标 / 右侧箭头 | 各 14×14;箭头色 `rgba(0,0,0,.3)`;文字 12px/400 |
|
||||
|
||||
### 13.2 导航项(实测 `.conversation-list-tab-button`)
|
||||
|
||||
| 项 | 备注 |
|
||||
| --- | --- |
|
||||
| 新建任务 | 主入口 |
|
||||
| 助理 | 带 **Beta** 徽标 |
|
||||
| 专家·技能·连接器 | |
|
||||
| 定时任务 | |
|
||||
| 资料库 | |
|
||||
| 更多 | 右侧附 **「灵感」** 副文案 |
|
||||
|
||||
尺寸:**215×32**,`padding: 5px 12px`,`gap: 8px`,**圆角 8px**,图标 **16×16**,标签 **14px** / 行高 22。
|
||||
|
||||
- Beta 徽标:**10px / 500** / 行高 16,`padding: 0 5px`,边框 1px `#dedede`,圆角 100px,色 `rgba(0,0,0,.45)`
|
||||
- 「灵感」副文案:**11px** / 行高 20,色 `rgba(0,0,0,.5)`
|
||||
|
||||
### 13.3 分组
|
||||
|
||||
| 元素 | 实测值 |
|
||||
| --- | --- |
|
||||
| 分组标签 `.conversation-section-label` | **215×30**,`padding: 5px 12px`,`gap: 4px`,背景 `#f7f7f7`,**圆角 8px**,**`position: sticky`** |
|
||||
| 分组文字 | **12px / 600** / 行高 20,色 `rgba(0,0,0,.5)`,形如「任务 (1)」「空间 (2)」 |
|
||||
| 折叠箭头 | 14×14,色 `rgba(0,0,0,.3)`,**默认 opacity 0**(hover 显现) |
|
||||
| 分组操作按钮 | **20×20**,圆角 4px,色 `rgba(0,0,0,.5)`,默认 opacity 0 |
|
||||
| 空间分组头 `.collapsible-section header` | **215×34**,`padding: 5px 12px`,`gap: 4px`,背景 `#f7f7f7`,圆角 8px |
|
||||
| └ 图标 / 名称 | 16×16 / **14px** 行高 22 |
|
||||
|
||||
### 13.4 底部账号区(实测)
|
||||
|
||||
| 元素 | 实测值 |
|
||||
| --- | --- |
|
||||
| `.conversation-list-footer` | 239×**57**,`padding: 8px 12px 8px 8px`,**`border-top: 1px solid #e6e6e6`** |
|
||||
| `.user-menu` | 219×**40**,`gap: 4px` |
|
||||
| `.user-menu-trigger` | 147×40(min-height 40),`padding: 6px 8px`,**圆角 8px**;内部 `gap: 10px` |
|
||||
| 头像 | **28×28**,`border-radius: 50%`,背景 `#ebebeb`,**12px / 500** |
|
||||
| 用户名 | **12px / 600**(`.user-menu-trigger-name` 高 12) |
|
||||
| 通知按钮 | **32×32**,圆角 6px,色 `rgba(0,0,0,.7)`,图标 16×16 |
|
||||
| 未读角标 `.msg-center-badge` | **14×14**,背景 **`#f64041`**,白字,`border-radius: 7px`,**9px / 500** / 行高 14,`padding: 0 3px` |
|
||||
| 小程序按钮 | 32×32,圆角 6px,图标 16×16 |
|
||||
|
||||
### 13.5 输入区补充
|
||||
|
||||
`.cr-permission-setting`(「允许完全访问」):**132×32** —— 权限选择器实为 32px 高控件。
|
||||
|
||||
---
|
||||
|
||||
## 14. Mock 数据约定
|
||||
|
||||
用户明确要求「登录账号先用 mock 写死数据」。约定:
|
||||
|
||||
| 文件 | 内容 | 替换时机 |
|
||||
| --- | --- | --- |
|
||||
| `src/renderer/src/mock.ts` | 账号、通知、空间、导航项清单 | 接入真实数据源时整体替换 |
|
||||
|
||||
**约束(已落实)**:
|
||||
|
||||
1. 所有导出一律 **`MOCK_` 前缀**,便于全局检索替换
|
||||
2. 使用处**必须在 UI 上显式标注**为示例数据:
|
||||
- 通知面板底部:「示例数据 · 尚未接入消息中心」
|
||||
- 设置 → 账号:「账号信息为 mock 写死数据,尚未接入登录」
|
||||
- 账号按钮 `title`:「账号为 mock 数据」
|
||||
3. **未实现的入口不做假交互**:点击给出 2 秒临时提示(如「『专家·技能·连接器』尚未实现」),
|
||||
不伪造可用状态。这是对外围壳层「配齐」与「不虚构能力」两条要求的折中。
|
||||
|
||||
---
|
||||
|
||||
## 15. 首页 / 新建任务页(空态)—— 冒烟实测
|
||||
|
||||
> 采集方式:用户批准「方案 B」后,由 CDP 直接点击侧栏「新建任务」切换页面后采集。
|
||||
> 脚本:`scripts/wb-probe.mjs`(按文案定位,应对 CSS Module 哈希类名)、`scripts/wb-home.mjs`、`scripts/click-shot.mjs`
|
||||
> 参考截图:`docs/screenshots/wb-home-reference.png`
|
||||
|
||||
### 15.1 页面构成(自上而下)
|
||||
|
||||
1. 大标题:**「WorkBuddy, 我帮你」**
|
||||
2. 分段控件 `.wb-segmented`:[办公][开发][设计]…(场景切换)
|
||||
3. **分类胶囊行** `.quick-actions__list`
|
||||
4. **输入框**(比会话内更高)
|
||||
5. 工作目录 + 权限行(📁 YCode ⌄ / 🔒 允许完全访问 ⌄)
|
||||
6. **建议条目列表**(整行胶囊 + 右上箭头)
|
||||
7. 底部免责声明:内容由 AI 生成,请核实重要信息
|
||||
|
||||
### 15.2 实测尺寸
|
||||
|
||||
| 元素 | 实测值 |
|
||||
| --- | --- |
|
||||
| 分类行 `.quick-actions__list` | **宽 680**,flex row,**`gap: 8px`**,align center |
|
||||
| 分类胶囊 `.quick-actions__item` | **高 32**,`padding: 0 12px`,`gap: 4px`,背景 **`#f7f7f7`**,色 `rgba(0,0,0,.9)`,边框 **1px `#dedede`**,**`border-radius: 100px`**,**14px / 400** |
|
||||
| 分段控件 `.wb-segmented` | 高 32,**`border-radius: 9999px`**,`gap: 2px` |
|
||||
| 分段项 `.wb-segmented__item` | **72×32**,`padding: 5px 12px`,`gap: 4px`,圆角 9999px,**14px / 600**,阴影 `rgba(0,0,0,.05) 0 1px 4px 0` |
|
||||
| **首页输入编辑区** `.cr-input-editor-host` | **798 × 74**,`min-height: 74px`,`padding: 0 16px` |
|
||||
| 输入占位符 | 15px / 26.25px,色 `rgba(0,0,0,.9)`;文案「今天帮你做些什么?@ 添加上下文,/调用技能与指令」 |
|
||||
|
||||
> **注意**:首页编辑区 **74px**,会话内是 **64px** —— 两者不同,不能共用。
|
||||
|
||||
### 15.3 分类清单(实测)
|
||||
|
||||
`办公` `开发` `设计` `创作文档` `金融服务` `分析数据` `制作PPT` `深度研究` `策划方案` `定时任务`
|
||||
|
||||
> YCode 已按此实现分类行(`--yc-*` token 化),点击分类把对应提示词填入输入框(真实可用,
|
||||
> 提示词为自拟,非对标文案)。
|
||||
|
||||
### 15.4 与旧实现的差异(已修正)
|
||||
|
||||
旧空态是「56px 头像 + 大标题 + 竖排胶囊」——那是**从 CSS 规则推断**的 `.colleague-chat-empty--profile`,
|
||||
**与真实首页不符**。真实首页没有头像,改为「大标题 + 横排分类 + 建议列表」。已按实测重写。
|
||||
|
||||
### 15.5 垂直结构精测(第三轮,`scripts/wb-home-layout.mjs` + `wb-home-parts.mjs`)
|
||||
|
||||
> 本轮发现第一轮实现**整体结构错误**:我把输入框放页面底部、10 个分类挤一行。
|
||||
> 真实首页是**居中内容列**,输入框在页面中部、建议列表在其下方。
|
||||
|
||||
| 区块 | 实测 rect(视口 1276×901) |
|
||||
| --- | --- |
|
||||
| 标题 `h1.wb-home-header__title` | `[614, 159, 278, 42]` —— **30px / 600 / 行高 42**,色 `rgb(0,0,0)`,`gap: 10px` |
|
||||
| 分段控件 `.wb-segmented` | `[643, 219, 220, 32]` —— 居中于内容列(中心 753) |
|
||||
| 分类行 `.quick-actions` | `[353, 317, 680, 32]` —— **左对齐于内容列** |
|
||||
| 输入框外层 `.wb-home-route__input-box` | `[353, 365, 800, 184]`,flex column **`gap: 12px`** |
|
||||
| └ 白框 `.cr-input-container` | `[353, 365, 800, 144]`,圆角 24,`padding-top: 12`,白底 + 双层阴影 |
|
||||
| └ 编辑区 `.cr-input-editor-host` | `[354, 378, 798, 74]`,`padding: 0 16px` |
|
||||
| └ 工具栏 `.cr-input-toolbar` | `[354, 452, 798, 56]`,`padding: 12px`,space-between |
|
||||
| 权限项 `.cr-permission-setting` | `[461, 513, 132, 32]`,圆角 999px,**13.33px**,色 `rgb(180,44,63)` |
|
||||
| 建议项 `.wb-home-prompt-list__row` | `[353, 601, 238, 38]` 起 —— **高 38 / 圆角 9999 / 白底 / 边框 1px `#e6e6e6` / 14px**,**行距 50**(38 + 12),左对齐 |
|
||||
|
||||
**垂直间距**:标题底 201 → 分段 219 = **18**;分段底 251 → 分类 317 = **66**;
|
||||
分类底 349 → 输入 365 = **16**;输入底 549 → 建议 601 = **52**。
|
||||
|
||||
**结构结论**:
|
||||
1. 内容列 **x=353、宽 800**,整体居中(中心 753 ≈ 内容区中心 758)
|
||||
2. **输入框不是底部停靠**,在页面中部;建议列表在其下方
|
||||
3. 分类分两处:**分段控件 3 个(办公/开发/设计)** + **胶囊行 7 个**,不是 10 个一行
|
||||
4. 输入框下方有「工作目录 + 权限」行,**在输入框外层容器内部**(184 = 144 + 40)
|
||||
5. 白框 **144 = 12 + 74 + 56 + 2,纵向无 gap**(YCode 早期实现误加 4px gap → 148,已修)
|
||||
6. 会话内输入框 **134 = 12 + 64 + 56 + 2**,同为无 gap
|
||||
|
||||
**已实现**:`ChatPane` 拆为 `composer`(两种变体共用,`data-variant` 区分编辑区高度)+
|
||||
`composerFooter`(工作目录/权限行);首页走 `.home` 布局,会话走原底部停靠布局。
|
||||
分段控件用前 3 个分类,胶囊行用后 7 个,与对标结构一致。
|
||||
|
||||
---
|
||||
|
||||
## 16. OMP 内核接入(底层循环替换)
|
||||
|
||||
**架构决策(用户拍板)**:YCode 从「自建网关 + 自写 agent 循环」转为 **OMP 前端壳**。
|
||||
|
||||
### 16.1 事实
|
||||
|
||||
| 项 | 值 |
|
||||
| --- | --- |
|
||||
| OMP 可执行文件 | `C:\Users\Administrator\AppData\Local\Ygent\omp.exe`(随 Ygent 安装) |
|
||||
| 版本 | `omp/18.6.3` |
|
||||
| 协议 | `--mode rpc`:stdio 上的 **newline-delimited JSONL**,启动先发 `ready` 帧,单帧上限 1 MiB |
|
||||
| Profile | `~/.omp/profiles/ycode/agent/models.yml`(独立 profile,不动用户 ygent 配置) |
|
||||
| 上游 | `https://api.iiiii.run/v1`,**`api: openai-responses`**,模型 `gpt-6-luna/astra/6.1-sol` |
|
||||
|
||||
### 16.2 实现
|
||||
|
||||
| 文件 | 职责 |
|
||||
| --- | --- |
|
||||
| `src/main/omp.ts` | sidecar 管理:spawn + JSONL 解析 + 命令关联(id)+ ready 等待 + 退出清理;`detectOmpPath()` 探测可执行文件 |
|
||||
| `src/main/agent/omp-turn.ts` | OMP 事件 → YCode `ChatEvent` 映射(渲染进程零改动) |
|
||||
| `src/main/ipc.ts` | **会话 → 内核进程** 池;会话删除时释放进程;OMP 不可用时**回退自建循环** |
|
||||
|
||||
**事件映射**:
|
||||
|
||||
| OMP 事件 | YCode ChatEvent |
|
||||
| --- | --- |
|
||||
| `message_update.assistantMessageEvent.type = "text_delta"` | `text` |
|
||||
| `tool_execution_start` / `_update` / `_end` | `tool_call` / `tool_result` |
|
||||
| `agent_end`(`yielded !== false`) | `done` |
|
||||
| `prompt_result.status = "error"` / `notice(level=error)` | `error` |
|
||||
| abort | `cancelled` |
|
||||
|
||||
**踩过的坑**:
|
||||
1. `spawn` 报 `ENOENT` 但可执行文件明明存在 —— 是 **cwd 不存在**(工作目录为空字符串)。
|
||||
spawn 的 `cwd` 与可执行路径无关,必须单独兜底(现回退到用户主目录)。
|
||||
2. OMP 工具事件载荷文档未给全 → `readToolInfo()` 做**多形状兼容解析**
|
||||
(`toolCall/call/tool/data` 逐层找 `id/name/arguments`)。
|
||||
|
||||
### 16.3 端到端验证
|
||||
|
||||
```
|
||||
发送「只回复两个字:收到」 → 回复「收到」(omp.exe 被拉起)
|
||||
发送「用 list_dir 列出工作目录文件」 → 3 张工具卡:glob / read / bash(OMP 原生工具)
|
||||
全部 ok;回复「工作目录根目录下有 12 个文件。」
|
||||
```
|
||||
|
||||
> 注意工具名是 **OMP 自己的工具集**(glob/read/bash),不再是 YCode 的 `list_dir/read_file`
|
||||
> —— 内核真正接管。YCode 自带的 `agent/tools.ts` 在 OMP 可用时不再使用(保留代码作回退)。
|
||||
|
||||
### 16.4 遗留
|
||||
|
||||
- 取消链路已接(`abort`),但未做端到端验证
|
||||
- 工具事件载荷的解析是**容错**的,若 OMP 未来改字段名可能拿不到 name/args(UI 会显示 `tool`)
|
||||
- OMP 进程按会话存活:长会话会常驻一个 omp.exe;会话删除时释放
|
||||
- `~/.omp/profiles/ycode` 里的 key 有额度限制,过期后回合会失败(届时换 key 即可)
|
||||
@@ -0,0 +1,33 @@
|
||||
# 过程消息展开与思考项显示对照(2026-10-16)
|
||||
|
||||
## 结论
|
||||
|
||||
WorkBuddy 5.8.2 会在展开已完成的回合后,把“深度思考”、普通工具操作和回复正文放在同一条消息时间线上显示。用户提供的 YCode“看一下当前项目”截图呈现了相同的基本结构:外层“已完成 24s”展开后,思考项与“已列出”“已读取”等工具项按过程顺序出现。因此,对“WorkBuddy 是否也会这样展示”的回答是:**会,展示机制和整体组织方式一致。**
|
||||
|
||||
这只确认过程展示的结构,不代表这两个截图逐像素一致,也不证明它们来自相同的工具轨迹。
|
||||
|
||||
## YCode 当前样本
|
||||
|
||||
截图来自用户提供的当前 YCode 空间会话“看一下当前项目”,已存档为 `.tmp/ycode-completed-24s-details-expanded.png`。截图中外层完成折叠已展开,能看到目录/文件访问结果与多条“深度思考”项交替出现;思考块和工具行保留各自的标题、图标及展开提示。
|
||||
|
||||
`.tmp/ycode-completed-24s-expanded.png` 是此前仅展开外层完成折叠的另一个状态,不要把它当成本次用户提供的内层详情截图。
|
||||
|
||||
## WorkBuddy 5.8.2 依据
|
||||
|
||||
- 固定 JS 源码 Evidence:`ev_717fa5e846e64d67ac19c8925d121bff632c0d3aefb3603b10858559cabb2dcb`;源文件 `renderer/assets/src-DbE1_mgM.js`,SHA-256 `6c6ce63c93854783270e855572797d75e536e3b8d4548410e31fe9d147e1feb4`。恢复出的折叠逻辑将 reasoning 与普通工具调用标记为可折叠项,按正文锚点把中间过程放进可展开区;普通工具与思考可在同一过程里按原顺序出现。提问和展示 widget 等类别走特殊规则,不能一概套用普通工具行为。
|
||||
- WorkBuddy 运行时 DOM/截图 Evidence:`ev_5743426dbec2ba8116957f5ba47d9e0305140b3d15e9b3b6f9bb504054e407f7`,由 REA `inspect_electron_page` 在 WorkBuddy 5.8.2 页面取得。配套截图为 `.tmp/rea-visual-tool-expanded/workbuddy.png`。图中“已完成 1m27s”展开后包含“深度思考”、回复正文、“运行命令”和“编辑 MEMORY.md”等过程项,直接证明原版会将思考与工具操作共同呈现在已完成回合中。
|
||||
- WorkBuddy 静态证据用于说明分类与折叠规则;运行时截图用于证明该界面形态真实出现。截图来自另一条会话,不含本次 YCode 的 `list_dir`/`read_file` 轨迹,也不是与 YCode 同提示、同模型、同输出的成对样本。
|
||||
|
||||
## 对齐状态与下一步
|
||||
|
||||
当前可确认:YCode 已呈现 WorkBuddy 同类的完成耗时、思考块、工具动作行及过程顺序;本轮没有发现需要因这张截图立即改动的结构性缺项。
|
||||
|
||||
仍未确认:两边完全相同的行分组、思考块展开状态、图标与间距、滚动位置及动效。要把这一段标为 1:1,需要对同一提示和等价工作区取得 WorkBuddy 原版运行时截图,再通过 REA 记录并与 YCode 同状态比较。当前结论仍以用户指定复用的 WorkBuddy 5.8.2 证据为基线;不外推到 5.8.3。
|
||||
|
||||
## 2026-10-17 YCode 流式检查项修正
|
||||
|
||||
YCode 曾将 Responses `reasoning.summary_text` 原样显示为“深度思考”正文,也曾将连续的 reasoning/工具事件包成有子项的摘要行。后者造成不应有的视觉父子关系;前者又让思考块展开后为空。现已修正:流式阶段只保留一条动作行,按最新 reasoning 或工具事件原位更新;reasoning 片段合并到独立的“深度思考”块,展开后用 Markdown 显示;动作行不再包住工具明细。回合完成后,各思考和工具项按事件顺序平铺显示。`list_dir` / `Inspect` 使用终端图标,检查工具的原始英文 intent 不进入状态行,状态文案由当前工具摘要生成。
|
||||
|
||||
依据仍为 WorkBuddy 5.8.2。REA runtime Evidence `ev_5743426dbec2ba8116957f5ba47d9e0305140b3d15e9b3b6f9bb504054e407f7` 的一个已完成会话中,思考块标题可见且内容容器为空;同一画面把命令呈现为单条折叠项。该样本没有用户本次的同一思考文本,不能据此把原版思考块概括为空。原版 summary closure 的既有 Evidence 为 `ev_717fa5e846e64d67ac19c8925d121bff632c0d3aefb3603b10858559cabb2dcb`;它用于工具摘要规则,不作为工具父子关系的证据。
|
||||
|
||||
本次 YCode 回归覆盖初始动作行随新工具事件更新、单条行没有可展开的父级摘要、深度思考正文可展开且 Markdown 格式正常、完成态工具项平铺和终端图标;`npm run test:conversation` 与 `npm run build` 通过。尚未对 YCode 实际流式窗口与 WorkBuddy 取得同状态成对截图,因此全状态像素和动效仍未验收。
|
||||
@@ -0,0 +1,77 @@
|
||||
# 持续复刻进度(2026-10-16)
|
||||
|
||||
> 能力中心最新:已实现三页入口、本地技能完整生命周期、自定义 MCP 管理/真实 SDK host,以及 OMP/备用 Gateway 技能与连接器调用。完整应用14项+新进程恢复6项通过,最终版本已更新当前用户 YCode、原会话恢复。专家包创建/激活及云目录/授权仍待接,全状态1:1未完成;具体源码证据、原生几何、验证记录和边界见 [能力中心与本地能力接入](能力中心与本地能力接入-2026-10-16.md)。
|
||||
|
||||
用户授权:持续推进至可以修改模型、创建空间、正常对话;UI 1:1。必要时允许通过 REA 在 WorkBuddy 发测试消息。本轮没有向 WorkBuddy 发送消息,也未使用其模型服务。
|
||||
|
||||
> 最新:用户已更新当前模型为 `gpt-6-luna` 和完整 `/v1/responses` 地址。已修复连接测试、OMP 和备用 Gateway 的 Responses 协议识别;**真实用户上游连接测试与两轮对话、上下文回忆、磁盘保存已通过**,已返回原会话。此前 ECONNREFUSED 是旧配置历史结果,当前不再作为外部阻碍。详见 [Responses 协议与真实对话验收](Responses协议与真实对话验收-2026-10-16.md)。全 UI 1:1 仍未完整验收。
|
||||
|
||||
## 已接入的真实功能
|
||||
|
||||
- `models.json` 多模型注册表,旧网关配置迁移但不覆盖;安全存储密钥,CRUD/选择/未保存配置连接测试。编辑留空保留密钥。
|
||||
- 每会话绑定 `workspaceId/cwd/modelId`;模型配置在每轮开始冻结并传入 OMP。独立不可变 OMP profile 不落盘明文密钥,仅使用子进程环境。
|
||||
- `workspaces.json` 真实目录创建/导入/重命名显示名/移除注册;丢失目录报错。侧栏真实任务分组,新建任务先草稿、首条发送才落盘。
|
||||
- 900×680 独立模型设置窗口,表单恢复固定源 CSS;首页/模型菜单/空间弹窗/右工作台继续对照。
|
||||
- 导入历史 6 次取消修为 cancelled、429 保留 error;真实 raw 工具字段保留,别名只在展示层映射。启动迁移幂等并保护用户编辑。
|
||||
- 右工作台按会话独立标签/资源请求/关闭/重排,文件/图片/产物/历史变更可预览;实际 21 引用去重得 13 产物,不硬编码结果。
|
||||
- 首页办公/开发/设计三场景、真实模型选择、240×341 空间菜单及搜索/创建/导入/不使用空间;取消和再次选择同一路径返回不同结果,异步回调不串草稿。
|
||||
- 真实 WebContentsView 浏览器及 Windows ConPTY/xterm 终端;标签/会话所有权、输入、导航、目录、关闭和进程释放。修正 node-pty 在生产构建中被内联后原生加载路径失效的问题。
|
||||
- 右栏恢复原 12 个布局函数、7 项常量和 16 条分栏动效 CSS;Grid drawer 15 条源 CSS。普通栏360、资源初开可用区域半宽、宽度拖动与记忆、1000/640 阈值及24px滞后、mobile600、打开200ms/关闭150ms、抽屉300ms、全屏 portal及 reduced-motion 宿主适配。
|
||||
- 已在真实用户 YCode 注册当前项目目录为 YCode 空间,并仅为此前未绑定 cwd 的“开始新会话”导入副本绑定同一目录。原版 REA JSONL 的 cwd 支持此绑定;未改变原版 WorkBuddy 或导入副本消息内容。
|
||||
- 对话顶部栏已换原版源 DOM/CSS/8个SVG;标题可编辑保存、当前对话全文搜索及导航、高亮和右栏按钮条件已接真实回调。云端分享仅保留诚实的未接入反馈。
|
||||
- 首页已替换为实际运行时黑猫完整 PNG,而非默认灰猫或截图片段。REA 已加载资源导出:`ev_474129797ce3ab73eaaab2cd41247653e7f128c3b89b598158b57b74e1f17e88`,SHA `2713ed5bbf1288d56ebeaca49bfb0d622c967914ab9c98955cc995932049e7e8`,13,426 bytes,180×180;保留原140×140图像、120×120 clip布局。
|
||||
- 主窗口/独立设置窗口共用持久化主题;重用设置窗口时能从外观页正确导航回模型页,关闭重开仍保持主题。
|
||||
- 首页模型菜单“自定义模型”现在按原版 `openSettings('models','new')` 直接进入添加表单;原生窗口复用及一次性 intent 消费已接入。
|
||||
- 普通文本/代码预览已替换 `<pre>` 为原版随包 Monaco、SearchWidget、主题和语言资源,共101个固定 REA 资产。font13/line20、readonly、wrap、行号、10px滚动条及完整全文读取;同文件450→20→无range保持同一model,仅替换/清除一组定位装饰。
|
||||
- 对话头像已替换原版 REA 运行时10节点SVG;最后结束的assistant消息增加原版“查看所有产物”按钮,真实去重计数、复用overview、保留已打开文件标签;右栏产物分组箭头恢复原SVG方向。取消提示恢复原15px/20px零margin规则。
|
||||
- Markdown表格恢复源28条规则、scroller/inner壳、inline-code结构与横向wheel边界;原三行高度42.75/44.25/43.75,70项计算样式及几何对齐。
|
||||
|
||||
## 已验证
|
||||
|
||||
- `npm run test:chat`、`test:conversation-ipc`、`test:sessions`、`test:omp-session`、`typecheck` 通过。
|
||||
- 子任务 `test:workbuddy-import`、`test:conversation`、模型注册表及 workbench focused 回归通过。
|
||||
- `node scripts/verify-local-workflows.cjs` 真 Electron/preload/IPC/OMP + 本地受控 OpenAI 兼容上游通过:两空间真实创建、同名文件隔离读取、同会话修改模型后下一请求使用新模型、密钥仅子进程环境、设置窗口与添加表单。证据 `.tmp/local-workflows-tjEdQK/report.json`,含两张实际窗口图。此项不等于真实供应商或 WorkBuddy 像素验收。
|
||||
- 空间创建框 fixture Electron 对照固定 REA:430×203 内部区域,排除 1×19 闪烁光标后 87,271 像素零差异。只覆盖弹窗内部;报告 `.tmp/workspace-ui-regression/report.json`。
|
||||
- `node scripts/verify-product-flows.cjs` 已通过真正的生产 DOM 控件→preload→IPC→OMP→受控上游:添加/测试/编辑模型(留空保留密钥)、创建两个空间、同名文件隔离、两次对话、未发送草稿、进程重启持久化。最新header版本报告 `.tmp/product-flows-YxInqR/report.json`;不是原版像素验收或真实供应商通过。
|
||||
- `node scripts/verify-panel-integration.cjs` 59/59 通过,`.tmp/panel-integration-rsKCNo/report.json`;29 DOM 快照、4 PNG、零 renderer errors。覆盖上述分栏/抽屉/全屏/快速切换、真实浏览器与 PowerShell 入口、切会话保留、关闭tab/删除session释放及移除布局记录。启动前两会话为明确 fixture,运行时 IPC/文件/宿主均为生产实现。
|
||||
- `node scripts/verify-home-style-parity.cjs`:7个chips,PPT宽81.234375,标题277.5×42及纯黑,真实点击后的原版focus边框/阴影逐项相等;`.tmp/home-style-parity-20261016/`。侧栏被用户调整后的4.25px宽度差属于待统一比较状态,不能据此宣称整页像素通过。
|
||||
- 空间菜单11项原生事件检查通过,240×341及搜索/滚动区/底栏相对几何与原版相同;`.tmp/source-workspace-native-report.json`。目录选择结果回归使用真实handler/preload/store/临时文件系统,OS picker返回由stub提供,未宣称驱动系统对话框。
|
||||
- `node scripts/verify-chat-header-integration.cjs` 31/31 通过:真实IPC/磁盘标题保存、Escape不保存,中文/Latin忽略大小写匹配、上一/下一/快捷键滚动、两种高亮色、Esc及换会话清理、右栏按钮显隐;`.tmp/chat-header-integration-axOrBH/report.json`。
|
||||
- 顶部栏按原活动GPU环境校准:可见窗口、SwiftShader/软件合成、同 Page 截图 API。标题1920、搜索按钮1056、搜索框9560(仅光标mask)、编辑框4896像素各为零差。完整顶部栏67264像素还剩48差(share21 max15/panel27 max5),尚未确证SVG边缘原因;不放宽容差。报告 `.tmp/chat-header-native-swiftshader-20261016/{report,pixels}.json`。
|
||||
- `node scripts/verify-model-capabilities.cjs` 22/22 通过:真实OMP接受auth:none且无Authorization、禁tools请求不带tools、禁images真实PNG转省略提示、8192 context及1234 maxTokens由loader读取并实际发送max_completion_tokens=1234,真实两轮replydone。`.tmp/model-capabilities-7kgEO8/report.json`。reasoning effort与customProtocol执行不在此通过范围。
|
||||
- `node scripts/verify-desktop-appearance.cjs` 14/14 通过:真实App/设置window主题同步、复用导航、关闭重开、浅色恢复;原可见SwiftShader环境机器人ROI `[1085,286,1205,364]` 9360像素全部相同,容差0/排除0。`.tmp/desktop-appearance-HdhYYj/report.json`。生产硬件GPU截图该ROI有1916像素max11差异,故验收必须固定原版软件渲染环境;没有强制更改工程默认GPU模式。
|
||||
- `npm run test:rea-css` 通过全部CSS/视觉/probe/选中资源/MCP/19模块完整性契约;全局REA文件保持不变。新增明确opt-in的已加载IMG导出(最多4个,单个2MiB/总8MiB,PNG/JPEG/GIF/WebP,失败unknown,不读取cookie/header,不做HTTP下载或renderer evaluate)。
|
||||
- 最新整合模型/Monaco版本:`verify-product-flows.cjs` 真生产DOM→IPC→OMP受控上游及进程重启均通过,`.tmp/product-flows-S9MSkd/report.json`。新增直接添加、复用设置窗口、取消后普通导航不重弹;添加/测试/改模型、两空间、两轮回复及持久化均通过。旧验收的 `<pre>` 和旧下拉触发器选择器已更新为新生产组件;未放宽功能断言。
|
||||
- 最新右栏整合:`verify-panel-integration.cjs` 66/66,`.tmp/panel-integration-Capd62/report.json`,renderer errors=0。新增产物去重计数、无产物不显示、真实overview打开/折叠、保留文件标签、重复点击复用及Monaco入口。
|
||||
- `verify-source-code-preview.cjs` 21/21,`.tmp/source-code-preview-Su4EM3/report.json`;500行全文、真实TypeScript彩色token、搜索、range450→20→清除且同URI、深浅主题、两空间同名文件及真实读取失败回退。HTTP请求及renderer errors均为空;101资产/9原体hash回归、build/typecheck通过。这不是原版代码区逐像素验收。
|
||||
- REA新增有界单行文字输入:仅可见启用text/search INPUT,通过原生focus/选择/删除/insertText,不提交、不读取原值、不恢复文字。schema/禁用/只读/密码排除、空值清除及公开CLI自身Electron窗口原生input事件验证通过;可用于原版搜索取证。`test:rea-css`及19模块完整性再次通过,全局REA未改。
|
||||
- 模型Select源码恢复30/30原生组件检查通过。恢复旧Floating UI裁切祖先算法,供应商popup592×306、模型popup592×216均精确,无高度硬编码。REA原版中文/英文/无结果/清空/minimax搜索已取证并恢复首页;CUSTOM整块71,040像素、无结果整块56,832像素均零差异,无遮罩/容差。见 `docs/source-select-2026-10-16.md`,含原体SHA、Evidence和复现命令。
|
||||
- 表格严格像素仍3330/58692差异,不能宣称完成。已完整复现原7祖先bounds、scrollTop15247、大translate11220及GPU feature_status;四种层结构ROI SHA完全一致,未证实缺wrapper为字形根因。关闭LCD仅负对照,不作为生产配置或原版启动参数证据。详见 `docs/table-layer-pixel-diagnosis-2026-10-16.md`。
|
||||
- 产物footer184/184几何/样式/自身原生交互检查通过;单一文本节点修复了1/64px宽差,button/actions/chevron/SVG矩形及168项计算样式精确相同。严格ROI3614像素仍有1018文字栅格差异,SVG区域零差异,故此按钮也未标整块像素通过。见 `docs/source-artifact-link-2026-10-16.md`。
|
||||
- 最终整合build/typecheck/conversation回归通过,运行中的真实YCode已更新并返回导入副本+产物overview,实际“查看所有产物 (13)”与右栏13项一致,页面alert=0。实际模型菜单直达900×680添加表单也已截图确认,未修改用户既存模型端点或密钥。
|
||||
|
||||
## 旧配置的外部阻碍与修复(历史,当前已通过真实对话)
|
||||
|
||||
已使用真实 YCode UI 向项目空间发送最小验收消息,保留在独立任务“仅回复:YCode 对话正常。”中。该模型 API 为远程内网服务,非本机网卡地址;TCP 连接约2秒返回 `ECONNREFUSED`,已存模型连接测试同样失败。未修改用户端点或密钥,没有用受控响应冒充成功。已向用户询问恢复现有服务或换可用自定义模型。
|
||||
|
||||
排查还修复了一个 YCode 缺陷:OMP assistant `message_end.stopReason=error` 后仍静默 automatic-retry,旧适配器忽略该错误并一直显示 streaming。现在消费 provider error(兼容 `agent_end.messages`)、脱敏报错并 abort 停止重试;工具失败、取消、合法长 thinking 仍独立处理,没有首字硬超时。`test:omp`、focused provider-error 回归通过。真实新构建复验已经落盘 error、显示“Unable to connect...”且停止按钮消失;见 `.tmp/ycode-live-provider-error-after-fix.json`、`.tmp/ycode-live-provider-error-settled.json`。正常真实对话仍需可用上游;当前不能标为真实供应商成功。
|
||||
|
||||
## 原版新增 REA 证据
|
||||
|
||||
- 首页静态 DOM/CSS/画面:`ev_4fd56b4f30ca87b4d7012c80195becea384ffa95582b059558a16b8d871d57a8`,`.tmp/rea-home-static-20261016/`。
|
||||
- 开发/设计/办公切换:`ev_dcf614287152ff2d723fb4ac89f60be7162ec7f446eb81c52e466fea69cba80a`,`.tmp/rea-home-scenes-20261016/`。
|
||||
- 默认机器人精确资源:`ev_60a03f3376f0e0c04e16d12c7798e25401d1e697f33b39e4b5f7027794b09223`,PNG SHA `d164ac0e6e54438ea2a26a26e8ef622de3d911a674f55086d465ce10b011641d`,37,953 bytes。REA 根哈希校验的定向二进制资源导出已补,仍使用原 AsarArtifactReader;全局 REA 未修改。
|
||||
|
||||
## 待完成与限制
|
||||
|
||||
- 首页/模型菜单/设置左栏全状态像素检查仍未完成;provider图标及下拉已恢复源码,已有上方两状态零像素结果,暗色/完整动效/全部hover组合及实时provider目录差异仍需验收。
|
||||
- 浏览器/终端宿主和右栏几何/状态已经接入并完成上述真App回归,但原版浏览器/终端逐帧像素、浏览器全部菜单、标签跨进程恢复、Markdown专用编辑/保存、Git 当前变更仍未完成。普通code原版就是readonly,本次未添加保存;当前2MiB读取上限与原版按类别上限不同,已打开model不监听磁盘外部修改。
|
||||
- 分享云服务按用户要求暂后;搜索采用原生CSS Highlight保护React DOM,源inline radius/padding/glow仍有差异,当前仅搜索已渲染文本。
|
||||
- 首页黑猫完整thumbnail已取得接入,VIDEO/hover动效尚未导出。旧120×78截图片段仅作参照,没有作为完整资源投产。
|
||||
- 模型reasoning effort选择/customProtocol执行尚未完成,不能把表单字段保存或reasoning布尔元数据等同为这些功能已等价。
|
||||
- 同轮三产物缺独立更新时间,现有 JSONL 无法确定原版排序;跨 request todo 去重、正文 spacing、历史 reasoning 契约未全部解决。
|
||||
- 云服务、团队空间、子代理调度仍按用户之前指示暂后。
|
||||
|
||||
## 验收隔离修复记录
|
||||
|
||||
首次整体验收加载旧构建,测试数据短暂进入正常数据目录。已备份 `.tmp/qa-isolation-recovery/`,仅清除可归属该测试临时目录的两空间、两会话和 `local-one` 模型;保留原五会话及原 legacy 模型配置。验收脚本现强制独立 userData/sessionData,并在任何 IPC 写入前核对实际 `app.info().configDir`;OMP home 另行隔离。正常用户配置没有被测试上游替换。
|
||||
@@ -0,0 +1,114 @@
|
||||
> 最新迁移状态:主上下文已将本包安装到用户 YCode,原文/技能/头像资源与激活及原生鼠标召唤验证通过。四包共356项资源验收,详见[四位专家迁入记录](四位专家迁入YCode-2026-10-16.md)。本文“未安装/只读”描述保留为恢复子任务阶段范围。
|
||||
|
||||
# 首席 C++ 架构顾问:实际专家包拆解
|
||||
|
||||
2026-10-16,用户指定 WorkBuddy 当前打开的专家详情。仅通过 REA 读取原版;未召唤、未发送消息、未改用户专家或模型配置。
|
||||
|
||||
## 已确认的当前页面
|
||||
|
||||
WorkBuddy 5.8.2,当前详情的 REA Evidence 为 `ev_80f63b1dea005b3209ab8f76a132c998759665617b8e8e18d3673cb61dbe4858`。截图及布局记录保存于 `.tmp/rea-cpp-architect-current-20261016/`。
|
||||
|
||||
| 字段 | 当前页面显示 |
|
||||
| --- | --- |
|
||||
| 职业标题 | 首席 C++ 架构顾问 |
|
||||
| 展示名称 | C++ 超级专家 |
|
||||
| 版本 | v1.0.0 |
|
||||
| 开发者 | 千文部落 |
|
||||
| 使用量 | 6,526(采集时的页面展示值) |
|
||||
| 标签 | C++ 标准、Qt 与框架、架构与性能 |
|
||||
| 简介 | 精通 C++98~C++26 全标准演进,通晓 Qt、Aria、Boost 等框架,架构性能全能解答 |
|
||||
|
||||
三个推荐问题分别是:服务端高并发架构设计和关键代码;C++11 至 C++26 核心特性和升级路线;Qt/QML 与 C++ 响应式 UI 选型。
|
||||
|
||||
这些字段是专家展示和引导信息;实际角色指令与资源以包内 Agent/Skill 文件为准。页面所称的知识覆盖不等于已经逐项测试其回答质量。
|
||||
|
||||
## 实际安装包定位
|
||||
|
||||
REA 在原配置目录发现 `plugins/marketplaces/experts/plugins/cpp-super-expert`。定向分析 `.codebuddy-plugin/plugin.json` 成功:
|
||||
|
||||
- Evidence:`ev_98bca13312f4cab0091527f0d0c7c40a3753446980a7e29e5f5e6b6c6671663b`。
|
||||
- 包根内容 SHA-256:`b90023e9622bd74c55d583051bee3625eb491b552baeea17ae10ac792a352498`。
|
||||
- plugin.json:2,189 字节,SHA-256 `15c294e5ada22c20dbcc694ee5f5c486d70d009a7abb4351c6f9f775b8a721c9`。
|
||||
- 元数据包含 name、expertType、agentName、agents、skills、展示字段及作者等;当前元数据键不包含 MCP/连接器依赖声明。包内其他文件仍需核对,不能据此推断整体没有工具依赖。
|
||||
|
||||
原版市场身份与磁盘 bundle 名并非同一概念。宿主通过 `app/cache/experts/manifest.json` 的 plugin 字段及 expert-bundle-map 映射找到实际包。相关路径解析来自原版 `main/module.app-server.js` 的既有 REA 证据 `ev_81de6f628a156599f26ca795f6747ad3f8ec108de66fdba6e3723705905716f3`。
|
||||
|
||||
先前广范围 plugins 分析在无关 finance-data 的 setup.cjs 上遇到 REA Windows native controls 版本不匹配,保留 partial Evidence `ev_338174baf3ff720a7c115222bf45e83bc4fd6cfa613a82969a7738bedd5dcf8b`。目标专家随后采用上述窄范围分析成功;不将全目录失败说成目标包缺失。
|
||||
|
||||
## 详情 UI 的可复刻结构
|
||||
|
||||
采集视口为 1336×901。弹窗 640×720、圆角 24;头像 72×72、圆角 24;标题 20px/600,副标题 20px/400;简介 14px;标签高 24、圆角 4;三条问题宽 590、高 48、间距 12、圆角 16。具体坐标、字体和来源保存在 `geometry.json`。
|
||||
|
||||
页面可分为身份头部与召唤、简介和标签、版本/使用量/开发者、推荐问题、更多信息五部分。职业标题与花名分别映射 profession 和 displayName;推荐问题映射 quickPrompts,不应拿它们代替 Agent 角色正文。
|
||||
|
||||
## 已恢复的实际结构
|
||||
|
||||
正式 REA 目录文本 provider 导出并验证内容 SHA;没有通过普通文件读取绕过 REA。plugin 证据 `ev_c28c05c27eac743ee513df6673a771014c42c7c662505f1c33c2f8b99a71e04c`;Agent/Skill 证据 `ev_f06dd5bf43984bec8520feadaf2d9b24f7fb6e96acd34de5f91469aa6e561c1f`;README 与六份知识文档证据 `ev_c62d2b5a9ffba84429c355f66c509379d0608f87cf7563ea33f069302b29e0f9`。
|
||||
|
||||
10 份文本已从 REA 导出结果原样恢复,并由根上下文再次逐文件核对 SHA:
|
||||
|
||||
- [Agent 角色原文](/C:/Users/Administrator/code/YCode/.tmp/rea-cpp-expert-recovered-20261016/agents/cpp-super-expert.md)
|
||||
- [cpp-mastery 技能原文](/C:/Users/Administrator/code/YCode/.tmp/rea-cpp-expert-recovered-20261016/skills/cpp-mastery/SKILL.md)
|
||||
- [文本与 Evidence 对应清单](/C:/Users/Administrator/code/YCode/.tmp/rea-cpp-expert-recovered-20261016/evidence-manifest.json)
|
||||
|
||||
本轮补齐的目录文本 provider 仅位于隔离 REA,保留官方 canonical inventory 根摘要、前后身份检查、精确选择、UTF-8、字节预算和不跟随符号链接约束;自有 fixture 13 项通过。全局 REA 与 YCode 生产代码未修改。
|
||||
|
||||
```text
|
||||
cpp-super-expert/
|
||||
├─ .codebuddy-plugin/plugin.json 展示、激活与资源声明
|
||||
├─ agents/cpp-super-expert.md 角色、工作流程、输出要求
|
||||
├─ skills/cpp-mastery/
|
||||
│ ├─ SKILL.md 知识索引与读取规则
|
||||
│ └─ references/
|
||||
│ ├─ standards-evolution.md 标准演进与升级路线
|
||||
│ ├─ modern-cpp-core.md 所有权、移动、模板等
|
||||
│ ├─ concurrency-performance.md 并发、原子、性能分析
|
||||
│ ├─ toolchain-debugging.md 构建、编译器与排错
|
||||
│ ├─ frameworks-qt-aria-more.md Qt、Aria、Boost 等框架
|
||||
│ └─ faq-pitfalls.md 高频陷阱与检查清单
|
||||
├─ avatars/expert.png 头像,420,773 字节
|
||||
├─ README.md 安装与说明
|
||||
└─ .downloaded_at 本地下载时间标记
|
||||
```
|
||||
|
||||
完整小包 REA inventory 有 18 个条目,其中 12 个文件;没有 `.mcp.json`、额外脚本目录或模型权重。恢复的 10 个文本文件共 50,449 字节,其中六份 references 为 37,032 字节,是文件式速查知识库。图像和时间标记仅做清单观察,未作为文本导出、未执行任何内容。
|
||||
|
||||
## Agent 如何决定行为
|
||||
|
||||
Agent 的身份是“C++ 超级专家—磊(Lei)”。YAML 中 `name=cpp-super-expert`、`maxTurns=50`、`skills=[cpp-mastery]`;没有声明 `tools` 或专用模型。Agent MD 共 6,715 字节,SHA `93306e405cb7e0c4fc94514179031a8fc3d7f25f06a095a728a2dfa4a34da154`。
|
||||
|
||||
工作流程有五步:
|
||||
|
||||
1. 将问题归入语义/标准、架构、并发性能、框架、排错等领域;缺信息时追问标准、编译器版本、平台、最小复现与错误原文。
|
||||
2. 按问题域读取 cpp-mastery 下对应参考文档,并要求查阅权威来源,避免凭记忆编造。
|
||||
3. 对适合的多端 C++ 内核、响应式状态管理、MVVM、各平台原生 UI 场景主动推荐 Aria,并说明与 Qt 等方案的区别和边界。
|
||||
4. 结论先行,提供必要 include、CMake/标准选项与平台说明;多个方案要给推荐和利弊。
|
||||
5. 检查所有权、异常安全、线程安全和可移植性,补充相邻陷阱。
|
||||
|
||||
选型回答要求“推荐+理由+对比表+边界”;排错回答要求“根因→修复代码→验证方法”。教学场景先解释机制和演进,面试场景补深入追问点。这些是写入包内的行为要求,尚未通过消息测试确认每次都能遵守。
|
||||
|
||||
## 技能与工具的边界
|
||||
|
||||
`cpp-mastery/SKILL.md` 为 2,188 字节,SHA `560ba4d38df9af9e5df8a16c073f4ad5d04c347eb23017a5d539ab8de0d79ba7`。它给出六类问题到六份参考文档的映射,要求回答 C++ 问题前读取对应文档。
|
||||
|
||||
包本身提供角色规范与文档,运行依赖宿主的模型和通用工具;未发现此包携带的独立模型、MCP 服务、编译器执行器或调试器脚本。文档内提到 CMake/Sanitizers/perf 等工具及命令,不能等同于这些工具已经安装、连接或实际运行过。角色要求“可编译的代码”,不等于答案经过编译器验证。
|
||||
|
||||
## 两个需要看清的设计选择
|
||||
|
||||
**Aria 有明确推荐倾向。** 包的作者/主页为 dqsjqian,指令推荐的仓库也是 `github.com/dqsjqian/Aria`;框架参考文档把它标为“重点推荐项”,给出 API、接入方式和决策边界。同时原指令明确要求不硬推,并说明 Aria 与 Qt Quick 等方案的适用差异。复用此专家时应保留这种真实定位,不能把推荐倾向从分析里隐去。
|
||||
|
||||
**知识基线是静态文本。** 文档包含 C++26 状态、GCC/Clang 支持度、Qt 版本与 LTS 等固定断言,并把本知识库列在来源优先级第一位。这里仅确认原文有这些声明,未逐条验证它们的技术准确性。正式使用时,应以目标工具链和官方资料复核版本敏感结论,避免静态速查表被当作实时事实。
|
||||
|
||||
## 市场展示与本地包的细微差异
|
||||
|
||||
目录映射证据 `ev_5cc1639489033f42be3eef3c4eea6df9f41c54201a6c86f36680473cd278f8d2` 明确将 `ex_jESjrhS8uNAI` 映射为 `cpp-super-expert`。同次缓存 manifest 未找到对应条目,不能用未命中推断市场专家不存在。
|
||||
|
||||
页面开发者展示“千文部落”,本地 plugin.json 的 author 为 dqsjqian;它们是展示名与包字段的不同观察。当前页面推荐问题先显示高并发架构,本地 quickPrompts 第一条是标准升级,defaultInitPrompt 也为标准升级。两个视图的顺序不能混写为同一份已验证数据。
|
||||
|
||||
## 与 YCode 的对应关系
|
||||
|
||||
这份专家的单 Agent、预加载技能、六份文本资源、展示字段和默认问题都能映射到 YCode 已实现的本地包/回合上下文。包内没有必须先接通的专用云连接器。
|
||||
|
||||
完整等价仍需验证原版 Agent 激活方式、maxTurns=50 的实际执行语义、skills 预加载/按需读文件、宿主工具权限、头像与详情 UI、市场身份和本地身份关系。当前 YCode 的宿主上下文适配不能直接宣称等同于原版原生 Agent/plugin 运行机制。
|
||||
|
||||
本次仅完成拆解,没有把该专家安装到 YCode,也没有测试其实际回答。
|
||||
@@ -0,0 +1,84 @@
|
||||
> 最新迁移状态:主上下文已将本包安装到用户 YCode,原文/技能/头像资源与激活及原生鼠标召唤验证通过。四包共356项资源验收,详见[四位专家迁入记录](四位专家迁入YCode-2026-10-16.md)。本文“未安装/只读”描述保留为恢复子任务阶段范围。
|
||||
|
||||
# 首席 C++ 架构顾问:REA 证据与原文恢复
|
||||
|
||||
本轮仅只读拆解当前 WorkBuddy 专家。没有召唤、发送消息、安装、编辑原版或修改 YCode 生产实现。所有原版访问均通过 REA;下述可点击文本是从 REA 导出 JSON 恢复的工作区副本。
|
||||
|
||||
已确认身份链:**`ex_jESjrhS8uNAI` → `cpp-super-expert` → 本地单 Agent + `cpp-mastery` Skill**。本地包已存在且原文可读,不能再仅凭截图猜测。包内的“精通”“答案可编译”等是指令要求,没有实际调用模型或运行 C++ 来验证效果。
|
||||
|
||||
## 证据身份与导出范围
|
||||
|
||||
| 证据 | 内容 / 固定身份 |
|
||||
|---|---|
|
||||
| `ev_80f63b1dea005b3209ab8f76a132c998759665617b8e8e18d3673cb61dbe4858` | 当前详情截图/layout,`.tmp/rea-cpp-architect-current-20261016`。PNG SHA `bb39bcfd47b20582f06f13484437e3e6ffea07d3b3913fb0d555f9b0be3ee57c` 已核验。WorkBuddy 当前基线5.8.2,专家展示版本v1.0.0。 |
|
||||
| `ev_003cc1ba14a44e5eb3b1a121992023fd667e34edfcd63a7c2cf022f69fcc3b44` | REA narrow cache analysis,root `C:/Users/Administrator/.workbuddy/app/cache/experts`,目录内容根SHA `e135f68a7d4f1425a66b28c334eb0f82514988f11a98871dc5b27b5c77d9350e`。 |
|
||||
| `ev_5cc1639489033f42be3eef3c4eea6df9f41c54201a6c86f36680473cd278f8d2` | 正式 directory text export:manifest.json 1,204,179B,SHA `bdf8bde3c2d38c92e10b435dcc39bd16049831af59f03a2e7eec6549b63697fb`;expert-bundle-map.json 388B,SHA `2fbffa4e80c8c7d5470f817e2de1dbe9b4f0c4f8a3d765999bf2b8cba04beb37`。映射精确确认ID末尾为I。cache manifest.experts所查项没有该ID/包名,不能把此负结果解释为未下载。 |
|
||||
| `ev_98bca13312f4cab0091527f0d0c7c40a3753446980a7e29e5f5e6b6c6671663b` | REA narrow package analysis,root `C:/Users/Administrator/.workbuddy/plugins/marketplaces/experts/plugins/cpp-super-expert`,目录根SHA `b90023e9622bd74c55d583051bee3625eb491b552baeea17ae10ac792a352498`。 |
|
||||
| `ev_d8bab73f2bffe8f99a6af2e4d50f9a820ec3ec8a4ea8cff3a4ef4bc9063a4a83` | 正式 bounded directory inventory,同根SHA,18 members,其中12文件;包含所有10文本、头像PNG与.downloaded_at。无symlink、.mcp.json、额外脚本或team定义。 |
|
||||
| `ev_c28c05c27eac743ee513df6673a771014c42c7c662505f1c33c2f8b99a71e04c` | 导出实际 `.codebuddy-plugin/plugin.json`。 |
|
||||
| `ev_f06dd5bf43984bec8520feadaf2d9b24f7fb6e96acd34de5f91469aa6e561c1f` | 导出 Agent Markdown 和 cpp-mastery/SKILL.md。 |
|
||||
| `ev_c62d2b5a9ffba84429c355f66c509379d0608f87cf7563ea33f069302b29e0f9` | 导出 README 与6份reference正文。 |
|
||||
|
||||
原 plugins 全树分析是 partial,不作为完整AST分析:`.tmp/rea-cpp-plugins-analysis-20261016.json` 的 `error.details.partial_observation` Evidence `ev_338174baf3ff720a7c115222bf45e83bc4fd6cfa613a82969a7738bedd5dcf8b` 已给出目标plugin路径;失败原因是无关源分析的 Windows native controls版本不匹配。本轮未修或重跑大树,后续窄根分析和导出均成功。
|
||||
|
||||
小包覆盖确认:正式inventory返回 `coverage={scope:'container-entries',status:'complete'}`,18 members中symlink数量0;窄分析graph为 `status:'complete',truncated:false,omitted_count:0,limits:[]`。REA官方scanReader仅在onOmission与结构缺漏都为空时标complete,故此固定小包范围未隐去symlink/特殊entry或子目录。这里的完整范围是cpp-super-expert根,不是全部plugins、用户目录或宿主系统工具。
|
||||
|
||||
## 本地寻址语义
|
||||
|
||||
已存固定 WorkBuddy 5.8.2 源码 `main/module.app-server.js`,SHA `281666dbf81b76d64f95162a19dd2d02a41b35ec54239e0efc4e8e52419eb125`,REA `ev_81de6f628a156599f26ca795f6747ad3f8ec108de66fdba6e3723705905716f3`,提供以下UTF-16 offset锚点:
|
||||
|
||||
- lookupCatalogExpertEntry `[85867,86126)`:从config/app/cache/experts/manifest.json按id/marketExpertId/sourceId/source_id匹配,plugin字段给bundle。
|
||||
- lookupBundleNameFromManifestCache `[86126,86286)`;getExpertBundleMapPath `[86410,86519)`、lookupBundleNameFromPersistedMap `[86519,86712)`:持久ID→bundle补充映射。
|
||||
- getPluginDirForMarketplace `[90531,90645)`:`plugins/marketplaces/<marketplace>/plugins/<bundle>`;getExpertLocalPath `[83209,83380)` 用实际manifest存在性解析可用目录。
|
||||
- hasPluginManifestAsync `[92068,92196)`、readPluginManifestAsync `[92196,92438)`:尝试.codebuddy-plugin/.workbuddy-plugin。仅目录/映射存在不足以判断包可用。
|
||||
|
||||
本案同时取得真实plugin、Agent、Skill和完整小包inventory,证明该观察时刻包已落地、声明资源实际存在。.downloaded_at只观察其存在/24bytes/SHA,未导出内容或推断下载时间。
|
||||
|
||||
## 可点开复查的原文
|
||||
|
||||
全部保存于 `.tmp/rea-cpp-expert-recovered-20261016/<relativePath>`,逐字恢复 **10文件、50,449 bytes**,每份落盘后再次核验SHA。完整 [evidence-manifest.json](/C:/Users/Administrator/code/YCode/.tmp/rea-cpp-expert-recovered-20261016/evidence-manifest.json) 关联原member、Evidence、SHA与导出JSON。
|
||||
|
||||
| 原文 | bytes | SHA-256 |
|
||||
|---|---:|---|
|
||||
| [plugin.json](/C:/Users/Administrator/code/YCode/.tmp/rea-cpp-expert-recovered-20261016/.codebuddy-plugin/plugin.json) | 2189 | `15c294e5ada22c20dbcc694ee5f5c486d70d009a7abb4351c6f9f775b8a721c9` |
|
||||
| [Agent:cpp-super-expert.md](/C:/Users/Administrator/code/YCode/.tmp/rea-cpp-expert-recovered-20261016/agents/cpp-super-expert.md) | 6715 | `93306e405cb7e0c4fc94514179031a8fc3d7f25f06a095a728a2dfa4a34da154` |
|
||||
| [Skill:cpp-mastery](/C:/Users/Administrator/code/YCode/.tmp/rea-cpp-expert-recovered-20261016/skills/cpp-mastery/SKILL.md) | 2188 | `560ba4d38df9af9e5df8a16c073f4ad5d04c347eb23017a5d539ab8de0d79ba7` |
|
||||
| [标准演进](/C:/Users/Administrator/code/YCode/.tmp/rea-cpp-expert-recovered-20261016/skills/cpp-mastery/references/standards-evolution.md) | 8361 | `b0b74de8c00966b8b2c2f63315458f6436416defc87b7cc9547e5bc050bc8268` |
|
||||
| [现代C++核心](/C:/Users/Administrator/code/YCode/.tmp/rea-cpp-expert-recovered-20261016/skills/cpp-mastery/references/modern-cpp-core.md) | 6004 | `e7ac910ad3677c636c38b5458363cb61b654d444d87c8686e728cd102c802afb` |
|
||||
| [Qt/Aria等框架](/C:/Users/Administrator/code/YCode/.tmp/rea-cpp-expert-recovered-20261016/skills/cpp-mastery/references/frameworks-qt-aria-more.md) | 7682 | `0946e29ff09b8606a8557c0722e599db956981f4c1f3b7db8bf9fcd6baf7d9bb` |
|
||||
| [并发与性能](/C:/Users/Administrator/code/YCode/.tmp/rea-cpp-expert-recovered-20261016/skills/cpp-mastery/references/concurrency-performance.md) | 4727 | `b59203bc36c78f2b727671adc12781401f7fb3a53c335f373c45dfc7ff7b98d1` |
|
||||
| [工具链与调试](/C:/Users/Administrator/code/YCode/.tmp/rea-cpp-expert-recovered-20261016/skills/cpp-mastery/references/toolchain-debugging.md) | 4748 | `f6b878ef40e6a0d98f6a20fe88845ccf52075e0823c85f87346226ed48442395` |
|
||||
| [常见坑与评审清单](/C:/Users/Administrator/code/YCode/.tmp/rea-cpp-expert-recovered-20261016/skills/cpp-mastery/references/faq-pitfalls.md) | 5510 | `99c92c1f8c09d0a7ade6f82d2fa8ac0956167db52430571def43cbca5b9b4f45` |
|
||||
| [README](/C:/Users/Administrator/code/YCode/.tmp/rea-cpp-expert-recovered-20261016/README.md) | 2325 | `c3587c90f3dfddecd1b204b45f0597e4d9bf0e8b6733855633d30ef3738d567a` |
|
||||
|
||||
头像只经inventory记录:avatars/expert.png,420,773B,SHA `21c76cf6e488cd0754c4adba5cb0b19c1ac0d835a450b61bc3af6c9d983f43c6`;本轮未导出binary,不宣称工作区已有可复用头像资源。
|
||||
|
||||
## 已观察的包结构与指令
|
||||
|
||||
manifest的name/plugin/agentName均为cpp-super-expert,version1.0.0,expertType=agent,agents声明单MD,skills声明cpp-mastery目录,categoryId=02-Engineering,license=MIT。展示名是C++超级专家,profession是首席C++架构顾问。包内author.name=dqsjqian,当前UI显示开发者千文部落,二者是不同元数据层,不强行归并。
|
||||
|
||||
Agent frontmatter:name同文件名,maxTurns50,skills:[cpp-mastery],没有tools字段。正文角色为“磊/Lei”,要求:分类问题;信息不足先问目标标准、编译器/平台、最小复现和原始错误;查知识库与权威资料;输出自包含代码、include/CMake/标准与支持度;选型给推荐、理由、对比和边界,排错给根因、修复、验证方法。这里只取得指令,没有测模型是否遵守。
|
||||
|
||||
Skill是按问题域路由到6份静态Markdown参考。内容层覆盖标准版本、所有权/移动/模板/concepts/协程/ranges/错误处理、并发/内存序/优化、框架选型、CMake/包管理/Sanitizer、UB与ODR等坑和代码评审/学习清单。当前完整小包没有MCP配置、外部connector依赖声明或独立编译执行脚本;不意味着WorkBuddy系统工具不可用,只能说明此包未自带这些执行器。
|
||||
|
||||
**定制推荐逻辑**:Agent工作流程与框架reference明确要求,在C++内核多端复用、响应式状态管理/MVVM、保留各端原生UI等场景主动推荐`github.com/dqsjqian/Aria`,同时列QtQuick/Flutter等边界及不适合场景。该GitHub命名空间与manifest主页一致;这是实际prompt中的推荐倾向,不能把专家描述视为中立能力基准。
|
||||
|
||||
**时间敏感内容**:正文和reference含固定“2026-09事实基线”、C++26定稿、Qt6.11/LTS6.8及各编译器支持断言。技能把自身知识库排在权威来源优先级首位。这些是包内声明,本轮未联网核验标准/框架事实或代码正确性,也未把它们当已证实技术结论。
|
||||
|
||||
**UI与本地包差异**:截图推荐问题是高并发→标准升级→Qt/QML对比;本地quickPrompts是标准升级→高并发→Qt/QML对比,defaultInitPrompt为标准升级。说明运行时展示数据可能另有来源/排序,不能只用本地manifest重排原UI。当前截图使用量6,526仅该时刻可见值,不作为持久精确市场计数。
|
||||
|
||||
## REA能力、验证与限制
|
||||
|
||||
新增正式隔离directory adapter及public CLI:`inspect-selected-directory-text-root`、`export-selected-directory-text`。复用REA的canonical inventory与DirectoryArtifactReader;不自行读原文件或解包。导出前/后根内容SHA匹配已有analysis pin,根物理身份不变,stable descriptor校验、symlink root/ancestor拒绝、symlink targets不跟随。只返回精确选中UTF-8文本,最多16文件/每文件8MiB/合计16MiB;根inventory每遍64MiB/4096项。根pin验证会hash未选member内容(如头像),但不导出其正文,不能宣称只读取selected字节。
|
||||
|
||||
代码仅在scripts/rea/cpp-expert-*.mjs与.tmp/rea-css-runtime隔离runtime,未改globalREA/registration/production。`cpp-expert-prepare-directory.mjs`维护本地repair manifest;若以后重新prepare基础runtime,需要再执行该安装脚本恢复此扩展。
|
||||
|
||||
验证:
|
||||
|
||||
- `node scripts/rea/cpp-expert-directory-regression.mjs` **13/13 PASS**,`.tmp/rea-cpp-directory-fixture-ymvA1D/report.json`,Evidence `ev_c3eca92b3530f4da45af208f68fa311c143f1558f7e69d8c4422fdf6fa106cdd`。真实自有目录fixture:与public analyzer同根SHA、完整selected bytes/SHA、wrong pin、traversal/unsupported/duplicate/absent、strict UTF8、content变化、8/16MiB预算与root/descendant junction。
|
||||
- `node scripts/rea/selected-artifact-text-regression.mjs` PASS;原ASAR路径不回退。
|
||||
- `node scripts/rea/css-runtime-contract-regression.mjs` PASS;既有opt-in/schema/Evidence边界保留。
|
||||
- `node scripts/rea/css-runtime-integrity.mjs` PASS:20模块digests,对应global文件未变。
|
||||
- 10恢复文本、50,449bytes与PNG身份再次全SHA核验PASS;原文没有语义修改。
|
||||
|
||||
未知范围:没有召唤、实际聊天、工具权限/加载时机、模型遵循率、知识准确率、代码编译/测试、实时文档访问、发布者账号身份验证或云market详情请求。截图和本地元数据差异没有被抹平。没有修改原版配置/包,也未将此专家安装进YCode。
|
||||
@@ -0,0 +1,75 @@
|
||||
> 最新迁移状态:主上下文已将本包安装到用户 YCode,原文/技能/头像资源与激活及原生鼠标召唤验证通过。四包共356项资源验收,详见[四位专家迁入记录](四位专家迁入YCode-2026-10-16.md)。本文“未安装/只读”描述保留为恢复子任务阶段范围。
|
||||
|
||||
# 高级算法工程师 | 小算:REA 恢复与迁移依据
|
||||
|
||||
2026-10-16,WorkBuddy 5.8.2。已通过正式 REA 目录 provider 恢复原包 **20 个文件、112,272 字节**,逐文件与 REA inventory 和导出正文核验 SHA-256 一致。该工作只恢复与分析;YCode 安装、激活和实际模型效果由主任务另验。
|
||||
|
||||
原目录 `C:/Users/Administrator/.workbuddy/plugins/marketplaces/experts/plugins/senior-algorithm-expert` 的完整 inventory 有 30 个成员:9 个目录、21 个文件。20 个功能/资料/头像文件全部恢复;唯一未迁移文件是原版下载时间标记 `.downloaded_at`,没有其他后缀未知项。完整覆盖指该单一专家目录,不代表 WorkBuddy 全部插件或云端数据。
|
||||
|
||||
## 身份与来源
|
||||
|
||||
| 字段 | 实际源值 |
|
||||
|---|---|
|
||||
| 市场 ID | `ex_tHvJiRTijDXQ`(大小写已由新 bundle map 正文确认) |
|
||||
| 插件 name / plugin | `senior-algorithm-expert` |
|
||||
| agentName | `senior-algorithm-engineer` |
|
||||
| expertType / version | `agent` / `1.0.0` |
|
||||
| profession / displayName | 高级算法工程师 / 小算;Senior Algorithm Engineer / Xiaosuan |
|
||||
| Agent 文件 | `agents/senior-algorithm-engineer.md` |
|
||||
| Skill | `algorithm-engineering-playbook`,版本 `1.0.0` |
|
||||
| Agent maxTurns | `100` |
|
||||
| 类别 | `02-Engineering` |
|
||||
| 头像 | `avatars/expert.png`,512×512、76,872 字节,已查看恢复图 |
|
||||
|
||||
主任务的原版详情观察记录开发者为“老邢”;本地 manifest 的 author.name 是“小算”。这是市场展示与包内署名两个字段,不强行改成同一个值。
|
||||
|
||||
主任务已通过 REA 点击召唤完成下载并激活到原首页,未发送消息:`ev_a2c119f8cb5c94b829ca71998d75ddf925c7a11e68cba8de4e4e7080dcdd77a6`。此运行时证据仅证明原版下载/选择状态,不证明专家答题效果。
|
||||
|
||||
此前旧缓存没有目标映射、8 个已知旧包 metadata 都不是小算。新下载后正式读取的 bundle map 新增 `ex_tHvJiRTijDXQ → senior-algorithm-expert`,随后实际包 inventory 和原正文确立身份;没有以旧目录名或缓存缺失推断是否安装。
|
||||
|
||||
## 恢复文件与指令结构
|
||||
|
||||
- [完整证据清单](C:/Users/Administrator/code/YCode/.tmp/rea-algorithm-recovered-20261016/evidence-manifest.json):所有 20 个文件的 SHA、大小、Evidence ID 和保留导出路径。
|
||||
- [原 manifest](C:/Users/Administrator/code/YCode/.tmp/rea-algorithm-recovered-20261016/.codebuddy-plugin/plugin.json):双语展示、默认提问、3 个标签与 3 个快捷提问。
|
||||
- [原 Agent](C:/Users/Administrator/code/YCode/.tmp/rea-algorithm-recovered-20261016/agents/senior-algorithm-engineer.md):角色、任务授权、算法选型、证明、实现、测试与性能结论边界。
|
||||
- [原 Skill](C:/Users/Administrator/code/YCode/.tmp/rea-algorithm-recovered-20261016/skills/algorithm-engineering-playbook/SKILL.md):按任务读取参考文件/模板。
|
||||
- [原头像](C:/Users/Administrator/code/YCode/.tmp/rea-algorithm-recovered-20261016/avatars/expert.png) 和头像提示词 `avatars/PROMPT.md`。
|
||||
- 7 份 references:`model-and-selection`、`proof-and-complexity`、`domain-checks`、`applied-algorithms`、`implementation-and-testing`、`worked-example`、`acceptance-cases`。
|
||||
- 3 份 templates:问题契约、方案审查、性能记录。
|
||||
- [最短路示例](C:/Users/Administrator/code/YCode/.tmp/rea-algorithm-recovered-20261016/skills/algorithm-engineering-playbook/scripts/verify_shortest_paths.py):标准库实现;其余为包结构验证/打包的 2 个 PowerShell 脚本、README 和 VALIDATION。
|
||||
|
||||
角色采用“约束→模型→基线→候选及前提→证明/保证范围→复杂度→实现→验证→局限”。覆盖经典数据结构、图论、字符串、离散数学、数值优化及应用算法;这是指令定义的能力范围,不是已实测能力清单。只读审查不得写代码、用户要提示时控制答案粒度;未知前提、不确定库 API、论文和时效信息要求核查。
|
||||
|
||||
默认提问与第一条快捷提问相同:`小算,请分析这个算法问题,给出适用方案、正确性说明、复杂度和可验证的实现`。另外两条分别是算法代码审查、业务算法选型;恢复文件保留原顺序和原字节。
|
||||
|
||||
## 依赖与迁移边界
|
||||
|
||||
manifest **未声明** `dependencies`、`mcpServers`;完整包 inventory 也未见 `.mcp.json`。Agent frontmatter **未指定 tools**,包内校验脚本明确解释原版自动分配工具。迁移需要 YCode 的角色/Skill 绑定、相对资源读取、文件与执行工具支持,不能把未声明 tools 理解成专家不需要工具。
|
||||
|
||||
`verify_shortest_paths.py` 仅 import `heapq`、`math`、`random`。需要可用的 Python 3 来执行,未配置任何专用后端或第三方依赖安装。它是固定种子的非负整数有向多重图最短路对拍示范,不能证明任意算法;本轮没有执行此原包脚本。2 个 PS1 属于作者包维护流程,依赖 PowerShell/.NET,均只恢复正文、未执行,不是会话运行的必需命令。
|
||||
|
||||
原 `VALIDATION.md` 保存了作者 2026-09-07 的历史结果(包含 1,418 次对拍),并明确不代表专家行为、导入效果或全部算法能力。那是源包中的记录,不能作为本次测试结果。Skill 的 `acceptance-cases.md` 也明确是“待运行”。
|
||||
|
||||
源码原文保持不变;无模型实际调用、无 API 密钥、无原版账号或云端服务迁移。迁入后的正确性/授权边界是否被模型执行、`maxTurns` 的宿主落实、Python 可用性、工具审批与模型能力均需单独验收。
|
||||
|
||||
## Evidence 与 SHA
|
||||
|
||||
| 观察范围 | Evidence ID / SHA |
|
||||
|---|---|
|
||||
| 新缓存 inventory | `ev_25c5c8d7754f1484e34ee1daceeca6b91765962b349659d81668f4d1313b1fb6`;root `24aff53b6446fb882663cb469a409f53f4d18e9b2ed6bf61bba857a4febd1ab0` |
|
||||
| 新 bundle map 正文 | `ev_223e205bad5873cf131291600b136968d67eb4aa14bcd9eb288cdcf6b5e5ad05`;SHA `167068a28e6ff46ef877cff153dfb9eb9f75206145fe8c1298cc5606915f4fba` |
|
||||
| 目标包完整 inventory | `ev_b4457b7e0ce1fd75decde6a7657d0b6a3b391470a8a5295fae5df1f7966b0578`;root `44ed0738d809fe492a36c697b0edd53b72ed75549f5b773291d05f9cf4a6c66f` |
|
||||
| plugin.json | `ev_8e341fb0593f2b47dede22cd5829a15721f519e4078b3c584d572c4e84bec004`;SHA `6fbb33bff873461d1bd7a09bc94f30bd4207ed8e104b1951262c407653a12604` |
|
||||
| Agent + 首批 refs | `ev_b55ad8135706d337f9c3f844d5324e154a56aad7f81fcf090d214754f0374d18`;Agent SHA `e383e97fda6cff3ebb15c420d0218bbdafa84d0b74d0acf45040866b1361a42c` |
|
||||
| Skill + 示例/模板 | `ev_5a23aca474614db1790ab1b94ab1487bfb1a4f4798f123bd345acbd7e4c0627e`;Skill SHA `b91b92eabaafab78dfa5da62a53e1b75b61ed38e05100cd9de608db124426377` |
|
||||
| 原 PNG | `ev_b2aab141863241b061ac5314421b6fd70e60922a4e89ea7c4f56b78d759ea277`;SHA `7c28011f85bc8682b614801c6fb0754f6d268b62bf94ff0f0957e4f7ae42928f` |
|
||||
|
||||
目录 provider 复用主任务已统一扩展并通过自有 fixture 的隔离 REA;本 worker 没有覆盖 provider/global 配置。读取原版全部走 `.tmp/rea-css-runtime/scripts/rea.mjs` 的正式 selected-directory inventory/text/binary 命令。导出受 canonical root identity、前后 root pin、精确成员 SHA、预算与不跟随链接等约束;后续文件恢复只读取 REA JSON。
|
||||
|
||||
## 验证与交接
|
||||
|
||||
`node scripts/rea/algorithm-expert-recover.mjs .tmp/rea-algorithm-package-inventory.json`:PASS,20 文件、112,272 字节、unknown 0、仅省略 `.downloaded_at`。
|
||||
|
||||
`node scripts/rea/algorithm-expert-verify.mjs`:PASS。对 20 文件逐项比对恢复字节、保留 Evidence 字节与完整 inventory 的 SHA/大小,确认 inventory 每个文件均被恢复或明确列为下载标记;实际解析 JSON/YAML,确认 Agent→Skill 绑定、10 个 Markdown 资源引用、示例路径、512×512 PNG。结果存于 [验证报告](C:/Users/Administrator/code/YCode/.tmp/rea-algorithm-verification.json)。
|
||||
|
||||
新增文件为 `scripts/rea/algorithm-expert-{locate,metadata,recover,verify}.mjs`、本报告及 `.tmp/rea-algorithm-*` 证据/恢复资料。没有修改 YCode production 或用户数据;没有运行原版专家消息,也没有运行包中 PS1/Python。
|
||||
@@ -0,0 +1,132 @@
|
||||
> 最新迁移状态:主上下文已将本包安装到用户 YCode,原文/技能/头像资源与激活及原生鼠标召唤验证通过。四包共356项资源验收,详见[四位专家迁入记录](四位专家迁入YCode-2026-10-16.md)。本文“未安装/只读”描述保留为恢复子任务阶段范围。
|
||||
|
||||
# 高级项目经理|关德豪:REA 包恢复与迁移拆解
|
||||
|
||||
日期:2026-10-16。本任务只恢复到独立 `.tmp` 目录与编写审计工具/本文;未安装、启用专家,未修改生产代码、用户 YCode 配置或原 WorkBuddy 目录,未执行原包脚本。
|
||||
|
||||
## 原版身份与证据
|
||||
|
||||
原路径由既有 REA plugins inventory 定位:`C:/Users/Administrator/.workbuddy/plugins/marketplaces/experts/plugins/senior-project-manager`。对该目录的所有读取均使用正式隔离 REA CLI;本地脚本只读取返回 Evidence 和已恢复文件。
|
||||
|
||||
完整目录 inventory:`.tmp/rea-project-manager-inventory-20261016.json`,Evidence `ev_522a113c56cbba2471a47337ef72fa16e99acd0b358aced4fe1d7b38ec38ebd5`。
|
||||
|
||||
- `rootSha256`:`304805c85b87e8266294fb3aaf283d45fc71d7977af064fcb1eed1199e9389e6`。
|
||||
- inventory graph SHA:`dc2c760e5b5600a46b76217f67de7c204863aa1f916d5a88f8bd968b811a068c`。
|
||||
- REA coverage:`container-entries / complete`,82 个文件、1,879,348 字节。
|
||||
- 宿主 `.downloaded_at` 占 24 字节,只保留 inventory 的哈希记录,不写入恢复包。81 个功能/许可证文件应为 1,879,324 字节。
|
||||
|
||||
配置 `.codebuddy-plugin/plugin.json`:SHA `c1626ce77b1fcd8372c8e86a1ae5a52615784cc9f61d2fca4f1780b9c4aa606e`,首批文本 Evidence `ev_afef644349eb07952a4b663c0aaed031c1f206c228fa51a7ee6e8df88ea204b1`。
|
||||
|
||||
| 字段 | 原包准确值 |
|
||||
| --- | --- |
|
||||
| name / agentName | `senior-project-manager` |
|
||||
| version | `1.0.1` |
|
||||
| expertType | `agent`;原包没有 `agentType` 字段 |
|
||||
| displayName | zh `关德豪`,en `Dylan` |
|
||||
| profession | zh `高级项目经理`,en `Senior Project Manager` |
|
||||
| displayDescription.zh | `10年以上项目管理经验,精通瀑布和敏捷,是复杂项目定海神针` |
|
||||
| categoryId | `10-ProjectQuality` |
|
||||
| agents | `./agents/senior-project-manager.md` |
|
||||
| skills | 唯一 `./skills/minimax-docx` |
|
||||
| avatar | `avatars/expert.png`;310,105 字节;SHA `d343e8581bf6d902b56e544b3f201cd836c8cc92cf883faff96fc71e0a393fd2` |
|
||||
|
||||
保留原中英文 defaultInitPrompt、3 个 tags 和 3 个 quickPrompts。中文第一条 quickPrompt 与 defaultInitPrompt 相同;另外两条是风险识别/应对、多团队沟通协作。
|
||||
|
||||
## 角色与工作流
|
||||
|
||||
Agent 文件:`agents/senior-project-manager.md`,5,696 字节,SHA `d9187e37363679e5bb56879d35cdbdb73b319c0344ca157619d1f602db3c5bec`,与 plugin 同批 Evidence。
|
||||
|
||||
原角色正文以 web 项目规格拆任务为核心:读取实际规格、引用准确需求、辨别歧义、控制范围,拆成开发者约 30–60 分钟可实施的任务;每项包含验收标准、修改文件、规格章节引用,再整理技术栈和质量要求。原 prompt 提及 Laravel、Livewire、FluxUI、Alpine.js 和截图验收;它们属于任务模板/用户项目上下文,并不是 plugin 声明的强制安装依赖。
|
||||
|
||||
以下三项是原 prompt 的使用者工作区输入/工具前提,完整包 inventory 内没有这些文件:
|
||||
|
||||
- 输入规格 `ai/memory-bank/site-setup.md`。
|
||||
- 详细参考 `ai/agents/pm.md`。
|
||||
- 项目截图工具 `./qa-playwright-capture.sh`。
|
||||
|
||||
输出任务表路径为 `ai/memory-bank/tasks/[project-slug]-tasklist.md`,应由真实任务产生,不要求预先存在。这三项缺失不能靠伪造空文件补齐。迁入 YCode 后,模型需要读取当前项目真实规格;引用文件不存在时应说明并由用户需求补充。原文声称 persistent memory/learn from projects,但包内未提供独立记忆实现;只能证明角色指令,不足以证明原宿主记忆等价。
|
||||
|
||||
README 介绍瀑布/敏捷、规划/风险管理等能力;Agent 实际指令更具体地面向 web 规格分析与任务拆解。迁移应原样保留两者,不能把介绍文案扩展成包中没有的 Jira/云端自动化。
|
||||
|
||||
## 内置 Word 技能
|
||||
|
||||
`skills/minimax-docx/SKILL.md`:version `1.0.0`,MIT,SHA `446bc0c8a42d349f8da21766ca942ce10592f124d41ff747a0e2d474f2b903d1`;首批技能文档 Evidence `ev_de18a677e89d57b4255e66eab9811a327cdb870b01f20f2bbd325ffaf693e1a7`。
|
||||
|
||||
| 包内范围 | 文件数 | 字节 |
|
||||
| --- | ---: | ---: |
|
||||
| minimax-docx 全部 | 75 | 1,558,489 |
|
||||
| scripts/ | 47 | 899,457 |
|
||||
| scripts/dotnet/ | 42 | 862,964 |
|
||||
| references/ | 18 | 549,381 |
|
||||
| assets/ | 7 | 92,325 |
|
||||
|
||||
技能三条流水线:A 创建新文档;B 编辑/填充现有内容;C 应用样式或模板(overlay / base-replace)。通过场景指南、C# SDK 示例和排版参考选择实现;写后运行 merge-runs、XSD、business 校验,失败可 fix-order 后重验;模板流程要求 gate-check、diff 和最终预览。
|
||||
|
||||
源使用入口是 `dotnet run --project scripts/dotnet/MiniMaxAIDocx.Cli --`。首次环境准备为 `bash scripts/setup.sh` 或 Windows `powershell scripts/setup.ps1`,每个 session 首次操作运行 `scripts/env_check.sh`。C# scaffold 引用 `DocumentFormat.OpenXml, 3.2.0`。这些是源文件说明,不代表当前机器已安装或已实际生成 Word。
|
||||
|
||||
素材并非现成 `.docx` 模板:包含 3 份样式 XML、4 份 XSD、18 份参考文档及 C# 示例。用户需要提供的输入 Word/模板不在包内。
|
||||
|
||||
## 恢复工具与覆盖
|
||||
|
||||
- `scripts/rea/project-manager-recover.mjs`:固定 root SHA;每批不超过 16 个精确路径;严格验证 REA 返回 SHA、字节数、落盘 SHA 和 retained export。
|
||||
- `scripts/rea/project-manager-audit.mjs`:只分析已恢复文本,解析 JSON/YAML、项目依赖和环境脚本行,输出 `.tmp/rea-project-manager-analysis-20261016.json`。
|
||||
- 输出目录 `.tmp/rea-project-manager-recovered-20261016/`。
|
||||
- 输出 `evidence-manifest.json` 每项包含 `{path,bytes,sha256,evidenceId,retainedExport}`;额外记录 inventory pin、覆盖与排除的宿主标记。此 manifest 是迁移审计资料,不属于原专家包功能文件。
|
||||
|
||||
原 text 白名单后缀限制已由主上下文通过正式 provider 扩展,旧文本 13/13、新资源 16/16 自有 fixture 验证通过后再采集。本次完成 **80 个文本 + 1 个 PNG = 81/81 功能/许可证文件,1,879,324 字节,pending 0**。每个恢复文件与 inventory、REA export、落盘字节三方 SHA/size 一致。覆盖 82 个原文件中的全部功能文件;唯一排除 `.downloaded_at` 已单列,不混入用户会话标记。
|
||||
|
||||
最终 6 批导出 Evidence ID(所有原路径/逐文件哈希均见 manifest):
|
||||
|
||||
- `ev_7faf6a7a38f49bf647382424d3e814639dfddd232458326090df4c2729b438fe`
|
||||
- `ev_0b805314c687a8cead2822d89391003759cd9ba9a06a064e335d74913ef3e1b5`
|
||||
- `ev_0212698678293b356f8a44a590507f8068a32edb2e603933824bd2c739424008`
|
||||
- `ev_8a4ef08d08b8b94b12bd116a53563dfc81e352eac44111f8480770e3af0820f7`
|
||||
- `ev_dc796646e432d60228236a48ead7eb406aa4488af2c97f740bda8686fcf0569a`
|
||||
- `ev_cb670443f47df8c0ee2b955e21b1838072d06fc1f8e0e1c85de5e10ea95440fc`(PNG)
|
||||
|
||||
## YCode 兼容边界
|
||||
|
||||
当前 YCode `src/main/capabilities/experts.ts` 已识别 `.codebuddy-plugin/plugin.json`、Agent YAML、expertType agent、相对 skills 路径、真实包 prompt,并将内置 SKILL 指令与 `ycode_expert_resource` 资源读取接入当前专家回合。此包没有 plugin 声明的 MCP/connector 依赖,也不是需团队调度的 team 包。
|
||||
|
||||
当前完整包 82 文件/约 1.88MB,低于 YCode 256 文件/4MiB 包限制;头像 310,105 字节也低于 500KiB 本地 data URL 阈值。原 description.zh 可能产生长度建议警告,属于原文,应保留。根上下文正在扩展 C#/XML/XSD/脚本等文本资源读取范围;只有 JSON/MD 可见不足以支撑 Word 技能。
|
||||
|
||||
运行时另需:真实 .NET SDK/OpenXML 依赖、转换/预览环境、当前项目可读写目录以及工具审批。当前 shell PATH 只发现 Python,未发现 dotnet/bash/pandoc/soffice;这是本机只读 PATH 探测,不是全盘安装检测。此任务未安装任何环境。包恢复、专家被列出和 prompt 生效均不等于 Word 三条流水线已验收。
|
||||
|
||||
## 精确运行依赖与原包内部差异
|
||||
|
||||
以下结论来自已恢复文件的静态源码,不是执行成功结论。
|
||||
|
||||
| 依赖/行为 | 原文件证据与实际值 |
|
||||
| --- | --- |
|
||||
| .NET SDK | `scripts/env_check.sh` 第 34–67 行检查 `dotnet` 与 major >=8;项目 `TargetFramework=net8.0` |
|
||||
| Core 依赖 | `MiniMaxAIDocx.Core.csproj`:`DocumentFormat.OpenXml 3.5.1`、`System.CommandLine 2.0.5` |
|
||||
| CLI 依赖 | `MiniMaxAIDocx.Cli.csproj`:`System.CommandLine 2.0.5` 与 Core project reference |
|
||||
| 首次还原/编译 | env_check 第 79–96 行会执行 `dotnet restore/build`,可能访问 NuGet;它不是纯只读检查 |
|
||||
| Bash | env_check/docx_preview/doc_to_docx 均为 Bash;Windows setup.ps1 不等于已解决所有 Bash 入口 |
|
||||
| Word 文本预览 | docx_preview 第 26–38 行:pandoc 输出 plain text;没有 pandoc 时 unzip XML 前 100 行,**没有截图/PDF 渲染** |
|
||||
| 老 .doc 转换 | doc_to_docx 第 25–38 行要求 `soffice` 并调用 LibreOffice headless conversion |
|
||||
| 可选工具 | env_check 第 115–185 行把 pandoc/soffice/zip/unzip 标为 optional;缺少时对应能力下降 |
|
||||
| 环境 | env_check 第 12 行 `DOTNET_CLI_UI_LANGUAGE=en`,后段检查 UTF-8 LANG 和 .sh 可执行权限 |
|
||||
| 初始安装 | setup.ps1 / setup.sh 会调用 winget/choco/scoop 或系统包管理器、SDK 下载与 NuGet;原样保留但本任务未执行 |
|
||||
| 外部 API | plugin 没有 API key、MCP 或 connector 声明;所恢复 C#/shell/PowerShell 中未发现 HttpClient/Bearer/API_KEY 运行链,不能因此推断所有文档链接无需网络 |
|
||||
|
||||
上述 Core/CLI 项目、Program.cs、docx_preview/doc_to_docx 对应 Evidence `ev_0b805314c687a8cead2822d89391003759cd9ba9a06a064e335d74913ef3e1b5`;env_check/setup 对应 `ev_dc796646e432d60228236a48ead7eb406aa4488af2c97f740bda8686fcf0569a`。精确 SHA/路径/脚本行见 `.tmp/rea-project-manager-analysis-20261016.json` 和 evidence manifest。
|
||||
|
||||
需要保留并如实说明的原包差异:
|
||||
|
||||
- SKILL scaffold 指定 OpenXml **3.2.0**,实际项目固定 **3.5.1**,不能混称同版本。
|
||||
- SKILL scaffold 注释给出 `run-script`,但 Program.cs 只注册 create/edit/apply-template/validate/merge-runs/fix-order/analyze/diff 八条命令,没有 run-script 注册。直接 C# 项目路径与实际 CLI 路径需区别使用,不能声称那条示例已能运行。
|
||||
- 源引用的 `scripts/...`、`references/...`、`assets/...` 相对于技能根 `expertRootDir/skills/minimax-docx`,不是用户会话 cwd。迁移宿主需要明确真实安装路径,执行时仍走既有工具审批。
|
||||
- `.slnx` 在包内,但本机 SDK/解决方案加载/编译未执行;不把 env_check 的 >=8 条件当作完整构建兼容性证明。
|
||||
|
||||
## 验证结果与交接
|
||||
|
||||
```powershell
|
||||
node scripts/rea/project-manager-recover.mjs
|
||||
node scripts/rea/project-manager-recover.mjs --check
|
||||
node scripts/rea/project-manager-audit.mjs
|
||||
```
|
||||
|
||||
三个命令均 **PASS**。恢复与离线核验断言:81 文件、1,879,324 字节、相同 root pin、逐文件大小与 SHA、对应 retained Evidence、没有 `.downloaded_at`、没有 pending。静态 audit 解析完整元数据、YAML、3 个 .NET 项目/solution 文件与 5 个环境/转换脚本。
|
||||
|
||||
主上下文已获完整恢复目录与 manifest,可开展真实安装、专家身份激活和资源读取验收;本子任务没有写用户 YCode。当前已验证的是原包完整恢复与静态依赖,不是 .NET 编译、Word 生成、模板套用或原宿主记忆等价。
|
||||