Files
memind/conversation-repair.test.mjs

100 lines
3.2 KiB
JavaScript

import test from 'node:test';
import assert from 'node:assert/strict';
import {
buildConversationFromDbRows,
countNonEmptyConversationMessages,
filterUserVisibleConversation,
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');
});
test('filterUserVisibleConversation keeps messages without explicit userVisible flag', () => {
const messages = [
{ role: 'user', content: [{ type: 'text', text: '请记住别名' }] },
{ role: 'assistant', metadata: { userVisible: true }, content: [{ type: 'text', text: '已记住' }] },
{ role: 'system', metadata: { userVisible: false }, content: [{ type: 'text', text: 'hidden' }] },
];
const visible = filterUserVisibleConversation(messages);
assert.equal(visible.length, 2);
assert.equal(visible[0].role, 'user');
assert.equal(visible[1].role, 'assistant');
});