Files
Cyrene_v2/internal/db/migrations/0003_chat_history.up.sql
T
Aska 48421923f6 feat(history): 会话消息持久化 + 主/次级会话(design/16)
- runtime/history: Store + HistoryStore 接口(Append/List 游标分页/Recent/DeleteSession/NewSubSession/ListSessions),主会话固定 web、次级 web:<uuid>
- db 迁移 0003: chat_sessions + chat_messages + idx_chat_msgs_session_created(事务幂等)
- gateway: GET/POST /sessions、GET /sessions/{id}/messages 热分页、DELETE /sessions/{id}(主不可删 403);Deps.History 可空注入
- 编排层落库: session_persist.go(submitInternal 写用户消息、completeTurn 写助手消息,拒绝的消息不落库)
- WS: wsEvent 加 sessionId 定向 + history 回放帧(握手上行后回放主会话最新 50 条,thinking 剥离)
- wire.go 装配 History 到 gateway.Deps.History
- 端到端实测: POST /sessions 建次级 201 / GET /sessions 列表 / POST /chat 后 /messages 读到 user+assistant / DELETE 次级成功 / DELETE 主会话 403
2026-09-07 03:52:43 +08:00

32 lines
1.8 KiB
SQL

-- 0003_chat_history: persistent chat sessions + message stream (DevDocs/design/16 §2.1, §3.1).
-- chat_sessions records the persistent sessions: one fixed main session plus arbitrarily
-- many secondary (sub) sessions. chat_messages is the raw, durable message stream in
-- millisecond-timestamp cursor order. The two are the backend truth for the Web frontend;
-- they are NOT memory (design/16 §3.2 separates memory from the raw stream).
--
-- Its canonical schema is owned by internal/runtime/history, which reuses these tables. The
-- migration is the authoritative path; internal/runtime/history.NewStore re-issues the same
-- DDL idempotently so the store is self-contained (matching memory/session).
CREATE TABLE IF NOT EXISTS chat_sessions (
id TEXT PRIMARY KEY, -- main = fixed id ("web"); sub = "web:<uuid>"
type TEXT NOT NULL, -- 'main' | 'sub'
title TEXT NOT NULL DEFAULT '',
created_at INTEGER NOT NULL -- ms timestamp
);
CREATE TABLE IF NOT EXISTS chat_messages (
id TEXT PRIMARY KEY, -- message unique id (uuid)
session_id TEXT NOT NULL, -- owning session (main or sub)
role TEXT NOT NULL, -- user / assistant / system
content TEXT NOT NULL, -- raw message body (incl. <p>/<action>)
mode TEXT, -- behavior mode (optional, bubble render)
mood TEXT, -- mood (optional)
image TEXT, -- attachment base64/URL (optional)
thinking TEXT, -- chain of thought (optional, stored, not echoed by default)
created_at INTEGER NOT NULL -- ms timestamp (pagination cursor)
);
CREATE INDEX IF NOT EXISTS idx_chat_msgs_session_created
ON chat_messages (session_id, created_at DESC);