smarta2a 0.4.21__py3-none-any.whl → 0.4.23__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.
@@ -37,7 +37,7 @@ class A2AHuman:
37
37
 
38
38
  @self.app.on_send_task(forward_to_webhook=True)
39
39
  async def on_send_task(request: SendTaskRequest, state: StateData):
40
- return "I am human and take some time to respond, but I will definitely respond to your request"
40
+ return "I am human and will take some time to respond, please standby"
41
41
 
42
42
  @self.app.webhook()
43
43
  async def on_webhook(request: WebhookRequest, state: StateData):
smarta2a/server/server.py CHANGED
@@ -108,7 +108,7 @@ class SmartA2A:
108
108
  # <-- Accept both SSE‐style responses:
109
109
  if isinstance(response, (EventSourceResponse, StreamingResponse)):
110
110
  return response
111
- print(response)
111
+
112
112
  # <-- Everything else is a normal pydantic JSONRPCResponse
113
113
  return response.model_dump()
114
114
 
@@ -1,15 +1,19 @@
1
1
  # Library imports
2
2
  from typing import Callable, Any, Optional
3
+ import copy
4
+ from uuid import uuid4
3
5
 
4
6
  # Local imports
5
7
  from smarta2a.server.state_manager import StateManager
6
- from smarta2a.utils.types import WebhookRequest, WebhookResponse, StateData, Message
8
+ from smarta2a.utils.types import WebhookRequest, WebhookResponse, StateData, Message, TaskState
9
+ from smarta2a.utils.task_builder import TaskBuilder
7
10
  from smarta2a.client.a2a_client import A2AClient
8
11
 
9
12
  class WebhookRequestProcessor:
10
13
  def __init__(self, webhook_fn: Callable[[WebhookRequest], Any], state_manager: Optional[StateManager] = None):
11
14
  self.webhook_fn = webhook_fn
12
15
  self.state_manager = state_manager
16
+ self.task_builder = TaskBuilder(default_status=TaskState.COMPLETED)
13
17
  self.a2a_aclient = A2AClient()
14
18
 
15
19
  async def process_request(self, request: WebhookRequest) -> WebhookResponse:
@@ -18,67 +22,111 @@ class WebhookRequestProcessor:
18
22
  return await self._webhook_handler(request, state_data)
19
23
  else:
20
24
  return await self._webhook_handler(request)
21
-
25
+
22
26
 
23
27
  async def _webhook_handler(self, request: WebhookRequest, state_data: Optional[StateData] = None) -> WebhookResponse:
28
+ print("--- _webhook_handler ---")
29
+ print(request)
30
+ print("--- end of _webhook_handler ---")
31
+ print("--- state_data ---")
32
+ print(state_data)
33
+ print("--- end of state_data ---")
24
34
  try:
25
- # --- Step 1: Process Incoming Task ---
26
- if request.result:
27
- incoming_task = request.result
28
-
29
- # Initialize state_data if missing
30
- if not state_data:
31
- state_data = StateData(
32
- task_id=incoming_task.id,
33
- task=incoming_task.copy(update={"artifacts": incoming_task.artifacts}),
34
- context_history=[],
35
- push_notification_config=None
36
- )
35
+ # Extract parameters from request
36
+ task_id = request.id
37
+ task = request.result
37
38
 
38
- # --- Step 2: Call Webhook Function ---
39
- webhook_response = await self.webhook_fn(request, state_data) if state_data else await self.webhook_fn(request)
39
+ if state_data:
40
+ session_id = task.sessionId if task and task.sessionId else state_data.task.sessionId
41
+ task_history = task.history if task and task.history is not None else state_data.task.history.copy() if state_data.task.history else []
42
+ context_history = state_data.context_history.copy()
43
+ metadata = task.metadata if task and task.metadata is not None else state_data.task.metadata.copy() if state_data.task.metadata else {}
44
+ # Deep copy of push_notification_config
45
+ push_notification_config = copy.deepcopy(state_data.push_notification_config) if state_data.push_notification_config else None
46
+ else:
47
+ # No state_data so just assign based on task from the request
48
+ session_id = task.sessionId if task and task.sessionId else str(uuid4())
49
+ task_history = task.history if task and task.history else []
50
+ context_history = []
51
+ metadata = task.metadata if task and task.metadata else {}
52
+ push_notification_config = None
40
53
 
