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.
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 +269 -210
  54. jaf/core/types.py +371 -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 +361 -280
  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.9.dist-info → jaf_py-2.5.11.dist-info}/METADATA +2 -2
  87. jaf_py-2.5.11.dist-info/RECORD +97 -0
  88. jaf_py-2.5.9.dist-info/RECORD +0 -96
  89. {jaf_py-2.5.9.dist-info → jaf_py-2.5.11.dist-info}/WHEEL +0 -0
  90. {jaf_py-2.5.9.dist-info → jaf_py-2.5.11.dist-info}/entry_points.txt +0 -0
  91. {jaf_py-2.5.9.dist-info → jaf_py-2.5.11.dist-info}/licenses/LICENSE +0 -0
  92. {jaf_py-2.5.9.dist-info → jaf_py-2.5.11.dist-info}/top_level.txt +0 -0
@@ -7,7 +7,7 @@ and system relationships.
7
7
 
8
8
  Core functionality:
9
9
  - Agent architecture visualization
10
- - Tool ecosystem diagrams
10
+ - Tool ecosystem diagrams
11
11
  - Runner system visualization
12
12
  - Multiple output formats (PNG, SVG, PDF)
13
13
  - Customizable color schemes and layouts
@@ -17,9 +17,11 @@ from .types import GraphOptions
17
17
 
18
18
  # ========== Example Tool Implementations ==========
19
19
 
20
+
20
21
  @dataclass
21
22
  class CalculateArgs:
22
23
  """Arguments for calculator tool."""
24
+
23
25
  expression: str
24
26
 
25
27
 
@@ -30,9 +32,9 @@ class ExampleCalculatorTool:
30
32
  def schema(self) -> ToolSchema[CalculateArgs]:
31
33
  """Tool schema including name, description, and parameter validation."""
32
34
  return ToolSchema(
33
- name='calculator',
34
- description='Performs basic arithmetic operations',
35
- parameters=CalculateArgs
35
+ name="calculator",
36
+ description="Performs basic arithmetic operations",
37
+ parameters=CalculateArgs,
36
38
  )
37
39
 
38
40
  async def execute(self, args: CalculateArgs, context: Any) -> str:
@@ -48,6 +50,7 @@ class ExampleCalculatorTool:
48
50
  @dataclass
49
51
  class WeatherArgs:
50
52
  """Arguments for weather tool."""
53
+
51
54
  location: str
52
55
 
53
56
 
@@ -58,9 +61,9 @@ class ExampleWeatherTool:
58
61
  def schema(self) -> ToolSchema[WeatherArgs]:
59
62
  """Tool schema including name, description, and parameter validation."""
60
63
  return ToolSchema(
61
- name='weather',
62
- description='Gets current weather for a location',
63
- parameters=WeatherArgs
64
+ name="weather",
65
+ description="Gets current weather for a location",
66
+ parameters=WeatherArgs,
64
67
  )
65
68
 
66
69
  async def execute(self, args: WeatherArgs, context: Any) -> str:
@@ -72,6 +75,7 @@ class ExampleWeatherTool:
72
75
  @dataclass
73
76
  class SearchArgs:
74
77
  """Arguments for search tool."""
78
+
75
79
  query: str
76
80
 
77
81
 
@@ -82,9 +86,7 @@ class ExampleSearchTool:
82
86
  def schema(self) -> ToolSchema[SearchArgs]:
83
87
  """Tool schema including name, description, and parameter validation."""
84
88
  return ToolSchema(
85
- name='search',
86
- description='Searches the web for information',
87
- parameters=SearchArgs
89
+ name="search", description="Searches the web for information", parameters=SearchArgs
88
90
  )
89
91
 
90
92
  async def execute(self, args: SearchArgs, context: Any) -> str:
@@ -94,6 +96,7 @@ class ExampleSearchTool:
94
96
 
95
97
  # ========== Example Agent Definitions ==========
96
98
 
99
+
97
100
  def create_example_agent() -> Agent:
98
101
  """Create a multi-purpose example assistant agent."""
