praisonai-code 0.0.1__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 (309) hide show
  1. praisonai_code/__init__.py +17 -0
  2. praisonai_code/cli/__init__.py +12 -0
  3. praisonai_code/cli/_forward_shim.py +10 -0
  4. praisonai_code/cli/_paths.py +88 -0
  5. praisonai_code/cli/_warnings.py +58 -0
  6. praisonai_code/cli/app.py +757 -0
  7. praisonai_code/cli/approval_backend.py +272 -0
  8. praisonai_code/cli/branding.py +94 -0
  9. praisonai_code/cli/commands/__init__.py +114 -0
  10. praisonai_code/cli/commands/acp.py +80 -0
  11. praisonai_code/cli/commands/agent.py +116 -0
  12. praisonai_code/cli/commands/agents.py +80 -0
  13. praisonai_code/cli/commands/app.py +139 -0
  14. praisonai_code/cli/commands/attach.py +95 -0
  15. praisonai_code/cli/commands/audit.py +102 -0
  16. praisonai_code/cli/commands/auth.py +508 -0
  17. praisonai_code/cli/commands/batch.py +848 -0
  18. praisonai_code/cli/commands/benchmark.py +286 -0
  19. praisonai_code/cli/commands/browser.py +299 -0
  20. praisonai_code/cli/commands/call.py +45 -0
  21. praisonai_code/cli/commands/chat.py +332 -0
  22. praisonai_code/cli/commands/checkpoint.py +170 -0
  23. praisonai_code/cli/commands/code.py +276 -0
  24. praisonai_code/cli/commands/command.py +114 -0
  25. praisonai_code/cli/commands/commit.py +47 -0
  26. praisonai_code/cli/commands/completion.py +333 -0
  27. praisonai_code/cli/commands/config.py +681 -0
  28. praisonai_code/cli/commands/context.py +414 -0
  29. praisonai_code/cli/commands/daemon.py +203 -0
  30. praisonai_code/cli/commands/debug.py +142 -0
  31. praisonai_code/cli/commands/deploy.py +71 -0
  32. praisonai_code/cli/commands/diag.py +55 -0
  33. praisonai_code/cli/commands/docs.py +1575 -0
  34. praisonai_code/cli/commands/doctor.py +332 -0
  35. praisonai_code/cli/commands/endpoints.py +51 -0
  36. praisonai_code/cli/commands/environment.py +179 -0
  37. praisonai_code/cli/commands/eval.py +131 -0
  38. praisonai_code/cli/commands/examples.py +953 -0
  39. praisonai_code/cli/commands/flow.py +436 -0
  40. praisonai_code/cli/commands/github.py +752 -0
  41. praisonai_code/cli/commands/hooks.py +74 -0
  42. praisonai_code/cli/commands/init.py +174 -0
  43. praisonai_code/cli/commands/knowledge.py +440 -0
  44. praisonai_code/cli/commands/langextract.py +120 -0
  45. praisonai_code/cli/commands/langfuse.py +984 -0
  46. praisonai_code/cli/commands/loop.py +211 -0
  47. praisonai_code/cli/commands/lsp.py +112 -0
  48. praisonai_code/cli/commands/managed.py +659 -0
  49. praisonai_code/cli/commands/mcp.py +763 -0
  50. praisonai_code/cli/commands/memory.py +298 -0
  51. praisonai_code/cli/commands/models.py +264 -0
  52. praisonai_code/cli/commands/n8n.py +326 -0
  53. praisonai_code/cli/commands/obs.py +19 -0
  54. praisonai_code/cli/commands/package.py +76 -0
  55. praisonai_code/cli/commands/paths.py +106 -0
  56. praisonai_code/cli/commands/permissions.py +272 -0
  57. praisonai_code/cli/commands/plugins.py +609 -0
  58. praisonai_code/cli/commands/port.py +530 -0
  59. praisonai_code/cli/commands/profile.py +466 -0
  60. praisonai_code/cli/commands/publish.py +193 -0
  61. praisonai_code/cli/commands/rag.py +913 -0
  62. praisonai_code/cli/commands/realtime.py +52 -0
  63. praisonai_code/cli/commands/recipe.py +684 -0
  64. praisonai_code/cli/commands/registry.py +59 -0
  65. praisonai_code/cli/commands/replay.py +830 -0
  66. praisonai_code/cli/commands/research.py +49 -0
  67. praisonai_code/cli/commands/retrieval.py +377 -0
  68. praisonai_code/cli/commands/rules.py +71 -0
  69. praisonai_code/cli/commands/run.py +1573 -0
  70. praisonai_code/cli/commands/sandbox.py +371 -0
  71. praisonai_code/cli/commands/schedule.py +529 -0
  72. praisonai_code/cli/commands/serve.py +690 -0
  73. praisonai_code/cli/commands/session.py +450 -0
  74. praisonai_code/cli/commands/setup.py +174 -0
  75. praisonai_code/cli/commands/skills.py +545 -0
  76. praisonai_code/cli/commands/standardise.py +711 -0
  77. praisonai_code/cli/commands/templates.py +54 -0
  78. praisonai_code/cli/commands/test.py +558 -0
  79. praisonai_code/cli/commands/todo.py +74 -0
  80. praisonai_code/cli/commands/tools.py +205 -0
  81. praisonai_code/cli/commands/traces.py +145 -0
  82. praisonai_code/cli/commands/tracker.py +852 -0
  83. praisonai_code/cli/commands/train.py +613 -0
  84. praisonai_code/cli/commands/ui.py +172 -0
  85. praisonai_code/cli/commands/up.py +354 -0
  86. praisonai_code/cli/commands/validate.py +291 -0
  87. praisonai_code/cli/commands/version.py +101 -0
  88. praisonai_code/cli/commands/workflow.py +97 -0
  89. praisonai_code/cli/config_loader.py +437 -0
  90. praisonai_code/cli/configuration/__init__.py +27 -0
  91. praisonai_code/cli/configuration/config.schema.json +57 -0
  92. praisonai_code/cli/configuration/credentials.py +446 -0
  93. praisonai_code/cli/configuration/loader.py +364 -0
  94. praisonai_code/cli/configuration/model_resolver.py +161 -0
  95. praisonai_code/cli/configuration/oauth.py +389 -0
  96. praisonai_code/cli/configuration/paths.py +224 -0
  97. praisonai_code/cli/configuration/resolver.py +687 -0
  98. praisonai_code/cli/configuration/schema.py +317 -0
  99. praisonai_code/cli/execution/__init__.py +99 -0
  100. praisonai_code/cli/execution/core.py +208 -0
  101. praisonai_code/cli/execution/profiler.py +898 -0
  102. praisonai_code/cli/execution/request.py +85 -0
  103. praisonai_code/cli/execution/result.py +74 -0
  104. praisonai_code/cli/fallback_schema.py +416 -0
  105. praisonai_code/cli/features/__init__.py +278 -0
  106. praisonai_code/cli/features/_endpoint_registry.py +64 -0
  107. praisonai_code/cli/features/_search_registry.py +43 -0
  108. praisonai_code/cli/features/acp.py +236 -0
  109. praisonai_code/cli/features/action_orchestrator.py +576 -0
  110. praisonai_code/cli/features/agent_scheduler.py +773 -0
  111. praisonai_code/cli/features/agent_tools.py +603 -0
  112. praisonai_code/cli/features/agents.py +397 -0
  113. praisonai_code/cli/features/at_mentions.py +471 -0
  114. praisonai_code/cli/features/audit_cli.py +270 -0
  115. praisonai_code/cli/features/auto_memory.py +182 -0
  116. praisonai_code/cli/features/auto_mode.py +552 -0
  117. praisonai_code/cli/features/autonomy_mode.py +546 -0
  118. praisonai_code/cli/features/background.py +356 -0
  119. praisonai_code/cli/features/base.py +168 -0
  120. praisonai_code/cli/features/benchmark.py +1462 -0
  121. praisonai_code/cli/features/capabilities.py +1326 -0
  122. praisonai_code/cli/features/checkpoints.py +345 -0
  123. praisonai_code/cli/features/cli_profiler.py +335 -0
  124. praisonai_code/cli/features/code_intelligence.py +666 -0
  125. praisonai_code/cli/features/compaction.py +294 -0
  126. praisonai_code/cli/features/compare.py +534 -0
  127. praisonai_code/cli/features/config_hierarchy.py +366 -0
  128. praisonai_code/cli/features/context_manager.py +597 -0
  129. praisonai_code/cli/features/cost_tracker.py +514 -0
  130. praisonai_code/cli/features/csv_test_runner.py +736 -0
  131. praisonai_code/cli/features/custom_definitions.py +790 -0
  132. praisonai_code/cli/features/debug.py +810 -0
  133. praisonai_code/cli/features/deploy.py +605 -0
  134. praisonai_code/cli/features/diag.py +289 -0
  135. praisonai_code/cli/features/display_jsonl.py +173 -0
  136. praisonai_code/cli/features/doctor/__init__.py +63 -0
  137. praisonai_code/cli/features/doctor/checks/__init__.py +29 -0
  138. praisonai_code/cli/features/doctor/checks/acp_checks.py +220 -0
  139. praisonai_code/cli/features/doctor/checks/bot_checks.py +340 -0
  140. praisonai_code/cli/features/doctor/checks/config_checks.py +373 -0
  141. praisonai_code/cli/features/doctor/checks/db_checks.py +366 -0
  142. praisonai_code/cli/features/doctor/checks/env_checks.py +637 -0
  143. praisonai_code/cli/features/doctor/checks/gateway_checks.py +387 -0
  144. praisonai_code/cli/features/doctor/checks/lsp_checks.py +231 -0
  145. praisonai_code/cli/features/doctor/checks/mcp_checks.py +367 -0
  146. praisonai_code/cli/features/doctor/checks/memory_checks.py +268 -0
  147. praisonai_code/cli/features/doctor/checks/network_checks.py +251 -0
  148. praisonai_code/cli/features/doctor/checks/obs_checks.py +328 -0
  149. praisonai_code/cli/features/doctor/checks/packaging_checks.py +422 -0
  150. praisonai_code/cli/features/doctor/checks/performance_checks.py +235 -0
  151. praisonai_code/cli/features/doctor/checks/permissions_checks.py +259 -0
  152. praisonai_code/cli/features/doctor/checks/runtime_checks.py +650 -0
  153. praisonai_code/cli/features/doctor/checks/runtime_migration_checks.py +220 -0
  154. praisonai_code/cli/features/doctor/checks/selftest_checks.py +322 -0
  155. praisonai_code/cli/features/doctor/checks/serve_checks.py +426 -0
  156. praisonai_code/cli/features/doctor/checks/skills_checks.py +327 -0
  157. praisonai_code/cli/features/doctor/checks/tools_checks.py +371 -0
  158. praisonai_code/cli/features/doctor/engine.py +266 -0
  159. praisonai_code/cli/features/doctor/formatters.py +377 -0
  160. praisonai_code/cli/features/doctor/handler.py +564 -0
  161. praisonai_code/cli/features/doctor/models.py +276 -0
  162. praisonai_code/cli/features/doctor/registry.py +239 -0
  163. praisonai_code/cli/features/endpoints.py +1016 -0
  164. praisonai_code/cli/features/eval.py +559 -0
  165. praisonai_code/cli/features/examples.py +707 -0
  166. praisonai_code/cli/features/external_agents.py +231 -0
  167. praisonai_code/cli/features/fast_context.py +410 -0
  168. praisonai_code/cli/features/file_history.py +320 -0
  169. praisonai_code/cli/features/flow_display.py +566 -0
  170. praisonai_code/cli/features/git_attribution.py +159 -0
  171. praisonai_code/cli/features/git_integration.py +651 -0
  172. praisonai_code/cli/features/guardrail.py +171 -0
  173. praisonai_code/cli/features/handoff.py +252 -0
  174. praisonai_code/cli/features/hooks.py +583 -0
  175. praisonai_code/cli/features/hybrid_workflow.py +391 -0
  176. praisonai_code/cli/features/image.py +384 -0
  177. praisonai_code/cli/features/interactive_core_headless.py +450 -0
  178. praisonai_code/cli/features/interactive_runtime.py +600 -0
  179. praisonai_code/cli/features/interactive_test_harness.py +537 -0
  180. praisonai_code/cli/features/interactive_tools.py +428 -0
  181. praisonai_code/cli/features/interactive_tui.py +603 -0
  182. praisonai_code/cli/features/job_workflow.py +906 -0
  183. praisonai_code/cli/features/jobs.py +632 -0
  184. praisonai_code/cli/features/knowledge.py +531 -0
  185. praisonai_code/cli/features/knowledge_cli.py +438 -0
  186. praisonai_code/cli/features/lite.py +244 -0
  187. praisonai_code/cli/features/logs.py +200 -0
  188. praisonai_code/cli/features/lsp_cli.py +225 -0
  189. praisonai_code/cli/features/lsp_diagnostics.py +185 -0
  190. praisonai_code/cli/features/mcp.py +344 -0
  191. praisonai_code/cli/features/message_queue.py +587 -0
  192. praisonai_code/cli/features/metrics.py +210 -0
  193. praisonai_code/cli/features/migrate.py +1329 -0
  194. praisonai_code/cli/features/migration_flow.py +463 -0
  195. praisonai_code/cli/features/migration_spec.py +276 -0
  196. praisonai_code/cli/features/n8n.py +703 -0
  197. praisonai_code/cli/features/observability.py +293 -0
  198. praisonai_code/cli/features/ollama.py +361 -0
  199. praisonai_code/cli/features/output_modes.py +155 -0
  200. praisonai_code/cli/features/output_style.py +273 -0
  201. praisonai_code/cli/features/package.py +631 -0
  202. praisonai_code/cli/features/performance.py +308 -0
  203. praisonai_code/cli/features/persistence.py +636 -0
  204. praisonai_code/cli/features/profiler/__init__.py +81 -0
  205. praisonai_code/cli/features/profiler/core.py +558 -0
  206. praisonai_code/cli/features/profiler/optimizations.py +652 -0
  207. praisonai_code/cli/features/profiler/suite.py +386 -0
  208. praisonai_code/cli/features/queue/__init__.py +73 -0
  209. praisonai_code/cli/features/queue/manager.py +435 -0
  210. praisonai_code/cli/features/queue/models.py +289 -0
  211. praisonai_code/cli/features/queue/persistence.py +564 -0
  212. praisonai_code/cli/features/queue/scheduler.py +529 -0
  213. praisonai_code/cli/features/queue/worker.py +400 -0
  214. praisonai_code/cli/features/recipe.py +2187 -0
  215. praisonai_code/cli/features/recipe_creator.py +996 -0
  216. praisonai_code/cli/features/recipe_optimizer.py +1364 -0
  217. praisonai_code/cli/features/recipe_prompts.py +226 -0
  218. praisonai_code/cli/features/registry.py +229 -0
  219. praisonai_code/cli/features/repo_map.py +860 -0
  220. praisonai_code/cli/features/router.py +466 -0
  221. praisonai_code/cli/features/safe_shell.py +427 -0
  222. praisonai_code/cli/features/sandbox_cli.py +283 -0
  223. praisonai_code/cli/features/sandbox_executor.py +536 -0
  224. praisonai_code/cli/features/sdk_knowledge.py +500 -0
  225. praisonai_code/cli/features/session.py +222 -0
  226. praisonai_code/cli/features/session_checkpoints.py +208 -0
  227. praisonai_code/cli/features/setup/__init__.py +9 -0
  228. praisonai_code/cli/features/setup/handler.py +355 -0
  229. praisonai_code/cli/features/setup/templates.py +62 -0
  230. praisonai_code/cli/features/skills.py +940 -0
  231. praisonai_code/cli/features/slash_commands.py +692 -0
  232. praisonai_code/cli/features/telemetry.py +179 -0
  233. praisonai_code/cli/features/templates.py +1390 -0
  234. praisonai_code/cli/features/thinking.py +343 -0
  235. praisonai_code/cli/features/todo.py +334 -0
  236. praisonai_code/cli/features/tools.py +680 -0
  237. praisonai_code/cli/features/tui/__init__.py +83 -0
  238. praisonai_code/cli/features/tui/app.py +871 -0
  239. praisonai_code/cli/features/tui/cli.py +580 -0
  240. praisonai_code/cli/features/tui/config.py +150 -0
  241. praisonai_code/cli/features/tui/debug.py +526 -0
  242. praisonai_code/cli/features/tui/events.py +99 -0
  243. praisonai_code/cli/features/tui/mock_provider.py +328 -0
  244. praisonai_code/cli/features/tui/orchestrator.py +652 -0
  245. praisonai_code/cli/features/tui/screens/__init__.py +50 -0
  246. praisonai_code/cli/features/tui/screens/help.py +157 -0
  247. praisonai_code/cli/features/tui/screens/main.py +568 -0
  248. praisonai_code/cli/features/tui/screens/queue.py +174 -0
  249. praisonai_code/cli/features/tui/screens/session.py +124 -0
  250. praisonai_code/cli/features/tui/screens/settings.py +148 -0
  251. praisonai_code/cli/features/tui/session_store.py +198 -0
  252. praisonai_code/cli/features/tui/widgets/__init__.py +56 -0
  253. praisonai_code/cli/features/tui/widgets/chat.py +263 -0
  254. praisonai_code/cli/features/tui/widgets/command_popup.py +258 -0
  255. praisonai_code/cli/features/tui/widgets/composer.py +292 -0
  256. praisonai_code/cli/features/tui/widgets/file_popup.py +207 -0
  257. praisonai_code/cli/features/tui/widgets/queue_panel.py +223 -0
  258. praisonai_code/cli/features/tui/widgets/status.py +181 -0
  259. praisonai_code/cli/features/tui/widgets/tool_panel.py +307 -0
  260. praisonai_code/cli/features/wizard.py +289 -0
  261. praisonai_code/cli/features/workflow.py +802 -0
  262. praisonai_code/cli/features/yaml_utils.py +321 -0
  263. praisonai_code/cli/interactive/__init__.py +48 -0
  264. praisonai_code/cli/interactive/async_tui.py +1218 -0
  265. praisonai_code/cli/interactive/config.py +139 -0
  266. praisonai_code/cli/interactive/core.py +618 -0
  267. praisonai_code/cli/interactive/events.py +131 -0
  268. praisonai_code/cli/interactive/frontends/__init__.py +31 -0
  269. praisonai_code/cli/interactive/frontends/rich_frontend.py +462 -0
  270. praisonai_code/cli/interactive/frontends/textual_frontend.py +157 -0
  271. praisonai_code/cli/interactive/praison_io.py +502 -0
  272. praisonai_code/cli/interactive/repl.py +297 -0
  273. praisonai_code/cli/interactive/split_tui.py +456 -0
  274. praisonai_code/cli/interactive/tui_app.py +457 -0
  275. praisonai_code/cli/langfuse_client.py +360 -0
  276. praisonai_code/cli/main.py +7421 -0
  277. praisonai_code/cli/output/__init__.py +25 -0
  278. praisonai_code/cli/output/console.py +456 -0
  279. praisonai_code/cli/output/event_bridge.py +191 -0
  280. praisonai_code/cli/schedule_cli.py +54 -0
  281. praisonai_code/cli/schema_provider.py +23 -0
  282. praisonai_code/cli/session/__init__.py +16 -0
  283. praisonai_code/cli/session/resume.py +148 -0
  284. praisonai_code/cli/session/unified.py +548 -0
  285. praisonai_code/cli/state/__init__.py +31 -0
  286. praisonai_code/cli/state/identifiers.py +161 -0
  287. praisonai_code/cli/state/project_sessions.py +383 -0
  288. praisonai_code/cli/state/sessions.py +390 -0
  289. praisonai_code/cli/ui/__init__.py +160 -0
  290. praisonai_code/cli/ui/config.py +46 -0
  291. praisonai_code/cli/ui/events.py +61 -0
  292. praisonai_code/cli/ui/mg_backend.py +342 -0
  293. praisonai_code/cli/ui/plain.py +133 -0
  294. praisonai_code/cli/ui/rich_backend.py +162 -0
  295. praisonai_code/cli/unified_schema.py +655 -0
  296. praisonai_code/cli/utils/env_utils.py +126 -0
  297. praisonai_code/cli/utils/project.py +131 -0
  298. praisonai_code/cli_backends/__init__.py +73 -0
  299. praisonai_code/cli_backends/claude.py +373 -0
  300. praisonai_code/cli_backends/registry.py +113 -0
  301. praisonai_code/runtime/__init__.py +36 -0
  302. praisonai_code/runtime/__main__.py +81 -0
  303. praisonai_code/runtime/client.py +131 -0
  304. praisonai_code/runtime/descriptor.py +209 -0
  305. praisonai_code/runtime/server.py +356 -0
  306. praisonai_code-0.0.1.dist-info/METADATA +80 -0
  307. praisonai_code-0.0.1.dist-info/RECORD +309 -0
  308. praisonai_code-0.0.1.dist-info/WHEEL +5 -0
  309. praisonai_code-0.0.1.dist-info/top_level.txt +1 -0
