| 1 | package responses |
| 2 | |
| 3 | import ( |
| 4 | "encoding/json" |
| 5 | "strings" |
| 6 | "testing" |
| 7 | |
| 8 | "reasonix/internal/provider" |
| 9 | ) |
| 10 | |
| 11 | func TestBuildRequestBodyExcludesToolExecution(t *testing.T) { |
| 12 | code := 1 |
| 13 | msgs := []provider.Message{ |
| 14 | {Role: provider.RoleUser, Content: "run tests"}, |
| 15 | {Role: provider.RoleAssistant, ToolCalls: []provider.ToolCall{ |
| 16 | {ID: "call_1", Name: "bash", Arguments: `{"command":"go test ./..."}`}, |
| 17 | }}, |
| 18 | { |
| 19 | Role: provider.RoleTool, ToolCallID: "call_1", Name: "bash", Content: "FAIL", |
| 20 | ToolExecution: &provider.ToolExecution{ |
| 21 | Kind: "shell", Shell: "bash", State: "failed", ExitCode: &code, |
| 22 | FailurePhase: "execution", OutputTail: "中文stderr-marker-must-not-leak", |
| 23 | }, |
| 24 | }, |
| 25 | } |
| 26 | // Production Responses path applies ModelMessages inside buildRequestBody. |
| 27 | bodyMap, _, _ := (&client{model: "gpt-test"}).buildRequestBody(provider.Request{Messages: msgs}) |
| 28 | body, err := json.Marshal(bodyMap) |
| 29 | if err != nil { |
| 30 | t.Fatal(err) |
| 31 | } |
| 32 | s := string(body) |
| 33 | for _, banned := range []string{"tool_execution", "outputTail", "中文stderr-marker-must-not-leak", "failurePhase", "mutationRisk"} { |
| 34 | if strings.Contains(s, banned) { |
| 35 | t.Fatalf("responses wire leaked %q: %s", banned, s) |
| 36 | } |
| 37 | } |
| 38 | } |
| 39 | |
| 40 | func TestBuildRequestBodyStableWhenLocalExecutionAdded(t *testing.T) { |
| 41 | base := []provider.Message{ |
| 42 | {Role: provider.RoleUser, Content: "run"}, |
| 43 | {Role: provider.RoleAssistant, ToolCalls: []provider.ToolCall{{ID: "c1", Name: "bash", Arguments: `{"command":"true"}`}}}, |
| 44 | {Role: provider.RoleTool, ToolCallID: "c1", Name: "bash", Content: "ok"}, |
| 45 | } |
| 46 | code := 0 |
| 47 | withMeta := append([]provider.Message(nil), base...) |
| 48 | withMeta[2].ToolExecution = &provider.ToolExecution{Kind: "shell", OutputTail: "noise", ExitCode: &code} |
| 49 | |
| 50 | aMap, _, _ := (&client{model: "gpt-test"}).buildRequestBody(provider.Request{Messages: base}) |
| 51 | bMap, _, _ := (&client{model: "gpt-test"}).buildRequestBody(provider.Request{Messages: withMeta}) |
| 52 | a, err := json.Marshal(aMap) |
| 53 | if err != nil { |
| 54 | t.Fatal(err) |
| 55 | } |
| 56 | b, err := json.Marshal(bMap) |
| 57 | if err != nil { |
| 58 | t.Fatal(err) |
| 59 | } |
| 60 | if string(a) != string(b) { |
| 61 | t.Fatalf("responses request diverged\nbase=%s\nmeta=%s", a, b) |
| 62 | } |
| 63 | } |
| 64 |