Files
hermes-ui/docs/phases/phase_004.md
T
toor 1e9ea89d86
Build / build (push) Canceled after 0s
NPM Lockfile Check / npm ci --ignore-scripts (push) Canceled after 0s
Playwright / e2e (push) Canceled after 0s
chore: bootstrap hermes-ui skeleton from 0.6.29 snapshot
Import the client, server, skills, tests, and build scripts as the starting
point for the rebuild, then trim the surfaces this project does not ship:
Electron desktop packaging, the marketing website, and the ESP32 firmware
tree. CI keeps the web build, e2e, lockfile, release, and Docker workflows.

Rename the package and CLI entry points to hermes-ui, drop the prepare hook so
npm ci no longer triggers a build, and drop the removed tsconfig and nodemon
references. Rewrite AGENTS.md, ARCHITECTURE.md, DEVELOPMENT.md, and the READMEs
so the documented package map and hard rules match this repository.

reference_code/ is ignored: it is a read-only snapshot, not an input to the build.
2026-10-16 10:34:35 +08:00

254 lines
8.1 KiB
Markdown
Raw 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.
# Phase 004 — 砍桌面端 + 官网 + 清理依赖
| 项 | 值 |
|---|---|
| 目标 | 无 Electron、无官网;hermes CLI 改用户自装;依赖表与 lockfile 一次性收干净 |
| 前置 | Phase 003 通过 |
| 产出 | `npm ci && npm run build && npm run test:e2e` 全绿;gateway 自启仍工作 |
| 参考 | `docs/03-施工蓝图.md` §6 |
---
## 0. 已核实:gateway 自启零迁移
原蓝图担心的「gateway 自启逻辑一半长在 Electron 里」**不存在**。
`packages/server/src/index.ts` 的 `startRuntimeServicesBeforeListen()` / `startRuntimeServicesAfterListen()` 已经调用 `ensureProfileGatewaysRunning()`。
Electron 侧只有两处:
1. `gateway-autostart.ts` 里 `shouldRecoverWindowsDesktopGatewayOrphans()` 依赖 `HERMES_DESKTOP`
2. 注册在 `/api/desktop/shutdown` 的关闭回调
**本 Phase 只删这两处,不做任何迁移。**
---
## 1. 功能任务 1 — 删除 desktop 与 website
Phase 001 已删掉 `packages/desktop` / `packages/website` / 相关 workflow。本 Phase 处理**引用方**。
### 1.1 根 `package.json` scripts
删:
```
desktop:install
desktop:prepare-runtime
desktop:prepare-python
desktop:dev
build:desktop
build:desktop:mac
build:desktop:win
build:desktop:linux
dev:website
build:website
preview:website
claude # I 组配套:claude --dangerously-skip-permissions
```
`mcu:*` 系列:Phase 001 已删 `esp32-c3`,这些 script 也要删。若你后续要做语音硬件,另开 Phase 恢复。
保留:`start` `dev` `dev:client` `dev:server` `build` `harness:check` `preview` `test` `test:watch` `test:coverage` `test:e2e` `test:e2e:ui` `openapi:generate`
### 1.2 server 侧
| 文件 | 改动 |
|---|---|
| `src/index.ts` | 删 `registerDesktopShutdownRoute` import 与调用、删 `desktopShutdownHandler` 变量与赋值、删 `isDesktopEnv()` |
| `src/index.ts` | **注意**:`bindShutdown` 主流程要保留,它也服务正常关停。只删桌面分支 |
| `services/shutdown.ts` | 删 `desktop` 分支,保留主流程 |
| `controllers/auth.ts` | `requiresCredentialChange: process.env.HERMES_DESKTOP === 'true'` → 改常量 `false` 或删该字段 |
| `services/hermes/gateway-autostart.ts` | 删 `shouldRecoverWindowsDesktopGatewayOrphans()` 及 index.ts 里对它的调用 |
| `services/hermes/agent-bridge/manager.ts` | 删 `isDesktopEnv()` 用法 |
| `services/hermes/studio-mcp-autoinject.ts` | 同上 |
### 1.3 client 侧
| 文件 | 改动 |
|---|---|
| `src/utils/desktop-bridge.ts` | **整个文件删除** |
| `src/App.vue` | 删 `desktopBridge` import、`isDesktopShell` / `isDesktopPetRoute` / `hasDesktopTitleBar`、`DesktopTitleBar` 组件、`WebPet` |
| `src/main.ts` | 删 `desktopBridge` 调用 |
| `src/router/index.ts` | 删 `hermesDesktop` 路由注入逻辑 |
| `src/utils/completion-notification.ts` | 删本地 `desktopBridge` 副本 |
| `src/api/client.ts` | 删对应 import 与分支 |
| `src/components/layout/AppSidebar.vue` | 删对应 import |
| `src/components/layout/DesktopTitleBar.vue` | **整个文件删除** |
| `src/components/auth/DefaultCredentialPrompt.vue` | 删 `desktopBridge` 相关 |
| `src/views/hermes/DesktopPetView.vue` | **整个文件删除** |
| `src/components/hermes/pets/WebPet.vue` | 若无其他引用则删;有引用先解引用 |
### 1.4 测试
```bash
rm -f tests/client/desktop-titlebar.test.ts
rm -f tests/client/app-web-pet.test.ts
```
e2e 里的 desktop 用例移除。
---
## 2. 功能任务 2 — hermes CLI 改用户自装
砍桌面端后 hermes 不再捆绑。改动全部集中在两个文件。
### 2.1 `hermes-path.ts`
`resolveHermesBin()` 已是 `HERMES_BIN` → `'hermes'` 的优先级链,**保持不变**。
改 `bundledCliPythonForWindows()`:删掉「找捆绑运行时」的假设,改为——
- `HERMES_BIN` 指向 `hermes.exe` 时,在同级 / 上级目录找 `python.exe`
- 找不到就用 `hermes.exe` 直调(hermes 官方 Windows 包自带 launcher,不一定需要 `-m hermes_cli.main`)
### 2.2 `hermes-process.ts`
- **不新增 shell 拼接**。所有调用继续走 `execHermesWithBin` / `spawnHermesWithBin`,参数数组
- 加一个 `isHermesCliAvailable()` 探测函数
### 2.3 引导页(用户可见)
启动时若探测不到 hermes CLI,前端显示引导:
```
未检测到 hermes CLI
请先安装:
pip install hermes-agent
或设置环境变量指定路径:
HERMES_BIN=/path/to/hermes
安装后重启本服务。
```
**中英双语都要写**(`zh.ts` + `en.ts`)。
落点建议:新增 `packages/client/src/views/hermes/HermesMissingView.vue`,在 `router/index.ts` 里作为前置守卫(与 `LoginView` 同级,登录前判断)。
---
## 3. 功能任务 3 — 依赖与 lockfile 收口
**这是本 Phase 最需要小心的部分**:`npm ci` 要求 `package.json` 与 `package-lock.json` 严格一致,任何增删都会让它失败。
### 3.1 删依赖
`package.json` 的 `dependencies` / `devDependencies` 删:
```
electron
electron-builder
@electron/*
electron-store
electron-updater (若 devDeps 里有)
```
先跑一次定位:
```bash
grep -n "electron" package.json
```
### 3.2 重生成 lockfile
```bash
# 删旧 lock,用当前 package.json 重装,版本不主动升级
rm -f package-lock.json
npm install --package-lock-only --ignore-scripts
```
`--package-lock-only` 只更新 lock 不装包,**不会升级已存在的版本**(依赖树解析会沿用现有版本范围)。
```bash
npm ci --ignore-scripts
npm run build
```
### 3.3 校验版本没被偷偷升级
```bash
# 对比新旧 lock 里几个关键包的版本
git diff package-lock.json | grep -E "^\+.*\"(vue|koa|socket.io|better-sqlite3|vite|pinia)\""
# 期望:无新增版本行
```
---
## 4. 功能任务 4 — Dockerfile / CI 同步
| 文件 | 改动 |
|---|---|
| `Dockerfile` | 删 electron 相关 build 步骤与产物拷贝 |
| `docker-compose.yml` | 删 electron 挂载 |
| `.github/workflows/build.yml` | 确认无 desktop 步骤 |
| `.github/workflows/webui-release.yml` | Phase 002 已去品牌,确认打包产物名已改 |
### 4.1 `fetch-depth: 0` 必须保留
`harness-check.mjs` 靠 `git diff` 判断链路变更。CI 里 `actions/checkout` 缺 `fetch-depth: 0` 会让检测失效。
---
## 5. 验收
### 5.1 命令
```bash
cd /Users/jack/source/MyProject/js/hermes-ui
grep -rn "desktop\|electron\|Electron" packages/ --include="*.ts" --include="*.vue" \
| grep -v "bridge_runtime.py"
# 期望:零命中(python 的 HERMES_DESKTOP 判断例外,见 §6)
grep -n "electron" package.json
# 期望:零命中
npm ci --ignore-scripts
npm run build
npm run test
npm run test:e2e
```
### 5.2 手工
- [ ] `npm run dev` 正常启动
- [ ] 启动后 gateway 自动拉起(看日志)
- [ ] 聊天正常
- [ ] 故意把 `HERMES_BIN` 指向不存在的路径 → 出现引导页而非白屏报错
- [ ] Docker 构建成功且容器内聊天正常
---
## 6. 红线:这两处 `HERMES_DESKTOP` **保留不动**
`packages/server/src/services/hermes/agent-bridge/python/bridge_runtime.py` L74 / L119:
这是 Windows 下隐藏子进程控制台窗口的逻辑。删掉会导致 Windows 用户运行 git / 命令时**弹黑窗**。
虽然新项目是 Web 端、不再有 Electron 壳,但 Windows 用户从命令行起 Node 依然会弹。
**判断依据**:这两个 env 在新项目里永远为 `undefined`,条件分支永不进入 → 逻辑上等价于删除,但**保留代码不影响正确性**,删除则影响。留。
---
## 7. 风险
| # | 风险 | 缓解 |
|---|---|---|
| P4-1 | 删 `bindShutdown` 时误伤正常关停 | 只删桌面分支,主流程保留;手工 Ctrl+C 验证一次 |
| P4-2 | lockfile 重生成时依赖被升级 | `git diff package-lock.json` 逐项确认,锁版本 |
| P4-3 | Windows 用户失去捆绑 Python | 引导页 + README 显著位置写安装步骤。这是既定决策 |
| P4-4 | e2e 有 desktop 用例残留 | `test:e2e` 必跑 |
| P4-5 | `WebPet.vue` 被多处引用 | 删前先 `grep -rn "WebPet"` |
| P4-6 | `DefaultCredentialPrompt` 在 auth.ts 有对应字段 | 两边一起改 |
---
## 8. 完成标志
**项目此时功能完整、界面还是旧的 Naive UI。** 进入 Phase 005。
从此开始才允许改样式代码。