mirror of
https://github.com/n8n-io/n8n.git
synced 2026-10-17 05:29:44 +02:00
chore: Centralize conversation-history message ordering (#39599)
Co-authored-by: n8n-cat-bot[bot] <n8n-cat-bot[bot]@users.noreply.github.com>
This commit is contained in:
parent
29b9421518
commit
ea66d19c5e
|
|
@ -427,6 +427,40 @@ describe('InstanceAiConversationHistoryRepository', () => {
|
|||
});
|
||||
});
|
||||
|
||||
it('uses the same id tie-break for search, opening messages, and windows', async () => {
|
||||
const threadId = await createThread({ withOpeningMessage: false });
|
||||
const createdAt = at(9000);
|
||||
for (const id of ['msg-bbb', 'msg-ccc', 'msg-aaa']) {
|
||||
await createMessage({
|
||||
threadId,
|
||||
id,
|
||||
role: 'user',
|
||||
content: userContent('deploy'),
|
||||
createdAt,
|
||||
});
|
||||
}
|
||||
|
||||
const matches = await repository.findSearchMatchRows([threadId], 'deploy', 2);
|
||||
const first = await repository.findFirstUserMessages([threadId]);
|
||||
const tail = await repository.getConversationWindow({
|
||||
threadId,
|
||||
before: 2,
|
||||
after: 0,
|
||||
project: (row) => row,
|
||||
});
|
||||
const head = await repository.getConversationWindow({
|
||||
threadId,
|
||||
before: 0,
|
||||
after: 2,
|
||||
project: (row) => row,
|
||||
});
|
||||
|
||||
expect(matches.get(threadId)?.map((row) => row.id)).toEqual(['msg-ccc', 'msg-bbb']);
|
||||
expect(first.get(threadId)?.id).toBe('msg-aaa');
|
||||
expect(tail.rows.map((row) => row.id)).toEqual(['msg-bbb', 'msg-ccc']);
|
||||
expect(head.rows.map((row) => row.id)).toEqual(['msg-aaa', 'msg-bbb']);
|
||||
});
|
||||
|
||||
describe('findMessageInThread', () => {
|
||||
it('finds a conversation row and ignores rows of other threads', async () => {
|
||||
const threadId = await createThread({ title: 'Anchors' });
|
||||
|
|
|
|||
|
|
@ -123,14 +123,12 @@ export class InstanceAiConversationHistoryRepository {
|
|||
if (maxRowsPerThread <= 0) return byThread;
|
||||
|
||||
for (const threadId of threadIds) {
|
||||
const rows = await this.messages()
|
||||
const rows = await this.orderMessages(this.messages(), 'DESC')
|
||||
.where('m.threadId = :threadId', { threadId })
|
||||
.andWhere(buildMessageMatchCondition('m'), {
|
||||
pattern: buildSearchLikePattern(query),
|
||||
askUserMarker: ASK_USER_CONTENT_MARKER,
|
||||
})
|
||||
.orderBy('m.createdAt', 'DESC')
|
||||
.addOrderBy('m.id', 'DESC')
|
||||
.take(maxRowsPerThread)
|
||||
.getMany();
|
||||
byThread.set(threadId, rows);
|
||||
|
|
@ -146,11 +144,9 @@ export class InstanceAiConversationHistoryRepository {
|
|||
async findFirstUserMessages(threadIds: string[]): Promise<Map<string, InstanceAiMessage>> {
|
||||
const byThread = new Map<string, InstanceAiMessage>();
|
||||
for (const threadId of threadIds) {
|
||||
const row = await this.messages()
|
||||
const row = await this.orderMessages(this.messages(), 'ASC')
|
||||
.where('m.threadId = :threadId', { threadId })
|
||||
.andWhere("m.role = 'user'")
|
||||
.orderBy('m.createdAt', 'ASC')
|
||||
.addOrderBy('m.id', 'ASC')
|
||||
.take(1)
|
||||
.getOne();
|
||||
if (row) byThread.set(threadId, row);
|
||||
|
|
@ -309,11 +305,7 @@ export class InstanceAiConversationHistoryRepository {
|
|||
|
||||
const sqlOrder = direction === 'older' ? 'DESC' : 'ASC';
|
||||
const fetchLimit = limit * WINDOW_OVERFETCH_FACTOR + 1;
|
||||
const fetched = await qb
|
||||
.orderBy('m.createdAt', sqlOrder)
|
||||
.addOrderBy('m.id', sqlOrder)
|
||||
.take(fetchLimit)
|
||||
.getMany();
|
||||
const fetched = await this.orderMessages(qb, sqlOrder).take(fetchLimit).getMany();
|
||||
|
||||
const rows: T[] = [];
|
||||
let moreVisibleFetched = false;
|
||||
|
|
@ -341,6 +333,10 @@ export class InstanceAiConversationHistoryRepository {
|
|||
.andWhere(buildVisibleRowCondition('m'), VISIBLE_ROW_MARKERS);
|
||||
}
|
||||
|
||||
private orderMessages(qb: SelectQueryBuilder<InstanceAiMessage>, order: 'ASC' | 'DESC') {
|
||||
return qb.orderBy('m.createdAt', order).addOrderBy('m.id', order);
|
||||
}
|
||||
|
||||
private threads(): SelectQueryBuilder<InstanceAiThread> {
|
||||
return this.dataSource.createQueryBuilder(InstanceAiThread, 't');
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user