distributed-a2a 0.1.9rc5__py3-none-any.whl → 0.1.9rc6__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- distributed_a2a/executors.py +27 -5
- distributed_a2a/registry.py +7 -1
- distributed_a2a/router.py +18 -3
- {distributed_a2a-0.1.9rc5.dist-info → distributed_a2a-0.1.9rc6.dist-info}/METADATA +1 -1
- distributed_a2a-0.1.9rc6.dist-info/RECORD +13 -0
- distributed_a2a-0.1.9rc5.dist-info/RECORD +0 -13
- {distributed_a2a-0.1.9rc5.dist-info → distributed_a2a-0.1.9rc6.dist-info}/WHEEL +0 -0
- {distributed_a2a-0.1.9rc5.dist-info → distributed_a2a-0.1.9rc6.dist-info}/licenses/LICENSE +0 -0
- {distributed_a2a-0.1.9rc5.dist-info → distributed_a2a-0.1.9rc6.dist-info}/top_level.txt +0 -0
distributed_a2a/executors.py
CHANGED
|
@@ -64,11 +64,21 @@ class RoutingAgentExecutor(AgentExecutor):
|
|
|
64
64
|
if agent_response.status == TaskState.rejected:
|
|
65
65
|
routing_agent_response: RoutingResponse = await self.routing_agent(message=context.get_user_input(),
|
|
66
66
|
context_id=context.context_id)
|
|
67
|
-
|
|
67
|
+
agent_card = routing_agent_response.agent_card
|
|
68
|
+
if isinstance(agent_card, str):
|
|
69
|
+
try:
|
|
70
|
+
agent_card_dict = json.loads(agent_card)
|
|
71
|
+
except json.JSONDecodeError:
|
|
72
|
+
logger.error(f"Failed to parse agent_card as JSON: {agent_card}")
|
|
73
|
+
raise
|
|
74
|
+
else:
|
|
75
|
+
agent_card_dict = agent_card
|
|
76
|
+
|
|
77
|
+
agent_name: str = agent_card_dict["name"]
|
|
68
78
|
logger.info(f"Request with id {context.context_id} got rejected and will be rerouted to a '{agent_name}'.",
|
|
69
79
|
extra={"card": routing_agent_response.agent_card})
|
|
70
80
|
artifact = new_text_artifact(name='target_agent', description='New target agent for request.',
|
|
71
|
-
text=
|
|
81
|
+
text=json.dumps(agent_card_dict) if isinstance(agent_card_dict, dict) else str(agent_card))
|
|
72
82
|
else:
|
|
73
83
|
logger.info(f"Request with id {context.context_id} was successfully processed by agent.")
|
|
74
84
|
artifact = new_text_artifact(name='current_result', description='Result of request to agent.',
|
|
@@ -119,11 +129,23 @@ class RoutingExecutor(AgentExecutor):
|
|
|
119
129
|
agent_response: RoutingResponse = await self.routing_agent(message=context.get_user_input(),
|
|
120
130
|
context_id=context.context_id)
|
|
121
131
|
logger.info(f"Routing agent response for request with id {context.context_id}: {agent_response}")
|
|
122
|
-
|
|
132
|
+
agent_card = agent_response.agent_card
|
|
133
|
+
if isinstance(agent_card, str):
|
|
134
|
+
try:
|
|
135
|
+
agent_card_dict = json.loads(agent_card)
|
|
136
|
+
except json.JSONDecodeError:
|
|
137
|
+
# If it's not JSON, maybe it's already the name or something else?
|
|
138
|
+
# But AgentCard expects a dict if we use model_validate
|
|
139
|
+
logger.error(f"Failed to parse agent_card as JSON: {agent_card}")
|
|
140
|
+
raise
|
|
141
|
+
else:
|
|
142
|
+
agent_card_dict = agent_card
|
|
143
|
+
|
|
144
|
+
agent_name: str = agent_card_dict["name"]
|
|
123
145
|
logger.info(f"Request with id {context.context_id} got rejected and will be rerouted to a '{agent_name}'.",
|
|
124
|
-
extra={"card":
|
|
146
|
+
extra={"card": agent_card})
|
|
125
147
|
artifact = new_text_artifact(name='target_agent', description='New target agent for request.',
|
|
126
|
-
text=
|
|
148
|
+
text=json.dumps(agent_card_dict) if isinstance(agent_card_dict, dict) else str(agent_card))
|
|
127
149
|
|
|
128
150
|
# publish actual result
|
|
129
151
|
await event_queue.enqueue_event(TaskArtifactUpdateEvent(append=False,
|
distributed_a2a/registry.py
CHANGED
|
@@ -33,7 +33,13 @@ class AgentRegistryLookup:
|
|
|
33
33
|
json=agent_card,
|
|
34
34
|
timeout=30
|
|
35
35
|
)
|
|
36
|
-
|
|
36
|
+
try:
|
|
37
|
+
response.raise_for_status()
|
|
38
|
+
except requests.exceptions.HTTPError as e:
|
|
39
|
+
print(f"HTTP error during put_agent_card: {e}")
|
|
40
|
+
if response.text:
|
|
41
|
+
print(f"Response content: {response.text}")
|
|
42
|
+
raise
|
|
37
43
|
|
|
38
44
|
def as_tool(self) -> StructuredTool:
|
|
39
45
|
return StructuredTool.from_function(func=lambda: self.get_agent_cards(), name="agent_card_lookup",
|
distributed_a2a/router.py
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
from
|
|
1
|
+
from contextlib import asynccontextmanager
|
|
2
|
+
from typing import Any, AsyncGenerator
|
|
2
3
|
|
|
3
4
|
from a2a.server.apps import A2ARESTFastAPIApplication
|
|
4
5
|
from a2a.server.request_handlers import DefaultRequestHandler
|
|
@@ -8,8 +9,8 @@ from fastapi import FastAPI
|
|
|
8
9
|
|
|
9
10
|
from .executors import RoutingExecutor
|
|
10
11
|
from .model import RouterConfig
|
|
11
|
-
from .registry import
|
|
12
|
-
from .server import CAPABILITIES,
|
|
12
|
+
from .registry import AgentRegistryLookup, registry_heart_beat
|
|
13
|
+
from .server import CAPABILITIES, HEART_BEAT_INTERVAL_SEC, get_expire_at
|
|
13
14
|
|
|
14
15
|
|
|
15
16
|
def load_router(router_dic: dict[str, Any]) -> FastAPI:
|
|
@@ -36,6 +37,19 @@ def load_router(router_dic: dict[str, Any]) -> FastAPI:
|
|
|
36
37
|
routing_tool=AgentRegistryLookup(router_config.router.registry.agent.url).as_tool()
|
|
37
38
|
)
|
|
38
39
|
|
|
40
|
+
@asynccontextmanager
|
|
41
|
+
async def lifespan(_: FastAPI) -> AsyncGenerator[None, Any]:
|
|
42
|
+
if router_config.router.registry:
|
|
43
|
+
import asyncio
|
|
44
|
+
asyncio.create_task(registry_heart_beat(
|
|
45
|
+
name=agent_card.name,
|
|
46
|
+
registry_url=router_config.router.registry.agent.url,
|
|
47
|
+
agent_card=agent_card,
|
|
48
|
+
interval_sec=HEART_BEAT_INTERVAL_SEC,
|
|
49
|
+
get_expire_at=get_expire_at
|
|
50
|
+
))
|
|
51
|
+
yield
|
|
52
|
+
|
|
39
53
|
return A2ARESTFastAPIApplication(
|
|
40
54
|
agent_card=agent_card,
|
|
41
55
|
http_handler=DefaultRequestHandler(
|
|
@@ -43,4 +57,5 @@ def load_router(router_dic: dict[str, Any]) -> FastAPI:
|
|
|
43
57
|
task_store=InMemoryTaskStore() # TODO replace with dynamodb store
|
|
44
58
|
|
|
45
59
|
)).build(title=agent_card.name,
|
|
60
|
+
lifespan=lifespan,
|
|
46
61
|
root_path=f"/{router_config.router.card.name}")
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
distributed_a2a/__init__.py,sha256=gO8sTT20O6XvDRzj7B322O9v6HxV-_eIlJD1wMlPYoI,171
|
|
2
|
+
distributed_a2a/agent.py,sha256=qY775N3Br2YMuaHLALU4t6MO47syuEoTtFLLPRr8TyA,2910
|
|
3
|
+
distributed_a2a/client.py,sha256=3tEBqu3HKEQyOFk5vsO1YiuKP2pZx-n6SCzsJUYNcyc,4601
|
|
4
|
+
distributed_a2a/executors.py,sha256=gu3MdnUldOt-9yUJA2xkmJNoDyhwH7qyznRY4lwlTys,8226
|
|
5
|
+
distributed_a2a/model.py,sha256=x-Es1WIm-MMBMizD3CePXf04mpWLiqRCYbz61KGDLRc,3535
|
|
6
|
+
distributed_a2a/registry.py,sha256=4OK_Zbsq38UNKliyagifKfDG6nUIhflxq0VAoqeLKgM,2368
|
|
7
|
+
distributed_a2a/router.py,sha256=jBk_tR8Qbq-PDTYm0-R9OHCCwuEYm5qv1r5QTopJ0D4,2404
|
|
8
|
+
distributed_a2a/server.py,sha256=JVIcdjyjtVhP-YTeoaOb0R7d0honC_JPR0aQfJ4P_SQ,3434
|
|
9
|
+
distributed_a2a-0.1.9rc6.dist-info/licenses/LICENSE,sha256=Btzdu2kIoMbdSp6OyCLupB1aRgpTCJ_szMimgEnpkkE,1056
|
|
10
|
+
distributed_a2a-0.1.9rc6.dist-info/METADATA,sha256=Llaxl5djnyFtqrwbyLpCRJVhZ0e3wyGb38pamDx3xkY,3198
|
|
11
|
+
distributed_a2a-0.1.9rc6.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
|
|
12
|
+
distributed_a2a-0.1.9rc6.dist-info/top_level.txt,sha256=23qJ8n5k7796BHDK7a58uuO-X4GV0EgUWcGi8NIn-0k,16
|
|
13
|
+
distributed_a2a-0.1.9rc6.dist-info/RECORD,,
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
distributed_a2a/__init__.py,sha256=gO8sTT20O6XvDRzj7B322O9v6HxV-_eIlJD1wMlPYoI,171
|
|
2
|
-
distributed_a2a/agent.py,sha256=qY775N3Br2YMuaHLALU4t6MO47syuEoTtFLLPRr8TyA,2910
|
|
3
|
-
distributed_a2a/client.py,sha256=3tEBqu3HKEQyOFk5vsO1YiuKP2pZx-n6SCzsJUYNcyc,4601
|
|
4
|
-
distributed_a2a/executors.py,sha256=xinzle76ZpIpbAs1RqolaDKwABCQkz6mmrfE7gRqnFY,7258
|
|
5
|
-
distributed_a2a/model.py,sha256=x-Es1WIm-MMBMizD3CePXf04mpWLiqRCYbz61KGDLRc,3535
|
|
6
|
-
distributed_a2a/registry.py,sha256=2QDxCY02tkI8MsLA4JPYEzFSV4LuuKPtCVVx-u8BniU,2132
|
|
7
|
-
distributed_a2a/router.py,sha256=SRYBgLiN4j7JDIKb_9D8ypJxqVYs_fFlG5dgWYIbF7o,1803
|
|
8
|
-
distributed_a2a/server.py,sha256=JVIcdjyjtVhP-YTeoaOb0R7d0honC_JPR0aQfJ4P_SQ,3434
|
|
9
|
-
distributed_a2a-0.1.9rc5.dist-info/licenses/LICENSE,sha256=Btzdu2kIoMbdSp6OyCLupB1aRgpTCJ_szMimgEnpkkE,1056
|
|
10
|
-
distributed_a2a-0.1.9rc5.dist-info/METADATA,sha256=vUagOB9LxhhSFNh2yYPkFTjKnUcOtMeRe19SCX-06WA,3198
|
|
11
|
-
distributed_a2a-0.1.9rc5.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
|
|
12
|
-
distributed_a2a-0.1.9rc5.dist-info/top_level.txt,sha256=23qJ8n5k7796BHDK7a58uuO-X4GV0EgUWcGi8NIn-0k,16
|
|
13
|
-
distributed_a2a-0.1.9rc5.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|