mirror of
https://github.com/CJackHwang/ds2api.git
synced 2026-05-04 16:35:27 +08:00
test: cover openai formatter string protection
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
This commit is contained in:
@@ -1,8 +1,11 @@
|
||||
package openai
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"ds2api/internal/toolcall"
|
||||
)
|
||||
|
||||
func TestBuildResponseObjectKeepsFencedToolPayloadAsText(t *testing.T) {
|
||||
@@ -13,6 +16,7 @@ func TestBuildResponseObjectKeepsFencedToolPayloadAsText(t *testing.T) {
|
||||
"",
|
||||
"```json\n{\"tool_calls\":[{\"name\":\"search\",\"input\":{\"q\":\"golang\"}}]}\n```",
|
||||
[]string{"search"},
|
||||
nil,
|
||||
)
|
||||
|
||||
outputText, _ := obj["output_text"].(string)
|
||||
@@ -42,6 +46,7 @@ func TestBuildResponseObjectReasoningOnlyFallsBackToOutputText(t *testing.T) {
|
||||
"internal thinking content",
|
||||
"",
|
||||
nil,
|
||||
nil,
|
||||
)
|
||||
|
||||
outputText, _ := obj["output_text"].(string)
|
||||
@@ -75,6 +80,7 @@ func TestBuildResponseObjectPromotesToolCallFromThinkingWhenTextEmpty(t *testing
|
||||
`<tool_calls><invoke name="search"><parameter name="q">from-thinking</parameter></invoke></tool_calls>`,
|
||||
"",
|
||||
[]string{"search"},
|
||||
nil,
|
||||
)
|
||||
|
||||
output, _ := obj["output"].([]any)
|
||||
@@ -86,3 +92,88 @@ func TestBuildResponseObjectPromotesToolCallFromThinkingWhenTextEmpty(t *testing
|
||||
t.Fatalf("expected function_call output, got %#v", first["type"])
|
||||
}
|
||||
}
|
||||
|
||||
func TestBuildChatCompletionWithToolCallsCoercesSchemaDeclaredStringArguments(t *testing.T) {
|
||||
toolsRaw := []any{
|
||||
map[string]any{
|
||||
"type": "function",
|
||||
"function": map[string]any{
|
||||
"name": "Write",
|
||||
"parameters": map[string]any{
|
||||
"type": "object",
|
||||
"properties": map[string]any{
|
||||
"content": map[string]any{"type": "string"},
|
||||
"taskId": map[string]any{"type": "string"},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
obj := BuildChatCompletionWithToolCalls(
|
||||
"chat_test",
|
||||
"gpt-4o",
|
||||
"prompt",
|
||||
"",
|
||||
"",
|
||||
[]toolcall.ParsedToolCall{{
|
||||
Name: "Write",
|
||||
Input: map[string]any{
|
||||
"content": map[string]any{"message": "hi"},
|
||||
"taskId": 1,
|
||||
},
|
||||
}},
|
||||
toolsRaw,
|
||||
)
|
||||
choices, _ := obj["choices"].([]map[string]any)
|
||||
message, _ := choices[0]["message"].(map[string]any)
|
||||
toolCalls, _ := message["tool_calls"].([]map[string]any)
|
||||
fn, _ := toolCalls[0]["function"].(map[string]any)
|
||||
args := map[string]any{}
|
||||
if err := json.Unmarshal([]byte(fn["arguments"].(string)), &args); err != nil {
|
||||
t.Fatalf("decode arguments failed: %v", err)
|
||||
}
|
||||
if args["content"] != `{"message":"hi"}` {
|
||||
t.Fatalf("expected content stringified by schema, got %#v", args["content"])
|
||||
}
|
||||
if args["taskId"] != "1" {
|
||||
t.Fatalf("expected taskId stringified by schema, got %#v", args["taskId"])
|
||||
}
|
||||
}
|
||||
|
||||
func TestBuildResponseObjectWithToolCallsCoercesSchemaDeclaredStringArguments(t *testing.T) {
|
||||
toolsRaw := []any{
|
||||
map[string]any{
|
||||
"type": "function",
|
||||
"function": map[string]any{
|
||||
"name": "Write",
|
||||
"parameters": map[string]any{
|
||||
"type": "object",
|
||||
"properties": map[string]any{
|
||||
"content": map[string]any{"type": "string"},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
obj := BuildResponseObjectWithToolCalls(
|
||||
"resp_test",
|
||||
"gpt-4o",
|
||||
"prompt",
|
||||
"",
|
||||
"",
|
||||
[]toolcall.ParsedToolCall{{
|
||||
Name: "Write",
|
||||
Input: map[string]any{"content": []any{"a", 1}},
|
||||
}},
|
||||
toolsRaw,
|
||||
)
|
||||
output, _ := obj["output"].([]any)
|
||||
first, _ := output[0].(map[string]any)
|
||||
args := map[string]any{}
|
||||
if err := json.Unmarshal([]byte(first["arguments"].(string)), &args); err != nil {
|
||||
t.Fatalf("decode response arguments failed: %v", err)
|
||||
}
|
||||
if args["content"] != `["a",1]` {
|
||||
t.Fatalf("expected response content stringified by schema, got %#v", args["content"])
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user