Files
memind/conversation-repair.test.mjs
john 614837e199 fix: repair chat history from DB when Goose session has empty placeholders
Portal direct chat → goosed escalation can leave hollow Goose messages while
h5_conversation_messages retains the full dialogue. Backfill session detail
from DB, extend snapshot list fallback, and keep stored session id on transient
boot failures so refresh no longer looks like a blank new chat.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-05 11:04:25 +08:00

87 lines
2.6 KiB
JavaScript

import test from 'node:test';
import assert from 'node:assert/strict';
import {
buildConversationFromDbRows,
countNonEmptyConversationMessages,
parseStoredConversationRow,
repairConversationFromDbRows,
shouldRepairConversationFromDb,
} from './conversation-repair.mjs';
const gooseMsg = (id, role, text) => ({
id,
role,
metadata: { userVisible: true },
content: text ? [{ type: 'text', text }] : [],
});
test('parseStoredConversationRow prefers raw_json', () => {
const row = {
message_key: 'abc',
role: 'user',
text: 'fallback',
raw_json: JSON.stringify({
id: 'abc',
role: 'user',
content: [{ type: 'text', text: 'from raw' }],
metadata: { userVisible: true, displayText: '可见文案' },
}),
created_at: 1_700_000_000_000,
};
const parsed = parseStoredConversationRow(row);
assert.equal(parsed.content[0].text, 'from raw');
assert.equal(parsed.metadata.displayText, '可见文案');
});
test('shouldRepairConversationFromDb when goose has empty placeholders', () => {
const goose = [
gooseMsg('u1', 'user', '编排前缀'),
gooseMsg('a1', 'assistant', '好的'),
gooseMsg('msg_empty1', 'assistant', ''),
gooseMsg('msg_empty2', 'user', ''),
];
const dbRows = [
{
message_key: 'u-real',
role: 'user',
text: '小朋友在上海读初中',
created_at: 1,
sequence_no: 0,
},
{
message_key: 'a-real',
role: 'assistant',
text: '关于中考选择的分析…',
created_at: 2,
sequence_no: 1,
},
];
assert.equal(shouldRepairConversationFromDb(goose, dbRows), true);
const repaired = repairConversationFromDbRows(goose, dbRows);
assert.equal(countNonEmptyConversationMessages(repaired), 2);
assert.match(repaired[0].content[0].text, /上海读初中/);
assert.match(repaired[1].content[0].text, /中考/);
});
test('shouldRepairConversationFromDb returns false when goose is complete', () => {
const goose = [
gooseMsg('u1', 'user', 'hello'),
gooseMsg('a1', 'assistant', 'hi there'),
];
const dbRows = [
{ message_key: 'u1', role: 'user', text: 'hello', created_at: 1, sequence_no: 0 },
];
assert.equal(shouldRepairConversationFromDb(goose, dbRows), false);
});
test('buildConversationFromDbRows dedupes by message_key', () => {
const rows = [
{ message_key: 'same', role: 'user', text: 'first', created_at: 1, sequence_no: 0 },
{ message_key: 'same', role: 'user', text: 'second', created_at: 2, sequence_no: 0 },
];
const built = buildConversationFromDbRows(rows);
assert.equal(built.length, 1);
assert.equal(built[0].content[0].text, 'second');
});