feat(chat): chat_messages.turn_id 列 + DTO(写入接线留待下一步)
迁移 0018:ALTER TABLE chat_messages ADD COLUMN turn_id TEXT NOT NULL DEFAULT ''
(与 persona_id / client_msg_id / document 同族:不用 NULL,空串 = 不属于任何已知回合 ⇒ 旧行零迁移、键省略)。
存储层全链路带 turn_id(列清单唯一一份 ⇒ List/ListAfter/Recent/Search/FindByClientMsgID 自动同源);
新增 history/turn_id.go:ensureTurnIDColumn(既有库幂等前滚)+ SetMessagesTurnID
(第二段补写:单事务参数化、先到先得 WHERE turn_id = ''、幂等、未知 id 忽略)。
DTO:historyMessage.TurnID(json turnId,omitempty)⇒ REST 列表 / admin 渠道日志 / WS 握手回放 /
message_persisted / channel_persisted / message_edited 一次全覆盖。
写入面:persistUserMessages 读 ctx 回合标识;persistAssistantReply 增可选尾参(既有调用点零改动);
withTurnID / turnIDFrom / assignTurnID / turnIDOfLeg。
⚠️ 编排器把 turnId 交给落库的 4 处(新起一路 / 续跑路 / 被 steer 吃进 / 助手回复)尚未接线
(那些文件当时被另一路占用);当前生产行为 turn_id 仍为 ''。清单已在切片报告里精确到文件:行。
13 新用例 + 5 条变异(INSERT 不带列 / DTO 不回填 / 去掉 omitempty / 去掉先到先得 / 不回滚前滚)。
为守 session_persist.go ≤500 行,turnId 一节拆到新文件 session_turn_id.go。
This commit is contained in:
1 parent
354b08a45f
commit
d64b26d499
12 files changed
+950
-16
No files matched your search
@@ -167,9 +167,9 @@ func NewStore(ctx context.Context, db *sql.DB, log *slog.Logger, opts ...StoreOp
|
||||
}
|
||||
log = logger.WithSource(discardLogger(log), "history")
|
||||
// 顺序不能反:createMessagesTable 对全新库已含 client_msg_id,随后
|
||||
// ensureMessageColumns 把早于这些列(client_msg_id 与 document)建出的既有表
|
||||
// 前滚(幂等),最后才建索引 —— 部分唯一索引引用 client_msg_id,列还不存在时
|
||||
// 建它必然失败。
|
||||
// ensureMessageColumns 把早于这些列(client_msg_id / document / turn_id)建出的
|
||||
// 既有表前滚(幂等),最后才建索引 —— 部分唯一索引引用 client_msg_id,列还不
|
||||
// 存在时建它必然失败。
|
||||
for _, ddl := range []string{
|
||||
createSessionsTable,
|
||||
createMessagesTable,
|
||||
@@ -244,8 +244,8 @@ func (s *Store) insert(ctx context.Context, msg Message) (Message, error) {
|
||||
s.ensureTitle(ctx, msg.SessionID, msg.Content)
|
||||
}
|
||||
query := `INSERT INTO chat_messages
|
||||
(id, session_id, role, content, mode, mood, image, document, thinking, platform, device_id, sender_name, adapter_id, persona_id, client_msg_id, created_at)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`
|
||||
(id, session_id, role, content, mode, mood, image, document, thinking, platform, device_id, sender_name, adapter_id, persona_id, client_msg_id, turn_id, created_at)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`
|
||||
if msg.ClientMsgID != "" {
|
||||
query += ` ON CONFLICT DO NOTHING`
|
||||
}
|
||||
@@ -257,7 +257,7 @@ func (s *Store) insert(ctx context.Context, msg Message) (Message, error) {
|
||||
res, err := tx.ExecContext(ctx, query,
|
||||
msg.ID, msg.SessionID, msg.Role, msg.Content, msg.Mode, msg.Mood, msg.Image,
|
||||
msg.Document, msg.Thinking, msg.Platform, msg.DeviceID, msg.SenderName, msg.AdapterID,
|
||||
msg.PersonaID, msg.ClientMsgID, msg.CreatedAt)
|
||||
msg.PersonaID, msg.ClientMsgID, msg.TurnID, msg.CreatedAt)
|
||||
if err != nil {
|
||||
return Message{}, fmt.Errorf("history: append %s to %s: %w", msg.Role, msg.SessionID, err)
|
||||
}
|
||||
@@ -347,13 +347,13 @@ func (s *Store) ensureMainSession(ctx context.Context) error {
|
||||
// **唯一**一份列清单(位置顺序必须与 scanMessage 的 Scan 完全一致)。
|
||||
// 它刻意只写一次:此前七个查询各抄一份,加一列就得改七处,漏一处就只会在
|
||||
// 运行时以「扫描到的列数与列不清单不符」炸掉;共用常量让漏改成为不可能。
|
||||
const messageColumns = `id, session_id, role, content, mode, mood, image, document, thinking, platform, device_id, sender_name, adapter_id, persona_id, client_msg_id, created_at`
|
||||
const messageColumns = `id, session_id, role, content, mode, mood, image, document, thinking, platform, device_id, sender_name, adapter_id, persona_id, client_msg_id, turn_id, created_at`
|
||||
|
||||
// scanMessage 读取一行 chat_messages。消息各列按位置扫描,顺序见 messageColumns。
|
||||
func scanMessage(sc rowScanner) (Message, error) {
|
||||
var m Message
|
||||
var mode, mood, platform, deviceID, senderName, adapterID string
|
||||
if err := sc.Scan(&m.ID, &m.SessionID, &m.Role, &m.Content, &mode, &mood, &m.Image, &m.Document, &m.Thinking, &platform, &deviceID, &senderName, &adapterID, &m.PersonaID, &m.ClientMsgID, &m.CreatedAt); err != nil {
|
||||
if err := sc.Scan(&m.ID, &m.SessionID, &m.Role, &m.Content, &mode, &mood, &m.Image, &m.Document, &m.Thinking, &platform, &deviceID, &senderName, &adapterID, &m.PersonaID, &m.ClientMsgID, &m.TurnID, &m.CreatedAt); err != nil {
|
||||
return Message{}, err
|
||||
}
|
||||
m.Mode, m.Mood, m.Platform, m.DeviceID, m.SenderName, m.AdapterID = mode, mood, platform, deviceID, senderName, adapterID
|
||||
@@ -420,6 +420,7 @@ CREATE TABLE IF NOT EXISTS chat_messages (
|
||||
adapter_id TEXT NOT NULL DEFAULT '',
|
||||
persona_id TEXT NOT NULL DEFAULT '',
|
||||
client_msg_id TEXT NOT NULL DEFAULT '',
|
||||
turn_id TEXT NOT NULL DEFAULT '',
|
||||
created_at INTEGER NOT NULL
|
||||
)`
|
||||
|
||||
|
||||
Reference in new issue
Block a user