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,332 @@
1
+ """
2
+ Chat command group for PraisonAI CLI.
3
+
4
+ Provides terminal-native interactive chat mode.
5
+ This command NEVER opens a browser - it runs entirely in the terminal.
6
+ """
7
+
8
+ from typing import List, Optional, Union
9
+
10
+ import typer
11
+
12
+ app = typer.Typer(help="Terminal-native interactive chat mode")
13
+
14
+
15
+ def _parse_memory_flag(memory: Optional[str], no_memory: bool) -> Union[bool, str, None]:
16
+ """
17
+ Parse memory CLI flag to value for Agent.
18
+
19
+ Precedence: --no-memory > --memory=value > --memory (flag) > None
20
+
21
+ Args:
22
+ memory: Memory flag value (None, "true", preset string, or URL)
23
+ no_memory: Whether --no-memory was specified
24
+
25
+ Returns:
26
+ - False if --no-memory
27
+ - True if --memory (flag only)
28
+ - str if --memory=preset or --memory=URL
29
+ - None if neither specified
30
+ """
31
+ if no_memory:
32
+ return False
33
+
34
+ if memory is None:
35
+ return None
36
+
37
+ # --memory flag without value sets "true"
38
+ if memory.lower() == "true":
39
+ return True
40
+
41
+ # --memory=false explicitly disables
42
+ if memory.lower() == "false":
43
+ return False
44
+
45
+ # Otherwise it's a preset or URL string
46
+ return memory
47
+
48
+
49
+ @app.callback(invoke_without_command=True)
50
+ def chat_main(
51
+ ctx: typer.Context,
52
+ prompt: Optional[str] = typer.Argument(None, help="Initial prompt for chat"),
53
+ model: Optional[str] = typer.Option(None, "--model", "-m", help="LLM model to use"),
54
+ verbose: bool = typer.Option(False, "--verbose", "-v", help="Verbose output"),
55
+ memory: Optional[str] = typer.Option(
56
+ None, "--memory",
57
+ help="Enable memory. Use --memory for default, --memory=redis for preset, --memory=postgresql://... for URL",
58
+ is_flag=False,
59
+ flag_value="true",
60
+ ),
61
+ no_memory: bool = typer.Option(False, "--no-memory", help="Disable memory"),
62
+ tools: Optional[str] = typer.Option(None, "--tools", "-t", help="Tools file path"),
63
+ toolset: Optional[str] = typer.Option(None, "--toolset", help="Named toolset groups (comma-separated, e.g., web,files)"),
64
+ user_id: Optional[str] = typer.Option(None, "--user-id", help="User ID for memory isolation"),
65
+ session_id: Optional[str] = typer.Option(None, "--session", "-s", help="Session ID to resume"),
66
+ continue_session: bool = typer.Option(False, "--continue", "-c", help="Continue last session"),
67
+ file: Optional[List[str]] = typer.Option(None, "--file", "-f", help="Attach file(s) to prompt"),
68
+ workspace: Optional[str] = typer.Option(None, "--workspace", "-w", help="Workspace directory"),
69
+ no_acp: bool = typer.Option(False, "--no-acp", help="Disable ACP tools"),
70
+ no_lsp: bool = typer.Option(False, "--no-lsp", help="Disable LSP tools"),
71
+ safe_mode: bool = typer.Option(False, "--safe", help="Safe mode: require approval for file writes and commands"),
72
+ autonomy: bool = typer.Option(True, "--autonomy/--no-autonomy", help="Enable agent autonomy for complex tasks"),
73
+ # NEW: Agent-like consolidated params for ALL GREEN consistency
74
+ knowledge: Optional[str] = typer.Option(
75
+ None, "--knowledge", "-k",
76
+ help="Enable knowledge/RAG. Use --knowledge for default, --knowledge=docs/ for sources",
77
+ is_flag=False,
78
+ flag_value="true",
79
+ ),
80
+ guardrails: Optional[str] = typer.Option(
81
+ None, "--guardrails",
82
+ help="Enable guardrails. Use --guardrails for default, --guardrails=strict for preset",
83
+ is_flag=False,
84
+ flag_value="true",
85
+ ),
86
+ web: Optional[str] = typer.Option(
87
+ None, "--web",
88
+ help="Enable web search. Use --web for default, --web=duckduckgo for preset",
89
+ is_flag=False,
90
+ flag_value="true",
91
+ ),
92
+ reflection: Optional[str] = typer.Option(
93
+ None, "--reflection",
94
+ help="Enable self-reflection. Use --reflection for default, --reflection=thorough for preset",
95
+ is_flag=False,
96
+ flag_value="true",
97
+ ),
98
+ # NEW: Additional consolidated params for ALL GREEN feature parity
99
+ planning: Optional[str] = typer.Option(
100
+ None, "--planning",
101
+ help="Enable planning mode. Use --planning for default, --planning=thorough for preset",
102
+ is_flag=False,
103
+ flag_value="true",
104
+ ),
105
+ context: Optional[str] = typer.Option(
106
+ None, "--context",
107
+ help="Enable context management. Use --context for default",
108
+ is_flag=False,
109
+ flag_value="true",
110
+ ),
111
+ output: Optional[str] = typer.Option(
112
+ None, "--output", "-o",
113
+ help="Output mode (default: actions). Options: actions, plain, verbose, json, silent",
114
+ ),
115
+ execution: Optional[str] = typer.Option(
116
+ None, "--execution",
117
+ help="Execution preset. Use --execution=fast, --execution=thorough, --execution=unlimited",
118
+ ),
119
+ hooks: Optional[str] = typer.Option(
120
+ None, "--hooks",
121
+ help="Hooks config file path for lifecycle callbacks",
122
+ ),
123
+ caching: Optional[str] = typer.Option(
124
+ None, "--caching",
125
+ help="Enable caching. Use --caching for default, --caching=redis for preset",
126
+ is_flag=False,
127
+ flag_value="true",
128
+ ),
129
+ approval: Optional[str] = typer.Option(None, "--approval", help="Approval backend: console, slack, telegram, discord, webhook, http, agent, auto, none"),
130
+ profile: bool = typer.Option(False, "--profile", help="Enable CLI profiling (timing breakdown)"),
131
+ profile_deep: bool = typer.Option(False, "--profile-deep", help="Enable deep profiling (cProfile stats, higher overhead)"),
132
+ debug: bool = typer.Option(False, "--debug", help="Enable debug logging to ~/.praisonai/async_tui_debug.log"),
133
+ # UI backend selection
134
+ ui_backend: str = typer.Option("auto", "--ui-backend", help="UI backend: auto, plain, rich, mg (middle-ground)"),
135
+ json_output: bool = typer.Option(False, "--json", help="Output JSON (forces plain backend)"),
136
+ no_color: bool = typer.Option(False, "--no-color", help="Disable colors"),
137
+ theme: str = typer.Option("default", "--theme", help="UI theme: default, dark, light, minimal"),
138
+ compact: bool = typer.Option(False, "--compact", help="Compact output mode"),
139
+ no_rules: bool = typer.Option(False, "--no-rules", help="Disable auto-injection of project instruction files"),
140
+ ):
141
+ """
142
+ Start terminal-native interactive chat mode.
143
+
144
+ This is a terminal REPL with streaming responses, slash commands,
145
+ and multi-turn conversation support. It NEVER opens a browser.
146
+
147
+ For browser-based chat UI, use: praisonai ui chat
148
+
149
+ Examples:
150
+ praisonai chat
151
+ praisonai chat "Hello, how are you?"
152
+ praisonai chat --model gpt-4o --memory
153
+ praisonai chat --continue # Resume last session
154
+ praisonai chat "Summarize this" --file README.md
155
+ praisonai chat "What is 2+2?" --profile
156
+ """
157
+ import os
158
+
159
+ # Set workspace if provided
160
+ if workspace:
161
+ os.environ["PRAISONAI_WORKSPACE"] = workspace
162
+
163
+ # Handle profiling for single prompt mode
164
+ if prompt and (profile or profile_deep):
165
+ _run_profiled_chat(
166
+ prompt=prompt,
167
+ model=model,
168
+ verbose=verbose,
169
+ profile_deep=profile_deep,
170
+ )
171
+ return
172
+
173
+ # Warn if profiling requested without prompt (REPL mode doesn't support profiling)
174
+ if (profile or profile_deep) and not prompt:
175
+ typer.echo("⚠️ Profiling is only supported for single prompt mode.", err=True)
176
+ typer.echo(" Use: praisonai chat \"your prompt\" --profile", err=True)
177
+
178
+ # Parse memory flag: --no-memory takes precedence, then --memory value
179
+ # TODO: Pass memory_value to TUI when memory support is added
180
+ _parse_memory_flag(memory, no_memory)
181
+
182
+ # Set approval mode based on --safe flag
183
+ import os
184
+ if safe_mode:
185
+ os.environ["PRAISON_APPROVAL_MODE"] = "prompt"
186
+ else:
187
+ os.environ["PRAISON_APPROVAL_MODE"] = "auto"
188
+
189
+ # Wire --approval backend via global registry (TUI creates agents internally)
190
+ if approval:
191
+ from praisonai.cli.features.approval import resolve_approval_backend
192
+ try:
193
+ backend = resolve_approval_backend(approval)
194
+ if backend is not None:
195
+ from praisonaiagents.approval import get_approval_registry
196
+ get_approval_registry().set_backend(backend)
197
+ typer.echo(f"Approval backend: {approval}")
198
+ except ValueError as e:
199
+ typer.echo(f"Error: {e}", err=True)
200
+ raise typer.Exit(1)
201
+
202
+ # Use the async TUI (non-blocking, scrollable output)
203
+ from praisonai.cli.interactive.async_tui import AsyncTUI, AsyncTUIConfig
204
+
205
+ # Resolve a provider-aware default when no model was given:
206
+ # explicit --model > most-recently-used > provider credentials present.
207
+ try:
208
+ from ..configuration.model_resolver import resolve_default_model
209
+ resolved_model = resolve_default_model(model)
210
+ except Exception:
211
+ resolved_model = model or "gpt-4o-mini"
212
+
213
+ tui_config = AsyncTUIConfig(
214
+ model=resolved_model,
215
+ show_logo=not compact,
216
+ show_status_bar=not compact,
217
+ session_id=session_id,
218
+ workspace=workspace,
219
+ debug=debug,
220
+ autonomy_mode=autonomy,
221
+ no_rules=no_rules,
222
+ )
223
+
224
+ tui = AsyncTUI(config=tui_config)
225
+
226
+ if prompt:
227
+ # Single prompt mode - direct response, no streaming
228
+ response = tui.run_single(prompt)
229
+ if response:
230
+ print(response)
231
+ else:
232
+ # Interactive split-pane TUI mode
233
+ tui.run()
234
+
235
+
236
+ def _run_profiled_chat(
237
+ prompt: str,
238
+ model: Optional[str] = None,
239
+ verbose: bool = False,
240
+ profile_deep: bool = False,
241
+ ):
242
+ """Run chat with profiling enabled."""
243
+ from praisonai.cli.features.cli_profiler import (
244
+ CLIProfileConfig,
245
+ CLIProfiler,
246
+ )
247
+
248
+ config = CLIProfileConfig(enabled=True, deep=profile_deep)
249
+ profiler = CLIProfiler(config)
250
+
251
+ if profile_deep:
252
+ typer.echo("⚠️ Deep profiling enabled - this adds significant overhead", err=True)
253
+
254
+ profiler.start()
255
+
256
+ # Import phase
257
+ profiler.mark_import_start()
258
+ try:
259
+ from praisonaiagents import Agent
260
+ except ImportError:
261
+ typer.echo("Error: praisonaiagents not installed", err=True)
262
+ raise typer.Exit(1)
263
+ profiler.mark_import_end()
264
+
265
+ # Agent initialization phase
266
+ profiler.mark_init_start()
267
+ agent_config = {
268
+ "name": "ChatAgent",
269
+ "role": "Assistant",
270
+ "goal": "Help the user",
271
+ }
272
+ if model:
273
+ agent_config["llm"] = model
274
+
275
+ agent = Agent(**agent_config)
276
+ profiler.mark_init_end()
277
+
278
+ # Execution phase
279
+ profiler.mark_exec_start()
280
+ response = agent.start(prompt)
281
+ profiler.mark_exec_end()
282
+
283
+ profiler.stop()
284
+
285
+ # Print response
286
+ if response:
287
+ print(response)
288
+
289
+ # Print profiling report
290
+ profiler.print_report()
291
+
292
+
293
+ def _run_legacy_terminal_chat(
294
+ prompt: Optional[str] = None,
295
+ model: Optional[str] = None,
296
+ verbose: bool = False,
297
+ memory: bool = False,
298
+ tools: Optional[str] = None,
299
+ toolset: Optional[str] = None,
300
+ user_id: Optional[str] = None,
301
+ session_id: Optional[str] = None,
302
+ continue_session: bool = False,
303
+ workspace: Optional[str] = None,
304
+ no_acp: bool = False,
305
+ no_lsp: bool = False,
306
+ ):
307
+ """Run terminal-native chat using legacy _start_interactive_mode."""
308
+ import argparse
309
+
310
+ # Build args namespace for _start_interactive_mode
311
+ args = argparse.Namespace()
312
+ args.llm = model
313
+ args.verbose = verbose
314
+ args.memory = memory
315
+ args.tools = tools
316
+ args.toolset = toolset
317
+ args.user_id = user_id
318
+ args.resume_session = session_id if session_id else ('last' if continue_session else None)
319
+ args.no_acp = no_acp
320
+ args.no_lsp = no_lsp
321
+
322
+ # Import and run the terminal-native interactive mode
323
+ from praisonai.cli.main import PraisonAI
324
+
325
+ praison = PraisonAI()
326
+
327
+ if prompt:
328
+ # Single prompt mode - use _run_chat_mode
329
+ praison._run_chat_mode(prompt, args)
330
+ else:
331
+ # Interactive REPL mode - use _start_interactive_mode
332
+ praison._start_interactive_mode(args)
@@ -0,0 +1,170 @@
1
+ """
2
+ Checkpoint command group for PraisonAI CLI.
3
+
4
+ Surfaces the core file-level checkpoint engine
5
+ (``praisonaiagents.checkpoints.CheckpointService``) as first-class CLI
6
+ commands, delegating to the existing :class:`CheckpointsHandler`.
7
+
8
+ Examples:
9
+ praisonai checkpoint save "before refactor"
10
+ praisonai checkpoint list
11
+ praisonai checkpoint restore <id|last>
12
+ praisonai checkpoint diff [from] [to]
13
+ praisonai checkpoint delete
14
+ """
15
+
16
+ import asyncio
17
+ import os
18
+ from typing import Optional
19
+
20
+ import typer
21
+
22
+ app = typer.Typer(help="File-level checkpoint management (save / restore / diff)")
23
+
24
+
25
+ def _resolve_storage_dir() -> Optional[str]:
26
+ """Return a configured ``checkpoints.storage_dir`` if one is set.
27
+
28
+ Threading this through keeps the standalone ``praisonai checkpoint``
29
+ commands reading from the same store the interactive coding session
30
+ (``code --checkpoints``) writes to. Falls back to ``None`` (the default
31
+ store) when no config is present or it cannot be read.
32
+ """
33
+ try:
34
+ from ..configuration.resolver import resolve_config
35
+
36
+ section = (resolve_config().extra or {}).get("checkpoints", {})
37
+ if isinstance(section, dict):
38
+ return section.get("storage_dir")
39
+ except Exception:
40
+ pass
41
+ return None
42
+
43
+
44
+ def _handler(workspace: Optional[str] = None, verbose: bool = False):
45
+ """Build a CheckpointsHandler for the current workspace."""
46
+ from praisonai.cli.features.checkpoints import CheckpointsHandler
47
+
48
+ return CheckpointsHandler(
49
+ workspace_dir=workspace or os.getcwd(),
50
+ verbose=verbose,
51
+ storage_dir=_resolve_storage_dir(),
52
+ )
53
+
54
+
55
+ async def _resolve_checkpoint_id(handler, ref: str) -> Optional[str]:
56
+ """Resolve a checkpoint reference (an id/short_id or the literal 'last').
57
+
58
+ Resolution order: literal ``last``/``latest`` -> exact id/short_id ->
59
+ unique id prefix. Ambiguous prefixes (matching more than one checkpoint)
60
+ are rejected so a workspace-mutating restore never targets the wrong
61
+ checkpoint.
62
+
63
+ Returns the resolved checkpoint id, or ``None`` when no matching (or an
64
+ ambiguous) checkpoint reference is given.
65
+ """
66
+ service = await handler._get_service()
67
+ checkpoints = await service.list_checkpoints(limit=100)
68
+ if not checkpoints:
69
+ return None
70
+
71
+ if ref in ("last", "latest"):
72
+ # list_checkpoints returns newest-first.
73
+ return checkpoints[0].id
74
+
75
+ exact = [cp.id for cp in checkpoints if cp.id == ref or cp.short_id == ref]
76
+ if exact:
77
+ return exact[0]
78
+
79
+ prefix_matches = [cp.id for cp in checkpoints if cp.id.startswith(ref)]
80
+ if len(prefix_matches) == 1:
81
+ return prefix_matches[0]
82
+ if len(prefix_matches) > 1:
83
+ handler._print_error(f"Ambiguous checkpoint reference: {ref}")
84
+ return None
85
+
86
+
87
+ @app.command("save")
88
+ def save(
89
+ message: str = typer.Argument(..., help="Checkpoint message"),
90
+ allow_empty: bool = typer.Option(False, "--allow-empty", help="Allow checkpoint with no changes"),
91
+ workspace: Optional[str] = typer.Option(None, "--workspace", "-w", help="Workspace directory"),
92
+ ):
93
+ """Save a checkpoint of the current workspace."""
94
+ handler = _handler(workspace)
95
+ ok = asyncio.run(handler.save(message, allow_empty=allow_empty))
96
+ if not ok:
97
+ raise typer.Exit(1)
98
+
99
+
100
+ @app.command("list")
101
+ def list_checkpoints(
102
+ limit: int = typer.Option(20, "--limit", "-n", help="Maximum checkpoints to show"),
103
+ workspace: Optional[str] = typer.Option(None, "--workspace", "-w", help="Workspace directory"),
104
+ ):
105
+ """List checkpoints for the workspace (newest first)."""
106
+ handler = _handler(workspace)
107
+ asyncio.run(handler.list_checkpoints(limit=limit))
108
+
109
+
110
+ @app.command("restore")
111
+ def restore(
112
+ checkpoint_id: str = typer.Argument(..., help="Checkpoint id, short id, or 'last'"),
113
+ workspace: Optional[str] = typer.Option(None, "--workspace", "-w", help="Workspace directory"),
114
+ ):
115
+ """Restore the workspace to a checkpoint (accepts 'last')."""
116
+ handler = _handler(workspace)
117
+
118
+ async def _run() -> bool:
119
+ resolved = await _resolve_checkpoint_id(handler, checkpoint_id)
120
+ if resolved is None:
121
+ handler._print_error(f"No checkpoint found for: {checkpoint_id}")
122
+ return False
123
+ return await handler.restore(resolved)
124
+
125
+ if not asyncio.run(_run()):
126
+ raise typer.Exit(1)
127
+
128
+
129
+ @app.command("diff")
130
+ def diff(
131
+ from_id: Optional[str] = typer.Argument(None, help="Starting checkpoint (default: previous)"),
132
+ to_id: Optional[str] = typer.Argument(None, help="Ending checkpoint (default: working directory)"),
133
+ workspace: Optional[str] = typer.Option(None, "--workspace", "-w", help="Workspace directory"),
134
+ ):
135
+ """Show the diff between checkpoints (or against the working directory)."""
136
+ handler = _handler(workspace)
137
+
138
+ async def _run() -> None:
139
+ # Resolve the same references restore accepts ('last'/short id/prefix)
140
+ # so `diff last` or `diff <short_id>` don't reach git as literal refs.
141
+ resolved_from = (
142
+ await _resolve_checkpoint_id(handler, from_id) if from_id else None
143
+ )
144
+ resolved_to = (
145
+ await _resolve_checkpoint_id(handler, to_id) if to_id else None
146
+ )
147
+ if from_id and resolved_from is None:
148
+ handler._print_error(f"No checkpoint found for: {from_id}")
149
+ return
150
+ if to_id and resolved_to is None:
151
+ handler._print_error(f"No checkpoint found for: {to_id}")
152
+ return
153
+ await handler.diff(resolved_from, resolved_to)
154
+
155
+ asyncio.run(_run())
156
+
157
+
158
+ @app.command("delete")
159
+ def delete(
160
+ yes: bool = typer.Option(False, "--yes", "-y", help="Skip confirmation prompt"),
161
+ workspace: Optional[str] = typer.Option(None, "--workspace", "-w", help="Workspace directory"),
162
+ ):
163
+ """Delete all checkpoints for the workspace."""
164
+ handler = _handler(workspace)
165
+ if not yes and not typer.confirm("Delete all checkpoints?"):
166
+ typer.echo("Cancelled")
167
+ return
168
+ ok = asyncio.run(handler.delete_all())
169
+ if not ok:
170
+ raise typer.Exit(1)