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,49 @@
1
+ """
2
+ Research command group for PraisonAI CLI.
3
+
4
+ Provides research and analysis commands.
5
+ """
6
+
7
+ import typer
8
+
9
+ app = typer.Typer(help="Research and analysis")
10
+
11
+
12
+ @app.callback(invoke_without_command=True)
13
+ def research_main(
14
+ ctx: typer.Context,
15
+ query: str = typer.Argument(None, help="Research query"),
16
+ model: str = typer.Option(None, "--model", "-m", help="LLM model to use"),
17
+ verbose: bool = typer.Option(False, "--verbose", "-v", help="Verbose output"),
18
+ output: str = typer.Option(None, "--output", "-o", help="Output file path"),
19
+ ):
20
+ """
21
+ Run research and analysis tasks.
22
+
23
+ Examples:
24
+ praisonai research "What are the latest AI trends?"
25
+ praisonai research --model gpt-4o "Analyze market data"
26
+ """
27
+ from praisonai.cli.main import PraisonAI
28
+ import sys
29
+
30
+ argv = ['research']
31
+ if query:
32
+ argv.append(query)
33
+ if model:
34
+ argv.extend(['--model', model])
35
+ if verbose:
36
+ argv.append('--verbose')
37
+ if output:
38
+ argv.extend(['--output', output])
39
+
40
+ original_argv = sys.argv
41
+ sys.argv = ['praisonai'] + argv
42
+
43
+ try:
44
+ praison = PraisonAI()
45
+ praison.main()
46
+ except SystemExit:
47
+ pass
48
+ finally:
49
+ sys.argv = original_argv
@@ -0,0 +1,377 @@
1
+ """
2
+ Unified Retrieval CLI Commands - Agent-First Experience
3
+
4
+ This module provides the unified CLI commands for knowledge and retrieval:
5
+ - `praisonai index` - Index documents into knowledge base
6
+ - `praisonai query` - Query with structured answer and citations
7
+ - `praisonai chat` - Conversational interface with knowledge (handled by chat.py)
8
+
9
+ These commands replace the separate `knowledge` and `rag` command families.
10
+ """
11
+
12
+ import typer
13
+ from pathlib import Path
14
+ from typing import List, Optional
15
+ from contextlib import contextmanager
16
+ import time
17
+ import sys
18
+
19
+ app = typer.Typer(
20
+ name="retrieval",
21
+ help="Knowledge indexing and retrieval commands",
22
+ no_args_is_help=True,
23
+ )
24
+
25
+
26
+ @contextmanager
27
+ def retrieval_profiler(profile: bool, profile_out: Optional[Path], profile_top: int):
28
+ """Context manager for profiling retrieval operations."""
29
+ if not profile:
30
+ yield None
31
+ return
32
+
33
+ import json as json_module
34
+
35
+ start_time = time.perf_counter()
36
+ start_modules = set(sys.modules.keys())
37
+
38
+ profile_data = {
39
+ "metrics": {},
40
+ "modules_loaded": [],
41
+ }
42
+
43
+ try:
44
+ import tracemalloc
45
+ tracemalloc.start()
46
+ has_tracemalloc = True
47
+ except ImportError:
48
+ has_tracemalloc = False
49
+
50
+ yield profile_data
51
+
52
+ elapsed_ms = (time.perf_counter() - start_time) * 1000
53
+ profile_data["metrics"]["elapsed_ms"] = elapsed_ms
54
+
55
+ if has_tracemalloc:
56
+ current, peak = tracemalloc.get_traced_memory()
57
+ tracemalloc.stop()
58
+ profile_data["metrics"]["peak_memory_mb"] = peak / 1024 / 1024
59
+
60
+ new_modules = set(sys.modules.keys()) - start_modules
61
+ profile_data["modules_loaded"] = sorted(list(new_modules))[:profile_top]
62
+
63
+ if profile_out:
64
+ try:
65
+ profile_out.parent.mkdir(parents=True, exist_ok=True)
66
+ with open(profile_out, "w") as f:
67
+ json_module.dump(profile_data, f, indent=2, default=str)
68
+ except Exception as e:
69
+ print(f"Warning: Failed to save profile: {e}")
70
+
71
+ from rich.console import Console
72
+ console = Console(stderr=True)
73
+ console.print(f"\n[dim]Profile: {elapsed_ms:.2f}ms wall time[/dim]")
74
+ if "peak_memory_mb" in profile_data["metrics"]:
75
+ console.print(f"[dim]Profile: {profile_data['metrics']['peak_memory_mb']:.2f}MB peak memory[/dim]")
76
+ console.print(f"[dim]Profile: {len(new_modules)} modules imported[/dim]")
77
+ if profile_out:
78
+ console.print(f"[dim]Profile saved to: {profile_out}[/dim]")
79
+
80
+
81
+ @app.command("index")
82
+ def index_command(
83
+ sources: List[str] = typer.Argument(..., help="Source files, directories, or URLs to index"),
84
+ collection: str = typer.Option("default", "--collection", "-c", help="Collection/knowledge base name"),
85
+ config: Optional[Path] = typer.Option(None, "--config", "-f", help="Config file path"),
86
+ verbose: bool = typer.Option(False, "--verbose", "-v", help="Verbose output"),
87
+ profile: bool = typer.Option(False, "--profile", help="Enable performance profiling"),
88
+ profile_out: Optional[Path] = typer.Option(None, "--profile-out", help="Save profile to JSON file"),
89
+ profile_top: int = typer.Option(20, "--profile-top", help="Top N items in profile"),
90
+ ):
91
+ """
92
+ Index documents into a knowledge base.
93
+
94
+ This is the canonical command for adding documents to a knowledge base.
95
+ Use `praisonai query` to get answers with citations from the indexed knowledge.
96
+
97
+ Examples:
98
+ praisonai index ./docs
99
+ praisonai index paper.pdf --collection research
100
+ praisonai index ./data --profile --profile-out ./profile.json
101
+ """
102
+ from rich.console import Console
103
+ from rich.progress import Progress, SpinnerColumn, TextColumn
104
+
105
+ console = Console()
106
+
107
+ with retrieval_profiler(profile, profile_out, profile_top) as profile_data:
108
+ try:
109
+ from praisonaiagents.knowledge import Knowledge
110
+
111
+ knowledge_config = {
112
+ "vector_store": {
113
+ "provider": "chroma",
114
+ "config": {
115
+ "collection_name": collection,
116
+ "path": f"./.praison/knowledge/{collection}",
117
+ }
118
+ }
119
+ }
120
+
121
+ if config and config.exists():
122
+ import yaml
123
+ with open(config) as f:
124
+ file_config = yaml.safe_load(f)
125
+ if "knowledge" in file_config:
126
+ knowledge_config.update(file_config["knowledge"])
127
+
128
+ knowledge = Knowledge(config=knowledge_config, verbose=verbose)
129
+
130
+ with Progress(
131
+ SpinnerColumn(),
132
+ TextColumn("[progress.description]{task.description}"),
133
+ console=console,
134
+ transient=True,
135
+ ) as progress:
136
+ for source in sources:
137
+ task = progress.add_task(f"Indexing {source}...", total=None)
138
+ try:
139
+ result = knowledge.add(source)
140
+ count = len(result.get("results", [])) if isinstance(result, dict) else 0
141
+ console.print(f"[green]✓[/green] Indexed {source}: {count} chunks")
142
+ except Exception as e:
143
+ console.print(f"[red]✗[/red] Failed to index {source}: {e}")
144
+ progress.remove_task(task)
145
+
146
+ console.print(f"\n[bold green]Indexing complete![/bold green] Collection: {collection}")
147
+ if profile_data:
148
+ profile_data["command"] = "index"
149
+ profile_data["collection"] = collection
150
+ profile_data["sources"] = sources
151
+
152
+ except ImportError as e:
153
+ console.print(f"[red]Error:[/red] Missing dependency: {e}")
154
+ console.print("Install with: pip install 'praisonaiagents[knowledge]'")
155
+ raise typer.Exit(1)
156
+ except Exception as e:
157
+ console.print(f"[red]Error:[/red] {e}")
158
+ raise typer.Exit(1)
159
+
160
+
161
+ @app.command("query")
162
+ def query_command(
163
+ question: str = typer.Argument(..., help="Question to answer"),
164
+ collection: str = typer.Option("default", "--collection", "-c", help="Collection to query"),
165
+ top_k: int = typer.Option(5, "--top-k", "-k", help="Number of results to retrieve"),
166
+ min_score: float = typer.Option(0.0, "--min-score", help="Minimum relevance score (0.0-1.0)"),
167
+ hybrid: bool = typer.Option(False, "--hybrid", help="Use hybrid retrieval (dense + keyword)"),
168
+ rerank: bool = typer.Option(False, "--rerank", help="Enable reranking of results"),
169
+ citations: bool = typer.Option(True, "--citations/--no-citations", help="Include citations"),
170
+ citations_mode: str = typer.Option("append", "--citations-mode", help="Citations mode: append, inline, hidden"),
171
+ max_context_tokens: int = typer.Option(4000, "--max-context-tokens", help="Maximum context tokens"),
172
+ config: Optional[Path] = typer.Option(None, "--config", "-f", help="Config file path"),
173
+ verbose: bool = typer.Option(False, "--verbose", "-v", help="Verbose output"),
174
+ profile: bool = typer.Option(False, "--profile", help="Enable performance profiling"),
175
+ profile_out: Optional[Path] = typer.Option(None, "--profile-out", help="Save profile to JSON file"),
176
+ profile_top: int = typer.Option(20, "--profile-top", help="Top N items in profile"),
177
+ ):
178
+ """
179
+ Query knowledge and get a structured answer with citations.
180
+
181
+ Uses the Agent-first retrieval pipeline with token-aware context building.
182
+
183
+ Examples:
184
+ praisonai query "What is the main finding?"
185
+ praisonai query "Summarize the document" --collection research
186
+ praisonai query "Key points?" --top-k 10 --no-citations
187
+ praisonai query "Summary?" --hybrid --rerank
188
+ """
189
+ from rich.console import Console
190
+ from rich.panel import Panel
191
+ from rich.markdown import Markdown
192
+
193
+ console = Console()
194
+
195
+ with retrieval_profiler(profile, profile_out, profile_top) as profile_data:
196
+ try:
197
+ from praisonaiagents import Agent
198
+ from praisonaiagents.rag.retrieval_config import RetrievalConfig, RetrievalPolicy, CitationsMode
199
+
200
+ retrieval_config = RetrievalConfig(
201
+ enabled=True,
202
+ policy=RetrievalPolicy.ALWAYS,
203
+ top_k=top_k,
204
+ min_score=min_score,
205
+ max_context_tokens=max_context_tokens,
206
+ rerank=rerank,
207
+ hybrid=hybrid,
208
+ citations=citations,
209
+ citations_mode=CitationsMode(citations_mode),
210
+ vector_store_provider="chroma",
211
+ persist_path=f"./.praison/knowledge/{collection}",
212
+ collection_name=collection,
213
+ )
214
+
215
+ if config and config.exists():
216
+ import yaml
217
+ with open(config) as f:
218
+ file_config = yaml.safe_load(f)
219
+ if "retrieval" in file_config:
220
+ for key, value in file_config["retrieval"].items():
221
+ if hasattr(retrieval_config, key):
222
+ setattr(retrieval_config, key, value)
223
+
224
+ agent = Agent(
225
+ name="QueryAgent",
226
+ instructions="You are a helpful assistant that answers questions based on the provided knowledge.",
227
+ knowledge=[], # Empty - we'll use existing indexed knowledge
228
+ retrieval_config=retrieval_config,
229
+ verbose=verbose,
230
+ )
231
+
232
+ agent._ensure_knowledge_processed = lambda: None
233
+ from praisonaiagents.knowledge import Knowledge
234
+ agent.knowledge = Knowledge(config=retrieval_config.to_knowledge_config(), verbose=verbose)
235
+ agent._knowledge_processed = True
236
+
237
+ if verbose:
238
+ strategy_str = "hybrid (dense + keyword)" if hybrid else "dense"
239
+ rerank_str = " with reranking" if rerank else ""
240
+ console.print(f"[dim]Querying collection '{collection}' using {strategy_str}{rerank_str}, top_k={top_k}...[/dim]")
241
+
242
+ result = agent.query(question)
243
+
244
+ console.print(Panel(
245
+ Markdown(result.answer),
246
+ title="[bold]Answer[/bold]",
247
+ border_style="green",
248
+ ))
249
+
250
+ if citations and result.citations:
251
+ console.print("\n[bold]Sources:[/bold]")
252
+ for citation in result.citations:
253
+ score_str = f"[dim](score: {citation.score:.2f})[/dim]" if citation.score else ""
254
+ console.print(f" [{citation.id}] {citation.source} {score_str}")
255
+ if verbose:
256
+ snippet = citation.text[:200] + "..." if len(citation.text) > 200 else citation.text
257
+ console.print(f" [dim]{snippet}[/dim]")
258
+
259
+ if verbose and result.metadata:
260
+ elapsed = result.metadata.get('elapsed_seconds', 0)
261
+ console.print(f"\n[dim]Elapsed: {elapsed:.2f}s[/dim]")
262
+
263
+ if profile_data:
264
+ profile_data["command"] = "query"
265
+ profile_data["collection"] = collection
266
+ profile_data["question"] = question
267
+
268
+ except ImportError as e:
269
+ console.print(f"[red]Error:[/red] Missing dependency: {e}")
270
+ console.print("Install with: pip install 'praisonaiagents[knowledge]'")
271
+ raise typer.Exit(1)
272
+ except Exception as e:
273
+ console.print(f"[red]Error:[/red] {e}")
274
+ if verbose:
275
+ import traceback
276
+ console.print(traceback.format_exc())
277
+ raise typer.Exit(1)
278
+
279
+
280
+ @app.command("search")
281
+ def search_command(
282
+ query: str = typer.Argument(..., help="Search query"),
283
+ collection: str = typer.Option("default", "--collection", "-c", help="Collection to search"),
284
+ top_k: int = typer.Option(5, "--top-k", "-k", help="Number of results to retrieve"),
285
+ hybrid: bool = typer.Option(False, "--hybrid", help="Use hybrid retrieval (dense + keyword)"),
286
+ config: Optional[Path] = typer.Option(None, "--config", "-f", help="Config file path"),
287
+ verbose: bool = typer.Option(False, "--verbose", "-v", help="Verbose output"),
288
+ ):
289
+ """
290
+ Search/retrieve from a knowledge base (no LLM generation).
291
+
292
+ Returns raw search results without generating an answer.
293
+ For answers with citations, use `praisonai query`.
294
+
295
+ Examples:
296
+ praisonai search "capital of France"
297
+ praisonai search "main findings" --collection research --top-k 10
298
+ """
299
+ from rich.console import Console
300
+ from rich.table import Table
301
+
302
+ console = Console()
303
+
304
+ try:
305
+ from praisonaiagents.knowledge import Knowledge
306
+
307
+ knowledge_config = {
308
+ "vector_store": {
309
+ "provider": "chroma",
310
+ "config": {
311
+ "collection_name": collection,
312
+ "path": f"./.praison/knowledge/{collection}",
313
+ }
314
+ }
315
+ }
316
+
317
+ if hybrid:
318
+ knowledge_config["retrieval"] = {"strategy": "hybrid"}
319
+
320
+ if config and config.exists():
321
+ import yaml
322
+ with open(config) as f:
323
+ file_config = yaml.safe_load(f)
324
+ if "knowledge" in file_config:
325
+ knowledge_config.update(file_config["knowledge"])
326
+
327
+ knowledge = Knowledge(config=knowledge_config, verbose=verbose)
328
+
329
+ if verbose:
330
+ console.print(f"[dim]Searching collection '{collection}' for: {query}[/dim]")
331
+
332
+ results = knowledge.search(query)
333
+
334
+ if not results:
335
+ console.print("[yellow]No results found.[/yellow]")
336
+ return
337
+
338
+ if isinstance(results, dict) and 'results' in results:
339
+ result_list = results['results']
340
+ elif isinstance(results, list):
341
+ result_list = results
342
+ else:
343
+ result_list = [results]
344
+
345
+ table = Table(title=f"Search Results ({len(result_list[:top_k])} of {len(result_list)})")
346
+ table.add_column("#", style="dim", width=3)
347
+ table.add_column("Score", width=8)
348
+ table.add_column("Content", overflow="fold")
349
+
350
+ for i, result in enumerate(result_list[:top_k], 1):
351
+ if isinstance(result, dict):
352
+ content = result.get('memory', result.get('text', str(result)))
353
+ score = result.get('score', result.get('distance', 'N/A'))
354
+ else:
355
+ content = str(result)
356
+ score = 'N/A'
357
+
358
+ content_preview = content[:300] + "..." if len(content) > 300 else content
359
+ score_str = f"{score:.3f}" if isinstance(score, float) else str(score)
360
+ table.add_row(str(i), score_str, content_preview)
361
+
362
+ console.print(table)
363
+
364
+ except ImportError as e:
365
+ console.print(f"[red]Error:[/red] Missing dependency: {e}")
366
+ console.print("Install with: pip install 'praisonaiagents[knowledge]'")
367
+ raise typer.Exit(1)
368
+ except Exception as e:
369
+ console.print(f"[red]Error:[/red] {e}")
370
+ raise typer.Exit(1)
371
+
372
+
373
+ def register_commands(main_app: typer.Typer):
374
+ """Register unified retrieval commands with the main CLI app."""
375
+ main_app.command("index")(index_command)
376
+ main_app.command("query")(query_command)
377
+ main_app.command("search")(search_command)
@@ -0,0 +1,71 @@
1
+ """
2
+ Rules command group for PraisonAI CLI.
3
+
4
+ Provides rules management commands.
5
+ """
6
+
7
+ import typer
8
+
9
+ app = typer.Typer(help="Rules management")
10
+
11
+
12
+ @app.command("list")
13
+ def rules_list():
14
+ """List active rules."""
15
+ from praisonai.cli.main import PraisonAI
16
+ import sys
17
+
18
+ argv = ['rules', '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 rules_add(
34
+ rule: str = typer.Argument(..., help="Rule to add"),
35
+ ):
36
+ """Add a rule."""
37
+ from praisonai.cli.main import PraisonAI
38
+ import sys
39
+
40
+ argv = ['rules', 'add', rule]
41
+
42
+ original_argv = sys.argv
43
+ sys.argv = ['praisonai'] + argv
44
+
45
+ try:
46
+ praison = PraisonAI()
47
+ praison.main()
48
+ except SystemExit:
49
+ pass
50
+ finally:
51
+ sys.argv = original_argv
52
+
53
+
54
+ @app.command("clear")
55
+ def rules_clear():
56
+ """Clear all rules."""
57
+ from praisonai.cli.main import PraisonAI
58
+ import sys
59
+
60
+ argv = ['rules', 'clear']
61
+
62
+ original_argv = sys.argv
63
+ sys.argv = ['praisonai'] + argv
64
+
65
+ try:
66
+ praison = PraisonAI()
67
+ praison.main()
68
+ except SystemExit:
69
+ pass
70
+ finally:
71
+ sys.argv = original_argv