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,356 @@
1
+ """
2
+ Background Agents CLI Feature for PraisonAI.
3
+
4
+ Provides CLI commands for managing background agent tasks.
5
+
6
+ Commands:
7
+ - praisonai background list # List background tasks
8
+ - praisonai background status <id> # Get task status
9
+ - praisonai background cancel <id> # Cancel a task
10
+ - praisonai background clear # Clear completed tasks
11
+ """
12
+
13
+ import asyncio
14
+ from typing import Optional, List
15
+
16
+
17
+ class BackgroundHandler:
18
+ """
19
+ Handler for background CLI commands.
20
+
21
+ Provides functionality to:
22
+ - List running and completed background tasks
23
+ - Check task status
24
+ - Cancel running tasks
25
+ - Clear completed tasks
26
+ """
27
+
28
+ def __init__(self, verbose: bool = False):
29
+ self.verbose = verbose
30
+ self._runner = None
31
+
32
+ @property
33
+ def feature_name(self) -> str:
34
+ return "background"
35
+
36
+ async def _get_runner(self):
37
+ """Lazy load the background runner."""
38
+ if self._runner is None:
39
+ from praisonaiagents.background import BackgroundRunner
40
+ self._runner = BackgroundRunner()
41
+ return self._runner
42
+
43
+ async def list_tasks(self, status: Optional[str] = None) -> List[dict]:
44
+ """
45
+ List all background tasks.
46
+
47
+ Args:
48
+ status: Optional status filter (pending, running, completed, failed)
49
+
50
+ Returns:
51
+ List of task dictionaries
52
+ """
53
+ runner = await self._get_runner()
54
+
55
+ status_enum = None
56
+ if status:
57
+ from praisonaiagents.background import TaskStatus
58
+ status_map = {
59
+ "pending": TaskStatus.PENDING,
60
+ "running": TaskStatus.RUNNING,
61
+ "completed": TaskStatus.COMPLETED,
62
+ "failed": TaskStatus.FAILED,
63
+ "cancelled": TaskStatus.CANCELLED
64
+ }
65
+ status_enum = status_map.get(status.lower())
66
+
67
+ tasks = runner.list_tasks(status=status_enum)
68
+
69
+ self._print_tasks_table(tasks)
70
+ return tasks
71
+
72
+ def _print_tasks_table(self, tasks: List[dict]):
73
+ """Print tasks in table format."""
74
+ try:
75
+ from rich.console import Console
76
+ from rich.table import Table
77
+
78
+ console = Console()
79
+
80
+ if not tasks:
81
+ console.print("[yellow]No background tasks[/yellow]")
82
+ return
83
+
84
+ table = Table(title="Background Tasks")
85
+ table.add_column("ID", style="cyan")
86
+ table.add_column("Name", style="green")
87
+ table.add_column("Status", style="yellow")
88
+ table.add_column("Progress", style="blue")
89
+ table.add_column("Duration", style="magenta")
90
+
91
+ for task in tasks:
92
+ status = task.get("status", "unknown")
93
+ status_color = {
94
+ "pending": "dim",
95
+ "running": "yellow",
96
+ "completed": "green",
97
+ "failed": "red",
98
+ "cancelled": "dim"
99
+ }.get(status, "white")
100
+
101
+ progress = f"{task.get('progress', 0) * 100:.0f}%"
102
+ duration = task.get("duration_seconds")
103
+ duration_str = f"{duration:.1f}s" if duration else "-"
104
+
105
+ table.add_row(
106
+ task.get("id", "?"),
107
+ task.get("name", "unnamed"),
108
+ f"[{status_color}]{status}[/{status_color}]",
109
+ progress,
110
+ duration_str
111
+ )
112
+
113
+ console.print(table)
114
+ except ImportError:
115
+ print("Background Tasks:")
116
+ for task in tasks:
117
+ print(f" {task.get('id')} - {task.get('name')} ({task.get('status')})")
118
+
119
+ async def get_status(self, task_id: str) -> Optional[dict]:
120
+ """
121
+ Get status of a specific task.
122
+
123
+ Args:
124
+ task_id: Task ID
125
+
126
+ Returns:
127
+ Task dictionary or None
128
+ """
129
+ runner = await self._get_runner()
130
+ task = runner.get_task(task_id)
131
+
132
+ if task is None:
133
+ self._print_error(f"Task not found: {task_id}")
134
+ return None
135
+
136
+ task_dict = task.to_dict()
137
+ self._print_task_details(task_dict)
138
+ return task_dict
139
+
140
+ def _print_task_details(self, task: dict):
141
+ """Print detailed task information."""
142
+ try:
143
+ from rich.console import Console
144
+ from rich.panel import Panel
145
+
146
+ console = Console()
147
+
148
+ status = task.get("status", "unknown")
149
+ status_color = {
150
+ "pending": "dim",
151
+ "running": "yellow",
152
+ "completed": "green",
153
+ "failed": "red",
154
+ "cancelled": "dim"
155
+ }.get(status, "white")
156
+
157
+ content = f"""
158
+ [bold]ID:[/bold] {task.get('id')}
159
+ [bold]Name:[/bold] {task.get('name')}
160
+ [bold]Status:[/bold] [{status_color}]{status}[/{status_color}]
161
+ [bold]Progress:[/bold] {task.get('progress', 0) * 100:.0f}%
162
+ [bold]Created:[/bold] {task.get('created_at')}
163
+ [bold]Started:[/bold] {task.get('started_at') or '-'}
164
+ [bold]Completed:[/bold] {task.get('completed_at') or '-'}
165
+ [bold]Duration:[/bold] {task.get('duration_seconds', 0):.2f}s
166
+ """
167
+ if task.get("error"):
168
+ content += f"[bold]Error:[/bold] [red]{task.get('error')}[/red]\n"
169
+
170
+ if task.get("result"):
171
+ result_str = str(task.get("result"))[:200]
172
+ content += f"[bold]Result:[/bold] {result_str}\n"
173
+
174
+ console.print(Panel(content.strip(), title=f"Task: {task.get('name')}"))
175
+ except ImportError:
176
+ print(f"Task: {task.get('name')}")
177
+ print(f" ID: {task.get('id')}")
178
+ print(f" Status: {task.get('status')}")
179
+ print(f" Progress: {task.get('progress', 0) * 100:.0f}%")
180
+
181
+ async def cancel_task(self, task_id: str) -> bool:
182
+ """
183
+ Cancel a running task.
184
+
185
+ Args:
186
+ task_id: Task ID to cancel
187
+
188
+ Returns:
189
+ True if cancelled
190
+ """
191
+ runner = await self._get_runner()
192
+ result = await runner.cancel_task(task_id)
193
+
194
+ if result:
195
+ self._print_success(f"Task cancelled: {task_id}")
196
+ else:
197
+ self._print_error(f"Could not cancel task: {task_id}")
198
+
199
+ return result
200
+
201
+ async def clear_completed(self) -> int:
202
+ """
203
+ Clear all completed tasks.
204
+
205
+ Returns:
206
+ Number of tasks cleared
207
+ """
208
+ runner = await self._get_runner()
209
+ count = len([t for t in runner.tasks if t.is_completed])
210
+ runner.clear_completed()
211
+
212
+ self._print_success(f"Cleared {count} completed tasks")
213
+ return count
214
+
215
+ def _print_success(self, message: str):
216
+ """Print success message."""
217
+ try:
218
+ from rich.console import Console
219
+ Console().print(f"[green]✓[/green] {message}")
220
+ except ImportError:
221
+ print(f"✓ {message}")
222
+
223
+ def _print_error(self, message: str):
224
+ """Print error message."""
225
+ try:
226
+ from rich.console import Console
227
+ Console().print(f"[red]✗[/red] {message}")
228
+ except ImportError:
229
+ print(f"✗ {message}")
230
+
231
+
232
+ def handle_background_command(args: List[str], verbose: bool = False):
233
+ """
234
+ Handle background CLI commands.
235
+
236
+ Usage:
237
+ praisonai background list [--status <status>] [--json] [--page N] [--page-size N]
238
+ praisonai background status <task_id> [--json]
239
+ praisonai background cancel <task_id> [--json]
240
+ praisonai background clear [--all] [--older-than SEC] [--json]
241
+ praisonai background submit --recipe <name> [--input JSON] [--session-id ID] [--timeout SEC] [--json]
242
+ """
243
+ import argparse
244
+ import json
245
+
246
+ parser = argparse.ArgumentParser(prog="praisonai background", description="Manage background tasks")
247
+ subparsers = parser.add_subparsers(dest="subcommand", help="Available commands")
248
+
249
+ # List command
250
+ list_parser = subparsers.add_parser("list", help="List background tasks")
251
+ list_parser.add_argument("--status", choices=["pending", "running", "completed", "failed", "cancelled"], help="Filter by status")
252
+ list_parser.add_argument("--json", dest="output_json", action="store_true", help="Output JSON")
253
+ list_parser.add_argument("--page", type=int, default=1, help="Page number")
254
+ list_parser.add_argument("--page-size", type=int, default=20, help="Tasks per page")
255
+
256
+ # Status command
257
+ status_parser = subparsers.add_parser("status", help="Get task status")
258
+ status_parser.add_argument("task_id", help="Task ID")
259
+ status_parser.add_argument("--json", dest="output_json", action="store_true", help="Output JSON")
260
+
261
+ # Cancel command
262
+ cancel_parser = subparsers.add_parser("cancel", help="Cancel a task")
263
+ cancel_parser.add_argument("task_id", help="Task ID")
264
+ cancel_parser.add_argument("--json", dest="output_json", action="store_true", help="Output JSON")
265
+
266
+ # Clear command
267
+ clear_parser = subparsers.add_parser("clear", help="Clear completed tasks")
268
+ clear_parser.add_argument("--all", action="store_true", help="Clear all tasks including running")
269
+ clear_parser.add_argument("--older-than", type=int, help="Clear tasks older than N seconds")
270
+ clear_parser.add_argument("--json", dest="output_json", action="store_true", help="Output JSON")
271
+
272
+ # Submit command (NEW - for recipe background submission)
273
+ submit_parser = subparsers.add_parser("submit", help="Submit a recipe as background task")
274
+ submit_parser.add_argument("--recipe", required=True, dest="recipe_name", help="Recipe name to execute")
275
+ submit_parser.add_argument("--input", "-i", dest="input_data", help="Input data as JSON string")
276
+ submit_parser.add_argument("--config", "-c", help="Config overrides as JSON string")
277
+ submit_parser.add_argument("--session-id", "-s", help="Session ID for conversation continuity")
278
+ submit_parser.add_argument("--timeout", type=int, default=300, help="Timeout in seconds (default: 300)")
279
+ submit_parser.add_argument("--json", dest="output_json", action="store_true", help="Output JSON")
280
+
281
+ if not args:
282
+ parser.print_help()
283
+ return
284
+
285
+ # Handle legacy help
286
+ if args[0] in ["help", "--help", "-h"]:
287
+ parser.print_help()
288
+ return
289
+
290
+ parsed = parser.parse_args(args)
291
+
292
+ if not parsed.subcommand:
293
+ parser.print_help()
294
+ return
295
+
296
+ handler = BackgroundHandler(verbose=verbose)
297
+
298
+ try:
299
+ if parsed.subcommand == "list":
300
+ asyncio.run(handler.list_tasks(status=parsed.status))
301
+
302
+ elif parsed.subcommand == "status":
303
+ asyncio.run(handler.get_status(parsed.task_id))
304
+
305
+ elif parsed.subcommand == "cancel":
306
+ asyncio.run(handler.cancel_task(parsed.task_id))
307
+
308
+ elif parsed.subcommand == "clear":
309
+ asyncio.run(handler.clear_completed())
310
+
311
+ elif parsed.subcommand == "submit":
312
+ # Parse input and config
313
+ input_data = None
314
+ if parsed.input_data:
315
+ try:
316
+ input_data = json.loads(parsed.input_data)
317
+ except json.JSONDecodeError:
318
+ input_data = {"input": parsed.input_data}
319
+
320
+ config = None
321
+ if parsed.config:
322
+ try:
323
+ config = json.loads(parsed.config)
324
+ except json.JSONDecodeError:
325
+ print("Error: --config must be valid JSON")
326
+ return
327
+
328
+ # Submit recipe as background task
329
+ from praisonai.recipe.operations import run_background
330
+
331
+ task = run_background(
332
+ parsed.recipe_name,
333
+ input=input_data,
334
+ config=config,
335
+ session_id=parsed.session_id,
336
+ timeout_sec=parsed.timeout,
337
+ )
338
+
339
+ if parsed.output_json:
340
+ print(json.dumps({
341
+ "ok": True,
342
+ "task_id": task.task_id,
343
+ "recipe": task.recipe_name,
344
+ "session_id": task.session_id,
345
+ }))
346
+ else:
347
+ print(f"✓ Recipe '{parsed.recipe_name}' submitted to background")
348
+ print(f" Task ID: {task.task_id}")
349
+ print(f" Session: {task.session_id}")
350
+ print(f"\nCheck status with: praisonai background status {task.task_id}")
351
+
352
+ except Exception as e:
353
+ if getattr(parsed, 'output_json', False):
354
+ print(json.dumps({"ok": False, "error": str(e)}))
355
+ else:
356
+ print(f"✗ Error: {e}")
@@ -0,0 +1,168 @@
1
+ """
2
+ Base handler class for CLI features.
3
+
4
+ All CLI feature handlers inherit from this base class to ensure
5
+ consistent interface and behavior.
6
+ """
7
+
8
+ from abc import ABC, abstractmethod
9
+ from typing import Any, Dict, List
10
+ import logging
11
+
12
+ logger = logging.getLogger(__name__)
13
+
14
+
15
+ class BaseHandler(ABC):
16
+ """
17
+ Base class for all CLI feature handlers.
18
+
19
+ Provides common functionality and interface for feature handlers.
20
+ Each handler is responsible for a specific CLI feature.
21
+ """
22
+
23
+ def __init__(self, verbose: bool = False):
24
+ """
25
+ Initialize the handler.
26
+
27
+ Args:
28
+ verbose: Enable verbose output
29
+ """
30
+ self.verbose = verbose
31
+ self._initialized = False
32
+
33
+ @property
34
+ @abstractmethod
35
+ def feature_name(self) -> str:
36
+ """Return the name of this feature."""
37
+ pass
38
+
39
+ @property
40
+ def is_available(self) -> bool:
41
+ """Check if the feature dependencies are available."""
42
+ return True
43
+
44
+ def log(self, message: str, level: str = "info"):
45
+ """Log a message if verbose mode is enabled."""
46
+ if self.verbose:
47
+ getattr(logger, level)(f"[{self.feature_name}] {message}")
48
+
49
+ def print_status(self, message: str, status: str = "info"):
50
+ """Print a status message with color coding."""
51
+ from rich import print as rprint
52
+
53
+ colors = {
54
+ "info": "cyan",
55
+ "success": "green",
56
+ "warning": "yellow",
57
+ "error": "red"
58
+ }
59
+ color = colors.get(status, "white")
60
+ rprint(f"[{color}]{message}[/{color}]")
61
+
62
+ def check_dependencies(self) -> tuple[bool, str]:
63
+ """
64
+ Check if required dependencies are installed.
65
+
66
+ Returns:
67
+ Tuple of (available, error_message)
68
+ """
69
+ return True, ""
70
+
71
+ @abstractmethod
72
+ def execute(self, *args, **kwargs) -> Any:
73
+ """
74
+ Execute the feature's main functionality.
75
+
76
+ This method must be implemented by each handler.
77
+ """
78
+ pass
79
+
80
+
81
+ class CommandHandler(BaseHandler):
82
+ """
83
+ Base class for CLI command handlers (e.g., 'praisonai knowledge').
84
+
85
+ Command handlers process subcommands like:
86
+ - praisonai <command> <action> [args]
87
+ """
88
+
89
+ @abstractmethod
90
+ def get_actions(self) -> List[str]:
91
+ """Return list of supported actions for this command."""
92
+ pass
93
+
94
+ def get_help_text(self) -> str:
95
+ """Return help text for this command."""
96
+ return f"Available actions: {', '.join(self.get_actions())}"
97
+
98
+ def execute(self, action: str, action_args: List[str], **kwargs) -> Any:
99
+ """
100
+ Execute a command action.
101
+
102
+ Args:
103
+ action: The action to perform
104
+ action_args: Arguments for the action
105
+ **kwargs: Additional keyword arguments
106
+ """
107
+ if action == 'help' or action == '--help':
108
+ self.print_help()
109
+ return
110
+
111
+ method_name = f"action_{action.replace('-', '_')}"
112
+ if hasattr(self, method_name):
113
+ return getattr(self, method_name)(action_args, **kwargs)
114
+ else:
115
+ self.print_status(f"Unknown action: {action}", "error")
116
+ self.print_help()
117
+
118
+ def print_help(self):
119
+ """Print help for this command."""
120
+ from rich import print as rprint
121
+ rprint(f"[bold]{self.feature_name.title()} Commands:[/bold]")
122
+ rprint(self.get_help_text())
123
+
124
+
125
+ class FlagHandler(BaseHandler):
126
+ """
127
+ Base class for CLI flag handlers (e.g., '--guardrail').
128
+
129
+ Flag handlers modify agent behavior or add functionality
130
+ when a specific flag is provided.
131
+ """
132
+
133
+ @property
134
+ @abstractmethod
135
+ def flag_name(self) -> str:
136
+ """Return the flag name (without --)."""
137
+ pass
138
+
139
+ @property
140
+ def flag_help(self) -> str:
141
+ """Return help text for this flag."""
142
+ return f"Enable {self.feature_name}"
143
+
144
+ def apply_to_agent_config(self, config: Dict[str, Any], flag_value: Any) -> Dict[str, Any]:
145
+ """
146
+ Apply this flag's configuration to an agent config.
147
+
148
+ Args:
149
+ config: The agent configuration dictionary
150
+ flag_value: The value of the flag
151
+
152
+ Returns:
153
+ Modified agent configuration
154
+ """
155
+ return config
156
+
157
+ def post_process_result(self, result: Any, flag_value: Any) -> Any:
158
+ """
159
+ Post-process the agent result.
160
+
161
+ Args:
162
+ result: The agent's output
163
+ flag_value: The value of the flag
164
+
165
+ Returns:
166
+ Processed result
167
+ """
168
+ return result