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,328 @@
1
+ """
2
+ Observability checks for the Doctor CLI module.
3
+
4
+ Validates observability provider configurations.
5
+ """
6
+
7
+ import os
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
+ # Observability providers and their required env vars
20
+ OBS_PROVIDERS = {
21
+ "langfuse": {
22
+ "env_vars": ["LANGFUSE_PUBLIC_KEY", "LANGFUSE_SECRET_KEY"],
23
+ "optional_vars": ["LANGFUSE_HOST"],
24
+ "package": "langfuse",
25
+ },
26
+ "langsmith": {
27
+ "env_vars": ["LANGSMITH_API_KEY"],
28
+ "optional_vars": ["LANGSMITH_PROJECT"],
29
+ "package": "langsmith",
30
+ },
31
+ "agentops": {
32
+ "env_vars": ["AGENTOPS_API_KEY"],
33
+ "optional_vars": [],
34
+ "package": "agentops",
35
+ },
36
+ "arize": {
37
+ "env_vars": ["ARIZE_API_KEY"],
38
+ "optional_vars": ["ARIZE_SPACE_KEY"],
39
+ "package": "arize",
40
+ },
41
+ "datadog": {
42
+ "env_vars": ["DATADOG_API_KEY"],
43
+ "optional_vars": ["DD_SITE"],
44
+ "package": "ddtrace",
45
+ },
46
+ "mlflow": {
47
+ "env_vars": [],
48
+ "optional_vars": ["MLFLOW_TRACKING_URI"],
49
+ "package": "mlflow",
50
+ },
51
+ "wandb": {
52
+ "env_vars": ["WANDB_API_KEY"],
53
+ "optional_vars": ["WANDB_PROJECT"],
54
+ "package": "wandb",
55
+ },
56
+ "braintrust": {
57
+ "env_vars": ["BRAINTRUST_API_KEY"],
58
+ "optional_vars": [],
59
+ "package": "braintrust",
60
+ },
61
+ }
62
+
63
+
64
+ @register_check(
65
+ id="obs_config",
66
+ title="Observability Configuration",
67
+ description="Check observability provider configuration",
68
+ category=CheckCategory.OBSERVABILITY,
69
+ severity=CheckSeverity.INFO,
70
+ )
71
+ def check_obs_config(config: DoctorConfig) -> CheckResult:
72
+ """Check observability provider configuration."""
73
+ configured = []
74
+
75
+ for provider, info in OBS_PROVIDERS.items():
76
+ env_vars = info["env_vars"]
77
+ if env_vars:
78
+ if all(os.environ.get(var) for var in env_vars):
79
+ configured.append(provider)
80
+ else:
81
+ # Check optional vars for providers without required vars
82
+ if any(os.environ.get(var) for var in info.get("optional_vars", [])):
83
+ configured.append(provider)
84
+
85
+ if configured:
86
+ return CheckResult(
87
+ id="obs_config",
88
+ title="Observability Configuration",
89
+ category=CheckCategory.OBSERVABILITY,
90
+ status=CheckStatus.PASS,
91
+ message=f"Configured provider(s): {', '.join(configured)}",
92
+ metadata={"providers": configured},
93
+ )
94
+ else:
95
+ return CheckResult(
96
+ id="obs_config",
97
+ title="Observability Configuration",
98
+ category=CheckCategory.OBSERVABILITY,
99
+ status=CheckStatus.SKIP,
100
+ message="No observability providers configured (optional)",
101
+ details="Set provider API keys to enable observability",
102
+ )
103
+
104
+
105
+ @register_check(
106
+ id="obs_langfuse",
107
+ title="Langfuse",
108
+ description="Check Langfuse observability provider",
109
+ category=CheckCategory.OBSERVABILITY,
110
+ severity=CheckSeverity.LOW,
111
+ )
112
+ def check_obs_langfuse(config: DoctorConfig) -> CheckResult:
113
+ """Check Langfuse observability provider."""
114
+ public_key = os.environ.get("LANGFUSE_PUBLIC_KEY")
115
+ secret_key = os.environ.get("LANGFUSE_SECRET_KEY")
116
+
117
+ if public_key and secret_key:
118
+ try:
119
+ import langfuse
120
+ version = getattr(langfuse, "__version__", "unknown")
121
+ return CheckResult(
122
+ id="obs_langfuse",
123
+ title="Langfuse",
124
+ category=CheckCategory.OBSERVABILITY,
125
+ status=CheckStatus.PASS,
126
+ message=f"Langfuse configured (SDK {version})",
127
+ )
128
+ except ImportError:
129
+ return CheckResult(
130
+ id="obs_langfuse",
131
+ title="Langfuse",
132
+ category=CheckCategory.OBSERVABILITY,
133
+ status=CheckStatus.WARN,
134
+ message="Langfuse keys set but SDK not installed",
135
+ remediation="Install with: pip install langfuse",
136
+ )
137
+ else:
138
+ return CheckResult(
139
+ id="obs_langfuse",
140
+ title="Langfuse",
141
+ category=CheckCategory.OBSERVABILITY,
142
+ status=CheckStatus.SKIP,
143
+ message="Langfuse not configured (optional)",
144
+ )
145
+
146
+
147
+ @register_check(
148
+ id="obs_langsmith",
149
+ title="LangSmith",
150
+ description="Check LangSmith observability provider",
151
+ category=CheckCategory.OBSERVABILITY,
152
+ severity=CheckSeverity.LOW,
153
+ )
154
+ def check_obs_langsmith(config: DoctorConfig) -> CheckResult:
155
+ """Check LangSmith observability provider."""
156
+ api_key = os.environ.get("LANGSMITH_API_KEY")
157
+
158
+ if api_key:
159
+ try:
160
+ import langsmith
161
+ version = getattr(langsmith, "__version__", "unknown")
162
+ return CheckResult(
163
+ id="obs_langsmith",
164
+ title="LangSmith",
165
+ category=CheckCategory.OBSERVABILITY,
166
+ status=CheckStatus.PASS,
167
+ message=f"LangSmith configured (SDK {version})",
168
+ )
169
+ except ImportError:
170
+ return CheckResult(
171
+ id="obs_langsmith",
172
+ title="LangSmith",
173
+ category=CheckCategory.OBSERVABILITY,
174
+ status=CheckStatus.WARN,
175
+ message="LangSmith key set but SDK not installed",
176
+ remediation="Install with: pip install langsmith",
177
+ )
178
+ else:
179
+ return CheckResult(
180
+ id="obs_langsmith",
181
+ title="LangSmith",
182
+ category=CheckCategory.OBSERVABILITY,
183
+ status=CheckStatus.SKIP,
184
+ message="LangSmith not configured (optional)",
185
+ )
186
+
187
+
188
+ @register_check(
189
+ id="obs_agentops",
190
+ title="AgentOps",
191
+ description="Check AgentOps observability provider",
192
+ category=CheckCategory.OBSERVABILITY,
193
+ severity=CheckSeverity.LOW,
194
+ )
195
+ def check_obs_agentops(config: DoctorConfig) -> CheckResult:
196
+ """Check AgentOps observability provider."""
197
+ api_key = os.environ.get("AGENTOPS_API_KEY")
198
+
199
+ if api_key:
200
+ try:
201
+ import agentops
202
+ version = getattr(agentops, "__version__", "unknown")
203
+ return CheckResult(
204
+ id="obs_agentops",
205
+ title="AgentOps",
206
+ category=CheckCategory.OBSERVABILITY,
207
+ status=CheckStatus.PASS,
208
+ message=f"AgentOps configured (SDK {version})",
209
+ )
210
+ except ImportError:
211
+ return CheckResult(
212
+ id="obs_agentops",
213
+ title="AgentOps",
214
+ category=CheckCategory.OBSERVABILITY,
215
+ status=CheckStatus.WARN,
216
+ message="AgentOps key set but SDK not installed",
217
+ remediation="Install with: pip install agentops",
218
+ )
219
+ else:
220
+ return CheckResult(
221
+ id="obs_agentops",
222
+ title="AgentOps",
223
+ category=CheckCategory.OBSERVABILITY,
224
+ status=CheckStatus.SKIP,
225
+ message="AgentOps not configured (optional)",
226
+ )
227
+
228
+
229
+ @register_check(
230
+ id="obs_praisonai_telemetry",
231
+ title="PraisonAI Telemetry",
232
+ description="Check PraisonAI built-in telemetry",
233
+ category=CheckCategory.OBSERVABILITY,
234
+ severity=CheckSeverity.INFO,
235
+ )
236
+ def check_obs_praisonai_telemetry(config: DoctorConfig) -> CheckResult:
237
+ """Check PraisonAI built-in telemetry."""
238
+ telemetry_enabled = os.environ.get("PRAISONAI_TELEMETRY_ENABLED", "").lower() in ("true", "1", "yes")
239
+
240
+ try:
241
+ from praisonaiagents.telemetry import get_telemetry
242
+
243
+ if telemetry_enabled:
244
+ return CheckResult(
245
+ id="obs_praisonai_telemetry",
246
+ title="PraisonAI Telemetry",
247
+ category=CheckCategory.OBSERVABILITY,
248
+ status=CheckStatus.PASS,
249
+ message="PraisonAI telemetry enabled",
250
+ )
251
+ else:
252
+ return CheckResult(
253
+ id="obs_praisonai_telemetry",
254
+ title="PraisonAI Telemetry",
255
+ category=CheckCategory.OBSERVABILITY,
256
+ status=CheckStatus.SKIP,
257
+ message="PraisonAI telemetry available but not enabled",
258
+ details="Set PRAISONAI_TELEMETRY_ENABLED=true to enable",
259
+ )
260
+ except ImportError:
261
+ return CheckResult(
262
+ id="obs_praisonai_telemetry",
263
+ title="PraisonAI Telemetry",
264
+ category=CheckCategory.OBSERVABILITY,
265
+ status=CheckStatus.SKIP,
266
+ message="PraisonAI telemetry module not available",
267
+ )
268
+
269
+
270
+ @register_check(
271
+ id="obs_connectivity",
272
+ title="Observability Connectivity",
273
+ description="Test connectivity to observability providers",
274
+ category=CheckCategory.OBSERVABILITY,
275
+ severity=CheckSeverity.LOW,
276
+ requires_deep=True,
277
+ )
278
+ def check_obs_connectivity(config: DoctorConfig) -> CheckResult:
279
+ """Test connectivity to observability providers (deep mode)."""
280
+ # Only test if a specific provider is requested or if we have configured providers
281
+ provider = config.provider
282
+
283
+ if provider == "langfuse":
284
+ public_key = os.environ.get("LANGFUSE_PUBLIC_KEY")
285
+ secret_key = os.environ.get("LANGFUSE_SECRET_KEY")
286
+
287
+ if not (public_key and secret_key):
288
+ return CheckResult(
289
+ id="obs_connectivity",
290
+ title="Observability Connectivity",
291
+ category=CheckCategory.OBSERVABILITY,
292
+ status=CheckStatus.SKIP,
293
+ message="Langfuse not configured",
294
+ )
295
+
296
+ try:
297
+ from langfuse import Langfuse
298
+ client = Langfuse(
299
+ public_key=public_key,
300
+ secret_key=secret_key,
301
+ )
302
+ # Try to authenticate
303
+ client.auth_check()
304
+ return CheckResult(
305
+ id="obs_connectivity",
306
+ title="Observability Connectivity",
307
+ category=CheckCategory.OBSERVABILITY,
308
+ status=CheckStatus.PASS,
309
+ message="Langfuse connectivity verified",
310
+ )
311
+ except Exception as e:
312
+ return CheckResult(
313
+ id="obs_connectivity",
314
+ title="Observability Connectivity",
315
+ category=CheckCategory.OBSERVABILITY,
316
+ status=CheckStatus.FAIL,
317
+ message=f"Langfuse connection failed: {type(e).__name__}",
318
+ details=str(e)[:200],
319
+ )
320
+
321
+ # Default: skip if no specific provider requested
322
+ return CheckResult(
323
+ id="obs_connectivity",
324
+ title="Observability Connectivity",
325
+ category=CheckCategory.OBSERVABILITY,
326
+ status=CheckStatus.SKIP,
327
+ message="Use --provider to test specific provider connectivity",
328
+ )
@@ -0,0 +1,235 @@
1
+ """
2
+ Performance checks for the Doctor CLI module.
3
+
4
+ Measures import times and identifies slow imports.
5
+ """
6
+
7
+ import sys
8
+ import time
9
+
10
+ from ..models import (
11
+ CheckCategory,
12
+ CheckResult,
13
+ CheckStatus,
14
+ CheckSeverity,
15
+ DoctorConfig,
16
+ )
17
+ from ..registry import register_check
18
+
19
+
20
+ def _measure_import_time(module_name: str) -> tuple:
21
+ """Measure import time for a module."""
22
+ # Remove from cache if present
23
+ modules_before = set(sys.modules.keys())
24
+
25
+ start = time.perf_counter()
26
+ try:
27
+ __import__(module_name)
28
+ elapsed = (time.perf_counter() - start) * 1000 # ms
29
+ return True, elapsed, None
30
+ except ImportError as e:
31
+ elapsed = (time.perf_counter() - start) * 1000
32
+ return False, elapsed, str(e)
33
+ finally:
34
+ # Clean up imported modules (optional, for accurate re-measurement)
35
+ pass
36
+
37
+
38
+ @register_check(
39
+ id="performance_praisonai_import",
40
+ title="PraisonAI Import Time",
41
+ description="Measure praisonai package import time",
42
+ category=CheckCategory.PERFORMANCE,
43
+ severity=CheckSeverity.INFO,
44
+ )
45
+ def check_performance_praisonai_import(config: DoctorConfig) -> CheckResult:
46
+ """Measure praisonai package import time."""
47
+ budget_ms = config.budget_ms or 2000 # 2 second default budget
48
+
49
+ # praisonai is already imported, measure a fresh import of a submodule
50
+ start = time.perf_counter()
51
+ try:
52
+ # Import version module (lightweight)
53
+ from praisonai import version
54
+ elapsed = (time.perf_counter() - start) * 1000
55
+
56
+ if elapsed > budget_ms:
57
+ return CheckResult(
58
+ id="performance_praisonai_import",
59
+ title="PraisonAI Import Time",
60
+ category=CheckCategory.PERFORMANCE,
61
+ status=CheckStatus.WARN,
62
+ message=f"Import time {elapsed:.0f}ms exceeds budget {budget_ms}ms",
63
+ remediation="Check for slow dependencies or disk I/O issues",
64
+ )
65
+ else:
66
+ return CheckResult(
67
+ id="performance_praisonai_import",
68
+ title="PraisonAI Import Time",
69
+ category=CheckCategory.PERFORMANCE,
70
+ status=CheckStatus.PASS,
71
+ message=f"Import time: {elapsed:.0f}ms (budget: {budget_ms}ms)",
72
+ metadata={"import_time_ms": elapsed, "budget_ms": budget_ms},
73
+ )
74
+ except ImportError as e:
75
+ return CheckResult(
76
+ id="performance_praisonai_import",
77
+ title="PraisonAI Import Time",
78
+ category=CheckCategory.PERFORMANCE,
79
+ status=CheckStatus.FAIL,
80
+ message=f"Import failed: {e}",
81
+ )
82
+
83
+
84
+ @register_check(
85
+ id="performance_praisonaiagents_import",
86
+ title="PraisonAI Agents Import Time",
87
+ description="Measure praisonaiagents package import time",
88
+ category=CheckCategory.PERFORMANCE,
89
+ severity=CheckSeverity.INFO,
90
+ )
91
+ def check_performance_praisonaiagents_import(config: DoctorConfig) -> CheckResult:
92
+ """Measure praisonaiagents package import time."""
93
+ budget_ms = config.budget_ms or 3000 # 3 second default budget
94
+
95
+ start = time.perf_counter()
96
+ try:
97
+ import praisonaiagents
98
+ elapsed = (time.perf_counter() - start) * 1000
99
+
100
+ if elapsed > budget_ms:
101
+ return CheckResult(
102
+ id="performance_praisonaiagents_import",
103
+ title="PraisonAI Agents Import Time",
104
+ category=CheckCategory.PERFORMANCE,
105
+ status=CheckStatus.WARN,
106
+ message=f"Import time {elapsed:.0f}ms exceeds budget {budget_ms}ms",
107
+ remediation="Check for slow dependencies",
108
+ )
109
+ else:
110
+ return CheckResult(
111
+ id="performance_praisonaiagents_import",
112
+ title="PraisonAI Agents Import Time",
113
+ category=CheckCategory.PERFORMANCE,
114
+ status=CheckStatus.PASS,
115
+ message=f"Import time: {elapsed:.0f}ms (budget: {budget_ms}ms)",
116
+ metadata={"import_time_ms": elapsed, "budget_ms": budget_ms},
117
+ )
118
+ except ImportError as e:
119
+ return CheckResult(
120
+ id="performance_praisonaiagents_import",
121
+ title="PraisonAI Agents Import Time",
122
+ category=CheckCategory.PERFORMANCE,
123
+ status=CheckStatus.FAIL,
124
+ message=f"Import failed: {e}",
125
+ )
126
+
127
+
128
+ @register_check(
129
+ id="performance_slow_imports",
130
+ title="Slow Import Detection",
131
+ description="Detect slow-loading optional dependencies",
132
+ category=CheckCategory.PERFORMANCE,
133
+ severity=CheckSeverity.INFO,
134
+ requires_deep=True,
135
+ )
136
+ def check_performance_slow_imports(config: DoctorConfig) -> CheckResult:
137
+ """Detect slow-loading optional dependencies."""
138
+ modules_to_check = [
139
+ "litellm",
140
+ "chromadb",
141
+ "langchain",
142
+ "torch",
143
+ "transformers",
144
+ "pandas",
145
+ "numpy",
146
+ ]
147
+
148
+ top_n = config.top_n or 5
149
+ budget_ms = config.budget_ms or 1000
150
+
151
+ import_times = []
152
+
153
+ for module in modules_to_check:
154
+ if module in sys.modules:
155
+ # Already imported, skip
156
+ continue
157
+
158
+ success, elapsed, error = _measure_import_time(module)
159
+ if success:
160
+ import_times.append((module, elapsed))
161
+
162
+ # Sort by time, descending
163
+ import_times.sort(key=lambda x: x[1], reverse=True)
164
+
165
+ slow_imports = [(m, t) for m, t in import_times if t > budget_ms]
166
+ top_imports = import_times[:top_n]
167
+
168
+ if slow_imports:
169
+ slow_str = ", ".join(f"{m}({t:.0f}ms)" for m, t in slow_imports[:3])
170
+ return CheckResult(
171
+ id="performance_slow_imports",
172
+ title="Slow Import Detection",
173
+ category=CheckCategory.PERFORMANCE,
174
+ status=CheckStatus.WARN,
175
+ message=f"{len(slow_imports)} slow import(s) detected",
176
+ details=f"Slow: {slow_str}",
177
+ metadata={"slow_imports": slow_imports, "top_imports": top_imports},
178
+ )
179
+ elif top_imports:
180
+ top_str = ", ".join(f"{m}({t:.0f}ms)" for m, t in top_imports[:3])
181
+ return CheckResult(
182
+ id="performance_slow_imports",
183
+ title="Slow Import Detection",
184
+ category=CheckCategory.PERFORMANCE,
185
+ status=CheckStatus.PASS,
186
+ message=f"No slow imports (top: {top_str})",
187
+ metadata={"top_imports": top_imports},
188
+ )
189
+ else:
190
+ return CheckResult(
191
+ id="performance_slow_imports",
192
+ title="Slow Import Detection",
193
+ category=CheckCategory.PERFORMANCE,
194
+ status=CheckStatus.SKIP,
195
+ message="No optional modules to measure",
196
+ )
197
+
198
+
199
+ @register_check(
200
+ id="performance_loaded_modules",
201
+ title="Loaded Modules Count",
202
+ description="Count currently loaded Python modules",
203
+ category=CheckCategory.PERFORMANCE,
204
+ severity=CheckSeverity.INFO,
205
+ )
206
+ def check_performance_loaded_modules(config: DoctorConfig) -> CheckResult:
207
+ """Count currently loaded Python modules."""
208
+ module_count = len(sys.modules)
209
+
210
+ # Categorize modules
211
+ stdlib_count = 0
212
+ third_party_count = 0
213
+ praison_count = 0
214
+
215
+ for name in sys.modules:
216
+ if name.startswith("praisonai"):
217
+ praison_count += 1
218
+ elif "site-packages" in str(getattr(sys.modules[name], "__file__", "")):
219
+ third_party_count += 1
220
+ else:
221
+ stdlib_count += 1
222
+
223
+ return CheckResult(
224
+ id="performance_loaded_modules",
225
+ title="Loaded Modules Count",
226
+ category=CheckCategory.PERFORMANCE,
227
+ status=CheckStatus.PASS,
228
+ message=f"{module_count} modules loaded (praison: {praison_count})",
229
+ metadata={
230
+ "total": module_count,
231
+ "praison": praison_count,
232
+ "third_party": third_party_count,
233
+ "stdlib": stdlib_count,
234
+ },
235
+ )