Skip to content

仓库结构与模块化约定

本文约定本 monorepo 的目录职责、包命名与 package.json 写法。新增或调整包时,请优先遵守「第 3 节 源码与构建产物」中的双轨约定。

1. 工作区(pnpm workspace 单仓库)

本仓库采用 pnpm workspace 管理多个包目录;不再使用 git submodule。克隆后执行 pnpm install 即可。

若你仍在使用带子模块元数据(.gitmodules + gitlink)的旧克隆,请按 monorepo-no-submodules.md 运行一次性导入脚本,将各路径改为普通目录。

克隆

bash
git clone https://github.com/zhinjs/zhin.git
cd zhin
pnpm install

目录与历史来源(参考)

以下路径为 monorepo 内普通目录;历史上曾对应 github.com/zhinjs/<repo> 独立仓库,便于对照 issue/PR 或 cherry-pick:

路径曾用远程(参考)
basic/clizhinjs/cli
basic/databasezhinjs/database
basic/loggerzhinjs/logger
basic/schemazhinjs/schema
packages/im/kernelzhinjs/kernel
packages/im/aizhinjs/ai
packages/im/agentzhinjs/agent
packages/console/clientzhinjs/client
packages/toolkit/create-zhinzhinjs/create-zhin
packages/toolkit/scaffold-wizard(monorepo 内新建)
packages/toolkit/satorizhinjs/satori
pluginszhinjs/plugins
docszhinjs/docs

