refactor: replace focusedIndex with activeChildId

- Replace focusedIndex integer with activeChildId string in messages schema
- Add migration to convert existing data and drop focused_index column
- Add  hooks for providers.updatedAt and messageParts.lastUpdatedAt
- Add file size column to files table
- Update message navigation to use child ID-based lookup
- Simplify delete logic by removing focusedIndex math
- Fix file delete endpoint filename ([id[ -> [id])
This commit is contained in:
Zoe
2026-05-11 17:41:57 -05:00
parent 7a944afdb5
commit 103dedd9cc
16 changed files with 2106 additions and 1793 deletions
@@ -77,7 +77,9 @@ export default defineEventHandler(async (event) => {
}
if (rootMessage.deleted === true) {
const childMessage = rootMessage.children[rootMessage.focusedIndex!];
const childMessage = rootMessage.activeChildId
? rootMessage.children.find(c => c.id === rootMessage.activeChildId)
: rootMessage.children[0];
if (!childMessage) {
console.error('Message not found');
return { ok: false };
@@ -88,27 +90,15 @@ export default defineEventHandler(async (event) => {
const remainingChildren = rootMessage.children.filter(child => child!.id !== childMessage.id);
if (remainingChildren.length === 0) {
await deeplyDeleteMessage(rootMessage.id, topicId, userId);
} else {
const newFocusedIndex = rootMessage.focusedIndex && rootMessage.focusedIndex > 0
? Math.min(rootMessage.focusedIndex - 1, remainingChildren.length - 1)
: 0;
await db.update(messages).set({ focusedIndex: newFocusedIndex }).where(sql`${messages.id} = ${rootMessage.id} AND ${messages.userId} = ${userId}`);
topicEvents.emit(topicId, {
type: 'MESSAGE_UPDATED',
payload: { ...rootMessage, focusedIndex: newFocusedIndex },
});
}
return { ok: true };
}
if (
(rootMessage.focusedIndex !== undefined && rootMessage.focusedIndex !== null)
&& rootMessage.focusedIndex > 0
rootMessage.activeChildId
&& rootMessage.children.length > 0
) {
const childMessage = rootMessage.children[rootMessage.focusedIndex - 1];
const childMessage = rootMessage.children.find(c => c.id === rootMessage.activeChildId);
if (!childMessage) {
console.error('Message not found');
return { ok: false };
@@ -116,17 +106,6 @@ export default defineEventHandler(async (event) => {
await deeplyDeleteMessage(childMessage.id, topicId, userId);
const remainingChildren = rootMessage.children.filter(child => child!.id !== childMessage.id);
const newFocusedIndex = remainingChildren.length > 0
? Math.min(rootMessage.focusedIndex - 1, remainingChildren.length - 1)
: 0;
await db.update(messages).set({ focusedIndex: newFocusedIndex }).where(sql`${messages.id} = ${rootMessage.id} AND ${messages.userId} = ${userId}`);
topicEvents.emit(topicId, {
type: 'MESSAGE_UPDATED',
payload: { ...rootMessage, focusedIndex: newFocusedIndex },
});
return { ok: true };
}
+13 -4
View File
@@ -260,8 +260,8 @@ export default defineEventHandler(async (event) => {
});
}
await db.update(messages).set({ focusedIndex: (parentMessage.focusedIndex ?? 0) + 1 }).where(eq(messages.id, parentMessageId));
events.push({ type: 'MESSAGE_UPDATED', payload: { focusedIndex: (parentMessage.focusedIndex ?? 0) + 1 } });
await db.update(messages).set({ activeChildId: agentmessage.id }).where(eq(messages.id, parentMessageId));
events.push({ type: 'MESSAGE_UPDATED', payload: { id: parentMessageId, activeChildId: agentmessage.id } });
// we need to make the topic messages all the messages excluding the ones after the message we wish to regenerate
// and if parentMessageId is undefined, then excluding the last message
@@ -392,7 +392,13 @@ type SearchTheWebConfig = SearchTheWebRerankedConfig | SearchTheWebUnrankedConfi
export const searchTheWeb = (config: SearchTheWebConfig) => {
return async (query: string) => {
const results = await $fetch<any>(`${process.env.SEARXNG_URL}/search`, {
const results = await $fetch<{
results: Array<{
title: string;
url: string;
content: string;
}>;
}>(`${process.env.SEARXNG_URL}/search`, {
query: {
q: query,
format: 'json',
@@ -675,6 +681,7 @@ async function generateResponse(
payload: {
messageId: message.id,
partId: part.id,
lastUpdatedAt: new Date(),
content: part.accumulatedContent,
}
})
@@ -850,6 +857,7 @@ async function generateResponse(
payload: {
messageId: message.id,
partId: part.id,
lastUpdatedAt: new Date(),
content: token.text,
}
})
@@ -903,6 +911,7 @@ async function generateResponse(
payload: {
messageId: message.id,
partId: part.id,
lastUpdatedAt: dbPart.lastUpdatedAt,
content: part.accumulatedContent,
}
})
@@ -1177,7 +1186,7 @@ async function generateResponse(
error: {
type: outputType as ToolCallType,
value: outputValue as string,
}
},
}
})
} else {