Files
ycode/docs/WorkBuddy-UI复刻可行性评估.md

228 lines
12 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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