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,54 @@
1
+ """
2
+ Templates command group for PraisonAI CLI.
3
+
4
+ Provides template management commands.
5
+ """
6
+
7
+ import typer
8
+
9
+ app = typer.Typer(help="Template management")
10
+
11
+
12
+ @app.command("list")
13
+ def templates_list():
14
+ """List available templates."""
15
+ from praisonai.cli.main import PraisonAI
16
+ import sys
17
+
18
+ argv = ['templates', 'list']
19
+
20
+ original_argv = sys.argv
21
+ sys.argv = ['praisonai'] + argv
22
+
23
+ try:
24
+ praison = PraisonAI()
25
+ praison.main()
26
+ except SystemExit:
27
+ pass
28
+ finally:
29
+ sys.argv = original_argv
30
+
31
+
32
+ @app.command("create")
33
+ def templates_create(
34
+ name: str = typer.Argument(..., help="Template name"),
35
+ source: str = typer.Option(None, "--source", "-s", help="Source file to create template from"),
36
+ ):
37
+ """Create a new template."""
38
+ from praisonai.cli.main import PraisonAI
39
+ import sys
40
+
41
+ argv = ['templates', 'create', name]
42
+ if source:
43
+ argv.extend(['--source', source])
44
+
45
+ original_argv = sys.argv
46
+ sys.argv = ['praisonai'] + argv
47
+
48
+ try:
49
+ praison = PraisonAI()
50
+ praison.main()
51
+ except SystemExit:
52
+ pass
53
+ finally:
54
+ sys.argv = original_argv
@@ -0,0 +1,558 @@
1
+ """
2
+ PraisonAI Test CLI Command
3
+
4
+ Provides a unified interface for running tests with tier and provider options.
5
+
6
+ Usage:
7
+ praisonai test # Run main tier (default)
8
+ praisonai test --tier smoke # Run smoke tests only
9
+ praisonai test --tier extended # Run extended tests
10
+ praisonai test --provider openai # Run OpenAI provider tests
11
+ praisonai test --live # Enable live API tests
12
+ praisonai test --parallel auto # Run with parallelization
13
+
14
+ # Interactive mode tests
15
+ praisonai test interactive --csv tests.csv
16
+ praisonai test interactive --suite smoke
17
+ praisonai test interactive --list
18
+ praisonai test interactive --generate-template
19
+ """
20
+
21
+ import os
22
+ import subprocess
23
+ from typing import Optional, List
24
+
25
+ import typer
26
+
27
+ app = typer.Typer(help="Run PraisonAI test suite with tier and provider options")
28
+
29
+
30
+ def _get_pytest_args(
31
+ tier: str,
32
+ provider: Optional[str],
33
+ live: bool,
34
+ parallel: Optional[str],
35
+ verbose: bool,
36
+ coverage: bool,
37
+ ) -> List[str]:
38
+ """Build pytest arguments based on options."""
39
+ args = ["python", "-m", "pytest"]
40
+
41
+ # Base test paths
42
+ if tier == "smoke":
43
+ args.append("tests/unit/")
44
+ elif tier == "main":
45
+ args.extend(["tests/unit/", "tests/integration/"])
46
+ elif tier in ("extended", "nightly"):
47
+ args.append("tests/")
48
+ else:
49
+ args.append("tests/")
50
+
51
+ # Always ignore fixtures directory
52
+ args.extend(["--ignore=tests/fixtures"])
53
+
54
+ # Tier-specific markers
55
+ if tier == "smoke":
56
+ args.extend(["-m", "not slow and not network"])
57
+ elif tier == "main":
58
+ # Exclude non-OpenAI providers by default
59
+ args.extend([
60
+ "-m",
61
+ "not provider_anthropic and not provider_google and not provider_ollama and not provider_grok_xai and not provider_groq and not provider_cohere"
62
+ ])
63
+
64
+ # Provider-specific filter
65
+ if provider:
66
+ if provider == "all":
67
+ pass # No filter
68
+ else:
69
+ provider_marker = f"provider_{provider}"
70
+ args.extend(["-m", provider_marker])
71
+
72
+ # Verbosity
73
+ if verbose:
74
+ args.append("-v")
75
+ else:
76
+ args.append("-q")
77
+
78
+ args.append("--tb=short")
79
+
80
+ # Timeout
81
+ if tier == "smoke":
82
+ args.extend(["--timeout=30"])
83
+ elif tier == "main":
84
+ args.extend(["--timeout=60"])
85
+ else:
86
+ args.extend(["--timeout=120"])
87
+
88
+ # Coverage
89
+ if coverage:
90
+ args.extend([
91
+ "--cov=praisonai",
92
+ "--cov-report=term-missing",
93
+ "--cov-report=xml"
94
+ ])
95
+
96
+ # Parallelization
97
+ if parallel:
98
+ if parallel == "auto":
99
+ args.extend(["-n", "auto"])
100
+ else:
101
+ args.extend(["-n", parallel])
102
+
103
+ return args
104
+
105
+
106
+ def _set_environment(tier: str, provider: Optional[str], live: bool):
107
+ """Set environment variables for test run."""
108
+ os.environ["PRAISONAI_TEST_TIER"] = tier
109
+
110
+ if live:
111
+ os.environ["PRAISONAI_ALLOW_NETWORK"] = "1"
112
+ os.environ["PRAISONAI_LIVE_TESTS"] = "1"
113
+ else:
114
+ os.environ["PRAISONAI_ALLOW_NETWORK"] = "0"
115
+ os.environ["PRAISONAI_LIVE_TESTS"] = "0"
116
+
117
+ if provider:
118
+ os.environ["PRAISONAI_TEST_PROVIDERS"] = provider
119
+
120
+
121
+ def _print_skip_summary(tier: str, provider: Optional[str], live: bool):
122
+ """Print summary of what will be skipped."""
123
+ typer.echo("\nšŸ“‹ Test Configuration:")
124
+ typer.echo(f" Tier: {tier}")
125
+ typer.echo(f" Provider: {provider or 'all (gated)'}")
126
+ typer.echo(f" Live tests: {'enabled' if live else 'disabled'}")
127
+ typer.echo("")
128
+
129
+ if not live:
130
+ typer.echo("āš ļø Network tests will be skipped (use --live to enable)")
131
+
132
+ if tier == "smoke":
133
+ typer.echo("ā„¹ļø Running unit tests only (no integration/e2e)")
134
+ elif tier == "main":
135
+ typer.echo("ā„¹ļø Skipping non-OpenAI provider tests")
136
+
137
+ typer.echo("")
138
+
139
+
140
+ @app.command()
141
+ def run(
142
+ tier: str = typer.Option(
143
+ "main",
144
+ "--tier", "-t",
145
+ help="Test tier: smoke (fast), main (default), extended, nightly"
146
+ ),
147
+ provider: Optional[str] = typer.Option(
148
+ None,
149
+ "--provider", "-p",
150
+ help="Run tests for specific provider: openai, anthropic, google, ollama, grok_xai, groq, cohere, all"
151
+ ),
152
+ live: bool = typer.Option(
153
+ False,
154
+ "--live", "-l",
155
+ help="Enable live API tests (requires API keys)"
156
+ ),
157
+ allow_network: bool = typer.Option(
158
+ False,
159
+ "--allow-network",
160
+ help="Allow network access in tests"
161
+ ),
162
+ parallel: Optional[str] = typer.Option(
163
+ None,
164
+ "--parallel", "-n",
165
+ help="Run tests in parallel: auto or number of workers"
166
+ ),
167
+ verbose: bool = typer.Option(
168
+ False,
169
+ "--verbose", "-v",
170
+ help="Verbose output"
171
+ ),
172
+ coverage: bool = typer.Option(
173
+ False,
174
+ "--coverage", "-c",
175
+ help="Generate coverage report"
176
+ ),
177
+ fail_fast: bool = typer.Option(
178
+ False,
179
+ "--fail-fast", "-x",
180
+ help="Stop on first failure"
181
+ ),
182
+ ):
183
+ """
184
+ Run the PraisonAI test suite.
185
+
186
+ Examples:
187
+ praisonai test # Run main tier
188
+ praisonai test --tier smoke # Fast smoke tests
189
+ praisonai test --tier extended # Extended tests
190
+ praisonai test --provider openai --live # OpenAI live tests
191
+ praisonai test --parallel auto # Parallel execution
192
+ """
193
+ # Validate tier
194
+ valid_tiers = ["smoke", "main", "extended", "nightly"]
195
+ if tier not in valid_tiers:
196
+ typer.echo(f"āŒ Invalid tier: {tier}. Must be one of: {', '.join(valid_tiers)}")
197
+ raise typer.Exit(1)
198
+
199
+ # Validate provider
200
+ valid_providers = ["openai", "anthropic", "google", "ollama", "grok_xai", "groq", "cohere", "all"]
201
+ if provider and provider not in valid_providers:
202
+ typer.echo(f"āŒ Invalid provider: {provider}. Must be one of: {', '.join(valid_providers)}")
203
+ raise typer.Exit(1)
204
+
205
+ # Set environment
206
+ _set_environment(tier, provider, live or allow_network)
207
+
208
+ # Print summary
209
+ _print_skip_summary(tier, provider, live or allow_network)
210
+
211
+ # Build pytest args
212
+ args = _get_pytest_args(tier, provider, live or allow_network, parallel, verbose, coverage)
213
+
214
+ if fail_fast:
215
+ args.append("-x")
216
+
217
+ # Print command
218
+ typer.echo(f"🧪 Running: {' '.join(args)}")
219
+ typer.echo("")
220
+
221
+ # Find the tests directory
222
+ # Try current directory first, then src/praisonai
223
+ test_dirs = [
224
+ os.getcwd(),
225
+ os.path.join(os.getcwd(), "src", "praisonai"),
226
+ os.path.dirname(os.path.dirname(os.path.dirname(os.path.dirname(__file__)))),
227
+ ]
228
+
229
+ cwd = None
230
+ for test_dir in test_dirs:
231
+ if os.path.isdir(os.path.join(test_dir, "tests")):
232
+ cwd = test_dir
233
+ break
234
+
235
+ if not cwd:
236
+ typer.echo("āŒ Could not find tests directory")
237
+ raise typer.Exit(1)
238
+
239
+ # Run pytest
240
+ try:
241
+ result = subprocess.run(args, cwd=cwd)
242
+ raise typer.Exit(result.returncode)
243
+ except KeyboardInterrupt:
244
+ typer.echo("\nāŒ Tests interrupted")
245
+ raise typer.Exit(1)
246
+
247
+
248
+ # Built-in interactive test suites
249
+ BUILTIN_SUITES = {
250
+ "smoke": "smoke.csv",
251
+ "tools": "tools.csv",
252
+ "refactor": "refactor.csv",
253
+ "multi_agent": "multi_agent.csv",
254
+ }
255
+
256
+ # Special suites that don't use CSV
257
+ SPECIAL_SUITES = {
258
+ "advanced": "Advanced Agent-Centric (5 complex autonomous scenarios)",
259
+ }
260
+
261
+
262
+ def _get_builtin_suite_path(suite: str):
263
+ """Get path to built-in test suite."""
264
+ from pathlib import Path
265
+
266
+ if suite not in BUILTIN_SUITES:
267
+ return None
268
+
269
+ # Find fixtures directory relative to package
270
+ package_dir = Path(__file__).parent.parent.parent.parent # Up to src/praisonai
271
+ fixtures_dir = package_dir / "tests" / "fixtures" / "interactive"
272
+
273
+ suite_path = fixtures_dir / BUILTIN_SUITES[suite]
274
+ if suite_path.exists():
275
+ return suite_path
276
+
277
+ return None
278
+
279
+
280
+ @app.command("interactive")
281
+ def interactive(
282
+ csv: Optional[str] = typer.Option(
283
+ None, "--csv", "-c",
284
+ help="Path to CSV file with test cases"
285
+ ),
286
+ suite: Optional[str] = typer.Option(
287
+ None, "--suite", "-s",
288
+ help="Built-in test suite: smoke, tools, refactor, multi_agent"
289
+ ),
290
+ model: str = typer.Option(
291
+ "gpt-4o-mini", "--model", "-m",
292
+ help="LLM model for agent"
293
+ ),
294
+ judge_model: str = typer.Option(
295
+ "gpt-4o-mini", "--judge-model",
296
+ help="LLM model for judge"
297
+ ),
298
+ workspace: Optional[str] = typer.Option(
299
+ None, "--workspace", "-w",
300
+ help="Workspace directory (default: temp)"
301
+ ),
302
+ artifacts_dir: Optional[str] = typer.Option(
303
+ None, "--artifacts-dir",
304
+ help="Directory for test artifacts"
305
+ ),
306
+ fail_fast: bool = typer.Option(
307
+ False, "--fail-fast", "-x",
308
+ help="Stop on first failure"
309
+ ),
310
+ keep_artifacts: bool = typer.Option(
311
+ False, "--keep-artifacts",
312
+ help="Keep test artifacts after run"
313
+ ),
314
+ no_judge: bool = typer.Option(
315
+ False, "--no-judge",
316
+ help="Skip judge evaluation even if rubric present"
317
+ ),
318
+ verbose: bool = typer.Option(
319
+ False, "--verbose", "-v",
320
+ help="Verbose output"
321
+ ),
322
+ list_suites: bool = typer.Option(
323
+ False, "--list",
324
+ help="List available built-in suites"
325
+ ),
326
+ generate_template: bool = typer.Option(
327
+ False, "--generate-template",
328
+ help="Generate CSV template in current directory"
329
+ ),
330
+ ):
331
+ """
332
+ Run interactive mode tests from CSV.
333
+
334
+ Tests are executed through the headless interactive core, using the same
335
+ pipeline as the interactive TUI (InteractiveRuntime, get_interactive_tools,
336
+ ActionOrchestrator).
337
+
338
+ Examples:
339
+ praisonai test interactive --csv tests.csv
340
+ praisonai test interactive --suite smoke
341
+ praisonai test interactive --suite tools --keep-artifacts
342
+ praisonai test interactive --list
343
+ praisonai test interactive --generate-template
344
+ """
345
+ from pathlib import Path
346
+
347
+ # List suites
348
+ if list_suites:
349
+ typer.echo("šŸ“‹ Available built-in test suites:")
350
+ typer.echo("")
351
+ typer.echo("CSV-based suites:")
352
+ for name, filename in BUILTIN_SUITES.items():
353
+ suite_path = _get_builtin_suite_path(name)
354
+ status = "āœ…" if suite_path else "āŒ (not found)"
355
+ typer.echo(f" {name:15} {filename:20} {status}")
356
+ typer.echo("")
357
+ typer.echo("Special suites:")
358
+ for name, description in SPECIAL_SUITES.items():
359
+ typer.echo(f" {name:15} {description}")
360
+ typer.echo("")
361
+ typer.echo("Usage: praisonai test interactive --suite <name>")
362
+ typer.echo(" PRAISONAI_LIVE_INTERACTIVE=1 praisonai test interactive --suite advanced")
363
+ return
364
+
365
+ # Generate template
366
+ if generate_template:
367
+ # Lazy import
368
+ from praisonai.cli.features.csv_test_runner import generate_csv_template
369
+
370
+ output_path = Path.cwd() / "interactive_tests_template.csv"
371
+ generate_csv_template(output_path)
372
+ typer.echo(f"āœ… Generated CSV template: {output_path}")
373
+ return
374
+
375
+ # Validate inputs
376
+ if not csv and not suite:
377
+ typer.echo("āŒ Either --csv or --suite is required")
378
+ typer.echo("")
379
+ typer.echo("Examples:")
380
+ typer.echo(" praisonai test interactive --csv tests.csv")
381
+ typer.echo(" praisonai test interactive --suite smoke")
382
+ typer.echo(" praisonai test interactive --suite advanced")
383
+ typer.echo(" praisonai test interactive --list")
384
+ raise typer.Exit(1)
385
+
386
+ # Handle special suites
387
+ if suite and suite in SPECIAL_SUITES:
388
+ if suite == "advanced":
389
+ _run_advanced_suite(
390
+ model=model,
391
+ artifacts_dir=Path(artifacts_dir) if artifacts_dir else None,
392
+ keep_artifacts=keep_artifacts,
393
+ verbose=verbose,
394
+ )
395
+ return
396
+
397
+ # Get CSV path
398
+ if csv:
399
+ csv_path = Path(csv)
400
+ if not csv_path.exists():
401
+ typer.echo(f"āŒ CSV file not found: {csv}")
402
+ raise typer.Exit(1)
403
+ else:
404
+ csv_path = _get_builtin_suite_path(suite)
405
+ if not csv_path:
406
+ typer.echo(f"āŒ Built-in suite not found: {suite}")
407
+ typer.echo("Use --list to see available suites")
408
+ raise typer.Exit(1)
409
+
410
+ # Lazy import runner
411
+ from praisonai.cli.features.csv_test_runner import CSVTestRunner
412
+
413
+ typer.echo(f"🧪 Running interactive tests from: {csv_path}")
414
+ typer.echo(f" Model: {model} | Judge: {judge_model}")
415
+ typer.echo("")
416
+
417
+ # Create runner
418
+ runner = CSVTestRunner(
419
+ csv_path=csv_path,
420
+ model=model,
421
+ judge_model=judge_model,
422
+ workspace=Path(workspace) if workspace else None,
423
+ artifacts_dir=Path(artifacts_dir) if artifacts_dir else None,
424
+ fail_fast=fail_fast,
425
+ keep_artifacts=keep_artifacts,
426
+ no_judge=no_judge,
427
+ verbose=verbose,
428
+ )
429
+
430
+ # Run tests
431
+ summary = runner.run()
432
+
433
+ # Print summary
434
+ typer.echo("")
435
+ summary.print_summary()
436
+
437
+ # Save summary if keeping artifacts
438
+ if keep_artifacts and runner.artifacts_dir:
439
+ import json
440
+ summary_path = runner.artifacts_dir / "summary.json"
441
+ summary_path.parent.mkdir(parents=True, exist_ok=True)
442
+ with open(summary_path, "w") as f:
443
+ json.dump(summary.to_dict(), f, indent=2, default=str)
444
+ typer.echo(f"\nšŸ“ Artifacts saved to: {runner.artifacts_dir}")
445
+
446
+ # Exit code based on results
447
+ if summary.failed > 0 or summary.errors > 0:
448
+ raise typer.Exit(1)
449
+
450
+
451
+ def _run_advanced_suite(
452
+ model: str = "gpt-4o-mini",
453
+ artifacts_dir = None,
454
+ keep_artifacts: bool = True,
455
+ verbose: bool = True,
456
+ ):
457
+ """Run the Advanced Agent-Centric test suite."""
458
+ from pathlib import Path
459
+
460
+ # Check prerequisites
461
+ typer.echo("šŸ” Checking Advanced suite prerequisites...")
462
+
463
+ # Check if live interactive is enabled
464
+ live_enabled = os.environ.get("PRAISONAI_LIVE_INTERACTIVE", "0") == "1"
465
+ has_api_key = bool(os.environ.get("OPENAI_API_KEY"))
466
+
467
+ if not live_enabled:
468
+ typer.echo("\nāš ļø Cannot run Advanced tests: PRAISONAI_LIVE_INTERACTIVE=1 not set")
469
+ typer.echo("")
470
+ typer.echo("Prerequisites:")
471
+ typer.echo(" 1. Set PRAISONAI_LIVE_INTERACTIVE=1")
472
+ typer.echo(" 2. Set OPENAI_API_KEY")
473
+ typer.echo("")
474
+ typer.echo("Example:")
475
+ typer.echo(" PRAISONAI_LIVE_INTERACTIVE=1 praisonai test interactive --suite advanced")
476
+ raise typer.Exit(1)
477
+
478
+ if not has_api_key:
479
+ typer.echo("\nāš ļø Cannot run Advanced tests: OPENAI_API_KEY not set")
480
+ raise typer.Exit(1)
481
+
482
+ typer.echo("āœ… Live interactive mode enabled")
483
+ typer.echo("āœ… API key configured")
484
+ typer.echo("")
485
+
486
+ # Lazy import runner and scenarios
487
+ from tests.live.interactive.runner import LiveInteractiveRunner
488
+ from tests.live.interactive.advanced.scenarios import ALL_ADVANCED_SCENARIOS
489
+
490
+ # Create runner
491
+ runner = LiveInteractiveRunner(
492
+ model=model,
493
+ artifacts_dir=Path(artifacts_dir) if artifacts_dir else None,
494
+ keep_artifacts=keep_artifacts,
495
+ verbose=verbose,
496
+ )
497
+
498
+ # Run tests
499
+ summary = runner.run_all(ALL_ADVANCED_SCENARIOS)
500
+
501
+ # Print summary
502
+ typer.echo("")
503
+ summary.print_summary()
504
+
505
+ # Show artifacts location
506
+ if keep_artifacts:
507
+ typer.echo(f"\nšŸ“ Artifacts saved to: {runner.artifacts_dir}")
508
+
509
+ # Exit code
510
+ if summary.failed > 0:
511
+ raise typer.Exit(1)
512
+
513
+
514
+ @app.command()
515
+ def info():
516
+ """Show test configuration and available options."""
517
+ typer.echo("šŸ“Š PraisonAI Test Suite Information")
518
+ typer.echo("=" * 50)
519
+ typer.echo("")
520
+
521
+ typer.echo("šŸŽÆ Test Tiers:")
522
+ typer.echo(" smoke - Fast unit tests, no network (≤2 min)")
523
+ typer.echo(" main - Unit + integration, OpenAI only (≤5 min)")
524
+ typer.echo(" extended - All providers, gated by keys (≤15 min)")
525
+ typer.echo(" nightly - Full matrix + stress tests (≤30 min)")
526
+ typer.echo("")
527
+
528
+ typer.echo("šŸ”Œ Providers:")
529
+ providers = {
530
+ "openai": "OPENAI_API_KEY",
531
+ "anthropic": "ANTHROPIC_API_KEY",
532
+ "google": "GOOGLE_API_KEY",
533
+ "ollama": "(local service)",
534
+ "grok_xai": "XAI_API_KEY",
535
+ "groq": "GROQ_API_KEY",
536
+ "cohere": "COHERE_API_KEY",
537
+ }
538
+ for provider, env_var in providers.items():
539
+ status = "āœ…" if os.environ.get(env_var.replace("(local service)", "")) else "āŒ"
540
+ if env_var == "(local service)":
541
+ status = "šŸ”§"
542
+ typer.echo(f" {provider:12} {env_var:25} {status}")
543
+ typer.echo("")
544
+
545
+ typer.echo("🌐 Environment Variables:")
546
+ env_vars = {
547
+ "PRAISONAI_TEST_TIER": os.environ.get("PRAISONAI_TEST_TIER", "main"),
548
+ "PRAISONAI_ALLOW_NETWORK": os.environ.get("PRAISONAI_ALLOW_NETWORK", "0"),
549
+ "PRAISONAI_LIVE_TESTS": os.environ.get("PRAISONAI_LIVE_TESTS", "0"),
550
+ "PRAISONAI_TEST_PROVIDERS": os.environ.get("PRAISONAI_TEST_PROVIDERS", "openai"),
551
+ "PRAISONAI_LOCAL_SERVICES": os.environ.get("PRAISONAI_LOCAL_SERVICES", "0"),
552
+ }
553
+ for var, value in env_vars.items():
554
+ typer.echo(f" {var}: {value}")
555
+
556
+
557
+ if __name__ == "__main__":
558
+ app()
@@ -0,0 +1,74 @@
1
+ """
2
+ Todo command group for PraisonAI CLI.
3
+
4
+ Provides todo/task management commands.
5
+ """
6
+
7
+ import typer
8
+
9
+ app = typer.Typer(help="Todo/task management")
10
+
11
+
12
+ @app.command("list")
13
+ def todo_list():
14
+ """List todos."""
15
+ from praisonai.cli.main import PraisonAI
16
+ import sys
17
+
18
+ argv = ['todo', 'list']
19
+
20
+ original_argv = sys.argv
21
+ sys.argv = ['praisonai'] + argv
22
+
23
+ try:
24
+ praison = PraisonAI()
25
+ praison.main()
26
+ except SystemExit:
27
+ pass
28
+ finally:
29
+ sys.argv = original_argv
30
+
31
+
32
+ @app.command("add")
33
+ def todo_add(
34
+ task: str = typer.Argument(..., help="Task description"),
35
+ priority: str = typer.Option("medium", "--priority", "-p", help="Priority (low, medium, high)"),
36
+ ):
37
+ """Add a todo."""
38
+ from praisonai.cli.main import PraisonAI
39
+ import sys
40
+
41
+ argv = ['todo', 'add', task]
42
+
43
+ original_argv = sys.argv
44
+ sys.argv = ['praisonai'] + argv
45
+
46
+ try:
47
+ praison = PraisonAI()
48
+ praison.main()
49
+ except SystemExit:
50
+ pass
51
+ finally:
52
+ sys.argv = original_argv
53
+
54
+
55
+ @app.command("done")
56
+ def todo_done(
57
+ task_id: str = typer.Argument(..., help="Task ID to mark as done"),
58
+ ):
59
+ """Mark a todo as done."""
60
+ from praisonai.cli.main import PraisonAI
61
+ import sys
62
+
63
+ argv = ['todo', 'done', task_id]
64
+
65
+ original_argv = sys.argv
66
+ sys.argv = ['praisonai'] + argv
67
+
68
+ try:
69
+ praison = PraisonAI()
70
+ praison.main()
71
+ except SystemExit:
72
+ pass
73
+ finally:
74
+ sys.argv = original_argv