TestChatReadsUsageTokens: tokens come from `usage.completion_tokens` (and prompt_tokens rides along for the debug-log calibration), not content length; we trust what the backend reports.
(t *testing.T)
| 393 | // turn re-sends corrupt JSON and the backend 400s forever (session poisoning). |
| 394 | func TestToInputParseErrorArgsStayValidJSON(t *testing.T) { |
| 395 | items := toInput([]chmctx.Message{{ |
| 396 | Role: chmctx.RoleAssistant, |
| 397 | ToolCalls: []chmctx.ToolCall{{ |
| 398 | ID: "c1", |
| 399 | Name: "write_file", |
| 400 | Arguments: map[string]any{"_parse_error": "unexpected end of JSON input"}, |
| 401 | }}, |
| 402 | }}) |
| 403 | args := items[0].(functionCallItem).Arguments |
| 404 | if !json.Valid([]byte(args)) { |
| 405 | t.Fatalf("arguments must stay valid JSON to avoid poisoning the session: %q", args) |
| 406 | } |
| 407 | } |
| 408 | |
| 409 | // TestChatToolsAreFlat: the Responses tool declaration has no `function` |
| 410 | // wrapper; the old chat-completions nesting 400s here. |
| 411 | func TestChatToolsAreFlat(t *testing.T) { |
| 412 | var gotBody string |
| 413 | srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { |
| 414 | b, _ := io.ReadAll(r.Body) |
| 415 | gotBody = string(b) |
| 416 | sseOK(w, []string{completed(0, 0)}) |
| 417 | })) |
| 418 | defer srv.Close() |