99
102
  calculator_tool = ExampleCalculatorTool()
@@ -101,15 +104,17 @@ def create_example_agent() -> Agent:
101
104
  search_tool = ExampleSearchTool()
102
105
 
103
106
  def instructions(state: RunState[Any]) -> str:
104
- return ("I am a helpful assistant that can perform calculations, "
105
- "check weather, and search for information.")
107
+ return (
108
+ "I am a helpful assistant that can perform calculations, "
109
+ "check weather, and search for information."
110
+ )
106
111
 
107
112
  return Agent(
108
- name='ExampleAssistant',
113
+ name="ExampleAssistant",
109
114
  instructions=instructions,
110
115
  tools=[calculator_tool, weather_tool, search_tool],
111
- model_config=ModelConfig(name='gpt-4'),
112
- handoffs=['MathSpecialist', 'WeatherBot']
116
+ model_config=ModelConfig(name="gpt-4"),
117
+ handoffs=["MathSpecialist", "WeatherBot"],
113
118
  )
114
119
 
115
120
 
@@ -121,10 +126,10 @@ def create_math_specialist() -> Agent:
121
126
  return "I specialize in mathematical calculations and problem solving."
122
127
 
123
128
  return Agent(
124
- name='MathSpecialist',
129
+ name="MathSpecialist",
125
130
  instructions=instructions,
126
131
  tools=[calculator_tool],
127
- model_config=ModelConfig(name='gpt-3.5-turbo')
132
+ model_config=ModelConfig(name="gpt-3.5-turbo"),
128
133
  )
129
134
 
130
135
 
@@ -136,10 +141,10 @@ def create_weather_bot() -> Agent:
136
141
  return "I provide weather information and forecasts."
137
142
 
138
143
  return Agent(
139
- name='WeatherBot',
144
+ name="WeatherBot",
140
145
  instructions=instructions,
141
146
  tools=[weather_tool],
142
- model_config=ModelConfig(name='gpt-3.5-turbo')
147
+ model_config=ModelConfig(name="gpt-3.5-turbo"),
143
148
  )
144
149
 
145
150
 
@@ -151,21 +156,22 @@ def create_search_specialist() -> Agent:
151
156
  return "I specialize in finding and retrieving information from various sources."
152
157
 
153
158
  return Agent(
154
- name='SearchSpecialist',
159
+ name="SearchSpecialist",
155
160
  instructions=instructions,
156
161
  tools=[search_tool],
157
- model_config=ModelConfig(name='gpt-4')
162
+ model_config=ModelConfig(name="gpt-4"),
158
163
  )
159
164
 
160
165
 
161
166
  # ========== Example Functions ==========
162
167
 
168
+
163
169
  async def run_visualization_examples() -> None:
164
170
  """Run comprehensive visualization examples."""
165
- print('šŸŽØ Running JAF Visualization Examples...\n')
171
+ print("šŸŽØ Running JAF Visualization Examples...\n")
166
172
 
167
173
  # Ensure output directory exists
168
- os.makedirs('./examples', exist_ok=True)
174
+ os.makedirs("./examples", exist_ok=True)
169
175
 
170
176
  try:
171
177
  # Create example agents
@@ -177,152 +183,148 @@ async def run_visualization_examples() -> None:
177
183
  agents = [example_agent, math_specialist, weather_bot, search_specialist]
178
184
 
179
185
  # 1. Generate Agent Graph
180
- print('šŸ“Š Generating agent visualization...')
186
+ print("šŸ“Š Generating agent visualization...")
181
187
  agent_result = await generate_agent_graph(
182
188
  agents,
183
189
  GraphOptions(
184
- title='JAF Agent System',
185
- output_path='./examples/agent-graph.png',
186
- output_format='png',
190
+ title="JAF Agent System",
191
+ output_path="./examples/agent-graph.png",
192
+ output_format="png",
187
193
  show_tool_details=True,
188
194
  show_sub_agents=True,
189
- color_scheme='modern'
190
- )
195
+ color_scheme="modern",
196
+ ),
191
197
  )
