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,583 @@
1
+ """
2
+ Hooks CLI Feature for PraisonAI.
3
+
4
+ Provides CLI commands for managing and testing hooks.
5
+
6
+ Commands:
7
+ - praisonai hooks list # List registered hooks
8
+ - praisonai hooks test <event> <target> # Test hooks for an event
9
+ - praisonai hooks validate <config> # Validate hooks configuration
10
+ - praisonai hooks run <command> # Run a command hook manually
11
+ """
12
+
13
+ import os
14
+ import json
15
+ import asyncio
16
+ from typing import Optional, Dict, Any, List
17
+ from dataclasses import dataclass, field
18
+
19
+
20
+ @dataclass
21
+ class HooksConfig:
22
+ """Configuration for hooks loaded from file."""
23
+ hooks: List[Dict[str, Any]] = field(default_factory=list)
24
+ enabled: bool = True
25
+
26
+ @classmethod
27
+ def from_file(cls, path: str) -> "HooksConfig":
28
+ """Load hooks configuration from a JSON/YAML file."""
29
+ if not os.path.exists(path):
30
+ raise FileNotFoundError(f"Hooks config file not found: {path}")
31
+
32
+ with open(path, 'r') as f:
33
+ if path.endswith('.yaml') or path.endswith('.yml'):
34
+ try:
35
+ import yaml
36
+ data = yaml.safe_load(f)
37
+ except ImportError:
38
+ raise ImportError("PyYAML required for YAML config files")
39
+ else:
40
+ data = json.load(f)
41
+
42
+ return cls(
43
+ hooks=data.get('hooks', []),
44
+ enabled=data.get('enabled', True)
45
+ )
46
+
47
+ def to_dict(self) -> Dict[str, Any]:
48
+ """Convert to dictionary."""
49
+ return {
50
+ 'hooks': self.hooks,
51
+ 'enabled': self.enabled
52
+ }
53
+
54
+
55
+ class HooksHandler:
56
+ """
57
+ Handler for hooks CLI commands.
58
+
59
+ Provides functionality to:
60
+ - List registered hooks
61
+ - Test hooks with sample events
62
+ - Validate hook configurations
63
+ - Run command hooks manually
64
+ """
65
+
66
+ def __init__(self, verbose: bool = False):
67
+ self.verbose = verbose
68
+ self._registry = None
69
+ self._runner = None
70
+
71
+ @property
72
+ def feature_name(self) -> str:
73
+ return "hooks"
74
+
75
+ def _get_registry(self):
76
+ """Lazy load the hook registry."""
77
+ if self._registry is None:
78
+ from praisonaiagents.hooks import HookRegistry
79
+ self._registry = HookRegistry()
80
+ return self._registry
81
+
82
+ def _get_runner(self):
83
+ """Lazy load the hook runner."""
84
+ if self._runner is None:
85
+ from praisonaiagents.hooks import HookRunner
86
+ self._runner = HookRunner(self._get_registry())
87
+ return self._runner
88
+
89
+ def list_hooks(self, format: str = "table") -> Dict[str, Any]:
90
+ """
91
+ List all registered hooks.
92
+
93
+ Args:
94
+ format: Output format (table, json)
95
+
96
+ Returns:
97
+ Dictionary of hooks by event
98
+ """
99
+ registry = self._get_registry()
100
+ hooks = registry.list_hooks()
101
+
102
+ if format == "json":
103
+ print(json.dumps(hooks, indent=2))
104
+ else:
105
+ self._print_hooks_table(hooks)
106
+
107
+ return hooks
108
+
109
+ def _print_hooks_table(self, hooks: Dict[str, List[Dict]]):
110
+ """Print hooks in table format."""
111
+ try:
112
+ from rich.console import Console
113
+ from rich.table import Table
114
+
115
+ console = Console()
116
+
117
+ if not hooks:
118
+ console.print("[yellow]No hooks registered[/yellow]")
119
+ return
120
+
121
+ table = Table(title="Registered Hooks")
122
+ table.add_column("Event", style="cyan")
123
+ table.add_column("Name", style="green")
124
+ table.add_column("Type", style="blue")
125
+ table.add_column("Matcher", style="magenta")
126
+ table.add_column("Enabled", style="yellow")
127
+
128
+ for event, event_hooks in hooks.items():
129
+ for hook in event_hooks:
130
+ table.add_row(
131
+ event,
132
+ hook.get('name', 'unknown'),
133
+ hook.get('type', 'unknown'),
134
+ hook.get('matcher') or '*',
135
+ '✓' if hook.get('enabled', True) else '✗'
136
+ )
137
+
138
+ console.print(table)
139
+ except ImportError:
140
+ # Fallback to simple print
141
+ print("Registered Hooks:")
142
+ for event, event_hooks in hooks.items():
143
+ print(f"\n {event}:")
144
+ for hook in event_hooks:
145
+ print(f" - {hook.get('name', 'unknown')} ({hook.get('type', 'unknown')})")
146
+
147
+ def test_hook(
148
+ self,
149
+ event: str,
150
+ target: Optional[str] = None,
151
+ input_data: Optional[Dict[str, Any]] = None
152
+ ) -> List[Dict[str, Any]]:
153
+ """
154
+ Test hooks for a specific event.
155
+
156
+ Args:
157
+ event: Event name (before_tool, after_tool, etc.)
158
+ target: Optional target to filter hooks (e.g., tool name)
159
+ input_data: Optional custom input data
160
+
161
+ Returns:
162
+ List of hook execution results
163
+ """
164
+ from praisonaiagents.hooks import HookEvent
165
+ from praisonaiagents.hooks.events import BeforeToolInput, BeforeAgentInput
166
+
167
+ # Map string to HookEvent
168
+ event_map = {
169
+ 'before_tool': HookEvent.BEFORE_TOOL,
170
+ 'after_tool': HookEvent.AFTER_TOOL,
171
+ 'before_agent': HookEvent.BEFORE_AGENT,
172
+ 'after_agent': HookEvent.AFTER_AGENT,
173
+ 'session_start': HookEvent.SESSION_START,
174
+ 'session_end': HookEvent.SESSION_END,
175
+ }
176
+
177
+ hook_event = event_map.get(event.lower())
178
+ if hook_event is None:
179
+ print(f"[red]Unknown event: {event}[/red]")
180
+ print(f"Available events: {', '.join(event_map.keys())}")
181
+ return []
182
+
183
+ # Create sample input based on event type
184
+ from datetime import datetime
185
+ timestamp = datetime.now().isoformat()
186
+
187
+ if hook_event in (HookEvent.BEFORE_TOOL, HookEvent.AFTER_TOOL):
188
+ sample_input = BeforeToolInput(
189
+ session_id="cli-test",
190
+ cwd=os.getcwd(),
191
+ event_name=event,
192
+ timestamp=timestamp,
193
+ tool_name=target or "test_tool",
194
+ tool_input=input_data or {"test": "data"}
195
+ )
196
+ else:
197
+ sample_input = BeforeAgentInput(
198
+ session_id="cli-test",
199
+ cwd=os.getcwd(),
200
+ event_name=event,
201
+ timestamp=timestamp,
202
+ prompt=target or "Test prompt"
203
+ )
204
+
205
+ runner = self._get_runner()
206
+ results = asyncio.run(runner.execute(hook_event, sample_input, target))
207
+
208
+ # Print results
209
+ self._print_test_results(results)
210
+
211
+ return [r.to_dict() for r in results]
212
+
213
+ def _print_test_results(self, results):
214
+ """Print test results."""
215
+ try:
216
+ from rich.console import Console
217
+ from rich.panel import Panel
218
+
219
+ console = Console()
220
+
221
+ if not results:
222
+ console.print("[yellow]No hooks executed[/yellow]")
223
+ return
224
+
225
+ console.print(f"\n[bold]Hook Execution Results ({len(results)} hooks)[/bold]\n")
226
+
227
+ for result in results:
228
+ status = "[green]✓ PASSED[/green]" if result.success else "[red]✗ FAILED[/red]"
229
+ decision = result.output.decision if result.output else "N/A"
230
+
231
+ content = f"""
232
+ Hook: {result.hook_name}
233
+ Status: {status}
234
+ Decision: {decision}
235
+ Duration: {result.duration_ms:.2f}ms
236
+ """
237
+ if result.error:
238
+ content += f"Error: {result.error}\n"
239
+ if result.output and result.output.reason:
240
+ content += f"Reason: {result.output.reason}\n"
241
+
242
+ panel_style = "green" if result.success else "red"
243
+ console.print(Panel(content.strip(), title=result.hook_name, border_style=panel_style))
244
+ except ImportError:
245
+ print(f"\nHook Execution Results ({len(results)} hooks):")
246
+ for result in results:
247
+ status = "PASSED" if result.success else "FAILED"
248
+ print(f" - {result.hook_name}: {status}")
249
+
250
+ def validate_config(self, config_path: str) -> bool:
251
+ """
252
+ Validate a hooks configuration file.
253
+
254
+ Args:
255
+ config_path: Path to the configuration file
256
+
257
+ Returns:
258
+ True if valid, False otherwise
259
+ """
260
+ try:
261
+ config = HooksConfig.from_file(config_path)
262
+
263
+ errors = []
264
+ warnings = []
265
+
266
+ for i, hook in enumerate(config.hooks):
267
+ # Check required fields
268
+ if 'event' not in hook:
269
+ errors.append(f"Hook {i}: missing 'event' field")
270
+
271
+ if 'command' not in hook and 'function' not in hook:
272
+ errors.append(f"Hook {i}: must have 'command' or 'function'")
273
+
274
+ # Check event name
275
+ valid_events = ['before_tool', 'after_tool', 'before_agent',
276
+ 'after_agent', 'session_start', 'session_end']
277
+ if hook.get('event') and hook['event'] not in valid_events:
278
+ warnings.append(f"Hook {i}: unknown event '{hook['event']}'")
279
+
280
+ # Check timeout
281
+ if 'timeout' in hook:
282
+ try:
283
+ timeout = float(hook['timeout'])
284
+ if timeout <= 0:
285
+ warnings.append(f"Hook {i}: timeout should be positive")
286
+ except (ValueError, TypeError):
287
+ errors.append(f"Hook {i}: invalid timeout value")
288
+
289
+ # Print results
290
+ try:
291
+ from rich.console import Console
292
+ console = Console()
293
+
294
+ if errors:
295
+ console.print("[red]Validation FAILED[/red]")
296
+ for error in errors:
297
+ console.print(f" [red]✗[/red] {error}")
298
+ else:
299
+ console.print("[green]Validation PASSED[/green]")
300
+
301
+ if warnings:
302
+ console.print("\n[yellow]Warnings:[/yellow]")
303
+ for warning in warnings:
304
+ console.print(f" [yellow]![/yellow] {warning}")
305
+
306
+ console.print(f"\n[dim]Found {len(config.hooks)} hooks in config[/dim]")
307
+ except ImportError:
308
+ if errors:
309
+ print("Validation FAILED")
310
+ for error in errors:
311
+ print(f" - {error}")
312
+ else:
313
+ print("Validation PASSED")
314
+
315
+ if warnings:
316
+ print("\nWarnings:")
317
+ for warning in warnings:
318
+ print(f" - {warning}")
319
+
320
+ return len(errors) == 0
321
+
322
+ except FileNotFoundError as e:
323
+ print(f"[red]Error: {e}[/red]")
324
+ return False
325
+ except json.JSONDecodeError as e:
326
+ print(f"[red]Invalid JSON: {e}[/red]")
327
+ return False
328
+ except Exception as e:
329
+ print(f"[red]Error validating config: {e}[/red]")
330
+ return False
331
+
332
+ def run_command_hook(
333
+ self,
334
+ command: str,
335
+ event: str = "before_tool",
336
+ input_json: Optional[str] = None,
337
+ timeout: float = 60.0
338
+ ) -> Dict[str, Any]:
339
+ """
340
+ Run a command hook manually.
341
+
342
+ Args:
343
+ command: Shell command to execute
344
+ event: Event type for the hook
345
+ input_json: Optional JSON input to pass to the command
346
+ timeout: Timeout in seconds
347
+
348
+ Returns:
349
+ Execution result
350
+ """
351
+ from praisonaiagents.hooks import HookEvent, HookRegistry, HookRunner
352
+ from praisonaiagents.hooks.events import BeforeToolInput
353
+ from datetime import datetime
354
+
355
+ registry = HookRegistry()
356
+ registry.register_command(
357
+ event=HookEvent.BEFORE_TOOL,
358
+ command=command,
359
+ name="cli_test_hook",
360
+ timeout=timeout
361
+ )
362
+
363
+ runner = HookRunner(registry)
364
+
365
+ # Create input
366
+ if input_json:
367
+ try:
368
+ custom_input = json.loads(input_json)
369
+ except json.JSONDecodeError:
370
+ custom_input = {}
371
+ else:
372
+ custom_input = {}
373
+
374
+ sample_input = BeforeToolInput(
375
+ session_id="cli-manual",
376
+ cwd=os.getcwd(),
377
+ event_name=event,
378
+ timestamp=datetime.now().isoformat(),
379
+ tool_name=custom_input.get('tool_name', 'manual_test'),
380
+ tool_input=custom_input.get('tool_input', {})
381
+ )
382
+
383
+ results = asyncio.run(runner.execute(HookEvent.BEFORE_TOOL, sample_input))
384
+
385
+ if results:
386
+ result = results[0]
387
+ self._print_command_result(result)
388
+ return result.to_dict()
389
+
390
+ return {}
391
+
392
+ def _print_command_result(self, result):
393
+ """Print command hook result."""
394
+ try:
395
+ from rich.console import Console
396
+ from rich.syntax import Syntax
397
+
398
+ console = Console()
399
+
400
+ console.print(f"\n[bold]Command Hook Result[/bold]")
401
+ console.print(f"Exit Code: {result.exit_code}")
402
+ console.print(f"Success: {'[green]Yes[/green]' if result.success else '[red]No[/red]'}")
403
+ console.print(f"Duration: {result.duration_ms:.2f}ms")
404
+
405
+ if result.stdout:
406
+ console.print("\n[bold]STDOUT:[/bold]")
407
+ console.print(result.stdout)
408
+
409
+ if result.stderr:
410
+ console.print("\n[bold]STDERR:[/bold]")
411
+ console.print(f"[red]{result.stderr}[/red]")
412
+
413
+ if result.output:
414
+ console.print(f"\n[bold]Decision:[/bold] {result.output.decision}")
415
+ if result.output.reason:
416
+ console.print(f"[bold]Reason:[/bold] {result.output.reason}")
417
+ except ImportError:
418
+ print(f"\nCommand Hook Result")
419
+ print(f"Exit Code: {result.exit_code}")
420
+ print(f"Success: {result.success}")
421
+ if result.stdout:
422
+ print(f"STDOUT: {result.stdout}")
423
+ if result.stderr:
424
+ print(f"STDERR: {result.stderr}")
425
+
426
+ def register_from_config(self, config_path: str) -> int:
427
+ """
428
+ Register hooks from a configuration file.
429
+
430
+ Args:
431
+ config_path: Path to the configuration file
432
+
433
+ Returns:
434
+ Number of hooks registered
435
+ """
436
+ from praisonaiagents.hooks import HookEvent
437
+
438
+ config = HooksConfig.from_file(config_path)
439
+ registry = self._get_registry()
440
+
441
+ event_map = {
442
+ 'before_tool': HookEvent.BEFORE_TOOL,
443
+ 'after_tool': HookEvent.AFTER_TOOL,
444
+ 'before_agent': HookEvent.BEFORE_AGENT,
445
+ 'after_agent': HookEvent.AFTER_AGENT,
446
+ 'session_start': HookEvent.SESSION_START,
447
+ 'session_end': HookEvent.SESSION_END,
448
+ }
449
+
450
+ count = 0
451
+ for hook in config.hooks:
452
+ event = event_map.get(hook.get('event', '').lower())
453
+ if event is None:
454
+ continue
455
+
456
+ if 'command' in hook:
457
+ registry.register_command(
458
+ event=event,
459
+ command=hook['command'],
460
+ name=hook.get('name'),
461
+ matcher=hook.get('matcher'),
462
+ timeout=hook.get('timeout', 60.0),
463
+ env=hook.get('env', {})
464
+ )
465
+ count += 1
466
+
467
+ print(f"[green]Registered {count} hooks from {config_path}[/green]")
468
+ return count
469
+
470
+
471
+ def handle_hooks_command(args: List[str], verbose: bool = False):
472
+ """
473
+ Handle hooks CLI commands.
474
+
475
+ Usage:
476
+ praisonai hooks list [--format json|table]
477
+ praisonai hooks test <event> [target] [--input '{"key": "value"}']
478
+ praisonai hooks validate <config_path>
479
+ praisonai hooks run <command> [--event <event>] [--input <json>] [--timeout <seconds>]
480
+ praisonai hooks load <config_path>
481
+ """
482
+ handler = HooksHandler(verbose=verbose)
483
+
484
+ if not args:
485
+ print("Usage: praisonai hooks <command> [options]")
486
+ print("\nCommands:")
487
+ print(" list List registered hooks")
488
+ print(" test <event> [target] Test hooks for an event")
489
+ print(" validate <config> Validate hooks configuration")
490
+ print(" run <command> Run a command hook manually")
491
+ print(" load <config> Load hooks from configuration file")
492
+ return
493
+
494
+ command = args[0]
495
+
496
+ if command == "list":
497
+ format_type = "table"
498
+ if "--format" in args:
499
+ idx = args.index("--format")
500
+ if idx + 1 < len(args):
501
+ format_type = args[idx + 1]
502
+ handler.list_hooks(format=format_type)
503
+
504
+ elif command == "test":
505
+ if len(args) < 2:
506
+ print("Usage: praisonai hooks test <event> [target] [--input <json>]")
507
+ return
508
+
509
+ event = args[1]
510
+ target = args[2] if len(args) > 2 and not args[2].startswith("--") else None
511
+
512
+ input_data = None
513
+ if "--input" in args:
514
+ idx = args.index("--input")
515
+ if idx + 1 < len(args):
516
+ try:
517
+ input_data = json.loads(args[idx + 1])
518
+ except json.JSONDecodeError:
519
+ print("[red]Invalid JSON input[/red]")
520
+ return
521
+
522
+ handler.test_hook(event, target, input_data)
523
+
524
+ elif command == "validate":
525
+ if len(args) < 2:
526
+ print("Usage: praisonai hooks validate <config_path>")
527
+ return
528
+ handler.validate_config(args[1])
529
+
530
+ elif command == "run":
531
+ if len(args) < 2:
532
+ print("Usage: praisonai hooks run <command> [--event <event>] [--input <json>] [--timeout <seconds>]")
533
+ return
534
+
535
+ cmd = args[1]
536
+ event = "before_tool"
537
+ input_json = None
538
+ timeout = 60.0
539
+
540
+ if "--event" in args:
541
+ idx = args.index("--event")
542
+ if idx + 1 < len(args):
543
+ event = args[idx + 1]
544
+
545
+ if "--input" in args:
546
+ idx = args.index("--input")
547
+ if idx + 1 < len(args):
548
+ input_json = args[idx + 1]
549
+
550
+ if "--timeout" in args:
551
+ idx = args.index("--timeout")
552
+ if idx + 1 < len(args):
553
+ try:
554
+ timeout = float(args[idx + 1])
555
+ except ValueError:
556
+ print("[red]Invalid timeout value[/red]")
557
+ return
558
+
559
+ handler.run_command_hook(cmd, event, input_json, timeout)
560
+
561
+ elif command == "load":
562
+ if len(args) < 2:
563
+ print("Usage: praisonai hooks load <config_path>")
564
+ return
565
+ handler.register_from_config(args[1])
566
+
567
+ elif command == "help" or command == "--help":
568
+ print("Hooks CLI Commands:")
569
+ print("\n praisonai hooks list [--format json|table]")
570
+ print(" List all registered hooks")
571
+ print("\n praisonai hooks test <event> [target] [--input <json>]")
572
+ print(" Test hooks for a specific event")
573
+ print(" Events: before_tool, after_tool, before_agent, after_agent, session_start, session_end")
574
+ print("\n praisonai hooks validate <config_path>")
575
+ print(" Validate a hooks configuration file (JSON or YAML)")
576
+ print("\n praisonai hooks run <command> [--event <event>] [--input <json>] [--timeout <seconds>]")
577
+ print(" Run a command hook manually for testing")
578
+ print("\n praisonai hooks load <config_path>")
579
+ print(" Load and register hooks from a configuration file")
580
+
581
+ else:
582
+ print(f"[red]Unknown command: {command}[/red]")
583
+ print("Use 'praisonai hooks help' for available commands")