|
32 | 32 | from typing import Union |
33 | 33 |
|
34 | 34 | from google.genai import types |
| 35 | +from opentelemetry import context |
35 | 36 | from pydantic import BaseModel |
36 | 37 | from pydantic import ConfigDict |
37 | 38 | from pydantic import Field |
@@ -87,6 +88,21 @@ class BaseAgentState(BaseModel): |
87 | 88 |
|
88 | 89 |
|
89 | 90 | AgentState = TypeVar('AgentState', bound=BaseAgentState) |
| 91 | +_T = TypeVar('_T') |
| 92 | + |
| 93 | + |
| 94 | +async def _with_caller_context( |
| 95 | + agen: AsyncGenerator[_T, None], |
| 96 | + caller_ctx: context.Context, |
| 97 | +) -> AsyncGenerator[_T, None]: |
| 98 | + """Wraps an async generator to attach caller_ctx around each yield.""" |
| 99 | + async with Aclosing(agen) as a: |
| 100 | + async for item in a: |
| 101 | + token = context.attach(caller_ctx) |
| 102 | + try: |
| 103 | + yield item |
| 104 | + finally: |
| 105 | + context.detach(token) |
90 | 106 |
|
91 | 107 |
|
92 | 108 | # TODO: drop the explicit abc.ABC base once BaseNode surfaces ABCMeta to |
@@ -295,26 +311,33 @@ async def run_async( |
295 | 311 | Event: the events generated by the agent. |
296 | 312 | """ |
297 | 313 |
|
298 | | - ctx = self._create_invocation_context(parent_context) |
299 | | - async with _instrumentation.record_agent_invocation(ctx, self): |
300 | | - try: |
301 | | - if event := await self._handle_before_agent_callback(ctx): |
302 | | - yield event |
303 | | - if ctx.end_invocation: |
304 | | - return |
| 314 | + caller_ctx = context.get_current() |
305 | 315 |
|
306 | | - async with Aclosing(self._run_async_impl(ctx)) as agen: |
307 | | - async for event in agen: |
| 316 | + async def _run() -> AsyncGenerator[Event, None]: |
| 317 | + ctx = self._create_invocation_context(parent_context) |
| 318 | + async with _instrumentation.record_agent_invocation(ctx, self): |
| 319 | + try: |
| 320 | + if event := await self._handle_before_agent_callback(ctx): |
308 | 321 | yield event |
| 322 | + if ctx.end_invocation: |
| 323 | + return |
| 324 | + |
| 325 | + async with Aclosing(self._run_async_impl(ctx)) as agen: |
| 326 | + async for event in agen: |
| 327 | + yield event |
309 | 328 |
|
310 | | - if ctx.end_invocation: |
311 | | - return |
| 329 | + if ctx.end_invocation: |
| 330 | + return |
312 | 331 |
|
313 | | - if event := await self._handle_after_agent_callback(ctx): |
314 | | - yield event |
315 | | - except Exception as e: |
316 | | - await self._handle_agent_error_callback(ctx, e) |
317 | | - raise |
| 332 | + if event := await self._handle_after_agent_callback(ctx): |
| 333 | + yield event |
| 334 | + except Exception as e: |
| 335 | + await self._handle_agent_error_callback(ctx, e) |
| 336 | + raise |
| 337 | + |
| 338 | + async with Aclosing(_with_caller_context(_run(), caller_ctx)) as agen: |
| 339 | + async for event in agen: |
| 340 | + yield event |
318 | 341 |
|
319 | 342 | @override |
320 | 343 | async def _run_impl( |
@@ -350,23 +373,30 @@ async def run_live( |
350 | 373 | Event: the events generated by the agent. |
351 | 374 | """ |
352 | 375 |
|
353 | | - ctx = self._create_invocation_context(parent_context) |
354 | | - async with _instrumentation.record_agent_invocation(ctx, self): |
355 | | - try: |
356 | | - if event := await self._handle_before_agent_callback(ctx): |
357 | | - yield event |
358 | | - if ctx.end_invocation: |
359 | | - return |
| 376 | + caller_ctx = context.get_current() |
| 377 | + |
| 378 | + async def _run() -> AsyncGenerator[Event, None]: |
| 379 | + ctx = self._create_invocation_context(parent_context) |
| 380 | + async with _instrumentation.record_agent_invocation(ctx, self): |
| 381 | + try: |
| 382 | + if event := await self._handle_before_agent_callback(ctx): |
| 383 | + yield event |
| 384 | + if ctx.end_invocation: |
| 385 | + return |
| 386 | + |
| 387 | + async with Aclosing(self._run_live_impl(ctx)) as agen: |
| 388 | + async for event in agen: |
| 389 | + yield event |
360 | 390 |
|
361 | | - async with Aclosing(self._run_live_impl(ctx)) as agen: |
362 | | - async for event in agen: |
| 391 | + if event := await self._handle_after_agent_callback(ctx): |
363 | 392 | yield event |
| 393 | + except Exception as e: |
| 394 | + await self._handle_agent_error_callback(ctx, e) |
| 395 | + raise |
364 | 396 |
|
365 | | - if event := await self._handle_after_agent_callback(ctx): |
366 | | - yield event |
367 | | - except Exception as e: |
368 | | - await self._handle_agent_error_callback(ctx, e) |
369 | | - raise |
| 397 | + async with Aclosing(_with_caller_context(_run(), caller_ctx)) as agen: |
| 398 | + async for event in agen: |
| 399 | + yield event |
370 | 400 |
|
371 | 401 | async def _run_async_impl( |
372 | 402 | self, ctx: InvocationContext |
|
0 commit comments