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,680 @@
1
+ """
2
+ Tools Handler for CLI.
3
+
4
+ Provides tool registry management.
5
+ Usage: praisonai tools list
6
+ praisonai tools info internet_search
7
+ """
8
+
9
+ from typing import Any, Dict, List
10
+ from .base import CommandHandler
11
+
12
+
13
+ class ToolsHandler(CommandHandler):
14
+ """
15
+ Handler for tools command.
16
+
17
+ Manages tool registry and provides tool information.
18
+
19
+ Example:
20
+ praisonai tools list
21
+ praisonai tools info internet_search
22
+ praisonai tools search "web"
23
+ """
24
+
25
+ def __init__(self, verbose: bool = False):
26
+ super().__init__(verbose)
27
+ self._registry = None
28
+
29
+ @property
30
+ def feature_name(self) -> str:
31
+ return "tools"
32
+
33
+ def get_actions(self) -> List[str]:
34
+ return ["list", "info", "search", "doctor", "resolve", "discover", "show-sources", "add", "add-sources", "remove-sources", "help"]
35
+
36
+ def get_help_text(self) -> str:
37
+ return """
38
+ Tools Commands:
39
+ praisonai tools list - List all available tools
40
+ praisonai tools info <name> - Show tool details
41
+ praisonai tools search <query> - Search tools by name/description
42
+ praisonai tools doctor - Diagnose tool availability and dependencies
43
+ praisonai tools doctor --json - Output diagnosis as JSON
44
+ praisonai tools resolve <name> - Resolve a tool name to its source
45
+ praisonai tools discover - Discover tools from installed packages
46
+ praisonai tools show-sources - Show all tool sources for a template
47
+ praisonai tools add <source> - Add tools from package, file, or GitHub
48
+ praisonai tools add-sources <source> - Add a tool source to persistent config
49
+ praisonai tools remove-sources <source> - Remove a tool source from config
50
+
51
+ Add Examples:
52
+ praisonai tools add pandas - Wrap pandas functions as tools
53
+ praisonai tools add ./my_tools.py - Add local tools file
54
+ praisonai tools add github:user/repo - Add tools from GitHub
55
+
56
+ Built-in tools include: internet_search, calculator, file operations, etc.
57
+ """
58
+
59
+ def _get_registry(self):
60
+ """Get tool registry lazily."""
61
+ if self._registry is None:
62
+ try:
63
+ from praisonaiagents.tools import get_registry
64
+ self._registry = get_registry()
65
+ except ImportError:
66
+ self.print_status(
67
+ "Tools require praisonaiagents. Install with: pip install praisonaiagents",
68
+ "error"
69
+ )
70
+ return None
71
+ return self._registry
72
+
73
+ def _get_builtin_tools(self) -> Dict[str, Any]:
74
+ """Get dictionary of built-in tools."""
75
+ tools = {}
76
+ try:
77
+ from praisonaiagents.tools import TOOL_MAPPINGS
78
+ tools.update(TOOL_MAPPINGS)
79
+ except ImportError:
80
+ pass
81
+
82
+ # Add common tool descriptions
83
+ tool_descriptions = {
84
+ "internet_search": "Search the internet using DuckDuckGo",
85
+ "calculator": "Perform mathematical calculations",
86
+ "read_file": "Read contents of a file",
87
+ "write_file": "Write content to a file",
88
+ "list_files": "List files in a directory",
89
+ "execute_code": "Execute Python code",
90
+ "shell_command": "Execute shell commands",
91
+ "wikipedia_search": "Search Wikipedia",
92
+ "arxiv_search": "Search arXiv papers",
93
+ "tavily_search": "Search using Tavily API",
94
+ "csv_read": "Read CSV files",
95
+ "json_read": "Read JSON files",
96
+ "yaml_read": "Read YAML files",
97
+ }
98
+
99
+ for name, desc in tool_descriptions.items():
100
+ if name not in tools:
101
+ tools[name] = {"description": desc, "available": name in tools}
102
+
103
+ return tools
104
+
105
+ def action_list(self, args: List[str], **kwargs) -> List[str]:
106
+ """
107
+ List all available tools.
108
+
109
+ Returns:
110
+ List of tool names
111
+ """
112
+ tools = self._get_builtin_tools()
113
+
114
+ self.print_status("\n🔧 Available Tools:", "info")
115
+ self.print_status("-" * 50, "info")
116
+
117
+ # Group by category
118
+ categories = {
119
+ "Search": ["internet_search", "wikipedia_search", "arxiv_search", "tavily_search"],
120
+ "File": ["read_file", "write_file", "list_files", "csv_read", "json_read", "yaml_read"],
121
+ "Code": ["execute_code", "shell_command", "calculator"],
122
+ }
123
+
124
+ for category, tool_names in categories.items():
125
+ self.print_status(f"\n {category}:", "info")
126
+ for name in tool_names:
127
+ if name in tools:
128
+ desc = tools[name].get("description", "No description") if isinstance(tools[name], dict) else "Available"
129
+ self.print_status(f" • {name}: {desc}", "info")
130
+
131
+ # List any uncategorized tools
132
+ categorized = set(t for tools_list in categories.values() for t in tools_list)
133
+ uncategorized = [t for t in tools.keys() if t not in categorized]
134
+
135
+ if uncategorized:
136
+ self.print_status("\n Other:", "info")
137
+ for name in uncategorized[:10]: # Limit to 10
138
+ self.print_status(f" • {name}", "info")
139
+
140
+ # Show added tool sources from config
141
+ config = self._load_config()
142
+ if config.get("sources"):
143
+ self.print_status("\n Added Sources (use with Agent):", "info")
144
+ for source in config["sources"]:
145
+ self.print_status(f" • {source}", "info")
146
+
147
+ return list(tools.keys())
148
+
149
+ def action_info(self, args: List[str], **kwargs) -> Dict[str, Any]:
150
+ """
151
+ Show tool information.
152
+
153
+ Args:
154
+ args: List containing tool name
155
+
156
+ Returns:
157
+ Dictionary of tool info
158
+ """
159
+ if not args:
160
+ self.print_status("Usage: praisonai tools info <tool_name>", "error")
161
+ return {}
162
+
163
+ tool_name = args[0]
164
+
165
+ try:
166
+ import praisonaiagents.tools as tools_module
167
+
168
+ if hasattr(tools_module, tool_name):
169
+ tool = getattr(tools_module, tool_name)
170
+
171
+ info = {
172
+ "name": tool_name,
173
+ "type": type(tool).__name__,
174
+ "doc": tool.__doc__ or "No documentation",
175
+ }
176
+
177
+ # Get function signature if available
178
+ if callable(tool):
179
+ import inspect
180
+ try:
181
+ sig = inspect.signature(tool)
182
+ info["signature"] = str(sig)
183
+ info["parameters"] = list(sig.parameters.keys())
184
+ except (ValueError, TypeError):
185
+ pass
186
+
187
+ self.print_status(f"\n🔧 Tool: {tool_name}", "info")
188
+ self.print_status("-" * 40, "info")
189
+ for key, value in info.items():
190
+ if key == "doc":
191
+ self.print_status(f"\nDescription:\n{value}", "info")
192
+ else:
193
+ self.print_status(f" {key}: {value}", "info")
194
+
195
+ return info
196
+ else:
197
+ self.print_status(f"Tool '{tool_name}' not found", "error")
198
+ return {}
199
+
200
+ except ImportError:
201
+ self.print_status("Could not load tools module", "error")
202
+ return {}
203
+
204
+ def action_search(self, args: List[str], **kwargs) -> List[str]:
205
+ """
206
+ Search tools by name or description.
207
+
208
+ Args:
209
+ args: List containing search query
210
+
211
+ Returns:
212
+ List of matching tool names
213
+ """
214
+ if not args:
215
+ self.print_status("Usage: praisonai tools search <query>", "error")
216
+ return []
217
+
218
+ query = ' '.join(args).lower()
219
+ tools = self._get_builtin_tools()
220
+
221
+ matches = []
222
+ for name, info in tools.items():
223
+ desc = info.get("description", "") if isinstance(info, dict) else ""
224
+ if query in name.lower() or query in desc.lower():
225
+ matches.append(name)
226
+
227
+ if matches:
228
+ self.print_status(f"\n🔍 Tools matching '{query}':", "info")
229
+ for name in matches:
230
+ self.print_status(f" • {name}", "info")
231
+ else:
232
+ self.print_status(f"No tools found matching '{query}'", "warning")
233
+
234
+ return matches
235
+
236
+ def action_doctor(self, args: List[str], **kwargs) -> Dict[str, Any]:
237
+ """
238
+ Diagnose tool availability and dependencies.
239
+
240
+ Args:
241
+ args: List containing optional flags (--json)
242
+
243
+ Returns:
244
+ Dict with diagnostic results
245
+ """
246
+ json_output = "--json" in args
247
+
248
+ try:
249
+ from praisonai.templates.tools_doctor import ToolsDoctor
250
+
251
+ doctor = ToolsDoctor()
252
+
253
+ if json_output:
254
+ print(doctor.diagnose_json())
255
+ else:
256
+ print(doctor.diagnose_human())
257
+
258
+ return doctor.diagnose()
259
+
260
+ except Exception as e:
261
+ self.print_status(f"Error running diagnostics: {e}", "error")
262
+ return {}
263
+
264
+ def action_resolve(self, args: List[str], **kwargs) -> Dict[str, Any]:
265
+ """
266
+ Resolve a tool name to its source.
267
+
268
+ Args:
269
+ args: [tool_name, --template <template>, --tools <file>, --tools-dir <dir>]
270
+ """
271
+ if not args:
272
+ self.print_status("Usage: praisonai tools resolve <tool_name> [--template <template>]", "error")
273
+ return {}
274
+
275
+ tool_name = args[0]
276
+ template_name = None
277
+ tools_files = []
278
+ tools_dirs = []
279
+
280
+ # Parse flags
281
+ i = 1
282
+ while i < len(args):
283
+ if args[i] == "--template" and i + 1 < len(args):
284
+ template_name = args[i + 1]
285
+ i += 2
286
+ elif args[i] == "--tools" and i + 1 < len(args):
287
+ tools_files.append(args[i + 1])
288
+ i += 2
289
+ elif args[i] == "--tools-dir" and i + 1 < len(args):
290
+ tools_dirs.append(args[i + 1])
291
+ i += 2
292
+ else:
293
+ i += 1
294
+
295
+ try:
296
+ from praisonai.templates.tool_override import create_tool_registry_with_overrides, resolve_tools
297
+
298
+ registry = create_tool_registry_with_overrides(
299
+ override_files=tools_files if tools_files else None,
300
+ override_dirs=tools_dirs if tools_dirs else None,
301
+ include_defaults=True,
302
+ )
303
+
304
+ resolved = resolve_tools([tool_name], registry=registry)
305
+
306
+ if resolved:
307
+ tool = resolved[0]
308
+ info = {
309
+ "name": tool_name,
310
+ "resolved": True,
311
+ "type": type(tool).__name__,
312
+ "module": getattr(tool, "__module__", "unknown"),
313
+ }
314
+ self.print_status(f"\n✓ Tool '{tool_name}' resolved:", "success")
315
+ for k, v in info.items():
316
+ self.print_status(f" {k}: {v}", "info")
317
+ return info
318
+ else:
319
+ self.print_status(f"✗ Tool '{tool_name}' not found", "error")
320
+ return {"name": tool_name, "resolved": False}
321
+
322
+ except Exception as e:
323
+ self.print_status(f"Error resolving tool: {e}", "error")
324
+ return {}
325
+
326
+ def action_discover(self, args: List[str], **kwargs) -> Dict[str, Any]:
327
+ """
328
+ Discover tools from installed packages.
329
+
330
+ Args:
331
+ args: [--include <package>, --entrypoints]
332
+ """
333
+ include_packages = []
334
+ use_entrypoints = "--entrypoints" in args
335
+
336
+ i = 0
337
+ while i < len(args):
338
+ if args[i] == "--include" and i + 1 < len(args):
339
+ include_packages.append(args[i + 1])
340
+ i += 2
341
+ else:
342
+ i += 1
343
+
344
+ discovered = {}
345
+
346
+ # Try praisonai_tools package
347
+ try:
348
+ import praisonai_tools
349
+ pkg_tools = []
350
+
351
+ # Check for video module
352
+ try:
353
+ from praisonai_tools import video
354
+ pkg_tools.append("praisonai_tools.video")
355
+ except ImportError:
356
+ pass
357
+
358
+ # Check for tools module
359
+ try:
360
+ import praisonai_tools.tools as ext_tools
361
+ for name in dir(ext_tools):
362
+ if not name.startswith('_'):
363
+ obj = getattr(ext_tools, name, None)
364
+ if callable(obj):
365
+ pkg_tools.append(name)
366
+ except ImportError:
367
+ pass
368
+
369
+ if pkg_tools:
370
+ discovered["praisonai_tools"] = pkg_tools
371
+ except ImportError:
372
+ pass
373
+
374
+ # Try praisonaiagents built-in tools
375
+ try:
376
+ from praisonaiagents.tools import TOOL_MAPPINGS
377
+ discovered["praisonaiagents.tools"] = list(TOOL_MAPPINGS.keys())[:20] # Limit
378
+ except ImportError:
379
+ pass
380
+
381
+ # Additional packages from --include
382
+ for pkg in include_packages:
383
+ try:
384
+ import importlib
385
+ mod = importlib.import_module(pkg)
386
+ tools = [n for n in dir(mod) if not n.startswith('_') and callable(getattr(mod, n, None))]
387
+ if tools:
388
+ discovered[pkg] = tools[:20]
389
+ except ImportError:
390
+ self.print_status(f"Package '{pkg}' not found", "warning")
391
+
392
+ self.print_status("\n🔍 Discovered Tools:", "info")
393
+ for pkg, tools in discovered.items():
394
+ self.print_status(f"\n {pkg}:", "info")
395
+ for t in tools[:10]:
396
+ self.print_status(f" • {t}", "info")
397
+ if len(tools) > 10:
398
+ self.print_status(f" ... and {len(tools) - 10} more", "info")
399
+
400
+ return discovered
401
+
402
+ def action_show_sources(self, args: List[str], **kwargs) -> Dict[str, Any]:
403
+ """
404
+ Show all tool sources for a template.
405
+
406
+ Args:
407
+ args: [--template <template>]
408
+ """
409
+ template_name = None
410
+
411
+ i = 0
412
+ while i < len(args):
413
+ if args[i] == "--template" and i + 1 < len(args):
414
+ template_name = args[i + 1]
415
+ i += 2
416
+ else:
417
+ i += 1
418
+
419
+ from pathlib import Path
420
+
421
+ # Check if tools.py exists in current directory
422
+ cwd_tools_py = Path.cwd() / "tools.py"
423
+
424
+ sources = {
425
+ "built_in": "praisonaiagents.tools.TOOL_MAPPINGS",
426
+ "package_discovery": ["praisonai_tools"],
427
+ "default_dirs": [
428
+ "~/.praison/tools",
429
+ "~/.config/praison/tools",
430
+ ],
431
+ "cwd_tools_py": str(cwd_tools_py) if cwd_tools_py.exists() else "(not found: ./tools.py)",
432
+ }
433
+
434
+ if template_name:
435
+ try:
436
+ from praisonai.templates.loader import TemplateLoader
437
+ loader = TemplateLoader()
438
+ template = loader.load_template(template_name)
439
+
440
+ if template.requires and isinstance(template.requires, dict):
441
+ ts = template.requires.get("tools_sources", [])
442
+ if ts:
443
+ sources["template_tools_sources"] = ts
444
+
445
+ if template.path:
446
+ from pathlib import Path
447
+ tools_py = Path(template.path) / "tools.py"
448
+ if tools_py.exists():
449
+ sources["template_local_tools_py"] = str(tools_py)
450
+
451
+ except Exception as e:
452
+ self.print_status(f"Could not load template: {e}", "warning")
453
+
454
+ self.print_status("\n📦 Tool Sources:", "info")
455
+ for source_type, value in sources.items():
456
+ if isinstance(value, list):
457
+ self.print_status(f"\n {source_type}:", "info")
458
+ for v in value:
459
+ self.print_status(f" • {v}", "info")
460
+ else:
461
+ self.print_status(f"\n {source_type}: {value}", "info")
462
+
463
+ return sources
464
+
465
+ def _get_config_path(self):
466
+ """Get the path to the tools config file."""
467
+ from pathlib import Path
468
+ config_dir = Path.home() / ".praison"
469
+ config_dir.mkdir(parents=True, exist_ok=True)
470
+ return config_dir / "tools_sources.yaml"
471
+
472
+ def _load_config(self) -> Dict[str, Any]:
473
+ """Load tools config from file."""
474
+ config_path = self._get_config_path()
475
+ if config_path.exists():
476
+ import yaml
477
+ with open(config_path, 'r') as f:
478
+ return yaml.safe_load(f) or {}
479
+ return {"sources": []}
480
+
481
+ def _save_config(self, config: Dict[str, Any]):
482
+ """Save tools config to file."""
483
+ import yaml
484
+ config_path = self._get_config_path()
485
+ with open(config_path, 'w') as f:
486
+ yaml.dump(config, f, default_flow_style=False)
487
+
488
+ def action_add(self, args: List[str], **kwargs) -> Dict[str, Any]:
489
+ """
490
+ Add tools from package, file, or GitHub.
491
+
492
+ Args:
493
+ args: [source] - package name, file path, or github:user/repo
494
+
495
+ Examples:
496
+ praisonai tools add pandas
497
+ praisonai tools add ./my_tools.py
498
+ praisonai tools add github:user/repo/tools
499
+ """
500
+ if not args:
501
+ self.print_status("Usage: praisonai tools add <source>", "error")
502
+ self.print_status(" source: package name, file path, or github:user/repo", "info")
503
+ return {"success": False, "error": "No source provided"}
504
+
505
+ source = args[0]
506
+ result = {"source": source, "success": False, "tools": []}
507
+
508
+ from pathlib import Path
509
+
510
+ # Check if it's a local file
511
+ if source.startswith("./") or source.startswith("/") or source.endswith(".py"):
512
+ path = Path(source).resolve()
513
+ if path.exists():
514
+ # Copy to ~/.praison/tools/
515
+ tools_dir = Path.home() / ".praison" / "tools"
516
+ tools_dir.mkdir(parents=True, exist_ok=True)
517
+ dest = tools_dir / path.name
518
+
519
+ import shutil
520
+ shutil.copy(path, dest)
521
+
522
+ self.print_status(f"\n✅ Added tools file: {path.name}", "success")
523
+ self.print_status(f" Copied to: {dest}", "info")
524
+
525
+ # Discover tools in the file
526
+ try:
527
+ import importlib.util
528
+ spec = importlib.util.spec_from_file_location("tools_module", dest)
529
+ module = importlib.util.module_from_spec(spec)
530
+ spec.loader.exec_module(module)
531
+
532
+ tools = [n for n in dir(module) if not n.startswith('_') and callable(getattr(module, n, None))]
533
+ result["tools"] = tools
534
+ self.print_status(f" Found {len(tools)} tools: {', '.join(tools[:5])}", "info")
535
+ except Exception as e:
536
+ self.print_status(f" Warning: Could not inspect tools: {e}", "warning")
537
+
538
+ result["success"] = True
539
+ return result
540
+ else:
541
+ self.print_status(f"File not found: {source}", "error")
542
+ return result
543
+
544
+ # Check if it's a GitHub reference
545
+ elif source.startswith("github:"):
546
+ github_path = source[7:] # Remove "github:"
547
+ parts = github_path.split("/")
548
+ if len(parts) < 2:
549
+ self.print_status("Invalid GitHub format. Use: github:user/repo/path", "error")
550
+ return result
551
+
552
+ user, repo = parts[0], parts[1]
553
+ path = "/".join(parts[2:]) if len(parts) > 2 else ""
554
+
555
+ # Download from GitHub
556
+ import urllib.request
557
+
558
+ if path:
559
+ raw_url = f"https://raw.githubusercontent.com/{user}/{repo}/main/{path}"
560
+ if not path.endswith(".py"):
561
+ raw_url += "/tools.py"
562
+ else:
563
+ raw_url = f"https://raw.githubusercontent.com/{user}/{repo}/main/tools.py"
564
+
565
+ try:
566
+ self.print_status(f"Downloading from: {raw_url}", "info")
567
+
568
+ tools_dir = Path.home() / ".praison" / "tools"
569
+ tools_dir.mkdir(parents=True, exist_ok=True)
570
+
571
+ filename = f"{user}_{repo}_{path.replace('/', '_')}.py" if path else f"{user}_{repo}_tools.py"
572
+ dest = tools_dir / filename
573
+
574
+ urllib.request.urlretrieve(raw_url, dest)
575
+
576
+ self.print_status(f"\n✅ Added tools from GitHub: {user}/{repo}", "success")
577
+ self.print_status(f" Saved to: {dest}", "info")
578
+
579
+ result["success"] = True
580
+ return result
581
+ except Exception as e:
582
+ self.print_status(f"Failed to download from GitHub: {e}", "error")
583
+ return result
584
+
585
+ # Assume it's a package name - but warn that packages need wrapper tools
586
+ else:
587
+ try:
588
+ import importlib
589
+ module = importlib.import_module(source)
590
+
591
+ # Get callable functions from the module
592
+ tools = [n for n in dir(module) if not n.startswith('_') and callable(getattr(module, n, None))]
593
+
594
+ self.print_status(f"\n⚠️ Package '{source}' is installed but NOT directly usable as tools", "warning")
595
+ self.print_status(f" Found {len(tools)} callable items in package", "info")
596
+ self.print_status("", "info")
597
+ self.print_status(" To use this package with agents, create wrapper tools:", "info")
598
+ self.print_status(" 1. Create a file: ~/.praison/tools/my_tools.py", "info")
599
+ self.print_status(" 2. Define wrapper functions with docstrings", "info")
600
+ self.print_status(" 3. Tools will be auto-discovered", "info")
601
+ self.print_status("", "info")
602
+ self.print_status(" Example wrapper:", "info")
603
+ self.print_status(f" def my_{source}_tool(data: str) -> str:", "info")
604
+ self.print_status(f' """Use {source} to process data."""', "info")
605
+ self.print_status(f" import {source}", "info")
606
+ self.print_status(" # Your logic here", "info")
607
+ self.print_status(" return result", "info")
608
+
609
+ result["success"] = True
610
+ result["tools"] = tools[:10]
611
+ result["note"] = "Package requires wrapper tools"
612
+ return result
613
+ except ImportError:
614
+ self.print_status(f"Package '{source}' not found. Install with: pip install {source}", "error")
615
+ return result
616
+
617
+ def action_add_sources(self, args: List[str], **kwargs) -> Dict[str, Any]:
618
+ """
619
+ Add a tool source to persistent config.
620
+
621
+ Args:
622
+ args: [source] - package name, file path, or github:user/repo
623
+ """
624
+ if not args:
625
+ self.print_status("Usage: praisonai tools add-sources <source>", "error")
626
+ return {"success": False, "error": "No source provided"}
627
+
628
+ source = args[0]
629
+ config = self._load_config()
630
+
631
+ if "sources" not in config:
632
+ config["sources"] = []
633
+
634
+ if source in config["sources"]:
635
+ self.print_status(f"Source '{source}' already in config", "warning")
636
+ return {"success": True, "already_exists": True}
637
+
638
+ config["sources"].append(source)
639
+ self._save_config(config)
640
+
641
+ self.print_status(f"\n✅ Added tool source: {source}", "success")
642
+ self.print_status(f" Config saved to: {self._get_config_path()}", "info")
643
+
644
+ return {"success": True, "source": source}
645
+
646
+ def action_remove_sources(self, args: List[str], **kwargs) -> Dict[str, Any]:
647
+ """
648
+ Remove a tool source from persistent config.
649
+
650
+ Args:
651
+ args: [source] - source to remove
652
+ """
653
+ if not args:
654
+ self.print_status("Usage: praisonai tools remove-sources <source>", "error")
655
+ return {"success": False, "error": "No source provided"}
656
+
657
+ source = args[0]
658
+ config = self._load_config()
659
+
660
+ if "sources" not in config or source not in config["sources"]:
661
+ self.print_status(f"Source '{source}' not found in config", "warning")
662
+ return {"success": False, "not_found": True}
663
+
664
+ config["sources"].remove(source)
665
+ self._save_config(config)
666
+
667
+ self.print_status(f"\n✅ Removed tool source: {source}", "success")
668
+
669
+ return {"success": True, "source": source}
670
+
671
+ def execute(self, action: str, action_args: List[str], **kwargs) -> Any:
672
+ """Execute tools command action."""
673
+ # Handle hyphenated action names
674
+ if action == "show-sources":
675
+ return self.action_show_sources(action_args, **kwargs)
676
+ elif action == "add-sources":
677
+ return self.action_add_sources(action_args, **kwargs)
678
+ elif action == "remove-sources":
679
+ return self.action_remove_sources(action_args, **kwargs)
680
+ return super().execute(action, action_args, **kwargs)