jaf-py 2.5.10__py3-none-any.whl → 2.5.12__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.
Files changed (92) hide show
  1. jaf/__init__.py +154 -57
  2. jaf/a2a/__init__.py +42 -21
  3. jaf/a2a/agent.py +79 -126
  4. jaf/a2a/agent_card.py +87 -78
  5. jaf/a2a/client.py +30 -66
  6. jaf/a2a/examples/client_example.py +12 -12
  7. jaf/a2a/examples/integration_example.py +38 -47
  8. jaf/a2a/examples/server_example.py +56 -53
  9. jaf/a2a/memory/__init__.py +0 -4
  10. jaf/a2a/memory/cleanup.py +28 -21
  11. jaf/a2a/memory/factory.py +155 -133
  12. jaf/a2a/memory/providers/composite.py +21 -26
  13. jaf/a2a/memory/providers/in_memory.py +89 -83
  14. jaf/a2a/memory/providers/postgres.py +117 -115
  15. jaf/a2a/memory/providers/redis.py +128 -121
  16. jaf/a2a/memory/serialization.py +77 -87
  17. jaf/a2a/memory/tests/run_comprehensive_tests.py +112 -83
  18. jaf/a2a/memory/tests/test_cleanup.py +211 -94
  19. jaf/a2a/memory/tests/test_serialization.py +73 -68
  20. jaf/a2a/memory/tests/test_stress_concurrency.py +186 -133
  21. jaf/a2a/memory/tests/test_task_lifecycle.py +138 -120
  22. jaf/a2a/memory/types.py +91 -53
  23. jaf/a2a/protocol.py +95 -125
  24. jaf/a2a/server.py +90 -118
  25. jaf/a2a/standalone_client.py +30 -43
  26. jaf/a2a/tests/__init__.py +16 -33
  27. jaf/a2a/tests/run_tests.py +17 -53
  28. jaf/a2a/tests/test_agent.py +40 -140
  29. jaf/a2a/tests/test_client.py +54 -117
  30. jaf/a2a/tests/test_integration.py +28 -82
  31. jaf/a2a/tests/test_protocol.py +54 -139
  32. jaf/a2a/tests/test_types.py +50 -136
  33. jaf/a2a/types.py +58 -34
  34. jaf/cli.py +21 -41
  35. jaf/core/__init__.py +7 -1
  36. jaf/core/agent_tool.py +93 -72
  37. jaf/core/analytics.py +257 -207
  38. jaf/core/checkpoint.py +223 -0
  39. jaf/core/composition.py +249 -235
  40. jaf/core/engine.py +817 -519
  41. jaf/core/errors.py +55 -42
  42. jaf/core/guardrails.py +276 -202
  43. jaf/core/handoff.py +47 -31
  44. jaf/core/parallel_agents.py +69 -75
  45. jaf/core/performance.py +75 -73
  46. jaf/core/proxy.py +43 -44
  47. jaf/core/proxy_helpers.py +24 -27
  48. jaf/core/regeneration.py +220 -129
  49. jaf/core/state.py +68 -66
  50. jaf/core/streaming.py +115 -108
  51. jaf/core/tool_results.py +111 -101
  52. jaf/core/tools.py +114 -116
  53. jaf/core/tracing.py +310 -210
  54. jaf/core/types.py +403 -151
  55. jaf/core/workflows.py +209 -168
  56. jaf/exceptions.py +46 -38
  57. jaf/memory/__init__.py +1 -6
  58. jaf/memory/approval_storage.py +54 -77
  59. jaf/memory/factory.py +4 -4
  60. jaf/memory/providers/in_memory.py +216 -180
  61. jaf/memory/providers/postgres.py +216 -146
  62. jaf/memory/providers/redis.py +173 -116
  63. jaf/memory/types.py +70 -51
  64. jaf/memory/utils.py +36 -34
  65. jaf/plugins/__init__.py +12 -12
  66. jaf/plugins/base.py +105 -96
  67. jaf/policies/__init__.py +0 -1
  68. jaf/policies/handoff.py +37 -46
  69. jaf/policies/validation.py +76 -52
  70. jaf/providers/__init__.py +6 -3
  71. jaf/providers/mcp.py +97 -51
  72. jaf/providers/model.py +475 -283
  73. jaf/server/__init__.py +1 -1
  74. jaf/server/main.py +7 -11
  75. jaf/server/server.py +514 -359
  76. jaf/server/types.py +208 -52
  77. jaf/utils/__init__.py +17 -18
  78. jaf/utils/attachments.py +111 -116
  79. jaf/utils/document_processor.py +175 -174
  80. jaf/visualization/__init__.py +1 -1
  81. jaf/visualization/example.py +111 -110
  82. jaf/visualization/functional_core.py +46 -71
  83. jaf/visualization/graphviz.py +154 -189
  84. jaf/visualization/imperative_shell.py +7 -16
  85. jaf/visualization/types.py +8 -4
  86. {jaf_py-2.5.10.dist-info → jaf_py-2.5.12.dist-info}/METADATA +2 -2
  87. jaf_py-2.5.12.dist-info/RECORD +97 -0
  88. jaf_py-2.5.10.dist-info/RECORD +0 -96
  89. {jaf_py-2.5.10.dist-info → jaf_py-2.5.12.dist-info}/WHEEL +0 -0
  90. {jaf_py-2.5.10.dist-info → jaf_py-2.5.12.dist-info}/entry_points.txt +0 -0
  91. {jaf_py-2.5.10.dist-info → jaf_py-2.5.12.dist-info}/licenses/LICENSE +0 -0
  92. {jaf_py-2.5.10.dist-info → jaf_py-2.5.12.dist-info}/top_level.txt +0 -0