主仓库内常驻包packages/im/*packages/console/*packages/toolkit/*packages/host/*examples/*

pnpm workspace

根目录 pnpm-workspace.yaml 已声明:

  • basic/* — 基础能力(CLI、数据库、日志、schema 等)
  • packages/im/* — IM 主链:kernelaicoreagentzhin
    • ai:通用 AI 引擎(agent/memory/compaction/
    • agent:IM Agent 编排(orchestrator/discovery/security/mcp-client/defaults/
  • packages/console/* — 控制台:contractpagemanagerclient(npm 名均为单词包名)
  • packages/toolkit/* — 脚手架与独立工具库:create-zhinscaffold-wizardsatori
  • packages/host/* — Host 运行时:host-routerhost-apimcp
  • plugins/adapters/* — 平台适配器
  • plugins/services/*可选服务类插件(内置 Host 栈见 packages/host/
  • plugins/features/* — 特性类插件
  • plugins/utils/* — 工具类插件
  • plugins/games/* — 游戏类插件(可为空,仅保留说明时请放 README.md
  • examples/*docs

规则: 凡应被 pnpm install / workspace:* 解析的包,必须在对应 glob 下提供独立的 package.json。不要提交「仅有空目录、无 package.json」的占位文件夹,以免误导协作者。

2. 包命名(npm name

类型约定示例
主入口zhin.js
核心/共享库@zhin.js/<短名>@zhin.js/core@zhin.js/kernel
适配器@zhin.js/adapter-<平台>@zhin.js/adapter-icqq
工具插件@zhin.js/plugin-<名称>@zhin.js/plugin-rss
服务@zhin.js/<服务名>@zhin.js/host-api@zhin.js/host-router

目录名(文件夹)优先 kebab-case;与平台强相关的缩写(如 icqqqq)可保持小写短名。

3. 源码与构建产物(核心约定)

本仓库对每个包采用统一语义(与运行环境对应):

运行环境源码目录构建输出目录package.json 入口习惯
Node.js 服务端src/lib/main / types / import./lib/index.js
浏览器客户端client/dist/按实际导出配置(如仅静态资源可无 main,库包可指向 ./dist/index.js

原则:

  1. 不要混放:服务端逻辑只在 src/;仅在浏览器执行的 UI、路由、DOM API 等在 client/
  2. lib/dist/ 并列:同一包内可同时存在 lib/(Node)与 dist/(前端产物),二者职责不同。
  3. 工具链:Node 侧常用 tsc / tsuplib/;客户端常用 Vite / Rolldown → dist/(具体脚本以各包 package.json 为准)。
  4. 发布范围files 字段应包含实际发布的 lib 和/或 dist(以及 client 源码若需随包提供扩展入口,见下)。

3.1 仅 Node 的包(无浏览器部分)

<包根>/
  package.json
  tsconfig.json  # 通常 outDir: lib, rootDir: src
  src/
  lib/           # 构建输出,gitignore
  tests/

典型:packages/im/core@zhin.js/adapter-* 服务端部分、basic/database 等。

3.2 带浏览器扩展的适配器 / 插件

  • Node 适配逻辑src/lib/
  • 控制台扩展 UI:源码在包根 client/(如 client/index.tsx),由 zhin build(CLI esbuild)打包;产物落在该包根目录下的 dist/

package.jsonfiles 中通常需包含 client(源码供开发/扩展加载)及构建生成的 dist(若对外分发预构建产物)。

3.3 控制台架构(对齐 page-manager)

控制台采用三层分包,与 page-manager 架构对齐:

源码 → 产物职责
@zhin.js/contractsrc/ → tsc → lib/Console / PageManager 契约PluginRegisterHostApiConsoleEntry、常量)
@zhin.js/pagemanagersrc/node/ → tsc → lib/PageManager、EntryStore、esbuild 管线(Host 运行时)
@zhin.js/clientclient/ → tsc → dist/Remote Console SDK:app、REST/SSE、loadConsoleEntries
@zhin.js/host-routersrc/ → tsc → lib/Host 传输:Koa、Router、Bearer、CORS
@zhin.js/host-apisrc/ → tsup → lib/Host 管理面:REST + Console 协议(api_only
zhin-console(独立仓库)Farm / 未来 Vite全部 Console UI;依赖 npm 上的 @zhin.js/client

插件注册契约

  • 服务端:useContext('web', pageManager => pageManager.addEntry({ id, development, production }))
  • 浏览器:export function register(api: PluginRegisterHostApi),使用 api.React.createElementapi.addRouteapi.addTool

共享依赖/console/esm/*.mjs 提供 canonical ESM(react、react-dom 等),esbuild 按需打包 + 缓存,无需 import map / farm-peer-shim。

构建顺序(Host)contract (tsc) → pagemanager (tsc) → client (tsc) → host-router (tsc) → host-api (tsup)。

类型导入:适配器 client/ 使用 import type { PluginRegisterHostApi } from '@zhin.js/contract'(类型勿从 host-api 主入口副作用 import;PageManager 类型可 import type { PageManager } from '@zhin.js/host-api')。

约定:Host 传输在 packages/host/router/src/;管理面 API 在 packages/host/api/src/;适配器控制台扩展仍在各适配器包根 client/(由 Host /@dev 打包)。内置仪表盘等 UI 仅在 zhin-console 仓库维护。

3.4 @zhin.js/clientpackages/console/client

  • packages/console/client/:npm 包 @zhin.js/client 的根。
  • packages/console/client/client/:浏览器端源码(app.ts 单例、WebSocket 模块、mediaSrc 工具)。
  • 构建输出dist/main/types 指向 ./dist/...)。
  • 核心导出app 单例;WebSocket / REST+SSE hooks;loadConsoleEntriesapiFetch / getApiBase(Remote 用)。
  • 无 Redux:状态管理由 app 单例 + useSyncExternalStore 替代。

4. 文件命名(前端 / TS)

建议新代码按下列执行;存量代码可渐进调整。

类别约定
React 组件文件PascalCase,如 MessageBody.tsx
默认导出页面组件PascalCase,语义准确(如 BotManagePage,避免 Mange 等拼写错误)
页面/路由目录kebab-case,如 bot-detail/index.tsx
工具函数、非组件模块camelCase,如 parseComposerContent.ts
样式与配置kebab-case,如 tailwind.config.js
Node 单文件模块kebab-casecamelCase 与所在包存量保持一致;新增宜 kebab-case(如 adapter-process.ts

测试与类型: *.test.ts / *.spec.ts 与源码同目录或 tests/ 均可,同一包内保持一种主风格即可。

5. package.json 元数据

  • repository.directory:必须与包在仓库中的真实路径一致。
  • type ESM 包使用 "module" 时,与构建产物一致即可。
  • exports 子路径导出应指向真实存在的构建产物libdist),避免文档与磁盘不一致。

6. 与约定对照(仓库审计备忘)

以下条目在引入新包或重构时用于自检;不必一次性全部改掉,但新增代码应对齐第 3 节。

位置状态说明
多数 plugins/*packages/*basic/*(仅 Node)src/lib/,与约定一致。
@zhin.js/client浏览器源码在 client/,发布入口在 dist/
client/ 的适配器扩展构建输出目标为包根 dist/zhin build)。
@zhin.js/host-routersrc/lib/;Koa + Router + 鉴权。
@zhin.js/host-apisrc/lib/;Host api_only(无内置 SPA)。
@zhin.js/satoripackages/toolkit/satoriNode 库:src/lib/(tsup),与全局约定一致。
examples/*ℹ️示例工程可能直接运行 src,不强制 lib/dist,不纳入插件包约定。

7. 其他说明

  • 个别旧包若 main / types 仍写作 lib/... 而未带 ./,建议统一为 ./lib/...;若发现遗漏可随 PR 补上。
  • clean 脚本 应删除本包实际构建输出目录(例如 @zhin.js/client 仅产出 dist/ 时不应再 rimraf lib)。

8. 代码组织与可维护性

  • 分层: packages/im/kernelaicoreagentzhin 依赖方向保持单向;插件只通过公开 API 与 zhin.js / @zhin.js/core 交互,避免环形依赖。
  • 单文件体量: 页面或路由文件若超过约 400~500 行,优先拆出子组件、hooks/utils/types.ts(控制台 bot-detaildatabase 等可按此渐进拆分)。
  • 副作用入口: 插件 src/index.ts 宜保持「注册路由 / 命令 / 生命周期」为主;重逻辑抽到同目录 *.service.tslib/ 子模块便于测试。
  • 日志: 构建脚本、CLI 中避免长期保留无环境变量的 console.log 调试输出;必要进度信息可用 console.error(stderr)或受 DEBUG=* 控制。
  • 英文标识符: 公共导出符号、类型名、路由 key 使用正确英文拼写,避免混入拼音缩写(除非领域通用如 icqq)。

9. AI 能力文件约定

插件 / 工作区可通过标准目录放置 AI 声明文件,框架自动扫描与热重载:

目录文件格式用途
tools/*.tool.md(扁平)或 <name>/<name>.tool.md(嵌套 + handler)文件化 AI Tool:YAML frontmatter 定义参数/元数据,可选 handler 或 body 模板
skills/<name>/SKILL.md文件化 Skill:粗筛描述 + 关联工具列表,always: true 常驻注入
agents/*.agent.md(扁平)或 <name>/<name>.agent.md(嵌套)文件化 Agent 预设:frontmatter + body 作为 systemPrompt
包根plugin.yml插件元数据清单(namedescriptionversion),通过 plugin.manifest 访问

发现优先级:工作区 cwd/ > ~/.zhin/ > data/ > 已加载插件包根。同名先发现者优先;程序化注册的同名 Tool 优先于文件化版本。


维护者更新本文时,请同步检查 pnpm-workspace.yamldocs/contributing.md 中的链接。

基于 MIT 许可发布