- bash is now Delegatable so named Agents may run shell commands - remove the legacy anonymous 'general' path entirely: SubAgentManager run_background/run_foreground_batch/run_inline/run_foreground, filter_tools/get_skills_prompt, TaskNotification direct delivery, DelegateContext task-local, background_permits/admission, and the delegate tool's check_task/cancel_task/list_tasks actions (agent_task replaces them); /stop and todo migrate off the task-local bridge - stop writing the legacy background_tasks table (read-only transition); /api/tasks union still renders historical records - ship a built-in general-purpose Agent definition (resources/agents) released to ~/.picobot/agents on first run like built-in skills, with bash/read-only/search/web/calculator/sleep tools; root_delegates now defaults to it so orchestration works out of the box - update AGENTS/README/architecture/config/db-schema docs accordingly
246 lines
14 KiB
Markdown
246 lines
14 KiB
Markdown
# PicoBot 数据库表结构
|
||
|
||
数据库为 SQLite,默认位于 workspace 下的 `picobot.db`。
|
||
|
||
连接启用 WAL、`synchronous=NORMAL`、foreign keys、5 秒 busy timeout,连接池最多 8 个连接。当前 `PRAGMA user_version=6`;启动时会在事务内补齐旧库字段和索引,遇到比程序更新的 schema version 会拒绝启动。
|
||
|
||
## sessions 表
|
||
|
||
会话表,一个 session 对应一个 (channel, chat_id, dialog_id) 组合。
|
||
|
||
| 字段 | 类型 | 说明 |
|
||
|------|------|------|
|
||
| `id` | TEXT PK | session ID,格式 `<channel>:<chat_id>:<dialog_id>` |
|
||
| `channel` | TEXT | 渠道名称 |
|
||
| `chat_id` | TEXT | 聊天/群组标识 |
|
||
| `dialog_id` | TEXT | 对话标识 |
|
||
| `title` | TEXT | 会话标题(默认 "新对话") |
|
||
| `created_at` | INTEGER | 创建时间(Unix 毫秒) |
|
||
| `last_active_at` | INTEGER | 最后活跃时间(Unix 毫秒) |
|
||
| `message_count` | INTEGER | 消息计数 |
|
||
| `routing_info` | TEXT | 路由信息 |
|
||
| `archived_at` | INTEGER | 归档时间(Unix 毫秒),NULL 表示未归档 |
|
||
| `deleted_at` | INTEGER | 软删除时间戳 |
|
||
| `last_consolidated_at` | INTEGER | 上次记忆归并时间 |
|
||
| `last_compressed_message_at` | INTEGER | 上次上下文压缩边界时间戳 |
|
||
| `delivery_context` | TEXT | 渠道声明的可跨 Turn 复用投递上下文 JSON(如飞书 thread/root 身份);一次性 reply/reaction ID 永不写入 |
|
||
| `delivery_context_updated_at` | INTEGER | delivery_context 最后更新时间 |
|
||
|
||
`session_turn_usage` 以 `turn_id` 幂等保存已提交 Turn 的 Provider usage,包括累计输入、输出、缓存输入、请求数和最后一次请求的 prompt tokens。它与 Turn 消息批次在同一事务中提交,供 WebUI 状态栏和 `/info` 使用;升级前历史无法可靠回填,因此统计起点以首条 usage 记录为准。
|
||
|
||
`(channel, chat_id, dialog_id)` 唯一。普通列表排除 `deleted_at`;是否包含归档记录由查询参数决定。
|
||
|
||
## messages 表
|
||
|
||
| 字段 | 类型 | 说明 |
|
||
|------|------|------|
|
||
| `id` | TEXT PK | 消息 UUID |
|
||
| `session_id` | TEXT FK | 所属会话,外键关联 sessions(id) |
|
||
| `seq` | INTEGER | 消息序号 |
|
||
| `role` | TEXT | 角色: user / assistant / tool / system |
|
||
| `content` | TEXT | 消息内容 |
|
||
| `media_refs` | TEXT | 多媒体引用 JSON |
|
||
| `tool_call_id` | TEXT | 工具调用 ID |
|
||
| `tool_name` | TEXT | 工具名称 |
|
||
| `tool_calls` | TEXT | 工具调用参数 JSON |
|
||
| `source` | TEXT | 消息来源(跨会话消息时标记来源 session_id) |
|
||
| `created_at` | INTEGER | 创建时间(Unix 毫秒) |
|
||
| `reasoning_content` | TEXT | 可展示的模型 reasoning(如有) |
|
||
| `provider_state` | TEXT | Provider 私有回放状态 JSON;只回放给匹配 Provider,不下发客户端或 Channel |
|
||
| `turn_id` | TEXT | 产生该消息的活动 Turn ID |
|
||
| `iteration` | INTEGER | Agent 工具循环中的迭代序号 |
|
||
| `completion_status` | TEXT | `completed` / `cancelled` / `interrupted`,旧数据默认 completed |
|
||
| `client_visibility` | TEXT | `visible` / `hidden`,默认 visible;hidden 只供模型回放(continuation 内部触发),客户端历史/投影/投递一律过滤 |
|
||
| `turn_origin` | TEXT | `user` / `agent_continuation` / `scheduled`,默认 user;客户端据此渲染"后台结果处理"标签而不创建用户气泡 |
|
||
|
||
`(session_id, seq)` 有唯一索引,防止并发写入重复序号。删除 session 会通过外键级联删除 messages。索引 `(session_id, client_visibility, seq)` 支撑按可见性分层查询。
|
||
|
||
## background_tasks 表(legacy 兼容,只读过渡)
|
||
|
||
旧 general(无 target)delegate 后台子任务表,由 legacy 适配器写入、`/api/tasks` 只读展示,等待一个版本观察后随旧适配器一起移除。具名 Agent 的后台运行不再写此表。`session_id` 不使用数据库外键,因为 session 使用软删除,关联关系由应用层维护。
|
||
|
||
| 字段 | 类型 | 说明 |
|
||
|------|------|------|
|
||
| `id` | TEXT PK | 后台任务 ID |
|
||
| `session_id` | TEXT | 所属会话 |
|
||
| `channel` | TEXT | 回传渠道 |
|
||
| `chat_id` | TEXT | 回传目标对话 |
|
||
| `prompt` | TEXT | 子任务提示 |
|
||
| `allowed_tools` | TEXT | 允许工具 JSON |
|
||
| `status` | TEXT | pending / running / completed / failed / cancelled |
|
||
| `result` | TEXT | 执行结果 |
|
||
| `error` | TEXT | 错误信息 |
|
||
| `tool_calls_count` | INTEGER | 工具调用次数 |
|
||
| `iterations` | INTEGER | Agent 迭代次数 |
|
||
| `started_at` | INTEGER | 开始时间 |
|
||
| `finished_at` | INTEGER | 结束时间 |
|
||
| `created_at` | INTEGER | 创建时间 |
|
||
|
||
## agent_run_groups 表(schema v6,Agent 编排)
|
||
|
||
批量委托的组头。单任务委托不建组;`completion_policy` 决定 background 完成事件形态(当前 background 批量未开放,组仅用于批量 foreground)。
|
||
|
||
| 字段 | 类型 | 说明 |
|
||
|------|------|------|
|
||
| `id` | TEXT PK | 组 ID |
|
||
| `root_session_id` | TEXT | 根会话(软删除,无级联外键,由应用层收敛) |
|
||
| `caller_run_id` | TEXT | 发起方 run ID(NULL 表示 Root 发起) |
|
||
| `caller_scope_id` | TEXT | 幂等作用域;Root 固定字面量 `"ROOT"` |
|
||
| `idempotency_key` | TEXT | 幂等键(当前工具未开放,预留) |
|
||
| `mode` | TEXT | foreground / background |
|
||
| `completion_policy` | TEXT | all / each |
|
||
| `expected_runs` / `terminal_runs` / `abnormal_runs` | INTEGER | 组内 run 计数 |
|
||
| `completion_slot_reserved` | INTEGER | 是否预留 background completion 槽 |
|
||
| `completion_delivery` / `failure_delivery` | TEXT | 组完成/失败投递 lane(queue/steer) |
|
||
| `status` | TEXT | queued / running / completed / partial / failed / timed_out / cancelled / interrupted |
|
||
| `deadline_at` / `runtime_generation` / `revision` | INTEGER | 截止、运行代、客户端投影修订号 |
|
||
| `created_at` / `updated_at` / `finished_at` | INTEGER | 时间线 |
|
||
|
||
## agent_runs 表(schema v6,Agent 编排)
|
||
|
||
每次具名委托(foreground 与 background 一致)先落库再执行;`execution_id` 条件更新保证迟到结果丢弃。
|
||
|
||
| 字段 | 类型 | 说明 |
|
||
|------|------|------|
|
||
| `id` | TEXT PK | run ID |
|
||
| `group_id` | TEXT FK | 所属组(RESTRICT) |
|
||
| `root_session_id` | TEXT | 根会话 |
|
||
| `parent_run_id` | TEXT FK | 父 run(RESTRICT),NULL 表示 Root 直接委托 |
|
||
| `caller_agent_id` / `caller_scope_id` | TEXT | 调用方身份;Root 的 caller_scope_id 固定 `"ROOT"` |
|
||
| `agent_id` / `definition_hash` / `provider_profile` | TEXT | Definition 快照(绑定运行代,运行中不热切换) |
|
||
| `provider_name` / `model_id` | TEXT | Provider 与模型 |
|
||
| `mode` | TEXT | foreground / background |
|
||
| `depth` | INTEGER | 委托深度(>=1) |
|
||
| `plan_item_id` | TEXT | 绑定计划子项(接纳时原子领取) |
|
||
| `execution_id` | TEXT | 执行尝试 ID,唯一索引 |
|
||
| `task` / `context_json` | TEXT | 任务与调用方上下文 |
|
||
| `budget_json` | TEXT | 树级剩余预算 |
|
||
| `signal_contract_json` / `signal_delivery` | TEXT | Definition 信号契约快照与投递 lane(queue/steer) |
|
||
| `completion_delivery` / `failure_delivery` | TEXT | 完成/失败投递 lane(当前单任务 background 恒为 queue,保留给批量) |
|
||
| `status` | TEXT | queued / running / waiting_children / completed / failed / timed_out / cancelled / interrupted |
|
||
| `result` / `error` | TEXT | 终态完整结果/错误(get_result 与 tool 结果同源) |
|
||
| `prompt_tokens` / `completion_tokens` / `cost` | INTEGER/REAL | Provider usage |
|
||
| `tool_calls_count` / `iterations` | INTEGER | 执行统计 |
|
||
| `runtime_generation` / `attempt` | INTEGER | 运行代与重试次数 |
|
||
| `completion_slot_reserved` | INTEGER | background 完成槽预留 |
|
||
| `deadline_at` / `started_at` / `finished_at` / `created_at` / `updated_at` | INTEGER | 时间线 |
|
||
| `revision` | INTEGER | 客户端投影修订号 |
|
||
|
||
索引:`execution_id` 唯一、`(root_session_id, caller_scope_id, idempotency_key)` 部分唯一、`(root_session_id, created_at DESC)`、`(parent_run_id, created_at)`、`(runtime_generation, status, deadline_at)`(恢复扫描)。
|
||
|
||
## agent_session_state 表(schema v6,Agent 编排)
|
||
|
||
每根会话一行,inbox 容量与客户端 revision 的权威计数:
|
||
|
||
| 字段 | 说明 |
|
||
|------|------|
|
||
| `root_session_id` | TEXT PK |
|
||
| `revision` | 单调客户端投影修订号 |
|
||
| `pending_event_count` | 未消费事件数(容量条件更新) |
|
||
| `reserved_completion_slots` | 已接纳 background run 预留的完成槽 |
|
||
| `updated_at` | 最后更新时间 |
|
||
|
||
容量判断在同一写事务内做条件 `UPDATE`(`pending + reserved + 新增 <= 上限`),杜绝并发 `COUNT(*)` 漂移。
|
||
|
||
## agent_inbox_events 表(schema v6,Agent 编排)
|
||
|
||
background 完成/信号投递的唯一事实源:`pending → leased → admitted → consumed`,失败按 token 释放回 pending,超限进 dead-letter,崩溃靠 lease 过期恢复。
|
||
|
||
| 字段 | 说明 |
|
||
|------|------|
|
||
| `id` | TEXT PK |
|
||
| `root_session_id` / `scope_kind` / `scope_id` | 归属(run 或 group,CHECK 互斥) |
|
||
| `run_id` / `group_id` | TEXT FK(RESTRICT) |
|
||
| `event_type` | signal / completion / group_completion |
|
||
| `event_key` | 去重键(signal 含冷却窗口 id) |
|
||
| `delivery` | queue / steer |
|
||
| `requires_continuation` | 是否反向启动 continuation Turn(cancel 产物为 false) |
|
||
| `severity` / `payload_json` | 信号级别与结构化载荷(completion 含 signal_ids) |
|
||
| `status` | pending / leased / admitted / consumed / superseded / dead_letter |
|
||
| `attempt_count` / `lease_token` / `lease_until` / `next_attempt_at` | 投递尝试与租约 |
|
||
| `admitted_turn_id` | steer 事件接纳的 Turn(/stop 按此条件释放) |
|
||
| `last_error` | 最近失败原因 |
|
||
| `revision` | 投影修订号 |
|
||
| `updated_at` | 最后更新时间 |
|
||
| `created_at` / `consumed_at` / `superseded_at` / `dead_lettered_at` / `fallback_notified_at` / `fallback_suppressed_reason` | 状态时间线 |
|
||
|
||
`(scope_kind, scope_id, event_type, event_key)` 唯一(signal 冷却窗去重)。消费/死信会同步递减 `agent_session_state.pending_event_count`。
|
||
|
||
## task_plans / task_items 表
|
||
|
||
`task_plans` 保存 session 级任务计划,通过部分唯一索引保证每个 session 最多一个 `status='active'` 的计划。`version` 在任何子项变化时递增,用于 WebSocket 快照排序和乐观并发检查。
|
||
|
||
`task_items` 以 `(plan_id, id)` 为复合主键,因此每个计划都可使用 `T1`、`T2` 等稳定显示 ID。子项状态为 `pending`、`in_progress`、`completed` 或 `blocked`;`executor_kind` 和 `execution_id` 将并行子 Agent 执行绑定到具体子项。只有 active plan 且 execution ID 匹配时,异步结果才能提交。
|
||
|
||
## memories 表
|
||
|
||
长期记忆存储。
|
||
|
||
| 字段 | 类型 | 说明 |
|
||
|------|------|------|
|
||
| `id` | TEXT PK | 记忆 UUID |
|
||
| `key` | TEXT UNIQUE | 记忆唯一键 |
|
||
| `content` | TEXT | 记忆内容 |
|
||
| `category` | TEXT | 类别: knowledge / timeline |
|
||
| `importance` | REAL | 重要性权重 (0-1) |
|
||
| `session_id` | TEXT | 关联会话 |
|
||
| `created_at` | TEXT | 创建时间 |
|
||
| `updated_at` | TEXT | 更新时间 |
|
||
|
||
配套 FTS5 全文索引虚拟表 `memory_fts(key, content)`,用于关键词搜索,通过触发器自动同步。
|
||
|
||
## scheduled_jobs 表
|
||
|
||
| 字段 | 类型 | 说明 |
|
||
|------|------|------|
|
||
| `id` | TEXT PK | 任务 UUID |
|
||
| `name` | TEXT | 任务名称 |
|
||
| `schedule` | TEXT | 调度规则 JSON(at/every/cron) |
|
||
| `prompt` | TEXT | 任务提示词 |
|
||
| `channel` | TEXT | 执行渠道 |
|
||
| `chat_id` | TEXT | 目标对话 |
|
||
| `model` | TEXT | 可选模型标记;当前会存储/展示,但 Scheduler 执行仍使用默认 Agent 模型 |
|
||
| `enabled` | INTEGER | 是否启用 (1/0) |
|
||
| `delete_after_run` | INTEGER | 执行后自动删除 (1/0) |
|
||
| `next_run_at` | INTEGER | 下次执行时间 |
|
||
| `last_run_at` | INTEGER | 上次执行时间 |
|
||
| `last_status` | TEXT | 上次执行状态 |
|
||
| `last_error` | TEXT | 上次错误信息 |
|
||
| `locked_at` | INTEGER | 本次领取时间 |
|
||
| `lock_owner` | TEXT | 领取任务的 Scheduler owner UUID |
|
||
| `lease_until` | INTEGER | 租约到期时间;进程崩溃后允许其他实例重新领取 |
|
||
| `created_at` | INTEGER | 创建时间(Unix 毫秒) |
|
||
| `updated_at` | INTEGER | 更新时间(Unix 毫秒) |
|
||
|
||
Scheduler 使用原子 `UPDATE ... RETURNING` 领取到期任务。任务结果、下次运行时间和租约释放在同一事务中提交,并校验 owner,防止过期 worker 覆盖已恢复的任务。
|
||
|
||
## job_runs 表
|
||
|
||
| 字段 | 类型 | 说明 |
|
||
|------|------|------|
|
||
| `id` | INTEGER PK | 自增 ID |
|
||
| `job_id` | TEXT FK | 关联任务,外键关联 scheduled_jobs(id) |
|
||
| `started_at` | INTEGER | 开始时间 |
|
||
| `finished_at` | INTEGER | 结束时间 |
|
||
| `status` | TEXT | 执行状态 |
|
||
| `output` | TEXT | 执行输出 |
|
||
| `error` | TEXT | 错误信息 |
|
||
| `duration_ms` | INTEGER | 耗时(毫秒) |
|
||
|
||
## llm_calls 表
|
||
|
||
记录所有 LLM API 调用的请求/响应详情,自动保留最近 1000 条。
|
||
|
||
| 字段 | 类型 | 说明 |
|
||
|------|------|------|
|
||
| `id` | INTEGER PK | 自增 ID |
|
||
| `created_at` | INTEGER | 调用时间 |
|
||
| `provider` | TEXT | 提供商类型 |
|
||
| `model` | TEXT | 模型名称 |
|
||
| `request_body` | TEXT | 请求摘要 JSON;旧记录可能是完整请求体 |
|
||
| `response_body` | TEXT | 响应体 JSON |
|
||
| `error` | TEXT | 错误信息 |
|
||
| `duration_ms` | INTEGER | 耗时(毫秒) |
|
||
|
||
旧数据中的 `request_body`/`response_body` 可能包含用户内容,排障和导出数据库时应按敏感数据处理。新 Provider 请求的 `request_body` 只保存模型、消息数、工具数和 stream 标志等摘要;错误响应仍可能包含服务端回显内容。
|