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,552 @@
1
+ """
2
+ Auto Mode Handler for PraisonAI CLI.
3
+
4
+ Provides CLI flags and controls for auto-mode execution with progressive escalation.
5
+ Implements the "advanced-by-default, fast-by-default" strategy.
6
+
7
+ CLI Flags:
8
+ --auto / --no-auto Enable/disable auto mode (default: auto)
9
+ --dry-run Show what would be done without executing
10
+ --apply Apply changes (opposite of dry-run)
11
+ --budget-steps N Maximum steps budget
12
+ --budget-time N Maximum time budget in seconds
13
+ --budget-tokens N Maximum tokens budget
14
+ --allow-tools TOOLS Comma-separated list of allowed tools
15
+ --deny-tools TOOLS Comma-separated list of denied tools
16
+ --checkpoint / --no-checkpoint Enable/disable checkpoints
17
+ --router MODE Router mode: heuristic, trained, off
18
+ """
19
+
20
+ import logging
21
+ from dataclasses import dataclass, field
22
+ from typing import Any, Dict, List, Optional, Set, Callable
23
+ from enum import Enum
24
+
25
+ logger = logging.getLogger(__name__)
26
+
27
+
28
+ class AutoModeLevel(Enum):
29
+ """Auto mode levels for CLI."""
30
+ OFF = "off" # Manual mode - ask for everything
31
+ SUGGEST = "suggest" # Suggest actions, require approval
32
+ AUTO = "auto" # Auto-approve safe actions
33
+ FULL_AUTO = "full_auto" # Auto-approve everything (YOLO)
34
+
35
+
36
+ class RouterMode(Enum):
37
+ """Router modes for model selection."""
38
+ HEURISTIC = "heuristic" # Fast keyword-based routing (default)
39
+ TRAINED = "trained" # ML-based routing (optional plugin)
40
+ OFF = "off" # No routing, use default model
41
+
42
+
43
+ @dataclass
44
+ class AutoModeConfig:
45
+ """Configuration for auto mode execution."""
46
+ # Mode settings
47
+ mode: AutoModeLevel = AutoModeLevel.AUTO
48
+ dry_run: bool = False
49
+
50
+ # Budgets
51
+ budget_steps: int = 50
52
+ budget_time_seconds: int = 300
53
+ budget_tokens: int = 100000
54
+ budget_tool_calls: int = 100
55
+
56
+ # Tool controls
57
+ allow_tools: Set[str] = field(default_factory=set)
58
+ deny_tools: Set[str] = field(default_factory=set)
59
+
60
+ # Checkpoint settings
61
+ enable_checkpoints: bool = True
62
+ auto_checkpoint_on_write: bool = True
63
+
64
+ # Router settings
65
+ router_mode: RouterMode = RouterMode.HEURISTIC
66
+
67
+ # Escalation settings
68
+ auto_escalate: bool = True
69
+ auto_deescalate: bool = True
70
+
71
+ # Approval settings
72
+ require_approval_for_writes: bool = True
73
+ require_approval_for_commands: bool = True
74
+ require_approval_for_deletes: bool = True
75
+
76
+ # Display settings
77
+ show_stage: bool = True
78
+ show_budgets: bool = True
79
+ show_checkpoints: bool = True
80
+ verbose: bool = False
81
+
82
+ @classmethod
83
+ def from_cli_args(cls, **kwargs) -> "AutoModeConfig":
84
+ """Create config from CLI arguments."""
85
+ config = cls()
86
+
87
+ # Mode
88
+ if kwargs.get("auto") is False:
89
+ config.mode = AutoModeLevel.OFF
90
+ elif kwargs.get("full_auto"):
91
+ config.mode = AutoModeLevel.FULL_AUTO
92
+ elif kwargs.get("suggest"):
93
+ config.mode = AutoModeLevel.SUGGEST
94
+
95
+ # Dry run
96
+ if kwargs.get("dry_run"):
97
+ config.dry_run = True
98
+ elif kwargs.get("apply"):
99
+ config.dry_run = False
100
+
101
+ # Budgets
102
+ if kwargs.get("budget_steps"):
103
+ config.budget_steps = kwargs["budget_steps"]
104
+ if kwargs.get("budget_time"):
105
+ config.budget_time_seconds = kwargs["budget_time"]
106
+ if kwargs.get("budget_tokens"):
107
+ config.budget_tokens = kwargs["budget_tokens"]
108
+
109
+ # Tools
110
+ if kwargs.get("allow_tools"):
111
+ config.allow_tools = set(kwargs["allow_tools"].split(","))
112
+ if kwargs.get("deny_tools"):
113
+ config.deny_tools = set(kwargs["deny_tools"].split(","))
114
+
115
+ # Checkpoints
116
+ if kwargs.get("checkpoint") is False:
117
+ config.enable_checkpoints = False
118
+ elif kwargs.get("no_checkpoint"):
119
+ config.enable_checkpoints = False
120
+
121
+ # Router
122
+ if kwargs.get("router"):
123
+ try:
124
+ config.router_mode = RouterMode(kwargs["router"])
125
+ except ValueError:
126
+ logger.warning(f"Unknown router mode: {kwargs['router']}")
127
+
128
+ # Verbose
129
+ config.verbose = kwargs.get("verbose", False)
130
+
131
+ return config
132
+
133
+
134
+ @dataclass
135
+ class AutoModeState:
136
+ """Runtime state for auto mode execution."""
137
+ # Current execution
138
+ current_stage: int = 0
139
+ steps_taken: int = 0
140
+ tokens_used: int = 0
141
+ tool_calls: int = 0
142
+ time_elapsed: float = 0.0
143
+
144
+ # Checkpoints
145
+ checkpoint_ids: List[str] = field(default_factory=list)
146
+ files_modified: Set[str] = field(default_factory=set)
147
+
148
+ # Approvals
149
+ pending_approvals: List[Dict[str, Any]] = field(default_factory=list)
150
+ approved_actions: int = 0
151
+ denied_actions: int = 0
152
+
153
+ # Errors
154
+ errors: List[str] = field(default_factory=list)
155
+ warnings: List[str] = field(default_factory=list)
156
+
157
+ def is_within_budget(self, config: AutoModeConfig) -> bool:
158
+ """Check if execution is within budget."""
159
+ if self.steps_taken >= config.budget_steps:
160
+ return False
161
+ if self.time_elapsed >= config.budget_time_seconds:
162
+ return False
163
+ if self.tokens_used >= config.budget_tokens:
164
+ return False
165
+ if self.tool_calls >= config.budget_tool_calls:
166
+ return False
167
+ return True
168
+
169
+ def get_budget_status(self, config: AutoModeConfig) -> Dict[str, Any]:
170
+ """Get budget utilization status."""
171
+ return {
172
+ "steps": {
173
+ "used": self.steps_taken,
174
+ "limit": config.budget_steps,
175
+ "percent": (self.steps_taken / config.budget_steps * 100) if config.budget_steps > 0 else 0,
176
+ },
177
+ "time": {
178
+ "used": self.time_elapsed,
179
+ "limit": config.budget_time_seconds,
180
+ "percent": (self.time_elapsed / config.budget_time_seconds * 100) if config.budget_time_seconds > 0 else 0,
181
+ },
182
+ "tokens": {
183
+ "used": self.tokens_used,
184
+ "limit": config.budget_tokens,
185
+ "percent": (self.tokens_used / config.budget_tokens * 100) if config.budget_tokens > 0 else 0,
186
+ },
187
+ "tool_calls": {
188
+ "used": self.tool_calls,
189
+ "limit": config.budget_tool_calls,
190
+ "percent": (self.tool_calls / config.budget_tool_calls * 100) if config.budget_tool_calls > 0 else 0,
191
+ },
192
+ }
193
+
194
+
195
+ class AutoModeHandler:
196
+ """
197
+ Handler for auto mode CLI integration.
198
+
199
+ Provides:
200
+ - CLI flag parsing
201
+ - Escalation pipeline integration
202
+ - Budget tracking
203
+ - Checkpoint management
204
+ - Status display
205
+
206
+ Example:
207
+ handler = AutoModeHandler()
208
+ config = handler.parse_args(auto=True, budget_steps=20)
209
+
210
+ # Execute with auto mode
211
+ result = await handler.execute(prompt, config)
212
+ """
213
+
214
+ def __init__(
215
+ self,
216
+ verbose: bool = False,
217
+ on_stage_change: Optional[Callable[[int, int], None]] = None,
218
+ on_checkpoint: Optional[Callable[[str], None]] = None,
219
+ ):
220
+ """
221
+ Initialize the handler.
222
+
223
+ Args:
224
+ verbose: Enable verbose output
225
+ on_stage_change: Callback for stage transitions
226
+ on_checkpoint: Callback for checkpoint creation
227
+ """
228
+ self.verbose = verbose
229
+ self.on_stage_change = on_stage_change
230
+ self.on_checkpoint = on_checkpoint
231
+
232
+ self._config: Optional[AutoModeConfig] = None
233
+ self._state: Optional[AutoModeState] = None
234
+ self._pipeline = None
235
+ self._checkpoint_service = None
236
+
237
+ @property
238
+ def feature_name(self) -> str:
239
+ return "auto_mode"
240
+
241
+ def parse_args(self, **kwargs) -> AutoModeConfig:
242
+ """
243
+ Parse CLI arguments into config.
244
+
245
+ Args:
246
+ **kwargs: CLI arguments
247
+
248
+ Returns:
249
+ AutoModeConfig
250
+ """
251
+ self._config = AutoModeConfig.from_cli_args(**kwargs)
252
+ self._state = AutoModeState()
253
+ return self._config
254
+
255
+ def get_config(self) -> Optional[AutoModeConfig]:
256
+ """Get current configuration."""
257
+ return self._config
258
+
259
+ def get_state(self) -> Optional[AutoModeState]:
260
+ """Get current state."""
261
+ return self._state
262
+
263
+ async def execute(
264
+ self,
265
+ prompt: str,
266
+ agent: Optional[Any] = None,
267
+ tools: Optional[List[Any]] = None,
268
+ context: Optional[Dict[str, Any]] = None,
269
+ ) -> Dict[str, Any]:
270
+ """
271
+ Execute prompt with auto mode.
272
+
273
+ Args:
274
+ prompt: User prompt
275
+ agent: Agent instance
276
+ tools: Available tools
277
+ context: Execution context
278
+
279
+ Returns:
280
+ Execution result
281
+ """
282
+ if not self._config:
283
+ self._config = AutoModeConfig()
284
+ if not self._state:
285
+ self._state = AutoModeState()
286
+
287
+ import time
288
+ start_time = time.time()
289
+
290
+ # Filter tools based on config
291
+ filtered_tools = self._filter_tools(tools or [])
292
+
293
+ # Initialize escalation pipeline
294
+ try:
295
+ from praisonaiagents.escalation import EscalationPipeline, EscalationConfig
296
+
297
+ escalation_config = EscalationConfig(
298
+ max_steps=self._config.budget_steps,
299
+ max_time_seconds=self._config.budget_time_seconds,
300
+ max_tokens=self._config.budget_tokens,
301
+ auto_escalate=self._config.auto_escalate,
302
+ auto_deescalate=self._config.auto_deescalate,
303
+ enable_checkpoints=self._config.enable_checkpoints,
304
+ require_approval_for_writes=self._config.require_approval_for_writes,
305
+ )
306
+
307
+ self._pipeline = EscalationPipeline(
308
+ config=escalation_config,
309
+ agent=agent,
310
+ tools=filtered_tools,
311
+ checkpoint_service=self._checkpoint_service,
312
+ on_stage_change=self._handle_stage_change,
313
+ )
314
+
315
+ # Execute
316
+ result = await self._pipeline.execute(prompt, context)
317
+
318
+ # Update state
319
+ self._state.steps_taken = result.steps_taken
320
+ self._state.tokens_used = result.tokens_used
321
+ self._state.tool_calls = result.tool_calls
322
+ self._state.time_elapsed = time.time() - start_time
323
+ self._state.current_stage = result.final_stage.value
324
+
325
+ if result.checkpoint_id:
326
+ self._state.checkpoint_ids.append(result.checkpoint_id)
327
+
328
+ self._state.files_modified.update(result.files_modified)
329
+ self._state.errors.extend(result.errors)
330
+ self._state.warnings.extend(result.warnings)
331
+
332
+ return {
333
+ "success": result.success,
334
+ "response": result.response,
335
+ "stage": result.final_stage.name,
336
+ "escalations": result.escalations,
337
+ "state": self._state,
338
+ }
339
+
340
+ except ImportError:
341
+ # Fallback if escalation module not available
342
+ logger.warning("Escalation module not available, using basic execution")
343
+
344
+ if agent and hasattr(agent, 'chat'):
345
+ response = agent.chat(prompt)
346
+ self._state.time_elapsed = time.time() - start_time
347
+
348
+ return {
349
+ "success": True,
350
+ "response": response,
351
+ "stage": "DIRECT",
352
+ "escalations": 0,
353
+ "state": self._state,
354
+ }
355
+
356
+ return {
357
+ "success": False,
358
+ "response": "No agent available",
359
+ "stage": "DIRECT",
360
+ "escalations": 0,
361
+ "state": self._state,
362
+ }
363
+
364
+ def _filter_tools(self, tools: List[Any]) -> List[Any]:
365
+ """Filter tools based on allow/deny lists."""
366
+ if not self._config:
367
+ return tools
368
+
369
+ filtered = []
370
+ for tool in tools:
371
+ tool_name = getattr(tool, '__name__', str(tool)).lower()
372
+
373
+ # Check deny list first
374
+ if self._config.deny_tools:
375
+ if any(d.lower() in tool_name for d in self._config.deny_tools):
376
+ continue
377
+
378
+ # Check allow list
379
+ if self._config.allow_tools:
380
+ if not any(a.lower() in tool_name for a in self._config.allow_tools):
381
+ continue
382
+
383
+ filtered.append(tool)
384
+
385
+ return filtered
386
+
387
+ def _handle_stage_change(self, old_stage, new_stage):
388
+ """Handle stage change event."""
389
+ if self._state:
390
+ self._state.current_stage = new_stage.value
391
+
392
+ if self.on_stage_change:
393
+ self.on_stage_change(old_stage.value, new_stage.value)
394
+
395
+ if self.verbose:
396
+ self._display_stage_change(old_stage, new_stage)
397
+
398
+ def _display_stage_change(self, old_stage, new_stage):
399
+ """Display stage change to user."""
400
+ try:
401
+ from rich import print as rprint
402
+
403
+ direction = "⬆️" if new_stage > old_stage else "⬇️"
404
+ rprint(f"[cyan]{direction} Stage: {old_stage.name} → {new_stage.name}[/cyan]")
405
+ except ImportError:
406
+ print(f"Stage: {old_stage.name} -> {new_stage.name}")
407
+
408
+ def display_status(self):
409
+ """Display current status."""
410
+ if not self._config or not self._state:
411
+ return
412
+
413
+ try:
414
+ from rich.console import Console
415
+ from rich.table import Table
416
+ from rich.panel import Panel
417
+
418
+ console = Console()
419
+
420
+ # Budget table
421
+ budget = self._state.get_budget_status(self._config)
422
+
423
+ table = Table(title="Auto Mode Status")
424
+ table.add_column("Metric", style="cyan")
425
+ table.add_column("Used", style="green")
426
+ table.add_column("Limit", style="yellow")
427
+ table.add_column("Usage", style="magenta")
428
+
429
+ for name, data in budget.items():
430
+ table.add_row(
431
+ name.replace("_", " ").title(),
432
+ str(data["used"]),
433
+ str(data["limit"]),
434
+ f"{data['percent']:.1f}%"
435
+ )
436
+
437
+ console.print(table)
438
+
439
+ # Stage info
440
+ stage_names = ["DIRECT", "HEURISTIC", "PLANNED", "AUTONOMOUS"]
441
+ current = stage_names[self._state.current_stage] if self._state.current_stage < len(stage_names) else "UNKNOWN"
442
+ console.print(f"\n[bold]Current Stage:[/bold] {current}")
443
+
444
+ # Checkpoints
445
+ if self._state.checkpoint_ids:
446
+ console.print(f"[bold]Checkpoints:[/bold] {len(self._state.checkpoint_ids)}")
447
+
448
+ # Files modified
449
+ if self._state.files_modified:
450
+ console.print(f"[bold]Files Modified:[/bold] {len(self._state.files_modified)}")
451
+
452
+ except ImportError:
453
+ # Fallback to basic output
454
+ print(f"Steps: {self._state.steps_taken}/{self._config.budget_steps}")
455
+ print(f"Time: {self._state.time_elapsed:.1f}s/{self._config.budget_time_seconds}s")
456
+
457
+ def get_cli_options(self) -> List[Dict[str, Any]]:
458
+ """
459
+ Get CLI option definitions for integration.
460
+
461
+ Returns:
462
+ List of option definitions
463
+ """
464
+ return [
465
+ {
466
+ "name": "--auto/--no-auto",
467
+ "default": True,
468
+ "help": "Enable/disable auto mode",
469
+ },
470
+ {
471
+ "name": "--dry-run",
472
+ "is_flag": True,
473
+ "help": "Show what would be done without executing",
474
+ },
475
+ {
476
+ "name": "--apply",
477
+ "is_flag": True,
478
+ "help": "Apply changes (opposite of dry-run)",
479
+ },
480
+ {
481
+ "name": "--budget-steps",
482
+ "type": int,
483
+ "default": 50,
484
+ "help": "Maximum steps budget",
485
+ },
486
+ {
487
+ "name": "--budget-time",
488
+ "type": int,
489
+ "default": 300,
490
+ "help": "Maximum time budget in seconds",
491
+ },
492
+ {
493
+ "name": "--budget-tokens",
494
+ "type": int,
495
+ "default": 100000,
496
+ "help": "Maximum tokens budget",
497
+ },
498
+ {
499
+ "name": "--allow-tools",
500
+ "type": str,
501
+ "help": "Comma-separated list of allowed tools",
502
+ },
503
+ {
504
+ "name": "--deny-tools",
505
+ "type": str,
506
+ "help": "Comma-separated list of denied tools",
507
+ },
508
+ {
509
+ "name": "--checkpoint/--no-checkpoint",
510
+ "default": True,
511
+ "help": "Enable/disable checkpoints",
512
+ },
513
+ {
514
+ "name": "--router",
515
+ "type": str,
516
+ "default": "heuristic",
517
+ "help": "Router mode: heuristic, trained, off",
518
+ },
519
+ ]
520
+
521
+
522
+ # Convenience function for quick auto mode execution
523
+ async def auto_execute(
524
+ prompt: str,
525
+ agent: Optional[Any] = None,
526
+ budget_steps: int = 50,
527
+ budget_time: int = 300,
528
+ dry_run: bool = False,
529
+ verbose: bool = False,
530
+ ) -> Dict[str, Any]:
531
+ """
532
+ Quick auto mode execution.
533
+
534
+ Args:
535
+ prompt: User prompt
536
+ agent: Agent instance
537
+ budget_steps: Max steps
538
+ budget_time: Max time in seconds
539
+ dry_run: Dry run mode
540
+ verbose: Verbose output
541
+
542
+ Returns:
543
+ Execution result
544
+ """
545
+ handler = AutoModeHandler(verbose=verbose)
546
+ handler.parse_args(
547
+ budget_steps=budget_steps,
548
+ budget_time=budget_time,
549
+ dry_run=dry_run,
550
+ )
551
+
552
+ return await handler.execute(prompt, agent=agent)