41
- # --- Step 3: Process Webhook Response ---
42
- if webhook_response.result:
43
- updated_task = webhook_response.result
44
- existing_task = state_data.task
45
-
46
- # Overwrite artifacts from response
47
- existing_task.artifacts = updated_task.artifacts.copy() if updated_task.artifacts else []
48
-
49
- # Merge metadata
50
- existing_task.metadata = {**(existing_task.metadata or {}), **(updated_task.metadata or {})}
51
-
52
- # Build messages from updated artifacts
53
- updated_parts = [part for artifact in updated_task.artifacts for part in artifact.parts] if updated_task.artifacts else []
54
- updated_messages = [Message(role="agent", parts=updated_parts, metadata=updated_task.metadata)]
55
-
56
- # Update context history again
57
- if self.state_manager:
58
- history_strategy = self.state_manager.get_history_strategy()
59
- state_data.context_history = history_strategy.update_history(
60
- existing_history=state_data.context_history,
61
- new_messages=updated_messages
62
- )
63
- await self.state_manager.update_state(state_data)
64
-
65
- # --- Step 4: Push Notification ---
66
- push_url = state_data.push_notification_config.url if state_data and state_data.push_notification_config else None
54
+ # Call webhook handler
55
+ if state_data:
56
+ # Call webhook_fn with state_data
57
+ raw_result = await self.webhook_fn(request, state_data)
58
+ else:
59
+ # Call webhook_fn with request
60
+ raw_result = await self.webhook_fn(request)
61
+
62
+ # Handle direct WebhookResponse returns
63
+ if isinstance(raw_result, WebhookResponse):
64
+ return raw_result
65
+
66
+ # Process webhook_response in a way that is similar to handle_send_task
67
+ # Build task with updated history
68
+ updated_task = self.task_builder.build(
69
+ content=raw_result,
70
+ task_id=task_id,
71
+ session_id=session_id,
72
+ metadata=metadata,
73
+ history=task_history
74
+ )
75
+
76
+ # Process messages through strategy (similar to handle_send_task)
77
+ messages = []
78
+ if updated_task.artifacts:
79
+ agent_parts = [p for a in updated_task.artifacts for p in a.parts]
80
+ agent_message = Message(
81
+ role="agent",
82
+ parts=agent_parts,
83
+ metadata=updated_task.metadata
84
+ )
85
+ messages.append(agent_message)
86
+
87
+ # Update Task history with a simple append
88
+ task_history.extend(messages)
67
89
 
68
- if push_url:
90
+ if state_data:
91
+ # Update context history with a strategy
92
+ history_strategy = self.state_manager.get_history_strategy()
93
+ context_history = history_strategy.update_history(
94
+ existing_history=context_history,
95
+ new_messages=messages
96
+ )
97
+
98
+ # Update task with final state
99
+ updated_task.history = task_history
100
+
101
+ # State store update (if enabled)
102
+ if state_data:
103
+ await self.state_manager.update_state(
104
+ state_data=StateData(
105
+ task_id=task_id,
106
+ task=updated_task,
107
+ context_history=context_history,
108
+ push_notification_config=push_notification_config,
109
+ )
110
+ )
111
+ print("--- push_notification_config ---")
112
+ print(push_notification_config)
113
+ print("--- end of push_notification_config ---")
114
+ # If push_notification_config is set send the task to the push notification url
115
+ if push_notification_config:
69
116
  try:
70
- self.a2a_aclient.send_to_webhook(webhook_url=push_url, id=state_data.task_id, task=state_data.task)
117
+ await self.a2a_aclient.send_to_webhook(webhook_url=push_notification_config.url,id=task_id,task=updated_task.model_dump())
71
118
  except Exception as e:
72
- return WebhookResponse(
73
- id=request.id,
74
- error=f"Push notification failed: {str(e)}"
75
- )
76
-
77
- # --- Step 5: Return Final Response ---
119
+ pass
120
+
121
+ # Return the updated task
78
122
  return WebhookResponse(
79
123
  id=request.id,
80
- result=state_data.task if state_data else None
124
+ result=updated_task
81
125
  )
82
-
126
+
83
127
  except Exception as e:
84
- return WebhookResponse(id=request.id, error=f"Internal error: {str(e)}")
128
+ # Handle exceptions
129
+ return WebhookResponse(
130
+ id=request.id,
131
+ error=str(e)
132
+ )
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: smarta2a
3
- Version: 0.4.21
3
+ Version: 0.4.23
4
4
  Summary: a Python framework that helps you build servers and AI agents that communicate using the A2A protocol
5
5
  Project-URL: Homepage, https://github.com/siddharthsma/smarta2a
6
6
  Project-URL: Bug Tracker, https://github.com/siddharthsma/smarta2a/issues
@@ -1,6 +1,6 @@
1
1
  smarta2a/__init__.py,sha256=T_EECYqWrxshix0FbgUv22zlKRX22HFU-HKXcYTOb3w,175
2
2
  smarta2a/agent/a2a_agent.py,sha256=EurcxpV14e3OPWCMutYL0EXMHb5ZKQqAHEGZZF6pNgg,1892
