Skip to content

Commit 4905f7b

Browse files
committed
fix: resolve intermittent reasoning content not displayed for Claude Code provider (#5111)
- Modified fallback logic in stream parsing to handle all message types, not just assistant messages - Added proper parsing attempts for partial data before yielding - Improved error logging to help debug streaming issues - Added debug logging (controlled by DEBUG_CLAUDE_CODE env var) to trace message types This ensures reasoning/thinking content from Claude 3.5 Sonnet 4.0 is properly displayed in all cases.
1 parent 3598e3c commit 4905f7b

File tree

1 file changed

+32
-6
lines changed
  • src/integrations/claude-code

1 file changed

+32
-6
lines changed

src/integrations/claude-code/run.ts

Lines changed: 32 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -63,10 +63,21 @@ export async function* runClaudeCode(options: ClaudeCodeOptions): AsyncGenerator
6363
}
6464
}
6565

66-
// We rely on the assistant message. If the output was truncated, it's better having a poorly formatted message
67-
// from which to extract something, than throwing an error/showing the model didn't return any messages.
68-
if (processState.partialData && processState.partialData.startsWith(`{"type":"assistant"`)) {
69-
yield processState.partialData
66+
// Handle any remaining partial data that could be a valid message
67+
// This helps recover from truncated output and ensures we don't lose reasoning/thinking content
68+
if (processState.partialData) {
69+
// Try to parse the partial data as it might be a complete message
70+
const partialChunk = attemptParseChunk(processState.partialData)
71+
if (partialChunk) {
72+
yield partialChunk
73+
} else {
74+
// If it's not parseable but looks like it could be a message, yield it as raw string
75+
// The provider will handle string messages appropriately
76+
const partialTrimmed = processState.partialData.trim()
77+
if (partialTrimmed.startsWith('{"type":') && partialTrimmed.includes('"message"')) {
78+
yield processState.partialData
79+
}
80+
}
7081
}
7182

7283
const { exitCode } = await process
@@ -169,9 +180,24 @@ function parseChunk(data: string, processState: ProcessState) {
169180

170181
function attemptParseChunk(data: string): ClaudeCodeMessage | null {
171182
try {
172-
return JSON.parse(data)
183+
const parsed = JSON.parse(data)
184+
// Log message types for debugging streaming issues
185+
if (parsed?.type && process.env.DEBUG_CLAUDE_CODE) {
186+
console.debug(`Claude Code message type: ${parsed.type}`, {
187+
hasMessage: !!parsed.message,
188+
contentTypes: parsed.message?.content?.map((c: any) => c.type) || [],
189+
})
190+
}
191+
return parsed
173192
} catch (error) {
174-
console.error("Error parsing chunk:", error, data.length)
193+
// Only log errors for non-empty data
194+
if (data.trim()) {
195+
console.error(
196+
"Error parsing chunk:",
197+
error,
198+
`Length: ${data.length}, Preview: ${data.substring(0, 100)}...`,
199+
)
200+
}
175201
return null
176202
}
177203
}

0 commit comments

Comments
 (0)