diff --git a/.changeset/seven-kings-drop.md b/.changeset/seven-kings-drop.md new file mode 100644 index 00000000..ade48e4c --- /dev/null +++ b/.changeset/seven-kings-drop.md @@ -0,0 +1,5 @@ +--- +'@openai/agents-openai': patch +--- + +Fix tracing exception in model response getting method when tracing is disabled diff --git a/packages/agents-openai/src/openaiResponsesModel.ts b/packages/agents-openai/src/openaiResponsesModel.ts index d86f627d..178c9913 100644 --- a/packages/agents-openai/src/openaiResponsesModel.ts +++ b/packages/agents-openai/src/openaiResponsesModel.ts @@ -1,7 +1,6 @@ import { Model, Usage, - withResponseSpan, createResponseSpan, setCurrentSpan, resetCurrentSpan, @@ -876,32 +875,56 @@ export class OpenAIResponsesModel implements Model { * @returns A promise that resolves to the response from the model. */ async getResponse(request: ModelRequest): Promise { - const response = await withResponseSpan(async (span) => { + const span = request.tracing ? createResponseSpan() : undefined; + + try { + if (span) { + span.start(); + setCurrentSpan(span); + } + const response = await this.#fetchResponse(request, false); - if (request.tracing) { + if (request.tracing && span) { span.spanData.response_id = response.id; span.spanData._input = request.input; span.spanData._response = response; } - return response; - }); - - const output: ModelResponse = { - usage: new Usage({ - inputTokens: response.usage?.input_tokens ?? 0, - outputTokens: response.usage?.output_tokens ?? 0, - totalTokens: response.usage?.total_tokens ?? 0, - inputTokensDetails: { ...response.usage?.input_tokens_details }, - outputTokensDetails: { ...response.usage?.output_tokens_details }, - }), - output: convertToOutputItem(response.output), - responseId: response.id, - providerData: response, - }; + const output: ModelResponse = { + usage: new Usage({ + inputTokens: response.usage?.input_tokens ?? 0, + outputTokens: response.usage?.output_tokens ?? 0, + totalTokens: response.usage?.total_tokens ?? 0, + inputTokensDetails: { ...response.usage?.input_tokens_details }, + outputTokensDetails: { ...response.usage?.output_tokens_details }, + }), + output: convertToOutputItem(response.output), + responseId: response.id, + providerData: response, + }; - return output; + return output; + } catch (error) { + if (span) { + span.setError({ + message: 'Error getting response', + data: { + error: request.tracing + ? String(error) + : error instanceof Error + ? error.name + : undefined, + }, + }); + } + throw error; + } finally { + if (span) { + span.end(); + resetCurrentSpan(); + } + } } /** diff --git a/packages/agents-openai/test/openaiResponsesModel.test.ts b/packages/agents-openai/test/openaiResponsesModel.test.ts index 7aacd173..ba13d776 100644 --- a/packages/agents-openai/test/openaiResponsesModel.test.ts +++ b/packages/agents-openai/test/openaiResponsesModel.test.ts @@ -74,6 +74,47 @@ describe('OpenAIResponsesModel', () => { }); }); + it('getResponse should not throw tracing exception when tracing is disabled', async () => { + const fakeResponse = { + id: 'res1', + usage: { + input_tokens: 3, + output_tokens: 4, + total_tokens: 7, + }, + output: [ + { + id: 'test_id', + type: 'message', + status: 'completed', + content: [{ type: 'output_text', text: 'hi' }], + role: 'assistant', + }, + ], + }; + const createMock = vi.fn().mockResolvedValue(fakeResponse); + const fakeClient = { + responses: { create: createMock }, + } as unknown as OpenAI; + const model = new OpenAIResponsesModel(fakeClient, 'gpt-test'); + + const request = { + systemInstructions: 'inst', + input: 'hello', + modelSettings: {}, + tools: [], + outputType: 'text', + handoffs: [], + tracing: false, + signal: undefined, + }; + + await expect(model.getResponse(request as any)).resolves.not.toThrow(); + await expect(model.getResponse(request as any)).resolves.not.toThrow( + 'No existing trace found', + ); + }); + it('getStreamedResponse yields events and calls client with stream flag', async () => { withTrace('test', async () => { const fakeResponse = { id: 'res2', usage: {}, output: [] };