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,829 @@
1
+ """
2
+ Serve CLI Feature Handler
3
+
4
+ Provides CLI commands for launching PraisonAI servers:
5
+ - praisonai serve agents - Launch agents as HTTP API
6
+ - praisonai serve recipe - Launch recipe runner
7
+ - praisonai serve mcp - Launch MCP server
8
+ - praisonai serve tools - Launch tools as MCP server
9
+ - praisonai serve a2a - Launch A2A server
10
+ - praisonai serve a2u - Launch A2U event stream server
11
+ - praisonai serve unified - Launch unified server with all providers
12
+
13
+ All servers include the unified discovery endpoint at /__praisonai__/discovery.
14
+ """
15
+
16
+ import os
17
+ import sys
18
+ from typing import Any, Dict, List
19
+
20
+
21
+ class ServeHandler:
22
+ """
23
+ CLI handler for serve operations.
24
+
25
+ Commands:
26
+ - agents: Launch agents as HTTP API
27
+ - recipe: Launch recipe runner
28
+ - mcp: Launch MCP server
29
+ - tools: Launch tools as MCP server
30
+ - a2a: Launch A2A server
31
+ - a2u: Launch A2U event stream server
32
+ - unified: Launch unified server
33
+ """
34
+
35
+ EXIT_SUCCESS = 0
36
+ EXIT_GENERAL_ERROR = 1
37
+ EXIT_VALIDATION_ERROR = 2
38
+
39
+ DEFAULT_HOST = "127.0.0.1"
40
+ DEFAULT_PORT = 8765
41
+
42
+ def __init__(self):
43
+ """Initialize the handler."""
44
+ pass
45
+
46
+ def handle(self, args: List[str]) -> int:
47
+ """
48
+ Handle serve subcommand.
49
+
50
+ Args:
51
+ args: Command arguments
52
+
53
+ Returns:
54
+ Exit code
55
+ """
56
+ if not args:
57
+ self._print_help()
58
+ return self.EXIT_SUCCESS
59
+
60
+ command = args[0]
61
+ remaining = args[1:]
62
+
63
+ commands = {
64
+ "agents": self.cmd_agents,
65
+ "recipe": self.cmd_recipe,
66
+ "mcp": self.cmd_mcp,
67
+ "tools": self.cmd_tools,
68
+ "a2a": self.cmd_a2a,
69
+ "a2u": self.cmd_a2u,
70
+ "unified": self.cmd_unified,
71
+ "help": lambda _: self._print_help() or self.EXIT_SUCCESS,
72
+ "--help": lambda _: self._print_help() or self.EXIT_SUCCESS,
73
+ "-h": lambda _: self._print_help() or self.EXIT_SUCCESS,
74
+ }
75
+
76
+ if command in commands:
77
+ return commands[command](remaining)
78
+ else:
79
+ self._print_error(f"Unknown command: {command}")
80
+ self._print_help()
81
+ return self.EXIT_GENERAL_ERROR
82
+
83
+ def _print_help(self):
84
+ """Print help message."""
85
+ help_text = """
86
+ [bold cyan]PraisonAI Serve[/bold cyan]
87
+
88
+ Launch PraisonAI servers with unified discovery support.
89
+
90
+ [bold]Usage:[/bold]
91
+ praisonai serve <command> [options]
92
+
93
+ [bold]Commands:[/bold]
94
+ agents Launch agents as HTTP API
95
+ recipe Launch recipe runner server
96
+ mcp Launch MCP server (HTTP mode)
97
+ tools Launch tools as MCP server
98
+ a2a Launch A2A protocol server
99
+ a2u Launch A2U event stream server
100
+ unified Launch unified server with all providers
101
+
102
+ [bold]Common Options:[/bold]
103
+ --host <host> Server host (default: 127.0.0.1)
104
+ --port <port> Server port (default: 8765)
105
+ --reload Enable hot reload
106
+ --api-key <key> API key for authentication
107
+
108
+ [bold]Agents Options:[/bold]
109
+ --file <path> Agents YAML file (default: agents.yaml)
110
+ --path <path> API endpoint path (default: /agents)
111
+
112
+ [bold]Recipe Options:[/bold]
113
+ --config <path> Config file path (serve.yaml)
114
+ --preload Preload all recipes
115
+
116
+ [bold]MCP Options:[/bold]
117
+ --transport Transport type: http, sse (default: http)
118
+
119
+ [bold]Examples:[/bold]
120
+ praisonai serve agents --file agents.yaml --port 8000
121
+ praisonai serve recipe --port 8765
122
+ praisonai serve mcp --transport http --port 8080
123
+ praisonai serve tools --port 8081
124
+ praisonai serve a2a --port 8082
125
+ praisonai serve unified --port 8765
126
+
127
+ [bold]Discovery:[/bold]
128
+ All servers expose /__praisonai__/discovery for unified endpoint discovery.
129
+ Use `praisonai endpoints` to interact with any server.
130
+ """
131
+ self._print_rich(help_text)
132
+
133
+ def _print_rich(self, text: str):
134
+ """Print with rich formatting if available."""
135
+ try:
136
+ from rich import print as rprint
137
+ rprint(text)
138
+ except ImportError:
139
+ import re
140
+ plain = re.sub(r'\[/?[^\]]+\]', '', text)
141
+ print(plain)
142
+
143
+ def _print_error(self, message: str):
144
+ """Print error message."""
145
+ try:
146
+ from rich import print as rprint
147
+ rprint(f"[red]Error: {message}[/red]")
148
+ except ImportError:
149
+ print(f"Error: {message}", file=sys.stderr)
150
+
151
+ def _print_success(self, message: str):
152
+ """Print success message."""
153
+ try:
154
+ from rich import print as rprint
155
+ rprint(f"[green]✓ {message}[/green]")
156
+ except ImportError:
157
+ print(f"✓ {message}")
158
+
159
+ def _parse_args(self, args: List[str], spec: Dict[str, Any]) -> Dict[str, Any]:
160
+ """Parse command arguments based on spec."""
161
+ result = {k: v.get("default") for k, v in spec.items()}
162
+
163
+ i = 0
164
+ while i < len(args):
165
+ arg = args[i]
166
+
167
+ if arg.startswith("--"):
168
+ key = arg[2:].replace("-", "_")
169
+ if key in spec:
170
+ if spec[key].get("flag"):
171
+ result[key] = True
172
+ elif i + 1 < len(args):
173
+ value = args[i + 1]
174
+ # Type conversion
175
+ if spec[key].get("type") == "int":
176
+ value = int(value)
177
+ result[key] = value
178
+ i += 1
179
+ i += 1
180
+ else:
181
+ i += 1
182
+
183
+ return result
184
+
185
+ def cmd_agents(self, args: List[str]) -> int:
186
+ """Launch agents as HTTP API."""
187
+ spec = {
188
+ "file": {"default": "agents.yaml"},
189
+ "host": {"default": self.DEFAULT_HOST},
190
+ "port": {"default": self.DEFAULT_PORT, "type": "int"},
191
+ "path": {"default": "/agents"},
192
+ "reload": {"flag": True, "default": False},
193
+ "api_key": {"default": None},
194
+ }
195
+ parsed = self._parse_args(args, spec)
196
+
197
+ # Check if agents file exists
198
+ if not os.path.exists(parsed["file"]):
199
+ self._print_error(f"Agents file not found: {parsed['file']}")
200
+ return self.EXIT_VALIDATION_ERROR
201
+
202
+ try:
203
+ self._print_success(f"Starting agents server on {parsed['host']}:{parsed['port']}")
204
+ print(f" Agents file: {parsed['file']}")
205
+ print(f" Endpoint: {parsed['path']}")
206
+ print(" Discovery: /__praisonai__/discovery")
207
+
208
+ # Create and run server
209
+ app = self._create_agents_app(parsed)
210
+ self._run_server(app, parsed["host"], parsed["port"], parsed["reload"])
211
+
212
+ except ImportError as e:
213
+ self._print_error(f"Missing dependency: {e}")
214
+ print("Install with: pip install praisonai[serve]")
215
+ return self.EXIT_GENERAL_ERROR
216
+ except Exception as e:
217
+ self._print_error(str(e))
218
+ return self.EXIT_GENERAL_ERROR
219
+
220
+ return self.EXIT_SUCCESS
221
+
222
+ def _create_agents_app(self, config: Dict[str, Any]) -> Any:
223
+ """Create FastAPI app for agents."""
224
+ from fastapi import FastAPI, HTTPException, Request
225
+ from fastapi.responses import JSONResponse
226
+ from pydantic import BaseModel
227
+
228
+ from praisonai.endpoints.discovery import (
229
+ create_discovery_document,
230
+ EndpointInfo,
231
+ ProviderInfo,
232
+ )
233
+ from praisonai.endpoints.server import add_discovery_routes
234
+
235
+ # Load agents from YAML
236
+ import yaml
237
+ with open(config["file"]) as f:
238
+ _ = yaml.safe_load(f) # Validate YAML
239
+
240
+ # Create discovery document
241
+ discovery = create_discovery_document(server_name="praisonai-agents")
242
+ discovery.add_provider(ProviderInfo(
243
+ type="agents-api",
244
+ name="Agents API",
245
+ description="Agent HTTP API endpoints",
246
+ capabilities=["invoke", "health"],
247
+ ))
248
+
249
+ # Create app
250
+ app = FastAPI(
251
+ title="PraisonAI Agents API",
252
+ description="HTTP API for PraisonAI Agents",
253
+ )
254
+
255
+ # Add discovery routes
256
+ add_discovery_routes(app, discovery)
257
+
258
+ # Request model
259
+ class AgentQuery(BaseModel):
260
+ query: str
261
+
262
+ # Create endpoint for agents
263
+ path = config["path"]
264
+
265
+ @app.post(path)
266
+ async def invoke_agents(request: Request, query_data: AgentQuery = None):
267
+ """Invoke agents with a query."""
268
+ if query_data is None:
269
+ try:
270
+ body = await request.json()
271
+ _ = body.get("query", "") # Extract query
272
+ except Exception:
273
+ raise HTTPException(status_code=400, detail="Invalid request")
274
+
275
+ try:
276
+ # Lazy load and run agents
277
+ from praisonai.agents_generator import AgentsGenerator
278
+
279
+ generator = AgentsGenerator(
280
+ agent_file=config["file"],
281
+ framework="praisonai",
282
+ )
283
+ result = generator.generate_crew_and_kickoff()
284
+
285
+ return {"response": result}
286
+ except Exception as e:
287
+ return JSONResponse(
288
+ {"error": str(e)},
289
+ status_code=500,
290
+ )
291
+
292
+ # Add endpoint to discovery
293
+ discovery.add_endpoint(EndpointInfo(
294
+ name=path.lstrip("/"),
295
+ description="Invoke agents workflow",
296
+ provider_type="agents-api",
297
+ input_schema={"type": "object", "properties": {"query": {"type": "string"}}},
298
+ streaming=["none"],
299
+ ))
300
+
301
+ # Root endpoint
302
+ @app.get("/")
303
+ async def root():
304
+ return {
305
+ "message": "PraisonAI Agents API",
306
+ "endpoints": [path],
307
+ "discovery": "/__praisonai__/discovery",
308
+ }
309
+
310
+ return app
311
+
312
+ def cmd_recipe(self, args: List[str]) -> int:
313
+ """Launch recipe runner server."""
314
+ spec = {
315
+ "host": {"default": self.DEFAULT_HOST},
316
+ "port": {"default": self.DEFAULT_PORT, "type": "int"},
317
+ "config": {"default": None},
318
+ "reload": {"flag": True, "default": False},
319
+ "api_key": {"default": None},
320
+ "preload": {"flag": True, "default": False},
321
+ }
322
+ parsed = self._parse_args(args, spec)
323
+
324
+ try:
325
+ self._print_success(f"Starting recipe server on {parsed['host']}:{parsed['port']}")
326
+ print(" Discovery: /__praisonai__/discovery")
327
+
328
+ from praisonai.recipe.serve import serve, load_config
329
+
330
+ # Load config
331
+ config = load_config(parsed["config"]) if parsed["config"] else {}
332
+ if parsed["api_key"]:
333
+ config["api_key"] = parsed["api_key"]
334
+
335
+ serve(
336
+ host=parsed["host"],
337
+ port=parsed["port"],
338
+ reload=parsed["reload"],
339
+ config=config,
340
+ )
341
+
342
+ except ImportError as e:
343
+ self._print_error(f"Missing dependency: {e}")
344
+ print("Install with: pip install praisonai[serve]")
345
+ return self.EXIT_GENERAL_ERROR
346
+ except Exception as e:
347
+ self._print_error(str(e))
348
+ return self.EXIT_GENERAL_ERROR
349
+
350
+ return self.EXIT_SUCCESS
351
+
352
+ def cmd_mcp(self, args: List[str]) -> int:
353
+ """Launch MCP server (DEPRECATED - use 'praisonai mcp serve' instead)."""
354
+ import sys
355
+
356
+ # Print deprecation warning
357
+ print("\n[yellow]⚠ DEPRECATION WARNING:[/yellow]", file=sys.stderr)
358
+ print("[yellow]'praisonai serve mcp' is deprecated and will be removed in a future version.[/yellow]", file=sys.stderr)
359
+ print("[yellow]Please use 'praisonai mcp serve' instead.[/yellow]\n", file=sys.stderr)
360
+
361
+ # Redirect to new MCP server CLI
362
+ try:
363
+ from praisonai.mcp_server.cli import handle_mcp_command
364
+
365
+ # Convert args to new format
366
+ new_args = ["serve"]
367
+ spec = {
368
+ "host": {"default": self.DEFAULT_HOST},
369
+ "port": {"default": 8080, "type": "int"},
370
+ "transport": {"default": "http-stream"},
371
+ }
372
+ parsed = self._parse_args(args, spec)
373
+
374
+ new_args.extend(["--host", parsed["host"]])
375
+ new_args.extend(["--port", str(parsed["port"])])
376
+ new_args.extend(["--transport", parsed["transport"]])
377
+
378
+ return handle_mcp_command(new_args)
379
+
380
+ except ImportError as e:
381
+ self._print_error(f"Missing dependency: {e}")
382
+ return self.EXIT_GENERAL_ERROR
383
+ except Exception as e:
384
+ self._print_error(str(e))
385
+ return self.EXIT_GENERAL_ERROR
386
+
387
+ def _create_mcp_app(self, config: Dict[str, Any]) -> Any:
388
+ """Create FastAPI app for MCP server."""
389
+ from fastapi import FastAPI
390
+
391
+ from praisonai.endpoints.discovery import (
392
+ create_discovery_document,
393
+ ProviderInfo,
394
+ )
395
+ from praisonai.endpoints.server import add_discovery_routes
396
+
397
+ # Create discovery document
398
+ discovery = create_discovery_document(server_name="praisonai-mcp")
399
+ discovery.add_provider(ProviderInfo(
400
+ type="mcp",
401
+ name="MCP Server",
402
+ description=f"MCP server ({config['transport']} transport)",
403
+ capabilities=["list-tools", "call-tool"],
404
+ ))
405
+
406
+ app = FastAPI(
407
+ title="PraisonAI MCP Server",
408
+ description="MCP protocol server",
409
+ )
410
+
411
+ add_discovery_routes(app, discovery)
412
+
413
+ # MCP tools endpoint
414
+ @app.get("/mcp/tools")
415
+ async def list_tools():
416
+ """List available MCP tools."""
417
+ # TODO: Load tools from config or registry
418
+ return {"tools": []}
419
+
420
+ @app.post("/mcp/tools/call")
421
+ async def call_tool(request_data: dict):
422
+ """Call an MCP tool."""
423
+ tool_name = request_data.get("tool")
424
+ _ = request_data.get("arguments", {}) # Arguments for tool
425
+
426
+ # TODO: Execute tool
427
+ return {"result": None, "tool": tool_name}
428
+
429
+ @app.get("/")
430
+ async def root():
431
+ return {
432
+ "message": "PraisonAI MCP Server",
433
+ "transport": config["transport"],
434
+ "discovery": "/__praisonai__/discovery",
435
+ }
436
+
437
+ return app
438
+
439
+ def cmd_tools(self, args: List[str]) -> int:
440
+ """Launch tools as MCP server (DEPRECATED - use 'praisonai mcp serve' instead)."""
441
+ import sys
442
+
443
+ # Print deprecation warning
444
+ print("\n[yellow]⚠ DEPRECATION WARNING:[/yellow]", file=sys.stderr)
445
+ print("[yellow]'praisonai serve tools' is deprecated and will be removed in a future version.[/yellow]", file=sys.stderr)
446
+ print("[yellow]Please use 'praisonai mcp serve' instead.[/yellow]\n", file=sys.stderr)
447
+
448
+ # Redirect to new MCP server CLI
449
+ try:
450
+ from praisonai.mcp_server.cli import handle_mcp_command
451
+
452
+ # Convert args to new format
453
+ new_args = ["serve"]
454
+ spec = {
455
+ "host": {"default": self.DEFAULT_HOST},
456
+ "port": {"default": 8080, "type": "int"},
457
+ }
458
+ parsed = self._parse_args(args, spec)
459
+
460
+ new_args.extend(["--host", parsed["host"]])
461
+ new_args.extend(["--port", str(parsed["port"])])
462
+ new_args.extend(["--transport", "http-stream"])
463
+
464
+ return handle_mcp_command(new_args)
465
+
466
+ except ImportError as e:
467
+ self._print_error(f"Missing dependency: {e}")
468
+ return self.EXIT_GENERAL_ERROR
469
+ except Exception as e:
470
+ self._print_error(str(e))
471
+ return self.EXIT_GENERAL_ERROR
472
+
473
+ def _create_tools_app(self, config: Dict[str, Any]) -> Any:
474
+ """Create FastAPI app for tools MCP server."""
475
+ from fastapi import FastAPI
476
+
477
+ from praisonai.endpoints.discovery import (
478
+ create_discovery_document,
479
+ ProviderInfo,
480
+ )
481
+ from praisonai.endpoints.server import add_discovery_routes
482
+
483
+ discovery = create_discovery_document(server_name="praisonai-tools-mcp")
484
+ discovery.add_provider(ProviderInfo(
485
+ type="tools-mcp",
486
+ name="Tools MCP Server",
487
+ description="Python tools exposed as MCP server",
488
+ capabilities=["list-tools", "call-tool"],
489
+ ))
490
+
491
+ app = FastAPI(
492
+ title="PraisonAI Tools MCP Server",
493
+ description="Tools exposed as MCP server",
494
+ )
495
+
496
+ add_discovery_routes(app, discovery)
497
+
498
+ @app.get("/tools")
499
+ async def list_tools():
500
+ """List available tools."""
501
+ return {"tools": []}
502
+
503
+ @app.post("/tools/call")
504
+ async def call_tool(request_data: dict):
505
+ """Call a tool."""
506
+ return {"result": None}
507
+
508
+ @app.get("/")
509
+ async def root():
510
+ return {
511
+ "message": "PraisonAI Tools MCP Server",
512
+ "discovery": "/__praisonai__/discovery",
513
+ }
514
+
515
+ return app
516
+
517
+ def cmd_a2a(self, args: List[str]) -> int:
518
+ """Launch A2A protocol server."""
519
+ spec = {
520
+ "host": {"default": self.DEFAULT_HOST},
521
+ "port": {"default": 8082, "type": "int"},
522
+ "file": {"default": "agents.yaml"},
523
+ }
524
+ parsed = self._parse_args(args, spec)
525
+
526
+ try:
527
+ self._print_success(f"Starting A2A server on {parsed['host']}:{parsed['port']}")
528
+ print(" Agent Card: /.well-known/agent.json")
529
+ print(" Discovery: /__praisonai__/discovery")
530
+
531
+ app = self._create_a2a_app(parsed)
532
+ self._run_server(app, parsed["host"], parsed["port"], False)
533
+
534
+ except ImportError as e:
535
+ self._print_error(f"Missing dependency: {e}")
536
+ return self.EXIT_GENERAL_ERROR
537
+ except Exception as e:
538
+ self._print_error(str(e))
539
+ return self.EXIT_GENERAL_ERROR
540
+
541
+ return self.EXIT_SUCCESS
542
+
543
+ def _create_a2a_app(self, config: Dict[str, Any]) -> Any:
544
+ """Create FastAPI app for A2A server."""
545
+ from fastapi import FastAPI
546
+
547
+ from praisonai.endpoints.discovery import (
548
+ create_discovery_document,
549
+ EndpointInfo,
550
+ ProviderInfo,
551
+ )
552
+ from praisonai.endpoints.server import add_discovery_routes
553
+
554
+ discovery = create_discovery_document(server_name="praisonai-a2a")
555
+ discovery.add_provider(ProviderInfo(
556
+ type="a2a",
557
+ name="A2A Protocol",
558
+ description="Agent-to-Agent communication",
559
+ capabilities=["agent-card", "message-send"],
560
+ ))
561
+
562
+ app = FastAPI(
563
+ title="PraisonAI A2A Server",
564
+ description="A2A protocol server",
565
+ )
566
+
567
+ add_discovery_routes(app, discovery)
568
+
569
+ # Agent card
570
+ @app.get("/.well-known/agent.json")
571
+ async def agent_card():
572
+ """Return agent card for A2A discovery."""
573
+ return {
574
+ "name": "PraisonAI Agent",
575
+ "description": "PraisonAI Agent via A2A protocol",
576
+ "version": "1.0.0",
577
+ "url": f"http://{config.get('host', 'localhost')}:{config.get('port', 8082)}/a2a",
578
+ "capabilities": {
579
+ "streaming": True,
580
+ "pushNotifications": False,
581
+ },
582
+ "skills": [],
583
+ }
584
+
585
+ @app.get("/status")
586
+ async def status():
587
+ """Return server status."""
588
+ return {"status": "ok", "name": "PraisonAI A2A", "version": "1.0.0"}
589
+
590
+ @app.post("/a2a")
591
+ async def a2a_endpoint(request_data: dict):
592
+ """Handle A2A JSON-RPC requests."""
593
+ method = request_data.get("method")
594
+ params = request_data.get("params", {})
595
+ request_id = request_data.get("id")
596
+
597
+ if method == "message/send":
598
+ # Handle message
599
+ message = params.get("message", {})
600
+ parts = message.get("parts", [])
601
+ text = ""
602
+ for part in parts:
603
+ if part.get("type") == "text":
604
+ text += part.get("text", "")
605
+
606
+ # TODO: Process with agent
607
+ return {
608
+ "jsonrpc": "2.0",
609
+ "id": request_id,
610
+ "result": {
611
+ "message": {
612
+ "role": "assistant",
613
+ "parts": [{"type": "text", "text": f"Received: {text}"}],
614
+ },
615
+ },
616
+ }
617
+
618
+ return {
619
+ "jsonrpc": "2.0",
620
+ "id": request_id,
621
+ "error": {"code": -32601, "message": f"Method not found: {method}"},
622
+ }
623
+
624
+ discovery.add_endpoint(EndpointInfo(
625
+ name="a2a",
626
+ description="A2A protocol endpoint",
627
+ provider_type="a2a",
628
+ streaming=["sse"],
629
+ ))
630
+
631
+ @app.get("/")
632
+ async def root():
633
+ return {
634
+ "message": "PraisonAI A2A Server",
635
+ "agent_card": "/.well-known/agent.json",
636
+ "discovery": "/__praisonai__/discovery",
637
+ }
638
+
639
+ return app
640
+
641
+ def cmd_a2u(self, args: List[str]) -> int:
642
+ """Launch A2U event stream server."""
643
+ spec = {
644
+ "host": {"default": self.DEFAULT_HOST},
645
+ "port": {"default": 8083, "type": "int"},
646
+ }
647
+ parsed = self._parse_args(args, spec)
648
+
649
+ try:
650
+ self._print_success(f"Starting A2U server on {parsed['host']}:{parsed['port']}")
651
+ print(" Events: /a2u/events/<stream>")
652
+ print(" Discovery: /__praisonai__/discovery")
653
+
654
+ app = self._create_a2u_app(parsed)
655
+ self._run_server(app, parsed["host"], parsed["port"], False)
656
+
657
+ except ImportError as e:
658
+ self._print_error(f"Missing dependency: {e}")
659
+ return self.EXIT_GENERAL_ERROR
660
+ except Exception as e:
661
+ self._print_error(str(e))
662
+ return self.EXIT_GENERAL_ERROR
663
+
664
+ return self.EXIT_SUCCESS
665
+
666
+ def _create_a2u_app(self, config: Dict[str, Any]) -> Any:
667
+ """Create FastAPI app for A2U server."""
668
+ from fastapi import FastAPI
669
+
670
+ from praisonai.endpoints.discovery import (
671
+ create_discovery_document,
672
+ EndpointInfo,
673
+ ProviderInfo,
674
+ )
675
+ from praisonai.endpoints.server import add_discovery_routes
676
+ from praisonai.endpoints.a2u_server import create_a2u_routes
677
+
678
+ discovery = create_discovery_document(server_name="praisonai-a2u")
679
+ discovery.add_provider(ProviderInfo(
680
+ type="a2u",
681
+ name="A2U Event Stream",
682
+ description="Agent-to-User event streaming",
683
+ capabilities=["subscribe", "stream"],
684
+ ))
685
+
686
+ app = FastAPI(
687
+ title="PraisonAI A2U Server",
688
+ description="A2U event stream server",
689
+ )
690
+
691
+ add_discovery_routes(app, discovery)
692
+ create_a2u_routes(app)
693
+
694
+ discovery.add_endpoint(EndpointInfo(
695
+ name="events",
696
+ description="Agent event stream",
697
+ provider_type="a2u",
698
+ streaming=["sse"],
699
+ ))
700
+
701
+ @app.get("/")
702
+ async def root():
703
+ return {
704
+ "message": "PraisonAI A2U Server",
705
+ "events": "/a2u/events/<stream>",
706
+ "discovery": "/__praisonai__/discovery",
707
+ }
708
+
709
+ return app
710
+
711
+ def cmd_unified(self, args: List[str]) -> int:
712
+ """Launch unified server with all providers."""
713
+ spec = {
714
+ "host": {"default": self.DEFAULT_HOST},
715
+ "port": {"default": self.DEFAULT_PORT, "type": "int"},
716
+ "file": {"default": "agents.yaml"},
717
+ "reload": {"flag": True, "default": False},
718
+ "api_key": {"default": None},
719
+ }
720
+ parsed = self._parse_args(args, spec)
721
+
722
+ try:
723
+ self._print_success(f"Starting unified server on {parsed['host']}:{parsed['port']}")
724
+ print(" Providers: agents-api, recipe, mcp, a2a, a2u")
725
+ print(" Discovery: /__praisonai__/discovery")
726
+
727
+ app = self._create_unified_app(parsed)
728
+ self._run_server(app, parsed["host"], parsed["port"], parsed["reload"])
729
+
730
+ except ImportError as e:
731
+ self._print_error(f"Missing dependency: {e}")
732
+ print("Install with: pip install praisonai[serve]")
733
+ return self.EXIT_GENERAL_ERROR
734
+ except Exception as e:
735
+ self._print_error(str(e))
736
+ return self.EXIT_GENERAL_ERROR
737
+
738
+ return self.EXIT_SUCCESS
739
+
740
+ def _create_unified_app(self, config: Dict[str, Any]) -> Any:
741
+ """Create unified FastAPI app with all providers."""
742
+ from fastapi import FastAPI
743
+
744
+ from praisonai.endpoints.discovery import (
745
+ create_discovery_document,
746
+ EndpointInfo,
747
+ ProviderInfo,
748
+ )
749
+ from praisonai.endpoints.server import add_discovery_routes
750
+ from praisonai.endpoints.a2u_server import create_a2u_routes
751
+
752
+ discovery = create_discovery_document(server_name="praisonai-unified")
753
+
754
+ # Add all providers
755
+ discovery.add_provider(ProviderInfo(
756
+ type="agents-api",
757
+ name="Agents API",
758
+ capabilities=["invoke", "health"],
759
+ ))
760
+ discovery.add_provider(ProviderInfo(
761
+ type="recipe",
762
+ name="Recipe Runner",
763
+ capabilities=["list", "describe", "invoke", "stream"],
764
+ ))
765
+ discovery.add_provider(ProviderInfo(
766
+ type="mcp",
767
+ name="MCP Server",
768
+ capabilities=["list-tools", "call-tool"],
769
+ ))
770
+ discovery.add_provider(ProviderInfo(
771
+ type="a2a",
772
+ name="A2A Protocol",
773
+ capabilities=["agent-card", "message-send"],
774
+ ))
775
+ discovery.add_provider(ProviderInfo(
776
+ type="a2u",
777
+ name="A2U Event Stream",
778
+ capabilities=["subscribe", "stream"],
779
+ ))
780
+
781
+ app = FastAPI(
782
+ title="PraisonAI Unified Server",
783
+ description="Unified server with all PraisonAI providers",
784
+ )
785
+
786
+ add_discovery_routes(app, discovery)
787
+ create_a2u_routes(app)
788
+
789
+ # Add sample endpoints
790
+ discovery.add_endpoint(EndpointInfo(
791
+ name="agents",
792
+ description="Agents workflow endpoint",
793
+ provider_type="agents-api",
794
+ ))
795
+ discovery.add_endpoint(EndpointInfo(
796
+ name="events",
797
+ description="Agent event stream",
798
+ provider_type="a2u",
799
+ streaming=["sse"],
800
+ ))
801
+
802
+ @app.get("/")
803
+ async def root():
804
+ return {
805
+ "message": "PraisonAI Unified Server",
806
+ "providers": ["agents-api", "recipe", "mcp", "a2a", "a2u"],
807
+ "discovery": "/__praisonai__/discovery",
808
+ }
809
+
810
+ @app.get("/.well-known/agent.json")
811
+ async def agent_card():
812
+ return {
813
+ "name": "PraisonAI Unified",
814
+ "description": "PraisonAI Unified Server",
815
+ "version": "1.0.0",
816
+ }
817
+
818
+ return app
819
+
820
+ def _run_server(self, app: Any, host: str, port: int, reload: bool) -> None:
821
+ """Run the server with uvicorn."""
822
+ import uvicorn
823
+ uvicorn.run(app, host=host, port=port, reload=reload)
824
+
825
+
826
+ def handle_serve_command(args: List[str]) -> int:
827
+ """Entry point for serve command."""
828
+ handler = ServeHandler()
829
+ return handler.handle(args)