(
workspaceId: WorkspaceId,
streamInfo: WorkspaceStreamInfo
)
| 1936 | } |
| 1937 | |
| 1938 | private async handleEmptyStreamCompletion( |
| 1939 | workspaceId: WorkspaceId, |
| 1940 | streamInfo: WorkspaceStreamInfo |
| 1941 | ): Promise<void> { |
| 1942 | const workspaceLog = this.getWorkspaceLogger(workspaceId, streamInfo); |
| 1943 | const streamMeta = await this.getStreamMetadata(streamInfo); |
| 1944 | const totalUsage = this.resolveTotalUsageForStreamEnd(streamInfo, streamMeta.totalUsage); |
| 1945 | const contextUsage = streamMeta.contextUsage ?? streamInfo.lastStepUsage; |
| 1946 | const previousResponseId = this.getOpenAIPreviousResponseId(streamInfo.request.providerOptions); |
| 1947 | |
| 1948 | // Surface silent provider drops instead of leaving an empty assistant placeholder behind. |
| 1949 | // Recent gpt-5.4-pro stalls only logged stream startup, so future occurrences need an |
| 1950 | // explicit backend breadcrumb and a user-visible retryable error. |
| 1951 | workspaceLog.error("Stream ended without emitting text, reasoning, or tool events", { |
| 1952 | messageId: streamInfo.messageId, |
| 1953 | model: streamInfo.model, |
| 1954 | durationMs: streamMeta.duration, |
| 1955 | totalUsage, |
| 1956 | contextUsage, |
| 1957 | cumulativeUsage: streamInfo.cumulativeUsage, |
| 1958 | previousResponseId, |
| 1959 | }); |
| 1960 | |
| 1961 | await this.handleStreamFailure(workspaceId, streamInfo, new EmptyStreamOutputError()); |
| 1962 | } |
| 1963 | |
| 1964 | private async handleModelRefusalCompletion( |
| 1965 | workspaceId: WorkspaceId, |
no test coverage detected