# CONTRIBUTING 开发前先阅读 [README.md](README.md)。用户配置、工具用法、事件投递约定和迁移说明 只在 README 维护;本文记录开发所需的实现约束。 ## 代码结构 | 文件 | 职责 | |---|---| | `src/index.ts` | cordis 生命周期、连接启动、服务与工具注册、卸载清理 | | `src/config.ts` | 连接配置 schema、推导类型与默认值 | | `src/adapter/client-api.ts` | 从安装的 SDK 声明读取 API、事件与引用类型 | | `src/tools.ts` | 模型工具 schema 与执行入口 | | `src/service.ts` | `ctx.onebot`、订阅所有权、Worker 生命周期与 agent 投递 | | `src/event-worker.ts` | Worker 中的脚本编译、同步处理与 JSON 序列化 | | `src/log.ts` | cordis 控制台 exporter 与日志格式化 | | `src/profile-setup.ts` | 首次运行配置门与注释模板 | | `src/connect-error.ts` | 连接与令牌校验失败报告、令牌脱敏与 TCP 探测 | ## 构建、检查与测试 ```sh pnpm install pnpm typecheck pnpm test pnpm build ``` 源码改动后必须运行 `pnpm build`;linked profile 加载的是 `lib/`,不构建就会运行旧代码。 测试通过 Node 原生执行 TypeScript,因此相对导入带 `.ts` 后缀,不能使用需转换才能 执行的 TypeScript 语法。构建时 tsc 改写相对导入扩展名。 测试使用 `node:test`。服务测试使用真实 cordis Context 与 SDK client,API 和 agent 行为可以替换,不能为方便测试改变生产服务参数形状。需要模拟 agent 生命周期时使用 真实的 cordis plugin fiber。协议集成测试启动本地 WebSocket 服务,不连接真实账号。 路径样本通过 `tmpdir()` / `homedir()` 与 `join()` 构造,改变环境变量的测试必须还原。 ## 实现约束 - **职责边界**:不在连接插件内创建、恢复或释放 agent,不配置模型、人格或持久化根。 事件结果通过调用方已有 agent 的 inbox 投递,调度交给 dsh;投递行为约定见 README。 - **SDK 是协议定义来源**:不手写 API 或事件清单,不在通用模块写死平台动作名。 声明读取依赖 SDK 发布包中的 `.d.ts` 布局,SDK 升级必须验证方法与事件覆盖; 解析不完整时显式报错,不能悄悄退化成部分能力。 - **所有权**:运行中的订阅绑定具体 Agent 对象,不能仅按 session id 授权。订阅定义通过 session 的插件记录保存,用 session projection 读取;宿主恢复同一 session 后重新绑定 新 Agent,fork 按继承的日志恢复订阅,之后独立管理,不能按订阅 id 跨 Agent 操作。工具调用结束不清理订阅;agent scope 释放只清理运行资源,显式取消才删除保存的定义。启动失败、取消和卸载都不能遗留 Worker 或监听器。 - **执行预算**:脚本与结果序列化都放在 Worker 的 vm 执行预算内,主线程另有响应期限。 不把 client、Context、Agent 或其他宿主对象传入脚本。Worker 不等于通用安全沙箱, 不应把此接口扩展成任意宿主代码执行器。 - **错误处理**:协议成功判定交给 SDK 的 `invoke`;不能把失败改成成功空结果,也不能 自动重试可能产生副作用的 API。脚本失败需脱离事件流并保留可查询的诊断。 - **配置真源**:只在 `Config` 声明字段,`OnebotConfig` 从 schema 推导,默认值取 `DEFAULTS`。不为旧配置保留另一套隐式解析路径。schemastery 对象字段默认可选, 不使用不存在的 `.optional()`。 - **工具 schema**:名称使用 `onebot_` 前缀;`defineTool` 推导参数与返回类型,输出 必须匹配声明,尤其是 `additionalProperties`。SDK 经 JSON 传输的 unknown 类型只在 协议返回边界收窄,不转换或裁剪实际数据。 - **日志**:统一使用 `ctx.logger("onebot")`,常规控制台输出只允许出现在 `src/log.ts`。 exporter 的 levels 保留 `default: -1`,避免泄漏其他插件日志;不输出访问令牌。 - **启动与卸载**:要求 tools 与 sessionProjections 服务,模型与 agent 管理服务不是启动依赖。使用 `ctx.effect` 先注册清理再发布服务;清理时终止订阅 Worker 并等待 client 断开。 - **配置门**:配置路径只取宿主 `profileContext.patchPath`,没有该服务时跳过文件引导, 不根据环境变量或固定 profile 名猜测路径。只有 `seedProfilePatch` 可以追加模板, 不能覆盖用户已有内容。已种下但 仍被注释的模板不能被误认为有效配置;连接失败诊断不能修改配置。 服务类型从入口导出,并在入口增强 cordis Context。生产代码持有完整 Context 和 OneBotClient;其他插件通过 `ctx.onebot` 或 `ctx.get("onebot")` 消费服务。 ## 发布 先修改并提交 `package.json` 的版本,再推送匹配版本的 tag。发布 workflow 校验 版本与 tag 一致,安装锁定依赖并运行类型检查、测试,再通过 `NPM_TOKEN` 发布。 `prepack` 负责构建,`lib/` 不纳入 Git;发布内容由 `package.json` 的 `files` 控制。 ## 依赖 - 协议与事件:[onebot.js](https://www.npmjs.com/package/onebot.js)。 - 宿主服务:cordis Context、dsh 工具定义与 agent 消息投递接口。 - 同步事件预处理:Node Worker 与 vm,不引入另一套常驻 agent 执行器。