762 lines
37 KiB
Markdown
762 lines
37 KiB
Markdown
# 安装中心模块拆解(2026-10-17)
|
||
|
||
> **范围订正:本文件不再是当前实施任务。** 用户已明确第18项是“设置 → 安全中心”,此前按应用安装管理理解有误。本文件保留历史证据与分析,不作为安全中心的需求、实现方案或完成度。当前入口见[安全中心范围订正与待拆解项](安全中心模块拆解-2026-10-17.md)。已有发现应用功能保留;下文安装/更新/卸载等批次不再列入本次四模块计划。
|
||
|
||
## 文档范围与结论
|
||
|
||
本文只做模块拆解、证据归档和分批实施方案,不实现业务代码,不触发安装、更新、卸载、授权或保存。本文形成后通过 REA 对 WorkBuddy 5.8.3 做了一次只读 target 枚举、一次无操作的声明式探针,以及一次打开设置窗口的声明式探针尝试;没有执行产品写操作,也没有修改 REA 配置。
|
||
|
||
**当前结论:**
|
||
|
||
- 既有 REA 证据已经证明 WorkBuddy 5.8.3 侧栏“发现应用”浮层的入口、稳定打开态、主要几何、CSS 和客户端请求/授权逻辑。
|
||
- 既有证据**没有**采集“设置 → 应用管理/安装中心”的懒加载主页面。现有脚本清单只出现 `BuddyAppsPanel-vC0qX_Oo.js` 和 `BuddyAppsPanel-OzkcFEe0.css` 的文件名,没有这两个资源的正文。
|
||
- 2026-10-17 的最新 REA 枚举只返回主窗口 `1CAD78026104DDABDB43F9EB6BA7635D`,没有设置窗口 target。一次无操作声明式探针成功(`ev_a3ca56f518f5c5101d2ae6e64f24794a564956da643c11e622c56b5cbb245000`),但没有导航。
|
||
- 打开设置窗口的声明式探针被 REA 以 `invalid_request / invalid_input` 拒绝,未产生 Evidence ID、设置 target 或 `data-settings-tab="buddyApps"` 页面。这次结果只记为工具输入失败,不能反推 WorkBuddy 没有应用管理页,也不能反推 REA 不支持该动作。
|
||
- “发现应用”是应用切换/发现浮层,不能据此推定安装中心主页面的列表、已安装状态、版本、更新、卸载、授权按钮和失败恢复。
|
||
- YCode 当前只有同壳适配的本地“发现应用”浮层,映射到专家、技能、连接器三个本地能力入口;没有云应用目录、应用详情、安装/更新/卸载、授权、依赖安装或应用管理主页。
|
||
- 因此 TODO 18 只能保持“部分实现”。本轮不能把它标记为完成,也不能把浮层通过当作安装中心 1:1 验收。
|
||
|
||
本文证据标签:
|
||
|
||
| 标签 | 含义 |
|
||
| --- | --- |
|
||
| `REA-RUNTIME` | REA 运行时观察到的页面、DOM、布局、视觉或声明式输入结果 |
|
||
| `REA-STATIC` | REA 保存的 renderer script/CSS/manifest 正文静态结论 |
|
||
| `YCODE-SOURCE` | 当前 YCode 源码事实 |
|
||
| `INFERENCE` | 基于证据的工程建议,不能当成原版事实 |
|
||
|
||
## REA 证据清单
|
||
|
||
目标版本均为 WorkBuddy 5.8.3,Windows,Chrome 138 / Electron 37.10.3。主要观察在暗色主题、`1336×1240` 主窗口或 `900×680` 设置窗口下完成。
|
||
|
||
| 用途 | Evidence ID | 保存位置 | 时间(UTC) | 观察范围与边界 |
|
||
| --- | --- | --- | --- | --- |
|
||
| 主窗口基线 | `ev_ab93f4313af45f559597bfa886f218257edb9b8c1c1c056c446b2ed26a2352e9` | `.tmp/rea-todo18-main-visual.json`、`.tmp/rea-todo18-main/` | `2026-10-17T05:44:14.389Z` | 暗色主窗口、1336×1240、无浮层的基线。截图 SHA-256 `b561129cfa37a5b6220e449fd13de7eadc2bc88b68cf48b5c647052aff4a8591`。不能证明打开态。 |
|
||
| 设置窗口基线 | `ev_5b635ae361c0988fa459b5d58897d40ab52ae2e814394b8c21080d1eb9bcb6a1` | `.tmp/rea-todo18-settings.json`、`.tmp/rea-todo18-settings/` | `2026-10-17T05:44:00.912Z` | 暗色设置窗口、900×680,停在“记忆与进化”。截图可见“数据与安全”分组下的“应用管理”导航,但右侧不是应用管理页。截图 SHA-256 `5fe5eb779151e04e1415198cd5e3a2958f02395381cc743713f3cddf9961bc3c`。 |
|
||
| 打开后复核 | `ev_43e8726c4cfac93184509ea30ae0d1305f4ad9c4a186f6ce7a20a7b16810316c` | `.tmp/rea-todo18-discover-after.json`、`.tmp/rea-todo18-discover-after/` | `2026-10-17T05:45:42.851Z` | 截图 SHA 与主窗口基线完全相同,画面未出现浮层。它不能作为“发现应用”打开态证据。 |
|
||
| 键盘打开过程 | `ev_d3527391f609e4a8cb4d194a24ee17dcbbdfc0a2d58db240ef3686119694d85f` | `.tmp/rea-todo18-discover-key.json`、`.tmp/rea-todo18-discover-key/` | `2026-10-17T05:49:07.439Z` | REA 对 `.industry-template-switcher__trigger` 执行 Enter,动作完成并等待 500ms;`frame-000.png` 显示浮层。最终截图 SHA `65f7ce3cd1d81f4f01f9fabe745b50c0236831f55e69b2012f0fe4e2135271cc`。只证明入口可打开,不证明搜索、选择、滚动到底和授权。 |
|
||
| 稳定打开态 | `ev_bd22e46c95d3887daba16dbe319389ad74e10afea8f71af9a7639e8bce95ebb4` | `.tmp/rea-todo18-discover-state.json`、`.tmp/rea-todo18-discover-state/` | `2026-10-17T05:49:49.145Z` | 暗色浮层稳定截图 SHA-256 `f5284085280418769f8c6f022c1e2451f167815783227373c2a90d766ea2bd40`。含布局树,但 REA 布局不含文本/input value,应用名称与描述需结合同次截图。 |
|
||
| renderer 脚本源 | `ev_2b8db4eb73c59a8d3d80c3e37db5ea9b5bf1d13390d5238d81ff2cc53d11dc09` | `.tmp/rea-todo18-main-scripts.json`;恢复件 `.tmp/rea-todo18-matches/contexts-DgzzFjnf.js` | 采集于 2026-10-17 | REA 捕获 321 个当前已加载脚本。`contexts-DgzzFjnf.js` 为 7,553,508 bytes,SHA-256 `8d0c375f141cf724c7f77233ee1d54dd21c9cc86286b79d119711f34a6236746`。其中包含发现浮层、API、登录、consent、依赖和缓存逻辑。 |
|
||
| 样式源 | `ev_7eb66ea8d5949eb7d872f1a93a97894a811b3beb7a02eabd81a500409f1045e4` | `.tmp/rea-todo18-styles-current.json`、`.tmp/rea-todo18-current-contexts.css`、`.tmp/rea-todo18-industry.css` | 采集于 2026-10-17 | `contexts-BkjwYSZT.css` 为 1,600,789 bytes,SHA-256 `50cbd673f7f35fc7f966bdddc6c9f5677fdfe944cb904888d214619fca259380`。恢复出的行业浮层规则文件为 21,085 bytes,SHA-256 `ab1771d8109a137d566e19d24901fa088f893354553900172e5719684de58a5d`,只是原 CSS 的子集。 |
|
||
| 当前 target 枚举 | `ev_2504239bed6d570c1e1e274465ffb9989058ba81ea503f7b295db6add4e380f1` | `.tmp/rea-four-modules-install-targets.json` | 采集于 2026-10-17 | WorkBuddy 5.8.3 / Electron 37.10.3;只枚举到主窗口 target `1CAD78026104DDABDB43F9EB6BA7635D`,没有设置窗口。 |
|
||
| 无操作探针确认 | `ev_a3ca56f518f5c5101d2ae6e64f24794a564956da643c11e622c56b5cbb245000` | `.tmp/rea-four-modules-install-probe-minimal.json` | `2026-10-17T10:04:39.891Z` | 使用仅含 wait 的 REA 声明式探针;`probe.status=completed`,0 个探针帧。视觉 viewport 为 `1336×902`,PNG SHA-256 `d6ef3903bee943b69272a003d8ac7753e7bef882d4949d10104ccac06f70115f`。没有点击、导航或设置窗口证据。 |
|
||
| 打开设置探针失败 | 无;工具拒绝后未生成 Evidence ID | `.tmp/rea-four-modules-install-open-settings.json`、`.tmp/rea-four-modules-install-open-settings-retry.json` | 2026-10-17 | 两个文件均 295 bytes;返回 `code=invalid_request`、`category=invalid_input`、`message=Analysis input is invalid. Check the arguments and try again.`。没有证据表明点击已执行;失败后停止重试。 |
|
||
|
||
### 证据边界
|
||
|
||
1. 没有安装中心主页面 DOM、视觉、CSS 或 lazy chunk 正文。
|
||
2. 没有“应用管理”导航的实际点击记录;当前截图只证明导航文字可见。
|
||
3. 没有真实 catalog API 响应、账号/企业 header、登录跳转结果或 consent 页面截图。
|
||
4. 没有安装、更新、卸载、重装、取消、失败、重试或部分成功的产品运行态。
|
||
5. 没有浅色主题下的原版“发现应用”稳定截图;当前浅色验收来自 YCode 自身。
|
||
6. REA DOM/layout 会省略文本和输入值,不能从布局节点单独证明中文文案。
|
||
7. 运行时截图与 DOM/layout 是顺序观察,不是同一原子帧。
|
||
8. 最新打开设置窗口探针在 REA 参数校验阶段失败;没有设置 target、`buddyApps` active 状态或主页面截图。
|
||
9. `BuddyAppsPanel-*` 是否已在当前窗口加载仍未证明;没有打开主页面就不能把“未观察到”写成“不存在”。
|
||
|
||
## 可用入口与选择器
|
||
|
||
### 设置主页面入口
|
||
|
||
`REA-STATIC` 已从保存的 renderer 正文确认设置导航项稳定带有 `data-settings-tab`:
|
||
|
||
```css
|
||
[data-settings-tab="buddyApps"]
|
||
.settings-navigation__item[data-settings-tab="buddyApps"]
|
||
.settings-navigation__item--active[data-settings-tab="buddyApps"]
|
||
```
|
||
|
||
设置窗口外层可用的稳定选择器:
|
||
|
||
```css
|
||
body.settings-window
|
||
.settings-window-root
|
||
.settings-modal__nav
|
||
.settings-navigation
|
||
.settings-modal__content
|
||
.settings-modal__panel
|
||
```
|
||
|
||
现有证据截图对应“应用管理”的导航行,但页面未打开。主协调补采时建议:
|
||
|
||
1. 选择设置窗口自己的 REA target。历史设置 target 为 `8E8A75786E23EA4A57CD049223F7099D`;当前主窗口 target `1CAD78026104DDABDB43F9EB6BA7635D` 不能默认代表设置窗口。
|
||
2. 点击 `button[data-settings-tab="buddyApps"]`。
|
||
3. 等待 `.settings-navigation__item--active[data-settings-tab="buddyApps"]`。
|
||
4. 再等待 500–1000ms,确保 `BuddyAppsPanel-vC0qX_Oo.js` 与其 CSS 懒加载完成。
|
||
5. 因主页面根 class 尚未知,先使用 `.settings-modal__panel`、`.settings-modal__content` 和 `.settings-modal__panel > *` 记录页面边界,不要先假定 `.buddy-apps-panel`。
|
||
6. 同一次 lifecycle 同时采集视觉、script sources 和 style sources;只采稳定页面,不点击安装、更新、卸载或授权动作。
|
||
|
||
### 发现应用浮层
|
||
|
||
`REA-RUNTIME` 与 `REA-STATIC` 共同确认的稳定选择器:
|
||
|
||
```css
|
||
.industry-template-switcher__trigger
|
||
.industry-template-switcher__trigger--general
|
||
.industry-template-switcher__trigger--application
|
||
.industry-template-switcher__reset-button
|
||
.industry-template-switcher__popover[role="dialog"]
|
||
.industry-template-switcher__panel
|
||
.industry-template-switcher__search-header
|
||
.industry-template-switcher__search
|
||
.industry-template-switcher__search .wb-input__inner
|
||
.industry-template-switcher__list
|
||
.industry-template-switcher__group
|
||
.industry-template-switcher__group-items
|
||
.industry-template-switcher__item[data-template-id]
|
||
.industry-template-switcher__item-action-btn
|
||
.industry-template-switcher__retry
|
||
.industry-template-switcher__more
|
||
.industry-template-switcher__back
|
||
.industry-template-switcher__recent-grid
|
||
.industry-template-switcher__empty
|
||
```
|
||
|
||
说明:
|
||
|
||
- `data-template-id` 在运行时实际承载 `applicationId` 值。
|
||
- 选中项在原版是 `role="option"` 的非按钮 `div`,未选中项是可点击 `button`。
|
||
- 不应依赖样式哈希类名 `src-*` 或 `_tag_*`,这些类名跨构建不稳定。
|
||
|
||
## 原版可证行为
|
||
|
||
### 1. 功能开关、登录与入口
|
||
|
||
`REA-STATIC`:
|
||
|
||
- 设置路由 `buddyApps` 由 feature flag `buddyAppEnabled` 控制是否可见。
|
||
- 发现应用根据账号、API route 和 feature flag 决定是否出现。
|
||
- 未登录时点击打开入口会先走登录,不会直接展示云目录。
|
||
- API route 分个人与企业两种;企业路线把 enterprise id 编入路径。
|
||
|
||
`REA-RUNTIME`:
|
||
|
||
- 暗色主窗口侧栏顶部存在“发现应用”胶囊入口。
|
||
- 当前截图中的入口是通用态,文案“发现应用”,不是已选中某个业务应用的状态。
|
||
|
||
### 2. 浮层结构与分组
|
||
|
||
`REA-RUNTIME` 稳定打开态:
|
||
|
||
| 结构 | 实测 |
|
||
| --- | --- |
|
||
| 触发按钮 | `[173.28125,48,98,28]`;12/500/20;暗色背景 `rgb(46,46,46)`;圆角 100px |
|
||
| 浮层 | `[31,82,240,420]`;固定定位;padding 8;圆角 16;暗色背景 `rgb(36,36,36)` |
|
||
| 内面板 | `[40,91,222,402]` |
|
||
| 搜索区 | `[40,91,222,33]`,输入框 `[40,91,222,28]` |
|
||
| 列表视口 | `[40,128,222,365]`;gap 4;纵向滚动 |
|
||
| 推荐组 | 标题高 24,条目列表高 960;按 48px 行高可容纳 20 项后继续滚动 |
|
||
| 条目 | 218×48;padding 8;gap 12;圆角 8 |
|
||
| 图标 | 24×24;列表中圆形,暗色背景 `rgb(41,41,41)` |
|
||
| 标题/描述 | 13/16、11/14;描述为 50% 暗色文字 |
|
||
|
||
当前截图可见的推荐样例为“通达信、企鹅教师助手、美图设计室、腾讯自选股、腾讯电子签AI合同助手、Alpha派 Lite、广发证券”。这些是随账号/服务变化的运行时数据样例,**不得写死为 YCode 目录契约**。
|
||
|
||
### 3. 列表、搜索和分页
|
||
|
||
`REA-STATIC`:
|
||
|
||
- `recent` 与 `recommended` 各按场景请求 20 项。
|
||
- 默认只展示 recent 前 6 项;recommended 会过滤掉已在 recent 中出现的 `applicationId`。
|
||
- recent 超过 6 项或 `hasMore` 时有“更多”,进入独立 recent 网格视图并可返回。
|
||
- 非搜索模式滚动到距底部 80px 内时调用对应场景的 `loadMore()`。
|
||
- 搜索输入有 250ms debounce;搜索模式隐藏 recent/recommended 分组,只显示搜索结果。
|
||
- 搜索有 loading、error/retry、空结果非搜索和搜索无结果状态。
|
||
- 请求使用 owner key 隔离个人/企业账号;旧请求有 generation guard。
|
||
|
||
`REA-RUNTIME` 只覆盖默认非空推荐列表;上述分页、搜索、错误和空态属于代码事实,未逐态截图。
|
||
|
||
### 4. 条目身份与选择
|
||
|
||
列表 summary 的核心字段来自 `REA-STATIC`:
|
||
|
||
```ts
|
||
interface BuddyApplicationSummary {
|
||
applicationId: string
|
||
name: string
|
||
description?: string
|
||
icon?: string
|
||
operationTag?: {
|
||
title: string
|
||
description: string
|
||
}
|
||
}
|
||
```
|
||
|
||
条目行为:
|
||
|
||
- 未选中行悬停/聚焦显示“进入”动作;选中行显示品牌色对勾与“退出”。
|
||
- 选中项由当前应用/模板选择状态决定,不由列表自带 installed 布尔值决定。
|
||
- 点击未选中 summary 后,浮层先关闭,再请求 detail。
|
||
|
||
### 5. 应用详情、激活与授权
|
||
|
||
`REA-STATIC` 证明的 detail 字段:
|
||
|
||
```ts
|
||
interface BuddyApplicationTemplate {
|
||
templateId: string
|
||
applicationId: string
|
||
name: string
|
||
templateName: string
|
||
description?: string
|
||
category?: string
|
||
operationTag?: { title: string; description: string }
|
||
icon?: string
|
||
schemaVersion: number
|
||
templateVersion: number
|
||
versionNo: number
|
||
requiredScopes: string[]
|
||
allowedOrigins: string[]
|
||
templateConfig: unknown
|
||
releaseNote?: string
|
||
publishedAt?: string
|
||
}
|
||
```
|
||
|
||
上面的 `templateConfig` 在实际代码里还有 schema 校验;这里保留为 `unknown`,避免把未经原文逐项恢复的完整 schema 当成 YCode 契约。
|
||
|
||
选择流程:
|
||
|
||
1. 请求 detail。
|
||
2. 等待本地选择状态 hydrated,最长 8s。
|
||
3. 校验账号在异步过程中没有切换。
|
||
4. 调登录/授权状态接口,取得 `authorized`、application、redirect URI 和 granted scopes。
|
||
5. 已授权则直接提交本地模板上下文。
|
||
6. 未授权则显示 consent;用户可批准或跳过跳转。
|
||
7. consent 后获得一次性 code 和 granted scopes。
|
||
8. 根据模板配置安装/连接 MCP 依赖,并可能打开外部 authorization URL。
|
||
9. 成功后提交模板选择、上报 usage、触发 onboarding,并返回主页。
|
||
10. 退出当前应用时清空选择,并尝试移除该应用的 MCP dependency。
|
||
|
||
全局同一时间只允许一个应用切换流程,避免并发授权。
|
||
|
||
### 6. 远程 API 事实
|
||
|
||
`REA-STATIC` 中可确认的个人账号端点:
|
||
|
||
| 功能 | 方法 | 路径/参数 |
|
||
| --- | --- | --- |
|
||
| 场景列表 | GET | `/api/v1/open-platform/buddy_application?limit={limit}&scene={recent\|recommended}[&cursor=...]` |
|
||
| 搜索 | POST | `/api/v1/open-platform/buddy_application/search`,body `{ keyword }` |
|
||
| 详情 | POST | `/api/v1/open-platform/buddy_application/detail`,body `{ application_id }` |
|
||
| 使用上报 | POST | `/api/v2/open-platform/asset-usage/report`,body `{ asset_id, asset_type: "buddy_app" }` |
|
||
| 入口可用性 | GET | `/api/v2/open-platform/buddy/entrance` |
|
||
|
||
企业账号使用 `/v2/enterprises/{enterpriseId}` 前缀和对应子路径。
|
||
|
||
列表响应可确认字段包括 `applications`、`has_more`、`next_cursor`。请求会按需附加 `X-GPU-DEVICE-NAME`。
|
||
|
||
**目前没有证据证明以下接口:**应用包下载、安装、更新、卸载、版本检查、安装进度、取消、回滚、权限撤销、已安装列表。不能用上述 discovery/usage 端点臆造完整安装 API。
|
||
|
||
### 7. 设置页中的应用管理
|
||
|
||
`REA-STATIC` 已确认:
|
||
|
||
- 设置 route id 为 `buddyApps`。
|
||
- 入口是 `button[data-settings-tab="buddyApps"]`,中文截图显示“应用管理”。
|
||
- 页面是懒加载 `BuddyAppsPanel-vC0qX_Oo.js`,配套 `BuddyAppsPanel-OzkcFEe0.css`。
|
||
- route 可用性受 `buddyAppEnabled` 控制。
|
||
|
||
**尚不能确认:**
|
||
|
||
- 主页面标题、分组、搜索、筛选和排序。
|
||
- 是否显示市场目录、已安装应用或两者共存。
|
||
- installed 的判定规则,以及安装与应用激活是否同一概念。
|
||
- 版本、更新提示、自动更新、更新检查、发布说明。
|
||
- 安装、更新、卸载、打开、停用、退出、重试、取消的入口和确认方式。
|
||
- loading、empty、error、partial、offline、unauthorized、dependency-missing 状态。
|
||
- 主页面的所有几何、深层深浅主题和动画。
|
||
|
||
这是主协调下一步最优先的 REA 补采目标。
|
||
|
||
2026-10-17 补采结果:
|
||
|
||
- 设置窗口 target 不在当前 REA endpoint 的 target 列表中,只有一个主窗口。
|
||
- 计划中的 `open-account-menu → open-settings-window` 探针没有进入动作生命周期;REA 在输入校验阶段返回 `invalid_request / invalid_input`,因此没有 Evidence ID 和声明式动作步骤。
|
||
- 没有采集 `button[data-settings-tab="buddyApps"]`、`.settings-navigation__item--active[data-settings-tab="buddyApps"]` 或 `.settings-modal__panel` 的主页面内容。
|
||
- 本专项按用户要求停止重复尝试。安装中心主页面的布局、状态、版本更新、卸载和错误恢复仍为明确未知,等待后续设置窗口 target 和新 Evidence 补证。
|
||
|
||
## YCode 当前状态
|
||
|
||
### 已实现
|
||
|
||
| 能力 | 状态 | 主要源码 |
|
||
| --- | --- | --- |
|
||
| “发现应用”入口与浮层 | 已实现可交互壳 | `src/renderer/src/components/AppDiscoverPopover.tsx` |
|
||
| 浮层几何、搜索、空态、键盘、外部点击、焦点恢复 | 已实现本地版本 | 同上、`app-discover-popover.css` |
|
||
| 最近使用 | 已实现 localStorage 版,最多 6 个本地能力 ID | `ycode.app-discover.recent.v1` |
|
||
| 应用选择 | 映射到 experts / skills / connectors 三个本地能力页 | `Sidebar.tsx`、`App.tsx`、`CapabilityCenter.tsx` |
|
||
| 选中态退出 | 从本地能力页回到聊天 | `AppDiscoverPopover` 的 `onExit` |
|
||
| 本地能力 | 专家、本地技能、自定义 MCP 已有各自页面和数据层 | `src/renderer/src/capabilities/` |
|
||
|
||
### 占位
|
||
|
||
| 能力 | 现状 |
|
||
| --- | --- |
|
||
| 技能市场 | 技能页对未连接目录显示本地空态,可导入本地技能 |
|
||
| 连接器目录 | 当前以自定义 MCP 为主,云目录和第三方 OAuth 未接 |
|
||
| 最近使用 | 只保存本地三个 capability ID,不是原版账号级应用使用历史 |
|
||
| 应用图标 | 使用本地 SVG,不是远端应用图标和失败 fallback |
|
||
|
||
### 缺失
|
||
|
||
| 能力 | 缺口 |
|
||
| --- | --- |
|
||
| 安装中心主页面 | 完全缺失;设置导航中 `buddyApps` 还被用户明确移除 |
|
||
| 云应用目录 | 无列表、搜索、detail、最近、推荐和分页 API |
|
||
| 应用身份模型 | 无 `applicationId/templateId/version/scopes` 数据 |
|
||
| 安装状态机 | 无 installed/installing/updating/uninstalling/failed |
|
||
| 安装来源 | 无市场、企业、URL、本地包或内置来源模型 |
|
||
| 更新与版本 | 无版本比较、release note、更新检查 |
|
||
| 卸载与恢复 | 无卸载确认、部分失败、重试、回滚 |
|
||
| 授权 | 无 login、consent、scope grant、redirect URI |
|
||
| 应用依赖 | 无应用级 MCP dependency 安装/移除 |
|
||
| 使用上报/onboarding | 无 usage report、show observer、onboarding 状态 |
|
||
| 管理入口 | `SettingsDialog.tsx` 的 `REMOVED_SETTINGS_TABS` 包含 `buddyApps` |
|
||
|
||
### 需要先决定的产品边界
|
||
|
||
用户此前要求移除“系统设置 → 应用管理”入口。若后续恢复安装中心,不应静默推翻该决定。可由主协调确认采用下列之一:
|
||
|
||
1. 保留设置入口移除,只在侧栏“发现应用”中增加管理/浏览入口。
|
||
2. 恢复“应用管理”设置页,同时保留“发现应用”作为切换器。
|
||
3. 将两者合并为独立安装中心页面,设置与侧栏都指向同一路由。
|
||
|
||
本拆解建议先按“两个表面、一个状态源”设计:发现浮层负责快速发现/切换,安装中心管理页负责目录、安装、版本、授权和卸载;两侧共享同一 registry,避免出现两套 installed 状态。
|
||
|
||
## 建议数据契约
|
||
|
||
以下是 `INFERENCE`,用于 YCode 后续实现;字段名尽量贴近 REA 静态事实,但不冒充原版完整 schema。
|
||
|
||
```ts
|
||
type BuddyAppSource = 'builtin' | 'marketplace' | 'enterprise' | 'local'
|
||
type BuddyAppAvailability = 'available' | 'unavailable' | 'entitlement-required'
|
||
type BuddyAppLifecycle =
|
||
| 'not-installed'
|
||
| 'installing'
|
||
| 'installed'
|
||
| 'active'
|
||
| 'updating'
|
||
| 'update-available'
|
||
| 'uninstalling'
|
||
| 'failed'
|
||
| 'unauthorized'
|
||
| 'dependency-missing'
|
||
|
||
interface BuddyAppSummary {
|
||
applicationId: string
|
||
templateId?: string
|
||
name: string
|
||
description?: string
|
||
iconUrl?: string
|
||
operationTag?: { title: string; description?: string }
|
||
source: BuddyAppSource
|
||
availability?: BuddyAppAvailability
|
||
}
|
||
|
||
interface BuddyAppDetail extends BuddyAppSummary {
|
||
name: string
|
||
versionNo: number
|
||
templateVersion?: number
|
||
schemaVersion?: number
|
||
category?: string
|
||
requiredScopes: string[]
|
||
allowedOrigins: string[]
|
||
templateConfig: unknown
|
||
releaseNote?: string
|
||
publishedAt?: string
|
||
}
|
||
|
||
interface BuddyAppRegistryEntry {
|
||
applicationId: string
|
||
templateId?: string
|
||
installedVersion?: number
|
||
availableVersion?: number
|
||
lifecycle: BuddyAppLifecycle
|
||
source: BuddyAppSource
|
||
installedAt?: number
|
||
lastOpenedAt?: number
|
||
lastError?: string
|
||
operationId?: string
|
||
dependencies: BuddyAppDependencyState[]
|
||
}
|
||
|
||
interface BuddyAppDependencyState {
|
||
kind: 'mcp' | 'connector'
|
||
key: string
|
||
state: 'missing' | 'installing' | 'connected' | 'needs-auth' | 'error'
|
||
error?: string
|
||
}
|
||
|
||
interface BuddyAppOperation {
|
||
operationId: string
|
||
applicationId: string
|
||
kind: 'install' | 'update' | 'uninstall' | 'activate' | 'deactivate'
|
||
phase: 'queued' | 'downloading' | 'verifying' | 'applying' | 'authorizing' | 'connected' | 'done' | 'failed' | 'cancelled'
|
||
progress?: number
|
||
message?: string
|
||
startedAt: number
|
||
finishedAt?: number
|
||
}
|
||
```
|
||
|
||
工程约束:
|
||
|
||
- `applicationId` 与 `templateId` 分开;现有原版列表以 `applicationId` 去重。
|
||
- 版本、scope、origin、redirect URI 必须保存快照,避免更新过程中配置变化。
|
||
- installed、active、authorized、dependency-ready 必须分开。
|
||
- operationId 用于 UI 去重和恢复;不能只靠 loading 布尔值。
|
||
- token、authorization code、secret 不进入 renderer 持久状态或日志。
|
||
|
||
## 本地功能与远端依赖边界
|
||
|
||
| 能力 | 本地可完成 | 依赖远端/宿主 |
|
||
| --- | --- | --- |
|
||
| 浮层/主页面布局 | 是 | 否 |
|
||
| 列表缓存、最近使用、当前选择 | 是 | 初次目录数据需要远端 |
|
||
| 本地 registry 和 operation journal | 是 | 状态变更需要服务端确认 |
|
||
| 目录列表、搜索、详情 | 否 | 是 |
|
||
| 登录、consent、scope grant | 否 | 是 |
|
||
| 应用包下载、校验、安装、更新、卸载 | 否 | 是;若 YCode 自建安装包生态则另立本地协议 |
|
||
| 应用模板 config 和 allowed origin | 可缓存 | 更新源来自远端 |
|
||
| MCP dependency 本地注册 | 是 | 授权/远端 connector 仍可能需要服务端 |
|
||
| usage report、show/click telemetry | 可本地排队 | 上报需要远端 |
|
||
| entitlement、企业策略、配额 | 否 | 是 |
|
||
| 错误文案和恢复 UI | 是 | 具体 reason code 来自宿主/服务端 |
|
||
| 安装 provenance/checksum | 可实现本地校验器 | 可信摘要/签名来源需可信配置 |
|
||
|
||
原则:没有真实安装结果时,UI 只能显示“未接入/等待服务”,不能显示“安装成功”。
|
||
|
||
## 建议模块拆分
|
||
|
||
### A. `buddyAppCatalog`
|
||
|
||
职责:
|
||
|
||
- recent/recommended/search/detail。
|
||
- 500ms 内搜索 debounce 的内部实现可沿用 250ms 事实,但需要统一 abort/generation。
|
||
- 账号、企业、feature flag 作为请求 key。
|
||
- summary/detail 校验、去重、缓存和 stale 响应丢弃。
|
||
|
||
不负责安装状态。
|
||
|
||
### B. `buddyAppRegistry`
|
||
|
||
职责:
|
||
|
||
- 已安装列表、版本、来源、最近打开时间。
|
||
- selected application/template。
|
||
- install/update/uninstall/active 状态。
|
||
- 操作日志、错误和恢复。
|
||
|
||
本地 registry 必须可以独立启动;远端 catalog 失败不能让已安装应用消失。
|
||
|
||
### C. `buddyAppInstaller`
|
||
|
||
职责:
|
||
|
||
- 下载、完整性校验、解包/安装、原子切换、失败回滚。
|
||
- operation progress/cancel。
|
||
- 安装来源差异。
|
||
|
||
此模块是否存在原版真实包安装流程目前未知;不得把“安装 MCP dependency”改名为“安装应用”。
|
||
|
||
### D. `buddyAppAuthorization`
|
||
|
||
职责:
|
||
|
||
- login/authorized 状态。
|
||
- consent、scope diff、grant。
|
||
- redirect/MCP 授权的衔接。
|
||
- 账号切换取消未完成操作。
|
||
|
||
### E. `buddyAppUi`
|
||
|
||
包含两个 surface:
|
||
|
||
- switcher:快速发现、最近、推荐、搜索、切换/退出。
|
||
- manager:已安装、目录、版本、更新、卸载、授权、依赖、错误恢复。
|
||
|
||
两者共享 Registry/Store,但各自保留 surface-specific UI state。
|
||
|
||
### F. `buddyAppObservability`
|
||
|
||
- 展示曝光、点击、进入、consent、授权失败、usage report。
|
||
- 事件失败不能破坏业务主流程。
|
||
- 脱敏 app id/version,不记录 token/code/secret。
|
||
|
||
## 分批任务与验收标准
|
||
|
||
### 批次 0:补采应用管理主页面
|
||
|
||
范围:
|
||
|
||
- 主协调通过现有 REA lifecycle,在设置窗口点击 `[data-settings-tab="buddyApps"]`。
|
||
- 同次 capture 开启 scripts、styles、visuals。
|
||
|
||
验收:
|
||
|
||
- 捕获到 `BuddyAppsPanel-vC0qX_Oo.js` 正文或其新的 build hash。
|
||
- 捕获到 `BuddyAppsPanel-*.css` 正文。
|
||
- 新 Evidence ID、target、captured_at、script/CSS SHA-256、viewport、theme 全部记录。
|
||
- 产出主页面 DOM/layout/稳定截图,至少覆盖默认稳定态。
|
||
- 明确没有触发安装、更新、卸载、授权等有副作用动作。
|
||
|
||
当前状态:**已尝试,未完成。** 最新 target 枚举只有主窗口;打开设置窗口的探针在 REA 参数校验阶段失败,没有设置 target。批次 0 未通过,阻塞条件正是设置页面 source/lifecycle,而不是已有静态结论不足。
|
||
|
||
取消条件:
|
||
|
||
- 只采到导航 active class,未加载 lazy chunk。
|
||
- 只采到 `.settings-modal__panel` 但内容仍为其他设置页。
|
||
|
||
### 批次 1:数据契约与只读 registry
|
||
|
||
范围:
|
||
|
||
- 建 `BuddyAppSummary/Detail/RegistryEntry/Operation/Dependency` 类型。
|
||
- 建立按账号/企业隔离的本地 registry。
|
||
- 无远端时显示真实“目录未连接”,已安装本地条目仍可展示。
|
||
|
||
验收:
|
||
|
||
- ID 身份稳定;同 application 不会因 template 版本重复成多张卡。
|
||
- 本地 registry 跨重启保留。
|
||
- account/enterprise 切换不会串数据。
|
||
- 没有真实 installed 数据时不伪造 installed 状态。
|
||
|
||
### 批次 2:应用管理页壳与本地状态
|
||
|
||
范围:
|
||
|
||
- 安装中心主页面骨架、搜索、筛选、分组。
|
||
- 列表、空态、加载态、错误态和 operation banner。
|
||
- 配置入口决定:独立页或恢复设置入口由主协调拍板。
|
||
|
||
验收:
|
||
|
||
- 在 900×680 设置窗口和主窗口布局无溢出。
|
||
- 浅色/深色、正常/窄宽、空/错/loading 可稳定渲染。
|
||
- `[data-settings-tab="buddyApps"]` 或替代入口的导航语义明确。
|
||
- 不依赖云端即可打开本地 manager shell。
|
||
|
||
### 批次 3:目录列表、搜索和详情
|
||
|
||
范围:
|
||
|
||
- recent/recommended/search/detail adapter。
|
||
- summary 去重、分页、stale guard、请求取消。
|
||
|
||
验收:
|
||
|
||
- 空查询、250ms 搜索、无结果、失败重试、下一页、末尾停止。
|
||
- recent 与 recommended 去重。
|
||
- account/enterprise 切换取消旧请求。
|
||
- 远端不可达时返回可恢复错误,不显示空目录冒充成功。
|
||
|
||
### 批次 4:安装/激活状态机
|
||
|
||
范围:
|
||
|
||
- `not-installed → installing → installed → active` 等状态。
|
||
- 同一 application 的并发操作锁。
|
||
- failure、retry、cancel、app restart 恢复。
|
||
|
||
验收:
|
||
|
||
- 双击安装只产生一个 operation。
|
||
- UI 进度来自 operation 状态,不由定时器模拟。
|
||
- 失败不会部分标记 installed。
|
||
- 重启后未完成操作可查询、恢复或明确标记未知。
|
||
- “安装应用”与“安装 MCP dependency”在产品文案和状态上分开。
|
||
|
||
### 批次 5:更新、卸载与恢复
|
||
|
||
范围:
|
||
|
||
- 版本比较、release note、确认流程。
|
||
- 卸载对 active 应用、MCP dependency、云端授权和本地数据的影响。
|
||
|
||
验收:
|
||
|
||
- 同版本、旧版本、新版本、降级、unknown version均有明确状态。
|
||
- 更新失败回滚到旧版本和旧 selected template。
|
||
- 卸载前明确是否保留本地数据与授权。
|
||
- 卸载失败可重试,不把卡片直接删掉。
|
||
|
||
### 批次 6:登录、consent、scope 和依赖授权
|
||
|
||
范围:
|
||
|
||
- login/authorization adapter。
|
||
- consent summary、scope diff、取消、拒绝、跳转失败、回到桌面。
|
||
- MCP/builtin/custom/joint auth 分支。
|
||
|
||
验收:
|
||
|
||
- 账号切换时取消旧流程。
|
||
- redirect URI、scopes、template version 在授权期间发生变化则拒绝提交。
|
||
- 取消/失败不会写入 ready 状态。
|
||
- code/token 不落盘、不打印。
|
||
- 依赖失败与应用安装状态可区分。
|
||
|
||
### 批次 7:像素与全状态验收
|
||
|
||
范围:
|
||
|
||
- switcher 与 manager 的原版同数据、同主题、同尺寸对照。
|
||
|
||
验收:
|
||
|
||
- 入口、popover、manager 默认态在浅/深色完成截图和几何比对。
|
||
- 搜索、loading、error、empty、scroll、load-more、hover、focus、selected、disabled。
|
||
- 安装、更新、卸载、授权、依赖、失败、重启恢复。
|
||
- 键盘、focus trap、Escape/外部点击、IME 和窄窗。
|
||
- 不以 YCode 专项 PASS 代替 WorkBuddy 同状态 1:1。
|
||
|
||
## 精确未知项
|
||
|
||
### 主页面与产品信息架构
|
||
|
||
1. 设置“应用管理”和侧栏“发现应用”是否共享同一个应用实体、选择状态和 installed 列表。
|
||
2. 主页面是否只管理已安装应用,还是也展示市场目录。
|
||
3. 主页面标题、分组、筛选、排序、搜索和详情进入方式。
|
||
4. 是否支持企业目录、内置应用、本地应用和第三方 market 的混合列表。
|
||
|
||
### 安装语义
|
||
|
||
1. “安装”是否下载本地包,还是只创建账号授权/云端绑定。
|
||
2. 安装与应用“进入/激活”是否同一操作。
|
||
3. 安装成功后是否立即成为当前应用,还是仍展示“进入”。
|
||
4. 同一 application 是否可安装多个 template/version。
|
||
|
||
### 更新语义
|
||
|
||
1. 更新源、版本比较规则和自动/手动检查时机。
|
||
2. 更新通知显示位置、release note 来源和强制更新规则。
|
||
3. 更新中能否使用当前版本,失败时是否回滚。
|
||
|
||
### 卸载语义
|
||
|
||
1. 卸载按钮的确认文案和危险色层级。
|
||
2. 本地数据、云端 grant、MCP dependency、recent snapshot 是否一起清除。
|
||
3. active 应用或 dependency-disconnected 状态下的卸载限制。
|
||
|
||
### 状态与错误
|
||
|
||
1. 完整状态枚举和 reason codes。
|
||
2. 进度是否支持百分比、字节数、阶段文案。
|
||
3. 取消、超时、断网、配额不足、企业策略、权限撤销、依赖失败的实际文案。
|
||
4. 失败后 operation 是否保留、恢复或可重试次数。
|
||
|
||
### 数据与持久化
|
||
|
||
1. 本机 registry 的 storage key、schema version、账号/企业隔离。
|
||
2. 已安装包位置、完整性校验、签名和升级目录。
|
||
3. recent/show/usage 的服务端与本地双层缓存。
|
||
4. 应用图标 URL、缓存、CSP 和失败 fallback。
|
||
|
||
### 视觉
|
||
|
||
1. “应用管理”主页面完整 DOM/CSS、默认数据量和空数据量。
|
||
2. 浅色稳定态和深色稳定态。
|
||
3. 安装/更新/卸载/授权弹窗与 toast。
|
||
4. 菜单、hover、disabled、focus、loading、滚底、分页。
|
||
5. 900×680 设置窗口之外的独立页面尺寸。
|
||
|
||
## 补采检查表
|
||
|
||
主协调下一次统一补采应至少保存:
|
||
|
||
- 设置 target id、窗口 URL 和 viewport。
|
||
- `[data-settings-tab="buddyApps"]` 点击前后稳定帧。
|
||
- 主页面 `.settings-modal__panel` 的 DOM、layout、可见文本和截图。
|
||
- `BuddyAppsPanel-vC0qX_Oo.js`/新 hash 的完整 REA script source。
|
||
- `BuddyAppsPanel-OzkcFEe0.css`/新 hash 的完整 REA style source。
|
||
- 默认列表数量及至少一个已安装、一个未安装、一个有更新条目的字段。
|
||
- 主操作的 DOM selector、文案、disabled 条件和确认弹窗。
|
||
- 浅色与深色稳定态;若窗口主题由设置控制,记录切换证据。
|
||
- 只读网络/状态来源证据;不在主页面直接执行真实安装或卸载。
|
||
|
||
建议的探针起点:
|
||
|
||
```json
|
||
[
|
||
{
|
||
"kind": "click",
|
||
"selector": "[data-settings-tab=\"buddyApps\"]",
|
||
"frames": 0
|
||
},
|
||
{
|
||
"kind": "wait",
|
||
"duration_ms": 750,
|
||
"frames": 1
|
||
}
|
||
]
|
||
```
|
||
|
||
探针完成后以 `.settings-navigation__item--active[data-settings-tab="buddyApps"]` 确认路由,再检查 `.settings-modal__panel` 内是否出现新模块内容。
|
||
|
||
## 决策
|
||
|
||
1. **不把发现浮层等同于安装中心。** 两者共享可能的数据,但当前证据将它们拆为 switcher 与 manager 两个 surface。
|
||
2. **不在主页面证据缺失时实现安装按钮。** 后续先建立 registry/operation 状态,再接真实能力。
|
||
3. **把 installed、active、authorized、dependency-ready 分开。** 现有原版已证明选择/授权/依赖是独立步骤。
|
||
4. **应用 ID 使用 `applicationId` 作为首选去重键。** `templateId`、version 和 schema 另存。
|
||
5. **远端目录失败不等于空目录。** 本地已安装 registry 必须离线可见,远端错误必须可恢复。
|
||
6. **保留用户移除设置入口的决定。** 安装中心的最终入口位置需要主协调明确,不能擅自恢复 `buddyApps` 设置项。
|
||
7. **sample app 名称只作截图样例。** 通达信等运行时条目不得写死。
|
||
|
||
## 本轮核对命令
|
||
|
||
本轮没有运行测试或构建。除下方明确列出的 REA target 枚举和两次声明式探针外,其余核对均为静态读取。
|
||
|
||
```text
|
||
rg --files docs | rg '安装|应用|发现|中心|模块拆解'
|
||
Get-ChildItem .tmp -Recurse | Where-Object FullName -match 'rea-todo18'
|
||
rg -n '安装中心|发现应用|Discover|app discover|install' docs src scripts
|
||
Get-Content docs/复刻待办清单-2026-10-17.md
|
||
Get-Content src/renderer/src/components/AppDiscoverPopover.tsx
|
||
Get-Content src/renderer/src/components/app-discover-popover.css
|
||
Get-Content src/renderer/src/capabilities/CapabilityCenter.tsx
|
||
Get-Content scripts/verify-app-discover.cjs
|
||
Get-Content .tmp/rea-todo18-BuddyAppDiscoverPanel.js
|
||
Get-Content .tmp/rea-todo18-BuddyAppIcon.js
|
||
Python 解析 .tmp/rea-todo18-*.json 的 evidence_id、target、captured_at、viewport、artifact SHA-256、limitations
|
||
Python 解析 .tmp/rea-todo18-main-scripts.json 的 contexts-DgzzFjnf.js source artifact
|
||
Python 解析 .tmp/rea-todo18-styles-current.json 的 contexts-BkjwYSZT.css source artifact
|
||
Python 解析 .tmp/rea-todo18-discover-state/layout.json 的浮层几何
|
||
Python 解析 .tmp/rea-todo18-settings/layout.json 的设置导航结构
|
||
Python 在保存的 contexts-DgzzFjnf.js 中检索 API、selection、consent、dependency、settings route
|
||
```
|
||
|
||
2026-10-17 新增的 REA 读取与失败记录:
|
||
|
||
```text
|
||
node .tmp/rea-css-runtime/scripts/rea.mjs list-electron-targets http://127.0.0.1:9223
|
||
REA inspect-electron-page:主窗口 + 仅 wait 的 visual_probe
|
||
REA inspect-electron-page:主窗口 + 打开账户菜单/设置窗口的 visual_probe
|
||
结果:target list 成功;无操作探针成功;设置打开探针 invalid_request,未生成 Evidence ID
|
||
保存:.tmp/rea-four-modules-install-targets.json
|
||
.tmp/rea-four-modules-install-probe-minimal.json
|
||
.tmp/rea-four-modules-install-open-settings.json
|
||
.tmp/rea-four-modules-install-open-settings-retry.json
|
||
```
|
||
|
||
## 风险
|
||
|
||
1. **把浮层当完整安装中心**:会严重高估完成度。
|
||
2. **把 MCP 依赖安装冒充应用安装**:原版代码明确区分 dependency 与 application 选择。
|
||
3. **恢复已移除设置入口而不确认**:与用户此前要求冲突。
|
||
4. **远端服务不可用时伪造状态**:可产生虚假 installed/update 结果。
|
||
5. **账号/企业隔离错误**:可能把企业目录、授权或用量混进个人数据。
|
||
6. **授权并发和账号切换**:可能出现旧 consent 写入新账号。
|
||
7. **安装/更新破坏用户内容**:需要原子操作、备份、回滚和明确确认。
|
||
8. **敏感信息泄漏**:authorization code、token、secret 和完整远端 URL 不应进入日志/普通本地状态。
|
||
9. **运行时动态条目被写死**:sample app 名称、顺序和描述会随账号/服务变化。
|
||
10. **主页面像素误判**:当前没有该页面任何 REA 视觉,不能从浮层几何推导。
|
||
|
||
## 交接结论
|
||
|
||
本轮安装中心专项到此收口:已有足够证据拆出“发现浮层”和“安装中心主页面”两个 surface,以及目录、选择、授权、依赖和未知安装生命周期边界;但安装中心主页面仍没有 REA 运行时证据。下一步需要先获得可操作的原版设置窗口 target,再点击 `[data-settings-tab="buddyApps"]` 并同次采集 DOM、视觉、脚本和样式。补采成功后,优先恢复 `BuddyAppsPanel` 的 DOM/CSS 和页面状态,再决定 manager 的真实信息架构。YCode 已有浮层壳可以保留,但其数据层仍是本地能力适配,必须和后续云应用 registry 解耦。
|