From 970a262554a1d78ff47c8f6f5ef491dd0809e9a8 Mon Sep 17 00:00:00 2001 From: Claude Opus 5 Date: Mon, 3 Aug 2026 15:36:24 -0400 Subject: [PATCH] Cover Ollama streaming tool calling with a test The streaming tool loop landed without a test, so nothing checked that tool activity reaches the transcript while the stream is still running rather than only at the end. `streamWithTools` asserts the tool calls and tool output entries appear during iteration, that the output survives into the final transcript, and that the tool was invoked once with the expected arguments. It mirrors the Anthropic suite's equivalent and reuses this suite's `spy(on:)` fixture. --- .../OllamaLanguageModelTests.swift | 35 +++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/Tests/AnyLanguageModelTests/OllamaLanguageModelTests.swift b/Tests/AnyLanguageModelTests/OllamaLanguageModelTests.swift index 5a8911f0..d460cdc8 100644 --- a/Tests/AnyLanguageModelTests/OllamaLanguageModelTests.swift +++ b/Tests/AnyLanguageModelTests/OllamaLanguageModelTests.swift @@ -146,6 +146,41 @@ struct OllamaLanguageModelTests { } } + @Test func streamWithTools() async throws { + let weatherTool = spy(on: WeatherTool()) + let session = LanguageModelSession(model: model, tools: [weatherTool]) + + let stream = session.streamResponse(to: "How's the weather in San Francisco?") + + var toolCallAppearedDuringStream = false + var toolOutputAppearedDuringStream = false + + for try await _ in stream { + for entry in session.transcript { + switch entry { + case .toolCalls: toolCallAppearedDuringStream = true + case .toolOutput: toolOutputAppearedDuringStream = true + default: break + } + } + } + + #expect(toolCallAppearedDuringStream, "Expected a tool call in the transcript while streaming.") + #expect(toolOutputAppearedDuringStream, "Expected a tool output in the transcript while streaming.") + + var foundToolOutput = false + for case let .toolOutput(toolOutput) in session.transcript { + #expect(!toolOutput.id.isEmpty) + #expect(toolOutput.toolName == weatherTool.name) + foundToolOutput = true + } + #expect(foundToolOutput, "Expected the tool output to remain in the final transcript.") + + let calls = await weatherTool.calls + #expect(calls.count == 1) + #expect(calls.first?.arguments.city == "San Francisco") + } + @Test func multimodalWithImageURL() async throws { let transcript = Transcript(entries: [ .prompt(