首页
/ LobeHub 仓库 AI 编码代理开发指南:架构约定、工程流程与质量门禁全解析

LobeHub 仓库 AI 编码代理开发指南:架构约定、工程流程与质量门禁全解析

2026-09-06 19:01:13作者:贡沫苏Truman

LobeHub 是一个以「首席 Agent 操作员」为核心定位的开源 AI 产品套件(聊天、Agent、工具一体的 7×24 运营平台)。本仓库同时将 AI 编码代理视为一等公民:项目根目录的 AGENTS.md(由 CLAUDE.md 通过 @AGENTS.md 指令直接引用)为 Claude Code 等 AI 编码代理编写了一整套开发守则,覆盖技术栈、目录职责边界、SPA 路由架构、Git 工作流与质量检查协议。本文围绕这份开发守则展开,逐条解释其背后的仓库结构与源码佐证,帮助开发者和 AI 编码代理快速理解 LobeHub 的工程约定并上手开发。

技术栈全景:一次读懂仓库选型

AGENTS.md 开篇即锁定了该仓库的核心技术栈,任何新增代码都应当在这一选型框架内决策:

  • 前端框架:Next.js 16 + React 19 + TypeScript,其中主业务界面以 Next.js 内嵌的 SPA 形态存在,由 react-router-dom(React Router 8)驱动,而非依赖 Next.js App Router 的页面路由来承载全部交互逻辑;
  • UI 体系@lobehub/ui(lobe-ui)、antd 与 antd-style 组合使用,antd 6.x 作为底层组件生态,而组件消费优先走 lobe-ui 语义层;
  • 国际化与状态react-i18next 负责多语言,zustand 5.x 管理客户端状态;
  • 数据层:SWR 负责服务端状态获取与缓存,TRPC 提供端到端类型安全的后端调用;
  • 存储与测试:Drizzle ORM + PostgreSQL(服务端)、Vitest 负责单元与集成测试。