@@ -34,10 +34,7 @@ class CountArgs(BaseModel):
34
34
 
35
35
  async def echo_tool(args: EchoArgs, context) -> Dict[str, Any]:
36
36
  """Simple echo tool for testing"""
37
- return {
38
- "result": f"Echo: {args.message}",
39
- "original": args.message
40
- }
37
+ return {"result": f"Echo: {args.message}", "original": args.message}
41
38
 
42
39
 
43
40
  async def count_tool(args: CountArgs, context) -> Dict[str, Any]:
@@ -47,10 +44,7 @@ async def count_tool(args: CountArgs, context) -> Dict[str, Any]:
47
44
 
48
45
  return {
49
46
  "result": f"Analysis: {char_count} characters, {word_count} words",
50
- "stats": {
51
- "characters": char_count,
52
- "words": word_count
53
- }
47
+ "stats": {"characters": char_count, "words": word_count},
54
48
  }
55
49
 
56
50
 
@@ -62,7 +56,7 @@ class MockModelProvider:
62
56
  {
63
57
  "message": {
64
58
  "content": "I understand you want me to help with your request.",
65
- "tool_calls": None
59
+ "tool_calls": None,
66
60
  }
67
61
  }
68
62
  ]
@@ -79,47 +73,34 @@ def create_test_agents():
79
73
 
80
74
  # Echo agent
81
75
  echo_tool_obj = create_a2a_tool(
82
- "echo",
83
- "Echo back messages",
84
- EchoArgs.model_json_schema(),
85
- echo_tool
76
+ "echo", "Echo back messages", EchoArgs.model_json_schema(), echo_tool
86
77
  )
87
78
 
88
79
  echo_agent = create_a2a_agent(
89
80
  "EchoBot",
90
81
  "An agent that echoes messages",
91
82
  "You are an echo bot. Use the echo tool to repeat messages.",
92
- [echo_tool_obj]
83
+ [echo_tool_obj],
93
84
  )
94
85
 
95
86
  # Counter agent
96
87
  count_tool_obj = create_a2a_tool(
97
- "count_text",
98
- "Count characters and words",
99
- CountArgs.model_json_schema(),
100
- count_tool
88
+ "count_text", "Count characters and words", CountArgs.model_json_schema(), count_tool
101
89
  )
102
90
 
103
91
  counter_agent = create_a2a_agent(
104
92
  "CounterBot",
105
93
  "An agent that analyzes text",
106
94
  "You are a text analysis bot. Use the count tool to analyze text.",
107
- [count_tool_obj]
95
+ [count_tool_obj],
108
96
  )
109
97
 
110
98
  # Simple chat agent
