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,358 @@
1
+ """
2
+ Dependency Checker for Templates.
3
+
4
+ Checks availability of tools, packages, and environment variables
5
+ required by templates. Supports strict mode for fail-fast behavior.
6
+ """
7
+
8
+ import importlib.util
9
+ import os
10
+ from dataclasses import dataclass, field
11
+ from pathlib import Path
12
+ from typing import Any, Dict, List, Optional, TYPE_CHECKING
13
+
14
+ if TYPE_CHECKING:
15
+ from .loader import TemplateConfig
16
+
17
+
18
+ class StrictModeError(Exception):
19
+ """Raised when strict mode detects missing dependencies."""
20
+
21
+ def __init__(self, message: str, missing_items: Dict[str, List[str]]):
22
+ super().__init__(message)
23
+ self.missing_items = missing_items
24
+
25
+
26
+ @dataclass
27
+ class DependencyStatus:
28
+ """Status of a single dependency."""
29
+ name: str
30
+ available: bool
31
+ source: Optional[str] = None
32
+ install_hint: Optional[str] = None
33
+ masked_value: Optional[str] = None
34
+
35
+
36
+ class DependencyChecker:
37
+ """
38
+ Checks availability of template dependencies.
39
+
40
+ Supports checking:
41
+ - Tools (from built-in registry, praisonai-tools, custom dirs)
42
+ - Packages (via importlib.util.find_spec)
43
+ - Environment variables (via os.environ)
44
+ """
45
+
46
+ # Known tool sources for install hints
47
+ TOOL_INSTALL_HINTS = {
48
+ "youtube_tool": "pip install praisonai-tools[video]",
49
+ "whisper_tool": "pip install praisonai-tools[audio]",
50
+ "vision_tool": "pip install praisonai-tools[vision]",
51
+ "tavily_search": "pip install tavily-python",
52
+ }
53
+
54
+ def __init__(self, custom_tool_dirs: Optional[List[str]] = None):
55
+ """
56
+ Initialize dependency checker.
57
+
58
+ Args:
59
+ custom_tool_dirs: Additional directories to search for tools
60
+ """
61
+ self._custom_tool_dirs = custom_tool_dirs or []
62
+ self._tool_cache: Dict[str, DependencyStatus] = {}
63
+
64
+ def check_tool(self, tool_name: str) -> Dict[str, Any]:
65
+ """
66
+ Check if a tool is available.
67
+
68
+ Args:
69
+ tool_name: Name of the tool to check
70
+
71
+ Returns:
72
+ Dict with 'available', 'source', and 'install_hint' keys
73
+ """
74
+ # Check cache first
75
+ if tool_name in self._tool_cache:
76
+ status = self._tool_cache[tool_name]
77
+ return {
78
+ "available": status.available,
79
+ "source": status.source,
80
+ "install_hint": status.install_hint
81
+ }
82
+
83
+ # Check built-in tools
84
+ source = self._check_builtin_tool(tool_name)
85
+ if source:
86
+ status = DependencyStatus(
87
+ name=tool_name,
88
+ available=True,
89
+ source=source
90
+ )
91
+ self._tool_cache[tool_name] = status
92
+ return {"available": True, "source": source, "install_hint": None}
93
+
94
+ # Check praisonai-tools
95
+ source = self._check_praisonai_tools(tool_name)
96
+ if source:
97
+ status = DependencyStatus(
98
+ name=tool_name,
99
+ available=True,
100
+ source=source
101
+ )
102
+ self._tool_cache[tool_name] = status
103
+ return {"available": True, "source": source, "install_hint": None}
104
+
105
+ # Check custom directories
106
+ source = self._check_custom_dirs(tool_name)
107
+ if source:
108
+ status = DependencyStatus(
109
+ name=tool_name,
110
+ available=True,
111
+ source=source
112
+ )
113
+ self._tool_cache[tool_name] = status
114
+ return {"available": True, "source": source, "install_hint": None}
115
+
116
+ # Tool not found
117
+ install_hint = self.TOOL_INSTALL_HINTS.get(tool_name)
118
+ if not install_hint:
119
+ install_hint = "Check praisonai-tools or define custom tool"
120
+
121
+ status = DependencyStatus(
122
+ name=tool_name,
123
+ available=False,
124
+ source=None,
125
+ install_hint=install_hint
126
+ )
127
+ self._tool_cache[tool_name] = status
128
+ return {"available": False, "source": None, "install_hint": install_hint}
129
+
130
+ def _check_builtin_tool(self, tool_name: str) -> Optional[str]:
131
+ """Check if tool exists in built-in registry."""
132
+ try:
133
+ from praisonaiagents.tools import TOOL_MAPPINGS
134
+ if tool_name in TOOL_MAPPINGS:
135
+ return "builtin"
136
+ except ImportError:
137
+ pass
138
+ return None
139
+
140
+ def _check_praisonai_tools(self, tool_name: str) -> Optional[str]:
141
+ """Check if tool exists in praisonai-tools package."""
142
+ try:
143
+ import praisonai_tools
144
+ if hasattr(praisonai_tools, tool_name):
145
+ return "praisonai-tools"
146
+ # Check for get_tool function
147
+ if hasattr(praisonai_tools, 'get_tool'):
148
+ try:
149
+ tool = praisonai_tools.get_tool(tool_name)
150
+ if tool:
151
+ return "praisonai-tools"
152
+ except Exception:
153
+ pass
154
+ except ImportError:
155
+ pass
156
+ return None
157
+
158
+ def _check_custom_dirs(self, tool_name: str) -> Optional[str]:
159
+ """Check if tool exists in custom directories."""
160
+ for dir_path in self._custom_tool_dirs:
161
+ path = Path(dir_path).expanduser()
162
+ if not path.exists():
163
+ continue
164
+
165
+ # Check for tool file
166
+ tool_file = path / f"{tool_name}.py"
167
+ if tool_file.exists():
168
+ return f"custom:{dir_path}"
169
+
170
+ # Check for tool in any Python file (by function name)
171
+ for py_file in path.glob("*.py"):
172
+ try:
173
+ content = py_file.read_text()
174
+ if f"def {tool_name}" in content:
175
+ return f"custom:{dir_path}"
176
+ except Exception:
177
+ pass
178
+
179
+ return None
180
+
181
+ def check_package(self, package_name: str) -> Dict[str, Any]:
182
+ """
183
+ Check if a Python package is available.
184
+
185
+ Args:
186
+ package_name: Name of the package to check
187
+
188
+ Returns:
189
+ Dict with 'available' and 'install_hint' keys
190
+ """
191
+ spec = importlib.util.find_spec(package_name)
192
+ if spec is not None:
193
+ return {"available": True, "install_hint": None}
194
+
195
+ return {
196
+ "available": False,
197
+ "install_hint": f"pip install {package_name}"
198
+ }
199
+
200
+ def check_env_var(self, var_name: str) -> Dict[str, Any]:
201
+ """
202
+ Check if an environment variable is set.
203
+
204
+ Args:
205
+ var_name: Name of the environment variable
206
+
207
+ Returns:
208
+ Dict with 'available' and 'masked_value' keys
209
+ """
210
+ value = os.environ.get(var_name)
211
+ if value:
212
+ # Mask the value for security
213
+ if len(value) > 8:
214
+ masked = value[:4] + "*" * (len(value) - 8) + value[-4:]
215
+ else:
216
+ masked = "*" * len(value)
217
+ return {"available": True, "masked_value": masked}
218
+
219
+ return {"available": False, "masked_value": None}
220
+
221
+ def check_template_dependencies(
222
+ self,
223
+ template: "TemplateConfig"
224
+ ) -> Dict[str, Any]:
225
+ """
226
+ Check all dependencies for a template.
227
+
228
+ Args:
229
+ template: Template configuration to check
230
+
231
+ Returns:
232
+ Dict with 'tools', 'packages', 'env', and 'all_satisfied' keys
233
+ """
234
+ result = {
235
+ "tools": [],
236
+ "packages": [],
237
+ "env": [],
238
+ "all_satisfied": True
239
+ }
240
+
241
+ # Check tools
242
+ tools = template.requires.get("tools", [])
243
+ if isinstance(tools, str):
244
+ tools = [tools]
245
+
246
+ for tool_name in tools:
247
+ status = self.check_tool(tool_name)
248
+ result["tools"].append({
249
+ "name": tool_name,
250
+ **status
251
+ })
252
+ if not status["available"]:
253
+ result["all_satisfied"] = False
254
+
255
+ # Check packages
256
+ packages = template.requires.get("packages", [])
257
+ if isinstance(packages, str):
258
+ packages = [packages]
259
+
260
+ for pkg_name in packages:
261
+ status = self.check_package(pkg_name)
262
+ result["packages"].append({
263
+ "name": pkg_name,
264
+ **status
265
+ })
266
+ if not status["available"]:
267
+ result["all_satisfied"] = False
268
+
269
+ # Check environment variables
270
+ env_vars = template.requires.get("env", [])
271
+ if isinstance(env_vars, str):
272
+ env_vars = [env_vars]
273
+
274
+ for var_name in env_vars:
275
+ status = self.check_env_var(var_name)
276
+ result["env"].append({
277
+ "name": var_name,
278
+ **status
279
+ })
280
+ if not status["available"]:
281
+ result["all_satisfied"] = False
282
+
283
+ return result
284
+
285
+ def get_install_hints(self, template: "TemplateConfig") -> List[str]:
286
+ """
287
+ Get install hints for missing dependencies.
288
+
289
+ Args:
290
+ template: Template configuration to check
291
+
292
+ Returns:
293
+ List of actionable install hints
294
+ """
295
+ hints = []
296
+ deps = self.check_template_dependencies(template)
297
+
298
+ # Tool hints
299
+ for tool in deps["tools"]:
300
+ if not tool["available"] and tool.get("install_hint"):
301
+ hints.append(f"Tool '{tool['name']}': {tool['install_hint']}")
302
+
303
+ # Package hints
304
+ for pkg in deps["packages"]:
305
+ if not pkg["available"] and pkg.get("install_hint"):
306
+ hints.append(f"Package '{pkg['name']}': {pkg['install_hint']}")
307
+
308
+ # Env hints
309
+ for env in deps["env"]:
310
+ if not env["available"]:
311
+ hints.append(f"Environment variable '{env['name']}': export {env['name']}=<value>")
312
+
313
+ return hints
314
+
315
+ def enforce_strict_mode(self, template: "TemplateConfig") -> bool:
316
+ """
317
+ Enforce strict mode - fail if any dependency is missing.
318
+
319
+ Args:
320
+ template: Template configuration to check
321
+
322
+ Returns:
323
+ True if all dependencies satisfied
324
+
325
+ Raises:
326
+ StrictModeError: If any dependency is missing
327
+ """
328
+ deps = self.check_template_dependencies(template)
329
+
330
+ if deps["all_satisfied"]:
331
+ return True
332
+
333
+ # Collect missing items
334
+ missing = {
335
+ "tools": [t["name"] for t in deps["tools"] if not t["available"]],
336
+ "packages": [p["name"] for p in deps["packages"] if not p["available"]],
337
+ "env": [e["name"] for e in deps["env"] if not e["available"]]
338
+ }
339
+
340
+ # Build error message
341
+ messages = []
342
+ if missing["tools"]:
343
+ messages.append(f"Missing tools: {', '.join(missing['tools'])}")
344
+ if missing["packages"]:
345
+ messages.append(f"Missing packages: {', '.join(missing['packages'])}")
346
+ if missing["env"]:
347
+ messages.append(f"Missing environment variables: {', '.join(missing['env'])}")
348
+
349
+ # Add hints
350
+ hints = self.get_install_hints(template)
351
+ if hints:
352
+ messages.append("\nTo fix:")
353
+ messages.extend(f" - {hint}" for hint in hints)
354
+
355
+ raise StrictModeError(
356
+ "\n".join(messages),
357
+ missing_items=missing
358
+ )