(
workspaceId: WorkspaceId,
streamInfo: WorkspaceStreamInfo,
part: CompletedMessagePart,
schedulePartialWrite = false
)
| 1193 | } |
| 1194 | |
| 1195 | private async appendPartAndEmit( |
| 1196 | workspaceId: WorkspaceId, |
| 1197 | streamInfo: WorkspaceStreamInfo, |
| 1198 | part: CompletedMessagePart, |
| 1199 | schedulePartialWrite = false |
| 1200 | ): Promise<void> { |
| 1201 | // Emit BEFORE adding to streamInfo.parts. |
| 1202 | // |
| 1203 | // On reconnect, we call replayStream() which snapshots streamInfo.parts. If we push a part to |
| 1204 | // streamInfo.parts and then await tokenization/emit, replay can include the "in-flight" part |
| 1205 | // and then the live emit still happens, causing duplicate deltas in the renderer. |
| 1206 | try { |
| 1207 | await this.emitPartAsEvent(workspaceId, streamInfo.messageId, part); |
| 1208 | } finally { |
| 1209 | // Always persist the part in-memory (and to partial.json, if enabled), even if emit fails. |
| 1210 | let partToPersist = part; |
| 1211 | let pendingAttachment: WorkflowRunToolAttachment | undefined; |
| 1212 | if (part.type === "dynamic-tool") { |
| 1213 | pendingAttachment = this.takePendingWorkflowRunAttachment(streamInfo, part.toolCallId); |
| 1214 | if (pendingAttachment != null) { |
| 1215 | partToPersist = { ...part, workflowRun: pendingAttachment }; |
| 1216 | } |
| 1217 | } |
| 1218 | streamInfo.parts.push(partToPersist); |
| 1219 | if (pendingAttachment != null && part.type === "dynamic-tool") { |
| 1220 | await this.flushPartialWrite(workspaceId, streamInfo); |
| 1221 | this.emitWorkflowRunAttachedFromAttachment({ |
| 1222 | workspaceId, |
| 1223 | messageId: streamInfo.messageId, |
| 1224 | toolCallId: part.toolCallId, |
| 1225 | attachment: pendingAttachment, |
| 1226 | }); |
| 1227 | } else if (schedulePartialWrite) { |
| 1228 | void this.schedulePartialWrite(workspaceId, streamInfo); |
| 1229 | } |
| 1230 | } |
| 1231 | } |
| 1232 | |
| 1233 | private async cancelStreamSafely( |
| 1234 | workspaceId: WorkspaceId, |
no test coverage detected