(params: {
chatId?: string
userMessageId: string
requestId: string
workspaceId?: string
notifyWorkspaceStatus: boolean
})
| 510 | } |
| 511 | |
| 512 | function buildOnError(params: { |
| 513 | chatId?: string |
| 514 | userMessageId: string |
| 515 | requestId: string |
| 516 | workspaceId?: string |
| 517 | notifyWorkspaceStatus: boolean |
| 518 | }) { |
| 519 | const { chatId, userMessageId, requestId, workspaceId, notifyWorkspaceStatus } = params |
| 520 | |
| 521 | return async (_error: Error, result?: OrchestratorResult) => { |
| 522 | if (!chatId) return |
| 523 | |
| 524 | try { |
| 525 | // Persist whatever streamed before a thrown backend error, mirroring the |
| 526 | // cancelled / non-success completion path, so the partial assistant turn |
| 527 | // (text + tool calls + subagent work) survives the refetch instead of the |
| 528 | // chat collapsing to an empty assistant row. |
| 529 | const assistantMessage = result |
| 530 | ? buildPersistedAssistantMessage(result, requestId) |
| 531 | : undefined |
| 532 | const hasPartial = |
| 533 | !!assistantMessage?.content?.trim() || (assistantMessage?.contentBlocks?.length ?? 0) > 0 |
| 534 | await finalizeAssistantTurn({ |
| 535 | chatId, |
| 536 | userMessageId, |
| 537 | ...(hasPartial ? { assistantMessage } : {}), |
| 538 | streamMarkerPolicy: 'active-or-cleared', |
| 539 | }) |
| 540 | |
| 541 | if (notifyWorkspaceStatus && workspaceId) { |
| 542 | chatPubSub?.publishStatusChanged({ |
| 543 | workspaceId, |
| 544 | chatId, |
| 545 | type: 'completed', |
| 546 | streamId: userMessageId, |
| 547 | }) |
| 548 | } |
| 549 | } catch (error) { |
| 550 | logger.error(`[${requestId}] Failed to finalize errored chat stream`, { |
| 551 | chatId, |
| 552 | error: getErrorMessage(error, 'Unknown error'), |
| 553 | }) |
| 554 | } |
| 555 | } |
| 556 | } |
| 557 | |
| 558 | async function resolveBranch(params: { |
| 559 | authenticatedUserId: string |
no test coverage detected