PraisonAI 3.0.0__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 (393) hide show
  1. praisonai/__init__.py +54 -0
  2. praisonai/__main__.py +15 -0
  3. praisonai/acp/__init__.py +54 -0
  4. praisonai/acp/config.py +159 -0
  5. praisonai/acp/server.py +587 -0
  6. praisonai/acp/session.py +219 -0
  7. praisonai/adapters/__init__.py +50 -0
  8. praisonai/adapters/readers.py +395 -0
  9. praisonai/adapters/rerankers.py +315 -0
  10. praisonai/adapters/retrievers.py +394 -0
  11. praisonai/adapters/vector_stores.py +409 -0
  12. praisonai/agent_scheduler.py +337 -0
  13. praisonai/agents_generator.py +903 -0
  14. praisonai/api/call.py +292 -0
  15. praisonai/auto.py +1197 -0
  16. praisonai/capabilities/__init__.py +275 -0
  17. praisonai/capabilities/a2a.py +140 -0
  18. praisonai/capabilities/assistants.py +283 -0
  19. praisonai/capabilities/audio.py +320 -0
  20. praisonai/capabilities/batches.py +469 -0
  21. praisonai/capabilities/completions.py +336 -0
  22. praisonai/capabilities/container_files.py +155 -0
  23. praisonai/capabilities/containers.py +93 -0
  24. praisonai/capabilities/embeddings.py +158 -0
  25. praisonai/capabilities/files.py +467 -0
  26. praisonai/capabilities/fine_tuning.py +293 -0
  27. praisonai/capabilities/guardrails.py +182 -0
  28. praisonai/capabilities/images.py +330 -0
  29. praisonai/capabilities/mcp.py +190 -0
  30. praisonai/capabilities/messages.py +270 -0
  31. praisonai/capabilities/moderations.py +154 -0
  32. praisonai/capabilities/ocr.py +217 -0
  33. praisonai/capabilities/passthrough.py +204 -0
  34. praisonai/capabilities/rag.py +207 -0
  35. praisonai/capabilities/realtime.py +160 -0
  36. praisonai/capabilities/rerank.py +165 -0
  37. praisonai/capabilities/responses.py +266 -0
  38. praisonai/capabilities/search.py +109 -0
  39. praisonai/capabilities/skills.py +133 -0
  40. praisonai/capabilities/vector_store_files.py +334 -0
  41. praisonai/capabilities/vector_stores.py +304 -0
  42. praisonai/capabilities/videos.py +141 -0
  43. praisonai/chainlit_ui.py +304 -0
  44. praisonai/chat/__init__.py +106 -0
  45. praisonai/chat/app.py +125 -0
  46. praisonai/cli/__init__.py +26 -0
  47. praisonai/cli/app.py +213 -0
  48. praisonai/cli/commands/__init__.py +75 -0
  49. praisonai/cli/commands/acp.py +70 -0
  50. praisonai/cli/commands/completion.py +333 -0
  51. praisonai/cli/commands/config.py +166 -0
  52. praisonai/cli/commands/debug.py +142 -0
  53. praisonai/cli/commands/diag.py +55 -0
  54. praisonai/cli/commands/doctor.py +166 -0
  55. praisonai/cli/commands/environment.py +179 -0
  56. praisonai/cli/commands/lsp.py +112 -0
  57. praisonai/cli/commands/mcp.py +210 -0
  58. praisonai/cli/commands/profile.py +457 -0
  59. praisonai/cli/commands/run.py +228 -0
  60. praisonai/cli/commands/schedule.py +150 -0
  61. praisonai/cli/commands/serve.py +97 -0
  62. praisonai/cli/commands/session.py +212 -0
  63. praisonai/cli/commands/traces.py +145 -0
  64. praisonai/cli/commands/version.py +101 -0
  65. praisonai/cli/configuration/__init__.py +18 -0
  66. praisonai/cli/configuration/loader.py +353 -0
  67. praisonai/cli/configuration/paths.py +114 -0
  68. praisonai/cli/configuration/schema.py +164 -0
  69. praisonai/cli/features/__init__.py +268 -0
  70. praisonai/cli/features/acp.py +236 -0
  71. praisonai/cli/features/action_orchestrator.py +546 -0
  72. praisonai/cli/features/agent_scheduler.py +773 -0
  73. praisonai/cli/features/agent_tools.py +474 -0
  74. praisonai/cli/features/agents.py +375 -0
  75. praisonai/cli/features/at_mentions.py +471 -0
  76. praisonai/cli/features/auto_memory.py +182 -0
  77. praisonai/cli/features/autonomy_mode.py +490 -0
  78. praisonai/cli/features/background.py +356 -0
  79. praisonai/cli/features/base.py +168 -0
  80. praisonai/cli/features/capabilities.py +1326 -0
  81. praisonai/cli/features/checkpoints.py +338 -0
  82. praisonai/cli/features/code_intelligence.py +652 -0
  83. praisonai/cli/features/compaction.py +294 -0
  84. praisonai/cli/features/compare.py +534 -0
  85. praisonai/cli/features/cost_tracker.py +514 -0
  86. praisonai/cli/features/debug.py +810 -0
  87. praisonai/cli/features/deploy.py +517 -0
  88. praisonai/cli/features/diag.py +289 -0
  89. praisonai/cli/features/doctor/__init__.py +63 -0
  90. praisonai/cli/features/doctor/checks/__init__.py +24 -0
  91. praisonai/cli/features/doctor/checks/acp_checks.py +240 -0
  92. praisonai/cli/features/doctor/checks/config_checks.py +366 -0
  93. praisonai/cli/features/doctor/checks/db_checks.py +366 -0
  94. praisonai/cli/features/doctor/checks/env_checks.py +543 -0
  95. praisonai/cli/features/doctor/checks/lsp_checks.py +199 -0
  96. praisonai/cli/features/doctor/checks/mcp_checks.py +349 -0
  97. praisonai/cli/features/doctor/checks/memory_checks.py +268 -0
  98. praisonai/cli/features/doctor/checks/network_checks.py +251 -0
  99. praisonai/cli/features/doctor/checks/obs_checks.py +328 -0
  100. praisonai/cli/features/doctor/checks/performance_checks.py +235 -0
  101. praisonai/cli/features/doctor/checks/permissions_checks.py +259 -0
  102. praisonai/cli/features/doctor/checks/selftest_checks.py +322 -0
  103. praisonai/cli/features/doctor/checks/serve_checks.py +426 -0
  104. praisonai/cli/features/doctor/checks/skills_checks.py +231 -0
  105. praisonai/cli/features/doctor/checks/tools_checks.py +371 -0
  106. praisonai/cli/features/doctor/engine.py +266 -0
  107. praisonai/cli/features/doctor/formatters.py +310 -0
  108. praisonai/cli/features/doctor/handler.py +397 -0
  109. praisonai/cli/features/doctor/models.py +264 -0
  110. praisonai/cli/features/doctor/registry.py +239 -0
  111. praisonai/cli/features/endpoints.py +1019 -0
  112. praisonai/cli/features/eval.py +560 -0
  113. praisonai/cli/features/external_agents.py +231 -0
  114. praisonai/cli/features/fast_context.py +410 -0
  115. praisonai/cli/features/flow_display.py +566 -0
  116. praisonai/cli/features/git_integration.py +651 -0
  117. praisonai/cli/features/guardrail.py +171 -0
  118. praisonai/cli/features/handoff.py +185 -0
  119. praisonai/cli/features/hooks.py +583 -0
  120. praisonai/cli/features/image.py +384 -0
  121. praisonai/cli/features/interactive_runtime.py +585 -0
  122. praisonai/cli/features/interactive_tools.py +380 -0
  123. praisonai/cli/features/interactive_tui.py +603 -0
  124. praisonai/cli/features/jobs.py +632 -0
  125. praisonai/cli/features/knowledge.py +531 -0
  126. praisonai/cli/features/lite.py +244 -0
  127. praisonai/cli/features/lsp_cli.py +225 -0
  128. praisonai/cli/features/mcp.py +169 -0
  129. praisonai/cli/features/message_queue.py +587 -0
  130. praisonai/cli/features/metrics.py +211 -0
  131. praisonai/cli/features/n8n.py +673 -0
  132. praisonai/cli/features/observability.py +293 -0
  133. praisonai/cli/features/ollama.py +361 -0
  134. praisonai/cli/features/output_style.py +273 -0
  135. praisonai/cli/features/package.py +631 -0
  136. praisonai/cli/features/performance.py +308 -0
  137. praisonai/cli/features/persistence.py +636 -0
  138. praisonai/cli/features/profile.py +226 -0
  139. praisonai/cli/features/profiler/__init__.py +81 -0
  140. praisonai/cli/features/profiler/core.py +558 -0
  141. praisonai/cli/features/profiler/optimizations.py +652 -0
  142. praisonai/cli/features/profiler/suite.py +386 -0
  143. praisonai/cli/features/profiling.py +350 -0
  144. praisonai/cli/features/queue/__init__.py +73 -0
  145. praisonai/cli/features/queue/manager.py +395 -0
  146. praisonai/cli/features/queue/models.py +286 -0
  147. praisonai/cli/features/queue/persistence.py +564 -0
  148. praisonai/cli/features/queue/scheduler.py +484 -0
  149. praisonai/cli/features/queue/worker.py +372 -0
  150. praisonai/cli/features/recipe.py +1723 -0
  151. praisonai/cli/features/recipes.py +449 -0
  152. praisonai/cli/features/registry.py +229 -0
  153. praisonai/cli/features/repo_map.py +860 -0
  154. praisonai/cli/features/router.py +466 -0
  155. praisonai/cli/features/sandbox_executor.py +515 -0
  156. praisonai/cli/features/serve.py +829 -0
  157. praisonai/cli/features/session.py +222 -0
  158. praisonai/cli/features/skills.py +856 -0
  159. praisonai/cli/features/slash_commands.py +650 -0
  160. praisonai/cli/features/telemetry.py +179 -0
  161. praisonai/cli/features/templates.py +1384 -0
  162. praisonai/cli/features/thinking.py +305 -0
  163. praisonai/cli/features/todo.py +334 -0
  164. praisonai/cli/features/tools.py +680 -0
  165. praisonai/cli/features/tui/__init__.py +83 -0
  166. praisonai/cli/features/tui/app.py +580 -0
  167. praisonai/cli/features/tui/cli.py +566 -0
  168. praisonai/cli/features/tui/debug.py +511 -0
  169. praisonai/cli/features/tui/events.py +99 -0
  170. praisonai/cli/features/tui/mock_provider.py +328 -0
  171. praisonai/cli/features/tui/orchestrator.py +652 -0
  172. praisonai/cli/features/tui/screens/__init__.py +50 -0
  173. praisonai/cli/features/tui/screens/main.py +245 -0
  174. praisonai/cli/features/tui/screens/queue.py +174 -0
  175. praisonai/cli/features/tui/screens/session.py +124 -0
  176. praisonai/cli/features/tui/screens/settings.py +148 -0
  177. praisonai/cli/features/tui/widgets/__init__.py +56 -0
  178. praisonai/cli/features/tui/widgets/chat.py +261 -0
  179. praisonai/cli/features/tui/widgets/composer.py +224 -0
  180. praisonai/cli/features/tui/widgets/queue_panel.py +200 -0
  181. praisonai/cli/features/tui/widgets/status.py +167 -0
  182. praisonai/cli/features/tui/widgets/tool_panel.py +248 -0
  183. praisonai/cli/features/workflow.py +720 -0
  184. praisonai/cli/legacy.py +236 -0
  185. praisonai/cli/main.py +5559 -0
  186. praisonai/cli/schedule_cli.py +54 -0
  187. praisonai/cli/state/__init__.py +31 -0
  188. praisonai/cli/state/identifiers.py +161 -0
  189. praisonai/cli/state/sessions.py +313 -0
  190. praisonai/code/__init__.py +93 -0
  191. praisonai/code/agent_tools.py +344 -0
  192. praisonai/code/diff/__init__.py +21 -0
  193. praisonai/code/diff/diff_strategy.py +432 -0
  194. praisonai/code/tools/__init__.py +27 -0
  195. praisonai/code/tools/apply_diff.py +221 -0
  196. praisonai/code/tools/execute_command.py +275 -0
  197. praisonai/code/tools/list_files.py +274 -0
  198. praisonai/code/tools/read_file.py +206 -0
  199. praisonai/code/tools/search_replace.py +248 -0
  200. praisonai/code/tools/write_file.py +217 -0
  201. praisonai/code/utils/__init__.py +46 -0
  202. praisonai/code/utils/file_utils.py +307 -0
  203. praisonai/code/utils/ignore_utils.py +308 -0
  204. praisonai/code/utils/text_utils.py +276 -0
  205. praisonai/db/__init__.py +64 -0
  206. praisonai/db/adapter.py +531 -0
  207. praisonai/deploy/__init__.py +62 -0
  208. praisonai/deploy/api.py +231 -0
  209. praisonai/deploy/docker.py +454 -0
  210. praisonai/deploy/doctor.py +367 -0
  211. praisonai/deploy/main.py +327 -0
  212. praisonai/deploy/models.py +179 -0
  213. praisonai/deploy/providers/__init__.py +33 -0
  214. praisonai/deploy/providers/aws.py +331 -0
  215. praisonai/deploy/providers/azure.py +358 -0
  216. praisonai/deploy/providers/base.py +101 -0
  217. praisonai/deploy/providers/gcp.py +314 -0
  218. praisonai/deploy/schema.py +208 -0
  219. praisonai/deploy.py +185 -0
  220. praisonai/endpoints/__init__.py +53 -0
  221. praisonai/endpoints/a2u_server.py +410 -0
  222. praisonai/endpoints/discovery.py +165 -0
  223. praisonai/endpoints/providers/__init__.py +28 -0
  224. praisonai/endpoints/providers/a2a.py +253 -0
  225. praisonai/endpoints/providers/a2u.py +208 -0
  226. praisonai/endpoints/providers/agents_api.py +171 -0
  227. praisonai/endpoints/providers/base.py +231 -0
  228. praisonai/endpoints/providers/mcp.py +263 -0
  229. praisonai/endpoints/providers/recipe.py +206 -0
  230. praisonai/endpoints/providers/tools_mcp.py +150 -0
  231. praisonai/endpoints/registry.py +131 -0
  232. praisonai/endpoints/server.py +161 -0
  233. praisonai/inbuilt_tools/__init__.py +24 -0
  234. praisonai/inbuilt_tools/autogen_tools.py +117 -0
  235. praisonai/inc/__init__.py +2 -0
  236. praisonai/inc/config.py +96 -0
  237. praisonai/inc/models.py +155 -0
  238. praisonai/integrations/__init__.py +56 -0
  239. praisonai/integrations/base.py +303 -0
  240. praisonai/integrations/claude_code.py +270 -0
  241. praisonai/integrations/codex_cli.py +255 -0
  242. praisonai/integrations/cursor_cli.py +195 -0
  243. praisonai/integrations/gemini_cli.py +222 -0
  244. praisonai/jobs/__init__.py +67 -0
  245. praisonai/jobs/executor.py +425 -0
  246. praisonai/jobs/models.py +230 -0
  247. praisonai/jobs/router.py +314 -0
  248. praisonai/jobs/server.py +186 -0
  249. praisonai/jobs/store.py +203 -0
  250. praisonai/llm/__init__.py +66 -0
  251. praisonai/llm/registry.py +382 -0
  252. praisonai/mcp_server/__init__.py +152 -0
  253. praisonai/mcp_server/adapters/__init__.py +74 -0
  254. praisonai/mcp_server/adapters/agents.py +128 -0
  255. praisonai/mcp_server/adapters/capabilities.py +168 -0
  256. praisonai/mcp_server/adapters/cli_tools.py +568 -0
  257. praisonai/mcp_server/adapters/extended_capabilities.py +462 -0
  258. praisonai/mcp_server/adapters/knowledge.py +93 -0
  259. praisonai/mcp_server/adapters/memory.py +104 -0
  260. praisonai/mcp_server/adapters/prompts.py +306 -0
  261. praisonai/mcp_server/adapters/resources.py +124 -0
  262. praisonai/mcp_server/adapters/tools_bridge.py +280 -0
  263. praisonai/mcp_server/auth/__init__.py +48 -0
  264. praisonai/mcp_server/auth/api_key.py +291 -0
  265. praisonai/mcp_server/auth/oauth.py +460 -0
  266. praisonai/mcp_server/auth/oidc.py +289 -0
  267. praisonai/mcp_server/auth/scopes.py +260 -0
  268. praisonai/mcp_server/cli.py +852 -0
  269. praisonai/mcp_server/elicitation.py +445 -0
  270. praisonai/mcp_server/icons.py +302 -0
  271. praisonai/mcp_server/recipe_adapter.py +573 -0
  272. praisonai/mcp_server/recipe_cli.py +824 -0
  273. praisonai/mcp_server/registry.py +703 -0
  274. praisonai/mcp_server/sampling.py +422 -0
  275. praisonai/mcp_server/server.py +490 -0
  276. praisonai/mcp_server/tasks.py +443 -0
  277. praisonai/mcp_server/transports/__init__.py +18 -0
  278. praisonai/mcp_server/transports/http_stream.py +376 -0
  279. praisonai/mcp_server/transports/stdio.py +132 -0
  280. praisonai/persistence/__init__.py +84 -0
  281. praisonai/persistence/config.py +238 -0
  282. praisonai/persistence/conversation/__init__.py +25 -0
  283. praisonai/persistence/conversation/async_mysql.py +427 -0
  284. praisonai/persistence/conversation/async_postgres.py +410 -0
  285. praisonai/persistence/conversation/async_sqlite.py +371 -0
  286. praisonai/persistence/conversation/base.py +151 -0
  287. praisonai/persistence/conversation/json_store.py +250 -0
  288. praisonai/persistence/conversation/mysql.py +387 -0
  289. praisonai/persistence/conversation/postgres.py +401 -0
  290. praisonai/persistence/conversation/singlestore.py +240 -0
  291. praisonai/persistence/conversation/sqlite.py +341 -0
  292. praisonai/persistence/conversation/supabase.py +203 -0
  293. praisonai/persistence/conversation/surrealdb.py +287 -0
  294. praisonai/persistence/factory.py +301 -0
  295. praisonai/persistence/hooks/__init__.py +18 -0
  296. praisonai/persistence/hooks/agent_hooks.py +297 -0
  297. praisonai/persistence/knowledge/__init__.py +26 -0
  298. praisonai/persistence/knowledge/base.py +144 -0
  299. praisonai/persistence/knowledge/cassandra.py +232 -0
  300. praisonai/persistence/knowledge/chroma.py +295 -0
  301. praisonai/persistence/knowledge/clickhouse.py +242 -0
  302. praisonai/persistence/knowledge/cosmosdb_vector.py +438 -0
  303. praisonai/persistence/knowledge/couchbase.py +286 -0
  304. praisonai/persistence/knowledge/lancedb.py +216 -0
  305. praisonai/persistence/knowledge/langchain_adapter.py +291 -0
  306. praisonai/persistence/knowledge/lightrag_adapter.py +212 -0
  307. praisonai/persistence/knowledge/llamaindex_adapter.py +256 -0
  308. praisonai/persistence/knowledge/milvus.py +277 -0
  309. praisonai/persistence/knowledge/mongodb_vector.py +306 -0
  310. praisonai/persistence/knowledge/pgvector.py +335 -0
  311. praisonai/persistence/knowledge/pinecone.py +253 -0
  312. praisonai/persistence/knowledge/qdrant.py +301 -0
  313. praisonai/persistence/knowledge/redis_vector.py +291 -0
  314. praisonai/persistence/knowledge/singlestore_vector.py +299 -0
  315. praisonai/persistence/knowledge/surrealdb_vector.py +309 -0
  316. praisonai/persistence/knowledge/upstash_vector.py +266 -0
  317. praisonai/persistence/knowledge/weaviate.py +223 -0
  318. praisonai/persistence/migrations/__init__.py +10 -0
  319. praisonai/persistence/migrations/manager.py +251 -0
  320. praisonai/persistence/orchestrator.py +406 -0
  321. praisonai/persistence/state/__init__.py +21 -0
  322. praisonai/persistence/state/async_mongodb.py +200 -0
  323. praisonai/persistence/state/base.py +107 -0
  324. praisonai/persistence/state/dynamodb.py +226 -0
  325. praisonai/persistence/state/firestore.py +175 -0
  326. praisonai/persistence/state/gcs.py +155 -0
  327. praisonai/persistence/state/memory.py +245 -0
  328. praisonai/persistence/state/mongodb.py +158 -0
  329. praisonai/persistence/state/redis.py +190 -0
  330. praisonai/persistence/state/upstash.py +144 -0
  331. praisonai/persistence/tests/__init__.py +3 -0
  332. praisonai/persistence/tests/test_all_backends.py +633 -0
  333. praisonai/profiler.py +1214 -0
  334. praisonai/recipe/__init__.py +134 -0
  335. praisonai/recipe/bridge.py +278 -0
  336. praisonai/recipe/core.py +893 -0
  337. praisonai/recipe/exceptions.py +54 -0
  338. praisonai/recipe/history.py +402 -0
  339. praisonai/recipe/models.py +266 -0
  340. praisonai/recipe/operations.py +440 -0
  341. praisonai/recipe/policy.py +422 -0
  342. praisonai/recipe/registry.py +849 -0
  343. praisonai/recipe/runtime.py +214 -0
  344. praisonai/recipe/security.py +711 -0
  345. praisonai/recipe/serve.py +859 -0
  346. praisonai/recipe/server.py +613 -0
  347. praisonai/scheduler/__init__.py +45 -0
  348. praisonai/scheduler/agent_scheduler.py +552 -0
  349. praisonai/scheduler/base.py +124 -0
  350. praisonai/scheduler/daemon_manager.py +225 -0
  351. praisonai/scheduler/state_manager.py +155 -0
  352. praisonai/scheduler/yaml_loader.py +193 -0
  353. praisonai/scheduler.py +194 -0
  354. praisonai/setup/__init__.py +1 -0
  355. praisonai/setup/build.py +21 -0
  356. praisonai/setup/post_install.py +23 -0
  357. praisonai/setup/setup_conda_env.py +25 -0
  358. praisonai/setup.py +16 -0
  359. praisonai/templates/__init__.py +116 -0
  360. praisonai/templates/cache.py +364 -0
  361. praisonai/templates/dependency_checker.py +358 -0
  362. praisonai/templates/discovery.py +391 -0
  363. praisonai/templates/loader.py +564 -0
  364. praisonai/templates/registry.py +511 -0
  365. praisonai/templates/resolver.py +206 -0
  366. praisonai/templates/security.py +327 -0
  367. praisonai/templates/tool_override.py +498 -0
  368. praisonai/templates/tools_doctor.py +256 -0
  369. praisonai/test.py +105 -0
  370. praisonai/train.py +562 -0
  371. praisonai/train_vision.py +306 -0
  372. praisonai/ui/agents.py +824 -0
  373. praisonai/ui/callbacks.py +57 -0
  374. praisonai/ui/chainlit_compat.py +246 -0
  375. praisonai/ui/chat.py +532 -0
  376. praisonai/ui/code.py +717 -0
  377. praisonai/ui/colab.py +474 -0
  378. praisonai/ui/colab_chainlit.py +81 -0
  379. praisonai/ui/components/aicoder.py +284 -0
  380. praisonai/ui/context.py +283 -0
  381. praisonai/ui/database_config.py +56 -0
  382. praisonai/ui/db.py +294 -0
  383. praisonai/ui/realtime.py +488 -0
  384. praisonai/ui/realtimeclient/__init__.py +756 -0
  385. praisonai/ui/realtimeclient/tools.py +242 -0
  386. praisonai/ui/sql_alchemy.py +710 -0
  387. praisonai/upload_vision.py +140 -0
  388. praisonai/version.py +1 -0
  389. praisonai-3.0.0.dist-info/METADATA +3493 -0
  390. praisonai-3.0.0.dist-info/RECORD +393 -0
  391. praisonai-3.0.0.dist-info/WHEEL +5 -0
  392. praisonai-3.0.0.dist-info/entry_points.txt +4 -0
  393. praisonai-3.0.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,566 @@
