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,268 @@
1
+ """
2
+ Memory checks for the Doctor CLI module.
3
+
4
+ Validates memory/session storage and integrity.
5
+ """
6
+
7
+ import os
8
+ from pathlib import Path
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 _find_memory_dirs() -> list:
21
+ """Find memory storage directories."""
22
+ locations = [
23
+ Path.cwd() / ".praison" / "memory",
24
+ Path.cwd() / ".praison" / "sessions",
25
+ Path.home() / ".praison" / "memory",
26
+ Path.home() / ".praison" / "sessions",
27
+ Path.home() / ".config" / "praison" / "memory",
28
+ ]
29
+
30
+ found = []
31
+ for loc in locations:
32
+ if loc.exists() and loc.is_dir():
33
+ found.append(str(loc))
34
+
35
+ return found
36
+
37
+
38
+ @register_check(
39
+ id="memory_dirs",
40
+ title="Memory Directories",
41
+ description="Check memory storage directories",
42
+ category=CheckCategory.MEMORY,
43
+ severity=CheckSeverity.INFO,
44
+ )
45
+ def check_memory_dirs(config: DoctorConfig) -> CheckResult:
46
+ """Check memory storage directories."""
47
+ dirs = _find_memory_dirs()
48
+
49
+ if dirs:
50
+ return CheckResult(
51
+ id="memory_dirs",
52
+ title="Memory Directories",
53
+ category=CheckCategory.MEMORY,
54
+ status=CheckStatus.PASS,
55
+ message=f"Found {len(dirs)} memory directory(ies)",
56
+ details=", ".join(dirs),
57
+ metadata={"directories": dirs},
58
+ )
59
+ else:
60
+ return CheckResult(
61
+ id="memory_dirs",
62
+ title="Memory Directories",
63
+ category=CheckCategory.MEMORY,
64
+ status=CheckStatus.SKIP,
65
+ message="No memory directories found (will be created on first use)",
66
+ )
67
+
68
+
69
+ @register_check(
70
+ id="memory_files",
71
+ title="Memory Files",
72
+ description="Check memory file integrity",
73
+ category=CheckCategory.MEMORY,
74
+ severity=CheckSeverity.MEDIUM,
75
+ dependencies=["memory_dirs"],
76
+ )
77
+ def check_memory_files(config: DoctorConfig) -> CheckResult:
78
+ """Check memory file integrity."""
79
+ dirs = _find_memory_dirs()
80
+
81
+ if not dirs:
82
+ return CheckResult(
83
+ id="memory_files",
84
+ title="Memory Files",
85
+ category=CheckCategory.MEMORY,
86
+ status=CheckStatus.SKIP,
87
+ message="No memory directories to check",
88
+ )
89
+
90
+ valid_files = 0
91
+ corrupt_files = []
92
+ total_size = 0
93
+
94
+ for dir_path in dirs:
95
+ memory_dir = Path(dir_path)
96
+ for file_path in memory_dir.rglob("*.json"):
97
+ try:
98
+ import json
99
+ with open(file_path) as f:
100
+ json.load(f)
101
+ valid_files += 1
102
+ total_size += file_path.stat().st_size
103
+ except json.JSONDecodeError:
104
+ corrupt_files.append(str(file_path))
105
+ except Exception:
106
+ pass
107
+
108
+ if corrupt_files:
109
+ return CheckResult(
110
+ id="memory_files",
111
+ title="Memory Files",
112
+ category=CheckCategory.MEMORY,
113
+ status=CheckStatus.WARN,
114
+ message=f"{len(corrupt_files)} corrupt file(s) found",
115
+ details="; ".join(corrupt_files[:3]) + ("..." if len(corrupt_files) > 3 else ""),
116
+ remediation="Remove or repair corrupt memory files",
117
+ metadata={"valid": valid_files, "corrupt": corrupt_files},
118
+ )
119
+ elif valid_files > 0:
120
+ size_kb = total_size / 1024
121
+ return CheckResult(
122
+ id="memory_files",
123
+ title="Memory Files",
124
+ category=CheckCategory.MEMORY,
125
+ status=CheckStatus.PASS,
126
+ message=f"{valid_files} valid memory file(s) ({size_kb:.1f} KB)",
127
+ metadata={"valid_count": valid_files, "total_size_bytes": total_size},
128
+ )
129
+ else:
130
+ return CheckResult(
131
+ id="memory_files",
132
+ title="Memory Files",
133
+ category=CheckCategory.MEMORY,
134
+ status=CheckStatus.SKIP,
135
+ message="No memory files found",
136
+ )
137
+
138
+
139
+ @register_check(
140
+ id="memory_sessions",
141
+ title="Session Storage",
142
+ description="Check session storage",
143
+ category=CheckCategory.MEMORY,
144
+ severity=CheckSeverity.INFO,
145
+ )
146
+ def check_memory_sessions(config: DoctorConfig) -> CheckResult:
147
+ """Check session storage."""
148
+ session_dirs = [
149
+ Path.cwd() / ".praison" / "sessions",
150
+ Path.home() / ".praison" / "sessions",
151
+ ]
152
+
153
+ sessions = []
154
+ for dir_path in session_dirs:
155
+ if dir_path.exists():
156
+ for item in dir_path.iterdir():
157
+ if item.is_dir() or item.suffix == ".json":
158
+ sessions.append(item.name)
159
+
160
+ if sessions:
161
+ return CheckResult(
162
+ id="memory_sessions",
163
+ title="Session Storage",
164
+ category=CheckCategory.MEMORY,
165
+ status=CheckStatus.PASS,
166
+ message=f"Found {len(sessions)} saved session(s)",
167
+ metadata={"sessions": sessions[:10]},
168
+ )
169
+ else:
170
+ return CheckResult(
171
+ id="memory_sessions",
172
+ title="Session Storage",
173
+ category=CheckCategory.MEMORY,
174
+ status=CheckStatus.SKIP,
175
+ message="No saved sessions found",
176
+ )
177
+
178
+
179
+ @register_check(
180
+ id="memory_chromadb",
181
+ title="ChromaDB Memory",
182
+ description="Check ChromaDB vector memory",
183
+ category=CheckCategory.MEMORY,
184
+ severity=CheckSeverity.LOW,
185
+ )
186
+ def check_memory_chromadb(config: DoctorConfig) -> CheckResult:
187
+ """Check ChromaDB vector memory."""
188
+ chroma_dirs = [
189
+ Path.cwd() / ".praison" / "chroma",
190
+ Path.cwd() / "chroma_db",
191
+ Path.home() / ".praison" / "chroma",
192
+ ]
193
+
194
+ found = None
195
+ for dir_path in chroma_dirs:
196
+ if dir_path.exists():
197
+ found = dir_path
198
+ break
199
+
200
+ if found:
201
+ try:
202
+ import chromadb
203
+ # Try to open the database
204
+ client = chromadb.PersistentClient(path=str(found))
205
+ collections = client.list_collections()
206
+ return CheckResult(
207
+ id="memory_chromadb",
208
+ title="ChromaDB Memory",
209
+ category=CheckCategory.MEMORY,
210
+ status=CheckStatus.PASS,
211
+ message=f"ChromaDB found with {len(collections)} collection(s)",
212
+ metadata={"path": str(found), "collections": len(collections)},
213
+ )
214
+ except ImportError:
215
+ return CheckResult(
216
+ id="memory_chromadb",
217
+ title="ChromaDB Memory",
218
+ category=CheckCategory.MEMORY,
219
+ status=CheckStatus.WARN,
220
+ message="ChromaDB directory found but chromadb not installed",
221
+ remediation="Install with: pip install chromadb",
222
+ )
223
+ except Exception as e:
224
+ return CheckResult(
225
+ id="memory_chromadb",
226
+ title="ChromaDB Memory",
227
+ category=CheckCategory.MEMORY,
228
+ status=CheckStatus.WARN,
229
+ message=f"ChromaDB found but cannot open: {type(e).__name__}",
230
+ details=str(e)[:200],
231
+ )
232
+ else:
233
+ return CheckResult(
234
+ id="memory_chromadb",
235
+ title="ChromaDB Memory",
236
+ category=CheckCategory.MEMORY,
237
+ status=CheckStatus.SKIP,
238
+ message="No ChromaDB storage found (optional)",
239
+ )
240
+
241
+
242
+ @register_check(
243
+ id="memory_praisonai_module",
244
+ title="PraisonAI Memory Module",
245
+ description="Check PraisonAI memory module",
246
+ category=CheckCategory.MEMORY,
247
+ severity=CheckSeverity.LOW,
248
+ )
249
+ def check_memory_praisonai_module(config: DoctorConfig) -> CheckResult:
250
+ """Check PraisonAI memory module."""
251
+ try:
252
+ from praisonaiagents.memory import FileMemory, Memory
253
+ return CheckResult(
254
+ id="memory_praisonai_module",
255
+ title="PraisonAI Memory Module",
256
+ category=CheckCategory.MEMORY,
257
+ status=CheckStatus.PASS,
258
+ message="Memory modules available (FileMemory, Memory)",
259
+ )
260
+ except ImportError as e:
261
+ return CheckResult(
262
+ id="memory_praisonai_module",
263
+ title="PraisonAI Memory Module",
264
+ category=CheckCategory.MEMORY,
265
+ status=CheckStatus.WARN,
266
+ message="Memory module import failed",
267
+ details=str(e),
268
+ )
@@ -0,0 +1,251 @@
1
+ """
2
+ Network checks for the Doctor CLI module.
3
+
4
+ Validates network connectivity and configuration.
5
+ """
6
+
7
+ import os
8
+ import socket
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
+ @register_check(
21
+ id="network_dns",
22
+ title="DNS Resolution",
23
+ description="Check DNS resolution",
24
+ category=CheckCategory.NETWORK,
25
+ severity=CheckSeverity.MEDIUM,
26
+ requires_deep=True,
27
+ )
28
+ def check_network_dns(config: DoctorConfig) -> CheckResult:
29
+ """Check DNS resolution."""
30
+ test_hosts = [
31
+ "api.openai.com",
32
+ "api.anthropic.com",
33
+ "google.com",
34
+ ]
35
+
36
+ resolved = []
37
+ failed = []
38
+
39
+ for host in test_hosts:
40
+ try:
41
+ socket.gethostbyname(host)
42
+ resolved.append(host)
43
+ except socket.gaierror:
44
+ failed.append(host)
45
+
46
+ if failed:
47
+ return CheckResult(
48
+ id="network_dns",
49
+ title="DNS Resolution",
50
+ category=CheckCategory.NETWORK,
51
+ status=CheckStatus.WARN,
52
+ message=f"DNS resolution failed for {len(failed)} host(s)",
53
+ details=f"Failed: {', '.join(failed)}",
54
+ remediation="Check DNS configuration and network connectivity",
55
+ )
56
+ else:
57
+ return CheckResult(
58
+ id="network_dns",
59
+ title="DNS Resolution",
60
+ category=CheckCategory.NETWORK,
61
+ status=CheckStatus.PASS,
62
+ message=f"DNS resolution working ({len(resolved)} hosts tested)",
63
+ )
64
+
65
+
66
+ @register_check(
67
+ id="network_https",
68
+ title="HTTPS Connectivity",
69
+ description="Check HTTPS connectivity to key endpoints",
70
+ category=CheckCategory.NETWORK,
71
+ severity=CheckSeverity.MEDIUM,
72
+ requires_deep=True,
73
+ )
74
+ def check_network_https(config: DoctorConfig) -> CheckResult:
75
+ """Check HTTPS connectivity to key endpoints."""
76
+ import urllib.request
77
+ import urllib.error
78
+
79
+ endpoints = [
80
+ ("https://api.openai.com/v1/models", "OpenAI"),
81
+ ("https://api.anthropic.com/v1/messages", "Anthropic"),
82
+ ]
83
+
84
+ reachable = []
85
+ unreachable = []
86
+
87
+ for url, name in endpoints:
88
+ try:
89
+ req = urllib.request.Request(url, method="HEAD")
90
+ req.add_header("User-Agent", "PraisonAI-Doctor/1.0")
91
+ urllib.request.urlopen(req, timeout=5)
92
+ reachable.append(name)
93
+ except urllib.error.HTTPError as e:
94
+ # HTTP errors (401, 403, etc.) mean we reached the server
95
+ if e.code in (401, 403, 404, 405):
96
+ reachable.append(name)
97
+ else:
98
+ unreachable.append(f"{name} ({e.code})")
99
+ except Exception as e:
100
+ unreachable.append(f"{name} ({type(e).__name__})")
101
+
102
+ if unreachable:
103
+ return CheckResult(
104
+ id="network_https",
105
+ title="HTTPS Connectivity",
106
+ category=CheckCategory.NETWORK,
107
+ status=CheckStatus.WARN,
108
+ message=f"Cannot reach {len(unreachable)} endpoint(s)",
109
+ details=f"Unreachable: {', '.join(unreachable)}",
110
+ remediation="Check network connectivity and firewall settings",
111
+ )
112
+ else:
113
+ return CheckResult(
114
+ id="network_https",
115
+ title="HTTPS Connectivity",
116
+ category=CheckCategory.NETWORK,
117
+ status=CheckStatus.PASS,
118
+ message=f"HTTPS connectivity verified ({len(reachable)} endpoints)",
119
+ )
120
+
121
+
122
+ @register_check(
123
+ id="network_proxy",
124
+ title="Proxy Configuration",
125
+ description="Check proxy environment variables",
126
+ category=CheckCategory.NETWORK,
127
+ severity=CheckSeverity.INFO,
128
+ )
129
+ def check_network_proxy(config: DoctorConfig) -> CheckResult:
130
+ """Check proxy environment variables."""
131
+ proxy_vars = {
132
+ "HTTP_PROXY": os.environ.get("HTTP_PROXY") or os.environ.get("http_proxy"),
133
+ "HTTPS_PROXY": os.environ.get("HTTPS_PROXY") or os.environ.get("https_proxy"),
134
+ "NO_PROXY": os.environ.get("NO_PROXY") or os.environ.get("no_proxy"),
135
+ }
136
+
137
+ configured = {k: v for k, v in proxy_vars.items() if v}
138
+
139
+ if configured:
140
+ # Mask proxy URLs that might contain credentials
141
+ masked = {}
142
+ for k, v in configured.items():
143
+ if "@" in v:
144
+ # Contains credentials, mask them
145
+ parts = v.split("@")
146
+ masked[k] = f"***@{parts[-1]}"
147
+ else:
148
+ masked[k] = v
149
+
150
+ return CheckResult(
151
+ id="network_proxy",
152
+ title="Proxy Configuration",
153
+ category=CheckCategory.NETWORK,
154
+ status=CheckStatus.PASS,
155
+ message=f"Proxy configured: {', '.join(configured.keys())}",
156
+ details="; ".join(f"{k}={v}" for k, v in masked.items()),
157
+ )
158
+ else:
159
+ return CheckResult(
160
+ id="network_proxy",
161
+ title="Proxy Configuration",
162
+ category=CheckCategory.NETWORK,
163
+ status=CheckStatus.SKIP,
164
+ message="No proxy configured (direct connection)",
165
+ )
166
+
167
+
168
+ @register_check(
169
+ id="network_ssl",
170
+ title="SSL Configuration",
171
+ description="Check SSL/TLS configuration",
172
+ category=CheckCategory.NETWORK,
173
+ severity=CheckSeverity.INFO,
174
+ )
175
+ def check_network_ssl(config: DoctorConfig) -> CheckResult:
176
+ """Check SSL/TLS configuration."""
177
+ ssl_vars = {
178
+ "SSL_CERT_FILE": os.environ.get("SSL_CERT_FILE"),
179
+ "SSL_CERT_DIR": os.environ.get("SSL_CERT_DIR"),
180
+ "REQUESTS_CA_BUNDLE": os.environ.get("REQUESTS_CA_BUNDLE"),
181
+ "CURL_CA_BUNDLE": os.environ.get("CURL_CA_BUNDLE"),
182
+ }
183
+
184
+ configured = {k: v for k, v in ssl_vars.items() if v}
185
+
186
+ # Check for SSL verification disable (security concern)
187
+ ssl_verify = os.environ.get("PYTHONHTTPSVERIFY", "1")
188
+ requests_verify = os.environ.get("REQUESTS_SSL_VERIFY", "1")
189
+
190
+ warnings = []
191
+ if ssl_verify == "0":
192
+ warnings.append("PYTHONHTTPSVERIFY=0 (SSL verification disabled)")
193
+ if requests_verify.lower() in ("0", "false"):
194
+ warnings.append("REQUESTS_SSL_VERIFY disabled")
195
+
196
+ if warnings:
197
+ return CheckResult(
198
+ id="network_ssl",
199
+ title="SSL Configuration",
200
+ category=CheckCategory.NETWORK,
201
+ status=CheckStatus.WARN,
202
+ message="SSL verification disabled",
203
+ details="; ".join(warnings),
204
+ remediation="Enable SSL verification for security",
205
+ )
206
+ elif configured:
207
+ return CheckResult(
208
+ id="network_ssl",
209
+ title="SSL Configuration",
210
+ category=CheckCategory.NETWORK,
211
+ status=CheckStatus.PASS,
212
+ message=f"Custom SSL config: {', '.join(configured.keys())}",
213
+ )
214
+ else:
215
+ return CheckResult(
216
+ id="network_ssl",
217
+ title="SSL Configuration",
218
+ category=CheckCategory.NETWORK,
219
+ status=CheckStatus.PASS,
220
+ message="Using default SSL configuration",
221
+ )
222
+
223
+
224
+ @register_check(
225
+ id="network_openai_base_url",
226
+ title="OpenAI Base URL",
227
+ description="Check OpenAI base URL configuration",
228
+ category=CheckCategory.NETWORK,
229
+ severity=CheckSeverity.INFO,
230
+ )
231
+ def check_network_openai_base_url(config: DoctorConfig) -> CheckResult:
232
+ """Check OpenAI base URL configuration."""
233
+ base_url = os.environ.get("OPENAI_BASE_URL") or os.environ.get("OPENAI_API_BASE")
234
+
235
+ if base_url:
236
+ return CheckResult(
237
+ id="network_openai_base_url",
238
+ title="OpenAI Base URL",
239
+ category=CheckCategory.NETWORK,
240
+ status=CheckStatus.PASS,
241
+ message=f"Custom OpenAI base URL: {base_url}",
242
+ details="Using custom endpoint (e.g., Azure, local proxy)",
243
+ )
244
+ else:
245
+ return CheckResult(
246
+ id="network_openai_base_url",
247
+ title="OpenAI Base URL",
248
+ category=CheckCategory.NETWORK,
249
+ status=CheckStatus.PASS,
250
+ message="Using default OpenAI endpoint",
251
+ )