patrickcmd's picture
Deploy: sync from local
ad6dc26 verified
"""Chat orchestration: run the agent against a user turn, stream tokens, return cost."""
from typing import AsyncIterator
from agents import Agent, Runner, SQLiteSession
from openai.types.responses import ResponseTextDeltaEvent
from .cost import CostBreakdown, cost_from_usage
async def chat_turn(
user_message: str,
agent: Agent,
session: SQLiteSession,
max_turns: int = 8,
) -> AsyncIterator[tuple[str, CostBreakdown | None]]:
"""Run one user turn. Yields (accumulated_text, cost_or_None).
Cost is None on every yield until the final one — the final yield contains
the same accumulated text plus the run's cost breakdown.
"""
result = Runner.run_streamed(
agent,
user_message,
session=session,
max_turns=max_turns,
)
text = ""
async for event in result.stream_events():
if event.type == "raw_response_event" and isinstance(
event.data, ResponseTextDeltaEvent
):
text += event.data.delta
yield text, None
cost = cost_from_usage(result.context_wrapper.usage)
yield text, cost