3
- smarta2a/agent/a2a_human.py,sha256=yAW9naxyqStQhWwDamXRZIlw-mT_7RW2wcHyhy3rR6Y,1671
3
+ smarta2a/agent/a2a_human.py,sha256=Bz4M9rhEwQEtIdDnV7VTL2n14nTT2wACyPBhDMph4FQ,1645
4
4
  smarta2a/agent/a2a_mcp_server.py,sha256=X_mxkgYgCA_dSNtCvs0rSlOoWYc-8d3Qyxv0e-a7NKY,1015
5
5
  smarta2a/archive/smart_mcp_client.py,sha256=0s2OWFKWSv-_UF7rb9fOrsh1OIYsYOsGukkXXp_E1cU,4158
6
6
  smarta2a/archive/subscription_service.py,sha256=vftmZD94HbdjPFa_1UBvsBm-WkW-s3ZCVq60fF7OCgA,4109
@@ -23,9 +23,9 @@ smarta2a/server/json_rpc_request_processor.py,sha256=qRB3sfj_n9ImkIOCdaUKMsDmKcO
23
23
  smarta2a/server/nats_client.py,sha256=K97e8awvAxsqgs3BxsTZU_mB3JPPZ0yjLX1LnZZjfXE,1450
24
24
  smarta2a/server/request_handler.py,sha256=tUAoxkrJtOnLPJxdUDMThGPFAxYnNFFofS3QD80g_8M,26184
25
25
  smarta2a/server/send_task_handler.py,sha256=fiBeCCHCu9c2H4EJOUc0t3EZgpHVFJy4B_6qZOC140s,6336
26
- smarta2a/server/server.py,sha256=E58tvOjAvHf_gYjST76sPEC5piaNyrHePa9k-fSadZA,6797
26
+ smarta2a/server/server.py,sha256=L0vh1i-s8bAQKarTPkqzZRdZuqFUjoqeGOCfo8wUvgU,6782
27
27
  smarta2a/server/state_manager.py,sha256=jFxf9cDxLqjIo87tv_Ynh2dH1vCTFLrVSLPuVg6YWnA,8063
28
- smarta2a/server/webhook_request_processor.py,sha256=PErCC5HbeYsZ7JDf7Cbx_eIf1ZtLGiGe1LsmAD6Oxj0,3985
28
+ smarta2a/server/webhook_request_processor.py,sha256=aoRUsTxvwX9JZcDjO51y-h9hX9YGsMGFNdTf_Zyr_GA,5876
29
29
  smarta2a/state_stores/__init__.py,sha256=vafxAqpwvag_cYFH2XKGk3DPmJIWJr4Ioey30yLFkVQ,220
30
30
  smarta2a/state_stores/base_state_store.py,sha256=_3LInM-qepKwwdypJTDNs9-DozBNrKVycwPwUm7bYdU,512
31
31
  smarta2a/state_stores/inmemory_state_store.py,sha256=nEBBUiiqhEluP2MYJjFUImcjIwLJEvL8BWwMbLCb8Fw,1268
@@ -36,7 +36,7 @@ smarta2a/utils/task_builder.py,sha256=wqSyfVHNTaXuGESu09dhlaDi7D007gcN3-8tH-nPQ4
36
36
  smarta2a/utils/task_request_builder.py,sha256=6cOGOqj2Rg43xWM03GRJQzlIZHBptsMCJRp7oD-TDAQ,3362
37
37
  smarta2a/utils/tools_manager.py,sha256=oR5cbwzPZ36hQAsWAgb-c6wFv5BthmCPraD7DSv-Bv8,4332
38
38
  smarta2a/utils/types.py,sha256=kzA6Vv5xXfu1sJuxhEXrglI9e9S6eZVIljMnsrQVyN0,13650
39
- smarta2a-0.4.21.dist-info/METADATA,sha256=q9zzIWTWwn2rIWg2tKHAzmb3CAq204N_XaFQ-NaYBN0,13051
40
- smarta2a-0.4.21.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
41
- smarta2a-0.4.21.dist-info/licenses/LICENSE,sha256=lDbqrxVnzDMY5KJ8JS1WhvkWE8TJaw-O-CHDy-ecsJA,2095
42
- smarta2a-0.4.21.dist-info/RECORD,,
39
+ smarta2a-0.4.23.dist-info/METADATA,sha256=bxlqSN9pysNL_bx1CsYjBLknPHRkKLyL2-Gg8BFl5w8,13051
40
+ smarta2a-0.4.23.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
41
+ smarta2a-0.4.23.dist-info/licenses/LICENSE,sha256=lDbqrxVnzDMY5KJ8JS1WhvkWE8TJaw-O-CHDy-ecsJA,2095
42
+ smarta2a-0.4.23.dist-info/RECORD,,