@@ -0,0 +1,172 @@
1
+ """
2
+ UI command — launch the PraisonAI Clean Chat UI.
3
+
4
+ Usage:
5
+ praisonai ui # Chat on :8081
6
+ praisonai ui --port 9000 # Custom port
7
+ praisonai ui --app my-chat.py # Custom app file
8
+ """
9
+
10
+ import sys
11
+ from pathlib import Path
12
+ from typing import Optional
13
+
14
+ import typer
15
+
16
+ app = typer.Typer(
17
+ help=(
18
+ "🤖 PraisonAI Clean Chat UI (Pattern B host via bundled default_app). "
19
+ "Pattern C: AIUIGateway. Legacy: PRAISONAI_HOST_LEGACY=1."
20
+ )
21
+ )
22
+
23
+
24
+ def _launch_aiui_app(
25
+ app_dir: str,
26
+ default_app_name: str,
27
+ port: int,
28
+ host: str,
29
+ app_file: Optional[str],
30
+ reload: bool,
31
+ ui_name: str
32
+ ) -> None:
33
+ """Common function to launch aiui apps."""
34
+ # 1. Check praisonaiui is installed
35
+ try:
36
+ import importlib.util
37
+ if importlib.util.find_spec("praisonaiui") is None:
38
+ raise ImportError
39
+ except ImportError:
40
+ print(f"\n\033[91mERROR: PraisonAI UI (aiui) is not installed.\033[0m")
41
+ print('\nInstall with:\n pip install "praisonai[ui]"\n')
42
+ sys.exit(1)
43
+
44
+ # 2. Resolve app file
45
+ if app_file:
46
+ resolved = Path(app_file)
47
+ if not resolved.exists():
48
+ print(f"\033[91mERROR: App file not found: {app_file}\033[0m")
49
+ sys.exit(1)
50
+ else:
51
+ ui_dir = Path.home() / ".praisonai" / app_dir
52
+ default_app = ui_dir / "app.py"
53
+
54
+ # Ensure default app exists
55
+ if not default_app.exists():
56
+ ui_dir.mkdir(parents=True, exist_ok=True)
57
+ bundled = Path(__file__).parent.parent.parent / default_app_name / "default_app.py"
58
+ if not bundled.exists():
59
+ print(f"\033[91mERROR: Bundled default_app.py not found at {bundled}\033[0m")
60
+ sys.exit(1)
61
+ default_app.write_text(bundled.read_text())
62
+ print(f" ✓ Created default {ui_name} config: {default_app}")
63
+
64
+ resolved = default_app
65
+
66
+ # 3. Launch via aiui run
67
+ import subprocess
68
+
69
+ cmd = ["aiui", "run", str(resolved), "--port", str(port), "--host", host]
70
+ if reload:
71
+ cmd.append("--reload")
72
+
73
+ print(f"\n🤖 PraisonAI {ui_name} starting at http://{host}:{port}")
74
+ print(f" App: {resolved}\n")
75
+
76
+ try:
77
+ subprocess.run(cmd, check=True)
78
+ except FileNotFoundError:
79
+ # Fallback: python -m praisonaiui.cli
80
+ cmd = [sys.executable, "-m", "praisonaiui.cli", "run", str(resolved),
81
+ "--port", str(port), "--host", host]
82
+ if reload:
83
+ cmd.append("--reload")
84
+ subprocess.run(cmd, check=True)
85
+ except KeyboardInterrupt:
86
+ print(f"\n🤖 {ui_name} stopped.")
87
+
88
+
89
+ @app.callback(invoke_without_command=True)
90
+ def ui(
91
+ ctx: typer.Context,
92
+ port: int = typer.Option(8081, "--port", "-p", help="Port to run chat UI on"),
93
+ host: str = typer.Option("127.0.0.1", "--host", help="Host to bind to"),
94
+ app_file: Optional[str] = typer.Option(
95
+ None, "--app", "-a", help="Custom app.py file (default: ~/.praisonai/ui/app.py)"
96
+ ),
97
+ reload: bool = typer.Option(False, "--reload", "-r", help="Enable auto-reload"),
98
+ ):
99
+ """
100
+ Launch the PraisonAI Clean Chat UI.
101
+
102
+ Starts a clean chat interface powered by PraisonAIUI — no sidebar,
103
+ single-page chat experience.
104
+
105
+ For the full dashboard with agents, memory, knowledge, etc.,
106
+ use: praisonai claw
107
+
108
+ Examples:
109
+ praisonai ui
110
+ praisonai ui --port 9000
111
+ praisonai ui --app my-chat.py
112
+ praisonai ui agents # YAML agents dashboard
113
+ praisonai ui bot # Bot interface
114
+ praisonai ui realtime # Voice realtime
115
+ """
116
+ if ctx.invoked_subcommand is not None:
117
+ return
118
+
119
+ _launch_aiui_app("ui", "ui_chat", port, host, app_file, reload, "Chat")
120
+
121
+
122
+ @app.command()
123
+ def agents(
124
+ port: int = typer.Option(8083, "--port", "-p", help="Port to run agents UI on"),
125
+ host: str = typer.Option("127.0.0.1", "--host", help="Host to bind to"),
126
+ app_file: Optional[str] = typer.Option(
127
+ None, "--app", "-a", help="Custom app.py file"
128
+ ),
129
+ reload: bool = typer.Option(False, "--reload", "-r", help="Enable auto-reload"),
130
+ ):
131
+ """
132
+ Launch YAML Agents Dashboard.
133
+
134
+ Replaces the old Chainlit agents interface with aiui.
135
+ Loads agents from agents.yaml in the current directory.
136
+ """
137
+ _launch_aiui_app("ui_agents", "ui_agents", port, host, app_file, reload, "Agents Dashboard")
138
+
139
+
140
+ @app.command()
141
+ def bot(
142
+ port: int = typer.Option(8084, "--port", "-p", help="Port to run bot UI on"),
143
+ host: str = typer.Option("127.0.0.1", "--host", help="Host to bind to"),
144
+ app_file: Optional[str] = typer.Option(
145
+ None, "--app", "-a", help="Custom app.py file"
146
+ ),
147
+ reload: bool = typer.Option(False, "--reload", "-r", help="Enable auto-reload"),
148
+ ):
149
+ """
150
+ Launch Bot Interface.
151
+
152
+ Replaces the old Chainlit bot interface with aiui.
153
+ Provides step-by-step interaction visualization.
154
+ """
155
+ _launch_aiui_app("ui_bot", "ui_bot", port, host, app_file, reload, "Bot Interface")
156
+
157
+
158
+ @app.command()
159
+ def realtime(
160
+ port: int = typer.Option(8085, "--port", "-p", help="Port to run realtime UI on"),
161
+ host: str = typer.Option("127.0.0.1", "--host", help="Host to bind to"),
162
+ app_file: Optional[str] = typer.Option(
163
+ None, "--app", "-a", help="Custom app.py file"
164
+ ),
165
+ reload: bool = typer.Option(False, "--reload", "-r", help="Enable auto-reload"),
166
+ ):
167
+ """
168
+ Launch Realtime Voice Interface.
169
+
170
+ Uses aiui's OpenAIRealtimeManager for WebRTC voice conversations.
171
+ """
172
+ _launch_aiui_app("ui_realtime", "ui_realtime", port, host, app_file, reload, "Realtime Voice")
@@ -0,0 +1,354 @@
1
+ """PraisonAI Up — Unified startup command.
2
+
3
+ Starts Langfuse + Langflow + observability in one command for
4
+ the complete PraisonAI × Langfuse × Langflow experience.
5
+ """
6
+
7
+ import os
8
+ import signal
9
+ import subprocess
10
+ import time
11
+ from typing import List, Optional
12
+
13
+ import typer
14
+ from rich.console import Console
15
+ from rich.panel import Panel
16
+ from rich.table import Table
17
+
18
+ app = typer.Typer(name="up", help="Start unified PraisonAI stack (Langfuse + Langflow + tracing)")
19
+
20
+
21
+ class ServiceManager:
22
+ """Manages multiple services with graceful shutdown."""
23
+
24
+ def __init__(self):
25
+ self.services: List[subprocess.Popen] = []
26
+ self.console = Console()
27
+
28
+ def add_service(self, cmd: List[str], name: str, env: Optional[dict] = None) -> subprocess.Popen:
29
+ """Start a service and add to managed list."""
30
+ self.console.print(f"[cyan]Starting {name}...[/cyan]")
31
+
32
+ try:
33
+ proc = subprocess.Popen(
34
+ cmd,
35
+ env=env or os.environ.copy(),
36
+ stdout=subprocess.DEVNULL,
37
+ stderr=subprocess.DEVNULL,
38
+ )
39
+ self.services.append(proc)
40
+ self.console.print(f"[green]✅ {name} started (PID: {proc.pid})[/green]")
41
+ return proc
42
+
43
+ except Exception as e:
44
+ self.console.print(f"[red]❌ Failed to start {name}: {e}[/red]")
45
+ raise typer.Abort()
46
+
47
+ def wait_for_service(self, url: str, service_name: str, timeout: int = 60) -> bool:
48
+ """Wait for service to become healthy."""
49
+ try:
50
+ import requests
51
+ except ImportError:
52
+ self.console.print(f"[yellow]⚠️ Cannot health-check {service_name} (requests not installed)[/yellow]")
53
+ return True
54
+
55
+ self.console.print(f"[cyan]Waiting for {service_name} at {url}...[/cyan]")
56
+
57
+ start_time = time.time()
58
+ while time.time() - start_time < timeout:
59
+ try:
60
+ response = requests.get(f"{url}/api/v1/health", timeout=5)
61
+ if response.status_code == 200:
62
+ self.console.print(f"[green]✅ {service_name} is ready![/green]")
63
+ return True
64
+ except requests.RequestException:
65
+ pass
66
+
67
+ time.sleep(2)
68
+
69
+ self.console.print(f"[yellow]⚠️ {service_name} health check timed out[/yellow]")
70
+ return False
71
+
72
+ def shutdown_all(self):
73
+ """Gracefully shutdown all services."""
74
+ if not self.services:
75
+ return
76
+
77
+ self.console.print("\n[yellow]Shutting down services...[/yellow]")
78
+
79
+ # Send SIGTERM to all processes
80
+ for proc in self.services:
81
+ if proc.poll() is None: # Process still running
82
+ try:
83
+ proc.terminate()
84
+ except ProcessLookupError:
85
+ pass
86
+
87
+ # Wait for graceful shutdown
88
+ time.sleep(3)
89
+
90
+ # Force kill any remaining processes
91
+ for proc in self.services:
92
+ if proc.poll() is None:
93
+ try:
94
+ proc.kill()
95
+ proc.wait(timeout=5)
96
+ except (ProcessLookupError, subprocess.TimeoutExpired):
97
+ pass
98
+
99
+ self.console.print("[green]✅ All services stopped[/green]")
100
+
101
+
102
+ @app.callback(invoke_without_command=True)
103
+ def up_start(
104
+ ctx: typer.Context,
105
+ # Langfuse options
106
+ langfuse_port: int = typer.Option(3000, "--langfuse-port", help="Langfuse port"),
107
+ no_langfuse: bool = typer.Option(False, "--no-langfuse", help="Skip starting Langfuse"),
108
+
109
+ # Langflow options
110
+ langflow_port: int = typer.Option(7860, "--langflow-port", help="Langflow port"),
111
+ no_langflow: bool = typer.Option(False, "--no-langflow", help="Skip starting Langflow"),
112
+
113
+ # Observability options
114
+ observe: str = typer.Option("langfuse", "--observe", help="Enable observability (langfuse)"),
115
+
116
+ # General options
117
+ host: str = typer.Option("127.0.0.1", "--host", help="Host to bind to"),
118
+ no_open: bool = typer.Option(False, "--no-open", help="Don't open browser"),
119
+ wait_timeout: int = typer.Option(60, "--wait", help="Seconds to wait for services"),
120
+ ):
121
+ """Start unified PraisonAI stack.
122
+
123
+ Launches Langfuse (observability) + Langflow (visual builder) with
124
+ automatic observability wiring. The complete PraisonAI experience.
125
+
126
+ Examples:
127
+ praisonai up
128
+ praisonai up --no-langfuse # Langflow only
129
+ praisonai up --no-langflow # Langfuse only
130
+ praisonai up --host 0.0.0.0 --langfuse-port 3001
131
+ """
132
+ if ctx.invoked_subcommand is not None:
133
+ return
134
+
135
+ console = Console()
136
+ manager = ServiceManager()
137
+
138
+ # Validate options
139
+ if no_langfuse and no_langflow:
140
+ console.print("[red]Error: Cannot skip both Langfuse and Langflow[/red]")
141
+ raise typer.Abort()
142
+
143
+ # Show startup banner
144
+ console.print()
145
+ console.print(Panel.fit(
146
+ "[bold green]🚀 PraisonAI Stack Starting[/bold green]\n\n"
147
+ f"[cyan]Langfuse:[/cyan] {'✅ Enabled' if not no_langfuse else '❌ Disabled'} "
148
+ f"(port {langfuse_port})\n"
149
+ f"[cyan]Langflow:[/cyan] {'✅ Enabled' if not no_langflow else '❌ Disabled'} "
150
+ f"(port {langflow_port})\n"
151
+ f"[cyan]Observability:[/cyan] {observe}",
152
+ title="PraisonAI Up",
153
+ border_style="green"
154
+ ))
155
+ console.print()
156
+
157
+ try:
158
+ import sys
159
+
160
+ # Setup environment for observability
161
+ env = os.environ.copy()
162
+ if observe == "langfuse" and not no_langfuse:
163
+ # Configure Langfuse environment
164
+ env["LANGFUSE_HOST"] = f"http://{host}:{langfuse_port}"
165
+ env["PRAISONAI_OBSERVE"] = "langfuse"
166
+
167
+ # Suppress macOS warnings
168
+ if sys.platform == "darwin":
169
+ env.setdefault("OBJC_DISABLE_INITIALIZE_FORK_SAFETY", "YES")
170
+
171
+ services_started = []
172
+
173
+ # Start Langfuse
174
+ if not no_langfuse:
175
+ try:
176
+ # Check if praisonai langfuse command exists
177
+ langfuse_cmd = [
178
+ sys.executable, "-m", "praisonai.cli.main", "langfuse",
179
+ "--port", str(langfuse_port),
180
+ "--host", host,
181
+ ]
182
+
183
+ langfuse_proc = manager.add_service(langfuse_cmd, "Langfuse", env)
184
+ services_started.append(("Langfuse", f"http://{host}:{langfuse_port}"))
185
+
186
+ # Wait for Langfuse to be ready
187
+ if wait_timeout > 0:
188
+ manager.wait_for_service(
189
+ f"http://{host}:{langfuse_port}",
190
+ "Langfuse",
191
+ timeout=wait_timeout
192
+ )
193
+
194
+ except Exception as e:
195
+ console.print(f"[red]Failed to start Langfuse: {e}[/red]")
196
+ console.print("[yellow]Try: pip install 'praisonai[langfuse]'[/yellow]")
197
+ if not no_langflow:
198
+ console.print("[cyan]Continuing with Langflow only...[/cyan]")
199
+
200
+ # Start Langflow
201
+ if not no_langflow:
202
+ try:
203
+ # Get path to praisonai flow command
204
+ langflow_cmd = [
205
+ sys.executable, "-m", "praisonai.cli.main", "flow",
206
+ "--port", str(langflow_port),
207
+ "--host", host,
208
+ "--no-open", # We'll handle browser opening
209
+ ]
210
+
211
+ langflow_proc = manager.add_service(langflow_cmd, "Langflow", env)
212
+ services_started.append(("Langflow", f"http://{host}:{langflow_port}"))
213
+
214
+ # Wait for Langflow to be ready
215
+ if wait_timeout > 0:
216
+ manager.wait_for_service(
217
+ f"http://{host}:{langflow_port}",
218
+ "Langflow",
219
+ timeout=wait_timeout
220
+ )
221
+
222
+ except Exception as e:
223
+ console.print(f"[red]Failed to start Langflow: {e}[/red]")
224
+ console.print("[yellow]Try: pip install 'praisonai[flow]'[/yellow]")
225
+
226
+ if not services_started:
227
+ console.print("[red]No services started successfully[/red]")
228
+ raise typer.Abort()
229
+
230
+ # Show service summary
231
+ console.print()
232
+ table = Table(title="🎉 Services Ready")
233
+ table.add_column("Service", style="cyan")
234
+ table.add_column("URL", style="green")
235
+ table.add_column("Status", style="bold")
236
+
237
+ for service_name, service_url in services_started:
238
+ table.add_row(service_name, service_url, "✅ Running")
239
+
240
+ console.print(table)
241
+
242
+ # Show usage instructions
243
+ console.print()
244
+ console.print(Panel(
245
+ "[bold]Quick Start:[/bold]\n\n"
246
+ "1. Open Langflow in your browser to build visual workflows\n"
247
+ "2. Use PraisonAI Agent/AgentTeam components from the sidebar\n"
248
+ "3. Run workflows with: [cyan]praisonai run workflow.yaml --observe langfuse[/cyan]\n"
249
+ "4. View traces in Langfuse dashboard\n\n"
250
+ "[dim]Press Ctrl+C to stop all services[/dim]",
251
+ title="Next Steps",
252
+ border_style="blue"
253
+ ))
254
+
255
+ # Open browser if requested
256
+ if not no_open and not no_langflow:
257
+ try:
258
+ import webbrowser
259
+ webbrowser.open(f"http://{host}:{langflow_port}")
260
+ console.print("[dim]Opening Langflow in browser...[/dim]")
261
+ except Exception:
262
+ pass
263
+
264
+ # Setup signal handler for graceful shutdown
265
+ def signal_handler(signum, frame):
266
+ raise KeyboardInterrupt() # Let the try/except/finally handle cleanup
267
+
268
+ signal.signal(signal.SIGINT, signal_handler)
269
+ signal.signal(signal.SIGTERM, signal_handler)
270
+
271
+ # Keep running until interrupted
272
+ try:
273
+ while True:
274
+ time.sleep(1)
275
+ # Check if any service died
276
+ for proc in manager.services[:]:
277
+ if proc.poll() is not None:
278
+ console.print(f"[red]Service died (exit code: {proc.returncode})[/red]")
279
+ manager.services.remove(proc)
280
+
281
+ # If all services died, exit
282
+ if not manager.services:
283
+ console.print("[yellow]All services stopped[/yellow]")
284
+ break
285
+
286
+ except KeyboardInterrupt:
287
+ pass
288
+ finally:
289
+ manager.shutdown_all()
290
+
291
+ except Exception as e:
292
+ console.print(f"[red]Error: {e}[/red]")
293
+ manager.shutdown_all()
294
+ raise typer.Abort()
295
+
296
+
297
+ @app.command("status")
298
+ def up_status(
299
+ langfuse_url: str = typer.Option("http://localhost:3000", "--langfuse-url", help="Langfuse URL"),
300
+ langflow_url: str = typer.Option("http://localhost:7860", "--langflow-url", help="Langflow URL"),
301
+ ):
302
+ """Check status of PraisonAI services."""
303
+ console = Console()
304
+
305
+ try:
306
+ import requests
307
+ except ImportError:
308
+ console.print("[red]requests package required for status checks[/red]")
309
+ raise typer.Abort()
310
+
311
+ table = Table(title="Service Status")
312
+ table.add_column("Service", style="cyan")
313
+ table.add_column("URL", style="blue")
314
+ table.add_column("Status", style="bold")
315
+ table.add_column("Response Time", style="dim")
316
+
317
+ services = [
318
+ ("Langfuse", langfuse_url),
319
+ ("Langflow", langflow_url),
320
+ ]
321
+
322
+ for service_name, service_url in services:
323
+ try:
324
+ start_time = time.time()
325
+ response = requests.get(f"{service_url}/health", timeout=5)
326
+ response_time = f"{(time.time() - start_time)*1000:.0f}ms"
327
+
328
+ if response.status_code == 200:
329
+ status = "✅ Healthy"
330
+ status_style = "green"
331
+ else:
332
+ status = f"⚠️ Error {response.status_code}"
333
+ status_style = "yellow"
334
+
335
+ except requests.RequestException as e:
336
+ status = "❌ Down"
337
+ status_style = "red"
338
+ response_time = "N/A"
339
+
340
+ table.add_row(service_name, service_url, status, response_time)
341
+
342
+ console.print(table)
343
+
344
+
345
+ @app.command("logs")
346
+ def up_logs(
347
+ service: str = typer.Option("all", "--service", help="Service to show logs for (all, langfuse, langflow)"),
348
+ follow: bool = typer.Option(False, "--follow", "-f", help="Follow log output"),
349
+ lines: int = typer.Option(50, "--lines", "-n", help="Number of lines to show"),
350
+ ):
351
+ """Show logs from PraisonAI services."""
352
+ console = Console()
353
+ console.print("[yellow]Log viewing not implemented yet[/yellow]")
354
+ console.print("[dim]Use docker logs or check process output directly[/dim]")