fix: prevent stale SDK session and tool-marker parroting after idle timeout (#184)

fix: prevent stale SDK session and tool-marker parroting after idle timeout
This commit is contained in:
jasonjaclyn2017 authored and GitHub committed 2026-03-07 10:26:05 +08:00
1 parent 03d2636d7f
commit a53c60531f
3 files changed
+18 -10

No files matched your search

+4 -1
View File
@@ -1,5 +1,5 @@
import { NextRequest } from 'next/server';
import { deleteSession, getSession, updateSessionWorkingDirectory, updateSessionTitle, updateSessionMode, updateSessionModel, updateSessionProviderId, clearSessionMessages } from '@/lib/db';
import { deleteSession, getSession, updateSessionWorkingDirectory, updateSessionTitle, updateSessionMode, updateSessionModel, updateSessionProviderId, clearSessionMessages, updateSdkSessionId } from '@/lib/db';
export async function GET(
_request: NextRequest,
@@ -46,6 +46,9 @@ export async function PATCH(
if (body.provider_id !== undefined) {
updateSessionProviderId(id, body.provider_id);
}
if (body.sdk_session_id !== undefined) {
updateSdkSessionId(id, body.sdk_session_id);
}
if (body.clear_messages) {
clearSessionMessages(id);
}
+8 -9
View File
@@ -235,9 +235,13 @@ function buildPromptWithHistory(
): string {
if (!history || history.length === 0) return prompt;
const lines: string[] = ['<conversation_history>'];
const lines: string[] = [
'<conversation_history>',
'(This is a summary of earlier conversation turns for context. Tool calls shown here were already executed — do not repeat them or output their markers as text.)',
];
for (const msg of history) {
// For assistant messages with tool blocks (JSON arrays), summarize
// For assistant messages with tool blocks (JSON arrays), extract only the text portions.
// Tool-use and tool-result blocks are omitted to avoid Claude parroting them as plain text.
let content = msg.content;
if (msg.role === 'assistant' && content.startsWith('[')) {
try {
@@ -245,14 +249,9 @@ function buildPromptWithHistory(
const parts: string[] = [];
for (const b of blocks) {
if (b.type === 'text' && b.text) parts.push(b.text);
else if (b.type === 'tool_use') parts.push(`[Used tool: ${b.name}]`);
else if (b.type === 'tool_result') {
const resultStr = typeof b.content === 'string' ? b.content : JSON.stringify(b.content);
// Truncate long tool results
parts.push(`[Tool result: ${resultStr.slice(0, 500)}${resultStr.length > 500 ? '...' : ''}]`);
}
// Skip tool_use and tool_result — they were already executed
}
content = parts.join('\n');
content = parts.length > 0 ? parts.join('\n') : '(assistant used tools)';
} catch {
// Not JSON, use as-is
}
+6
View File
@@ -405,6 +405,12 @@ async function runStream(stream: ActiveStream, params: StartStreamParams): Promi
stream.toolResultsArray = [];
stream.toolOutputAccumulated = '';
emit(stream, 'completed');
// Clear stale SDK session so next message starts fresh
fetch(`/api/chat/sessions/${encodeURIComponent(stream.sessionId)}`, {
method: 'PATCH',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ sdk_session_id: '' }),
}).catch(() => {});
scheduleGC(stream);
} else if (stream.toolTimeoutInfo) {
// Tool timeout — auto-retry