- 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
32 lines
1.8 KiB
SQL
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);
|