Files
hermes-desktop/docs/01-技术选型推荐.md
toor 01d9e301fc
Build / build (push) Canceled after 0s
Playwright / browser (push) Canceled after 0s
initialize Electron desktop app and remove unused files
2026-10-25 01:09:01 +08:00

14 KiB
Raw Permalink Blame History

复刻项目技术选型推荐(0.6.29 基线)

前置结论:我们的目标不是从零重写,而是以当前 0.6.29 代码为底子魔改。 因此选型分两个维度:

  1. 沿用 —— 原项目已经验证过、且替换成本高的部分,直接用;
  2. 重做/新增 —— 原项目写得烂、或我们不需要的部分,才考虑换。

对接 Hermes 的方案单独在第 4 节说明(这是核心,也是你让我把关的部分)。


1. 分层总览

层 推荐方案 决策 理由
前端框架 Vue 3 + <script setup> TS 沿用 原项目 27 个视图全是 Vue 3,换框架 = 全部重写,没有收益
构建工具 Vite 8 沿用 快、零配置争议,原项目已调好(含代理、多配置文件)
前端状态 Pinia 沿用 Vue 官方标配,13 个 store 结构清晰
UI 组件库 换库(已确认) ❌ 弃用 Naive UI 见第 2 节,具体库待拍板
路由 Vue Router(hash 模式) 沿用 hash 路由对桌面端 / file:// 场景友好
后端运行时 Node.js ≥ 23 + TypeScript 沿用 与前端同语言,agent-bridge 的 Node 客户端、Socket.IO 编排全在 TS 里
Web 框架 Koa 2 沿用 见第 3 节;换 Fastify 收益低、迁移 46 个路由文件成本高
实时通信 Socket.IO 必须沿用 /chat-run 命名空间是聊天核心协议,见第 4 节
数据库 SQLite(better-sqlite3) 沿用 local-first 单机场景,零运维;原项目有完整 schema 与迁移
桌面端 Electron ❌ 已确认砍掉 砍 packages/desktop 整包,见第 2.1 节影响面
测试 Vitest + Playwright 沿用 原项目已有大量测试基建可复用
Python 桥 CPython 子进程 + JSON over socket 必须沿用 Hermes 对接的唯一正道,见第 4 节

2. 已确认的结构性决策

2.1 砍掉桌面端(已确认)

  • 删除 packages/desktop 整包,以及根 workspace 引用、desktop 相关 scripts、CI 打包 workflow;
  • 连带死亡的代码(无需保留):系统托盘、自动更新、开机自启、捆绑运行时打包脚本、自定义标题栏、桌面通知、登录态注入、/desktop-pet 独立桌宠窗口(透明置顶窗口是 Electron 专用);
  • 连带必须处理的依赖缺口:
    • Hermes CLI 不再捆绑:运行环境改为「用户自装 Python + hermes-agent」,通过 HERMES_BIN 环境变量或启动参数指定 hermes 可执行文件路径;缺失时 UI 给出引导提示(原 hermes-path 逻辑保留,去掉 bundled 路径推断);
    • Node 运行方式:从 Electron 内嵌服务改为纯 node / npm start 启动(可选再加个 pkg/bun 单文件打包,不引入新框架);
    • 桌宠系统随 P 组砍除(/desktop-pet 路由、Petdex、pet-state socket 一并删除)。
  • Docker 部署路径不受影响(本就有 server 镜像)。

2.2 IM 频道保留(已确认)

  • K 组 10 平台频道配置 + gateway 守护进程管理(autostart/锁文件/per-profile)全部沿用;
  • 注意:gateway 自启原逻辑有一半长在 Electron 生命周期里,需迁到 Koa 启动钩子。

2.3 i18n 只保留中英双语(已确认)

  • locale 目录只留 zh 与 en,删除其余 8 个语种文件与语言切换项;
  • 硬规则(继承原项目):新增/改动的用户可见字符串必须同时写入 zh 与 en 两个 locale 文件,施工蓝图里会加检查项。

2.4 品牌去标识(已确认)

新版本中不得出现 ekko 与 hermes-web-ui 字样:

  • package.json name:hermes-web-ui → 新包名(待定,见文末);
  • 窗口标题、侧边栏 Logo/产品名、登录页、更新弹窗、Docker 镜像名、GitHub workflow 名、README/文档统一替换;
  • 代码内标识符:EkkoAgent 类/包名、ekko-agent 目录、路径常量、i18n key(如 ekko.*)→ J 组已确认整组砍除,ekko 字样随之全部消失;
  • Hermes 字样不在禁用列表:它指被对接的 Agent 本体(hermes CLI、HERMES_HOME 等),技术上无法回避,全部保留。

2b. UI 组件库:换库(已确认,具体库待拍板)

