fix(api): return assistant messages with parents before children
getThread ordered purely by created_at, which is second-granular on MySQL and SQLite. A user turn and the assistant reply routinely land in the same second, so their relative order was whatever the storage engine returned. The client rebuilds the conversation tree from parent_id, so a child ahead of its parent corrupts the thread. Adds an id tiebreaker for a deterministic database order, then a stable topological pass that guarantees parents precede children while preserving sibling order. Dangling parent references are treated as roots and cycles are appended, so no message is ever dropped.
This commit is contained in:
3 files changed
+119
-2
No files matched your search
@@ -29,6 +29,7 @@ import {
|
||||
|
||||
import type { createTRPCContext } from "../trpc";
|
||||
import { fetchOpenRouterGenerationTelemetryAsync } from "../assistant-generation-telemetry";
|
||||
import { orderMessagesByParent } from "../assistant-message-order";
|
||||
import { verifyAssistantGenerationAccessToken } from "../assistant-generation-access";
|
||||
import { createTRPCRouter, isDemoMode, permissionRequiredProcedure, protectedProcedure } from "../trpc";
|
||||
import { boardRouter } from "./board";
|
||||
@@ -710,11 +711,13 @@ export const assistantRouter = createTRPCRouter({
|
||||
const thread = await ownedThreadAsync(ctx.db, input.threadId, ctx.session.user.id);
|
||||
const messages = await ctx.db.query.assistantMessages.findMany({
|
||||
where: eq(assistantMessages.threadId, thread.id),
|
||||
orderBy: assistantMessages.createdAt,
|
||||
// `created_at` is only second-granular on MySQL and SQLite, so sibling messages written in the
|
||||
// same second tie. The id tiebreaker makes the database order at least deterministic.
|
||||
orderBy: [asc(assistantMessages.createdAt), asc(assistantMessages.id)],
|
||||
});
|
||||
return {
|
||||
thread,
|
||||
messages: messages.map((message) => ({
|
||||
messages: orderMessagesByParent(messages).map((message) => ({
|
||||
id: message.id,
|
||||
parentId: message.parentId,
|
||||
format: message.format,
|
||||
|
||||
Reference in new issue
Block a user