TestChatToolCall: tool_calls in a delta emit EventToolCall and ride along in EventDone.Final.ToolCalls so the next turn can replay the assistant message.
(t *testing.T)
| 95 | // TestChatToolCall: tool_calls in a delta emit EventToolCall and ride along in |
| 96 | // EventDone.Final.ToolCalls so the next turn can replay the assistant message. |
| 97 | func TestChatToolCall(t *testing.T) { |
| 98 | srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { |
| 99 | sseOK(w, []string{ |
| 100 | `{"choices":[{"delta":{"tool_calls":[{"index":0,"id":"c1","function":{"name":"bash","arguments":"{\"cmd\":\"ls\"}"}}]}}]}`, |
| 101 | `{"choices":[{"delta":{},"finish_reason":"tool_calls"}],"usage":{"completion_tokens":5}}`, |
| 102 | }) |
| 103 | })) |
| 104 | defer srv.Close() |
| 105 | c := New(srv.URL, "m", "") |
| 106 | var got *chmctx.ToolCall |
| 107 | var final *chmctx.Message |
| 108 | for _, e := range collect(c.Chat(context.Background(), nil, nil)) { |
| 109 | switch e.Kind { |
| 110 | case EventToolCall: |
| 111 | got = e.ToolCall |
| 112 | case EventDone: |
| 113 | final = e.Final |
| 114 | } |
| 115 | } |
| 116 | if got == nil || got.Name != "bash" { |
| 117 | t.Fatalf("tool call missing: %+v", got) |
| 118 | } |
| 119 | if cmd, _ := got.Arguments["cmd"].(string); cmd != "ls" { |
| 120 | t.Fatalf("tool args wrong: %+v", got.Arguments) |
| 121 | } |
| 122 | if final == nil || len(final.ToolCalls) != 1 || final.ToolCalls[0].Name != "bash" { |
| 123 | t.Fatalf("Final.ToolCalls should carry the bash call: %+v", final) |
| 124 | } |
| 125 | } |
| 126 | |
| 127 | // TestChatToolCallFragmentedArgs: `arguments` arrives as JSON fragments, each |
| 128 | // invalid alone. The client must accumulate raw and parse once at finish_reason. |