(db: Database.Database)
| 314 | } |
| 315 | |
| 316 | private backfillMessageTree(db: Database.Database): void { |
| 317 | const aiChats = db.prepare('SELECT id FROM ai_chat').all() as Array<{ id: string }> |
| 318 | const updateMessage = db.prepare( |
| 319 | 'UPDATE ai_message SET parent_id = ?, sibling_group_id = COALESCE(sibling_group_id, ?), branch_index = COALESCE(branch_index, 0) WHERE id = ?' |
| 320 | ) |
| 321 | const updateAIChat = db.prepare('UPDATE ai_chat SET active_message_id = ? WHERE id = ?') |
| 322 | |
| 323 | const tx = db.transaction(() => { |
| 324 | for (const aiChat of aiChats) { |
| 325 | const messages = db |
| 326 | .prepare( |
| 327 | `SELECT id, parent_id as parentId, sibling_group_id as siblingGroupId |
| 328 | FROM ai_message WHERE ai_chat_id = ? ORDER BY timestamp ASC, id ASC` |
| 329 | ) |
| 330 | .all(aiChat.id) as Array<{ id: string; parentId: string | null; siblingGroupId: string | null }> |
| 331 | |
| 332 | let previousId: string | null = null |
| 333 | for (const message of messages) { |
| 334 | const parentId = message.parentId === undefined ? previousId : (message.parentId ?? previousId) |
| 335 | updateMessage.run(parentId, message.siblingGroupId ?? message.id, message.id) |
| 336 | previousId = message.id |
| 337 | } |
| 338 | |
| 339 | const aiChatRow = db |
| 340 | .prepare('SELECT active_message_id as activeMessageId FROM ai_chat WHERE id = ?') |
| 341 | .get(aiChat.id) as { activeMessageId: string | null } | undefined |
| 342 | if (!aiChatRow?.activeMessageId && previousId) { |
| 343 | updateAIChat.run(previousId, aiChat.id) |
| 344 | } |
| 345 | } |
| 346 | }) |
| 347 | |
| 348 | tx() |
| 349 | } |
| 350 | |
| 351 | private generateId(prefix: string): string { |
| 352 | return `${prefix}_${Date.now()}_${Math.random().toString(36).slice(2, 8)}` |
no test coverage detected