From afdbda91bf4402fafc4b9f6cc1b6b1e92ce99a2c Mon Sep 17 00:00:00 2001 From: robert Date: Sat, 6 Jun 2026 21:52:38 -0300 Subject: [PATCH] Bound builder runs and require a2a-pack 0.1.76 --- agent.py | 43 ++++++++++++++++++++++++++++++++++++++---- agent_builder/tools.py | 2 +- requirements.txt | 2 +- 3 files changed, 41 insertions(+), 6 deletions(-) diff --git a/agent.py b/agent.py index 9cedfd1..87c1243 100644 --- a/agent.py +++ b/agent.py @@ -39,6 +39,7 @@ class BuilderConfig(BaseModel): _URL_RE = re.compile(r"https?://[a-zA-Z0-9._-]+\.[a-zA-Z]{2,}[\w/?#%&=.-]*") DEEPAGENTS_RECURSION_LIMIT = 500 +BUILDER_WALL_TIMEOUT_SECONDS = 25 * 60 class AgentBuilder(A2AAgent[BuilderConfig, NoAuth]): @@ -165,8 +166,7 @@ class AgentBuilder(A2AAgent[BuilderConfig, NoAuth]): await asyncio.sleep(20) await ctx.emit_progress(f"agent-builder still working on {name!r}") - heartbeat_task = asyncio.create_task(_heartbeat()) - try: + async def _run_build_graph() -> None: async for event in graph.astream_events( {"messages": [{"role": "user", "content": user_msg}]}, version="v2", @@ -193,8 +193,43 @@ class AgentBuilder(A2AAgent[BuilderConfig, NoAuth]): out = data.get("output") if isinstance(out, dict): final_state = out + + heartbeat_task = asyncio.create_task(_heartbeat()) + try: + await asyncio.wait_for( + _run_build_graph(), + timeout=BUILDER_WALL_TIMEOUT_SECONDS, + ) + except TimeoutError: + return { + "ok": False, + "status": "failed", + "stop_reason": "builder_timeout", + "name": name, + "workspace_dir": f"agents/{name}/", + "error": ( + "agent-builder exceeded its wall-clock budget before " + "reaching a terminal result" + ), + } + except asyncio.CancelledError: + return { + "ok": False, + "status": "canceled", + "stop_reason": "builder_canceled", + "name": name, + "workspace_dir": f"agents/{name}/", + "error": "agent-builder was canceled before it reached a terminal result", + } except Exception as exc: # noqa: BLE001 - return {"error": _build_failure_error(exc)} + return { + "ok": False, + "status": "failed", + "stop_reason": "builder_failed", + "name": name, + "workspace_dir": f"agents/{name}/", + "error": _build_failure_error(exc), + } finally: heartbeat_task.cancel() with suppress(asyncio.CancelledError): @@ -298,4 +333,4 @@ def _build_failure_error(exc: BaseException) -> str: "or a smaller build scope" ) return f"build graph failed: {type(exc).__name__}: {exc}" -# rebuild against a2a-pack 0.1.75 for source-grant-aware agent updates +# rebuild against a2a-pack 0.1.76 for source-grant-aware agent updates diff --git a/agent_builder/tools.py b/agent_builder/tools.py index b8d7435..3ac6078 100644 --- a/agent_builder/tools.py +++ b/agent_builder/tools.py @@ -31,7 +31,7 @@ if TYPE_CHECKING: from .config import Settings -A2A_PACK_MIN_VERSION = "0.1.75" +A2A_PACK_MIN_VERSION = "0.1.76" @dataclass(frozen=True) diff --git a/requirements.txt b/requirements.txt index f3ab529..a2e4132 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,4 +1,4 @@ -a2a-pack>=0.1.75 +a2a-pack>=0.1.76 httpx>=0.27 boto3>=1.34 deepagents>=0.5.0