* Write error metadata to partial.json and emit the corresponding error event.
(
workspaceId: WorkspaceId,
streamInfo: WorkspaceStreamInfo,
payload: StreamErrorPayload & { errorType: StreamErrorType }
)
| 3197 | * Write error metadata to partial.json and emit the corresponding error event. |
| 3198 | */ |
| 3199 | private async persistStreamError( |
| 3200 | workspaceId: WorkspaceId, |
| 3201 | streamInfo: WorkspaceStreamInfo, |
| 3202 | payload: StreamErrorPayload & { errorType: StreamErrorType } |
| 3203 | ): Promise<void> { |
| 3204 | const refusalFinishReason = |
| 3205 | payload.errorType === "model_refusal" |
| 3206 | ? ([streamInfo.terminalFinishReason, streamInfo.terminalRawFinishReason].find( |
| 3207 | isRefusalFinishReason |
| 3208 | ) ?? streamInfo.terminalFinishReason) |
| 3209 | : undefined; |
| 3210 | const terminalRefusalUsage = streamInfo.terminalRefusalUsage; |
| 3211 | const terminalRefusalProviderMetadata = streamInfo.terminalRefusalProviderMetadata; |
| 3212 | |
| 3213 | const errorPartialMessage = this.buildPartialAssistantMessage(streamInfo, { |
| 3214 | metadata: { |
| 3215 | error: payload.error, |
| 3216 | errorType: payload.errorType, |
| 3217 | ...(refusalFinishReason !== undefined ? { finishReason: refusalFinishReason } : {}), |
| 3218 | ...(terminalRefusalUsage !== undefined ? { usage: terminalRefusalUsage } : {}), |
| 3219 | ...(terminalRefusalProviderMetadata !== undefined |
| 3220 | ? { providerMetadata: terminalRefusalProviderMetadata } |
| 3221 | : {}), |
| 3222 | // Keep tool-side / refused-fallback usage rows durable on the error |
| 3223 | // partial: a fallback chain that ends in a terminal refusal must not |
| 3224 | // drop the refused attempts' tokens from persisted metadata. |
| 3225 | ...(streamInfo.toolModelUsages.length > 0 |
| 3226 | ? { toolModelUsages: streamInfo.toolModelUsages.map(clonePersistedToolModelUsage) } |
| 3227 | : {}), |
| 3228 | }, |
| 3229 | }); |
| 3230 | |
| 3231 | // Wait for any in-flight partial write to complete before writing error state. |
| 3232 | // This prevents race conditions where the error write and a throttled flush |
| 3233 | // write at the same time, causing inconsistent partial.json state. |
| 3234 | await this.awaitPendingPartialWrite(streamInfo); |
| 3235 | |
| 3236 | // Write error state to disk - await to ensure consistent state before any resume. |
| 3237 | await this.historyService.writePartial(workspaceId as string, errorPartialMessage); |
| 3238 | |
| 3239 | // Emit error event. |
| 3240 | this.emit("error", createErrorEvent(workspaceId as string, payload)); |
| 3241 | } |
| 3242 | |
| 3243 | private getOpenAIPreviousResponseId( |
| 3244 | providerOptions?: Record<string, unknown> |
no test coverage detected