原 Naive UI 弃用。换库的真实成本不在装包,在于 27 个视图全部要动——Naive 的 NXxx 组件、NConfigProvider 主题体系会渗透进每个页面。因此策略是:

  1. 一次性换库 + 逐视图迁移,不搞双库共存(双库样式割裂,比换库本身更丑);
  2. 迁移顺序:先换 3 个样板页(登录、设置、历史)定风格基线 → 再核心聊天页 → 其余页面批量;
  3. 原项目的样式定制层(主题变量、明暗切换、themeOverrides 思路)用新库的等价主题体系重建,这是"改掉官方丑风格"的主战场;
  4. 聊天页的自绘部分(虚拟滚动消息列表、markdown 渲染、代码高亮、轨迹时间线)本来就没用组件库,换库对它们零影响——这是我们的运气。

候选库对比见文末问题,待你拍板后写入施工蓝图。

3. 后端:Koa 沿用,不要上 NestJS

  • 原项目结构已经是分层的:routes → controllers → services → db,规则写在 ARCHITECTURE.md 里,问题只在个别文件膨胀,不在框架。
  • 换 Fastify/NestJS 的收益(性能、DI、装饰器)在单机自托管工具场景里几乎为零;成本是 46 个路由文件 + 全部中间件重写。
  • 真正值得在魔改中做的后端改进(属于"顺手修",不属于换框架):
    • 路由保持薄,新逻辑进 services;
    • 继续用 execFile + 参数数组调 hermes CLI(禁止 shell 拼字符串,原项目硬规则);
    • Socket.IO 事件命名保持 /chat-run 协议不变,避免前端联动改动。

4. Hermes 对接方案(核心,把关结论)

原项目有三条通道,复刻时的取舍如下:

4.1 Agent Bridge(Python 子进程 + Socket)— ✅ 必须完整保留

浏览器 ──Socket.IO──> Koa/Node server ──JSON over Unix socket──> Python 子进程
                                                                 └─ hermes-agent 的 run_agent.AIAgent

为什么这是唯一正确的主通道:

  1. 零拷贝接入 Hermes 全部能力:模型配置、工具、技能、审批、会话 DB、上下文压缩,全部由 AIAgent 在 Python 侧自己解析 hermes 的 config.yaml,Node 侧只传 session_id + message。任何绕开它的方案(比如自己在 Node 里重新实现一遍工具调用/会话管理)都是在重写 hermes-agent,不可行。
  2. 进程内实例化 = 快且可流式:不用每次聊天冷启动 CLI,delta 流式回传,支持中断(interrupt)、审批(approval)、澄清(clarify)、断线重挂(reattach)。
  3. 原项目已替我们踩完了坑:桥池(profile worker 池)、IPC/TCP 双传输、Windows 兼容、错误脱敏(redact)、就绪探测与自动恢复,这些都在 agent-bridge/ 下有实现和测试。

魔改时的把关红线:

  • ❌ 不要改成"每条消息 fork 一个 hermes chat CLI 进程"——冷启动慢、无法流式、无法审批交互;
  • ❌ 不要试图用 hermes 的 HTTP gateway 替代桥做聊天——gateway 面向 IM 频道(telegram 等),聊天语义(队列/审批/压缩事件)对不上;
  • ✅ 只允许在桥的 JSON 协议上加字段(例如 reasoning effort 覆盖,原项目就是这么做的 local patch);
  • ✅ agent-bridge/python/ 整个目录视为只读 vendored 代码,除非你确实看懂了 bridge_pool.py 的会话池逻辑再动。

4.2 Hermes CLI(execFile)— ✅ 保留,用于管理面

sessions export/delete/rename、profile CRUD、logs、gateway start/stop、curator pin、setup --reset。这些是低频管理操作,走 CLI 子进程最合适(hermes 自己保证了这些命令的稳定性)。 把关点:所有调用必须走 hermes-process.ts 的 execHermesWithBin(参数数组 + HERMES_BIN 解析),禁止散落的 exec('hermes ...')。

4.3 Gateway 守护进程管理 — ⚠️ 按需保留

只有当你需要 telegram/discord 等 IM 频道接入时才需要管 gateway 生命周期(锁文件、pid、per-profile 启停)。如果你只要 Web 界面,这块可以整块砍掉——聊天不依赖它。

4.4 数据归属原则 — ✅ 必须继承

  • Hermes state.db = 只读,只用于历史 API;
  • Web UI 自己的 SQLite = 会话/消息/用量的唯一可写存储;
  • 两边不搞启动时导入同步(原项目明确禁用并写了注释,理由成立)。
  • Profile 隔离靠给子进程注入 HERMES_HOME,不要改。

5. 明确不推荐的选项

方案 为什么不要
Node 直连 hermes 的 Python 内部(pybind/嵌入) hermes 依赖 Python 生态,嵌入即噩梦;子进程隔离才能独立重启/崩溃恢复
把桥改成 gRPC/protobuf JSON over socket 够用,换协议 = Node/Python 两端重写,零收益
PostgreSQL 替代 SQLite 单机自托管,多一个运维依赖,违背 local-first
Next.js / SSR 前端 纯客户端仪表盘 + Socket.IO,SSR 无意义
微服务拆分 单人魔改项目,拆分只会增加部署成本

6. 依赖版本策略

  • 锁定当前 package-lock.json,npm ci --ignore-scripts 安装,不升级任何依赖(你特意要旧版底座);
  • 新增依赖遵循:能不加就不加,必须加时选与现有栈同生态的(Vue 系 / Node 内置优先);
  • Node 版本要求 >=23(package.json engines),与原项目一致。

