fix: writing stuck - handle empty model response + no-divider fallback + timeline cleanup

Root causes of writing getting stuck:
1. Model returns empty response for a section → now detected early with
   actionable error message including model name
2. Model responds but without ~~~ARTICLE~~~ divider (happens with fallback
   models like Gemini) → now treats entire response as markdown content
3. Stream ends without 'complete' event (error/exit in PHP) → JS timeline
   entries lingered as 'active' forever. Now deactivated on stream close.
4. Error messages in execution flow now use structured formatAiErrorMessage
   with retry button instead of raw text

Also: deactivateActiveTimelineEntries called in catch block so errors
properly clear the 'Writing section X' status indicator.
This commit is contained in:
Dwindi Ramadhana
2026-06-06 05:30:12 +07:00
parent 23a34b3035
commit 379a72e52d
2 changed files with 46 additions and 2 deletions

View File

@@ -2912,12 +2912,20 @@
}
}
clearTimeout(timeout);
// If stream ended without a 'complete' event, deactivate lingering timeline entries
setMessages(prev => {
const hasActive = prev.some(m => m.type === 'timeline' && m.status && !['complete', 'inactive', 'stopped'].includes(m.status));
if (hasActive) {
return deactivateActiveTimelineEntries(prev);
}
return prev;
});
} catch (error) {
setAgentMode(currentPlanRef.current ? 'planning' : 'chat');
setMessages(prev => [...prev, {
setMessages(prev => [...deactivateActiveTimelineEntries(prev), {
role: 'system',
type: 'error',
content: 'Error: ' + (error.message || 'Failed to execute outline'),
content: formatAiErrorMessage(error, 'Failed to execute outline'),
canRetry: true,
retryType: 'execute',
}]);