TestChatToolCallMultipleByIndex: two tool calls interleaved across chunks. Each fragment must route to its slot by `index`, not by slice position.
(t *testing.T)
| 199 | // TestChatToolCallMultipleByIndex: two tool calls interleaved across chunks. |
| 200 | // Each fragment must route to its slot by `index`, not by slice position. |
| 201 | func TestChatToolCallMultipleByIndex(t *testing.T) { |
| 202 | srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { |
| 203 | sseOK(w, []string{ |
| 204 | `{"choices":[{"delta":{"tool_calls":[{"index":0,"id":"c1","function":{"name":"bash"}}]}}]}`, |
| 205 | `{"choices":[{"delta":{"tool_calls":[{"index":1,"id":"c2","function":{"name":"python"}}]}}]}`, |
| 206 | `{"choices":[{"delta":{"tool_calls":[{"index":0,"function":{"arguments":"{\"cmd\":\"ls\"}"}}]}}]}`, |
| 207 | `{"choices":[{"delta":{"tool_calls":[{"index":1,"function":{"arguments":"{\"cmd\":\"print()\"}"}}]}}]}`, |
| 208 | `{"choices":[{"delta":{},"finish_reason":"tool_calls"}]}`, |
| 209 | }) |
| 210 | })) |
| 211 | defer srv.Close() |
| 212 | c := New(srv.URL, "m", "") |
| 213 | var calls []chmctx.ToolCall |
| 214 | for _, e := range collect(c.Chat(context.Background(), nil, nil)) { |
| 215 | if e.Kind == EventToolCall { |
| 216 | calls = append(calls, *e.ToolCall) |
| 217 | } |
| 218 | } |
| 219 | if len(calls) != 2 { |
| 220 | t.Fatalf("want 2 tool-call events, got %d: %+v", len(calls), calls) |
| 221 | } |
| 222 | byName := map[string]map[string]any{} |
| 223 | for _, c := range calls { |
| 224 | byName[c.Name] = c.Arguments |
| 225 | } |
| 226 | if cmd, _ := byName["bash"]["cmd"].(string); cmd != "ls" { |
| 227 | t.Fatalf("bash args wrong: %+v", byName["bash"]) |
| 228 | } |
| 229 | if cmd, _ := byName["python"]["cmd"].(string); cmd != "print()" { |
| 230 | t.Fatalf("python args wrong: %+v", byName["python"]) |
| 231 | } |
| 232 | } |
| 233 | |
| 234 | // TestChatDispatchesToolCallsOnFinishStop: Ollama's /v1 shim sometimes emits |
| 235 | // finish_reason="stop" even after streaming tool_calls. The client must still |