diff --git a/vibn-frontend/app/[workspace]/project/[projectId]/(home)/sessions/[sessionId]/page.tsx b/vibn-frontend/app/[workspace]/project/[projectId]/(home)/sessions/[sessionId]/page.tsx index 19c196e..851e42c 100644 --- a/vibn-frontend/app/[workspace]/project/[projectId]/(home)/sessions/[sessionId]/page.tsx +++ b/vibn-frontend/app/[workspace]/project/[projectId]/(home)/sessions/[sessionId]/page.tsx @@ -77,15 +77,23 @@ export default function SessionViewer() { session_id: sessionId, title: thread.title, created_at: thread.createdAt, - messages: messages.map((m) => ({ + messages: messages.map((m: any) => ({ role: m.role, content: m.content || (m.textSegments ? m.textSegments.join("\n\n") : ""), tool_calls: m.toolCalls - ? m.toolCalls.map((tc) => ({ - name: tc.name, - arguments: tc.args, - })) + ? m.toolCalls.map((tc: any) => { + const rawResult = m._rawToolResults?.find( + (tr: any) => + tr.name === tc.name && + JSON.stringify(tr.args) === JSON.stringify(tc.args), + )?.result; + return { + name: tc.name, + arguments: tc.args, + result: rawResult, + }; + }) : undefined, })), }; diff --git a/vibn-frontend/app/api/chat/route.ts b/vibn-frontend/app/api/chat/route.ts index 47604e0..f73e0d8 100644 --- a/vibn-frontend/app/api/chat/route.ts +++ b/vibn-frontend/app/api/chat/route.ts @@ -723,14 +723,38 @@ export async function POST(request: Request) { // segmentation it shows during streaming. Older messages // (pre-this-fix) won't have textSegments and fall back to // single-bubble content rendering. - const finalMsg: ChatMessage & { textSegments?: string[] } = { + const finalMsg: ChatMessage & { + textSegments?: string[]; + _rawToolResults?: Array<{ name: string; args: any; result: string }>; + } = { role: "assistant", content: assistantText, toolCalls: assistantToolCalls.length ? assistantToolCalls : undefined, textSegments: assistantTextSegments.length ? assistantTextSegments : undefined, + _rawToolResults: assistantToolCalls.length ? [] : undefined, }; + + // Option 1 implemented: Save the raw tool results directly into the database row + // alongside the assistant message so it can be extracted later for fine-tuning. + if (finalMsg._rawToolResults) { + // We slice out the tool messages from the internal messages array we just built + // during the loop and attach them to the final row payload. + const toolResults = messages.filter((m) => m.role === "tool"); + finalMsg._rawToolResults = assistantToolCalls.map((tc) => { + const tr = toolResults.find((m) => m.toolCallId === tc.id); + return { + name: tc.name, + args: tc.args, + result: + typeof tr?.content === "string" + ? tr.content + : JSON.stringify(tr?.content || ""), + }; + }); + } + await query( `INSERT INTO fs_chat_messages (thread_id, user_id, data) VALUES ($1, $2, $3)`, [thread_id, email, JSON.stringify(finalMsg)],