docs: add detailed answers for 21 learning roadmap questions

This commit is contained in:
2026-05-13 03:40:13 +00:00
parent a8d90d2980
commit c4753da8f5
10 changed files with 1308 additions and 0 deletions

View File

@@ -0,0 +1,167 @@
# Q16-Q17: 数据模型
---
## Q16: 中央库 `data/v2.db` 有哪些表?它们之间的外键关系是怎样的?
### 答案
中央库有约 20 张表,横跨多次迁移。以下按逻辑分类:
### 核心实体表(迁移 001
| # | 表 | 用途 | 关键 FK 关系 |
|---|-----|------|-------------|
| 1 | `agent_groups` | Agent 工作区folder、skills、CLAUDE.md | 根实体——无 FK 出 |
| 2 | `messaging_groups` | 一个平台聊天/频道/DM | 根实体;`UNIQUE(channel_type, platform_id)` |
| 3 | `messaging_group_agents` | 多对多 wiringagent↔channel | `→ messaging_groups(id)`, `→ agent_groups(id)``UNIQUE(messaging_group_id, agent_group_id)` |
| 4 | `users` | 平台用户身份(`<channel>:<handle>` | 根实体 |
| 5 | `user_roles` | 特权授予owner/admin | `→ users(id)` (x2: user + granted_by), `→ agent_groups(id)``PK (user_id, role, agent_group_id)` |
| 6 | `agent_group_members` | 非特权访问门 | `→ users(id)` (x2), `→ agent_groups(id)``PK (user_id, agent_group_id)` |
| 7 | `user_dms` | 冷 DM 缓存 | `→ users(id)`, `→ messaging_groups(id)``PK (user_id, channel_type)` |
| 8 | `sessions` | Session 生命周期元数据 | `→ agent_groups(id)`, `→ messaging_groups(id)` |
| 9 | `pending_questions` | 交互式问题状态 | `→ sessions(id)` |
### 后续迁移添加的表
| # | 表 | 迁移 | 说明 |
|---|-----|------|------|
| 10 | `chat_sdk_kv` | 002 | Chat SDK 不透明状态 |
| 11 | `chat_sdk_subscriptions` | 002 | Chat SDK 线程订阅 |
| 12 | `chat_sdk_locks` | 002 | Chat SDK 分布式锁 |
| 13 | `chat_sdk_lists` | 002 | Chat SDK 列表状态 |
| 14 | `pending_approvals` | module-003 | `→ sessions(id)`, `→ agent_groups(id)` |
| 15 | `agent_destinations` | module-004 | `→ agent_groups(id)``PK (agent_group_id, local_name)` |
| 16 | `unregistered_senders` | 008 | 审计跟踪;`PK (channel_type, platform_id)` |
| 17 | `container_configs` | 014 | `→ agent_groups(id) ON DELETE CASCADE` |
| 18 | `pending_sender_approvals` | 011 | `→ messaging_groups(id)`, `→ agent_groups(id)``UNIQUE(messaging_group_id, sender_identity)` |
| 19 | `pending_channel_approvals` | 012 | `→ messaging_groups(id)`, `→ agent_groups(id)` |
| 20 | `schema_version` | 内建 | 迁移分类账——无 FK |
### 已删除的表
- `pending_credentials` — 在迁移 009 中删除(已废弃)
### 列级变更
- `agent_groups.denied_at` — 迁移 012 添加
- `messaging_group_agents` 的 4 列(`engage_mode``engage_pattern``sender_scope``ignored_message_policy`)— 迁移 010 添加,替换旧的 `trigger_rules` + `response_scope`
- `container_configs.cli_scope` — 迁移 015 添加
### ER 关系图
```
agent_groups ──────────────────────────────────────────────────────────────────────────┐
│ │
├── messaging_group_agents ──→ messaging_groups ◄── user_dms │
│ (UNIQUE pair) │
│ │
├── sessions ──→ messaging_groups │
│ └── pending_questions │
│ │
├── user_roles (privilege: owner/admin, scoped or global) ──→ users (user_id, granted_by)
│ │
├── agent_group_members (unprivileged access gate) ──→ users (user_id, added_by) │
│ │
├── agent_destinations (ACL + name→target routing map) │
│ │
├── container_configs (1:1, ON DELETE CASCADE) │
│ │
├── pending_approvals │
├── pending_sender_approvals │
└── pending_channel_approvals │
users ────────────────────────────────────────────────────────────────────────────────┐
├── user_roles (user_id, granted_by 都自引用 users) │
├── agent_group_members │
└── user_dms │
schema_version, chat_sdk_*, unregistered_senders — 无 FK独立叶子表
```
### 关键不变式
- **Owner 必须全局:** `role='owner'` 意味着 `user_roles``agent_group_id IS NULL``grantRole()` 中强制
- **Admin 隐含 membership** agent group A 的 admin 自动是 member——不需要 `agent_group_members`
- **`agent_destinations` 双重角色:** 既是路由表也是 ACL。无行 = 未授权发送。源是中央库spawn 时投影写入容器内 `inbound.db`
- **Chat SDK 表是不透明的**NanoClaw 代码很少直接操作它们——由 `state-sqlite.ts` 持有
- **Session DB 是分离的**`inbound.db` / `outbound.db``data/v2-sessions/<session_id>/` 下,用 `CREATE TABLE IF NOT EXISTS` 做前向兼容
---
## Q17: DB 迁移怎么组织?我要加一张表或一个字段该改哪些文件?
### 答案
### 迁移文件组织
每个迁移是 `src/db/migrations/` 下的一个文件,导出 `Migration` 对象:
```typescript
// src/db/migrations/index.ts:18-22
interface Migration {
version: number; // 在 barrel 数组中的排序提示
name: string; // UNIQUE name — schema_version 中的去重 key
up: (db: Database) => void; // 在事务中运行
}
```
### 迁移注册顺序(`migrations/index.ts:24-38`
```
001-initial.ts → 核心表
002-chat-sdk-state.ts → Chat SDK 表
module-approvals-pending-approvals.ts → pending_approvals
module-agent-to-agent-destinations.ts → agent_destinations
module-approvals-title-options.ts → ALTER pending_approvals
008-dropped-messages.ts → unregistered_senders
009-drop-pending-credentials.ts → DROP pending_credentials
010-engage-modes.ts → ALTER messaging_group_agents
011-pending-sender-approvals.ts
012-channel-registration.ts
013-approval-render-metadata.ts
014-container-configs.ts
015-cli-scope.ts
```
005 和 006 编号空着——早前重编号的。
### 注册机制(`runMigrations``index.ts:40-77`
1. 如果不存在则创建 `schema_version` 表。唯一性在 `name`,不在 `version`
2.`SELECT name FROM schema_version``Set<string>` —— **去重 key 是 `name`**,不是 `version`。这允许模块迁移使用任意版本号
3. `migrations.filter(m => !applied.has(m.name))` 得到待执行列表
4.`db.transaction()` 中运行每个待执行迁移:
-`m.up(db)` 执行 DDL
- 计算 `next = MAX(version) + 1`
- 插入 `schema_version`
### 加一张表
1. 创建 `src/db/migrations/016-your-table.ts`
```typescript
import type Database from 'better-sqlite3';
import type { Migration } from './index.js';
export const migration016: Migration = {
version: 16,
name: 'your-table', // 必须在所有迁移中全局唯一
up(db: Database) {
db.exec(`CREATE TABLE IF NOT EXISTS your_table (...)`);
},
};
```
2. 在 `src/db/migrations/index.ts` 中:
- 添加 `import { migration016 } from './016-your-table.js';`
- 追加到 `migrations` 数组
### 加一个字段
同理,写一个 ALTER TABLE 的迁移。复杂变更(回填)做 JS 行级更新。**幂等守护模式**(迁移 012line 29-32ALTER TABLE ADD COLUMN 前先 `PRAGMA table_info()` 检查列是否已存在。
### 边界情况 / Gotchas
- **DROP TABLE 中的 FK 完整性:** 迁移事务中 DROP TABLE 会触发 SQLite FK 完整性检查。不能 toggle `PRAGMA foreign_keys`。优先 ALTER TABLE ADD COLUMN
- **模块迁移用任意版本:** `module-` 前缀文件的 `name` 与文件名不同——`name` 保持稳定,防止重命名后重新运行
- **Session DB 迁移是独立的:** Session DB schema`INBOUND_SCHEMA`、`OUTBOUND_SCHEMA`)用 `CREATE TABLE IF NOT EXISTS`,新列通过惰性迁移 helper`migrateDeliveredTable()` 等)落地,不跟踪 `schema_version`
- **Container 端也有自己的迁移**`container/agent-runner/src/db/connection.ts:86-110` 有惰性 session DB 迁移(添加 `on_wake` 列、`delivered` 表列等)