7.5 KiB
专家输入选择器恢复(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>:
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。