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,613 @@
1
+ """
2
+ Train command group for PraisonAI CLI.
3
+
4
+ Provides two types of training:
5
+ 1. LLM Fine-tuning: praisonai train dataset.json
6
+ 2. Agent Training: praisonai train agents [OPTIONS]
7
+ """
8
+
9
+ import json
10
+ from pathlib import Path
11
+ from typing import Optional
12
+
13
+ import typer
14
+
15
+ app = typer.Typer(help="Training commands for models and agents")
16
+
17
+
18
+ @app.callback()
19
+ def train_callback():
20
+ """
21
+ Training commands for models and agents.
22
+
23
+ For LLM fine-tuning:
24
+ praisonai train llm dataset.json
25
+
26
+ For agent training (iterative improvement):
27
+ praisonai train agents --input "What is Python?"
28
+ praisonai train agents --input "Explain AI" --human
29
+ """
30
+ pass
31
+
32
+
33
+ @app.command("llm")
34
+ def train_llm(
35
+ dataset: str = typer.Argument(..., help="Training dataset path"),
36
+ model: Optional[str] = typer.Option(None, "--model", "-m", help="Base model to fine-tune"),
37
+ verbose: bool = typer.Option(False, "--verbose", "-v", help="Verbose output"),
38
+ ):
39
+ """
40
+ Fine-tune LLM models using Unsloth.
41
+
42
+ Examples:
43
+ praisonai train llm dataset.json
44
+ praisonai train llm --model llama-3.1 dataset.json
45
+ """
46
+ from praisonai.cli.main import PraisonAI
47
+ import sys
48
+
49
+ argv = ['train', dataset]
50
+ if model:
51
+ argv.extend(['--model', model])
52
+ if verbose:
53
+ argv.append('--verbose')
54
+
55
+ original_argv = sys.argv
56
+ sys.argv = ['praisonai'] + argv
57
+
58
+ try:
59
+ praison = PraisonAI()
60
+ praison.main()
61
+ except SystemExit:
62
+ pass
63
+ finally:
64
+ sys.argv = original_argv
65
+
66
+
67
+ @app.command("agents")
68
+ def train_agents(
69
+ agent_file: Optional[str] = typer.Argument(
70
+ None,
71
+ help="Path to agent YAML file or Python file"
72
+ ),
73
+ iterations: int = typer.Option(
74
+ 3,
75
+ "--iterations", "-n",
76
+ help="Number of training iterations"
77
+ ),
78
+ human: bool = typer.Option(
79
+ False,
80
+ "--human", "-h",
81
+ help="Use human feedback instead of LLM grading"
82
+ ),
83
+ scenarios: Optional[str] = typer.Option(
84
+ None,
85
+ "--scenarios", "-s",
86
+ help="Path to scenarios JSON file"
87
+ ),
88
+ input_text: Optional[str] = typer.Option(
89
+ None,
90
+ "--input", "-i",
91
+ help="Single input text for training (alternative to scenarios file)"
92
+ ),
93
+ expected: Optional[str] = typer.Option(
94
+ None,
95
+ "--expected", "-e",
96
+ help="Expected output for the input (optional)"
97
+ ),
98
+ output_dir: Optional[str] = typer.Option(
99
+ None,
100
+ "--output", "-o",
101
+ help="Output directory for training data"
102
+ ),
103
+ model: Optional[str] = typer.Option(
104
+ None,
105
+ "--model", "-m",
106
+ help="LLM model for grading (default: gpt-4o-mini)"
107
+ ),
108
+ verbose: bool = typer.Option(
109
+ True,
110
+ "--verbose/--quiet", "-v/-q",
111
+ help="Show detailed progress"
112
+ ),
113
+ dry_run: bool = typer.Option(
114
+ False,
115
+ "--dry-run",
116
+ help="Show what would happen without running"
117
+ ),
118
+ storage_backend: Optional[str] = typer.Option(
119
+ None,
120
+ "--storage-backend",
121
+ help="Storage backend: 'file', 'sqlite', or 'redis://url'. Default: file"
122
+ ),
123
+ storage_path: Optional[str] = typer.Option(
124
+ None,
125
+ "--storage-path",
126
+ help="Path for storage backend (file dir or sqlite db path)"
127
+ ),
128
+ ):
129
+ """
130
+ Train agents through iterative feedback loops.
131
+
132
+ Two modes available:
133
+
134
+ 1. LLM-as-Judge (default): Agent runs, LLM grades output,
135
+ provides suggestions, agent re-runs with feedback.
136
+ Fully automated, no human intervention needed.
137
+
138
+ 2. Human-in-the-Loop (--human): Agent runs, you review
139
+ and provide feedback, agent re-runs with your feedback.
140
+
141
+ Examples:
142
+ # Simple: Train with a single input
143
+ praisonai train agents --input "What is Python?"
144
+
145
+ # With expected output
146
+ praisonai train agents --input "What is 2+2?" --expected "4"
147
+
148
+ # With scenarios file
149
+ praisonai train agents --scenarios scenarios.json
150
+
151
+ # Human feedback mode
152
+ praisonai train agents --input "Explain AI" --human
153
+
154
+ # More iterations
155
+ praisonai train agents --input "Hello" --iterations 5
156
+
157
+ # With agent file
158
+ praisonai train agents my_agent.yaml --scenarios scenarios.json
159
+ """
160
+ from ..output.console import get_output_controller
161
+
162
+ output = get_output_controller()
163
+
164
+ # Validate inputs
165
+ if not input_text and not scenarios:
166
+ output.print_error(
167
+ "No training input provided",
168
+ remediation="Use --input 'text' or --scenarios file.json"
169
+ )
170
+ raise typer.Exit(1)
171
+
172
+ if dry_run:
173
+ output.print_panel(
174
+ f"Mode: {'Human-in-the-Loop' if human else 'LLM-as-Judge'}\n"
175
+ f"Iterations: {iterations}\n"
176
+ f"Input: {input_text or 'from scenarios file'}\n"
177
+ f"Scenarios file: {scenarios or 'N/A'}\n"
178
+ f"Agent file: {agent_file or 'default agent'}\n"
179
+ f"Output dir: {output_dir or '~/.praison/train/'}",
180
+ title="Dry Run - Would execute:"
181
+ )
182
+ return
183
+
184
+ # Lazy import to avoid overhead
185
+ try:
186
+ from praisonai.train.agents import AgentTrainer, TrainingScenario
187
+ except ImportError as e:
188
+ output.print_error(f"Failed to import training module: {e}")
189
+ raise typer.Exit(1)
190
+
191
+ # Create or load agent
192
+ agent = None
193
+ if agent_file:
194
+ agent = _load_agent_from_file(agent_file, output)
195
+ if agent is None:
196
+ raise typer.Exit(1)
197
+ else:
198
+ # Create a simple default agent
199
+ try:
200
+ from praisonaiagents import Agent
201
+ agent = Agent(
202
+ instructions="You are a helpful assistant. Provide clear, accurate, and helpful responses."
203
+ )
204
+ except ImportError:
205
+ output.print_error(
206
+ "praisonaiagents not installed",
207
+ remediation="pip install praisonaiagents"
208
+ )
209
+ raise typer.Exit(1)
210
+
211
+ # Create trainer
212
+ storage_dir = Path(output_dir) if output_dir else None
213
+
214
+ from praisonai.train.agents.grader import TrainingGrader
215
+ grader = TrainingGrader(model=model) if model else None
216
+
217
+ # Create storage backend if specified
218
+ backend = None
219
+ if storage_backend:
220
+ backend = _create_storage_backend(storage_backend, storage_path, output)
221
+ if backend is None and storage_backend not in ("file", None):
222
+ raise typer.Exit(1)
223
+
224
+ trainer = AgentTrainer(
225
+ agent=agent,
226
+ iterations=iterations,
227
+ human_mode=human,
228
+ grader=grader,
229
+ storage_dir=storage_dir,
230
+ storage_backend=backend,
231
+ verbose=verbose,
232
+ )
233
+
234
+ # Add scenarios
235
+ if scenarios:
236
+ scenarios_list = _load_scenarios_from_file(scenarios, output)
237
+ if scenarios_list is None:
238
+ raise typer.Exit(1)
239
+ trainer.add_scenarios(scenarios_list)
240
+ elif input_text:
241
+ trainer.add_scenario(TrainingScenario(
242
+ id="cli-input",
243
+ input_text=input_text,
244
+ expected_output=expected,
245
+ ))
246
+
247
+ # Run training
248
+ try:
249
+ report = trainer.run()
250
+
251
+ if not verbose:
252
+ report.print_summary()
253
+
254
+ output.print_success(
255
+ f"Training complete! Session: {report.session_id}\n"
256
+ f"Average score: {report.avg_score:.1f}/10\n"
257
+ f"Improvement: {report.improvement:+.1f}"
258
+ )
259
+
260
+ except KeyboardInterrupt:
261
+ output.print_warning("Training interrupted by user")
262
+ raise typer.Exit(130)
263
+ except Exception as e:
264
+ output.print_error(f"Training failed: {e}")
265
+ raise typer.Exit(1)
266
+
267
+
268
+ @app.command("list")
269
+ def train_list(
270
+ limit: int = typer.Option(20, "--limit", "-n", help="Max sessions to show"),
271
+ json_output: bool = typer.Option(False, "--json", "-j", help="Output as JSON"),
272
+ ):
273
+ """List all training sessions."""
274
+ from ..output.console import get_output_controller
275
+
276
+ output = get_output_controller()
277
+
278
+ try:
279
+ from praisonai.train.agents.storage import list_training_sessions
280
+ except ImportError:
281
+ output.print_error("Training module not available")
282
+ raise typer.Exit(1)
283
+
284
+ sessions = list_training_sessions(limit=limit)
285
+
286
+ if json_output or output.is_json_mode:
287
+ output.print_json({
288
+ "sessions": [s.to_dict() for s in sessions]
289
+ })
290
+ return
291
+
292
+ if not sessions:
293
+ output.print_info("No training sessions found")
294
+ return
295
+
296
+ headers = ["Session ID", "Iterations", "Size", "Modified"]
297
+ rows = []
298
+
299
+ for s in sessions:
300
+ modified = s.modified_at.strftime("%Y-%m-%d %H:%M")
301
+ size_kb = s.size_bytes / 1024
302
+ size_str = f"{size_kb:.1f} KB" if size_kb >= 1 else f"{s.size_bytes} B"
303
+
304
+ rows.append([
305
+ s.session_id[:30] + "..." if len(s.session_id) > 30 else s.session_id,
306
+ str(s.iteration_count),
307
+ size_str,
308
+ modified,
309
+ ])
310
+
311
+ output.print_table(headers, rows, title="Training Sessions")
312
+
313
+
314
+ @app.command("show")
315
+ def train_show(
316
+ session_id: str = typer.Argument(..., help="Session ID to show"),
317
+ iterations_flag: bool = typer.Option(False, "--iterations", "-i", help="Show detailed iteration info"),
318
+ json_output: bool = typer.Option(False, "--json", "-j", help="Output as JSON"),
319
+ ):
320
+ """
321
+ Show details of a training session.
322
+
323
+ Examples:
324
+ # Show session summary
325
+ praisonai train show train-abc123
326
+
327
+ # Show with detailed iterations
328
+ praisonai train show train-abc123 --iterations
329
+
330
+ # Output as JSON
331
+ praisonai train show train-abc123 --json
332
+ """
333
+ from ..output.console import get_output_controller
334
+
335
+ output = get_output_controller()
336
+
337
+ try:
338
+ from praisonai.train.agents.storage import TrainingStorage
339
+ except ImportError:
340
+ output.print_error("Training module not available")
341
+ raise typer.Exit(1)
342
+
343
+ storage = TrainingStorage(session_id=session_id)
344
+
345
+ if not storage.storage_path.exists():
346
+ output.print_error(f"Session not found: {session_id}")
347
+ raise typer.Exit(1)
348
+
349
+ report = storage.load_report()
350
+ iterations = storage.load_iterations()
351
+
352
+ if json_output or output.is_json_mode:
353
+ output.print_json({
354
+ "session_id": session_id,
355
+ "report": report.to_dict() if report else None,
356
+ "iterations": [it.to_dict() for it in iterations],
357
+ })
358
+ return
359
+
360
+ if report:
361
+ report.print_summary()
362
+
363
+ # Show best iteration
364
+ best = report.get_best_iteration()
365
+ if best:
366
+ output.print(f"\n✨ Best Iteration: #{best.iteration_num} (Score: {best.score}/10)")
367
+
368
+ if iterations:
369
+ output.print("\nIterations:")
370
+
371
+ # Find best score for highlighting
372
+ best_score = max(it.score for it in iterations) if iterations else 0
373
+
374
+ for it in iterations:
375
+ # Highlight best iteration
376
+ marker = "★" if it.score == best_score else " "
377
+ feedback_preview = it.feedback[:50] + "..." if len(it.feedback) > 50 else it.feedback
378
+ output.print(f" {marker} [{it.iteration_num}] Score: {it.score}/10 - {feedback_preview}")
379
+
380
+ # Show suggestions if --iterations flag
381
+ if iterations_flag and it.suggestions:
382
+ for suggestion in it.suggestions[:3]: # Show top 3 suggestions
383
+ output.print(f" → {suggestion}")
384
+
385
+
386
+ @app.command("apply")
387
+ def train_apply(
388
+ session_id: str = typer.Argument(..., help="Training session ID to apply"),
389
+ agent_file: Optional[str] = typer.Option(
390
+ None,
391
+ "--agent", "-a",
392
+ help="Path to agent YAML file"
393
+ ),
394
+ iteration: Optional[int] = typer.Option(
395
+ None,
396
+ "--iteration", "-n",
397
+ help="Specific iteration number (default: best score)"
398
+ ),
399
+ run_prompt: Optional[str] = typer.Option(
400
+ None,
401
+ "--run", "-r",
402
+ help="Run agent with this prompt after applying training"
403
+ ),
404
+ json_output: bool = typer.Option(False, "--json", "-j", help="Output as JSON"),
405
+ ):
406
+ """
407
+ Apply training to an agent.
408
+
409
+ Loads training suggestions from a session and applies them to an agent
410
+ via hooks. By default, uses the iteration with the best score.
411
+
412
+ Examples:
413
+ # Apply best iteration to default agent
414
+ praisonai train apply train-abc123
415
+
416
+ # Apply specific iteration
417
+ praisonai train apply train-abc123 --iteration 2
418
+
419
+ # Apply to agent from YAML file
420
+ praisonai train apply train-abc123 --agent my_agent.yaml
421
+
422
+ # Apply and run immediately
423
+ praisonai train apply train-abc123 --run "Hello, how are you?"
424
+ """
425
+ from ..output.console import get_output_controller
426
+
427
+ output = get_output_controller()
428
+
429
+ try:
430
+ from praisonai.train.agents import apply_training, get_training_profile
431
+ from praisonai.train.agents.storage import TrainingStorage
432
+ except ImportError as e:
433
+ output.print_error(f"Training module not available: {e}")
434
+ raise typer.Exit(1)
435
+
436
+ # Verify session exists
437
+ storage = TrainingStorage(session_id=session_id)
438
+ if not storage.storage_path.exists():
439
+ output.print_error(f"Session not found: {session_id}")
440
+ raise typer.Exit(1)
441
+
442
+ # Get the training profile
443
+ profile = get_training_profile(
444
+ session_id=session_id,
445
+ iteration=iteration,
446
+ agent_name="agent",
447
+ )
448
+
449
+ if profile is None:
450
+ output.print_error(f"Could not load training profile from session {session_id}")
451
+ raise typer.Exit(1)
452
+
453
+ if json_output or output.is_json_mode:
454
+ output.print_json({
455
+ "session_id": session_id,
456
+ "iteration": profile.iteration_num,
457
+ "score": profile.quality_score,
458
+ "suggestions": profile.suggestions,
459
+ "summary": profile.summary,
460
+ })
461
+ if not run_prompt:
462
+ return
463
+
464
+ # Show profile info
465
+ output.print_panel(
466
+ f"Session: {profile.session_id}\n"
467
+ f"Iteration: {profile.iteration_num}\n"
468
+ f"Score: {profile.quality_score}/10\n"
469
+ f"Suggestions: {len(profile.suggestions)}",
470
+ title="Training Profile"
471
+ )
472
+
473
+ if profile.suggestions:
474
+ output.print("\nSuggestions:")
475
+ for i, suggestion in enumerate(profile.suggestions, 1):
476
+ output.print(f" {i}. {suggestion}")
477
+
478
+ # If run_prompt provided, create agent and run
479
+ if run_prompt:
480
+ # Create or load agent
481
+ agent = None
482
+ if agent_file:
483
+ agent = _load_agent_from_file(agent_file, output)
484
+ if agent is None:
485
+ raise typer.Exit(1)
486
+ else:
487
+ try:
488
+ from praisonaiagents import Agent
489
+ agent = Agent(
490
+ instructions="You are a helpful assistant."
491
+ )
492
+ except ImportError:
493
+ output.print_error(
494
+ "praisonaiagents not installed",
495
+ remediation="pip install praisonaiagents"
496
+ )
497
+ raise typer.Exit(1)
498
+
499
+ # Apply training
500
+ success = apply_training(agent, profile=profile)
501
+ if not success:
502
+ output.print_error("Failed to apply training to agent")
503
+ raise typer.Exit(1)
504
+
505
+ output.print_success("Training applied successfully!")
506
+ output.print(f"\nRunning agent with prompt: {run_prompt}\n")
507
+
508
+ # Run the agent
509
+ try:
510
+ if hasattr(agent, 'chat'):
511
+ response = agent.chat(run_prompt)
512
+ elif hasattr(agent, 'start'):
513
+ response = agent.start(run_prompt)
514
+ else:
515
+ output.print_error("Agent has no chat or start method")
516
+ raise typer.Exit(1)
517
+
518
+ output.print_panel(str(response), title="Agent Response")
519
+ except Exception as e:
520
+ output.print_error(f"Agent execution failed: {e}")
521
+ raise typer.Exit(1)
522
+ else:
523
+ output.print_info(
524
+ "\nTo apply this training to an agent, use:\n"
525
+ f" praisonai train apply {session_id} --run 'Your prompt here'\n"
526
+ "\nOr in Python:\n"
527
+ f" from praisonai.train.agents import apply_training\n"
528
+ f" apply_training(agent, session_id='{session_id}')"
529
+ )
530
+
531
+
532
+ def _load_agent_from_file(file_path: str, output) -> Optional[object]:
533
+ """Load agent from YAML or Python file."""
534
+ path = Path(file_path)
535
+
536
+ if not path.exists():
537
+ output.print_error(f"File not found: {file_path}")
538
+ return None
539
+
540
+ if path.suffix in ('.yaml', '.yml'):
541
+ try:
542
+ from praisonai.cli.main import PraisonAI
543
+ praison = PraisonAI(agent_file=str(path))
544
+ # Return the agents object
545
+ if hasattr(praison, 'agents') and praison.agents:
546
+ return praison.agents
547
+ output.print_error("Could not load agents from YAML")
548
+ return None
549
+ except Exception as e:
550
+ output.print_error(f"Failed to load YAML: {e}")
551
+ return None
552
+
553
+ elif path.suffix == '.py':
554
+ output.print_warning(
555
+ "Python file support coming soon. "
556
+ "For now, use YAML files or --input flag."
557
+ )
558
+ return None
559
+
560
+ else:
561
+ output.print_error(f"Unsupported file type: {path.suffix}")
562
+ return None
563
+
564
+
565
+ def _create_storage_backend(backend_type: str, storage_path: Optional[str], output):
566
+ """Create storage backend from CLI options."""
567
+ try:
568
+ if backend_type == "file":
569
+ from praisonaiagents.storage import FileBackend
570
+ return FileBackend(storage_dir=storage_path or "~/.praison/train")
571
+ elif backend_type == "sqlite":
572
+ from praisonaiagents.storage import SQLiteBackend
573
+ db_path = storage_path or "~/.praison/train.db"
574
+ return SQLiteBackend(db_path=db_path)
575
+ elif backend_type.startswith("redis://"):
576
+ from praisonaiagents.storage import RedisBackend
577
+ return RedisBackend(url=backend_type, prefix="train:")
578
+ else:
579
+ output.print_error(
580
+ f"Unknown storage backend: {backend_type}",
581
+ remediation="Use 'file', 'sqlite', or 'redis://url'"
582
+ )
583
+ return None
584
+ except ImportError as e:
585
+ output.print_error(f"Failed to import storage backend: {e}")
586
+ return None
587
+ except Exception as e:
588
+ output.print_error(f"Failed to create storage backend: {e}")
589
+ return None
590
+
591
+
592
+ def _load_scenarios_from_file(file_path: str, output) -> Optional[list]:
593
+ """Load scenarios from JSON file."""
594
+ path = Path(file_path)
595
+
596
+ if not path.exists():
597
+ output.print_error(f"Scenarios file not found: {file_path}")
598
+ return None
599
+
600
+ try:
601
+ with open(path) as f:
602
+ data = json.load(f)
603
+
604
+ if isinstance(data, list):
605
+ return data
606
+ elif isinstance(data, dict) and "scenarios" in data:
607
+ return data["scenarios"]
608
+ else:
609
+ output.print_error("Invalid scenarios format. Expected list or {scenarios: [...]}")
610
+ return None
611
+ except json.JSONDecodeError as e:
612
+ output.print_error(f"Invalid JSON: {e}")
613
+ return None