111
99
  chat_agent = create_a2a_agent(
112
- "ChatBot",
113
- "A conversational agent",
114
- "You are a friendly chat bot.",
115
- []
100
+ "ChatBot", "A conversational agent", "You are a friendly chat bot.", []
116
101
  )
117
102
 
118
- return {
119
- "EchoBot": echo_agent,
120
- "CounterBot": counter_agent,
121
- "ChatBot": chat_agent
122
- }
103
+ return {"EchoBot": echo_agent, "CounterBot": counter_agent, "ChatBot": chat_agent}
123
104
 
124
105
 
125
106
  class TestA2ASystemIntegration:
@@ -160,7 +141,7 @@ class TestA2ASystemIntegration:
160
141
  name="Test A2A Server",
161
142
  description="Integration test server",
162
143
  port=3002,
163
- host="localhost"
144
+ host="localhost",
164
145
  )
165
146
 
166
147
  assert server_config["agents"] == agents
@@ -174,10 +155,7 @@ class TestA2ASystemIntegration:
174
155
  agents = create_test_agents()
175
156
 
176
157
  server_config = create_server_config(
177
- agents=agents,
178
- name="Test Server",
179
- description="Test description",
180
- port=3003
158
+ agents=agents, name="Test Server", description="Test description", port=3003
181
159
  )
182
160
 
183
161
  server_obj = create_a2a_server(server_config)
@@ -204,10 +182,7 @@ class TestA2ASystemIntegration:
204
182
  assert client.session_id.startswith("client_")
205
183
 
206
184
  # Test with custom config
207
- custom_client = create_a2a_client(
208
- "http://example.com",
209
- {"timeout": 60000}
210
- )
185
+ custom_client = create_a2a_client("http://example.com", {"timeout": 60000})
211
186
 
212
187
  assert custom_client.config.timeout == 60000
213
188
 
@@ -216,10 +191,7 @@ class TestA2ASystemIntegration:
216
191
  """Test tool execution in isolation"""
217
192
  # Test echo tool
218
193
  echo_tool_obj = create_a2a_tool(
219
- "echo_test",
220
- "Echo tool for testing",
221
- EchoArgs.model_json_schema(),
222
- echo_tool
194
+ "echo_test", "Echo tool for testing", EchoArgs.model_json_schema(), echo_tool
223
195
  )
224
196
 
225
197
  args = EchoArgs(message="Hello world")
@@ -230,10 +202,7 @@ class TestA2ASystemIntegration:
230
202
 
231
203
  # Test count tool
232
204
  count_tool_obj = create_a2a_tool(
233
- "count_test",
234
- "Count tool for testing",
235
- CountArgs.model_json_schema(),
236
- count_tool
205
+ "count_test", "Count tool for testing", CountArgs.model_json_schema(), count_tool
237
206
  )
238
207
 
239
208
  args = CountArgs(text="Hello world testing")
@@ -249,7 +218,7 @@ class TestA2AProtocolIntegration:
249
218
  """Test A2A protocol integration"""
250
219
 
251
220
  @pytest.mark.asyncio
252
- @patch('jaf.a2a.server.uvicorn.Server')
221
+ @patch("jaf.a2a.server.uvicorn.Server")
253
222
  async def test_server_startup_flow(self, mock_server_class):
254
223
  """Test server startup process"""
255
224
  agents = create_test_agents()
@@ -258,7 +227,7 @@ class TestA2AProtocolIntegration:
258
227
  agents=agents,
259
228
  name="Integration Test Server",
260
229
  description="Test server for integration",
261
- port=3005
230
+ port=3005,
262
231
  )
263
232
 
264
233
  server_obj = create_a2a_server(server_config)
@@ -271,8 +240,9 @@ class TestA2AProtocolIntegration:
271
240
  assert callable(server_obj["start"])
272
241
 
273
242
  # Mock the server startup (don't actually start)
274
- with patch('jaf.a2a.server.uvicorn.Config') as mock_config:
243
+ with patch("jaf.a2a.server.uvicorn.Config") as mock_config:
275
244
  from unittest.mock import Mock
245
+
276
246
  mock_config.return_value = Mock()
277
247
 
278
248
  # Would start server here in real test
