Refactor runtime around isolated bot instances
This commit is contained in:
@@ -1,353 +1,262 @@
|
||||
# gori-agent 项目施工指南
|
||||
|
||||
本文件供 Kimi Code 等 Coding Agent 在本仓库中施工时使用。目标是让后续 Agent 先理解架构和配置契约,再做最小、可验证的修改。
|
||||
本文件供 Coding Agent 在本仓库施工时使用。先理解 Config v3 和实例隔离契约,再做最小、可验证的修改。
|
||||
|
||||
## 1. 项目定位
|
||||
## 1. 项目定位与固定边界
|
||||
|
||||
`gori-agent` 是一个 Node.js 20+ / TypeScript 项目,通过 IM 接收用户请求,并通过官方 Agent Client Protocol(ACP)驱动 Coding Agent。
|
||||
|
||||
当前主链路:
|
||||
`gori-agent` 是 Node.js 20+ / TypeScript 项目,通过单个 IM 平台接收请求,并通过官方 Agent Client Protocol(ACP)驱动一个 Coding Agent。
|
||||
|
||||
```text
|
||||
用户
|
||||
→ QQ / 其他 IM
|
||||
→ Platform Adapter
|
||||
→ Gateway
|
||||
→ AcpSessionManager
|
||||
→ AcpWorker
|
||||
→ ACP Coding Agent(默认 Kimi Code)
|
||||
→ 工具、脚本和工作目录
|
||||
→ 原路返回用户
|
||||
用户 → Platform Adapter → Gateway → AcpSessionManager → AcpWorker → ACP Agent
|
||||
```
|
||||
|
||||
当前运行时只使用 ACP。不要重新引入“一句话启动一次 CLI”的单轮调用方式,也不要把 legacy `CliAgent` 当作运行时 fallback。
|
||||
每个运行实例是一个完整且固定的 Bot:
|
||||
|
||||
模型和 provider 属于 ACP 后端自身的配置。例如 Kimi Code 使用其自己的 `config.toml`;`gori-agent/config.json` 只配置如何启动 ACP backend,不负责复制或管理模型凭据。
|
||||
- 一个 Gateway 进程。
|
||||
- 一份 Config v3 本地配置。
|
||||
- 一个 `bot.id`、workspace、persona。
|
||||
- 一个 ACP agent。
|
||||
- 一组直接声明的 skills 与一个 permission policy。
|
||||
- 一个平台身份。
|
||||
- 独立 PID、日志和 ACP state。
|
||||
|
||||
## 2. 核心设计原则
|
||||
不要重新引入 Config v1/v2 migration、`roles[]`、动态 role selection、`backends[]`、多平台同时启用或单轮 CLI fallback。
|
||||
|
||||
- **Role 是业务身份**:定义职责、workspace、skills 和权限策略。
|
||||
- **Backend 是执行后端**:定义 ACP 子进程的 command、args 和 env。
|
||||
- **Skill 是可注入知识**:顶层声明 SKILL.md,role 按 ID 引用。
|
||||
- **Session 是连续对话**:同一 `platform + chat + role` 复用同一 native ACP session。
|
||||
- **权限由 ACP policy 约束**:persona 不是安全边界,不能替代 permission policy。
|
||||
- **默认 fail closed**:不确定时拒绝权限,不自动扩大工具或命令范围。
|
||||
- **一个进程只登录一个 QQ Bot**:多 Bot 使用多个进程和独立配置、端口、状态目录。
|
||||
## 2. 实例目录契约
|
||||
|
||||
## 3. 代码结构
|
||||
统一实例根:
|
||||
|
||||
- `src/server.ts`
|
||||
- 组装 store、role registry、ACP session manager、Gateway 和平台 adapter。
|
||||
- 挂载 health/platform/webhook 路由,按配置启动 QQ WebSocket。
|
||||
- `src/config.ts`
|
||||
- config v2 的 Zod schema、默认值、交叉引用校验和 v1 Kimi 配置迁移。
|
||||
- 新增配置字段时,必须先更新 schema,再更新模板、setup/doctor、测试和文档。
|
||||
- `src/core/gateway.ts`
|
||||
- 入站 allowlist、群聊 mention 规则、命令分发、per-chat 串行锁和回复发送。
|
||||
- `/cancel` 必须能绕过 chat lock,避免无法取消长任务。
|
||||
- `src/core/command-router.ts`
|
||||
- `/help`、`/roles`、`/role`、`/status`、`/cancel`、`/new`。
|
||||
- `src/core/durable-session-store.ts`
|
||||
- 持久化 role 选择和 ACP session binding。
|
||||
- 使用单 writer lock 和原子写入;不要绕过或手改运行中的 state。
|
||||
- `src/roles/role-registry.ts`
|
||||
- 读取 role、加载 skill、生成 fingerprint 和隐藏 bootstrap prompt。
|
||||
- `src/roles/skill-loader.ts`
|
||||
- 校验 skill 文件、大小限制并计算内容 hash。
|
||||
- `src/acp/client.ts`
|
||||
- ACP initialize、session new/resume/load、prompt、cancel 和 permission request。
|
||||
- `src/acp/worker.ts`
|
||||
- 在 `role.workspace` 中启动 ACP 子进程,处理超时、取消和异常退出。
|
||||
- `src/acp/session-manager.ts`
|
||||
- 管理 chat/role binding、worker 池、冷恢复、idle sweep、容量淘汰和 reset。
|
||||
- `src/platforms/qq/`
|
||||
- QQ WebSocket、webhook、验签、消息标准化和发送。
|
||||
- `src/cli.ts`、`src/cli/`
|
||||
- setup、doctor、status 和 backend discovery。
|
||||
- `src/agents/`、`src/core/session-store.ts`
|
||||
- legacy compatibility/reference,不是当前运行链路。除非需求明确,不要在这里扩展新能力。
|
||||
- `dist/`
|
||||
- TypeScript 构建产物。只修改 `src/`,不要手改 `dist/`。
|
||||
```text
|
||||
${GORI_AGENT_ROOT:-$HOME/.gori-agent}/instances/<bot-id>/
|
||||
├── config.json
|
||||
├── logs/gori-agent.log
|
||||
└── state/
|
||||
├── acp-sessions.json
|
||||
└── gori-agent.pid
|
||||
```
|
||||
|
||||
## 4. Config v2 契约
|
||||
实例目录本身就是该进程的 `GORI_AGENT_HOME`。约束:
|
||||
|
||||
唯一可提交的配置模板是 `config.example.json`。真实部署配置复制为本地 `config.json`:
|
||||
- `bot.id` 只允许小写字母、数字和连字符,拒绝 `/`、`..` 等路径穿越。
|
||||
- CLI 加载后必须校验目录名与 `config.bot.id` 相同。
|
||||
- 实例目录、`logs/`、`state/` 为 `0700`。
|
||||
- `config.json`、PID、state 为 `0600`。
|
||||
- 多实例必须使用不同 `gateway.server.port` 和平台 credentials。
|
||||
- `instance init` / `setup` 必须交互询问并校验 server host/port;扫描其他 Config v3 的声明端口,冲突时警告,新实例建议下一个未声明端口,已有配置不得静默改端口。
|
||||
- setup 的声明冲突提示不替代实际 bind 检查;`start` 对缺配置、ID 不匹配、错误权限、占位符、运行 PID、端口冲突 fail closed。
|
||||
|
||||
日常入口:
|
||||
|
||||
```bash
|
||||
cp config.example.json config.json
|
||||
chmod 600 config.json
|
||||
gori-agent instance init <bot-id>
|
||||
gori-agent instance start <bot-id>
|
||||
gori-agent instance stop <bot-id>
|
||||
gori-agent instance restart <bot-id>
|
||||
gori-agent instance status <bot-id>
|
||||
gori-agent instance logs <bot-id>
|
||||
gori-agent instance list
|
||||
gori-agent instance doctor <bot-id>
|
||||
```
|
||||
|
||||
`config.json` 和备份包含 IM credentials,不得提交。
|
||||
保留 `start --config`、`status --config`、`doctor --config` 等用于本地调试,但运行配置不存在时不得回退 example。
|
||||
|
||||
### 4.1 顶层字段
|
||||
## 3. 核心代码结构
|
||||
|
||||
- `src/config.ts`
|
||||
- Config v3 Zod schema、类型、交叉校验和 state 默认路径。
|
||||
- 只接受 `configVersion: 3`。
|
||||
- `src/server.ts`
|
||||
- 组装 fixed Bot、state store、ACP manager、Gateway 和唯一 platform adapter。
|
||||
- 只挂载所选平台 route。
|
||||
- `src/roles/role-registry.ts`
|
||||
- 历史路径名保留,但实现是 `BotProfileResolver`,不是 role registry。
|
||||
- 加载当前 Bot skills、计算 fingerprint、生成版本化 bootstrap。
|
||||
- `src/acp/client.ts`
|
||||
- ACP initialize/new/resume/load/prompt/cancel 和 permission request。
|
||||
- `src/acp/worker.ts`
|
||||
- 直接使用 resolved Bot 的 agent,在 `bot.workspace` 启动。
|
||||
- `src/acp/session-manager.ts`
|
||||
- 固定 Bot 的 binding、worker pool、恢复、idle sweep、capacity、cancel/reset。
|
||||
- `src/core/durable-session-store.ts`
|
||||
- state v2,保存 bot/platform identity 和 chat binding。
|
||||
- 单 writer lock、串行持久化、临时文件、fsync、原子 rename。
|
||||
- `src/core/gateway.ts`
|
||||
- 入站 allowlist、群 mention、命令、per-chat lock 和回复。
|
||||
- `/cancel` 必须绕过 chat lock。
|
||||
- `src/core/command-router.ts`
|
||||
- `/help`、`/status`、`/cancel`、`/new`;旧 role 命令返回 retired 提示。
|
||||
- `src/platforms/*`
|
||||
- Adapter 依赖独立平台 config type,不依赖完整 AppConfig 路径。
|
||||
- `src/cli/config-file.ts`
|
||||
- fail-closed 加载、example seed 与原子 `0600` 配置写入。
|
||||
- `src/cli/instance.ts`
|
||||
- 实例目录、PID/log、端口和 lifecycle 管理。
|
||||
- `src/cli/doctor.ts`
|
||||
- v3、Bot、agent、platform、state、permission 和 placeholder 检查。
|
||||
- `src/agents/*`、`src/core/session-store.ts`
|
||||
- legacy compatibility/reference,不是当前运行链路。
|
||||
- `dist/`
|
||||
- 构建产物;不手改,修改 TypeScript 后运行 `npm run build`。
|
||||
|
||||
## 4. Config v3 契约
|
||||
|
||||
仓库中唯一可提交配置说明是 `config.example.json`。它含明显占位符,可通过 schema,但不能启动实际 Bot。
|
||||
|
||||
顶层:
|
||||
|
||||
```text
|
||||
configVersion 必须为 2
|
||||
server HTTP 服务配置
|
||||
policy IM 入站访问策略
|
||||
acp ACP 生命周期、状态和进程池配置
|
||||
backends[] ACP 后端启动定义,至少一个
|
||||
skills[] 可选 SKILL.md 定义
|
||||
defaultRole 默认 role ID
|
||||
roles[] 业务角色定义,至少一个
|
||||
platforms QQ、Feishu、WeCom、Webhook、Weixin 配置
|
||||
configVersion 固定 3
|
||||
bot 固定 Bot、agent、skills、permissions
|
||||
gateway server、入站 policy、唯一 platform
|
||||
runtime.acp state 和 ACP 生命周期
|
||||
```
|
||||
|
||||
Zod 会剥离 schema 未声明的字段。因此不能只在 JSON 中增加字段而不修改 `src/config.ts`。
|
||||
|
||||
### 4.2 `server`
|
||||
|
||||
- `host`:默认 `0.0.0.0`。
|
||||
- `port`:1–65535;多实例必须使用不同端口。
|
||||
- `publicBaseUrl`:反向代理或公开 webhook 基础地址;不需要时为空。
|
||||
|
||||
### 4.3 顶层 `policy`
|
||||
|
||||
- `allowedUsers: string[]`:空数组表示不按用户限制;非空时精确匹配。
|
||||
- `allowedChats: string[]`:空数组表示不按会话限制;非空时精确匹配。
|
||||
- `requireMentionInGroup: boolean`:群聊是否必须 @bot。
|
||||
- QQ 群 chat ID 形式为 `group:<group_openid>`。
|
||||
- 正式运维 Bot 应配置 allowlist,不要长期保持完全开放。
|
||||
|
||||
### 4.4 `acp`
|
||||
|
||||
- `stateFile`:空字符串时使用 `$GORI_AGENT_HOME/state/acp-sessions.json`。
|
||||
- `initializeTimeoutMs`:ACP 初始化超时。
|
||||
- `promptTimeoutMs`:单轮 prompt 超时。
|
||||
- `cancelGraceMs`:取消后等待时间,超时才终止 worker。
|
||||
- `idleTimeoutMs`:空闲 worker 回收时间;session binding 仍可持久化恢复。
|
||||
- `sweepIntervalMs`:空闲扫描周期。
|
||||
- `maxProcesses`:最大 ACP 子进程数。
|
||||
|
||||
不同实例不得共享 `stateFile` 或 `GORI_AGENT_HOME`。持久 store 有单 writer lock,共享会使第二个实例启动失败。
|
||||
|
||||
### 4.5 `backends[]`
|
||||
|
||||
每项字段:
|
||||
### 4.1 `bot`
|
||||
|
||||
```json
|
||||
{
|
||||
"id": "kimi",
|
||||
"command": "/home/USER/.kimi-code/bin/kimi",
|
||||
"args": ["acp"],
|
||||
"env": {}
|
||||
}
|
||||
```
|
||||
|
||||
约束:
|
||||
|
||||
- `id` 必须唯一。
|
||||
- `command` 必须是可执行程序。
|
||||
- Kimi Code backend 应使用 `args: ["acp"]`。
|
||||
- 子进程以 `shell: false`、`cwd: role.workspace` 启动。
|
||||
- `env` 会覆盖同名进程环境变量;不得把 token 或 API key 写入可提交模板。
|
||||
- 新增其他 Coding Agent 前,必须确认它提供兼容 ACP,或提供独立且有测试的 ACP adapter;不要假设普通 CLI 等同 ACP。
|
||||
|
||||
### 4.6 `skills[]`
|
||||
|
||||
每项字段:
|
||||
|
||||
```json
|
||||
{
|
||||
"id": "SKILL_ID",
|
||||
"file": "/absolute/path/to/SKILL.md",
|
||||
"maxBytes": 256000
|
||||
}
|
||||
```
|
||||
|
||||
约束:
|
||||
|
||||
- `id` 必须唯一。
|
||||
- 建议使用绝对路径,避免不同启动目录导致解析变化。
|
||||
- 文件必须存在、可读、是普通文件且不超过 `maxBytes`。
|
||||
- Role 只能引用已在顶层声明的 skill ID。
|
||||
- Skill 内容会发送给 ACP backend,也参与 role fingerprint;不要在 skill 中放 secret。
|
||||
|
||||
### 4.7 `roles[]`
|
||||
|
||||
推荐一个 Bot 实例只保留它自己的一个 role:
|
||||
|
||||
```json
|
||||
{
|
||||
"id": "ROLE_ID",
|
||||
"backend": "kimi",
|
||||
"workspace": "/absolute/path/to/workspace",
|
||||
"persona": "明确描述职责、边界和何时停止请求确认。",
|
||||
"id": "bot-id",
|
||||
"workspace": "/absolute/path",
|
||||
"persona": "明确职责、边界和确认点。",
|
||||
"agent": {
|
||||
"id": "kimi",
|
||||
"command": "/absolute/path/to/kimi",
|
||||
"args": ["acp"],
|
||||
"env": {}
|
||||
},
|
||||
"skills": [],
|
||||
"policy": {
|
||||
"permissionMode": "deny",
|
||||
"permissions": {
|
||||
"mode": "deny",
|
||||
"allowedTools": [],
|
||||
"allowedCommandPatterns": []
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
约束:
|
||||
- workspace 必须绝对。
|
||||
- 一个 Bot 只有一个 agent;不要添加 registry/reference。
|
||||
- Kimi Code 应使用 `args: ["acp"]`。
|
||||
- agent `shell: false`,cwd 为 workspace。
|
||||
- 模型/provider 属于 ACP agent 自己的配置,不写入 gori-agent config。
|
||||
- `env` 不得在模板、日志、diff 中泄漏 token。
|
||||
|
||||
- Role `id` 必须唯一,`defaultRole` 必须引用存在的 role。
|
||||
- `workspace` 必须是绝对路径,并应在 `doctor` 时真实存在。
|
||||
- `backend` 和 `skills` 引用必须存在。
|
||||
- 修改 role ID、backend、workspace、persona、policy 或 skill 内容会改变 fingerprint;下一条消息会创建新 native session,避免沿用旧身份上下文。
|
||||
### 4.2 Skills
|
||||
|
||||
权限模式:
|
||||
|
||||
- `deny`:拒绝所有 ACP permission request;新角色默认使用此模式。
|
||||
- `allowlist`:只允许 `allowedTools`;bash/terminal 还必须匹配至少一个 `allowedCommandPatterns` 正则。
|
||||
- `auto`:自动允许,等价于高风险/yolo;只有用户明确要求、workspace 与 Bot 访问范围都可控时才能配置。
|
||||
|
||||
配置 `allowlist` 时:
|
||||
|
||||
- 使用最小工具集合。
|
||||
- 命令正则应锚定开头并限制参数,不要使用 `.*` 放行所有命令。
|
||||
- 删除、部署、推送、发送消息等不可逆或外部操作仍应在 persona 中要求确认。
|
||||
- permission request 信息不足时必须拒绝,不能猜测。
|
||||
|
||||
### 4.8 `platforms.qq`
|
||||
`bot.skills[]` 每项直接声明:
|
||||
|
||||
```json
|
||||
{
|
||||
"enabled": true,
|
||||
"connectionMode": "websocket",
|
||||
"appId": "QQ_APP_ID",
|
||||
"clientSecret": "QQ_CLIENT_SECRET",
|
||||
"botSecret": "",
|
||||
"verifySignature": true,
|
||||
"botNames": ["QQ_BOT_NAME"],
|
||||
"intents": 33554432,
|
||||
"shard": [0, 1]
|
||||
}
|
||||
{ "id": "skill-id", "file": "/absolute/SKILL.md", "maxBytes": 256000 }
|
||||
```
|
||||
|
||||
- WebSocket 登录需要有效的 `appId` 和 `clientSecret`。
|
||||
- Webhook 验签使用 `botSecret || clientSecret`。
|
||||
- `botNames` 用于 mention 识别,应与平台上的机器人名称一致。
|
||||
- 一个 config 只有一个 QQ 对象,因此一个进程只能登录一个 QQ Bot。
|
||||
- 不要把 QQ 注销、群注销、无权限等平台 4xx 错误误判成 ACP session 错误;先检查错误码、目标 chat/user openid 和消息发送 endpoint。
|
||||
ID 唯一;文件须存在、可读、普通文件且未超限。skill 内容发送给 ACP,也进入 fingerprint;不得放 secret。
|
||||
|
||||
其他平台字段以 `src/config.ts` schema 为准。平台 `enabled` 不一定会统一禁用所有 HTTP 路由;公开 webhook 时仍需检查路由和验签实现。
|
||||
### 4.3 Permissions
|
||||
|
||||
## 5. Role 与 Session 行为
|
||||
- `deny`:默认,拒绝全部 permission request。
|
||||
- `allowlist`:`toolCall.name` 与 `allowedTools` 精确匹配;bash/terminal 的 raw command 还要被 `allowedCommandPatterns` 完整覆盖。
|
||||
- `auto`:高风险/yolo,只有用户明确授权才能设置。
|
||||
|
||||
- Binding key 是 `platform + chatId + roleId`。
|
||||
- 同一 chat 的不同 role 拥有不同 native ACP session。
|
||||
- 首次 prompt 会创建 session、发送隐藏 bootstrap,成功后保存 binding,再发送用户请求。
|
||||
- Gateway 或 ACP worker 重启后,使用持久 binding 尝试 `session/resume`,必要时回退 `session/load`。
|
||||
- `/new` 删除当前 chat/role binding;下一条普通消息再创建新 session。
|
||||
- `/cancel` 取消当前 turn,不应等待正在执行的 chat lock。
|
||||
- Prompt 失败不能擅自重放,因为工具操作可能已经产生副作用。
|
||||
- Session 上下文由 native ACP Agent 维护;gori-agent 维护角色选择、binding、生命周期和恢复信息,不应每轮把完整历史重新拼给 CLI。
|
||||
permission policy 只审批 ACP request,不会注册工具。persona 不是安全边界。请求信息不足时拒绝。命令 regex 应锚定并限制参数,不使用任意 `.*` 全放行。
|
||||
|
||||
## 6. 多机器、多 Bot 部署规范
|
||||
### 4.4 Gateway
|
||||
|
||||
每个 Bot 使用一份位于部署机器上的本地 `config.json`,不要在仓库中创建 `config.ops.json`、`config.developer.json` 等带真实凭据的文件。
|
||||
- `gateway.server`: host、port、publicBaseUrl。
|
||||
- `gateway.policy`: allowedUsers、allowedChats、requireMentionInGroup。
|
||||
- `gateway.platform`: `type` discriminated union,只能是 qq、feishu、wecom、webhook、weixin 之一。
|
||||
- 对象存在即启用,无 `enabled` 字段。
|
||||
|
||||
每个实例至少要唯一:
|
||||
QQ 群 chat ID 为 `group:<group_openid>`。正式运维 Bot 应配置入口 allowlist。
|
||||
|
||||
- QQ `appId`、`clientSecret`、`botNames`
|
||||
- `server.port`
|
||||
- `GORI_AGENT_HOME`,或显式且独立的 `acp.stateFile`
|
||||
- role ID、workspace、persona 和 policy
|
||||
### 4.5 Runtime ACP
|
||||
|
||||
示例:
|
||||
- `stateFile` 为空时为 `$GORI_AGENT_HOME/state/acp-sessions.json`。
|
||||
- `initializeTimeoutMs`: 默认 10000。
|
||||
- `promptTimeoutMs`: 默认 7200000(2 小时)。
|
||||
- `cancelGraceMs`: 默认 5000。
|
||||
- `idleTimeoutMs`: 默认 1800000。
|
||||
- `sweepIntervalMs`: 默认 60000。
|
||||
- `maxProcesses`: 默认 8。
|
||||
|
||||
## 5. Session 与 state v2
|
||||
|
||||
Binding key 是当前实例固定的 `platform + chatId`。不再包含 role。
|
||||
|
||||
state v2 header 保存 `botId` 和 platform。打开时不匹配必须拒绝,不能清空、迁移或覆盖。旧 state v1 也明确拒绝并保留原文件。
|
||||
|
||||
Binding 保存 agent ID、workspace、native session ID、Bot fingerprint 和时间戳。fingerprint 包含:
|
||||
|
||||
- bootstrap schema version
|
||||
- Bot ID
|
||||
- workspace/persona
|
||||
- agent 定义
|
||||
- permission policy
|
||||
- skill 路径和内容 hash
|
||||
|
||||
首次消息创建 native session,发送隐藏 bootstrap,成功后保存 binding。重启/idle 后优先 resume,再 fallback load。prompt 失败不重放。
|
||||
|
||||
`/new` 删除当前 chat binding;下一条消息创建新 session。`/cancel` 不等待 chat lock。
|
||||
|
||||
## 6. 单平台装配
|
||||
|
||||
Server 只构造 `gateway.platform.type` 对应 adapter,只挂载对应 webhook:
|
||||
|
||||
- qq webhook 模式 → `/webhook/qq`;QQ WebSocket 模式不挂载该 route
|
||||
- feishu → `/webhook/feishu`
|
||||
- wecom → `/webhook/wecom`
|
||||
- weixin → `/webhook/weixin`
|
||||
- webhook → `/webhook/generic`
|
||||
|
||||
QQ WebSocket 仅在 qq + websocket 模式启动。`GET /health` 只输出 configVersion、botId、platform 和 aggregate ACP counters,不得输出 credentials 或 native session ID。`GET /platforms` 返回单 Bot/platform 概览。
|
||||
|
||||
## 7. 配置与实例施工流程
|
||||
|
||||
1. 读取本文件、`config.example.json` 和 `src/config.ts`。
|
||||
2. 明确 Bot ID、workspace、persona、平台、skills 和最小 permission policy。
|
||||
3. 确认 ACP agent executable 与 ACP 可用。
|
||||
4. 使用 `instance init` 或 Coding Agent 生成实例 `config.json`;不要把 example 当运行配置。
|
||||
5. 交互确认并严格校验 `gateway.server.host/port`;对其他实例的声明端口冲突给出警告和建议,但仍由 `start` 做实际 bind 检查。
|
||||
6. 写配置必须同目录临时文件 + fsync + atomic rename,最终 `0600`;目录 `0700`。
|
||||
7. setup 的 secret/token 输入必须不回显;secrets 不在对话、日志、测试输出、diff 中回显。
|
||||
8. 运行 `instance doctor`,不发送真实平台消息。
|
||||
9. 只有用户明确授权时才启动/停止真实 Bot。
|
||||
|
||||
旧仓库本地 `config.json`、备份和 state 可供人工回退;改造实例时不要删除或覆盖。
|
||||
|
||||
## 8. 测试与验收
|
||||
|
||||
行为变化补测试,不削弱测试。配置 schema 变化同步:
|
||||
|
||||
- `src/config.ts`
|
||||
- `config.example.json`
|
||||
- setup/doctor/instance CLI
|
||||
- README 和本文件
|
||||
- config、session、store、Gateway、server 测试
|
||||
|
||||
最终运行:
|
||||
|
||||
```bash
|
||||
GORI_AGENT_HOME=/home/USER/.gori-agent-ROLE_ID \
|
||||
./gori-agent.sh start-daemon --config ./config.json
|
||||
```
|
||||
|
||||
`GORI_AGENT_HOME` 隔离:
|
||||
|
||||
- PID
|
||||
- 日志
|
||||
- 默认 ACP session state
|
||||
- 单实例锁
|
||||
|
||||
同一机器启动多个实例时,每个实例应从各自部署目录运行,或明确指定独立配置路径和 `GORI_AGENT_HOME`。
|
||||
|
||||
## 7. 配置施工流程
|
||||
|
||||
当用户让 Agent 配置一个新角色或新 Bot 时,按以下顺序执行:
|
||||
|
||||
1. 读取 `AGENTS.md`、`config.example.json` 和相关 schema;不要先读取或展示真实 secrets。
|
||||
2. 明确 role 的职责、workspace、所需 skills、允许的工具和命令。
|
||||
3. 确认 backend 可执行路径以及 `kimi acp` 可用。
|
||||
4. 从唯一模板复制本地 `config.json`,不另建可提交的具体 Bot 模板。
|
||||
5. 填写本机 QQ credentials;不要在回复、日志、diff 或测试输出中回显。
|
||||
6. 默认先用 `deny`;需要施工能力时配置最小 `allowlist`;只有明确授权才使用 `auto`。
|
||||
7. 设置文件权限为 `0600`。
|
||||
8. 运行配置和 backend 检查:
|
||||
|
||||
```bash
|
||||
./gori-agent.sh discover-backends --config ./config.json
|
||||
./gori-agent.sh doctor --config ./config.json
|
||||
```
|
||||
|
||||
9. 前台启动,确认 QQ WebSocket ready,再从 IM 执行只读验收。
|
||||
10. 前台通过后,使用唯一 `GORI_AGENT_HOME` 后台启动。
|
||||
11. 任何包含 secret 的配置、备份和日志都不得加入 Git。
|
||||
|
||||
若缺少真实凭据,可以完成无密钥模板和规范,但不得虚构 credentials,也不得声称真实 QQ 登录已验证。
|
||||
|
||||
## 8. 常用命令
|
||||
|
||||
```bash
|
||||
npm install
|
||||
npm run typecheck
|
||||
npm test
|
||||
npm run build
|
||||
|
||||
gori-agent setup --config ./config.json
|
||||
gori-agent discover-backends --config ./config.json
|
||||
gori-agent doctor --config ./config.json
|
||||
gori-agent start --config ./config.json
|
||||
|
||||
./gori-agent.sh start --config ./config.json
|
||||
./gori-agent.sh start-daemon --config ./config.json
|
||||
./gori-agent.sh status --config ./config.json
|
||||
./gori-agent.sh logs
|
||||
./gori-agent.sh stop
|
||||
git diff --check
|
||||
bash -n install.sh gori-agent.sh bin/gori-agent
|
||||
```
|
||||
|
||||
`gori-agent.sh` 不会检测源码是否比 `dist/` 新。修改 TypeScript 后必须显式运行 `npm run build`。
|
||||
额外检查:
|
||||
|
||||
## 9. 修改与验收规则
|
||||
- example 可 parse,doctor 识别 placeholder。
|
||||
- 不存在的运行配置明确失败。
|
||||
- tracked diff 无 config、backup、state、log、credentials 或手改 dist。
|
||||
- 不执行真实平台消息、pull、部署、远程机器修改或 Git mutation,除非用户当次明确授权。
|
||||
|
||||
- 做最小、局部、可审查的修改,不做无关重构。
|
||||
- 先修改 `src/`,不要直接修改 `dist/`。
|
||||
- 行为变化应补对应测试;不要通过削弱测试来适配实现。
|
||||
- 配置 schema 变化必须同步:
|
||||
- `src/config.ts`
|
||||
- `config.example.json`
|
||||
- setup/doctor(如适用)
|
||||
- README 和本文件
|
||||
- 配置测试
|
||||
- 平台错误必须保留足够的错误码和 trace ID 用于诊断,但不得输出 secret。
|
||||
- 修改后运行:
|
||||
|
||||
```bash
|
||||
npm run typecheck
|
||||
npm test
|
||||
npm run build
|
||||
git diff --check
|
||||
```
|
||||
|
||||
- 测试未通过时不能宣称完成。
|
||||
- 不执行真实 QQ 消息、pull、部署、push、创建 PR 等外部操作,除非用户明确要求并授权。
|
||||
- 不自动执行 Git commit/push;需要时按用户当次指令处理。
|
||||
|
||||
## 10. 敏感信息与禁止提交内容
|
||||
## 9. 敏感信息与禁止提交
|
||||
|
||||
不得提交或粘贴:
|
||||
|
||||
- `config.json`
|
||||
- `config.json.*.bak`
|
||||
- 任意包含真实 Bot/App credentials 的自定义配置
|
||||
- `.env`
|
||||
- `backends[].env` 中的 token/API key
|
||||
- ACP state、PID、lock 和 session metadata
|
||||
- 日志中的真实 chat ID、user ID、message ID、消息正文或 ACP stderr 敏感内容
|
||||
- 任何真实 `config.json` 或备份
|
||||
- `.env`、agent env token/API key
|
||||
- platform credentials
|
||||
- ACP state、PID、lock、session metadata
|
||||
- 含真实 chat/user/message ID 或消息正文的日志
|
||||
|
||||
唯一可提交配置模板:`config.example.json`。其中只能使用明显占位符。
|
||||
|
||||
当前 `.gitignore` 已覆盖 `config.json`、备份、日志、`dist/`、`node_modules/` 和 coverage。新增其他具体配置文件名时,不要依赖命名约定判断安全;只要包含真实凭据,就必须留在仓库外或明确忽略。
|
||||
`.gitignore` 已覆盖仓库本地 `config.json`、备份、日志、`dist`、`node_modules` 和 coverage。实例默认在仓库外。安全性按内容判断,不能只依赖文件名。
|
||||
|
||||
Reference in New Issue
Block a user