1
+ """
2
+ Flow Display Handler for CLI.
3
+
4
+ Shows a visual flow diagram of the workflow WITHOUT executing it.
5
+ Usage: praisonai agents.yaml --flow-display
6
+ """
7
+
8
+ from typing import Any, Dict, Tuple
9
+ from .base import FlagHandler
10
+ import os
11
+ import yaml
12
+
13
+
14
+ class FlowDisplayHandler(FlagHandler):
15
+ """
16
+ Handler for --flow-display flag.
17
+
18
+ Shows a visual flow diagram/chart of agents and tasks WITHOUT executing.
19
+ This allows users to preview the workflow structure before running it.
20
+
21
+ Example:
22
+ praisonai agents.yaml --flow-display
23
+ """
24
+
25
+ def __init__(self, verbose: bool = False):
26
+ super().__init__(verbose)
27
+ self._console = None
28
+
29
+ @property
30
+ def feature_name(self) -> str:
31
+ return "flow_display"
32
+
33
+ @property
34
+ def flag_name(self) -> str:
35
+ return "flow-display"
36
+
37
+ @property
38
+ def flag_help(self) -> str:
39
+ return "Show workflow flow diagram without executing"
40
+
41
+ def _get_console(self):
42
+ """Get or create Rich Console."""
43
+ if self._console is None:
44
+ try:
45
+ from rich.console import Console
46
+ self._console = Console()
47
+ except ImportError:
48
+ pass
49
+ return self._console
50
+
51
+ def check_dependencies(self) -> Tuple[bool, str]:
52
+ """Check if Rich is available."""
53
+ try:
54
+ import importlib.util
55
+ rich_available = importlib.util.find_spec("rich") is not None
56
+ if not rich_available:
57
+ return False, "rich not installed. Install with: pip install rich"
58
+ return True, ""
59
+ except ImportError:
60
+ return False, "rich not installed. Install with: pip install rich"
61
+
62
+ def apply_to_agent_config(self, config: Dict[str, Any], flag_value: Any) -> Dict[str, Any]:
63
+ """Apply flow display configuration."""
64
+ if flag_value:
65
+ config['flow_display'] = True
66
+ return config
67
+
68
+ def display_flow_diagram(self, yaml_file: str, show_footer: bool = True) -> bool:
69
+ """
70
+ Display a visual flow diagram of the workflow from YAML file.
71
+
72
+ Args:
73
+ yaml_file: Path to the agents.yaml file
74
+ show_footer: Whether to show the "run without --flow-display" footer
75
+
76
+ Returns:
77
+ True if displayed successfully, False otherwise
78
+ """
79
+ console = self._get_console()
80
+ if not console:
81
+ print("Rich library not available for flow display")
82
+ return False
83
+
84
+ # Load YAML config
85
+ try:
86
+ if not os.path.exists(yaml_file):
87
+ console.print(f"[red]Error: File not found: {yaml_file}[/red]")
88
+ return False
89
+
90
+ with open(yaml_file, 'r') as f:
91
+ config = yaml.safe_load(f)
92
+ except Exception as e:
93
+ console.print(f"[red]Error loading YAML: {e}[/red]")
94
+ return False
95
+
96
+ # Detect YAML format: 'roles' (old) or 'agents'+'steps' (new workflow)
97
+ has_roles = 'roles' in config and config['roles']
98
+ has_agents = 'agents' in config and config['agents']
99
+ has_steps = 'steps' in config and config['steps']
100
+
101
+ if not has_roles and not has_agents:
102
+ console.print("[red]Error: Invalid YAML format. No 'roles' or 'agents' found.[/red]")
103
+ return False
104
+
105
+ try:
106
+ from rich.panel import Panel
107
+ from rich.table import Table
108
+ from rich.text import Text
109
+ from rich import box
110
+
111
+ # Determine format type
112
+ is_workflow_format = has_agents and has_steps
113
+
114
+ # Extract workflow info based on format
115
+ if is_workflow_format:
116
+ name = config.get('name', 'Workflow')
117
+ description = config.get('description', '')
118
+ framework = config.get('framework', 'praisonai')
119
+ workflow_config = config.get('workflow', {})
120
+ memory = workflow_config.get('memory_config', {}).get('persist', False)
121
+ num_agents = len(config['agents'])
122
+ num_steps = len(config['steps'])
123
+ else:
124
+ name = config.get('topic', 'Workflow')
125
+ description = ''
126
+ framework = config.get('framework', 'praisonai')
127
+ process = config.get('process', 'sequential')
128
+ memory = config.get('memory', False)
129
+ num_agents = len(config['roles'])
130
+ num_steps = sum(len(details.get('tasks', {})) for details in config['roles'].values())
131
+
132
+ # Build the flow diagram
133
+ console.print()
134
+
135
+ # === HEADER ===
136
+ header = Text()
137
+ header.append("📊 WORKFLOW FLOW DIAGRAM\n", style="bold cyan")
138
+ header.append("─" * 40, style="dim")
139
+
140
+ header_panel = Panel(
141
+ header,
142
+ border_style="cyan",
143
+ box=box.DOUBLE_EDGE,
144
+ padding=(0, 2)
145
+ )
146
+ console.print(header_panel)
147
+
148
+ # === WORKFLOW INFO ===
149
+ info_table = Table(show_header=False, box=None, padding=(0, 2))
150
+ info_table.add_column("Key", style="bold yellow")
151
+ info_table.add_column("Value", style="white")
152
+
153
+ info_table.add_row("📋 Name:", name)
154
+ if description:
155
+ info_table.add_row("📝 Description:", description)
156
+
157
+ # Show input if present ('input' is canonical, 'topic' is alias)
158
+ workflow_input = config.get('input', config.get('topic', ''))
159
+ if workflow_input:
160
+ info_table.add_row("💬 Input:", workflow_input)
161
+
162
+ info_table.add_row("⚙️ Framework:", framework)
163
+
164
+ if is_workflow_format:
165
+ info_table.add_row("🔄 Format:", "WORKFLOW (steps-based)")
166
+ planning = workflow_config.get('planning', False)
167
+ info_table.add_row("🧠 Planning:", "✅ Enabled" if planning else "❌ Disabled")
168
+ else:
169
+ info_table.add_row("🔄 Process:", process.upper())
170
+
171
+ info_table.add_row("💾 Memory:", "✅ Enabled" if memory else "❌ Disabled")
172
+ info_table.add_row("👥 Agents:", str(num_agents))
173
+ info_table.add_row("📝 Steps:", str(num_steps))
174
+
175
+ console.print(Panel(info_table, title="[bold white]Workflow Configuration[/bold white]",
176
+ border_style="blue", box=box.ROUNDED))
177
+ console.print()
178
+
179
+ # === FLOW DIAGRAM ===
180
+ if is_workflow_format:
181
+ self._display_steps_flow(console, config)
182
+ else:
183
+ process = config.get('process', 'sequential')
184
+ if process == 'sequential':
185
+ self._display_sequential_flow(console, config)
186
+ elif process == 'hierarchical':
187
+ self._display_hierarchical_flow(console, config)
188
+ else:
189
+ self._display_sequential_flow(console, config)
190
+
191
+ # === DETAILED AGENT INFO ===
192
+ console.print()
193
+ if is_workflow_format:
194
+ self._display_workflow_agent_details(console, config)
195
+ else:
196
+ self._display_agent_details(console, config)
197
+
198
+ # === FOOTER ===
199
+ if show_footer:
200
+ console.print()
201
+ footer = Text()
202
+ footer.append("💡 ", style="bold")
203
+ footer.append("To execute this workflow, run without --flow-display flag", style="dim italic")
204
+ console.print(Panel(footer, border_style="dim", box=box.ROUNDED))
205
+ console.print()
206
+
207
+ return True
208
+
209
+ except ImportError as e:
210
+ console.print(f"[red]Error: Rich components not available: {e}[/red]")
211
+ return False
212
+
213
+ def _display_sequential_flow(self, console, config: Dict):
214
+ """Display sequential flow diagram."""
215
+ from rich.panel import Panel
216
+ from rich.text import Text
217
+ from rich import box
218
+
219
+ roles = list(config['roles'].items())
220
+
221
+ # Box width (content area)
222
+ BOX_WIDTH = 36
223
+
224
+ def pad_line(content: str, width: int = BOX_WIDTH) -> str:
225
+ """Pad content to fixed width."""
226
+ padding = width - len(content)
227
+ if padding > 0:
228
+ return content + " " * padding
229
+ return content[:width]
230
+
231
+ flow_text = Text()
232
+ flow_text.append(" SEQUENTIAL EXECUTION FLOW\n\n", style="bold magenta")
233
+
234
+ for i, (role_key, details) in enumerate(roles):
235
+ role_name = details.get('role', role_key)
236
+ tasks = list(details.get('tasks', {}).keys())
237
+
238
+ # Agent box
239
+ if i == 0:
240
+ flow_text.append(" ┌── START ──┐\n", style="green")
241
+ flow_text.append(" │\n", style="dim")
242
+ flow_text.append(" ▼\n", style="dim")
243
+
244
+ # Agent node
245
+ flow_text.append(" ╔════════════════════════════════════╗\n", style="cyan")
246
+ line = f" Agent {i+1}: {role_name}"
247
+ flow_text.append(f" ║{pad_line(line)}║\n", style="cyan")
248
+
249
+ # Tasks
250
+ for task in tasks:
251
+ line = f" -> {task}"
252
+ flow_text.append(f" ║{pad_line(line)}║\n", style="dim white")
253
+
254
+ flow_text.append(" ╚════════════════════════════════════╝\n", style="cyan")
255
+
256
+ # Arrow to next
257
+ if i < len(roles) - 1:
258
+ flow_text.append(" │\n", style="dim")
259
+ flow_text.append(" output\n", style="dim italic")
260
+ flow_text.append(" ▼\n", style="dim")
261
+ else:
262
+ flow_text.append(" │\n", style="dim")
263
+ flow_text.append(" ▼\n", style="dim")
264
+ flow_text.append(" └── END ────┘\n", style="red")
265
+
266
+ console.print(Panel(flow_text, border_style="magenta", box=box.DOUBLE_EDGE,
267
+ title="[bold white]Execution Flow[/bold white]"))
268
+
269
+ def _display_hierarchical_flow(self, console, config: Dict):
270
+ """Display hierarchical flow diagram."""
271
+ from rich.panel import Panel
272
+ from rich.text import Text
273
+ from rich import box
274
+
275
+ manager_llm = config.get('manager_llm', 'default')
276
+
277
+ flow_text = Text()
278
+ flow_text.append("👑 HIERARCHICAL EXECUTION FLOW\n\n", style="bold magenta")
279
+
280
+ # Manager at top
281
+ flow_text.append(" ┌──────────────────────┐\n", style="yellow")
282
+ flow_text.append(" │ 👑 MANAGER AGENT │\n", style="bold yellow")
283
+ flow_text.append(f" │ LLM: {manager_llm:<14}│\n", style="dim yellow")
284
+ flow_text.append(" └──────────┬───────────┘\n", style="yellow")
285
+ flow_text.append(" │\n", style="dim")
286
+ flow_text.append(" ┌──────────┴───────────┐\n", style="dim")
287
+ flow_text.append(" │ delegates to │\n", style="dim italic")
288
+ flow_text.append(" └──────────┬───────────┘\n", style="dim")
289
+
290
+ roles = list(config['roles'].items())
291
+ num_agents = len(roles)
292
+
293
+ # Draw branches
294
+ if num_agents > 0:
295
+ branch_line = " "
296
+ for i in range(num_agents):
297
+ if i == 0:
298
+ branch_line += "┌" + "─" * 8
299
+ elif i == num_agents - 1:
300
+ branch_line += "┬" + "─" * 8 + "┐"
301
+ else:
302
+ branch_line += "┬" + "─" * 8
303
+ flow_text.append(branch_line + "\n", style="dim")
304
+
305
+ # Agent boxes
306
+ for i, (role_key, details) in enumerate(roles):
307
+ flow_text.append("\n ╔═══════════════╗", style="cyan")
308
+ flow_text.append("\n")
309
+
310
+ for i, (role_key, details) in enumerate(roles):
311
+ role_name = details.get('role', role_key)[:12]
312
+ flow_text.append(f" ║ 🤖 {role_name:<10} ║", style="cyan")
313
+ flow_text.append("\n")
314
+
315
+ for i, (role_key, details) in enumerate(roles):
316
+ flow_text.append(" ╚═══════════════╝", style="cyan")
317
+ flow_text.append("\n")
318
+
319
+ console.print(Panel(flow_text, border_style="magenta", box=box.DOUBLE_EDGE,
320
+ title="[bold white]Execution Flow[/bold white]"))
321
+
322
+ def _display_agent_details(self, console, config: Dict):
323
+ """Display detailed agent information."""
324
+ from rich.table import Table
325
+ from rich import box
326
+
327
+ table = Table(
328
+ title="[bold cyan]📋 Agent & Task Details[/bold cyan]",
329
+ box=box.ROUNDED,
330
+ show_header=True,
331
+ header_style="bold magenta",
332
+ border_style="blue",
333
+ padding=(0, 1),
334
+ expand=True
335
+ )
336
+
337
+ table.add_column("#", style="dim", width=3, justify="center")
338
+ table.add_column("Agent", style="bold yellow", min_width=15)
339
+ table.add_column("Role", style="cyan", min_width=15)
340
+ table.add_column("Goal", style="white", min_width=25, overflow="fold")
341
+ table.add_column("Tasks", style="green", min_width=20)
342
+ table.add_column("Tools", style="magenta", min_width=15)
343
+
344
+ for i, (role_key, details) in enumerate(config['roles'].items(), 1):
345
+ role_name = details.get('role', role_key)
346
+ goal = details.get('goal', '-')
347
+ if len(goal) > 50:
348
+ goal = goal[:47] + "..."
349
+
350
+ tasks = list(details.get('tasks', {}).keys())
351
+ tasks_str = "\n".join(f"• {t}" for t in tasks) if tasks else "-"
352
+
353
+ tools = details.get('tools', [])
354
+ tools_str = ", ".join(t for t in tools if t) if tools else "-"
355
+
356
+ table.add_row(
357
+ str(i),
358
+ role_name,
359
+ role_key,
360
+ goal,
361
+ tasks_str,
362
+ tools_str
363
+ )
364
+
365
+ console.print(table)
366
+
367
+ def _display_steps_flow(self, console, config: Dict):
368
+ """Display steps-based workflow flow diagram."""
369
+ from rich.panel import Panel
370
+ from rich.text import Text
371
+ from rich import box
372
+
373
+ steps = config.get('steps', [])
374
+ agents = config.get('agents', {})
375
+
376
+ # Box width (content area)
377
+ BOX_WIDTH = 36
378
+
379
+ def pad_line(content: str, width: int = BOX_WIDTH) -> str:
380
+ """Pad content to fixed width, accounting for emoji width."""
381
+ # Emojis typically take 2 character widths
382
+ emoji_count = sum(1 for c in content if ord(c) > 0x1F300)
383
+ actual_len = len(content) + emoji_count # Add extra for emoji width
384
+ padding = width - actual_len
385
+ if padding > 0:
386
+ return content + " " * padding
387
+ return content[:width]
388
+
389
+ flow_text = Text()
390
+ flow_text.append(" STEPS-BASED EXECUTION FLOW\n\n", style="bold magenta")
391
+
392
+ flow_text.append(" ┌── START ──┐\n", style="green")
393
+ flow_text.append(" │\n", style="dim")
394
+ flow_text.append(" ▼\n", style="dim")
395
+
396
+ for i, step in enumerate(steps):
397
+ # Determine step type
398
+ agent_key = step.get('agent', '')
399
+ step_name = step.get('name', '')
400
+
401
+ # Check for special step types
402
+ has_route = 'route' in step
403
+ has_parallel = 'parallel' in step
404
+ has_loop = 'loop' in step
405
+ has_repeat = 'repeat' in step
406
+
407
+ if has_route:
408
+ # Route step
409
+ flow_text.append(" ╔════════════════════════════════════╗\n", style="yellow")
410
+ line = f" ROUTE: {step_name or 'routing'}"
411
+ flow_text.append(f" ║{pad_line(line)}║\n", style="yellow")
412
+
413
+ routes = step['route']
414
+ for route_name, route_agents in routes.items():
415
+ agents_str = ", ".join(route_agents) if isinstance(route_agents, list) else str(route_agents)
416
+ line = f" -> {route_name}: {agents_str}"
417
+ flow_text.append(f" ║{pad_line(line)}║\n", style="yellow")
418
+
419
+ flow_text.append(" ╚════════════════════════════════════╝\n", style="yellow")
420
+
421
+ elif has_parallel:
422
+ # Parallel step
423
+ flow_text.append(" ╔════════════════════════════════════╗\n", style="green")
424
+ line = f" PARALLEL: {step_name or 'parallel'}"
425
+ flow_text.append(f" ║{pad_line(line)}║\n", style="green")
426
+
427
+ for p_step in step['parallel']:
428
+ p_agent = p_step.get('agent', '?')
429
+ line = f" |-- {p_agent}"
430
+ flow_text.append(f" ║{pad_line(line)}║\n", style="green")
431
+
432
+ flow_text.append(" ╚════════════════════════════════════╝\n", style="green")
433
+
434
+ else:
435
+ # Regular agent step
436
+ agent_info = agents.get(agent_key, {})
437
+ agent_name = agent_info.get('name', agent_key)
438
+
439
+ flow_text.append(" ╔════════════════════════════════════╗\n", style="cyan")
440
+ line = f" Step {i+1}: {agent_name}"
441
+ flow_text.append(f" ║{pad_line(line)}║\n", style="cyan")
442
+
443
+ # Show modifiers
444
+ if has_loop:
445
+ loop_over = step['loop'].get('over', '?')
446
+ line = f" [loop over: {loop_over}]"
447
+ flow_text.append(f" ║{pad_line(line)}║\n", style="dim magenta")
448
+
449
+ if has_repeat:
450
+ until = step['repeat'].get('until', '?')
451
+ max_iter = step['repeat'].get('max_iterations', '?')
452
+ line = f" [repeat until: {until} max:{max_iter}]"
453
+ flow_text.append(f" ║{pad_line(line)}║\n", style="dim magenta")
454
+
455
+ flow_text.append(" ╚════════════════════════════════════╝\n", style="cyan")
456
+
457
+ # Arrow to next
458
+ if i < len(steps) - 1:
459
+ flow_text.append(" │\n", style="dim")
460
+ flow_text.append(" ▼\n", style="dim")
461
+
462
+ flow_text.append(" │\n", style="dim")
463
+ flow_text.append(" ▼\n", style="dim")
464
+ flow_text.append(" └── END ────┘\n", style="red")
465
+
466
+ console.print(Panel(flow_text, border_style="magenta", box=box.DOUBLE_EDGE,
467
+ title="[bold white]Execution Flow[/bold white]"))
468
+
469
+ def _display_workflow_agent_details(self, console, config: Dict):
470
+ """Display detailed agent information for workflow format."""
471
+ from rich.table import Table
472
+ from rich import box
473
+
474
+ table = Table(
475
+ title="[bold cyan]📋 Agent Details[/bold cyan]",
476
+ box=box.ROUNDED,
477
+ show_header=True,
478
+ header_style="bold magenta",
479
+ border_style="blue",
480
+ padding=(0, 1),
481
+ expand=True
482
+ )
483
+
484
+ table.add_column("#", style="dim", width=3, justify="center")
485
+ table.add_column("Agent Key", style="bold yellow", min_width=15)
486
+ table.add_column("Name", style="cyan", min_width=15)
487
+ table.add_column("Role", style="white", min_width=20)
488
+ table.add_column("Goal", style="green", min_width=25, overflow="fold")
489
+
490
+ for i, (agent_key, details) in enumerate(config['agents'].items(), 1):
491
+ name = details.get('name', agent_key)
492
+ role = details.get('role', '-')
493
+ goal = details.get('goal', '-')
494
+ if len(goal) > 40:
495
+ goal = goal[:37] + "..."
496
+
497
+ table.add_row(
498
+ str(i),
499
+ agent_key,
500
+ name,
501
+ role,
502
+ goal
503
+ )
504
+
505
+ console.print(table)
506
+
507
+ def display_workflow_start(self, workflow_name: str, agents: list) -> None:
508
+ """
509
+ Display workflow start message.
510
+
511
+ Args:
512
+ workflow_name: Name of the workflow being started
513
+ agents: List of agent names in the workflow
514
+ """
515
+ console = self._get_console()
516
+ if console:
517
+ try:
518
+ from rich.panel import Panel
519
+ from rich import box
520
+
521
+ agents_str = ", ".join(agents) if agents else "No agents"
522
+ content = f"🚀 Starting: {workflow_name}\n👥 Agents: {agents_str}"
523
+ console.print(Panel(content, title="[bold cyan]Workflow Started[/bold cyan]",
524
+ border_style="cyan", box=box.ROUNDED))
525
+ except ImportError:
526
+ print(f"Starting workflow: {workflow_name} with agents: {agents}")
527
+
528
+ def display_workflow_end(self, success: bool = True) -> None:
529
+ """
530
+ Display workflow end message.
531
+
532
+ Args:
533
+ success: Whether the workflow completed successfully
534
+ """
535
+ console = self._get_console()
536
+ if console:
537
+ try:
538
+ from rich.panel import Panel
539
+ from rich import box
540
+
541
+ if success:
542
+ content = "✅ Workflow completed successfully"
543
+ style = "green"
544
+ else:
545
+ content = "❌ Workflow failed"
546
+ style = "red"
547
+
548
+ console.print(Panel(content, title=f"[bold {style}]Workflow Ended[/bold {style}]",
549
+ border_style=style, box=box.ROUNDED))
550
+ except ImportError:
551
+ status = "successfully" if success else "with errors"
552
+ print(f"Workflow ended {status}")
553
+
554
+ def execute(self, yaml_file: str = None, **kwargs) -> bool:
555
+ """
556
+ Execute flow display - shows diagram without running workflow.
557
+
558
+ Args:
559
+ yaml_file: Path to the YAML file
560
+
561
+ Returns:
562
+ True if displayed successfully
563
+ """
564
+ if yaml_file:
565
+ return self.display_flow_diagram(yaml_file)
566
+ return False