Skip to content

Commit e7233bb

Browse files
committed
Add finalization on error
1 parent f34dbc4 commit e7233bb

2 files changed

Lines changed: 33 additions & 6 deletions

File tree

apps/sim/lib/copilot/chat/post.ts

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -457,12 +457,19 @@ function buildOnComplete(params: {
457457
return
458458
}
459459

460+
// On a non-success terminal (e.g. a transient provider error like
461+
// "overloaded"), persist whatever streamed before the failure — same as
462+
// the cancelled path — instead of dropping the partial assistant output.
463+
const assistantMessage = buildPersistedAssistantMessage(result, requestId)
464+
const hasPartial =
465+
!!assistantMessage.content?.trim() || (assistantMessage.contentBlocks?.length ?? 0) > 0
460466
await finalizeAssistantTurn({
461467
chatId,
462468
userMessageId,
463-
...(result.success
464-
? { assistantMessage: buildPersistedAssistantMessage(result, requestId) }
465-
: {}),
469+
...(result.success || hasPartial ? { assistantMessage } : {}),
470+
// Match the cancelled path so the partial still persists if onError
471+
// raced ahead and already cleared the stream marker.
472+
...(result.success ? {} : { streamMarkerPolicy: 'active-or-cleared' as const }),
466473
})
467474

468475
if (notifyWorkspaceStatus && workspaceId) {

apps/sim/lib/copilot/request/lifecycle/finalize.ts

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -115,23 +115,43 @@ async function handleError(
115115
result.errors?.[0] ||
116116
'An unexpected error occurred while processing the response.'
117117

118+
// Persist whatever was generated before the failure, exactly like an abort —
119+
// a transient provider error (e.g. overloaded) shouldn't discard the partial
120+
// assistant output the user already saw streaming.
121+
const partialContent = result.content || undefined
122+
const partialContentLen = result.content?.length ?? 0
123+
const toolCallCount = result.toolCalls?.length ?? 0
124+
118125
if (publisher.clientDisconnected) {
119126
logger.info(`[${requestId}] Stream failed after client disconnect`, { error: errorMessage })
120127
}
121-
logger.error(`[${requestId}] Orchestration returned failure`, { error: errorMessage })
128+
logger.error(`[${requestId}] Orchestration returned failure`, {
129+
error: errorMessage,
130+
partialContentLen,
131+
toolCallCount,
132+
})
122133

134+
// Surface the real error (Go already classifies provider errors like
135+
// "overloaded" into a friendly displayMessage). Don't clobber it with a
136+
// generic string.
123137
await publisher.publish({
124138
type: MothershipStreamV1EventType.error,
125139
payload: {
126140
message: errorMessage,
127141
error: errorMessage,
128-
data: { displayMessage: 'An unexpected error occurred while processing the response.' },
142+
displayMessage: errorMessage,
143+
data: { displayMessage: errorMessage },
129144
},
130145
})
131146
if (!publisher.sawComplete) {
132147
await publisher.publish({
133148
type: MothershipStreamV1EventType.complete,
134-
payload: { status: MothershipStreamV1CompletionStatus.error },
149+
payload: {
150+
status: MothershipStreamV1CompletionStatus.error,
151+
...(partialContent ? { partialContent } : {}),
152+
...(partialContentLen ? { partialContentLen } : {}),
153+
...(toolCallCount ? { toolCallCount } : {}),
154+
},
135155
})
136156
}
137157
await publisher.flush()

0 commit comments

Comments
 (0)