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/visualization/__init__.py
CHANGED
|
@@ -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
|
jaf/visualization/example.py
CHANGED
|
@@ -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=
|
|
34
|
-
description=
|
|
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=
|
|
62
|
-
description=
|
|
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=
|
|
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 (
|
|
105
|
-
|
|
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=
|
|
113
|
+
name="ExampleAssistant",
|
|
109
114
|
instructions=instructions,
|
|
110
115
|
tools=[calculator_tool, weather_tool, search_tool],
|
|
111
|
-
model_config=ModelConfig(name=
|
|
112
|
-
handoffs=[
|
|
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=
|
|
129
|
+
name="MathSpecialist",
|
|
125
130
|
instructions=instructions,
|
|
126
131
|
tools=[calculator_tool],
|
|
127
|
-
model_config=ModelConfig(name=
|
|
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=
|
|
144
|
+
name="WeatherBot",
|
|
140
145
|
instructions=instructions,
|
|
141
146
|
tools=[weather_tool],
|
|
142
|
-
model_config=ModelConfig(name=
|
|
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=
|
|
159
|
+
name="SearchSpecialist",
|
|
155
160
|
instructions=instructions,
|
|
156
161
|
tools=[search_tool],
|
|
157
|
-
model_config=ModelConfig(name=
|
|
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(
|
|
171
|
+
print("šØ Running JAF Visualization Examples...\n")
|
|
166
172
|
|
|
167
173
|
# Ensure output directory exists
|
|
168
|
-
os.makedirs(
|
|
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(
|
|
186
|
+
print("š Generating agent visualization...")
|
|
181
187
|
agent_result = await generate_agent_graph(
|
|
182
188
|
agents,
|
|
183
189
|
GraphOptions(
|
|
184
|
-
title=
|
|
185
|
-
output_path=
|
|
186
|
-
output_format=
|
|
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=
|
|
190
|
-
)
|
|
195
|
+
color_scheme="modern",
|
|
196
|
+
),
|
|
191
197
|
)
|
|
192
198
|
|
|
193
199
|
if agent_result.success:
|
|
194
|
-
print(f
|
|
200
|
+
print(f"ā
Agent graph generated: {agent_result.output_path}")
|
|
195
201
|
else:
|
|
196
|
-
print(f
|
|
202
|
+
print(f"ā Agent graph failed: {agent_result.error}")
|
|
197
203
|
|
|
198
204
|
# 2. Generate Tool Graph
|
|
199
|
-
print(
|
|
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=
|
|
210
|
-
output_path=
|
|
211
|
-
output_format=
|
|
212
|
-
layout=
|
|
213
|
-
color_scheme=
|
|
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
|
|
220
|
+
print(f"ā
Tool graph generated: {tool_result.output_path}")
|
|
219
221
|
else:
|
|
220
|
-
print(f
|
|
222
|
+
print(f"ā Tool graph failed: {tool_result.error}")
|
|
221
223
|
|
|
222
224
|
# 3. Generate Runner Visualization
|
|
223
|
-
print(
|
|
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=
|
|
230
|
-
output_path=
|
|
231
|
-
output_format=
|
|
232
|
-
color_scheme=
|
|
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
|
|
239
|
+
print(f"ā
Runner graph generated: {runner_result.output_path}")
|
|
238
240
|
else:
|
|
239
|
-
print(f
|
|
241
|
+
print(f"ā Runner graph failed: {runner_result.error}")
|
|
240
242
|
|
|
241
243
|
# 4. Generate different color schemes
|
|
242
|
-
print(
|
|
244
|
+
print("\nšØ Generating alternative color schemes...")
|
|
243
245
|
|
|
244
|
-
for scheme in [
|
|
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
|
|
249
|
-
output_path=f
|
|
250
|
-
output_format=
|
|
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
|
|
259
|
+
print(f"ā
{scheme} theme generated: {scheme_result.output_path}")
|
|
258
260
|
else:
|
|
259
|
-
print(f
|
|
261
|
+
print(f"ā {scheme} theme failed: {scheme_result.error}")
|
|
260
262
|
|
|
261
263
|
# 5. Generate different formats
|
|
262
|
-
print(
|
|
264
|
+
print("\nš Generating different output formats...")
|
|
263
265
|
|
|
264
|
-
for fmt in [
|
|
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=
|
|
269
|
-
output_path=f
|
|
270
|
+
title="JAF Multi-Format Example",
|
|
271
|
+
output_path=f"./examples/multi-format.{fmt}",
|
|
270
272
|
output_format=fmt,
|
|
271
|
-
color_scheme=
|
|
272
|
-
)
|
|
273
|
+
color_scheme="modern",
|
|
274
|
+
),
|
|
273
275
|
)
|
|
274
276
|
|
|
275
277
|
if format_result.success:
|
|
276
|
-
print(f
|
|
278
|
+
print(f"ā
{fmt.upper()} format generated: {format_result.output_path}")
|
|
277
279
|
else:
|
|
278
|
-
print(f
|
|
279
|
-
|
|
280
|
-
print(
|
|
281
|
-
print(
|
|
282
|
-
print(
|
|
283
|
-
print(
|
|
284
|
-
print(
|
|
285
|
-
print(
|
|
286
|
-
print(
|
|
287
|
-
print(
|
|
288
|
-
print(
|
|
289
|
-
print(
|
|
290
|
-
print(
|
|
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
|
|
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
|
|
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
|
|
310
|
-
output_format=
|
|
311
|
-
color_scheme=
|
|
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
|
|
320
|
+
print(f"ā
Visualization saved to: {result.output_path}")
|
|
319
321
|
else:
|
|
320
|
-
print(f
|
|
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(
|
|
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=
|
|
336
|
+
name="SimpleCalculator",
|
|
335
337
|
instructions=simple_instructions,
|
|
336
338
|
tools=[calculator_tool],
|
|
337
|
-
model_config=ModelConfig(name=
|
|
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
|
|
351
|
-
print(
|
|
352
|
-
print(result.graph_dot[:200] +
|
|
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
|
|
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(
|
|
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(
|
|
368
|
+
print("ā
Graphviz Python package available")
|
|
368
369
|
except ImportError:
|
|
369
|
-
print(
|
|
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(
|
|
377
|
+
test_graph.node("test", "Test Node")
|
|
377
378
|
test_graph.source # This will work if graphviz is available
|
|
378
|
-
print(
|
|
379
|
+
print("ā
Graphviz system dependency available")
|
|
379
380
|
except Exception:
|
|
380
|
-
print(
|
|
381
|
-
print(
|
|
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__ ==
|
|
391
|
+
if __name__ == "__main__":
|
|
391
392
|
asyncio.run(main())
|