上述版本信息可在仓库 package.json 中核实(Next 16、React 19.2.7、zustand 5.0.4、antd 6.3.5、drizzle-orm 0.45.x 等),工作区由 pnpm(pnpm@10.33.0)管理,包名统一为 @lobechat/*@lobehub/* 前缀。

Agent Skills:把实现规则沉淀为"单一事实来源"

该仓库与一般项目最大的不同在于,它把架构与工作流规则显式地"教"给 AI 编码代理:

AGENTS.md 拥有仓库级的架构与工作流定义。详细的实现规则下沉到 skills 中,让规则保持单一事实来源(one source of truth)。

skills 位于 .agents/skills/ 目录,每个 skill 以 SKILL.md 为入口,并带有 YAML frontmatter 声明其适用场景。开发守则明确要求编码代理在触碰两类改动前必须阅读对应 skill:

改动场景 必读 Skill 内容要点
编辑组件、组件状态、渲染边界、memo 优化 .agents/skills/react/SKILL.md 组件选型、样式方式、状态局部性、渲染性能规则
将过重的 Viewer/Page 拆分可复用片段 .agents/skills/compose-atoms/SKILL.md 按"可挂载能力"而非视觉区块拆分,禁止用 readOnly/mode 标志隐藏未用功能

react skill 的核心约定

react SKILL.md 是日常编写 TSX 的准则,核心要点包括:

  1. 组件优先级src/components(项目专属)> @lobehub/ui/base-ui(无头原语)> @lobehub/ui 根导出 > antd > 自定义实现。尤其注意 SelectModalDropdownMenu 等应优先从 base-ui 导入,而非 @lobehub/ui 根导出——后者是 antd 包装版;
  2. 样式方式:多数场景用 createStaticStyles + cssVar.*(零运行时、模块级);一次性简单样式用内联 style;真正需要 JS 动态计算颜色时才退化到 createStyles + token
  3. 渲染性能memo/useMemo/useCallback 是"可选优化"而非默认包装,先识别真实的重渲染边界,优先结构性修复——拆分更新边界、状态下沉到最小持有者、使用窄 Zustand selector。

compose-atoms skill 的拆分哲学

compose-atoms SKILL.md 面向重领域页面的模块图级拆分,其核心论断是"这是一个模块图拆分:隐藏 UI 并不会卸载模块,只有宿主(host)永不 import 一个文件,它才不会被发布"。判断拆分的粒度问题只有一个:

对每个 chunk 自问:是否存在某个宿主会保留其余部分而跳过这一块?如果是,它就是原子(atom)。

同时强调状态必须随原子下沉——useStore/useX/handleAccept 若残留在组装页上,就会让该模块及其全部依赖被每个宿主打包。

项目目录结构:app / packages / src 三大体系

AGENTS.md 用一棵目录树给出了全仓库的宏观地图,可归纳为三条主线:

  • apps/(可独立运行的应用)
    • apps/desktop/ — Electron 桌面应用;
    • apps/cli/ — LobeHub 命令行工具;
    • apps/server/ — 后端服务(Hono app + 服务端路由/服务)。
  • packages/@lobechat/* 共享包)
    • packages/database/ — 数据库 schema、模型、仓储层;
    • packages/agent-runtime/ — Agent 运行时;
    • packages/locales/ — i18n 源,位于 packages/locales/src/default/
    • packages/env/ — 环境变量 schema(@/envs/* 实际映射到 packages/env/src/*)。
  • src/(前端应用壳)
    • src/app/ — Next.js App Router 路由壳与认证;
    • src/routes/ — SPA 页面段(保持精简,只委托给 features);
    • src/spa/ — SPA 入口与路由配置;
    • src/store/(Zustand stores)、src/services/(客户端服务)、src/libs/(应用壳共享 helper);
  • e2e/ — Cucumber + Playwright 端到端测试。

后端业务代码位于 apps/server/src,通过 @/server/* 导入;而 src/app/(backend) 只保留 Next.js 路由壳,禁止在其中添加后端业务逻辑——这是守则中反复强调的边界纪律。

SPA 路由架构:roots 与 features 的职责分离

守则中架构含量最高的是 SPA 路由的 roots vs features 拆分,其根本原则是:

路由树只承载页面段;业务逻辑与 UI 一律放在 features 中。

  • src/spa/ 保存 SPA 入口(entry.web.tsxentry.mobile.tsxentry.desktop.tsxentry.popup.tsx)与 React Router 配置(router/ 目录),路由配置紧邻入口存放以避免与 src/routes/ 混淆。上述文件可从 src/spa/ 目录核实;
  • src/routes/(roots) 只允许三类页面段文件:_layout/index.tsxindex.tsx(或 page.tsx)、动态段如 [id]/index.tsx。它们必须保持:仅从 @/features/* 导入并组合布局与页面,不含业务逻辑与重型 UI;
  • src/features/ 按领域存放业务组件(如 PagesPageEditorHome),侧边栏/头部/正文等布局块、hooks 与领域 UI 都在此,每个 feature 通过 index.ts(或 index.tsx)暴露清晰导出。

新增或修改 SPA 路由的四步规程

  1. src/routes/ 中只新增委托给 features 的路由段文件(layout + page);
  2. src/features/<Domain>/ 下实现布局与页面内容并导出;
  3. 路由文件中使用 import { X } from '@/features/<Domain>' 形式导入,禁止src/routes/ 内部新建 features/ 文件夹;
  4. 共享桌面内容路由只注册一次:将 Web/Electron 共有的路径、嵌套结构、metadata、懒加载与 preloadId 集中到 src/spa/router/desktopRouter.shared.tsx。两个平台适配器 desktopRouter.config.tsxdesktopRouter.config.desktop.tsx 只保留运行时差异:Web 直接挂载内容树,而 Electron 通过 src/spa/router/tabRouter.tsx 在每标签页的内存 router 中挂载同一棵树、其自身仅保留精简根桩。只有当路由真正平台专属时才向平台适配器添加代码。

该同步行为的正确性由测试守护:src/spa/router/desktopRouter.sync.test.tsx(完整路由文件见 desktopRouter.shared.tsxtabRouter.tsx),守则要求保持该测试通过。路由骨架与懒加载还有专门的 routePreloadRegistry.tsrouteSkeletonChrome.tsx 等模块配套。

开发环境启动与"调试代理"机制

AGENTS.md 提供了三种开发模式:

# SPA 开发模式(仅前端,将 API 代理到 localhost:3010)
bun run dev:spa

# 全栈开发(Next.js + Vite SPA 并发)
bun run dev

# 独立 Hono 后端服务
pnpm --filter @lobechat/server dev

后端命令直接验证了守则所述的后端架构:运行时代码在 apps/server/src 中,通过 pnpm workspace filter 指定 @lobechat/server 包启动,无需 cd 进入目录。

启动 dev:spa 后,终端会打印一个 Debug Proxy URL:

Debug Proxy: https://app.lobehub.com/_dangerous_local_dev_proxy?debug-host=http%3A%2F%2Flocalhost%3A9876

打开该 URL 即可基于生产后端(app.lobehub.com)进行本地开发:代理页会把本地 Vite dev server 的 SPA 载入线上环境,从而在真实服务端配置下获得 HMR 能力。仓库根目录的 _dangerous_local_dev_proxy.html 正是这一机制的前端载体。

Git 工作流与包管理约定

守则对协作流程有明确约定:

  • 分支策略canary 是开发分支(云上生产分支),main 是发布分支(周期性从 canary cherry-pick);
  • 新分支应从 canary 创建,PR 应指向 canary
  • git pull 使用 rebase;
  • 提交信息须带 gitmoji 前缀;
  • 分支命名格式:<type>/<feature-name>

包管理上形成"双工具"分工:

  • pnpm 负责依赖管理;
  • bun 运行 npm scripts;
  • bunx 执行可执行 npm 包。

质量检查协议:check 命令与测试纪律

统一检查入口

守则强烈推荐使用统一的质量检查命令而非分散执行:

bun run check [changed-files...]

该命令由脚本 .agents/scripts/check/cli.ts 实现,内部通过 --lint / --test / --type 三个可组合开关控制范围:

  • 不指定开关 = lint + test 单次跑完,不要按选择器拆分多次;
  • --lint 自动修复给定文件并 diff 输出应用后的修复,方便审查改动;
  • --test 为给定源文件自动发现关联测试,并在最近的归属 vitest 配置(如 packages/database)下运行,无需 cd 进入包目录
  • --type 执行全量类型检查。

默认文件集合 = 工作树中全部变更(已暂存 + 未暂存 + 未跟踪);传入显式路径则覆盖默认集合。

测试纪律

  • 每个 bug 修复必须附带对应的回归测试,且该测试在修复前失败、修复后通过;纯样式/CSS 类修复(选择器、hover、mask、间距、颜色)除外——若唯一可行的断言是对样式表的源码字符串匹配,那不值得作为回归测试提交;
  • 明确警告:绝不运行 bun run test,全量测试套件约需 10 分钟;
  • 手动运行测试(单文件或特殊 flag)需先进入归属包:cd packages/database && bunx vitest run --silent='passed-only' '[file-path]'

国际化(i18n)工作流

仓库的 i18n 源位于 packages/locales/src/default/(如 agent.tsauth.ts 等 namespace 文件),CI 每日自动化翻译其余语言。守则规定的人工流程如下:

  1. packages/locales/src/default/ 下的 namespace 文件新增 key;
  2. 同一 PR 内手工提交 en-US 与 zh-CN:英文源写在 packages/locales/src/default/*.ts,同步镜像到 locales/en-US/,并人工翻译 locales/zh-CN/
  3. 其余语言交给每日 CI workflow(.github/workflows/auto-i18n.yml)执行 bun run i18n 并开启自动翻译 PR;在 PR 合并前,缺失的 locale key 自动回退到英文;
  4. bun run i18n 需要 OPENAI_API_KEY 且运行缓慢,仅当需要立即拿到翻译结果时才手动执行,生成产物不要人工再翻。

仓库根目录下 locales/ 中包含 20 余个语言目录、每个目录 54 个 JSON namespace,正是这一流水线的产物形态。

代码风格与 Review 机制

  • 文件规模:单文件超过约 800 行时考虑拆分(抽取子组件、hooks、helpers 或类型),小而聚焦的文件对人类与代理都更友好;
  • 代码审查:审查 PR/diff/分支改动前须先读 .agents/skills/deep-review/SKILL.md。普通 review 请求使用其 light 模式(一位独立 reviewer 对照各维度快速清单);完整的多子代理 deep 模式只在显式调用时运行。deep-review 遵循的核心原则包括反幻觉(候选发现由独立 verify 子代理逐一证伪)、反自我背书(写代码的代理不给自己评分)、规则优先于模型、校准到代码库既有水准、速度是特性;
  • 设计价值观:在设计或评审用户流(空/加载/错误状态、确认、异步反馈、按钮层级、列表规模、选择器等)时,遵循 DESIGN.md 中的四项价值观——自然 / 意义感 / 确定性 / 成长

从守则到设计系统:DESIGN.md 的关键约定

守则要求面向用户的功能设计对齐 DESIGN.md(暗色主题见 DESIGN.dark.md)。虽然设计系统文档独立于本开发守则,但其若干硬性约定与编码直接相关:

  • 语义化 token 优先:主色与中性色可被用户配置,组件必须消费语义 token(如 cssVar.colorTextcssVar.colorBgContainer),禁止硬编码十六进制值;默认主色为单色系(#222222),用户选取主色后才赋予色相;
  • 字体与字号Geist 负责正文、Geist Mono 负责代码;正文/标签字号刻度为 12/14/16,无 13px token,不得引入刻度外字号;
  • 4px 间距系统XXS 4、XS 8、SM 12、base 16、MD 20、LG 24、XL 32;组内 8px、组间 16px、区块间 24–32px;圆角是独立刻度(含 6px 的 borderRadiusSM),不得复用圆角值作间距;
  • 组件优先级与 React skill 一致:@lobehub/ui/base-ui 优先(SelectcreateModalDropdownMenuPopoverScrollAreaSwitchToast 等),其次 @lobehub/ui 根导出;
  • 文案与声音:术语保持一致(Workspace、Agent、Profile、Group、Context、Memory、Skill、Topic 等为规范术语),动作按钮用"动词 + 名词"(如 Create Agent)而非裸的 Confirm/OK,避免 hype 词汇,敏感消息遵循"承认现状 → 恢复控制 → 给出下一步"的三段式。

给 AI 编码代理与贡献者的一句话总结

AGENTS.md 的守则出发,进入 LobeHub 仓库工作的心智模型可以压缩为三条主线:

  1. 边界先于实现:路由文件瘦身、后端逻辑不进 src/app/(backend)、路由不通用的能力不进平台适配器——所有约定都以"保持模块可被按需挂载、可被按需发布"为目标;
  2. 规则先于探索:写 TSX 先读 react skill,拆分重页面先读 compose-atoms skill,路由变更以 desktopRouter.sync.test.tsx 等测试为护栏,审查改动先读 deep-review skill;
  3. 质量是单命令协议:一切变更收敛到 bun run check--lint/--test/--type 组合,回归测试随 bug fix 成对出现,全量 bun run test 是被明确禁止的耗时操作。

理解并遵守这份守则,是个人开发者与 AI 编码代理在这棵庞大且高度工程化的代码库中保持高效、安全协作的前提。

登录后查看全文
热门项目推荐
相关项目推荐