1f6cb1a48f
- 删除 SupabaseSettings 中未使用的 api_external_url computed field - 更新测试文件移除相关测试用例 - backend/AGENTS.md 新增软删除设计规则 - runtime-database.md 更新表结构(删除 user_agents,表名更新为 agent_chat_sessions/messages,system_agents) - runtime-frontend.md 补充路由结构和功能模块说明 - 根 AGENTS.md 清理过时技能路径引用
19 KiB
19 KiB
Database Schema
Status: Active
Last Updated: 2026-03-06
架构概览
数据库层职责
- Supabase: 认证(JWT 签发与验证)
- Backend: 业务授权(Service 层)、数据访问(Repository 层)
- ORM: SQLAlchemy(async + asyncpg,使用 service_role 连接)
核心模块
| 模块 | 路径 | 说明 |
|---|---|---|
| Base Classes | backend/src/core/db/ |
ORM 基类、Session 管理、Repository 基类 |
| Models | backend/src/models/ |
数据模型定义 |
| Migrations | backend/alembic/versions/ |
数据库迁移脚本 |
设计约定
枚举存储
所有枚举使用字符串存储,不使用整数值:
- Database:
VARCHAR(20)+CHECK约束 - Code: Python
Enum继承str
class AgentType(str, Enum):
INTENT_RECOGNITION = "INTENT_RECOGNITION"
TASK_EXECUTION = "TASK_EXECUTION"
RESULT_REPORTING = "RESULT_REPORTING"
软删除
软删除标记数据为不可见,不级联删除:
- 使用
deleted_at: datetime | None列(通过SoftDeleteMixin) - 查询过滤:Repository
_apply_soft_delete_filter()自动排除已删除记录 - 级联策略:默认不级联,强依赖关系在 Service 层手动处理
- 恢复策略:只恢复记录本身,关联数据通过查询自动恢复可见
- 唯一约束:使用 partial index 排除
deleted_at IS NOT NULL
-- Partial unique index in migration
CREATE UNIQUE INDEX ux_user_email
ON users(email)
WHERE deleted_at IS NULL
表清单
| 表名 | 说明 | 状态 |
|---|---|---|
profiles |
用户资料(含 settings JSONB) | Active |
memories |
用户记忆 | Active |
friendships |
好友关系 | Active |
groups |
群组 | Active |
group_members |
群组成员 | Active |
schedule_items |
日程事项 | Active |
schedule_subscriptions |
日程订阅与权限 | Active |
inbox_messages |
待处理消息 | Active |
todos |
待办 | Active |
todo_sources |
待办与日程来源关联 | Active |
automation_jobs |
定时任务 | Active |
agent_chat_sessions |
Agent 对话会话 | Active |
agent_chat_messages |
会话消息记录 | Active |
llm_factory |
LLM 工厂配置 | Active |
llms |
LLM 模型实例 | Active |
system_agents |
系统级 Agent 配置 | Active |
invite_codes |
邀请码 | Active |
表结构详细
profiles
用户资料表,含用户设置。
| 字段 | 类型 | 约束 | 说明 |
|---|---|---|---|
id |
UUID | PK, FK → auth.users.id | 用户 ID |
username |
VARCHAR(30) | UNIQUE, NOT NULL | 用户名 |
avatar_url |
TEXT | NULLABLE | 头像 URL |
bio |
VARCHAR(200) | NULLABLE | 个人简介 |
settings |
JSONB | NOT NULL, DEFAULT '{}' | 用户设置 |
referred_by |
UUID | NULLABLE, FK → profiles.id | 邀请人 ID |
created_at |
TIMESTAMPTZ | NOT NULL, DEFAULT now() | 创建时间 |
updated_at |
TIMESTAMPTZ | NOT NULL, DEFAULT now() | 更新时间 |
deleted_at |
TIMESTAMPTZ | NULLABLE | 软删时间 |
settings JSONB 结构:
{
"version": 1,
"preferences": {
"interface_language": "zh-CN",
"ai_language": "zh-CN",
"timezone": "Asia/Shanghai"
},
"agent_prompts": {
"INTENT_RECOGNITION": "自定义提示词...",
"TASK_EXECUTION": "自定义提示词..."
},
"privacy": {},
"notification": {}
}
memories
用户记忆。
| 字段 | 类型 | 约束 | 说明 |
|---|---|---|---|
id |
UUID | PK | 记忆 ID |
owner_id |
UUID | NOT NULL, FK → profiles.id | 所有者 ID |
memory_type |
VARCHAR(20) | NOT NULL, CHECK | 枚举:user, work |
title |
VARCHAR(255) | NOT NULL | 标题 |
content |
JSONB | NOT NULL | 记忆内容 |
source |
VARCHAR(20) | NOT NULL | 来源:manual, agent, imported |
status |
VARCHAR(20) | NOT NULL | 状态:active, disabled |
created_at |
TIMESTAMPTZ | NOT NULL, DEFAULT now() | 创建时间 |
updated_at |
TIMESTAMPTZ | NOT NULL, DEFAULT now() | 更新时间 |
content JSONB 示例:
// 用户记忆
{"type": "preference", "data": {"style": "concise", "language": "zh-CN"}}
// 工作记忆
{"type": "workflow_summary", "data": {"task": "代码审查", "learnings": ["优先检查安全漏洞"], "improvements": []}}
friendships
好友关系(双向规范化)。
| 字段 | 类型 | 约束 | 说明 |
|---|---|---|---|
id |
UUID | PK | 关系 ID |
user_low_id |
UUID | NOT NULL | 较小 UUID |
user_high_id |
UUID | NOT NULL | 较大 UUID |
initiator_id |
UUID | NOT NULL | 发起方用户 ID |
status |
VARCHAR(20) | NOT NULL, CHECK | 状态:pending, accepted, blocked, declined, canceled |
requested_at |
TIMESTAMPTZ | NOT NULL, DEFAULT now() | 请求时间 |
accepted_at |
TIMESTAMPTZ | NULLABLE | 接受时间 |
blocked_by |
UUID | NULLABLE | 阻止者用户 ID |
created_by |
UUID | NULLABLE | 创建者 |
updated_by |
UUID | NULLABLE | 更新者 |
created_at |
TIMESTAMPTZ | NOT NULL, DEFAULT now() | 创建时间 |
updated_at |
TIMESTAMPTZ | NOT NULL, DEFAULT now() | 更新时间 |
deleted_at |
TIMESTAMPTZ | NULLABLE | 软删时间 |
约束:
user_low_id < user_high_idUNIQUE(user_low_id, user_high_id)
groups
群组。
| 字段 | 类型 | 约束 | 说明 |
|---|---|---|---|
id |
UUID | PK | 群组 ID |
name |
VARCHAR(100) | NOT NULL | 群组名称 |
description |
TEXT | NULLABLE | 群组描述 |
owner_id |
UUID | NOT NULL, FK → profiles.id | 创建者 ID |
status |
VARCHAR(20) | NOT NULL, CHECK | 状态:active, archived |
created_by |
UUID | NULLABLE | 创建者 |
updated_by |
UUID | NULLABLE | 更新者 |
created_at |
TIMESTAMPTZ | NOT NULL, DEFAULT now() | 创建时间 |
updated_at |
TIMESTAMPTZ | NOT NULL, DEFAULT now() | 更新时间 |
deleted_at |
TIMESTAMPTZ | NULLABLE | 软删时间 |
group_members
群组成员。
| 字段 | 类型 | 约束 | 说明 |
|---|---|---|---|
id |
UUID | PK | 成员 ID |
group_id |
UUID | NOT NULL, FK → groups.id | 群组 ID |
user_id |
UUID | NOT NULL, FK → profiles.id | 用户 ID |
role |
VARCHAR(20) | NOT NULL, CHECK | 角色:owner, admin, member |
join_source |
VARCHAR(20) | NOT NULL | 加入方式:invited, joined |
invited_by |
UUID | NULLABLE, FK → profiles.id | 邀请人 ID |
joined_at |
TIMESTAMPTZ | NOT NULL, DEFAULT now() | 加入时间 |
removed_at |
TIMESTAMPTZ | NULLABLE | 移除时间 |
status |
VARCHAR(20) | NOT NULL, CHECK | 状态:active, muted, removed |
created_by |
UUID | NULLABLE | 创建者 |
updated_by |
UUID | NULLABLE | 更新者 |
created_at |
TIMESTAMPTZ | NOT NULL, DEFAULT now() | 创建时间 |
updated_at |
TIMESTAMPTZ | NOT NULL, DEFAULT now() | 更新时间 |
deleted_at |
TIMESTAMPTZ | NULLABLE | 软删时间 |
约束: UNIQUE(group_id, user_id)
schedule_items
日程事项。
| 字段 | 类型 | 约束 | 说明 |
|---|---|---|---|
id |
UUID | PK | 事项 ID |
owner_id |
UUID | NOT NULL, FK → profiles.id | 所有者 ID |
title |
VARCHAR(255) | NOT NULL | 标题 |
description |
TEXT | NULLABLE | 描述 |
start_at |
TIMESTAMPTZ | NOT NULL | 开始时间 |
end_at |
TIMESTAMPTZ | NULLABLE | 结束时间 |
timezone |
VARCHAR(50) | NOT NULL, DEFAULT 'UTC' | 时区 |
metadata |
JSONB | NOT NULL, DEFAULT '{}' | 扩展字段 |
recurrence_rule |
VARCHAR(255) | NULLABLE | 循环规则 |
source_type |
VARCHAR(20) | NOT NULL, CHECK | 来源:manual, imported, agent_generated |
status |
VARCHAR(20) | NOT NULL, CHECK | 状态:active, completed, canceled, archived |
created_by |
UUID | NULLABLE | 创建者 |
created_at |
TIMESTAMPTZ | NOT NULL, DEFAULT now() | 创建时间 |
updated_at |
TIMESTAMPTZ | NOT NULL, DEFAULT now() | 更新时间 |
deleted_at |
TIMESTAMPTZ | NULLABLE | 软删时间 |
metadata JSONB 结构:
{
"color": "#FF6B6B",
"location": "会议室A",
"notes": "记得提前准备投影仪",
"attachments": [
{
"name": "会议纪要.pdf",
"url": "https://...",
"visible_to": [],
"type": "document"
},
{
"name": "投影仪提醒",
"visible_to": ["uuid1"],
"type": "reminder",
"content": "记得带投影仪"
}
],
"version": 1
}
schedule_subscriptions
日程订阅与权限。
| 字段 | 类型 | 约束 | 说明 |
|---|---|---|---|
id |
UUID | PK | 订阅 ID |
item_id |
UUID | NOT NULL, FK → schedule_items.id | 日程事项 ID |
subscriber_id |
UUID | NOT NULL, FK → profiles.id | 订阅者 ID |
permission |
INTEGER | NOT NULL, CHECK, DEFAULT 1 | 权限位图(view=1, invite=2, edit=4) |
notify_level |
VARCHAR(20) | NOT NULL, DEFAULT 'all' | 通知级别:all, mentions, none |
status |
VARCHAR(20) | NOT NULL, DEFAULT 'active' | 状态:active, paused, unsubscribed |
created_by |
UUID | NULLABLE | 创建者 |
created_at |
TIMESTAMPTZ | NOT NULL, DEFAULT now() | 创建时间 |
updated_at |
TIMESTAMPTZ | NOT NULL, DEFAULT now() | 更新时间 |
约束:
UNIQUE(item_id, subscriber_id)permission BETWEEN 0 AND 7
inbox_messages
待处理消息(接收者视角)。
| 字段 | 类型 | 约束 | 说明 |
|---|---|---|---|
id |
UUID | PK | 消息 ID |
recipient_id |
UUID | NOT NULL, FK → profiles.id | 接收者 ID |
sender_id |
UUID | NULLABLE, FK → profiles.id | 发送者 ID(系统消息可为 NULL) |
message_type |
VARCHAR(20) | NOT NULL, CHECK | 类型:friend_request, calendar, system, group |
friendship_id |
UUID | NULLABLE, FK → friendships.id | 好友请求关联(friend_request 时必填) |
schedule_item_id |
UUID | NULLABLE, FK → schedule_items.id | 日程关联(calendar 时必填) |
group_id |
UUID | NULLABLE, FK → groups.id | 群组关联(group 时必填) |
content |
TEXT | NULLABLE | 消息内容(system 用) |
is_read |
BOOLEAN | NOT NULL, DEFAULT false | 是否已读 |
status |
VARCHAR(20) | NOT NULL, CHECK | 状态:pending, accepted, rejected, dismissed |
created_by |
UUID | NULLABLE | 创建者 |
created_at |
TIMESTAMPTZ | NOT NULL, DEFAULT now() | 创建时间 |
updated_at |
TIMESTAMPTZ | NOT NULL, DEFAULT now() | 更新时间 |
message_type 与业务字段对应:
| message_type | 必填字段 |
|---|---|
| friend_request | friendship_id |
| calendar | schedule_item_id |
| system | 全部可空 |
| group | group_id |
sender 约束: system 类型 sender_id 为空,其他类型 sender_id 必填
todos
待办事项。
| 字段 | 类型 | 约束 | 说明 |
|---|---|---|---|
id |
UUID | PK | 待办 ID |
owner_id |
UUID | NOT NULL, FK → profiles.id | 所有者 ID |
title |
VARCHAR(255) | NOT NULL | 标题 |
description |
VARCHAR(1000) | NULLABLE | 描述 |
due_at |
TIMESTAMPTZ | NULLABLE | 截止时间 |
priority |
INTEGER | NOT NULL, CHECK, DEFAULT 3 | 优先级(1-4,1=重要且紧急) |
status |
VARCHAR(20) | NOT NULL, CHECK | 状态:pending, done, canceled |
completed_at |
TIMESTAMPTZ | NULLABLE | 完成时间 |
created_by |
UUID | NULLABLE | 创建者 |
created_at |
TIMESTAMPTZ | NOT NULL, DEFAULT now() | 创建时间 |
updated_at |
TIMESTAMPTZ | NOT NULL, DEFAULT now() | 更新时间 |
deleted_at |
TIMESTAMPTZ | NULLABLE | 软删时间 |
约束: priority BETWEEN 1 AND 4
todo_sources
待办与日程来源关联。
| 字段 | 类型 | 约束 | 说明 |
|---|---|---|---|
id |
UUID | PK | 关联 ID |
todo_id |
UUID | NOT NULL, FK → todos.id ON DELETE CASCADE | 待办 ID |
schedule_item_id |
UUID | NOT NULL, FK → schedule_items.id ON DELETE CASCADE | 日程事项 ID |
created_at |
TIMESTAMPTZ | NOT NULL, DEFAULT now() | 创建时间 |
updated_at |
TIMESTAMPTZ | NOT NULL, DEFAULT now() | 更新时间 |
约束: UNIQUE(todo_id, schedule_item_id)
automation_jobs
自动化定时任务。
| 字段 | 类型 | 约束 | 说明 |
|---|---|---|---|
id |
UUID | PK | 任务 ID |
owner_id |
UUID | NOT NULL, FK → profiles.id | 所有者 ID |
title |
VARCHAR(255) | NOT NULL | 任务标题 |
prompt |
TEXT | NOT NULL | AI 执行 prompt |
schedule_type |
VARCHAR(20) | NOT NULL, CHECK | 调度类型:daily, weekly |
run_at |
TIMESTAMPTZ | NOT NULL | 首次运行时间 |
next_run_at |
TIMESTAMPTZ | NULLABLE | 下次运行时间 |
timezone |
VARCHAR(50) | NOT NULL, DEFAULT 'UTC' | 时区 |
last_run_at |
TIMESTAMPTZ | NULLABLE | 最近运行时间 |
status |
VARCHAR(20) | NOT NULL, CHECK | 状态:active, disabled |
created_by |
UUID | NULLABLE | 创建者 |
created_at |
TIMESTAMPTZ | NOT NULL, DEFAULT now() | 创建时间 |
updated_at |
TIMESTAMPTZ | NOT NULL, DEFAULT now() | 更新时间 |
deleted_at |
TIMESTAMPTZ | NULLABLE | 软删时间 |
约束: UNIQUE(id, owner_id)
agent_chat_sessions
Agent 对话会话。
| 字段 | 类型 | 约束 | 说明 |
|---|---|---|---|
id |
UUID | PK | 会话 ID |
user_id |
UUID | NOT NULL, FK → profiles.id | 用户 ID |
session_type |
VARCHAR(20) | NOT NULL, CHECK | 会话类型:chat, automation |
job_id |
UUID | NULLABLE, FK → automation_jobs.id ON DELETE RESTRICT | 自动化任务 ID(automation 时必填) |
title |
VARCHAR(255) | NULLABLE | 会话标题 |
status |
VARCHAR(20) | NOT NULL, CHECK | 状态:pending, running, completed, failed |
last_activity_at |
TIMESTAMPTZ | NULLABLE | 最后活跃时间 |
message_count |
INTEGER | NOT NULL, DEFAULT 0 | 消息计数 |
total_tokens |
INTEGER | NOT NULL, DEFAULT 0 | 总 token 数 |
total_cost |
NUMERIC(12,6) | NOT NULL, DEFAULT 0 | 总费用 |
created_at |
TIMESTAMPTZ | NOT NULL, DEFAULT now() | 创建时间 |
updated_at |
TIMESTAMPTZ | NOT NULL, DEFAULT now() | 更新时间 |
deleted_at |
TIMESTAMPTZ | NULLABLE | 软删时间 |
约束:
session_type='chat' → job_id IS NULLsession_type='automation' → job_id IS NOT NULL
agent_chat_messages
会话消息记录。
| 字段 | 类型 | 约束 | 说明 |
|---|---|---|---|
id |
UUID | PK | 消息 ID |
session_id |
UUID | NOT NULL, FK → agent_chat_sessions.id | 会话 ID |
seq |
INTEGER | NOT NULL | 消息序号 |
role |
VARCHAR(20) | NOT NULL, CHECK | 角色:user, assistant, system, tool |
content |
TEXT | NOT NULL | 消息内容 |
model_code |
VARCHAR(50) | NULLABLE | 模型标识 |
tool_name |
VARCHAR(100) | NULLABLE | 工具名称 |
input_tokens |
INTEGER | NOT NULL, DEFAULT 0 | 输入 token 数 |
output_tokens |
INTEGER | NOT NULL, DEFAULT 0 | 输出 token 数 |
cost |
NUMERIC(12,6) | NOT NULL, DEFAULT 0 | 费用 |
currency |
VARCHAR(3) | NOT NULL, DEFAULT 'USD' | 货币 |
latency_ms |
INTEGER | NULLABLE | 延迟(毫秒) |
metadata |
JSONB | NOT NULL, DEFAULT '{}' | 扩展字段 |
created_at |
TIMESTAMPTZ | NOT NULL, DEFAULT now() | 创建时间 |
updated_at |
TIMESTAMPTZ | NOT NULL, DEFAULT now() | 更新时间 |
deleted_at |
TIMESTAMPTZ | NULLABLE | 软删时间 |
约束: UNIQUE(session_id, seq)
llm_factory
LLM 工厂配置。
| 字段 | 类型 | 约束 | 说明 |
|---|---|---|---|
id |
UUID | PK | 工厂 ID |
name |
VARCHAR(50) | UNIQUE, NOT NULL | 工厂名称 |
request_url |
VARCHAR(255) | NOT NULL | API 请求 URL |
avatar |
TEXT | NULLABLE | 头像 URL |
created_at |
TIMESTAMPTZ | NOT NULL, DEFAULT now() | 创建时间 |
updated_at |
TIMESTAMPTZ | NOT NULL, DEFAULT now() | 更新时间 |
deleted_at |
TIMESTAMPTZ | NULLABLE | 软删时间 |
llms
LLM 模型实例。
| 字段 | 类型 | 约束 | 说明 |
|---|---|---|---|
id |
UUID | PK | 模型 ID |
factory_id |
UUID | NOT NULL, FK → llm_factory.id ON DELETE RESTRICT | 工厂 ID |
model_code |
VARCHAR(50) | UNIQUE, NOT NULL | 模型标识 |
created_at |
TIMESTAMPTZ | NOT NULL, DEFAULT now() | 创建时间 |
updated_at |
TIMESTAMPTZ | NOT NULL, DEFAULT now() | 更新时间 |
deleted_at |
TIMESTAMPTZ | NULLABLE | 软删时间 |
system_agents
系统级 Agent 配置(原 user_agent_catalog)。
| 字段 | 类型 | 约束 | 说明 |
|---|---|---|---|
agent_type |
VARCHAR(20) | PK, CHECK | Agent 类型 |
llm_id |
UUID | NOT NULL, FK → llms.id ON DELETE RESTRICT | 关联的 LLM 模型 |
status |
VARCHAR(20) | NOT NULL, CHECK | 状态:active, paused, migrating |
config |
JSONB | NOT NULL, DEFAULT '{}' | Agent 配置参数 |
created_at |
TIMESTAMPTZ | NOT NULL, DEFAULT now() | 创建时间 |
updated_at |
TIMESTAMPTZ | NOT NULL, DEFAULT now() | 更新时间 |
agent_type 枚举值:
INTENT_RECOGNITION- 意图识别TASK_EXECUTION- 任务执行RESULT_REPORTING- 结果报告
invite_codes
邀请码。
| 字段 | 类型 | 约束 | 说明 |
|---|---|---|---|
id |
UUID | PK | 邀请码 ID |
code |
VARCHAR(8) | UNIQUE, NOT NULL, CHECK | 邀请码(8 位大写字母数字) |
owner_id |
UUID | NOT NULL, FK → profiles.id | 拥有者 ID |
status |
VARCHAR(20) | NOT NULL, CHECK | 状态:active, disabled, expired |
used_count |
INTEGER | NOT NULL, DEFAULT 0, CHECK | 已使用次数 |
max_uses |
INTEGER | NULLABLE | 最大使用次数 |
expires_at |
TIMESTAMPTZ | NULLABLE | 过期时间 |
reward_config |
JSONB | NULLABLE | 奖励配置 |
created_at |
TIMESTAMPTZ | NOT NULL, DEFAULT now() | 创建时间 |
updated_at |
TIMESTAMPTZ | NOT NULL, DEFAULT now() | 更新时间 |
约束:
code符合[ABCDEFGHJKMNPQRSTUVWXYZ23456789]{8}used_count >= 0
外键删除策略
| 外键 | 删除策略 | 说明 |
|---|---|---|
agent_chat_sessions.job_id |
RESTRICT | 禁止删除正在使用的自动化任务 |
todo_sources.todo_id |
CASCADE | 删除待办时级联删除关联 |
todo_sources.schedule_item_id |
CASCADE | 删除日程时级联删除关联 |
inbox_messages.friendship_id |
CASCADE | 删除好友关系时级联删除消息 |
inbox_messages.schedule_item_id |
CASCADE | 删除日程时级联删除消息 |
inbox_messages.group_id |
CASCADE | 删除群组时级联删除消息 |
llms.factory_id |
RESTRICT | 禁止删除正在使用的工厂配置 |
system_agents.llm_id |
RESTRICT | 禁止删除正在使用的 LLM 模型 |
RLS 策略
所有 public 业务表默认启用 RLS:
anon: 全部 DENYauthenticated: 全部 DENYservice_role: 由后端服务连接,不依赖 RLS
例外: 迁移表 alembic_version 不暴露给任何角色。
Change Log
| 日期 | 变更 |
|---|---|
| 2026-03-06 | 删除 user_agents 表,重命名 user_agent_catalog → system_agents,更新 agent_chat_sessions / agent_chat_messages 表名,删除 memories.agent_id 字段 |
| 2026-02-28 | 新增 invite_codes 表、profiles.referred_by 字段 |
| 2026-02-26 | 初始版本,基于数据模型重设计 |