fix: use run() instead of run_stream() for scoped tools to avoid Ollama 400 bug

PydanticAI + Ollama streaming with tool calls has known issues:
- Issue #1292: Streaming stops after tool call due to empty TextPart
- Issue #2256: Empty text part causes run to end prematurely

This change uses run() for the actual tool execution while still
yielding the response in chunks to maintain the streaming UX.
The orchestration loop can emit <think> updates between await calls.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
2025-12-12 10:59:58 +01:00
co-authored by Claude Opus 4.5
parent 4efa717796
commit b5ee1f3e44
+13 -6
View File
@@ -587,16 +587,23 @@ class TatlockAgent(AgentInterface):
ModelResponse(parts=[TextPart(content=content)])
)
# Stream with scoped tools and tracker
async with scoped_agent.run_stream(
# Use run() instead of run_stream() to avoid Ollama 400 bug
# with streaming + tool calls (PydanticAI issues #1292, #2256)
# We yield the final response in chunks to maintain streaming interface
result = await scoped_agent.run(
enriched_message,
message_history=pydantic_history if pydantic_history else None,
deps=tool_tracker
) as stream:
async for chunk in stream.stream_text(delta=True):
yield chunk
)
logger.info("tatlock_stream_complete")
# Stream the final response in chunks to maintain UX
response_text = result.output
chunk_size = 50 # characters per chunk
for i in range(0, len(response_text), chunk_size):
yield response_text[i:i + chunk_size]
logger.info("tatlock_scoped_run_complete")
async def get_capabilities(self) -> dict:
"""Return current capabilities."""