6.0 KiB
输入框已选专家标签:源码恢复(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 声明值保留。主题增加 YCodedata-theme到原 light 规则的宿主映射。
接口与集成
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。
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 遍历可达性和全状态动效;这些不能由编译/局部几何通过替代。