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,165 @@
1
+ """
2
+ Unified Discovery Schema
3
+
4
+ Provides versioned discovery document format for all PraisonAI serve features.
5
+ This schema is consistent across all provider types.
6
+ """
7
+
8
+ from dataclasses import dataclass, field, asdict
9
+ from typing import Any, Dict, List, Optional
10
+ from enum import Enum
11
+
12
+
13
+ # Schema version - increment on breaking changes
14
+ SCHEMA_VERSION = "1.0.0"
15
+
16
+
17
+ class ProviderType(str, Enum):
18
+ """Supported provider types."""
19
+ RECIPE = "recipe"
20
+ AGENTS_API = "agents-api"
21
+ MCP = "mcp"
22
+ TOOLS_MCP = "tools-mcp"
23
+ A2A = "a2a"
24
+ A2U = "a2u"
25
+
26
+
27
+ class StreamingMode(str, Enum):
28
+ """Supported streaming modes."""
29
+ NONE = "none"
30
+ SSE = "sse"
31
+ WEBSOCKET = "websocket"
32
+ MCP_STREAM = "mcp-stream"
33
+
34
+
35
+ class AuthMode(str, Enum):
36
+ """Supported authentication modes."""
37
+ NONE = "none"
38
+ API_KEY = "api-key"
39
+ BEARER = "bearer"
40
+ JWT = "jwt"
41
+
42
+
43
+ @dataclass
44
+ class EndpointInfo:
45
+ """Information about a single endpoint."""
46
+ name: str
47
+ description: str = ""
48
+ provider_type: str = "recipe"
49
+ tags: List[str] = field(default_factory=list)
50
+ version: str = "1.0.0"
51
+
52
+ # Schema information
53
+ input_schema: Optional[Dict[str, Any]] = None
54
+ output_schema: Optional[Dict[str, Any]] = None
55
+
56
+ # Capabilities
57
+ streaming: List[str] = field(default_factory=lambda: ["none"])
58
+ auth_modes: List[str] = field(default_factory=lambda: ["none"])
59
+
60
+ # Metadata
61
+ examples: List[Dict[str, Any]] = field(default_factory=list)
62
+ metadata: Dict[str, Any] = field(default_factory=dict)
63
+
64
+ def to_dict(self) -> Dict[str, Any]:
65
+ """Convert to dictionary."""
66
+ return asdict(self)
67
+
68
+
69
+ @dataclass
70
+ class ProviderInfo:
71
+ """Information about a provider."""
72
+ type: str
73
+ name: str
74
+ version: str = "1.0.0"
75
+ description: str = ""
76
+ capabilities: List[str] = field(default_factory=list)
77
+
78
+ def to_dict(self) -> Dict[str, Any]:
79
+ """Convert to dictionary."""
80
+ return asdict(self)
81
+
82
+
83
+ @dataclass
84
+ class DiscoveryDocument:
85
+ """
86
+ Unified discovery document for PraisonAI servers.
87
+
88
+ This document is served at /__praisonai__/discovery and provides
89
+ a consistent interface for discovering endpoints across all provider types.
90
+ """
91
+ schema_version: str = SCHEMA_VERSION
92
+ server_name: str = "praisonai"
93
+ server_version: str = "1.0.0"
94
+
95
+ # Provider information
96
+ providers: List[ProviderInfo] = field(default_factory=list)
97
+
98
+ # Endpoint information
99
+ endpoints: List[EndpointInfo] = field(default_factory=list)
100
+
101
+ # Server capabilities
102
+ auth_modes: List[str] = field(default_factory=lambda: ["none"])
103
+ streaming_modes: List[str] = field(default_factory=lambda: ["none", "sse"])
104
+
105
+ # Metadata
106
+ metadata: Dict[str, Any] = field(default_factory=dict)
107
+
108
+ def to_dict(self) -> Dict[str, Any]:
109
+ """Convert to dictionary for JSON serialization."""
110
+ return {
111
+ "schema_version": self.schema_version,
112
+ "server_name": self.server_name,
113
+ "server_version": self.server_version,
114
+ "providers": [p.to_dict() for p in self.providers],
115
+ "endpoints": [e.to_dict() for e in self.endpoints],
116
+ "auth_modes": self.auth_modes,
117
+ "streaming_modes": self.streaming_modes,
118
+ "metadata": self.metadata,
119
+ }
120
+
121
+ def add_provider(self, provider: ProviderInfo) -> None:
122
+ """Add a provider to the discovery document."""
123
+ self.providers.append(provider)
124
+
125
+ def add_endpoint(self, endpoint: EndpointInfo) -> None:
126
+ """Add an endpoint to the discovery document."""
127
+ self.endpoints.append(endpoint)
128
+
129
+ def get_endpoints_by_type(self, provider_type: str) -> List[EndpointInfo]:
130
+ """Get endpoints filtered by provider type."""
131
+ return [e for e in self.endpoints if e.provider_type == provider_type]
132
+
133
+ def get_endpoint_by_name(self, name: str) -> Optional[EndpointInfo]:
134
+ """Get an endpoint by name."""
135
+ for e in self.endpoints:
136
+ if e.name == name:
137
+ return e
138
+ return None
139
+
140
+
141
+ def create_discovery_document(
142
+ server_name: str = "praisonai",
143
+ server_version: Optional[str] = None,
144
+ ) -> DiscoveryDocument:
145
+ """
146
+ Create a new discovery document.
147
+
148
+ Args:
149
+ server_name: Name of the server
150
+ server_version: Version of the server (auto-detected if not provided)
151
+
152
+ Returns:
153
+ DiscoveryDocument instance
154
+ """
155
+ if server_version is None:
156
+ try:
157
+ from praisonai.version import __version__
158
+ server_version = __version__
159
+ except ImportError:
160
+ server_version = "unknown"
161
+
162
+ return DiscoveryDocument(
163
+ server_name=server_name,
164
+ server_version=server_version,
165
+ )
@@ -0,0 +1,28 @@
1
+ """
2
+ Provider Adapters
3
+
4
+ Each provider adapter implements the BaseProvider interface
5
+ and handles protocol-specific details for discovery and invocation.
6
+ """
7
+
8
+ # Lazy loading for all exports
9
+ _lazy_imports = {
10
+ "BaseProvider": ".base",
11
+ "RecipeProvider": ".recipe",
12
+ "AgentsAPIProvider": ".agents_api",
13
+ "MCPProvider": ".mcp",
14
+ "ToolsMCPProvider": ".tools_mcp",
15
+ "A2AProvider": ".a2a",
16
+ "A2UProvider": ".a2u",
17
+ }
18
+
19
+ def __getattr__(name: str):
20
+ if name in _lazy_imports:
21
+ module_path = _lazy_imports[name]
22
+ import importlib
23
+ module = importlib.import_module(module_path, package=__name__)
24
+ return getattr(module, name)
25
+ raise AttributeError(f"module {__name__!r} has no attribute {name!r}")
26
+
27
+ def __dir__():
28
+ return list(_lazy_imports.keys())
@@ -0,0 +1,253 @@
1
+ """
2
+ A2A Provider
3
+
4
+ Provider adapter for Agent-to-Agent protocol endpoints.
5
+ """
6
+
7
+ from typing import Any, Dict, Iterator, List, Optional
8
+
9
+ from .base import BaseProvider, InvokeResult, HealthResult
10
+ from ..discovery import EndpointInfo, ProviderInfo
11
+
12
+
13
+ class A2AProvider(BaseProvider):
14
+ """
15
+ Provider adapter for A2A (Agent-to-Agent) protocol endpoints.
16
+
17
+ A2A enables agent-to-agent communication following the A2A protocol spec.
18
+ Supports discovery via /.well-known/agent.json and message passing.
19
+ """
20
+
21
+ provider_type = "a2a"
22
+
23
+ def get_provider_info(self) -> ProviderInfo:
24
+ """Get provider information."""
25
+ return ProviderInfo(
26
+ type=self.provider_type,
27
+ name="A2A Protocol",
28
+ description="Agent-to-Agent communication protocol",
29
+ capabilities=["agent-card", "message-send", "task-management"],
30
+ )
31
+
32
+ def list_endpoints(self, tags: Optional[List[str]] = None) -> List[EndpointInfo]:
33
+ """List available A2A agents."""
34
+ # Try unified discovery first
35
+ result = self._make_request("GET", "/__praisonai__/discovery")
36
+
37
+ if not result.get("error") and result.get("data"):
38
+ data = result.get("data", {})
39
+ endpoints = []
40
+ for ep in data.get("endpoints", []):
41
+ if ep.get("provider_type") == self.provider_type:
42
+ endpoints.append(EndpointInfo(
43
+ name=ep.get("name", ""),
44
+ description=ep.get("description", ""),
45
+ provider_type=self.provider_type,
46
+ tags=ep.get("tags", []),
47
+ streaming=ep.get("streaming", ["sse"]),
48
+ auth_modes=ep.get("auth_modes", ["none"]),
49
+ ))
50
+ return endpoints
51
+
52
+ # Fallback: try agent card
53
+ result = self._make_request("GET", "/.well-known/agent.json")
54
+
55
+ if result.get("error"):
56
+ return []
57
+
58
+ agent_card = result.get("data", {})
59
+
60
+ return [EndpointInfo(
61
+ name=agent_card.get("name", "a2a-agent"),
62
+ description=agent_card.get("description", "A2A Agent"),
63
+ provider_type=self.provider_type,
64
+ version=agent_card.get("version", "1.0.0"),
65
+ streaming=["sse"] if agent_card.get("capabilities", {}).get("streaming") else ["none"],
66
+ auth_modes=["none"],
67
+ metadata={"agent_card": agent_card},
68
+ )]
69
+
70
+ def describe_endpoint(self, name: str) -> Optional[EndpointInfo]:
71
+ """Get detailed information about an A2A agent."""
72
+ # Get agent card
73
+ result = self._make_request("GET", "/.well-known/agent.json")
74
+
75
+ if result.get("error"):
76
+ return None
77
+
78
+ agent_card = result.get("data", {})
79
+
80
+ return EndpointInfo(
81
+ name=agent_card.get("name", name),
82
+ description=agent_card.get("description", ""),
83
+ provider_type=self.provider_type,
84
+ version=agent_card.get("version", "1.0.0"),
85
+ streaming=["sse"] if agent_card.get("capabilities", {}).get("streaming") else ["none"],
86
+ auth_modes=["none"],
87
+ metadata={
88
+ "agent_card": agent_card,
89
+ "skills": agent_card.get("skills", []),
90
+ "capabilities": agent_card.get("capabilities", {}),
91
+ },
92
+ )
93
+
94
+ def invoke(
95
+ self,
96
+ name: str,
97
+ input_data: Optional[Dict[str, Any]] = None,
98
+ config: Optional[Dict[str, Any]] = None,
99
+ stream: bool = False,
100
+ ) -> InvokeResult:
101
+ """Send a message to an A2A agent."""
102
+ import uuid
103
+
104
+ # Build A2A message
105
+ message = input_data.get("message", "") if input_data else ""
106
+ if not message and config:
107
+ message = config.get("message", config.get("query", ""))
108
+
109
+ body = {
110
+ "jsonrpc": "2.0",
111
+ "method": "message/send",
112
+ "id": str(uuid.uuid4()),
113
+ "params": {
114
+ "message": {
115
+ "role": "user",
116
+ "parts": [{"type": "text", "text": message}],
117
+ },
118
+ },
119
+ }
120
+
121
+ result = self._make_request("POST", "/a2a", json_data=body)
122
+
123
+ if result.get("error"):
124
+ return InvokeResult(
125
+ ok=False,
126
+ status="error",
127
+ error=result["error"].get("message", str(result["error"])),
128
+ )
129
+
130
+ data = result.get("data", {})
131
+
132
+ # Handle JSON-RPC response
133
+ if "result" in data:
134
+ return InvokeResult(
135
+ ok=True,
136
+ status="success",
137
+ data=data["result"],
138
+ )
139
+ elif "error" in data:
140
+ return InvokeResult(
141
+ ok=False,
142
+ status="error",
143
+ error=data["error"].get("message", str(data["error"])),
144
+ )
145
+
146
+ return InvokeResult(
147
+ ok=True,
148
+ status="success",
149
+ data=data,
150
+ )
151
+
152
+ def invoke_stream(
153
+ self,
154
+ name: str,
155
+ input_data: Optional[Dict[str, Any]] = None,
156
+ config: Optional[Dict[str, Any]] = None,
157
+ ) -> Iterator[Dict[str, Any]]:
158
+ """Send a streaming message to an A2A agent."""
159
+ import json
160
+ import urllib.request
161
+ import uuid
162
+
163
+ message = input_data.get("message", "") if input_data else ""
164
+ if not message and config:
165
+ message = config.get("message", config.get("query", ""))
166
+
167
+ body = {
168
+ "jsonrpc": "2.0",
169
+ "method": "message/stream",
170
+ "id": str(uuid.uuid4()),
171
+ "params": {
172
+ "message": {
173
+ "role": "user",
174
+ "parts": [{"type": "text", "text": message}],
175
+ },
176
+ },
177
+ }
178
+
179
+ full_url = f"{self.base_url}/a2a"
180
+
181
+ headers = {
182
+ "Content-Type": "application/json",
183
+ "Accept": "text/event-stream",
184
+ }
185
+ if self.api_key:
186
+ headers["X-API-Key"] = self.api_key
187
+
188
+ data = json.dumps(body).encode("utf-8")
189
+
190
+ try:
191
+ req = urllib.request.Request(full_url, data=data, headers=headers, method="POST")
192
+
193
+ with urllib.request.urlopen(req, timeout=300) as response:
194
+ buffer = ""
195
+ for line in response:
196
+ line = line.decode("utf-8")
197
+ buffer += line
198
+
199
+ if buffer.endswith("\n\n"):
200
+ event_type = "message"
201
+ event_data = ""
202
+
203
+ for part in buffer.strip().split("\n"):
204
+ if part.startswith("event:"):
205
+ event_type = part[6:].strip()
206
+ elif part.startswith("data:"):
207
+ event_data = part[5:].strip()
208
+
209
+ if event_data:
210
+ try:
211
+ yield {"event": event_type, "data": json.loads(event_data)}
212
+ except json.JSONDecodeError:
213
+ yield {"event": event_type, "data": event_data}
214
+
215
+ buffer = ""
216
+
217
+ except Exception as e:
218
+ yield {"event": "error", "data": {"error": str(e)}}
219
+
220
+ def health(self) -> HealthResult:
221
+ """Check A2A server health."""
222
+ # Try status endpoint first
223
+ result = self._make_request("GET", "/status")
224
+
225
+ if not result.get("error"):
226
+ data = result.get("data", {})
227
+ return HealthResult(
228
+ healthy=data.get("status") == "ok",
229
+ status=data.get("status", "unknown"),
230
+ server_name=data.get("name", "A2A Agent"),
231
+ server_version=data.get("version"),
232
+ provider_type=self.provider_type,
233
+ )
234
+
235
+ # Fallback: try agent card
236
+ result = self._make_request("GET", "/.well-known/agent.json")
237
+
238
+ if result.get("error"):
239
+ return HealthResult(
240
+ healthy=False,
241
+ status="unhealthy",
242
+ provider_type=self.provider_type,
243
+ metadata={"error": result["error"].get("message", str(result["error"]))},
244
+ )
245
+
246
+ agent_card = result.get("data", {})
247
+ return HealthResult(
248
+ healthy=True,
249
+ status="healthy",
250
+ server_name=agent_card.get("name", "A2A Agent"),
251
+ server_version=agent_card.get("version"),
252
+ provider_type=self.provider_type,
253
+ )
@@ -0,0 +1,208 @@
1
+ """
2
+ A2U Provider
3
+
4
+ Provider adapter for Agent-to-User event stream endpoints.
5
+ """
6
+
7
+ from typing import Any, Dict, Iterator, List, Optional
8
+
9
+ from .base import BaseProvider, InvokeResult, HealthResult
10
+ from ..discovery import EndpointInfo, ProviderInfo
11
+
12
+
13
+ class A2UProvider(BaseProvider):
14
+ """
15
+ Provider adapter for A2U (Agent-to-User) event stream endpoints.
16
+
17
+ A2U provides a protocol surface for streaming agent events to users,
18
+ typically via SSE or WebSocket. This enables real-time UI updates.
19
+ """
20
+
21
+ provider_type = "a2u"
22
+
23
+ def get_provider_info(self) -> ProviderInfo:
24
+ """Get provider information."""
25
+ return ProviderInfo(
26
+ type=self.provider_type,
27
+ name="A2U Event Stream",
28
+ description="Agent-to-User event streaming protocol",
29
+ capabilities=["event-stream", "subscribe", "unsubscribe"],
30
+ )
31
+
32
+ def list_endpoints(self, tags: Optional[List[str]] = None) -> List[EndpointInfo]:
33
+ """List available A2U event streams."""
34
+ # Try unified discovery first
35
+ result = self._make_request("GET", "/__praisonai__/discovery")
36
+
37
+ if not result.get("error") and result.get("data"):
38
+ data = result.get("data", {})
39
+ endpoints = []
40
+ for ep in data.get("endpoints", []):
41
+ if ep.get("provider_type") == self.provider_type:
42
+ endpoints.append(EndpointInfo(
43
+ name=ep.get("name", ""),
44
+ description=ep.get("description", ""),
45
+ provider_type=self.provider_type,
46
+ tags=ep.get("tags", []),
47
+ streaming=ep.get("streaming", ["sse"]),
48
+ auth_modes=ep.get("auth_modes", ["none"]),
49
+ ))
50
+ return endpoints
51
+
52
+ # Fallback: check for events endpoint
53
+ result = self._make_request("GET", "/a2u/info")
54
+
55
+ if result.get("error"):
56
+ # Return default event stream endpoint
57
+ return [EndpointInfo(
58
+ name="events",
59
+ description="Agent event stream",
60
+ provider_type=self.provider_type,
61
+ streaming=["sse"],
62
+ auth_modes=["none"],
63
+ )]
64
+
65
+ data = result.get("data", {})
66
+ streams = data.get("streams", [{"name": "events", "description": "Agent event stream"}])
67
+
68
+ endpoints = []
69
+ for stream in streams:
70
+ endpoints.append(EndpointInfo(
71
+ name=stream.get("name", "events"),
72
+ description=stream.get("description", "Event stream"),
73
+ provider_type=self.provider_type,
74
+ streaming=["sse", "websocket"],
75
+ auth_modes=["none"],
76
+ ))
77
+
78
+ return endpoints
79
+
80
+ def describe_endpoint(self, name: str) -> Optional[EndpointInfo]:
81
+ """Get detailed information about an A2U event stream."""
82
+ endpoints = self.list_endpoints()
83
+ for ep in endpoints:
84
+ if ep.name == name:
85
+ return ep
86
+
87
+ # Return default info
88
+ return EndpointInfo(
89
+ name=name,
90
+ description=f"Event stream: {name}",
91
+ provider_type=self.provider_type,
92
+ streaming=["sse"],
93
+ auth_modes=["none"],
94
+ metadata={
95
+ "event_types": [
96
+ "agent.started",
97
+ "agent.thinking",
98
+ "agent.tool_call",
99
+ "agent.response",
100
+ "agent.completed",
101
+ "agent.error",
102
+ ],
103
+ },
104
+ )
105
+
106
+ def invoke(
107
+ self,
108
+ name: str,
109
+ input_data: Optional[Dict[str, Any]] = None,
110
+ config: Optional[Dict[str, Any]] = None,
111
+ stream: bool = False,
112
+ ) -> InvokeResult:
113
+ """Subscribe to an A2U event stream (returns subscription info)."""
114
+ body = {
115
+ "stream": name,
116
+ "filters": input_data.get("filters", []) if input_data else [],
117
+ }
118
+
119
+ result = self._make_request("POST", "/a2u/subscribe", json_data=body)
120
+
121
+ if result.get("error"):
122
+ return InvokeResult(
123
+ ok=False,
124
+ status="error",
125
+ error=result["error"].get("message", str(result["error"])),
126
+ )
127
+
128
+ data = result.get("data", {})
129
+ return InvokeResult(
130
+ ok=True,
131
+ status="subscribed",
132
+ data={
133
+ "subscription_id": data.get("subscription_id"),
134
+ "stream_url": data.get("stream_url", f"{self.base_url}/a2u/events/{name}"),
135
+ },
136
+ )
137
+
138
+ def invoke_stream(
139
+ self,
140
+ name: str,
141
+ input_data: Optional[Dict[str, Any]] = None,
142
+ config: Optional[Dict[str, Any]] = None,
143
+ ) -> Iterator[Dict[str, Any]]:
144
+ """Stream events from an A2U endpoint."""
145
+ import json
146
+ import urllib.request
147
+
148
+ stream_path = f"/a2u/events/{name}"
149
+ full_url = f"{self.base_url}{stream_path}"
150
+
151
+ headers = {"Accept": "text/event-stream"}
152
+ if self.api_key:
153
+ headers["X-API-Key"] = self.api_key
154
+
155
+ try:
156
+ req = urllib.request.Request(full_url, headers=headers, method="GET")
157
+
158
+ with urllib.request.urlopen(req, timeout=300) as response:
159
+ buffer = ""
160
+ for line in response:
161
+ line = line.decode("utf-8")
162
+ buffer += line
163
+
164
+ if buffer.endswith("\n\n"):
165
+ event_type = "event"
166
+ event_data = ""
167
+
168
+ for part in buffer.strip().split("\n"):
169
+ if part.startswith("event:"):
170
+ event_type = part[6:].strip()
171
+ elif part.startswith("data:"):
172
+ event_data = part[5:].strip()
173
+
174
+ if event_data:
175
+ try:
176
+ yield {"event": event_type, "data": json.loads(event_data)}
177
+ except json.JSONDecodeError:
178
+ yield {"event": event_type, "data": event_data}
179
+
180
+ buffer = ""
181
+
182
+ except Exception as e:
183
+ yield {"event": "error", "data": {"error": str(e)}}
184
+
185
+ def health(self) -> HealthResult:
186
+ """Check A2U server health."""
187
+ result = self._make_request("GET", "/health")
188
+
189
+ if result.get("error"):
190
+ # Try a2u-specific health
191
+ result = self._make_request("GET", "/a2u/health")
192
+
193
+ if result.get("error"):
194
+ return HealthResult(
195
+ healthy=False,
196
+ status="unhealthy",
197
+ provider_type=self.provider_type,
198
+ metadata={"error": result["error"].get("message", str(result["error"]))},
199
+ )
200
+
201
+ data = result.get("data", {})
202
+ return HealthResult(
203
+ healthy=True,
204
+ status="healthy",
205
+ server_name=data.get("server_name", "A2U Server"),
206
+ server_version=data.get("version"),
207
+ provider_type=self.provider_type,
208
+ )