jaf-py 2.5.9__py3-none-any.whl → 2.5.11__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.
- jaf/__init__.py +154 -57
- jaf/a2a/__init__.py +42 -21
- jaf/a2a/agent.py +79 -126
- jaf/a2a/agent_card.py +87 -78
- jaf/a2a/client.py +30 -66
- jaf/a2a/examples/client_example.py +12 -12
- jaf/a2a/examples/integration_example.py +38 -47
- jaf/a2a/examples/server_example.py +56 -53
- jaf/a2a/memory/__init__.py +0 -4
- jaf/a2a/memory/cleanup.py +28 -21
- jaf/a2a/memory/factory.py +155 -133
- jaf/a2a/memory/providers/composite.py +21 -26
- jaf/a2a/memory/providers/in_memory.py +89 -83
- jaf/a2a/memory/providers/postgres.py +117 -115
- jaf/a2a/memory/providers/redis.py +128 -121
- jaf/a2a/memory/serialization.py +77 -87
- jaf/a2a/memory/tests/run_comprehensive_tests.py +112 -83
- jaf/a2a/memory/tests/test_cleanup.py +211 -94
- jaf/a2a/memory/tests/test_serialization.py +73 -68
- jaf/a2a/memory/tests/test_stress_concurrency.py +186 -133
- jaf/a2a/memory/tests/test_task_lifecycle.py +138 -120
- jaf/a2a/memory/types.py +91 -53
- jaf/a2a/protocol.py +95 -125
- jaf/a2a/server.py +90 -118
- jaf/a2a/standalone_client.py +30 -43
- jaf/a2a/tests/__init__.py +16 -33
- jaf/a2a/tests/run_tests.py +17 -53
- jaf/a2a/tests/test_agent.py +40 -140
- jaf/a2a/tests/test_client.py +54 -117
- jaf/a2a/tests/test_integration.py +28 -82
- jaf/a2a/tests/test_protocol.py +54 -139
- jaf/a2a/tests/test_types.py +50 -136
- jaf/a2a/types.py +58 -34
- jaf/cli.py +21 -41
- jaf/core/__init__.py +7 -1
- jaf/core/agent_tool.py +93 -72
- jaf/core/analytics.py +257 -207
- jaf/core/checkpoint.py +223 -0
- jaf/core/composition.py +249 -235
- jaf/core/engine.py +817 -519
- jaf/core/errors.py +55 -42
- jaf/core/guardrails.py +276 -202
- jaf/core/handoff.py +47 -31
- jaf/core/parallel_agents.py +69 -75
- jaf/core/performance.py +75 -73
- jaf/core/proxy.py +43 -44
- jaf/core/proxy_helpers.py +24 -27
- jaf/core/regeneration.py +220 -129
- jaf/core/state.py +68 -66
- jaf/core/streaming.py +115 -108
- jaf/core/tool_results.py +111 -101
- jaf/core/tools.py +114 -116
- jaf/core/tracing.py +269 -210
- jaf/core/types.py +371 -151
- jaf/core/workflows.py +209 -168
- jaf/exceptions.py +46 -38
- jaf/memory/__init__.py +1 -6
- jaf/memory/approval_storage.py +54 -77
- jaf/memory/factory.py +4 -4
- jaf/memory/providers/in_memory.py +216 -180
- jaf/memory/providers/postgres.py +216 -146
- jaf/memory/providers/redis.py +173 -116
- jaf/memory/types.py +70 -51
- jaf/memory/utils.py +36 -34
- jaf/plugins/__init__.py +12 -12
- jaf/plugins/base.py +105 -96
- jaf/policies/__init__.py +0 -1
- jaf/policies/handoff.py +37 -46
- jaf/policies/validation.py +76 -52
- jaf/providers/__init__.py +6 -3
- jaf/providers/mcp.py +97 -51
- jaf/providers/model.py +361 -280
- jaf/server/__init__.py +1 -1
- jaf/server/main.py +7 -11
- jaf/server/server.py +514 -359
- jaf/server/types.py +208 -52
- jaf/utils/__init__.py +17 -18
- jaf/utils/attachments.py +111 -116
- jaf/utils/document_processor.py +175 -174
- jaf/visualization/__init__.py +1 -1
- jaf/visualization/example.py +111 -110
- jaf/visualization/functional_core.py +46 -71
- jaf/visualization/graphviz.py +154 -189
- jaf/visualization/imperative_shell.py +7 -16
- jaf/visualization/types.py +8 -4
- {jaf_py-2.5.9.dist-info → jaf_py-2.5.11.dist-info}/METADATA +2 -2
- jaf_py-2.5.11.dist-info/RECORD +97 -0
- jaf_py-2.5.9.dist-info/RECORD +0 -96
- {jaf_py-2.5.9.dist-info → jaf_py-2.5.11.dist-info}/WHEEL +0 -0
- {jaf_py-2.5.9.dist-info → jaf_py-2.5.11.dist-info}/entry_points.txt +0 -0
- {jaf_py-2.5.9.dist-info → jaf_py-2.5.11.dist-info}/licenses/LICENSE +0 -0
- {jaf_py-2.5.9.dist-info → jaf_py-2.5.11.dist-info}/top_level.txt +0 -0
jaf/a2a/types.py
CHANGED
|
@@ -11,6 +11,7 @@ from pydantic import BaseModel, Field
|
|
|
11
11
|
|
|
12
12
|
class A2AErrorCodes(Enum):
|
|
13
13
|
"""A2A protocol error codes"""
|
|
14
|
+
|
|
14
15
|
PARSE_ERROR = -32700
|
|
15
16
|
INVALID_REQUEST = -32600
|
|
16
17
|
METHOD_NOT_FOUND = -32601
|
|
@@ -26,6 +27,7 @@ class A2AErrorCodes(Enum):
|
|
|
26
27
|
|
|
27
28
|
class A2AFile(BaseModel):
|
|
28
29
|
"""A2A file representation"""
|
|
30
|
+
|
|
29
31
|
model_config = {"frozen": True}
|
|
30
32
|
|
|
31
33
|
bytes: Optional[str] = None
|
|
@@ -36,6 +38,7 @@ class A2AFile(BaseModel):
|
|
|
36
38
|
|
|
37
39
|
class A2ATextPart(BaseModel):
|
|
38
40
|
"""A2A text part"""
|
|
41
|
+
|
|
39
42
|
model_config = {"frozen": True, "extra": "forbid"}
|
|
40
43
|
|
|
41
44
|
kind: Literal["text"]
|
|
@@ -45,6 +48,7 @@ class A2ATextPart(BaseModel):
|
|
|
45
48
|
|
|
46
49
|
class A2ADataPart(BaseModel):
|
|
47
50
|
"""A2A data part"""
|
|
51
|
+
|
|
48
52
|
model_config = {"frozen": True, "extra": "forbid"}
|
|
49
53
|
|
|
50
54
|
kind: Literal["data"]
|
|
@@ -54,6 +58,7 @@ class A2ADataPart(BaseModel):
|
|
|
54
58
|
|
|
55
59
|
class A2AFilePart(BaseModel):
|
|
56
60
|
"""A2A file part"""
|
|
61
|
+
|
|
57
62
|
model_config = {"frozen": True}
|
|
58
63
|
|
|
59
64
|
kind: Literal["file"]
|
|
@@ -66,6 +71,7 @@ A2APart = Union[A2ATextPart, A2ADataPart, A2AFilePart]
|
|
|
66
71
|
|
|
67
72
|
class A2AMessage(BaseModel):
|
|
68
73
|
"""Core A2A message type"""
|
|
74
|
+
|
|
69
75
|
model_config = {"frozen": True}
|
|
70
76
|
|
|
71
77
|
role: Literal["user", "agent"]
|
|
@@ -81,6 +87,7 @@ class A2AMessage(BaseModel):
|
|
|
81
87
|
|
|
82
88
|
class TaskState(str, Enum):
|
|
83
89
|
"""Task state enumeration"""
|
|
90
|
+
|
|
84
91
|
SUBMITTED = "submitted"
|
|
85
92
|
WORKING = "working"
|
|
86
93
|
INPUT_REQUIRED = "input-required"
|
|
@@ -94,6 +101,7 @@ class TaskState(str, Enum):
|
|
|
94
101
|
|
|
95
102
|
class A2ATaskStatus(BaseModel):
|
|
96
103
|
"""Task status information"""
|
|
104
|
+
|
|
97
105
|
model_config = {"frozen": True}
|
|
98
106
|
|
|
99
107
|
state: TaskState
|
|
@@ -103,6 +111,7 @@ class A2ATaskStatus(BaseModel):
|
|
|
103
111
|
|
|
104
112
|
class A2AArtifact(BaseModel):
|
|
105
113
|
"""A2A artifact type"""
|
|
114
|
+
|
|
106
115
|
model_config = {"frozen": True}
|
|
107
116
|
|
|
108
117
|
artifact_id: str = Field(alias="artifactId")
|
|
@@ -115,6 +124,7 @@ class A2AArtifact(BaseModel):
|
|
|
115
124
|
|
|
116
125
|
class A2ATask(BaseModel):
|
|
117
126
|
"""A2A task representation"""
|
|
127
|
+
|
|
118
128
|
model_config = {"frozen": True}
|
|
119
129
|
|
|
120
130
|
id: str
|
|
@@ -128,6 +138,7 @@ class A2ATask(BaseModel):
|
|
|
128
138
|
|
|
129
139
|
class AgentSkill(BaseModel):
|
|
130
140
|
"""Agent skill definition"""
|
|
141
|
+
|
|
131
142
|
model_config = {"frozen": True}
|
|
132
143
|
|
|
133
144
|
id: str
|
|
@@ -141,6 +152,7 @@ class AgentSkill(BaseModel):
|
|
|
141
152
|
|
|
142
153
|
class AgentCapabilities(BaseModel):
|
|
143
154
|
"""Agent capabilities definition"""
|
|
155
|
+
|
|
144
156
|
model_config = {"frozen": True}
|
|
145
157
|
|
|
146
158
|
streaming: Optional[bool] = None
|
|
@@ -150,6 +162,7 @@ class AgentCapabilities(BaseModel):
|
|
|
150
162
|
|
|
151
163
|
class AgentProvider(BaseModel):
|
|
152
164
|
"""Agent provider information"""
|
|
165
|
+
|
|
153
166
|
model_config = {"frozen": True}
|
|
154
167
|
|
|
155
168
|
organization: str
|
|
@@ -158,6 +171,7 @@ class AgentProvider(BaseModel):
|
|
|
158
171
|
|
|
159
172
|
class AgentCard(BaseModel):
|
|
160
173
|
"""A2A agent card for discovery"""
|
|
174
|
+
|
|
161
175
|
model_config = {"frozen": True}
|
|
162
176
|
|
|
163
177
|
protocol_version: str = Field(alias="protocolVersion")
|
|
@@ -177,6 +191,7 @@ class AgentCard(BaseModel):
|
|
|
177
191
|
|
|
178
192
|
class JSONRPCError(BaseModel):
|
|
179
193
|
"""JSON-RPC error format"""
|
|
194
|
+
|
|
180
195
|
model_config = {"frozen": True}
|
|
181
196
|
|
|
182
197
|
code: int
|
|
@@ -186,6 +201,7 @@ class JSONRPCError(BaseModel):
|
|
|
186
201
|
|
|
187
202
|
class JSONRPCRequest(BaseModel):
|
|
188
203
|
"""JSON-RPC request format"""
|
|
204
|
+
|
|
189
205
|
model_config = {"frozen": True}
|
|
190
206
|
|
|
191
207
|
jsonrpc: Literal["2.0"]
|
|
@@ -196,6 +212,7 @@ class JSONRPCRequest(BaseModel):
|
|
|
196
212
|
|
|
197
213
|
class JSONRPCSuccessResponse(BaseModel):
|
|
198
214
|
"""JSON-RPC success response"""
|
|
215
|
+
|
|
199
216
|
model_config = {"frozen": True}
|
|
200
217
|
|
|
201
218
|
jsonrpc: Literal["2.0"]
|
|
@@ -205,6 +222,7 @@ class JSONRPCSuccessResponse(BaseModel):
|
|
|
205
222
|
|
|
206
223
|
class JSONRPCErrorResponse(BaseModel):
|
|
207
224
|
"""JSON-RPC error response"""
|
|
225
|
+
|
|
208
226
|
model_config = {"frozen": True}
|
|
209
227
|
|
|
210
228
|
jsonrpc: Literal["2.0"]
|
|
@@ -217,6 +235,7 @@ JSONRPCResponse = Union[JSONRPCSuccessResponse, JSONRPCErrorResponse]
|
|
|
217
235
|
|
|
218
236
|
class MessageSendConfiguration(BaseModel):
|
|
219
237
|
"""Configuration for message sending"""
|
|
238
|
+
|
|
220
239
|
model_config = {"frozen": True}
|
|
221
240
|
|
|
222
241
|
model: Optional[str] = None
|
|
@@ -228,6 +247,7 @@ class MessageSendConfiguration(BaseModel):
|
|
|
228
247
|
|
|
229
248
|
class SendMessageParams(BaseModel):
|
|
230
249
|
"""Parameters for message/send method"""
|
|
250
|
+
|
|
231
251
|
model_config = {"frozen": True}
|
|
232
252
|
|
|
233
253
|
message: A2AMessage
|
|
@@ -237,6 +257,7 @@ class SendMessageParams(BaseModel):
|
|
|
237
257
|
|
|
238
258
|
class SendMessageRequest(JSONRPCRequest):
|
|
239
259
|
"""A2A message/send request"""
|
|
260
|
+
|
|
240
261
|
model_config = {"frozen": True}
|
|
241
262
|
|
|
242
263
|
method: Literal["message/send"]
|
|
@@ -245,6 +266,7 @@ class SendMessageRequest(JSONRPCRequest):
|
|
|
245
266
|
|
|
246
267
|
class SendStreamingMessageRequest(JSONRPCRequest):
|
|
247
268
|
"""A2A message/stream request"""
|
|
269
|
+
|
|
248
270
|
model_config = {"frozen": True}
|
|
249
271
|
|
|
250
272
|
method: Literal["message/stream"]
|
|
@@ -253,6 +275,7 @@ class SendStreamingMessageRequest(JSONRPCRequest):
|
|
|
253
275
|
|
|
254
276
|
class GetTaskParams(BaseModel):
|
|
255
277
|
"""Parameters for tasks/get method"""
|
|
278
|
+
|
|
256
279
|
model_config = {"frozen": True}
|
|
257
280
|
|
|
258
281
|
id: str
|
|
@@ -262,6 +285,7 @@ class GetTaskParams(BaseModel):
|
|
|
262
285
|
|
|
263
286
|
class GetTaskRequest(JSONRPCRequest):
|
|
264
287
|
"""A2A tasks/get request"""
|
|
288
|
+
|
|
265
289
|
model_config = {"frozen": True}
|
|
266
290
|
|
|
267
291
|
method: Literal["tasks/get"]
|
|
@@ -270,6 +294,7 @@ class GetTaskRequest(JSONRPCRequest):
|
|
|
270
294
|
|
|
271
295
|
class A2AError(BaseModel):
|
|
272
296
|
"""A2A error format"""
|
|
297
|
+
|
|
273
298
|
model_config = {"frozen": True}
|
|
274
299
|
|
|
275
300
|
code: int
|
|
@@ -279,6 +304,7 @@ class A2AError(BaseModel):
|
|
|
279
304
|
|
|
280
305
|
class StreamEvent(BaseModel):
|
|
281
306
|
"""Base stream event"""
|
|
307
|
+
|
|
282
308
|
model_config = {"frozen": True}
|
|
283
309
|
|
|
284
310
|
isTaskComplete: bool
|
|
@@ -290,6 +316,7 @@ class StreamEvent(BaseModel):
|
|
|
290
316
|
|
|
291
317
|
class A2AStatusUpdateEvent(BaseModel):
|
|
292
318
|
"""A2A status update stream event"""
|
|
319
|
+
|
|
293
320
|
model_config = {"frozen": True}
|
|
294
321
|
|
|
295
322
|
kind: Literal["status-update"]
|
|
@@ -301,6 +328,7 @@ class A2AStatusUpdateEvent(BaseModel):
|
|
|
301
328
|
|
|
302
329
|
class A2AArtifactUpdateEvent(BaseModel):
|
|
303
330
|
"""A2A artifact update stream event"""
|
|
331
|
+
|
|
304
332
|
model_config = {"frozen": True}
|
|
305
333
|
|
|
306
334
|
kind: Literal["artifact-update"]
|
|
@@ -313,6 +341,7 @@ class A2AArtifactUpdateEvent(BaseModel):
|
|
|
313
341
|
|
|
314
342
|
class A2AMessageEvent(BaseModel):
|
|
315
343
|
"""A2A message stream event"""
|
|
344
|
+
|
|
316
345
|
model_config = {"frozen": True}
|
|
317
346
|
|
|
318
347
|
kind: Literal["message"]
|
|
@@ -324,6 +353,7 @@ A2AStreamEvent = Union[A2AStatusUpdateEvent, A2AArtifactUpdateEvent, A2AMessageE
|
|
|
324
353
|
|
|
325
354
|
class AgentState(BaseModel):
|
|
326
355
|
"""Agent state representation"""
|
|
356
|
+
|
|
327
357
|
model_config = {"frozen": True}
|
|
328
358
|
|
|
329
359
|
sessionId: str
|
|
@@ -335,6 +365,7 @@ class AgentState(BaseModel):
|
|
|
335
365
|
|
|
336
366
|
class ToolContext(BaseModel):
|
|
337
367
|
"""Tool execution context"""
|
|
368
|
+
|
|
338
369
|
model_config = {"frozen": True}
|
|
339
370
|
|
|
340
371
|
actions: Dict[str, bool]
|
|
@@ -343,6 +374,7 @@ class ToolContext(BaseModel):
|
|
|
343
374
|
|
|
344
375
|
class A2AToolResult(BaseModel):
|
|
345
376
|
"""A2A tool execution result"""
|
|
377
|
+
|
|
346
378
|
model_config = {"frozen": True}
|
|
347
379
|
|
|
348
380
|
status: str
|
|
@@ -354,6 +386,7 @@ class A2AToolResult(BaseModel):
|
|
|
354
386
|
|
|
355
387
|
class A2AAgentTool(BaseModel):
|
|
356
388
|
"""A2A agent tool definition"""
|
|
389
|
+
|
|
357
390
|
model_config = {"frozen": True}
|
|
358
391
|
|
|
359
392
|
name: str
|
|
@@ -364,6 +397,7 @@ class A2AAgentTool(BaseModel):
|
|
|
364
397
|
|
|
365
398
|
class A2AAgent(BaseModel):
|
|
366
399
|
"""A2A agent definition"""
|
|
400
|
+
|
|
367
401
|
model_config = {"frozen": True}
|
|
368
402
|
|
|
369
403
|
name: str
|
|
@@ -375,6 +409,7 @@ class A2AAgent(BaseModel):
|
|
|
375
409
|
|
|
376
410
|
class A2AServerConfig(BaseModel):
|
|
377
411
|
"""A2A server configuration"""
|
|
412
|
+
|
|
378
413
|
model_config = {"frozen": True}
|
|
379
414
|
|
|
380
415
|
agents: Dict[str, A2AAgent]
|
|
@@ -386,6 +421,7 @@ class A2AServerConfig(BaseModel):
|
|
|
386
421
|
|
|
387
422
|
class A2AClientConfig(BaseModel):
|
|
388
423
|
"""A2A client configuration"""
|
|
424
|
+
|
|
389
425
|
model_config = {"frozen": True}
|
|
390
426
|
|
|
391
427
|
base_url: str = Field(alias="baseUrl")
|
|
@@ -394,6 +430,7 @@ class A2AClientConfig(BaseModel):
|
|
|
394
430
|
|
|
395
431
|
class A2AClientState(BaseModel):
|
|
396
432
|
"""A2A client state"""
|
|
433
|
+
|
|
397
434
|
model_config = {"frozen": True}
|
|
398
435
|
|
|
399
436
|
config: A2AClientConfig
|
|
@@ -402,6 +439,7 @@ class A2AClientState(BaseModel):
|
|
|
402
439
|
|
|
403
440
|
# Factory functions for creating instances
|
|
404
441
|
|
|
442
|
+
|
|
405
443
|
def create_a2a_text_part(text: str, metadata: Optional[Dict[str, Any]] = None) -> A2ATextPart:
|
|
406
444
|
"""Create an A2A text part"""
|
|
407
445
|
if metadata is None:
|
|
@@ -409,7 +447,9 @@ def create_a2a_text_part(text: str, metadata: Optional[Dict[str, Any]] = None) -
|
|
|
409
447
|
return A2ATextPart(kind="text", text=text, metadata=metadata)
|
|
410
448
|
|
|
411
449
|
|
|
412
|
-
def create_a2a_data_part(
|
|
450
|
+
def create_a2a_data_part(
|
|
451
|
+
data: Dict[str, Any], metadata: Optional[Dict[str, Any]] = None
|
|
452
|
+
) -> A2ADataPart:
|
|
413
453
|
"""Create an A2A data part"""
|
|
414
454
|
if metadata is None:
|
|
415
455
|
return A2ADataPart(kind="data", data=data)
|
|
@@ -421,12 +461,16 @@ def create_a2a_file_part(file: A2AFile, metadata: Optional[Dict[str, Any]] = Non
|
|
|
421
461
|
return A2AFilePart(kind="file", file=file, metadata=metadata)
|
|
422
462
|
|
|
423
463
|
|
|
424
|
-
def create_jsonrpc_success_response(
|
|
464
|
+
def create_jsonrpc_success_response(
|
|
465
|
+
id: Union[str, int, None], result: Any
|
|
466
|
+
) -> JSONRPCSuccessResponse:
|
|
425
467
|
"""Create a JSON-RPC success response"""
|
|
426
468
|
return JSONRPCSuccessResponse(jsonrpc="2.0", id=id, result=result)
|
|
427
469
|
|
|
428
470
|
|
|
429
|
-
def create_jsonrpc_error_response(
|
|
471
|
+
def create_jsonrpc_error_response(
|
|
472
|
+
id: Union[str, int, None], error: Union[JSONRPCError, A2AError]
|
|
473
|
+
) -> JSONRPCErrorResponse:
|
|
430
474
|
"""Create a JSON-RPC error response"""
|
|
431
475
|
if isinstance(error, A2AError):
|
|
432
476
|
jsonrpc_error = JSONRPCError(code=error.code, message=error.message, data=error.data)
|
|
@@ -444,7 +488,7 @@ def create_a2a_message(
|
|
|
444
488
|
role: Literal["user", "agent"],
|
|
445
489
|
parts: List[A2APart],
|
|
446
490
|
context_id: str,
|
|
447
|
-
task_id: Optional[str] = None
|
|
491
|
+
task_id: Optional[str] = None,
|
|
448
492
|
) -> A2AMessage:
|
|
449
493
|
"""Create an A2A message"""
|
|
450
494
|
import time
|
|
@@ -456,14 +500,11 @@ def create_a2a_message(
|
|
|
456
500
|
messageId=f"msg_{int(time.time() * 1000)}_{uuid.uuid4().hex[:8]}",
|
|
457
501
|
contextId=context_id,
|
|
458
502
|
taskId=task_id,
|
|
459
|
-
kind="message"
|
|
503
|
+
kind="message",
|
|
460
504
|
)
|
|
461
505
|
|
|
462
506
|
|
|
463
|
-
def create_a2a_task(
|
|
464
|
-
initial_message: A2AMessage,
|
|
465
|
-
context_id: str
|
|
466
|
-
) -> A2ATask:
|
|
507
|
+
def create_a2a_task(initial_message: A2AMessage, context_id: str) -> A2ATask:
|
|
467
508
|
"""Create an A2A task"""
|
|
468
509
|
import time
|
|
469
510
|
import uuid
|
|
@@ -472,20 +513,14 @@ def create_a2a_task(
|
|
|
472
513
|
return A2ATask(
|
|
473
514
|
id=f"task_{int(time.time() * 1000)}_{uuid.uuid4().hex[:8]}",
|
|
474
515
|
contextId=context_id,
|
|
475
|
-
status=A2ATaskStatus(
|
|
476
|
-
state="submitted",
|
|
477
|
-
timestamp=datetime.now().isoformat()
|
|
478
|
-
),
|
|
516
|
+
status=A2ATaskStatus(state="submitted", timestamp=datetime.now().isoformat()),
|
|
479
517
|
history=[initial_message],
|
|
480
518
|
artifacts=[],
|
|
481
|
-
kind="task"
|
|
519
|
+
kind="task",
|
|
482
520
|
)
|
|
483
521
|
|
|
484
522
|
|
|
485
|
-
def create_a2a_artifact(
|
|
486
|
-
name: str,
|
|
487
|
-
parts: List[A2APart]
|
|
488
|
-
) -> A2AArtifact:
|
|
523
|
+
def create_a2a_artifact(name: str, parts: List[A2APart]) -> A2AArtifact:
|
|
489
524
|
"""Create an A2A artifact"""
|
|
490
525
|
import time
|
|
491
526
|
import uuid
|
|
@@ -495,29 +530,23 @@ def create_a2a_artifact(
|
|
|
495
530
|
artifactId=f"artifact_{int(time.time() * 1000)}_{uuid.uuid4().hex[:8]}",
|
|
496
531
|
name=name,
|
|
497
532
|
parts=parts,
|
|
498
|
-
timestamp=datetime.now().isoformat()
|
|
533
|
+
timestamp=datetime.now().isoformat(),
|
|
499
534
|
)
|
|
500
535
|
|
|
501
536
|
|
|
502
537
|
def create_a2a_agent_tool(
|
|
503
|
-
name: str,
|
|
504
|
-
description: str,
|
|
505
|
-
parameters: Dict[str, Any],
|
|
506
|
-
execute_func: Any
|
|
538
|
+
name: str, description: str, parameters: Dict[str, Any], execute_func: Any
|
|
507
539
|
) -> A2AAgentTool:
|
|
508
540
|
"""Create an A2A agent tool"""
|
|
509
541
|
return A2AAgentTool(
|
|
510
|
-
name=name,
|
|
511
|
-
description=description,
|
|
512
|
-
parameters=parameters,
|
|
513
|
-
execute=execute_func
|
|
542
|
+
name=name, description=description, parameters=parameters, execute=execute_func
|
|
514
543
|
)
|
|
515
544
|
|
|
516
545
|
|
|
517
546
|
def create_jsonrpc_request(
|
|
518
547
|
method: str,
|
|
519
548
|
params: Optional[Dict[str, Any]] = None,
|
|
520
|
-
request_id: Optional[Union[str, int]] = None
|
|
549
|
+
request_id: Optional[Union[str, int]] = None,
|
|
521
550
|
) -> JSONRPCRequest:
|
|
522
551
|
"""Create a JSON-RPC request"""
|
|
523
552
|
import time
|
|
@@ -526,9 +555,4 @@ def create_jsonrpc_request(
|
|
|
526
555
|
if request_id is None:
|
|
527
556
|
request_id = f"req_{int(time.time() * 1000)}_{uuid.uuid4().hex[:8]}"
|
|
528
557
|
|
|
529
|
-
return JSONRPCRequest(
|
|
530
|
-
jsonrpc="2.0",
|
|
531
|
-
method=method,
|
|
532
|
-
params=params,
|
|
533
|
-
id=request_id
|
|
534
|
-
)
|
|
558
|
+
return JSONRPCRequest(jsonrpc="2.0", method=method, params=params, id=request_id)
|
jaf/cli.py
CHANGED
|
@@ -30,27 +30,21 @@ def create_default_config() -> ServerConfig:
|
|
|
30
30
|
tools=None,
|
|
31
31
|
output_codec=None,
|
|
32
32
|
handoffs=None,
|
|
33
|
-
model_config=None
|
|
33
|
+
model_config=None,
|
|
34
34
|
)
|
|
35
35
|
|
|
36
36
|
# Create model provider
|
|
37
37
|
model_provider = make_litellm_provider(
|
|
38
|
-
base_url="https://api.openai.com/v1",
|
|
39
|
-
api_key="your-api-key-here"
|
|
38
|
+
base_url="https://api.openai.com/v1", api_key="your-api-key-here"
|
|
40
39
|
)
|
|
41
40
|
|
|
42
41
|
# Create run config
|
|
43
42
|
run_config = RunConfig(
|
|
44
|
-
agent_registry={"echo": echo_agent},
|
|
45
|
-
model_provider=model_provider,
|
|
46
|
-
max_turns=10
|
|
43
|
+
agent_registry={"echo": echo_agent}, model_provider=model_provider, max_turns=10
|
|
47
44
|
)
|
|
48
45
|
|
|
49
46
|
return ServerConfig(
|
|
50
|
-
host="0.0.0.0",
|
|
51
|
-
port=8000,
|
|
52
|
-
agent_registry={"echo": echo_agent},
|
|
53
|
-
run_config=run_config
|
|
47
|
+
host="0.0.0.0", port=8000, agent_registry={"echo": echo_agent}, run_config=run_config
|
|
54
48
|
)
|
|
55
49
|
|
|
56
50
|
|
|
@@ -63,17 +57,15 @@ async def run_server_command(args: argparse.Namespace) -> None:
|
|
|
63
57
|
|
|
64
58
|
# Override with command line arguments
|
|
65
59
|
if args.host:
|
|
66
|
-
config = config.__class__(
|
|
67
|
-
**{**config.__dict__, 'host': args.host}
|
|
68
|
-
)
|
|
60
|
+
config = config.__class__(**{**config.__dict__, "host": args.host})
|
|
69
61
|
|
|
70
62
|
if args.port:
|
|
71
|
-
config = config.__class__(
|
|
72
|
-
**{**config.__dict__, 'port': args.port}
|
|
73
|
-
)
|
|
63
|
+
config = config.__class__(**{**config.__dict__, "port": args.port})
|
|
74
64
|
|
|
75
65
|
print(f"📍 Server will run on {config.host}:{config.port}")
|
|
76
|
-
print(
|
|
66
|
+
print(
|
|
67
|
+
"💡 This is a default configuration. For production use, provide your own agents and model provider."
|
|
68
|
+
)
|
|
77
69
|
print("📚 See documentation for how to create custom agents and configurations.")
|
|
78
70
|
|
|
79
71
|
try:
|
|
@@ -88,8 +80,7 @@ async def run_server_command(args: argparse.Namespace) -> None:
|
|
|
88
80
|
def create_parser() -> argparse.ArgumentParser:
|
|
89
81
|
"""Create the argument parser."""
|
|
90
82
|
parser = argparse.ArgumentParser(
|
|
91
|
-
prog="jaf",
|
|
92
|
-
description="JAF (Juspay Agent Framework) - Command Line Interface"
|
|
83
|
+
prog="jaf", description="JAF (Juspay Agent Framework) - Command Line Interface"
|
|
93
84
|
)
|
|
94
85
|
|
|
95
86
|
subparsers = parser.add_subparsers(dest="command", help="Available commands")
|
|
@@ -97,21 +88,13 @@ def create_parser() -> argparse.ArgumentParser:
|
|
|
97
88
|
# Server command
|
|
98
89
|
server_parser = subparsers.add_parser("server", help="Run the JAF server")
|
|
99
90
|
server_parser.add_argument(
|
|
100
|
-
"--host",
|
|
101
|
-
type=str,
|
|
102
|
-
default="0.0.0.0",
|
|
103
|
-
help="Host to bind the server to (default: 0.0.0.0)"
|
|
91
|
+
"--host", type=str, default="0.0.0.0", help="Host to bind the server to (default: 0.0.0.0)"
|
|
104
92
|
)
|
|
105
93
|
server_parser.add_argument(
|
|
106
|
-
"--port",
|
|
107
|
-
type=int,
|
|
108
|
-
default=8000,
|
|
109
|
-
help="Port to bind the server to (default: 8000)"
|
|
94
|
+
"--port", type=int, default=8000, help="Port to bind the server to (default: 8000)"
|
|
110
95
|
)
|
|
111
96
|
server_parser.add_argument(
|
|
112
|
-
"--config",
|
|
113
|
-
type=str,
|
|
114
|
-
help="Path to configuration file (not implemented yet)"
|
|
97
|
+
"--config", type=str, help="Path to configuration file (not implemented yet)"
|
|
115
98
|
)
|
|
116
99
|
|
|
117
100
|
# Version command
|
|
@@ -119,11 +102,7 @@ def create_parser() -> argparse.ArgumentParser:
|
|
|
119
102
|
|
|
120
103
|
# Init command for creating project templates
|
|
121
104
|
init_parser = subparsers.add_parser("init", help="Initialize a new JAF project")
|
|
122
|
-
init_parser.add_argument(
|
|
123
|
-
"project_name",
|
|
124
|
-
type=str,
|
|
125
|
-
help="Name of the project to create"
|
|
126
|
-
)
|
|
105
|
+
init_parser.add_argument("project_name", type=str, help="Name of the project to create")
|
|
127
106
|
|
|
128
107
|
return parser
|
|
129
108
|
|
|
@@ -132,6 +111,7 @@ def show_version() -> None:
|
|
|
132
111
|
"""Show version information."""
|
|
133
112
|
try:
|
|
134
113
|
from . import __version__
|
|
114
|
+
|
|
135
115
|
print(f"JAF (Juspay Agent Framework) version {__version__}")
|
|
136
116
|
except ImportError:
|
|
137
117
|
print("JAF (Juspay Agent Framework) version unknown")
|
|
@@ -216,13 +196,13 @@ if __name__ == "__main__":
|
|
|
216
196
|
(project_path / "main.py").write_text(main_py_content)
|
|
217
197
|
|
|
218
198
|
# Create requirements.txt
|
|
219
|
-
requirements_content =
|
|
199
|
+
requirements_content = """jaf-py>=2.0.0
|
|
220
200
|
python-dotenv>=1.0.0
|
|
221
|
-
|
|
201
|
+
"""
|
|
222
202
|
(project_path / "requirements.txt").write_text(requirements_content)
|
|
223
203
|
|
|
224
204
|
# Create .env.example
|
|
225
|
-
env_example_content =
|
|
205
|
+
env_example_content = """# OpenAI API Configuration
|
|
226
206
|
OPENAI_API_KEY=your_openai_api_key_here
|
|
227
207
|
|
|
228
208
|
# Server Configuration
|
|
@@ -233,11 +213,11 @@ JAF_PORT=8000
|
|
|
233
213
|
JAF_MODEL=gpt-4o
|
|
234
214
|
JAF_TEMPERATURE=0.7
|
|
235
215
|
JAF_MAX_TOKENS=1000
|
|
236
|
-
|
|
216
|
+
"""
|
|
237
217
|
(project_path / ".env.example").write_text(env_example_content)
|
|
238
218
|
|
|
239
219
|
# Create README.md
|
|
240
|
-
readme_content = f
|
|
220
|
+
readme_content = f"""# {project_name}
|
|
241
221
|
|
|
242
222
|
A JAF (Juspay Agent Framework) project.
|
|
243
223
|
|
|
@@ -282,7 +262,7 @@ Edit `main.py` to:
|
|
|
282
262
|
- Configure model providers
|
|
283
263
|
- Add tools and capabilities
|
|
284
264
|
- Customize server settings
|
|
285
|
-
|
|
265
|
+
"""
|
|
286
266
|
|
|
287
267
|
(project_path / "README.md").write_text(readme_content)
|
|
288
268
|
|
jaf/core/__init__.py
CHANGED
|
@@ -22,7 +22,13 @@ from .parallel_agents import (
|
|
|
22
22
|
create_domain_experts_tool,
|
|
23
23
|
)
|
|
24
24
|
from .proxy import ProxyConfig, ProxyAuth, create_proxy_config, get_default_proxy_config
|
|
25
|
-
from .handoff import
|
|
25
|
+
from .handoff import (
|
|
26
|
+
handoff_tool,
|
|
27
|
+
handoff,
|
|
28
|
+
create_handoff_tool,
|
|
29
|
+
is_handoff_request,
|
|
30
|
+
extract_handoff_target,
|
|
31
|
+
)
|
|
26
32
|
|
|
27
33
|
__all__ = [
|
|
28
34
|
"Agent",
|