192
198
 
193
199
  if agent_result.success:
194
- print(f'āœ… Agent graph generated: {agent_result.output_path}')
200
+ print(f"āœ… Agent graph generated: {agent_result.output_path}")
195
201
  else:
196
- print(f'āŒ Agent graph failed: {agent_result.error}')
202
+ print(f"āŒ Agent graph failed: {agent_result.error}")
197
203
 
198
204
  # 2. Generate Tool Graph
199
- print('\nšŸ”§ Generating tool visualization...')
200
- all_tools = [
201
- ExampleCalculatorTool(),
202
- ExampleWeatherTool(),
203
- ExampleSearchTool()
204
- ]
205
+ print("\nšŸ”§ Generating tool visualization...")
206
+ all_tools = [ExampleCalculatorTool(), ExampleWeatherTool(), ExampleSearchTool()]
205
207
 
206
208
  tool_result = await generate_tool_graph(
207
209
  all_tools,
208
210
  GraphOptions(
209
- title='JAF Tool Ecosystem',
210
- output_path='./examples/tool-graph.png',
211
- output_format='png',
212
- layout='circo',
213
- color_scheme='default'
214
- )
211
+ title="JAF Tool Ecosystem",
212
+ output_path="./examples/tool-graph.png",
213
+ output_format="png",
214
+ layout="circo",
215
+ color_scheme="default",
216
+ ),
215
217
  )
216
218
 
217
219
  if tool_result.success:
218
- print(f'āœ… Tool graph generated: {tool_result.output_path}')
220
+ print(f"āœ… Tool graph generated: {tool_result.output_path}")
219
221
  else:
220
- print(f'āŒ Tool graph failed: {tool_result.error}')
222
+ print(f"āŒ Tool graph failed: {tool_result.error}")
221
223
 
222
224
  # 3. Generate Runner Visualization
223
- print('\nšŸƒ Generating runner visualization...')
225
+ print("\nšŸƒ Generating runner visualization...")
224
226
  agent_registry = {agent.name: agent for agent in agents}
225
227
 
226
228
  runner_result = await generate_runner_graph(
227
229
  agent_registry,
228
230
  GraphOptions(
229
- title='JAF Runner Architecture',
230
- output_path='./examples/runner-architecture.png',
231
- output_format='png',
232
- color_scheme='modern'
233
- )
231
+ title="JAF Runner Architecture",
232
+ output_path="./examples/runner-architecture.png",
233
+ output_format="png",
234
+ color_scheme="modern",
235
+ ),
234
236
  )
235
237
 
236
238
  if runner_result.success:
237
- print(f'āœ… Runner graph generated: {runner_result.output_path}')
239
+ print(f"āœ… Runner graph generated: {runner_result.output_path}")
238
240
  else:
239
- print(f'āŒ Runner graph failed: {runner_result.error}')
241
+ print(f"āŒ Runner graph failed: {runner_result.error}")
240
242
 
241
243
  # 4. Generate different color schemes
242
- print('\nšŸŽØ Generating alternative color schemes...')
244
+ print("\nšŸŽØ Generating alternative color schemes...")
243
245
 
244
- for scheme in ['default', 'modern', 'minimal']:
246
+ for scheme in ["default", "modern", "minimal"]:
245
247
  scheme_result = await generate_agent_graph(
246
248
  [example_agent],
247
249
  GraphOptions(
248
- title=f'JAF Agent ({scheme} theme)',
249
- output_path=f'./examples/agent-{scheme}.png',
250
- output_format='png',
250
+ title=f"JAF Agent ({scheme} theme)",
251
+ output_path=f"./examples/agent-{scheme}.png",
252
+ output_format="png",
251
253
  color_scheme=scheme,
252
- show_tool_details=True
253
- )
254
+ show_tool_details=True,
255
+ ),
254
256
  )
255
257
 
256
258
  if scheme_result.success:
257
- print(f'āœ… {scheme} theme generated: {scheme_result.output_path}')
259
+ print(f"āœ… {scheme} theme generated: {scheme_result.output_path}")
258
260
  else:
