Skip to content

Commit cde5081

Browse files
committed
test(translator): add tests to validate omission of top-level output_text in OpenAI responses
- Added `TestConvertOpenAIChatCompletionsResponseToOpenAIResponses_CompletedOmitsTopLevelOutputText` to ensure `output_text` is excluded in streamed responses. - Added `TestConvertOpenAIChatCompletionsResponseToOpenAIResponses_ToolCallCompletedOmitsTopLevelOutputText` to validate behavior during tool call completions. - Introduced `TestConvertOpenAIChatCompletionsResponseToOpenAIResponsesNonStream_OmitsTopLevelOutputText` to confirm the omission of `output_text` in non-streamed responses. - Expanded test coverage to ensure consistency with native OpenAI responses.
1 parent acaf250 commit cde5081

1 file changed

Lines changed: 81 additions & 0 deletions

File tree

internal/translator/openai/openai/responses/openai_openai-responses_response_test.go

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -371,6 +371,72 @@ func TestConvertOpenAIChatCompletionsResponseToOpenAIResponses_MixedMessageAndTo
371371
}
372372
}
373373

374+
func TestConvertOpenAIChatCompletionsResponseToOpenAIResponses_CompletedOmitsTopLevelOutputText(t *testing.T) {
375+
in := []string{
376+
`data: {"id":"resp_output_text","object":"chat.completion.chunk","created":1773896263,"model":"model","choices":[{"index":0,"delta":{"role":"assistant","content":"hello ","reasoning_content":null,"tool_calls":null},"finish_reason":null}]}`,
377+
`data: {"id":"resp_output_text","object":"chat.completion.chunk","created":1773896263,"model":"model","choices":[{"index":0,"delta":{"role":null,"content":"world","reasoning_content":null,"tool_calls":null},"finish_reason":"stop"}],"usage":{"completion_tokens":2,"total_tokens":4,"prompt_tokens":2}}`,
378+
`data: [DONE]`,
379+
}
380+
381+
request := []byte(`{"model":"gpt-5.4"}`)
382+
383+
var param any
384+
var completed gjson.Result
385+
for _, line := range in {
386+
for _, chunk := range ConvertOpenAIChatCompletionsResponseToOpenAIResponses(context.Background(), "model", request, request, []byte(line), &param) {
387+
ev, data := parseOpenAIResponsesSSEEvent(t, chunk)
388+
if ev == "response.completed" {
389+
completed = data
390+
}
391+
}
392+
}
393+
394+
if !completed.Exists() {
395+
t.Fatal("expected response.completed event")
396+
}
397+
if completed.Get("response.output_text").Exists() {
398+
t.Fatalf("response.output_text should be omitted to match native Responses output: %s", completed.Get("response.output_text").Raw)
399+
}
400+
if got := completed.Get("response.output.0.content.0.text").String(); got != "hello world" {
401+
t.Fatalf("response.output text = %q, want %q", got, "hello world")
402+
}
403+
}
404+
405+
func TestConvertOpenAIChatCompletionsResponseToOpenAIResponses_ToolCallCompletedOmitsTopLevelOutputText(t *testing.T) {
406+
in := []string{
407+
`data: {"id":"resp_tool_output_text","object":"chat.completion.chunk","created":1773896263,"model":"model","choices":[{"index":0,"delta":{"role":"assistant","content":"I will call the weather tool.","reasoning_content":null,"tool_calls":null},"finish_reason":null}]}`,
408+
`data: {"id":"resp_tool_output_text","object":"chat.completion.chunk","created":1773896263,"model":"model","choices":[{"index":0,"delta":{"role":"assistant","content":null,"reasoning_content":null,"tool_calls":[{"index":0,"id":"call_weather","type":"function","function":{"name":"get_weather","arguments":""}}]},"finish_reason":null}]}`,
409+
`data: {"id":"resp_tool_output_text","object":"chat.completion.chunk","created":1773896263,"model":"model","choices":[{"index":0,"delta":{"role":null,"content":null,"reasoning_content":null,"tool_calls":[{"index":0,"function":{"arguments":"{\"location\":\"北京\",\"unit\":\"celsius\"}"}}]},"finish_reason":"tool_calls"}],"usage":{"completion_tokens":10,"total_tokens":20,"prompt_tokens":10}}`,
410+
`data: [DONE]`,
411+
}
412+
413+
request := []byte(`{"model":"gpt-5.4","tool_choice":"auto","parallel_tool_calls":true}`)
414+
415+
var param any
416+
var completed gjson.Result
417+
for _, line := range in {
418+
for _, chunk := range ConvertOpenAIChatCompletionsResponseToOpenAIResponses(context.Background(), "model", request, request, []byte(line), &param) {
419+
ev, data := parseOpenAIResponsesSSEEvent(t, chunk)
420+
if ev == "response.completed" {
421+
completed = data
422+
}
423+
}
424+
}
425+
426+
if !completed.Exists() {
427+
t.Fatal("expected response.completed event")
428+
}
429+
if completed.Get("response.output_text").Exists() {
430+
t.Fatalf("response.output_text should be omitted to match native Responses output: %s", completed.Get("response.output_text").Raw)
431+
}
432+
if got := completed.Get("response.output.0.content.0.text").String(); got != "I will call the weather tool." {
433+
t.Fatalf("response output text = %q, want %q", got, "I will call the weather tool.")
434+
}
435+
if got := completed.Get("response.output.1.arguments").String(); !strings.Contains(got, "北京") {
436+
t.Fatalf("response function call arguments = %q, want Beijing argument", got)
437+
}
438+
}
439+
374440
func TestConvertOpenAIChatCompletionsResponseToOpenAIResponses_FunctionCallDoneAndCompletedOutputStayAscending(t *testing.T) {
375441
in := []string{
376442
`data: {"id":"resp_order","object":"chat.completion.chunk","created":1773896263,"model":"model","choices":[{"index":0,"delta":{"role":"assistant","content":null,"reasoning_content":null,"tool_calls":[{"index":0,"id":"call_glob","type":"function","function":{"name":"glob","arguments":""}}]},"finish_reason":null}]}`,
@@ -421,3 +487,18 @@ func TestConvertOpenAIChatCompletionsResponseToOpenAIResponses_FunctionCallDoneA
421487
t.Fatalf("unexpected completed function_call order: %v", completedOrder)
422488
}
423489
}
490+
491+
func TestConvertOpenAIChatCompletionsResponseToOpenAIResponsesNonStream_OmitsTopLevelOutputText(t *testing.T) {
492+
request := []byte(`{"model":"gpt-5.4"}`)
493+
raw := []byte(`{"id":"chatcmpl_output_text","object":"chat.completion","created":1773896263,"model":"model","choices":[{"index":0,"message":{"role":"assistant","content":"ping"},"finish_reason":"stop"}],"usage":{"prompt_tokens":2,"completion_tokens":1,"total_tokens":3}}`)
494+
495+
resp := ConvertOpenAIChatCompletionsResponseToOpenAIResponsesNonStream(context.Background(), "model", request, request, raw, nil)
496+
data := gjson.ParseBytes(resp)
497+
498+
if data.Get("output_text").Exists() {
499+
t.Fatalf("output_text should be omitted to match native Responses output: %s", resp)
500+
}
501+
if got := data.Get("output.0.content.0.text").String(); got != "ping" {
502+
t.Fatalf("output text = %q, want %q; response=%s", got, "ping", resp)
503+
}
504+
}

0 commit comments

Comments
 (0)