fix: image gen result persistence with fallback for temp message IDs, bump v0.17.3
Root cause: assistant messages use temporary IDs (temp-assistant-{timestamp})
in the frontend, which don't match real DB message IDs. The PUT update by
message_id always found 0 rows, so results were never persisted.
Fix — fallback search by session + prompt:
- db.ts: updateMessageContent now returns changes count; new
updateMessageBySessionAndHint() finds the latest assistant message
containing image-gen-request with matching prompt text and updates it
- /api/chat/messages PUT: tries message_id first, falls back to
session_id + prompt_hint search; returns 404 if neither finds a match;
response includes updated_message_id and fallback_used for debugging
- ImageGenConfirmation: always sends session_id and prompt_hint in PUT
request, regardless of whether messageId is a real or temp ID
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
1 parent
20a5934cfc
commit
40a78ea0fc
5 files changed
+68
-13
No files matched your search
Generated
+2
-2
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "codepilot",
|
||||
"version": "0.17.2",
|
||||
"version": "0.17.3",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "codepilot",
|
||||
"version": "0.17.2",
|
||||
"version": "0.17.3",
|
||||
"dependencies": {
|
||||
"@ai-sdk/anthropic": "^3.0.47",
|
||||
"@ai-sdk/google": "^3.0.31",
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "codepilot",
|
||||
"version": "0.17.2",
|
||||
"version": "0.17.3",
|
||||
"private": true,
|
||||
"author": {
|
||||
"name": "op7418",
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { NextRequest, NextResponse } from 'next/server';
|
||||
import { addMessage, updateMessageContent, getSession } from '@/lib/db';
|
||||
import { addMessage, updateMessageContent, updateMessageBySessionAndHint, getSession } from '@/lib/db';
|
||||
|
||||
export const runtime = 'nodejs';
|
||||
|
||||
@@ -42,24 +42,54 @@ export async function POST(request: NextRequest) {
|
||||
* PUT /api/chat/messages
|
||||
* Update the content of an existing message.
|
||||
* Used to replace image-gen-request with image-gen-result after generation.
|
||||
*
|
||||
* Tries message_id first. If no rows updated (temp ID), falls back to
|
||||
* searching by session_id + prompt_hint for the real DB message.
|
||||
*/
|
||||
export async function PUT(request: NextRequest) {
|
||||
try {
|
||||
const body = await request.json();
|
||||
const { message_id, content } = body as {
|
||||
const { message_id, content, session_id, prompt_hint } = body as {
|
||||
message_id: string;
|
||||
content: string;
|
||||
session_id?: string;
|
||||
prompt_hint?: string;
|
||||
};
|
||||
|
||||
if (!message_id || !content) {
|
||||
if (!content) {
|
||||
return NextResponse.json(
|
||||
{ error: 'message_id and content are required' },
|
||||
{ error: 'content is required' },
|
||||
{ status: 400 },
|
||||
);
|
||||
}
|
||||
|
||||
updateMessageContent(message_id, content);
|
||||
return NextResponse.json({ ok: true });
|
||||
// Try direct update by message_id
|
||||
let changes = 0;
|
||||
let updatedMessageId = message_id;
|
||||
let fallbackUsed = false;
|
||||
|
||||
if (message_id) {
|
||||
changes = updateMessageContent(message_id, content);
|
||||
}
|
||||
|
||||
// Fallback: search by session + prompt hint
|
||||
if (changes === 0 && session_id && prompt_hint) {
|
||||
const result = updateMessageBySessionAndHint(session_id, prompt_hint, content);
|
||||
changes = result.changes;
|
||||
if (result.messageId) {
|
||||
updatedMessageId = result.messageId;
|
||||
fallbackUsed = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (changes === 0) {
|
||||
return NextResponse.json(
|
||||
{ error: 'Message not found' },
|
||||
{ status: 404 },
|
||||
);
|
||||
}
|
||||
|
||||
return NextResponse.json({ ok: true, updated_message_id: updatedMessageId, fallback_used: fallbackUsed });
|
||||
} catch (error) {
|
||||
const msg = error instanceof Error ? error.message : 'Failed to update message';
|
||||
return NextResponse.json({ error: msg }, { status: 500 });
|
||||
|
||||
@@ -143,7 +143,7 @@ export function ImageGenConfirmation({
|
||||
}
|
||||
|
||||
// Persist result to DB by replacing image-gen-request with image-gen-result
|
||||
if (messageId) {
|
||||
{
|
||||
const resultBlock = JSON.stringify({
|
||||
status: 'completed',
|
||||
prompt,
|
||||
@@ -158,8 +158,10 @@ export function ImageGenConfirmation({
|
||||
method: 'PUT',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({
|
||||
message_id: messageId,
|
||||
message_id: messageId || '',
|
||||
content: '```image-gen-result\n' + resultBlock + '\n```',
|
||||
session_id: sessionId,
|
||||
prompt_hint: initialPrompt,
|
||||
}),
|
||||
}).catch(() => {});
|
||||
}
|
||||
|
||||
+25
-2
@@ -565,9 +565,32 @@ export function addMessage(
|
||||
return db.prepare('SELECT * FROM messages WHERE id = ?').get(id) as Message;
|
||||
}
|
||||
|
||||
export function updateMessageContent(messageId: string, content: string): void {
|
||||
export function updateMessageContent(messageId: string, content: string): number {
|
||||
const db = getDb();
|
||||
db.prepare('UPDATE messages SET content = ? WHERE id = ?').run(content, messageId);
|
||||
const result = db.prepare('UPDATE messages SET content = ? WHERE id = ?').run(content, messageId);
|
||||
return result.changes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the most recent assistant message in a session that contains a given text snippet,
|
||||
* update its content, and return the real message ID. Used as fallback when the frontend
|
||||
* only has a temporary message ID.
|
||||
*/
|
||||
export function updateMessageBySessionAndHint(
|
||||
sessionId: string,
|
||||
promptHint: string,
|
||||
content: string,
|
||||
): { changes: number; messageId?: string } {
|
||||
const db = getDb();
|
||||
// Find the latest assistant message containing the prompt hint within an image-gen-request block
|
||||
const row = db.prepare(
|
||||
"SELECT id FROM messages WHERE session_id = ? AND role = 'assistant' AND content LIKE '%image-gen-request%' AND content LIKE ? ORDER BY created_at DESC LIMIT 1"
|
||||
).get(sessionId, `%${promptHint.slice(0, 60)}%`) as { id: string } | undefined;
|
||||
|
||||
if (!row) return { changes: 0 };
|
||||
|
||||
const result = db.prepare('UPDATE messages SET content = ? WHERE id = ?').run(content, row.id);
|
||||
return { changes: result.changes, messageId: row.id };
|
||||
}
|
||||
|
||||
export function clearSessionMessages(sessionId: string): void {
|
||||
|
||||
Reference in new issue
Block a user