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,566 @@
1
+ """
2
+ CLI Commands for PraisonAI TUI and Queue.
3
+
4
+ Provides Typer-based CLI commands for:
5
+ - praison tui - Launch interactive TUI
6
+ - praison run - Execute single task
7
+ - praison queue ls/cancel/retry/clear
8
+ - praison session ls/resume
9
+ """
10
+
11
+ import asyncio
12
+ import json
13
+ import os
14
+ import sys
15
+ from typing import Optional
16
+
17
+ try:
18
+ import typer
19
+ from rich.console import Console
20
+ from rich.table import Table
21
+ from rich.panel import Panel
22
+ TYPER_AVAILABLE = True
23
+ except ImportError:
24
+ TYPER_AVAILABLE = False
25
+ typer = None
26
+
27
+ console = Console() if TYPER_AVAILABLE else None
28
+
29
+
30
+ def create_tui_app():
31
+ """Create the TUI CLI app."""
32
+ if not TYPER_AVAILABLE:
33
+ return None
34
+
35
+ app = typer.Typer(
36
+ name="tui",
37
+ help="PraisonAI TUI and Queue commands",
38
+ no_args_is_help=True,
39
+ )
40
+
41
+ @app.command("launch")
42
+ def tui_launch(
43
+ workspace: Optional[str] = typer.Option(
44
+ None, "--workspace", "-w",
45
+ help="Workspace directory"
46
+ ),
47
+ session: Optional[str] = typer.Option(
48
+ None, "--session", "-s",
49
+ help="Resume session ID"
50
+ ),
51
+ model: Optional[str] = typer.Option(
52
+ None, "--model", "-m",
53
+ help="Default model"
54
+ ),
55
+ agent: Optional[str] = typer.Option(
56
+ None, "--agent", "-a",
57
+ help="Agent config file (YAML)"
58
+ ),
59
+ no_acp: bool = typer.Option(
60
+ False, "--no-acp",
61
+ help="Disable ACP tools (file operations with plan/approve/apply)"
62
+ ),
63
+ no_lsp: bool = typer.Option(
64
+ False, "--no-lsp",
65
+ help="Disable LSP tools (code intelligence: symbols, definitions)"
66
+ ),
67
+ ):
68
+ """Launch the interactive TUI with ACP + LSP tools enabled by default."""
69
+ try:
70
+ from .app import run_tui
71
+ except ImportError:
72
+ console.print(
73
+ "[red]Textual is required for TUI. Install with:[/red]\n"
74
+ " pip install praisonai[tui]"
75
+ )
76
+ raise typer.Exit(1)
77
+
78
+ # Load agent config if provided
79
+ agent_config = {}
80
+ if agent:
81
+ import yaml
82
+ with open(agent, "r") as f:
83
+ agent_config = yaml.safe_load(f)
84
+
85
+ run_tui(
86
+ workspace=workspace,
87
+ session_id=session,
88
+ model=model,
89
+ agent_config=agent_config,
90
+ enable_acp=not no_acp,
91
+ enable_lsp=not no_lsp,
92
+ )
93
+
94
+ return app
95
+
96
+
97
+ def create_queue_app():
98
+ """Create the queue CLI app."""
99
+ if not TYPER_AVAILABLE:
100
+ return None
101
+
102
+ app = typer.Typer(
103
+ name="queue",
104
+ help="Queue management commands",
105
+ no_args_is_help=True,
106
+ )
107
+
108
+ @app.command("ls")
109
+ def queue_ls(
110
+ state: Optional[str] = typer.Option(
111
+ None, "--state", "-s",
112
+ help="Filter by state (queued, running, succeeded, failed, cancelled)"
113
+ ),
114
+ session: Optional[str] = typer.Option(
115
+ None, "--session",
116
+ help="Filter by session ID"
117
+ ),
118
+ limit: int = typer.Option(
119
+ 20, "--limit", "-n",
120
+ help="Maximum number of results"
121
+ ),
122
+ json_output: bool = typer.Option(
123
+ False, "--json", "-j",
124
+ help="Output as JSON"
125
+ ),
126
+ ):
127
+ """List queued runs."""
128
+ from ..queue import QueuePersistence, RunState
129
+
130
+ persistence = QueuePersistence()
131
+ persistence.initialize()
132
+
133
+ # Parse state filter
134
+ state_filter = None
135
+ if state:
136
+ try:
137
+ state_filter = RunState(state.lower())
138
+ except ValueError:
139
+ console.print(f"[red]Invalid state: {state}[/red]")
140
+ raise typer.Exit(1)
141
+
142
+ runs = persistence.list_runs(
143
+ state=state_filter,
144
+ session_id=session,
145
+ limit=limit,
146
+ )
147
+
148
+ if json_output:
149
+ output = [r.to_dict() for r in runs]
150
+ console.print(json.dumps(output, indent=2, default=str))
151
+ return
152
+
153
+ if not runs:
154
+ console.print("[dim]No runs found.[/dim]")
155
+ return
156
+
157
+ # Create table
158
+ table = Table(title="Queue Runs")
159
+ table.add_column("ID", style="cyan")
160
+ table.add_column("Agent", style="green")
161
+ table.add_column("Input", max_width=30)
162
+ table.add_column("State", style="yellow")
163
+ table.add_column("Priority")
164
+ table.add_column("Wait", style="dim")
165
+ table.add_column("Duration", style="dim")
166
+
167
+ for run in runs:
168
+ state_style = {
169
+ "queued": "yellow",
170
+ "running": "green",
171
+ "succeeded": "cyan",
172
+ "failed": "red",
173
+ "cancelled": "dim",
174
+ }.get(run.state.value, "")
175
+
176
+ input_preview = run.input_content[:27] + "..." if len(run.input_content) > 30 else run.input_content
177
+
178
+ table.add_row(
179
+ run.run_id[:8],
180
+ run.agent_name,
181
+ input_preview,
182
+ f"[{state_style}]{run.state.value}[/{state_style}]",
183
+ run.priority.name.lower(),
184
+ f"{run.wait_seconds:.1f}s" if run.wait_seconds else "-",
185
+ f"{run.duration_seconds:.1f}s" if run.duration_seconds else "-",
186
+ )
187
+
188
+ console.print(table)
189
+ persistence.close()
190
+
191
+ @app.command("cancel")
192
+ def queue_cancel(
193
+ run_id: str = typer.Argument(..., help="Run ID to cancel"),
194
+ ):
195
+ """Cancel a queued or running run."""
196
+ from ..queue import QueuePersistence, RunState
197
+
198
+ persistence = QueuePersistence()
199
+ persistence.initialize()
200
+
201
+ # Find the run
202
+ run = persistence.load_run(run_id)
203
+ if not run:
204
+ # Try partial match
205
+ runs = persistence.list_runs(limit=100)
206
+ matches = [r for r in runs if r.run_id.startswith(run_id)]
207
+ if len(matches) == 1:
208
+ run = matches[0]
209
+ elif len(matches) > 1:
210
+ console.print(f"[yellow]Multiple matches for '{run_id}':[/yellow]")
211
+ for r in matches:
212
+ console.print(f" {r.run_id}")
213
+ raise typer.Exit(1)
214
+ else:
215
+ console.print(f"[red]Run not found: {run_id}[/red]")
216
+ raise typer.Exit(1)
217
+
218
+ if run.state.is_terminal():
219
+ console.print(f"[yellow]Run {run.run_id[:8]} is already {run.state.value}[/yellow]")
220
+ raise typer.Exit(1)
221
+
222
+ # Update state
223
+ persistence.update_run_state(run.run_id, RunState.CANCELLED)
224
+ console.print(f"[green]Cancelled run: {run.run_id[:8]}[/green]")
225
+ persistence.close()
226
+
227
+ @app.command("retry")
228
+ def queue_retry(
229
+ run_id: str = typer.Argument(..., help="Run ID to retry"),
230
+ ):
231
+ """Retry a failed run."""
232
+ from ..queue import QueuePersistence, QueuedRun, RunState
233
+ import uuid
234
+
235
+ persistence = QueuePersistence()
236
+ persistence.initialize()
237
+
238
+ # Find the run
239
+ run = persistence.load_run(run_id)
240
+ if not run:
241
+ runs = persistence.list_runs(limit=100)
242
+ matches = [r for r in runs if r.run_id.startswith(run_id)]
243
+ if len(matches) == 1:
244
+ run = matches[0]
245
+ else:
246
+ console.print(f"[red]Run not found: {run_id}[/red]")
247
+ raise typer.Exit(1)
248
+
249
+ if run.state != RunState.FAILED:
250
+ console.print(f"[yellow]Can only retry failed runs (current: {run.state.value})[/yellow]")
251
+ raise typer.Exit(1)
252
+
253
+ if run.retry_count >= run.max_retries:
254
+ console.print(f"[yellow]Max retries reached ({run.retry_count}/{run.max_retries})[/yellow]")
255
+ raise typer.Exit(1)
256
+
257
+ # Create new run
258
+ new_run = QueuedRun(
259
+ run_id=str(uuid.uuid4())[:8],
260
+ agent_name=run.agent_name,
261
+ input_content=run.input_content,
262
+ state=RunState.QUEUED,
263
+ priority=run.priority,
264
+ session_id=run.session_id,
265
+ workspace=run.workspace,
266
+ retry_count=run.retry_count + 1,
267
+ max_retries=run.max_retries,
268
+ parent_run_id=run.run_id,
269
+ config=run.config,
270
+ )
271
+
272
+ persistence.save_run(new_run)
273
+ console.print(f"[green]Created retry run: {new_run.run_id} (from {run.run_id[:8]})[/green]")
274
+ persistence.close()
275
+
276
+ @app.command("clear")
277
+ def queue_clear(
278
+ force: bool = typer.Option(
279
+ False, "--force", "-f",
280
+ help="Skip confirmation"
281
+ ),
282
+ ):
283
+ """Clear all queued runs."""
284
+ from ..queue import QueuePersistence, RunState
285
+
286
+ if not force:
287
+ confirm = typer.confirm("Clear all queued runs?")
288
+ if not confirm:
289
+ raise typer.Abort()
290
+
291
+ persistence = QueuePersistence()
292
+ persistence.initialize()
293
+
294
+ # Get queued runs
295
+ runs = persistence.list_runs(state=RunState.QUEUED, limit=1000)
296
+
297
+ count = 0
298
+ for run in runs:
299
+ persistence.update_run_state(run.run_id, RunState.CANCELLED)
300
+ count += 1
301
+
302
+ console.print(f"[green]Cleared {count} queued runs[/green]")
303
+ persistence.close()
304
+
305
+ @app.command("stats")
306
+ def queue_stats(
307
+ session: Optional[str] = typer.Option(
308
+ None, "--session",
309
+ help="Filter by session ID"
310
+ ),
311
+ ):
312
+ """Show queue statistics."""
313
+ from ..queue import QueuePersistence
314
+
315
+ persistence = QueuePersistence()
316
+ persistence.initialize()
317
+
318
+ stats = persistence.get_stats(session)
319
+
320
+ console.print(Panel(
321
+ f"""
322
+ [bold]Queue Statistics[/bold]
323
+
324
+ Queued: {stats.queued_count}
325
+ Running: {stats.running_count}
326
+ Succeeded: {stats.succeeded_count}
327
+ Failed: {stats.failed_count}
328
+ Cancelled: {stats.cancelled_count}
329
+
330
+ Total Runs: {stats.total_runs}
331
+ Avg Wait: {stats.avg_wait_seconds:.1f}s
332
+ Avg Duration: {stats.avg_duration_seconds:.1f}s
333
+ """,
334
+ title="Queue Stats"
335
+ ))
336
+ persistence.close()
337
+
338
+ return app
339
+
340
+
341
+ def create_session_app():
342
+ """Create the session CLI app."""
343
+ if not TYPER_AVAILABLE:
344
+ return None
345
+
346
+ app = typer.Typer(
347
+ name="session",
348
+ help="Session management commands",
349
+ no_args_is_help=True,
350
+ )
351
+
352
+ @app.command("ls")
353
+ def session_ls(
354
+ limit: int = typer.Option(
355
+ 20, "--limit", "-n",
356
+ help="Maximum number of results"
357
+ ),
358
+ ):
359
+ """List recent sessions."""
360
+ from ..queue import QueuePersistence
361
+ from datetime import datetime
362
+
363
+ persistence = QueuePersistence()
364
+ persistence.initialize()
365
+
366
+ sessions = persistence.list_sessions(limit=limit)
367
+
368
+ if not sessions:
369
+ console.print("[dim]No sessions found.[/dim]")
370
+ return
371
+
372
+ table = Table(title="Sessions")
373
+ table.add_column("ID", style="cyan")
374
+ table.add_column("User")
375
+ table.add_column("Created", style="dim")
376
+ table.add_column("Updated", style="dim")
377
+
378
+ for session in sessions:
379
+ created = datetime.fromtimestamp(session["created_at"]).strftime("%Y-%m-%d %H:%M")
380
+ updated = datetime.fromtimestamp(session["updated_at"]).strftime("%Y-%m-%d %H:%M")
381
+
382
+ table.add_row(
383
+ session["session_id"][:8],
384
+ session.get("user_id", "-"),
385
+ created,
386
+ updated,
387
+ )
388
+
389
+ console.print(table)
390
+ persistence.close()
391
+
392
+ @app.command("resume")
393
+ def session_resume(
394
+ session_id: str = typer.Argument(..., help="Session ID to resume"),
395
+ ):
396
+ """Resume a session in TUI."""
397
+ try:
398
+ from .app import run_tui
399
+ except ImportError:
400
+ console.print(
401
+ "[red]Textual is required for TUI. Install with:[/red]\n"
402
+ " pip install praisonai[tui]"
403
+ )
404
+ raise typer.Exit(1)
405
+
406
+ run_tui(session_id=session_id)
407
+
408
+ return app
409
+
410
+
411
+ def create_run_command():
412
+ """Create the run command."""
413
+ if not TYPER_AVAILABLE:
414
+ return None
415
+
416
+ def run_command(
417
+ prompt: str = typer.Argument(..., help="Prompt to execute"),
418
+ agent: Optional[str] = typer.Option(
419
+ None, "--agent", "-a",
420
+ help="Agent config file (YAML)"
421
+ ),
422
+ model: Optional[str] = typer.Option(
423
+ None, "--model", "-m",
424
+ help="Model to use"
425
+ ),
426
+ stream: bool = typer.Option(
427
+ True, "--stream/--no-stream",
428
+ help="Stream output"
429
+ ),
430
+ priority: str = typer.Option(
431
+ "normal", "--priority", "-p",
432
+ help="Run priority (low, normal, high, urgent)"
433
+ ),
434
+ ):
435
+ """Run a single agent task."""
436
+ from ..queue import QueueManager, QueueConfig, RunPriority
437
+
438
+ # Parse priority
439
+ try:
440
+ run_priority = RunPriority.from_string(priority)
441
+ except (ValueError, KeyError):
442
+ console.print(f"[red]Invalid priority: {priority}[/red]")
443
+ raise typer.Exit(1)
444
+
445
+ # Load agent config
446
+ agent_config = {}
447
+ if agent:
448
+ import yaml
449
+ with open(agent, "r") as f:
450
+ agent_config = yaml.safe_load(f)
451
+
452
+ # Set model
453
+ if model:
454
+ agent_config["model"] = model
455
+
456
+ async def execute():
457
+ output_chunks = []
458
+
459
+ async def on_output(run_id: str, chunk: str):
460
+ output_chunks.append(chunk)
461
+ if stream:
462
+ console.print(chunk, end="")
463
+
464
+ async def on_complete(run_id: str, run):
465
+ if not stream:
466
+ console.print(run.output_content or "".join(output_chunks))
467
+
468
+ async def on_error(run_id: str, error: Exception):
469
+ console.print(f"\n[red]Error: {error}[/red]")
470
+
471
+ config = QueueConfig(enable_persistence=False)
472
+ manager = QueueManager(
473
+ config=config,
474
+ on_output=on_output,
475
+ on_complete=on_complete,
476
+ on_error=on_error,
477
+ )
478
+
479
+ await manager.start(recover=False)
480
+
481
+ try:
482
+ run_id = await manager.submit(
483
+ input_content=prompt,
484
+ agent_name=agent_config.get("name", "Assistant"),
485
+ priority=run_priority,
486
+ config={"agent_config": agent_config},
487
+ )
488
+
489
+ # Wait for completion
490
+ while True:
491
+ run = manager.get_run(run_id)
492
+ if run and run.state.is_terminal():
493
+ break
494
+ await asyncio.sleep(0.1)
495
+
496
+ if stream:
497
+ console.print() # Newline after streaming
498
+
499
+ finally:
500
+ await manager.stop()
501
+
502
+ asyncio.run(execute())
503
+
504
+ return run_command
505
+
506
+
507
+ # Main CLI integration
508
+ def register_tui_commands(app):
509
+ """Register TUI commands with the main CLI app."""
510
+ if not TYPER_AVAILABLE:
511
+ return
512
+
513
+ tui_app = create_tui_app()
514
+ queue_app = create_queue_app()
515
+ session_app = create_session_app()
516
+ run_cmd = create_run_command()
517
+
518
+ if tui_app:
519
+ app.add_typer(tui_app, name="tui")
520
+ if queue_app:
521
+ app.add_typer(queue_app, name="queue")
522
+ if session_app:
523
+ app.add_typer(session_app, name="session")
524
+ if run_cmd:
525
+ app.command("run")(run_cmd)
526
+
527
+
528
+ # Standalone entry point
529
+ def main():
530
+ """Main entry point for TUI CLI."""
531
+ if not TYPER_AVAILABLE:
532
+ print("Typer is required. Install with: pip install typer")
533
+ sys.exit(1)
534
+
535
+ app = typer.Typer(
536
+ name="praison-tui",
537
+ help="PraisonAI TUI and Queue CLI",
538
+ )
539
+
540
+ register_tui_commands(app)
541
+
542
+ # Add direct tui command
543
+ @app.callback(invoke_without_command=True)
544
+ def default(
545
+ ctx: typer.Context,
546
+ workspace: Optional[str] = typer.Option(None, "--workspace", "-w"),
547
+ session: Optional[str] = typer.Option(None, "--session", "-s"),
548
+ model: Optional[str] = typer.Option(None, "--model", "-m"),
549
+ ):
550
+ """Launch TUI if no subcommand given."""
551
+ if ctx.invoked_subcommand is None:
552
+ try:
553
+ from .app import run_tui
554
+ run_tui(workspace=workspace, session_id=session, model=model)
555
+ except ImportError:
556
+ console.print(
557
+ "[red]Textual is required for TUI. Install with:[/red]\n"
558
+ " pip install praisonai[tui]"
559
+ )
560
+ raise typer.Exit(1)
561
+
562
+ app()
563
+
564
+
565
+ if __name__ == "__main__":
566
+ main()