mirror of
https://github.com/simstudioai/sim.git
synced 2026-09-24 15:45:35 +08:00
fix(providers): name the header phase on streaming OpenAI requests (#6288)
This commit is contained in:
@@ -198,6 +198,20 @@ describe('OpenAI transport phase annotation', () => {
|
||||
expect(error.message.match(/phase=/g)).toHaveLength(1)
|
||||
})
|
||||
|
||||
/**
|
||||
* Streaming calls the request helper directly and never reaches `postResponses`, so a
|
||||
* header stall on a chat or SSE run used to surface as the bare runtime string with no
|
||||
* phase, elapsed time, or request id.
|
||||
*/
|
||||
it('names the header phase on a streaming request too', async () => {
|
||||
const error = await run(vi.fn().mockRejectedValue(timeoutError()), {
|
||||
stream: true,
|
||||
}).catch((e) => e)
|
||||
|
||||
expect(error.message).toContain('phase=awaiting-response-headers')
|
||||
expect(error.message).toMatch(/elapsedMs=\d+/)
|
||||
})
|
||||
|
||||
it('leaves a healthy response entirely unaffected', async () => {
|
||||
const fetchMock = vi.fn().mockResolvedValue({
|
||||
ok: true,
|
||||
|
||||
@@ -410,6 +410,29 @@ export async function executeResponsesProviderRequest(
|
||||
|
||||
let reasoningSummariesUnavailable = false
|
||||
|
||||
/**
|
||||
* The single point every Responses request leaves through, so a stall waiting for
|
||||
* headers is named on the streaming paths too — they call
|
||||
* {@link fetchResponsesWithSummaryFallback} directly and never reach `postResponses`,
|
||||
* which is where the annotation used to live.
|
||||
*/
|
||||
const postOnce = async (
|
||||
payload: Record<string, unknown>,
|
||||
abortSignal: AbortSignal | undefined,
|
||||
startedAt: number
|
||||
): Promise<Response> => {
|
||||
try {
|
||||
return await fetchImpl(config.endpoint, {
|
||||
method: 'POST',
|
||||
headers: config.headers,
|
||||
body: JSON.stringify(payload),
|
||||
signal: abortSignal,
|
||||
})
|
||||
} catch (error) {
|
||||
throw annotateTransportFailure(error, 'awaiting-response-headers', startedAt)
|
||||
}
|
||||
}
|
||||
|
||||
const fetchResponsesWithSummaryFallback = async (
|
||||
requestedBody: Record<string, unknown>,
|
||||
startedAt: number,
|
||||
@@ -418,12 +441,7 @@ export async function executeResponsesProviderRequest(
|
||||
const body = reasoningSummariesUnavailable
|
||||
? (stripReasoningSummary(requestedBody) ?? requestedBody)
|
||||
: requestedBody
|
||||
const response = await fetchImpl(config.endpoint, {
|
||||
method: 'POST',
|
||||
headers: config.headers,
|
||||
body: JSON.stringify(body),
|
||||
signal: abortSignal,
|
||||
})
|
||||
const response = await postOnce(body, abortSignal, startedAt)
|
||||
if (response.ok) return response
|
||||
|
||||
const message = await parseErrorResponse(response, startedAt)
|
||||
@@ -439,12 +457,7 @@ export async function executeResponsesProviderRequest(
|
||||
`${config.providerLabel} rejected reasoning summaries (organization not verified); retrying without summary`,
|
||||
{ model: config.modelName }
|
||||
)
|
||||
const retryResponse = await fetchImpl(config.endpoint, {
|
||||
method: 'POST',
|
||||
headers: config.headers,
|
||||
body: JSON.stringify(strippedBody),
|
||||
signal: abortSignal,
|
||||
})
|
||||
const retryResponse = await postOnce(strippedBody, abortSignal, startedAt)
|
||||
if (!retryResponse.ok) {
|
||||
const retryMessage = await parseErrorResponse(retryResponse, startedAt)
|
||||
throw new Error(
|
||||
@@ -459,12 +472,7 @@ export async function executeResponsesProviderRequest(
|
||||
): Promise<OpenAI.Responses.Response> => {
|
||||
const startedAt = Date.now()
|
||||
|
||||
let response: Response
|
||||
try {
|
||||
response = await fetchResponsesWithSummaryFallback(body, startedAt)
|
||||
} catch (error) {
|
||||
throw annotateTransportFailure(error, 'awaiting-response-headers', startedAt)
|
||||
}
|
||||
const response = await fetchResponsesWithSummaryFallback(body, startedAt)
|
||||
|
||||
const responseMeta = { ...describeResponse(response), ttfbMs: Date.now() - startedAt }
|
||||
|
||||
|
||||
Reference in New Issue
Block a user