7. 决策记录与遗留问题

已拍板

决策点 结论
桌面端 Electron ❌ 砍掉(含托盘/自动更新/捆绑运行时/桌宠窗口)
IM 频道 + gateway 管理 ✅ 保留
I 编程代理(Claude Code / Codex 代理 + stream-tee 网关) ❌ 砍掉(各有官方 UI,run-chat 只留 hermes 桥)
J ekko-agent(内置自有 Agent) ❌ 砍掉(品牌 ekko 冲突随之解决)
P 桌宠系统 ❌ 砍掉(浪费资源)
其余功能组(BH、KO、Q) ✅ 全部沿用
UI 组件库 ❌ 弃用 Naive UI,换库(库种待定)
ArkScope ✅ 确认采用:vendor 源码,作颜值特效层(个人用、不分发、私人仓库)
i18n 仅中文 + 英文
品牌 禁用 ekko、hermes-web-ui 字样;Hermes 保留
依赖 锁定 lockfile 不升级

遗留待定(下一步聊完定)

  1. 新包名/产品名(不能叫 ekko 或 hermes-web-ui);
  2. 基础组件库选哪个(ArkScope 的评估见第 8 节:它不能当基础库,需要另配一个)。

8. ArkScope 可行性评估(针对 github.com/triplepiers/ArkScope)

结论:不能作为本项目的基础组件库;可以作为「风格特效层」并入,且必须搭配一个真正的基础组件库。

8.1 它是什么

鹰角(明日方舟/终末地)游戏官网风格的装饰性 Vue 3 组件集,全部组件清单:

组件 作用
EndfieldSidebar 终末地风格导航栏(悬停展开、移动端适配)
ScrambleTitle 塞壬唱片风文字解码标题动画
IsometricWave 类亚克力质感 Hover 交互
GameplayAlbum / NoticeCarousel / OperatorCarousel / ArknightsOperatorCarousel 四种风格轮播图
FullScreenNavigator 全屏滚动 Section 切换
Particle2D / Particle3D 2D/3D 粒子点云(3D 依赖 three.js)
NewsList / OperatorList 公告/列表排版组件

8.2 为什么不能当基础库

  1. 没有基础 UI 控件:按钮、输入框、下拉、弹窗、表格、表单、Tabs、Toast、日期选择——一个都没有。而我们 27 个视图里到处是这类控件,Naive UI 换掉后必须有东西接住;
  2. 不是可安装的库:package.json 里 private: true、version 0.0.0、构建脚本是应用构建而非 library build,未发布到 npm —— 只能 vendor(把 src/components 源码拷进来维护),拿不到版本升级支持;
  3. 面向展示型官网,不是管理后台:组件全是官网 landing 页的视觉件,与"仪表盘/表单/数据表"场景错配;
  4. 素材版权:仓库明确声明第三方素材(© 鹰角网络)不在开源许可内 —— 个人魔改无所谓,但要知道这些素材不能用于公开分发;
  5. 依赖 three.js(仅 Particle3D 用),引入时注意按需,别让聊天页背这个包。

8.3 定位与用法(✅ 已确认,2026-10-15)

双层策略:基础组件库(管功能)+ ArkScope(管颜值)。已确认采纳。

使用前提已明确:纯个人使用、不分发、只进私人仓库 —— 鹰角素材版权与 private: true 不可安装的问题都不构成障碍(vendor 源码进仓库即可)。

  • 基础组件库(待拍板,候选见 8.4):承担全部表单/表格/弹窗/导航等交互控件,全量替换 Naive UI;
  • ArkScope:vendor 源码进仓库,只用于装饰性位面——
    • 登录页 / 首页的品牌标题(ScrambleTitle);
    • 侧边栏若做风格化改造可参考 EndfieldSidebar(但我们的侧边栏信息密度高,直接套大概率要重写);
    • Petdex / Journey 图谱页的展示性视觉(Particle2D、轮播)——Petdex 已随 P 组砍除,实际只剩 Journey 图谱页可用;
    • 桌宠相关的展示动效(P 组已砍,不适用)。
  • 明确不用的场景:聊天页、管理表单页、数据表格页——这些地方特效组件只会碍事;
  • 接入方式:源码 vendor 至 packages/client/src/components/arkscope/,不加 npm 依赖(它也装不了)。

8.4 基础组件库候选(仍待拍板)

候选 优点 缺点
Element Plus 生态最大、控件最全、中文文档、长得普通(但可深度定制主题) 观感"公司后台",需要我们自己下功夫做主题
Arco Design Vue 字节系、设计感较好、控件全、支持主题定制 生态比 EP 略小
PrimeVue 主题系统强(Aura/Material 等多套)、tailwind 友好 中文资料少
shadcn-vue + Tailwind 完全可控、改样式零阻力、最能实现"自己的风格" 无现成组件包,27 个视图的控件要逐个搬,成本最高

与 ArkScope 风格最搭的是 Element Plus / Arco(底子干净,套鹰角风主题变量即可);shadcn-vue 路线自由度最高但工时最长。