fix: SQLite 持久化 files 和 _videos,历史记录不再丢失视频指示牌和文件
- ALTER TABLE 新增 attachments TEXT 列 - saveMessage 序列化 files/_videos 为 JSON - getMessages 反序列化还原
This commit is contained in:
@@ -223,8 +223,10 @@ export async function initDatabase(): Promise<SQL.Database> {
|
|||||||
CREATE INDEX IF NOT EXISTS idx_skills_updated ON skills(updated_at DESC);
|
CREATE INDEX IF NOT EXISTS idx_skills_updated ON skills(updated_at DESC);
|
||||||
`);
|
`);
|
||||||
|
|
||||||
// 兼容迁移:为已有 messages 表补充 prompt_eval_count 列(新库已有,旧库需要 ALTER)
|
// 兼容迁移:为已有 messages 表补充 attachments 列(文件/视频等附件 JSON)
|
||||||
try { db.run('ALTER TABLE messages ADD COLUMN prompt_eval_count INTEGER'); } catch { /* 列已存在,忽略 */ }
|
try { db.run('ALTER TABLE messages ADD COLUMN attachments TEXT'); } catch { /* 列已存在,忽略 */ }
|
||||||
|
|
||||||
|
// 兼容迁移:为已有 messages 表补充 prompt_eval_count 列
|
||||||
|
|
||||||
// 兼容迁移:为已有 skills 表补充 summary 列
|
// 兼容迁移:为已有 skills 表补充 summary 列
|
||||||
try { db.run("ALTER TABLE skills ADD COLUMN summary TEXT DEFAULT ''"); } catch { /* 列已存在,忽略 */ }
|
try { db.run("ALTER TABLE skills ADD COLUMN summary TEXT DEFAULT ''"); } catch { /* 列已存在,忽略 */ }
|
||||||
@@ -272,6 +274,7 @@ export interface MessageRow {
|
|||||||
images: string | null;
|
images: string | null;
|
||||||
tool_calls: string | null;
|
tool_calls: string | null;
|
||||||
tool_name: string | null;
|
tool_name: string | null;
|
||||||
|
attachments: string | null;
|
||||||
eval_count: number | null;
|
eval_count: number | null;
|
||||||
prompt_eval_count: number | null;
|
prompt_eval_count: number | null;
|
||||||
total_duration: number | null;
|
total_duration: number | null;
|
||||||
@@ -374,10 +377,10 @@ export function clearAllSessions(): void {
|
|||||||
|
|
||||||
export function saveMessage(msg: MessageRow): string {
|
export function saveMessage(msg: MessageRow): string {
|
||||||
const d = getDb();
|
const d = getDb();
|
||||||
runExec(d, `INSERT OR REPLACE INTO messages (id, session_id, role, content, thinking, images, tool_calls, tool_name, eval_count, prompt_eval_count, total_duration, created_at)
|
runExec(d, `INSERT OR REPLACE INTO messages (id, session_id, role, content, thinking, images, tool_calls, tool_name, attachments, eval_count, prompt_eval_count, total_duration, created_at)
|
||||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
|
||||||
[msg.id, msg.session_id, msg.role, msg.content, msg.thinking, msg.images,
|
[msg.id, msg.session_id, msg.role, msg.content, msg.thinking, msg.images,
|
||||||
msg.tool_calls, msg.tool_name, msg.eval_count, msg.prompt_eval_count, msg.total_duration, msg.created_at]
|
msg.tool_calls, msg.tool_name, msg.attachments, msg.eval_count, msg.prompt_eval_count, msg.total_duration, msg.created_at]
|
||||||
);
|
);
|
||||||
persist();
|
persist();
|
||||||
return msg.id;
|
return msg.id;
|
||||||
|
|||||||
@@ -89,6 +89,7 @@ export class ChatDB {
|
|||||||
images: msg.images?.length ? JSON.stringify(msg.images) : null,
|
images: msg.images?.length ? JSON.stringify(msg.images) : null,
|
||||||
tool_calls: msg.toolCalls?.length ? JSON.stringify(msg.toolCalls) : null,
|
tool_calls: msg.toolCalls?.length ? JSON.stringify(msg.toolCalls) : null,
|
||||||
tool_name: null,
|
tool_name: null,
|
||||||
|
attachments: JSON.stringify({ files: msg.files, videos: (msg as any)._videos }),
|
||||||
eval_count: msg.eval_count || null,
|
eval_count: msg.eval_count || null,
|
||||||
prompt_eval_count: msg.prompt_eval_count || null,
|
prompt_eval_count: msg.prompt_eval_count || null,
|
||||||
total_duration: msg.total_duration || null,
|
total_duration: msg.total_duration || null,
|
||||||
@@ -106,7 +107,10 @@ export class ChatDB {
|
|||||||
const row = await dbBridge().getSession(id);
|
const row = await dbBridge().getSession(id);
|
||||||
if (!row) return null;
|
if (!row) return null;
|
||||||
const msgRows = await dbBridge().getMessages(id);
|
const msgRows = await dbBridge().getMessages(id);
|
||||||
const messages = msgRows.map((r: any) => ({
|
const messages = msgRows.map((r: any) => {
|
||||||
|
let files, videos;
|
||||||
|
try { const a = JSON.parse(r.attachments || '{}'); files = a.files; videos = a.videos; } catch { /* ignore */ }
|
||||||
|
return {
|
||||||
role: r.role,
|
role: r.role,
|
||||||
content: r.content || '',
|
content: r.content || '',
|
||||||
timestamp: r.created_at,
|
timestamp: r.created_at,
|
||||||
@@ -115,8 +119,11 @@ export class ChatDB {
|
|||||||
eval_count: r.eval_count || undefined,
|
eval_count: r.eval_count || undefined,
|
||||||
prompt_eval_count: r.prompt_eval_count || undefined,
|
prompt_eval_count: r.prompt_eval_count || undefined,
|
||||||
total_duration: r.total_duration || undefined,
|
total_duration: r.total_duration || undefined,
|
||||||
toolCalls: r.tool_calls ? JSON.parse(r.tool_calls) : undefined
|
toolCalls: r.tool_calls ? JSON.parse(r.tool_calls) : undefined,
|
||||||
}));
|
...(files?.length && { files }),
|
||||||
|
...(videos?.length && { _videos: videos })
|
||||||
|
};
|
||||||
|
});
|
||||||
return {
|
return {
|
||||||
id: row.id,
|
id: row.id,
|
||||||
title: row.title,
|
title: row.title,
|
||||||
|
|||||||
Reference in New Issue
Block a user