259
- print(f'āŒ {scheme} theme failed: {scheme_result.error}')
261
+ print(f"āŒ {scheme} theme failed: {scheme_result.error}")
260
262
 
261
263
  # 5. Generate different formats
262
- print('\nšŸ“„ Generating different output formats...')
264
+ print("\nšŸ“„ Generating different output formats...")
263
265
 
264
- for fmt in ['png', 'svg', 'pdf']:
266
+ for fmt in ["png", "svg", "pdf"]:
265
267
  format_result = await generate_agent_graph(
266
268
  [example_agent, math_specialist],
267
269
  GraphOptions(
268
- title='JAF Multi-Format Example',
269
- output_path=f'./examples/multi-format.{fmt}',
270
+ title="JAF Multi-Format Example",
271
+ output_path=f"./examples/multi-format.{fmt}",
270
272
  output_format=fmt,
271
- color_scheme='modern'
272
- )
273
+ color_scheme="modern",
274
+ ),
273
275
  )
274
276
 
275
277
  if format_result.success:
276
- print(f'āœ… {fmt.upper()} format generated: {format_result.output_path}')
278
+ print(f"āœ… {fmt.upper()} format generated: {format_result.output_path}")
277
279
  else:
278
- print(f'āŒ {fmt.upper()} format failed: {format_result.error}')
279
-
280
- print('\nšŸŽ‰ All visualization examples completed!')
281
- print('\nšŸ“ Generated files:')
282
- print(' - ./examples/agent-graph.png')
283
- print(' - ./examples/tool-graph.png')
284
- print(' - ./examples/runner-architecture.png')
285
- print(' - ./examples/agent-default.png')
286
- print(' - ./examples/agent-modern.png')
287
- print(' - ./examples/agent-minimal.png')
288
- print(' - ./examples/multi-format.png')
289
- print(' - ./examples/multi-format.svg')
290
- print(' - ./examples/multi-format.pdf')
280
+ print(f"āŒ {fmt.upper()} format failed: {format_result.error}")
281
+
282
+ print("\nšŸŽ‰ All visualization examples completed!")
283
+ print("\nšŸ“ Generated files:")
284
+ print(" - ./examples/agent-graph.png")
285
+ print(" - ./examples/tool-graph.png")
286
+ print(" - ./examples/runner-architecture.png")
287
+ print(" - ./examples/agent-default.png")
288
+ print(" - ./examples/agent-modern.png")
289
+ print(" - ./examples/agent-minimal.png")
290
+ print(" - ./examples/multi-format.png")
291
+ print(" - ./examples/multi-format.svg")
292
+ print(" - ./examples/multi-format.pdf")
291
293
 
292
294
  except Exception as error:
293
- print(f'āŒ Error running visualization examples: {error}')
295
+ print(f"āŒ Error running visualization examples: {error}")
294
296
 
295
297
 
296
298
  async def quick_start_visualization(agent: Agent, output_path: str = None) -> None:
297
299
  """
298
300
  Quick start function for visualizing a single agent.
299
-
301
+
300
302
  Args:
301
303
  agent: Agent to visualize
302
304
  output_path: Optional custom output path
303
305
  """
304
- print(f'šŸš€ Quick visualization for agent: {agent.name}')
306
+ print(f"šŸš€ Quick visualization for agent: {agent.name}")
305
307
 
306
308
  result = await generate_agent_graph(
307
309
  [agent],
308
310
  GraphOptions(
309
- output_path=output_path or f'./agent-{agent.name.lower()}.png',
310
- output_format='png',
311
- color_scheme='modern',
311
+ output_path=output_path or f"./agent-{agent.name.lower()}.png",
312
+ output_format="png",
313
+ color_scheme="modern",
312
314
  show_tool_details=True,
313
- show_sub_agents=True
314
- )
315
+ show_sub_agents=True,
316
+ ),
315
317
  )
316
318
 
317
319
  if result.success:
318
- print(f'āœ… Visualization saved to: {result.output_path}')
320
+ print(f"āœ… Visualization saved to: {result.output_path}")
319
321
  else:
