(t *testing.T)
| 4559 | } |
| 4560 | |
| 4561 | func TestDynamicToolCallMixedWithBuiltIn(t *testing.T) { |
| 4562 | t.Parallel() |
| 4563 | |
| 4564 | db, ps := dbtestutil.NewDB(t) |
| 4565 | ctx := testutil.Context(t, testutil.WaitLong) |
| 4566 | |
| 4567 | // Track streaming calls to the mock LLM. |
| 4568 | var streamedCallCount atomic.Int32 |
| 4569 | var streamedCallsMu sync.Mutex |
| 4570 | streamedCalls := make([]chattest.OpenAIRequest, 0, 2) |
| 4571 | |
| 4572 | openAIURL := chattest.NewOpenAI(t, func(req *chattest.OpenAIRequest) chattest.OpenAIResponse { |
| 4573 | if !req.Stream { |
| 4574 | return chattest.OpenAINonStreamingResponse("Mixed tool test") |
| 4575 | } |
| 4576 | |
| 4577 | streamedCallsMu.Lock() |
| 4578 | streamedCalls = append(streamedCalls, chattest.OpenAIRequest{ |
| 4579 | Messages: append([]chattest.OpenAIMessage(nil), req.Messages...), |
| 4580 | Tools: append([]chattest.OpenAITool(nil), req.Tools...), |
| 4581 | Stream: req.Stream, |
| 4582 | }) |
| 4583 | streamedCallsMu.Unlock() |
| 4584 | |
| 4585 | if streamedCallCount.Add(1) == 1 { |
| 4586 | // First call: return TWO tool calls in one |
| 4587 | // response: a built-in tool (read_file) and a |
| 4588 | // dynamic tool (my_dynamic_tool). |
| 4589 | builtinChunk := chattest.OpenAIToolCallChunk( |
| 4590 | "read_file", |
| 4591 | `{"path":"/tmp/test.txt"}`, |
| 4592 | ) |
| 4593 | dynamicChunk := chattest.OpenAIToolCallChunk( |
| 4594 | "my_dynamic_tool", |
| 4595 | `{"input":"hello world"}`, |
| 4596 | ) |
| 4597 | // Merge both tool calls into one chunk with |
| 4598 | // separate indices so the LLM appears to have |
| 4599 | // requested both tools simultaneously. |
| 4600 | mergedChunk := builtinChunk |
| 4601 | dynCall := dynamicChunk.Choices[0].ToolCalls[0] |
| 4602 | dynCall.Index = 1 |
| 4603 | mergedChunk.Choices[0].ToolCalls = append( |
| 4604 | mergedChunk.Choices[0].ToolCalls, |
| 4605 | dynCall, |
| 4606 | ) |
| 4607 | return chattest.OpenAIStreamingResponse(mergedChunk) |
| 4608 | } |
| 4609 | // Second call (after tool results): normal text |
| 4610 | // response. |
| 4611 | return chattest.OpenAIStreamingResponse( |
| 4612 | chattest.OpenAITextChunks("All done.")..., |
| 4613 | ) |
| 4614 | }) |
| 4615 | |
| 4616 | user, org, model := seedChatDependenciesWithProvider(t, db, "openai-compat", openAIURL) |
| 4617 | server := newActiveTestServer(t, db, ps) |
| 4618 |
nothing calls this directly
no test coverage detected