-- ============================================================ -- deep_agent 2.0 — MySQL 8.0 建表脚本 -- ============================================================ -- 设计约定(为了让存储层同时可跑 sqlite 开发档,见 schema_sqlite.sql): -- 1. 主键用 VARCHAR(64) 的 UUID,不用 AUTO_INCREMENT -- 2. 结构化数据(tool_calls / citations / snapshot)以 TEXT 存 JSON 字符串, -- 不用 MySQL 的 JSON 类型,避免方言函数 -- 3. 不用 ON DUPLICATE KEY UPDATE,upsert 在 Python 侧「先查后写」 -- 4. 时间列一律 DATETIME(6)(本地时间),不用 TIMESTAMP 的时区语义 -- -- 执行:mysql -u -p < db/mysql_schema.sql -- 或由应用启动时的 init_schema() 自动执行(幂等,全部 IF NOT EXISTS) -- ============================================================ -- ---------- 会话 ---------- CREATE TABLE IF NOT EXISTS sessions ( id VARCHAR(64) NOT NULL COMMENT '会话 ID(同时是 LangGraph thread_id)', title VARCHAR(255) NOT NULL DEFAULT '' COMMENT '会话标题,首轮自动生成', user_name VARCHAR(128) NOT NULL DEFAULT 'default' COMMENT '归属用户(2.0 无鉴权,由客户端自报)', mode VARCHAR(16) NOT NULL DEFAULT 'full' COMMENT '权限模式:plan | full', pinned TINYINT NOT NULL DEFAULT 0 COMMENT '是否置顶', created_at DATETIME(6) NOT NULL, updated_at DATETIME(6) NOT NULL, PRIMARY KEY (id), KEY idx_sessions_user_updated (user_name, updated_at), KEY idx_sessions_title (title) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='会话'; -- ---------- 消息 ---------- CREATE TABLE IF NOT EXISTS messages ( id VARCHAR(64) NOT NULL, session_id VARCHAR(64) NOT NULL, msg_role VARCHAR(16) NOT NULL COMMENT 'user | assistant', content MEDIUMTEXT NULL, tool_calls MEDIUMTEXT NULL COMMENT 'JSON 数组:本轮工具调用摘要', citations MEDIUMTEXT NULL COMMENT 'JSON 数组:本轮来源标注', created_at DATETIME(6) NOT NULL, PRIMARY KEY (id), KEY idx_messages_session_created (session_id, created_at) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='会话消息(事实源,冷启动据此补种图状态)'; -- ---------- 上下文用量 ---------- CREATE TABLE IF NOT EXISTS session_context_usage ( id VARCHAR(64) NOT NULL, session_id VARCHAR(64) NOT NULL, turn INT NOT NULL DEFAULT 0 COMMENT '第几轮(从 1 起)', input_tokens INT NOT NULL DEFAULT 0, output_tokens INT NOT NULL DEFAULT 0, cache_read_tokens INT NOT NULL DEFAULT 0, total_tokens INT NOT NULL DEFAULT 0, usage_source VARCHAR(16) NOT NULL DEFAULT 'provider' COMMENT 'provider=模型真实返回 | estimate=本地估算', compacted TINYINT NOT NULL DEFAULT 0 COMMENT '本轮是否触发了上下文压缩', compact_count INT NOT NULL DEFAULT 0 COMMENT '会话累计压缩次数', snapshot MEDIUMTEXT NULL COMMENT 'JSON:压缩前原文落盘路径、上下文窗口、阈值等', created_at DATETIME(6) NOT NULL, PRIMARY KEY (id), KEY idx_ctx_session_created (session_id, created_at) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='上下文用量明细(口径以模型真实 usage 为准)'; -- ---------- 历史消息压缩存档 ---------- CREATE TABLE IF NOT EXISTS context_archives ( id VARCHAR(64) NOT NULL, session_id VARCHAR(64) NOT NULL, turn INT NOT NULL DEFAULT 0, file_path VARCHAR(512) NOT NULL DEFAULT '' COMMENT '压缩前原文落盘的绝对路径', tokens INT NOT NULL DEFAULT 0 COMMENT '压缩前占用 token 估算', created_at DATETIME(6) NOT NULL, PRIMARY KEY (id), KEY idx_archive_session_created (session_id, created_at) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='压缩前原文存档索引,便于事后追溯'; -- ---------- 定时任务 ---------- CREATE TABLE IF NOT EXISTS schedules ( id VARCHAR(64) NOT NULL, user_name VARCHAR(128) NOT NULL DEFAULT 'default', title VARCHAR(255) NOT NULL DEFAULT '', cron VARCHAR(64) NOT NULL COMMENT '5 段 cron 表达式', prompt TEXT NOT NULL COMMENT '触发时喂给 agent 的指令', mode VARCHAR(16) NOT NULL DEFAULT 'full', enabled TINYINT NOT NULL DEFAULT 1, created_at DATETIME(6) NOT NULL, updated_at DATETIME(6) NOT NULL, PRIMARY KEY (id), KEY idx_schedules_enabled (enabled) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='定时任务定义'; CREATE TABLE IF NOT EXISTS schedule_runs ( id VARCHAR(64) NOT NULL, schedule_id VARCHAR(64) NOT NULL, thread_id VARCHAR(160) NOT NULL COMMENT '独立 thread:scheduled-task-{id}-{run_id}', status VARCHAR(24) NOT NULL COMMENT 'running | success | failed', started_at DATETIME(6) NOT NULL, finished_at DATETIME(6) NULL, error TEXT NULL, output MEDIUMTEXT NULL, PRIMARY KEY (id), KEY idx_runs_schedule_started (schedule_id, started_at) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='定时任务执行记录'; -- ---------- 计费 ---------- CREATE TABLE IF NOT EXISTS billing_usage ( id VARCHAR(64) NOT NULL, user_name VARCHAR(128) NOT NULL DEFAULT 'default', session_id VARCHAR(64) NOT NULL DEFAULT '', kind VARCHAR(24) NOT NULL DEFAULT 'chat' COMMENT 'chat | chat_only | resume | scheduled', model VARCHAR(128) NOT NULL DEFAULT '', input_tokens INT NOT NULL DEFAULT 0, output_tokens INT NOT NULL DEFAULT 0, total_tokens INT NOT NULL DEFAULT 0, cost DECIMAL(18,8) NOT NULL DEFAULT 0 COMMENT '按 billing_pricing 计价', usage_day CHAR(8) NOT NULL COMMENT 'YYYYMMDD,按请求开始时刻归属', trace_id VARCHAR(64) NOT NULL DEFAULT '', created_at DATETIME(6) NOT NULL, PRIMARY KEY (id), KEY idx_billing_user_day (user_name, usage_day), KEY idx_billing_session (session_id) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用量流水(每次请求一条)'; CREATE TABLE IF NOT EXISTS billing_pricing ( model VARCHAR(128) NOT NULL, input_price DECIMAL(18,8) NOT NULL DEFAULT 0 COMMENT '每 1K input token 单价', output_price DECIMAL(18,8) NOT NULL DEFAULT 0 COMMENT '每 1K output token 单价', currency VARCHAR(8) NOT NULL DEFAULT 'CNY', updated_at DATETIME(6) NOT NULL, PRIMARY KEY (model) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='模型单价表'; CREATE TABLE IF NOT EXISTS daily_quota ( user_name VARCHAR(128) NOT NULL, usage_day CHAR(8) NOT NULL, limit_tokens BIGINT NOT NULL DEFAULT 0 COMMENT '0 = 不限', used_tokens BIGINT NOT NULL DEFAULT 0, updated_at DATETIME(6) NOT NULL, PRIMARY KEY (user_name, usage_day) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='每用户每日额度与累计用量'; -- ---------- 用户偏好 ---------- CREATE TABLE IF NOT EXISTS user_preferences ( id VARCHAR(64) NOT NULL, user_name VARCHAR(128) NOT NULL, pref_key VARCHAR(128) NOT NULL, pref_value TEXT NOT NULL, updated_at DATETIME(6) NOT NULL, PRIMARY KEY (id), UNIQUE KEY uk_pref_user_key (user_name, pref_key) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用户偏好,新会话自动注入';