fix: persist image generation results to DB for reload survival, bump v0.17.2

Root cause: after image generation, the message content in DB stayed as
`image-gen-request` (the options form). On app restart, MessageItem re-parsed
this as a generation form instead of showing the completed result. The result
only lived in React state and localStorage.

Fix:
- db.ts: add updateMessageContent() to update a message's content by ID
- /api/chat/messages: add PUT handler for message content updates
- ImageGenConfirmation: accept messageId prop; on successful generation,
  replace message content from image-gen-request to image-gen-result format
  (with localPath references) via PUT API call
- MessageItem: pass message.id to ImageGenConfirmation

Now on restart, parseImageGenResult() matches the persisted image-gen-result
block and renders ImageGenCard directly with the saved image paths.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
7418andClaude Opus 4.6 committed 2026-02-27 11:32:00 +08:00
1 parent fd03d179e3
commit 20a5934cfc
6 files changed
+62 -4

No files matched your search

+2 -2
View File
@@ -1,12 +1,12 @@
{
"name": "codepilot",
"version": "0.17.1",
"version": "0.17.2",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "codepilot",
"version": "0.17.1",
"version": "0.17.2",
"dependencies": {
"@ai-sdk/anthropic": "^3.0.47",
"@ai-sdk/google": "^3.0.31",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "codepilot",
"version": "0.17.1",
"version": "0.17.2",
"private": true,
"author": {
"name": "op7418",
+29 -1
View File
@@ -1,5 +1,5 @@
import { NextRequest, NextResponse } from 'next/server';
import { addMessage, getSession } from '@/lib/db';
import { addMessage, updateMessageContent, getSession } from '@/lib/db';
export const runtime = 'nodejs';
@@ -37,3 +37,31 @@ export async function POST(request: NextRequest) {
return NextResponse.json({ error: msg }, { status: 500 });
}
}
/**
* PUT /api/chat/messages
* Update the content of an existing message.
* Used to replace image-gen-request with image-gen-result after generation.
*/
export async function PUT(request: NextRequest) {
try {
const body = await request.json();
const { message_id, content } = body as {
message_id: string;
content: string;
};
if (!message_id || !content) {
return NextResponse.json(
{ error: 'message_id and content are required' },
{ status: 400 },
);
}
updateMessageContent(message_id, content);
return NextResponse.json({ ok: true });
} catch (error) {
const msg = error instanceof Error ? error.message : 'Failed to update message';
return NextResponse.json({ error: msg }, { status: 500 });
}
}
@@ -17,6 +17,7 @@ const ASPECT_RATIOS = [
const RESOLUTIONS = ['1K', '2K', '4K'] as const;
interface ImageGenConfirmationProps {
messageId?: string;
initialPrompt: string;
initialAspectRatio: string;
initialResolution: string;
@@ -32,6 +33,7 @@ function storageKey(prompt: string, sessionId?: string): string {
}
export function ImageGenConfirmation({
messageId,
initialPrompt,
initialAspectRatio,
initialResolution,
@@ -140,6 +142,28 @@ export function ImageGenConfirmation({
// storage full
}
// Persist result to DB by replacing image-gen-request with image-gen-result
if (messageId) {
const resultBlock = JSON.stringify({
status: 'completed',
prompt,
aspectRatio,
resolution,
images: genResult.images.map(img => ({
mimeType: img.mimeType,
localPath: img.localPath,
})),
});
fetch('/api/chat/messages', {
method: 'PUT',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
message_id: messageId,
content: '```image-gen-result\n' + resultBlock + '\n```',
}),
}).catch(() => {});
}
// Defer event dispatch so React commits setResult/setStatus before
// ChatView's handler calls sendMessage and triggers a re-render
setTimeout(() => {
+1
View File
@@ -491,6 +491,7 @@ export function MessageItem({ message }: MessageItemProps) {
<>
{parsed.beforeText && <MessageResponse>{parsed.beforeText}</MessageResponse>}
<ImageGenConfirmation
messageId={message.id}
initialPrompt={parsed.request.prompt}
initialAspectRatio={parsed.request.aspectRatio}
initialResolution={parsed.request.resolution}
+5
View File
@@ -565,6 +565,11 @@ export function addMessage(
return db.prepare('SELECT * FROM messages WHERE id = ?').get(id) as Message;
}
export function updateMessageContent(messageId: string, content: string): void {
const db = getDb();
db.prepare('UPDATE messages SET content = ? WHERE id = ?').run(content, messageId);
}
export function clearSessionMessages(sessionId: string): void {
const db = getDb();
db.prepare('DELETE FROM messages WHERE session_id = ?').run(sessionId);