12 KiB
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)中的真实代码:
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(), ...
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:
.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)
: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.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/资源/代码仍构成侵权 |
具体受限点(诚实清单)
- 函数内部逻辑被混淆——
let l=..., u=...只能靠 Hook 名与调用顺序推断;行为需重写而非复制。 - 跨进程交互:窗口控件、原生菜单、文件对话框、拖到 Dock、剪贴板、截图 → 走主进程 + 原生模块(
@ban-dal/os-bridge、wwapi-electron等)。 - 富文档预览:office 预览经
editor_sdk.exe(199.5MB,见引擎报告)→ 不可复刻;但 PDF.js / Excalidraw / 图片 预览路径是开源的,可复用。 - 内部组件库:
cb-前缀 437 个类对应的组件需自行重写。 - 数据源:排除云后,对话区与侧栏没有内容可渲染——必须自建模型网关与服务端(这是真正的护城河,也是上篇报告已指出的核心)。
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