Files
ycode/docs/expert-picker-source-20261016.md

7.5 KiB
Raw Permalink Blame History

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