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,426 @@
1
+ """
2
+ Doctor checks for serve and endpoints functionality.
3
+
4
+ Checks for:
5
+ - Serve module availability
6
+ - Endpoints module availability
7
+ - Server connectivity
8
+ - Discovery endpoint
9
+ - Provider types
10
+ """
11
+
12
+ import os
13
+
14
+ from ..models import CheckResult, CheckStatus, CheckCategory, CheckSeverity, DoctorConfig
15
+ from ..registry import register_check
16
+
17
+
18
+ @register_check(
19
+ id="serve_module",
20
+ title="Serve Module",
21
+ description="Check if serve module is available",
22
+ category=CheckCategory.ENVIRONMENT,
23
+ severity=CheckSeverity.MEDIUM,
24
+ tags=["serve", "deploy"],
25
+ )
26
+ def check_serve_module(config: DoctorConfig) -> CheckResult:
27
+ """Check if serve module is available."""
28
+ try:
29
+ from praisonai.cli.features.serve import ServeHandler
30
+ ServeHandler() # Test instantiation
31
+ return CheckResult(
32
+ id="serve_module",
33
+ title="Serve Module",
34
+ category=CheckCategory.ENVIRONMENT,
35
+ status=CheckStatus.PASS,
36
+ message="Serve module available",
37
+ metadata={"handler": "ServeHandler"},
38
+ )
39
+ except ImportError as e:
40
+ return CheckResult(
41
+ id="serve_module",
42
+ title="Serve Module",
43
+ category=CheckCategory.ENVIRONMENT,
44
+ status=CheckStatus.WARN,
45
+ message=f"Serve module not available: {e}",
46
+ remediation="pip install praisonai[serve]",
47
+ )
48
+ except Exception as e:
49
+ return CheckResult(
50
+ id="serve_module",
51
+ title="Serve Module",
52
+ category=CheckCategory.ENVIRONMENT,
53
+ status=CheckStatus.ERROR,
54
+ message=f"Error checking serve module: {e}",
55
+ )
56
+
57
+
58
+ @register_check(
59
+ id="endpoints_module",
60
+ title="Endpoints Module",
61
+ description="Check if endpoints module is available",
62
+ category=CheckCategory.ENVIRONMENT,
63
+ severity=CheckSeverity.MEDIUM,
64
+ tags=["endpoints", "deploy"],
65
+ )
66
+ def check_endpoints_module(config: DoctorConfig) -> CheckResult:
67
+ """Check if endpoints module is available."""
68
+ try:
69
+ from praisonai.endpoints import (
70
+ DiscoveryDocument,
71
+ EndpointInfo,
72
+ ProviderInfo,
73
+ list_provider_types,
74
+ )
75
+ types = list_provider_types()
76
+ return CheckResult(
77
+ id="endpoints_module",
78
+ title="Endpoints Module",
79
+ category=CheckCategory.ENVIRONMENT,
80
+ status=CheckStatus.PASS,
81
+ message=f"Endpoints module available ({len(types)} provider types)",
82
+ metadata={"provider_types": types},
83
+ )
84
+ except ImportError as e:
85
+ return CheckResult(
86
+ id="endpoints_module",
87
+ title="Endpoints Module",
88
+ category=CheckCategory.ENVIRONMENT,
89
+ status=CheckStatus.WARN,
90
+ message=f"Endpoints module not available: {e}",
91
+ remediation="pip install praisonai[serve]",
92
+ )
93
+ except Exception as e:
94
+ return CheckResult(
95
+ id="endpoints_module",
96
+ title="Endpoints Module",
97
+ category=CheckCategory.ENVIRONMENT,
98
+ status=CheckStatus.ERROR,
99
+ message=f"Error checking endpoints module: {e}",
100
+ )
101
+
102
+
103
+ @register_check(
104
+ id="endpoints_cli",
105
+ title="Endpoints CLI",
106
+ description="Check if endpoints CLI handler is available",
107
+ category=CheckCategory.ENVIRONMENT,
108
+ severity=CheckSeverity.LOW,
109
+ tags=["endpoints", "cli"],
110
+ )
111
+ def check_endpoints_cli(config: DoctorConfig) -> CheckResult:
112
+ """Check if endpoints CLI handler is available."""
113
+ try:
114
+ from praisonai.cli.features.endpoints import EndpointsHandler
115
+ handler = EndpointsHandler()
116
+ return CheckResult(
117
+ id="endpoints_cli",
118
+ title="Endpoints CLI",
119
+ category=CheckCategory.ENVIRONMENT,
120
+ status=CheckStatus.PASS,
121
+ message="Endpoints CLI handler available",
122
+ metadata={"default_url": handler.DEFAULT_URL},
123
+ )
124
+ except ImportError as e:
125
+ return CheckResult(
126
+ id="endpoints_cli",
127
+ title="Endpoints CLI",
128
+ category=CheckCategory.ENVIRONMENT,
129
+ status=CheckStatus.WARN,
130
+ message=f"Endpoints CLI not available: {e}",
131
+ remediation="pip install praisonai",
132
+ )
133
+ except Exception as e:
134
+ return CheckResult(
135
+ id="endpoints_cli",
136
+ title="Endpoints CLI",
137
+ category=CheckCategory.ENVIRONMENT,
138
+ status=CheckStatus.ERROR,
139
+ message=f"Error checking endpoints CLI: {e}",
140
+ )
141
+
142
+
143
+ @register_check(
144
+ id="server_connectivity",
145
+ title="Server Connectivity",
146
+ description="Check if a PraisonAI server is reachable",
147
+ category=CheckCategory.NETWORK,
148
+ severity=CheckSeverity.LOW,
149
+ requires_deep=True,
150
+ tags=["serve", "network"],
151
+ )
152
+ def check_server_connectivity(config: DoctorConfig) -> CheckResult:
153
+ """Check if a PraisonAI server is reachable."""
154
+ import urllib.request
155
+ import urllib.error
156
+
157
+ url = os.environ.get("PRAISONAI_ENDPOINTS_URL", "http://localhost:8765")
158
+ health_url = f"{url}/health"
159
+
160
+ try:
161
+ req = urllib.request.Request(health_url, method="GET")
162
+ with urllib.request.urlopen(req, timeout=5) as resp:
163
+ if resp.status == 200:
164
+ return CheckResult(
165
+ id="server_connectivity",
166
+ title="Server Connectivity",
167
+ category=CheckCategory.NETWORK,
168
+ status=CheckStatus.PASS,
169
+ message=f"Server reachable at {url}",
170
+ metadata={"url": url, "status": resp.status},
171
+ )
172
+ else:
173
+ return CheckResult(
174
+ id="server_connectivity",
175
+ title="Server Connectivity",
176
+ category=CheckCategory.NETWORK,
177
+ status=CheckStatus.WARN,
178
+ message=f"Server returned status {resp.status}",
179
+ metadata={"url": url, "status": resp.status},
180
+ )
181
+ except urllib.error.URLError as e:
182
+ return CheckResult(
183
+ id="server_connectivity",
184
+ title="Server Connectivity",
185
+ category=CheckCategory.NETWORK,
186
+ status=CheckStatus.SKIP,
187
+ message=f"No server running at {url}",
188
+ details=str(e.reason),
189
+ remediation="Start a server: praisonai serve unified --port 8765",
190
+ )
191
+ except Exception as e:
192
+ return CheckResult(
193
+ id="server_connectivity",
194
+ title="Server Connectivity",
195
+ category=CheckCategory.NETWORK,
196
+ status=CheckStatus.ERROR,
197
+ message=f"Error checking server: {e}",
198
+ )
199
+
200
+
201
+ @register_check(
202
+ id="discovery_endpoint",
203
+ title="Discovery Endpoint",
204
+ description="Check if discovery endpoint is available",
205
+ category=CheckCategory.NETWORK,
206
+ severity=CheckSeverity.LOW,
207
+ requires_deep=True,
208
+ dependencies=["server_connectivity"],
209
+ tags=["serve", "discovery"],
210
+ )
211
+ def check_discovery_endpoint(config: DoctorConfig) -> CheckResult:
212
+ """Check if discovery endpoint is available."""
213
+ import urllib.request
214
+ import urllib.error
215
+ import json
216
+
217
+ url = os.environ.get("PRAISONAI_ENDPOINTS_URL", "http://localhost:8765")
218
+ discovery_url = f"{url}/__praisonai__/discovery"
219
+
220
+ try:
221
+ req = urllib.request.Request(discovery_url, method="GET")
222
+ with urllib.request.urlopen(req, timeout=5) as resp:
223
+ if resp.status == 200:
224
+ data = json.loads(resp.read().decode())
225
+ providers = data.get("providers", [])
226
+ endpoints = data.get("endpoints", [])
227
+ return CheckResult(
228
+ id="discovery_endpoint",
229
+ title="Discovery Endpoint",
230
+ category=CheckCategory.NETWORK,
231
+ status=CheckStatus.PASS,
232
+ message=f"Discovery available: {len(providers)} providers, {len(endpoints)} endpoints",
233
+ metadata={
234
+ "url": discovery_url,
235
+ "schema_version": data.get("schema_version"),
236
+ "server_name": data.get("server_name"),
237
+ "providers": [p.get("type") for p in providers],
238
+ },
239
+ )
240
+ else:
241
+ return CheckResult(
242
+ id="discovery_endpoint",
243
+ title="Discovery Endpoint",
244
+ category=CheckCategory.NETWORK,
245
+ status=CheckStatus.WARN,
246
+ message=f"Discovery returned status {resp.status}",
247
+ )
248
+ except urllib.error.URLError:
249
+ return CheckResult(
250
+ id="discovery_endpoint",
251
+ title="Discovery Endpoint",
252
+ category=CheckCategory.NETWORK,
253
+ status=CheckStatus.SKIP,
254
+ message="No server running (skipped)",
255
+ )
256
+ except Exception as e:
257
+ return CheckResult(
258
+ id="discovery_endpoint",
259
+ title="Discovery Endpoint",
260
+ category=CheckCategory.NETWORK,
261
+ status=CheckStatus.ERROR,
262
+ message=f"Error checking discovery: {e}",
263
+ )
264
+
265
+
266
+ @register_check(
267
+ id="a2u_module",
268
+ title="A2U Module",
269
+ description="Check if A2U server module is available",
270
+ category=CheckCategory.ENVIRONMENT,
271
+ severity=CheckSeverity.LOW,
272
+ tags=["serve", "a2u"],
273
+ )
274
+ def check_a2u_module(config: DoctorConfig) -> CheckResult:
275
+ """Check if A2U server module is available."""
276
+ try:
277
+ from praisonai.endpoints.a2u_server import (
278
+ A2UEvent,
279
+ A2USubscription,
280
+ A2UEventBus,
281
+ create_a2u_routes,
282
+ )
283
+ return CheckResult(
284
+ id="a2u_module",
285
+ title="A2U Module",
286
+ category=CheckCategory.ENVIRONMENT,
287
+ status=CheckStatus.PASS,
288
+ message="A2U server module available",
289
+ )
290
+ except ImportError as e:
291
+ return CheckResult(
292
+ id="a2u_module",
293
+ title="A2U Module",
294
+ category=CheckCategory.ENVIRONMENT,
295
+ status=CheckStatus.WARN,
296
+ message=f"A2U module not available: {e}",
297
+ remediation="pip install praisonai[serve]",
298
+ )
299
+ except Exception as e:
300
+ return CheckResult(
301
+ id="a2u_module",
302
+ title="A2U Module",
303
+ category=CheckCategory.ENVIRONMENT,
304
+ status=CheckStatus.ERROR,
305
+ message=f"Error checking A2U module: {e}",
306
+ )
307
+
308
+
309
+ @register_check(
310
+ id="provider_adapters",
311
+ title="Provider Adapters",
312
+ description="Check if all provider adapters are available",
313
+ category=CheckCategory.ENVIRONMENT,
314
+ severity=CheckSeverity.LOW,
315
+ tags=["serve", "providers"],
316
+ )
317
+ def check_provider_adapters(config: DoctorConfig) -> CheckResult:
318
+ """Check if all provider adapters are available."""
319
+ try:
320
+ from praisonai.endpoints.providers import (
321
+ BaseProvider,
322
+ RecipeProvider,
323
+ AgentsAPIProvider,
324
+ MCPProvider,
325
+ ToolsMCPProvider,
326
+ A2AProvider,
327
+ A2UProvider,
328
+ )
329
+ providers = [
330
+ "BaseProvider",
331
+ "RecipeProvider",
332
+ "AgentsAPIProvider",
333
+ "MCPProvider",
334
+ "ToolsMCPProvider",
335
+ "A2AProvider",
336
+ "A2UProvider",
337
+ ]
338
+ return CheckResult(
339
+ id="provider_adapters",
340
+ title="Provider Adapters",
341
+ category=CheckCategory.ENVIRONMENT,
342
+ status=CheckStatus.PASS,
343
+ message=f"All {len(providers)} provider adapters available",
344
+ metadata={"providers": providers},
345
+ )
346
+ except ImportError as e:
347
+ return CheckResult(
348
+ id="provider_adapters",
349
+ title="Provider Adapters",
350
+ category=CheckCategory.ENVIRONMENT,
351
+ status=CheckStatus.WARN,
352
+ message=f"Some provider adapters not available: {e}",
353
+ remediation="pip install praisonai[serve]",
354
+ )
355
+ except Exception as e:
356
+ return CheckResult(
357
+ id="provider_adapters",
358
+ title="Provider Adapters",
359
+ category=CheckCategory.ENVIRONMENT,
360
+ status=CheckStatus.ERROR,
361
+ message=f"Error checking provider adapters: {e}",
362
+ )
363
+
364
+
365
+ @register_check(
366
+ id="fastapi_available",
367
+ title="FastAPI Available",
368
+ description="Check if FastAPI is available for serving",
369
+ category=CheckCategory.ENVIRONMENT,
370
+ severity=CheckSeverity.MEDIUM,
371
+ tags=["serve", "dependencies"],
372
+ )
373
+ def check_fastapi_available(config: DoctorConfig) -> CheckResult:
374
+ """Check if FastAPI is available."""
375
+ try:
376
+ import fastapi
377
+ version = getattr(fastapi, "__version__", "unknown")
378
+ return CheckResult(
379
+ id="fastapi_available",
380
+ title="FastAPI Available",
381
+ category=CheckCategory.ENVIRONMENT,
382
+ status=CheckStatus.PASS,
383
+ message=f"FastAPI {version} available",
384
+ metadata={"version": version},
385
+ )
386
+ except ImportError:
387
+ return CheckResult(
388
+ id="fastapi_available",
389
+ title="FastAPI Available",
390
+ category=CheckCategory.ENVIRONMENT,
391
+ status=CheckStatus.WARN,
392
+ message="FastAPI not installed",
393
+ remediation="pip install fastapi uvicorn",
394
+ )
395
+
396
+
397
+ @register_check(
398
+ id="uvicorn_available",
399
+ title="Uvicorn Available",
400
+ description="Check if Uvicorn is available for serving",
401
+ category=CheckCategory.ENVIRONMENT,
402
+ severity=CheckSeverity.MEDIUM,
403
+ tags=["serve", "dependencies"],
404
+ )
405
+ def check_uvicorn_available(config: DoctorConfig) -> CheckResult:
406
+ """Check if Uvicorn is available."""
407
+ try:
408
+ import uvicorn
409
+ version = getattr(uvicorn, "__version__", "unknown")
410
+ return CheckResult(
411
+ id="uvicorn_available",
412
+ title="Uvicorn Available",
413
+ category=CheckCategory.ENVIRONMENT,
414
+ status=CheckStatus.PASS,
415
+ message=f"Uvicorn {version} available",
416
+ metadata={"version": version},
417
+ )
418
+ except ImportError:
419
+ return CheckResult(
420
+ id="uvicorn_available",
421
+ title="Uvicorn Available",
422
+ category=CheckCategory.ENVIRONMENT,
423
+ status=CheckStatus.WARN,
424
+ message="Uvicorn not installed",
425
+ remediation="pip install uvicorn",
426
+ )
@@ -0,0 +1,231 @@
1
+ """
2
+ Skills checks for the Doctor CLI module.
3
+
4
+ Validates Agent Skills configurations and manifests.
5
+ """
6
+
7
+ from pathlib import Path
8
+
9
+ from ..models import (
10
+ CheckCategory,
11
+ CheckResult,
12
+ CheckStatus,
13
+ CheckSeverity,
14
+ DoctorConfig,
15
+ )
16
+ from ..registry import register_check
17
+
18
+
19
+ def _find_skills_dirs() -> list:
20
+ """Find skills directories."""
21
+ locations = [
22
+ Path.cwd() / ".praison" / "skills",
23
+ Path.cwd() / ".claude" / "skills",
24
+ Path.home() / ".praison" / "skills",
25
+ Path.home() / ".config" / "praison" / "skills",
26
+ ]
27
+
28
+ found = []
29
+ for loc in locations:
30
+ if loc.exists() and loc.is_dir():
31
+ found.append(str(loc))
32
+
33
+ return found
34
+
35
+
36
+ def _validate_skill_dir(skill_path: Path) -> dict:
37
+ """Validate a single skill directory."""
38
+ result = {"valid": False, "errors": [], "warnings": []}
39
+
40
+ skill_md = skill_path / "SKILL.md"
41
+ if not skill_md.exists():
42
+ result["errors"].append("Missing SKILL.md")
43
+ return result
44
+
45
+ try:
46
+ content = skill_md.read_text()
47
+
48
+ # Check for YAML frontmatter
49
+ if not content.startswith("---"):
50
+ result["errors"].append("SKILL.md missing YAML frontmatter")
51
+ return result
52
+
53
+ # Parse frontmatter
54
+ parts = content.split("---", 2)
55
+ if len(parts) < 3:
56
+ result["errors"].append("Invalid YAML frontmatter format")
57
+ return result
58
+
59
+ try:
60
+ import yaml
61
+ frontmatter = yaml.safe_load(parts[1])
62
+
63
+ # Check required fields
64
+ if not frontmatter.get("name"):
65
+ result["errors"].append("Missing 'name' in frontmatter")
66
+ if not frontmatter.get("description"):
67
+ result["errors"].append("Missing 'description' in frontmatter")
68
+
69
+ # Check name format
70
+ name = frontmatter.get("name", "")
71
+ if name and not name.replace("-", "").replace("_", "").isalnum():
72
+ result["warnings"].append(f"Name '{name}' should be alphanumeric with hyphens")
73
+
74
+ if not result["errors"]:
75
+ result["valid"] = True
76
+ result["name"] = name
77
+ result["description"] = frontmatter.get("description", "")[:100]
78
+
79
+ except Exception as e:
80
+ result["errors"].append(f"YAML parse error: {e}")
81
+
82
+ except Exception as e:
83
+ result["errors"].append(f"Cannot read SKILL.md: {e}")
84
+
85
+ return result
86
+
87
+
88
+ @register_check(
89
+ id="skills_dirs",
90
+ title="Skills Directories",
91
+ description="Check for skills directories",
92
+ category=CheckCategory.SKILLS,
93
+ severity=CheckSeverity.INFO,
94
+ )
95
+ def check_skills_dirs(config: DoctorConfig) -> CheckResult:
96
+ """Check for skills directories."""
97
+ dirs = _find_skills_dirs()
98
+
99
+ if config.path:
100
+ # Check specific path
101
+ path = Path(config.path)
102
+ if path.exists():
103
+ dirs = [str(path)]
104
+ else:
105
+ return CheckResult(
106
+ id="skills_dirs",
107
+ title="Skills Directories",
108
+ category=CheckCategory.SKILLS,
109
+ status=CheckStatus.FAIL,
110
+ message=f"Specified path not found: {config.path}",
111
+ )
112
+
113
+ if dirs:
114
+ return CheckResult(
115
+ id="skills_dirs",
116
+ title="Skills Directories",
117
+ category=CheckCategory.SKILLS,
118
+ status=CheckStatus.PASS,
119
+ message=f"Found {len(dirs)} skills directory(ies)",
120
+ details=", ".join(dirs),
121
+ metadata={"directories": dirs},
122
+ )
123
+ else:
124
+ return CheckResult(
125
+ id="skills_dirs",
126
+ title="Skills Directories",
127
+ category=CheckCategory.SKILLS,
128
+ status=CheckStatus.SKIP,
129
+ message="No skills directories found (optional)",
130
+ details="Create .praison/skills/ to add agent skills",
131
+ )
132
+
133
+
134
+ @register_check(
135
+ id="skills_valid",
136
+ title="Skills Validation",
137
+ description="Validate installed skills",
138
+ category=CheckCategory.SKILLS,
139
+ severity=CheckSeverity.MEDIUM,
140
+ dependencies=["skills_dirs"],
141
+ )
142
+ def check_skills_valid(config: DoctorConfig) -> CheckResult:
143
+ """Validate installed skills."""
144
+ dirs = _find_skills_dirs()
145
+
146
+ if config.path:
147
+ path = Path(config.path)
148
+ if path.exists():
149
+ dirs = [str(path)]
150
+
151
+ if not dirs:
152
+ return CheckResult(
153
+ id="skills_valid",
154
+ title="Skills Validation",
155
+ category=CheckCategory.SKILLS,
156
+ status=CheckStatus.SKIP,
157
+ message="No skills to validate",
158
+ )
159
+
160
+ valid_skills = []
161
+ invalid_skills = []
162
+
163
+ for dir_path in dirs:
164
+ skills_dir = Path(dir_path)
165
+ for skill_path in skills_dir.iterdir():
166
+ if skill_path.is_dir() and not skill_path.name.startswith("."):
167
+ result = _validate_skill_dir(skill_path)
168
+ if result["valid"]:
169
+ valid_skills.append(result.get("name", skill_path.name))
170
+ else:
171
+ invalid_skills.append(f"{skill_path.name}: {'; '.join(result['errors'])}")
172
+
173
+ total = len(valid_skills) + len(invalid_skills)
174
+
175
+ if total == 0:
176
+ return CheckResult(
177
+ id="skills_valid",
178
+ title="Skills Validation",
179
+ category=CheckCategory.SKILLS,
180
+ status=CheckStatus.SKIP,
181
+ message="No skills found in directories",
182
+ )
183
+
184
+ if invalid_skills:
185
+ return CheckResult(
186
+ id="skills_valid",
187
+ title="Skills Validation",
188
+ category=CheckCategory.SKILLS,
189
+ status=CheckStatus.WARN,
190
+ message=f"{len(valid_skills)}/{total} skills valid",
191
+ details="; ".join(invalid_skills[:3]) + ("..." if len(invalid_skills) > 3 else ""),
192
+ metadata={"valid": valid_skills, "invalid": invalid_skills},
193
+ )
194
+ else:
195
+ return CheckResult(
196
+ id="skills_valid",
197
+ title="Skills Validation",
198
+ category=CheckCategory.SKILLS,
199
+ status=CheckStatus.PASS,
200
+ message=f"All {total} skill(s) valid",
201
+ metadata={"valid": valid_skills},
202
+ )
203
+
204
+
205
+ @register_check(
206
+ id="skills_praisonai_integration",
207
+ title="PraisonAI Skills Integration",
208
+ description="Check PraisonAI skills module",
209
+ category=CheckCategory.SKILLS,
210
+ severity=CheckSeverity.LOW,
211
+ )
212
+ def check_skills_praisonai_integration(config: DoctorConfig) -> CheckResult:
213
+ """Check PraisonAI skills module."""
214
+ try:
215
+ from praisonaiagents.skills import SkillManager
216
+ return CheckResult(
217
+ id="skills_praisonai_integration",
218
+ title="PraisonAI Skills Integration",
219
+ category=CheckCategory.SKILLS,
220
+ status=CheckStatus.PASS,
221
+ message="PraisonAI skills module available",
222
+ )
223
+ except ImportError as e:
224
+ return CheckResult(
225
+ id="skills_praisonai_integration",
226
+ title="PraisonAI Skills Integration",
227
+ category=CheckCategory.SKILLS,
228
+ status=CheckStatus.SKIP,
229
+ message="Skills module not available",
230
+ details=str(e),
231
+ )