@@ -290,7 +260,7 @@ class TestA2AProtocolIntegration:
290
260
  agents=agents,
291
261
  name="Card Test Server",
292
262
  description="Server for testing agent cards",
293
- port=3006
263
+ port=3006,
294
264
  )
295
265
 
296
266
  server_obj = create_a2a_server(server_config)
@@ -330,18 +300,13 @@ class TestA2AProtocolIntegration:
330
300
  agents=agents,
331
301
  name="Registry Test",
332
302
  description="Test agent registry operations",
333
- port=3007
303
+ port=3007,
334
304
  )
335
305
 
336
306
  server_obj = create_a2a_server(server_config)
337
307
 
338
308
  # Test adding new agent
339
- new_agent = create_a2a_agent(
340
- "NewAgent",
341
- "Newly added agent",
342
- "You are a new agent",
343
- []
344
- )
309
+ new_agent = create_a2a_agent("NewAgent", "Newly added agent", "You are a new agent", [])
345
310
 
346
311
  updated_config = server_obj["add_agent"]("NewAgent", new_agent)
347
312
 
@@ -422,12 +387,7 @@ class TestA2AErrorHandling:
422
387
  async def failing_tool(args, context):
423
388
  raise ValueError("Tool execution failed")
424
389
 
425
- tool = create_a2a_tool(
426
- "failing_tool",
427
- "A tool that always fails",
428
- {},
429
- failing_tool
430
- )
390
+ tool = create_a2a_tool("failing_tool", "A tool that always fails", {}, failing_tool)
431
391
 
432
392
  # Test that errors are properly caught and handled
433
393
  with pytest.raises(ValueError) as exc_info:
@@ -442,12 +402,7 @@ class TestA2AErrorHandling:
442
402
  # (This would depend on validation logic in the agent creation)
443
403
 
444
404
  # Valid agent should work
445
- valid_agent = create_a2a_agent(
446
- "ValidAgent",
447
- "A valid agent",
448
- "Valid instructions",
449
- []
450
- )
405
+ valid_agent = create_a2a_agent("ValidAgent", "A valid agent", "Valid instructions", [])
451
406
 
452
407
  assert valid_agent.name == "ValidAgent"
453
408
 
@@ -456,7 +411,7 @@ class TestA2AErrorHandling:
456
411
  "", # Empty name - should be handled gracefully
457
412
  "", # Empty description
458
413
  "", # Empty instruction
459
- []
414
+ [],
460
415
  )
461
416
 
462
417
  # Should still create agent (validation may be in server layer)
@@ -473,12 +428,7 @@ class TestA2APerformance:
473
428
  # Create many agents
474
429
  agents = []
475
430
  for i in range(100):
476
- agent = create_a2a_agent(
477
- f"Agent{i}",
478
- f"Test agent {i}",
479
- "You are helpful",
480
- []
481
- )
431
+ agent = create_a2a_agent(f"Agent{i}", f"Test agent {i}", "You are helpful", [])
482
432
  agents.append(agent)
483
433
 
484
434
  end_time = time.time()
@@ -494,6 +444,7 @@ class TestA2APerformance:
494
444
 
495
445
  def test_tool_creation_performance(self):
496
446
  """Test tool creation performance"""
447
+
497
448
  async def test_tool_func(args, context):
498
449
  return {"result": "test"}
499
450
 
@@ -502,12 +453,7 @@ class TestA2APerformance:
502
453
  # Create many tools
503
454
  tools = []
504
455
  for i in range(100):
505
- tool = create_a2a_tool(
506
- f"tool{i}",
507
- f"Test tool {i}",
508
- {"type": "object"},
509
- test_tool_func
510
- )
456
+ tool = create_a2a_tool(f"tool{i}", f"Test tool {i}", {"type": "object"}, test_tool_func)
511
457
  tools.append(tool)
512
458
 
513
459
  end_time = time.time()
@@ -532,7 +478,7 @@ class TestA2AComprehensive:
532
478
  agents=agents,
533
479
  name="Comprehensive Test Server",
534
480
  description="Full system test server",
535
- port=3010
481
+ port=3010,
536
482
  )
537
483
 
538
484
  # Create server object