320
- print(f'āŒ Visualization failed: {result.error}')
322
+ print(f"āŒ Visualization failed: {result.error}")
321
323
 
322
324
 
323
325
  async def demo_basic_usage() -> None:
324
326
  """Demonstrate basic usage patterns."""
325
- print('šŸ“š JAF Visualization - Basic Usage Demo\n')
327
+ print("šŸ“š JAF Visualization - Basic Usage Demo\n")
326
328
 
327
329
  # Create a simple agent
328
330
  calculator_tool = ExampleCalculatorTool()
@@ -331,54 +333,53 @@ async def demo_basic_usage() -> None:
331
333
  return "I am a simple calculator agent."
332
334
 
333
335
  simple_agent = Agent(
334
- name='SimpleCalculator',
336
+ name="SimpleCalculator",
335
337
  instructions=simple_instructions,
336
338
  tools=[calculator_tool],
337
- model_config=ModelConfig(name='gpt-3.5-turbo')
339
+ model_config=ModelConfig(name="gpt-3.5-turbo"),
338
340
  )
339
341
 
340
342
  # Generate basic visualization
341
343
  result = await generate_agent_graph(
342
344
  [simple_agent],
343
- GraphOptions(
344
- title='Simple Calculator Agent',
345
- output_path='./simple-agent.png'
346
- )
345
+ GraphOptions(title="Simple Calculator Agent", output_path="./simple-agent.png"),
347
346
  )
348
347
 
349
348
  if result.success:
350
- print(f'āœ… Basic visualization created: {result.output_path}')
351
- print('šŸ“„ DOT source preview:')
352
- print(result.graph_dot[:200] + '...' if result.graph_dot else 'No DOT source available')
349
+ print(f"āœ… Basic visualization created: {result.output_path}")
350
+ print("šŸ“„ DOT source preview:")
351
+ print(result.graph_dot[:200] + "..." if result.graph_dot else "No DOT source available")
353
352
  else:
354
- print(f'āŒ Basic visualization failed: {result.error}')
353
+ print(f"āŒ Basic visualization failed: {result.error}")
355
354
 
356
355
 
357
356
  # ========== CLI Integration ==========
358
357
 
358
+
359
359
  async def main() -> None:
360
360
  """Main function for CLI execution."""
361
- print('šŸŽØ JAF Visualization Examples\n')
361
+ print("šŸŽØ JAF Visualization Examples\n")
362
362
 
363
363
  # Check if graphviz is available
364
364
  try:
365
365
  from graphviz import Digraph
366
+
366
367
  test_graph = Digraph()
367
- print('āœ… Graphviz Python package available')
368
+ print("āœ… Graphviz Python package available")
368
369
  except ImportError:
369
- print('āŒ Graphviz Python package not installed')
370
+ print("āŒ Graphviz Python package not installed")
370
371
  print(' Install with: pip install "jaf-py[visualization]"')
371
372
  return
372
373
 
373
374
  try:
374
375
  # Test basic Graphviz system dependency
375
376
  test_graph = Digraph()
376
- test_graph.node('test', 'Test Node')
377
+ test_graph.node("test", "Test Node")
377
378
  test_graph.source # This will work if graphviz is available
378
- print('āœ… Graphviz system dependency available')
379
+ print("āœ… Graphviz system dependency available")
379
380
  except Exception:
380
- print('āŒ Graphviz system dependency not found')
381
- print(' Install with: brew install graphviz (macOS) or apt-get install graphviz (Ubuntu)')
381
+ print("āŒ Graphviz system dependency not found")
382
+ print(" Install with: brew install graphviz (macOS) or apt-get install graphviz (Ubuntu)")
382
383
  return
383
384
 
384
385
  # Run examples
@@ -387,5 +388,5 @@ async def main() -> None:
387
388
  await run_visualization_examples()
388
389
 
389
390
 
390
- if __name__ == '__main__':
391
+ if __name__ == "__main__":
391
392
  asyncio.run(main())