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.
- praisonai_code/__init__.py +17 -0
- praisonai_code/cli/__init__.py +12 -0
- praisonai_code/cli/_forward_shim.py +10 -0
- praisonai_code/cli/_paths.py +88 -0
- praisonai_code/cli/_warnings.py +58 -0
- praisonai_code/cli/app.py +757 -0
- praisonai_code/cli/approval_backend.py +272 -0
- praisonai_code/cli/branding.py +94 -0
- praisonai_code/cli/commands/__init__.py +114 -0
- praisonai_code/cli/commands/acp.py +80 -0
- praisonai_code/cli/commands/agent.py +116 -0
- praisonai_code/cli/commands/agents.py +80 -0
- praisonai_code/cli/commands/app.py +139 -0
- praisonai_code/cli/commands/attach.py +95 -0
- praisonai_code/cli/commands/audit.py +102 -0
- praisonai_code/cli/commands/auth.py +508 -0
- praisonai_code/cli/commands/batch.py +848 -0
- praisonai_code/cli/commands/benchmark.py +286 -0
- praisonai_code/cli/commands/browser.py +299 -0
- praisonai_code/cli/commands/call.py +45 -0
- praisonai_code/cli/commands/chat.py +332 -0
- praisonai_code/cli/commands/checkpoint.py +170 -0
- praisonai_code/cli/commands/code.py +276 -0
- praisonai_code/cli/commands/command.py +114 -0
- praisonai_code/cli/commands/commit.py +47 -0
- praisonai_code/cli/commands/completion.py +333 -0
- praisonai_code/cli/commands/config.py +681 -0
- praisonai_code/cli/commands/context.py +414 -0
- praisonai_code/cli/commands/daemon.py +203 -0
- praisonai_code/cli/commands/debug.py +142 -0
- praisonai_code/cli/commands/deploy.py +71 -0
- praisonai_code/cli/commands/diag.py +55 -0
- praisonai_code/cli/commands/docs.py +1575 -0
- praisonai_code/cli/commands/doctor.py +332 -0
- praisonai_code/cli/commands/endpoints.py +51 -0
- praisonai_code/cli/commands/environment.py +179 -0
- praisonai_code/cli/commands/eval.py +131 -0
- praisonai_code/cli/commands/examples.py +953 -0
- praisonai_code/cli/commands/flow.py +436 -0
- praisonai_code/cli/commands/github.py +752 -0
- praisonai_code/cli/commands/hooks.py +74 -0
- praisonai_code/cli/commands/init.py +174 -0
- praisonai_code/cli/commands/knowledge.py +440 -0
- praisonai_code/cli/commands/langextract.py +120 -0
- praisonai_code/cli/commands/langfuse.py +984 -0
- praisonai_code/cli/commands/loop.py +211 -0
- praisonai_code/cli/commands/lsp.py +112 -0
- praisonai_code/cli/commands/managed.py +659 -0
- praisonai_code/cli/commands/mcp.py +763 -0
- praisonai_code/cli/commands/memory.py +298 -0
- praisonai_code/cli/commands/models.py +264 -0
- praisonai_code/cli/commands/n8n.py +326 -0
- praisonai_code/cli/commands/obs.py +19 -0
- praisonai_code/cli/commands/package.py +76 -0
- praisonai_code/cli/commands/paths.py +106 -0
- praisonai_code/cli/commands/permissions.py +272 -0
- praisonai_code/cli/commands/plugins.py +609 -0
- praisonai_code/cli/commands/port.py +530 -0
- praisonai_code/cli/commands/profile.py +466 -0
- praisonai_code/cli/commands/publish.py +193 -0
- praisonai_code/cli/commands/rag.py +913 -0
- praisonai_code/cli/commands/realtime.py +52 -0
- praisonai_code/cli/commands/recipe.py +684 -0
- praisonai_code/cli/commands/registry.py +59 -0
- praisonai_code/cli/commands/replay.py +830 -0
- praisonai_code/cli/commands/research.py +49 -0
- praisonai_code/cli/commands/retrieval.py +377 -0
- praisonai_code/cli/commands/rules.py +71 -0
- praisonai_code/cli/commands/run.py +1573 -0
- praisonai_code/cli/commands/sandbox.py +371 -0
- praisonai_code/cli/commands/schedule.py +529 -0
- praisonai_code/cli/commands/serve.py +690 -0
- praisonai_code/cli/commands/session.py +450 -0
- praisonai_code/cli/commands/setup.py +174 -0
- praisonai_code/cli/commands/skills.py +545 -0
- praisonai_code/cli/commands/standardise.py +711 -0
- praisonai_code/cli/commands/templates.py +54 -0
- praisonai_code/cli/commands/test.py +558 -0
- praisonai_code/cli/commands/todo.py +74 -0
- praisonai_code/cli/commands/tools.py +205 -0
- praisonai_code/cli/commands/traces.py +145 -0
- praisonai_code/cli/commands/tracker.py +852 -0
- praisonai_code/cli/commands/train.py +613 -0
- praisonai_code/cli/commands/ui.py +172 -0
- praisonai_code/cli/commands/up.py +354 -0
- praisonai_code/cli/commands/validate.py +291 -0
- praisonai_code/cli/commands/version.py +101 -0
- praisonai_code/cli/commands/workflow.py +97 -0
- praisonai_code/cli/config_loader.py +437 -0
- praisonai_code/cli/configuration/__init__.py +27 -0
- praisonai_code/cli/configuration/config.schema.json +57 -0
- praisonai_code/cli/configuration/credentials.py +446 -0
- praisonai_code/cli/configuration/loader.py +364 -0
- praisonai_code/cli/configuration/model_resolver.py +161 -0
- praisonai_code/cli/configuration/oauth.py +389 -0
- praisonai_code/cli/configuration/paths.py +224 -0
- praisonai_code/cli/configuration/resolver.py +687 -0
- praisonai_code/cli/configuration/schema.py +317 -0
- praisonai_code/cli/execution/__init__.py +99 -0
- praisonai_code/cli/execution/core.py +208 -0
- praisonai_code/cli/execution/profiler.py +898 -0
- praisonai_code/cli/execution/request.py +85 -0
- praisonai_code/cli/execution/result.py +74 -0
- praisonai_code/cli/fallback_schema.py +416 -0
- praisonai_code/cli/features/__init__.py +278 -0
- praisonai_code/cli/features/_endpoint_registry.py +64 -0
- praisonai_code/cli/features/_search_registry.py +43 -0
- praisonai_code/cli/features/acp.py +236 -0
- praisonai_code/cli/features/action_orchestrator.py +576 -0
- praisonai_code/cli/features/agent_scheduler.py +773 -0
- praisonai_code/cli/features/agent_tools.py +603 -0
- praisonai_code/cli/features/agents.py +397 -0
- praisonai_code/cli/features/at_mentions.py +471 -0
- praisonai_code/cli/features/audit_cli.py +270 -0
- praisonai_code/cli/features/auto_memory.py +182 -0
- praisonai_code/cli/features/auto_mode.py +552 -0
- praisonai_code/cli/features/autonomy_mode.py +546 -0
- praisonai_code/cli/features/background.py +356 -0
- praisonai_code/cli/features/base.py +168 -0
- praisonai_code/cli/features/benchmark.py +1462 -0
- praisonai_code/cli/features/capabilities.py +1326 -0
- praisonai_code/cli/features/checkpoints.py +345 -0
- praisonai_code/cli/features/cli_profiler.py +335 -0
- praisonai_code/cli/features/code_intelligence.py +666 -0
- praisonai_code/cli/features/compaction.py +294 -0
- praisonai_code/cli/features/compare.py +534 -0
- praisonai_code/cli/features/config_hierarchy.py +366 -0
- praisonai_code/cli/features/context_manager.py +597 -0
- praisonai_code/cli/features/cost_tracker.py +514 -0
- praisonai_code/cli/features/csv_test_runner.py +736 -0
- praisonai_code/cli/features/custom_definitions.py +790 -0
- praisonai_code/cli/features/debug.py +810 -0
- praisonai_code/cli/features/deploy.py +605 -0
- praisonai_code/cli/features/diag.py +289 -0
- praisonai_code/cli/features/display_jsonl.py +173 -0
- praisonai_code/cli/features/doctor/__init__.py +63 -0
- praisonai_code/cli/features/doctor/checks/__init__.py +29 -0
- praisonai_code/cli/features/doctor/checks/acp_checks.py +220 -0
- praisonai_code/cli/features/doctor/checks/bot_checks.py +340 -0
- praisonai_code/cli/features/doctor/checks/config_checks.py +373 -0
- praisonai_code/cli/features/doctor/checks/db_checks.py +366 -0
- praisonai_code/cli/features/doctor/checks/env_checks.py +637 -0
- praisonai_code/cli/features/doctor/checks/gateway_checks.py +387 -0
- praisonai_code/cli/features/doctor/checks/lsp_checks.py +231 -0
- praisonai_code/cli/features/doctor/checks/mcp_checks.py +367 -0
- praisonai_code/cli/features/doctor/checks/memory_checks.py +268 -0
- praisonai_code/cli/features/doctor/checks/network_checks.py +251 -0
- praisonai_code/cli/features/doctor/checks/obs_checks.py +328 -0
- praisonai_code/cli/features/doctor/checks/packaging_checks.py +422 -0
- praisonai_code/cli/features/doctor/checks/performance_checks.py +235 -0
- praisonai_code/cli/features/doctor/checks/permissions_checks.py +259 -0
- praisonai_code/cli/features/doctor/checks/runtime_checks.py +650 -0
- praisonai_code/cli/features/doctor/checks/runtime_migration_checks.py +220 -0
- praisonai_code/cli/features/doctor/checks/selftest_checks.py +322 -0
- praisonai_code/cli/features/doctor/checks/serve_checks.py +426 -0
- praisonai_code/cli/features/doctor/checks/skills_checks.py +327 -0
- praisonai_code/cli/features/doctor/checks/tools_checks.py +371 -0
- praisonai_code/cli/features/doctor/engine.py +266 -0
- praisonai_code/cli/features/doctor/formatters.py +377 -0
- praisonai_code/cli/features/doctor/handler.py +564 -0
- praisonai_code/cli/features/doctor/models.py +276 -0
- praisonai_code/cli/features/doctor/registry.py +239 -0
- praisonai_code/cli/features/endpoints.py +1016 -0
- praisonai_code/cli/features/eval.py +559 -0
- praisonai_code/cli/features/examples.py +707 -0
- praisonai_code/cli/features/external_agents.py +231 -0
- praisonai_code/cli/features/fast_context.py +410 -0
- praisonai_code/cli/features/file_history.py +320 -0
- praisonai_code/cli/features/flow_display.py +566 -0
- praisonai_code/cli/features/git_attribution.py +159 -0
- praisonai_code/cli/features/git_integration.py +651 -0
- praisonai_code/cli/features/guardrail.py +171 -0
- praisonai_code/cli/features/handoff.py +252 -0
- praisonai_code/cli/features/hooks.py +583 -0
- praisonai_code/cli/features/hybrid_workflow.py +391 -0
- praisonai_code/cli/features/image.py +384 -0
- praisonai_code/cli/features/interactive_core_headless.py +450 -0
- praisonai_code/cli/features/interactive_runtime.py +600 -0
- praisonai_code/cli/features/interactive_test_harness.py +537 -0
- praisonai_code/cli/features/interactive_tools.py +428 -0
- praisonai_code/cli/features/interactive_tui.py +603 -0
- praisonai_code/cli/features/job_workflow.py +906 -0
- praisonai_code/cli/features/jobs.py +632 -0
- praisonai_code/cli/features/knowledge.py +531 -0
- praisonai_code/cli/features/knowledge_cli.py +438 -0
- praisonai_code/cli/features/lite.py +244 -0
- praisonai_code/cli/features/logs.py +200 -0
- praisonai_code/cli/features/lsp_cli.py +225 -0
- praisonai_code/cli/features/lsp_diagnostics.py +185 -0
- praisonai_code/cli/features/mcp.py +344 -0
- praisonai_code/cli/features/message_queue.py +587 -0
- praisonai_code/cli/features/metrics.py +210 -0
- praisonai_code/cli/features/migrate.py +1329 -0
- praisonai_code/cli/features/migration_flow.py +463 -0
- praisonai_code/cli/features/migration_spec.py +276 -0
- praisonai_code/cli/features/n8n.py +703 -0
- praisonai_code/cli/features/observability.py +293 -0
- praisonai_code/cli/features/ollama.py +361 -0
- praisonai_code/cli/features/output_modes.py +155 -0
- praisonai_code/cli/features/output_style.py +273 -0
- praisonai_code/cli/features/package.py +631 -0
- praisonai_code/cli/features/performance.py +308 -0
- praisonai_code/cli/features/persistence.py +636 -0
- praisonai_code/cli/features/profiler/__init__.py +81 -0
- praisonai_code/cli/features/profiler/core.py +558 -0
- praisonai_code/cli/features/profiler/optimizations.py +652 -0
- praisonai_code/cli/features/profiler/suite.py +386 -0
- praisonai_code/cli/features/queue/__init__.py +73 -0
- praisonai_code/cli/features/queue/manager.py +435 -0
- praisonai_code/cli/features/queue/models.py +289 -0
- praisonai_code/cli/features/queue/persistence.py +564 -0
- praisonai_code/cli/features/queue/scheduler.py +529 -0
- praisonai_code/cli/features/queue/worker.py +400 -0
- praisonai_code/cli/features/recipe.py +2187 -0
- praisonai_code/cli/features/recipe_creator.py +996 -0
- praisonai_code/cli/features/recipe_optimizer.py +1364 -0
- praisonai_code/cli/features/recipe_prompts.py +226 -0
- praisonai_code/cli/features/registry.py +229 -0
- praisonai_code/cli/features/repo_map.py +860 -0
- praisonai_code/cli/features/router.py +466 -0
- praisonai_code/cli/features/safe_shell.py +427 -0
- praisonai_code/cli/features/sandbox_cli.py +283 -0
- praisonai_code/cli/features/sandbox_executor.py +536 -0
- praisonai_code/cli/features/sdk_knowledge.py +500 -0
- praisonai_code/cli/features/session.py +222 -0
- praisonai_code/cli/features/session_checkpoints.py +208 -0
- praisonai_code/cli/features/setup/__init__.py +9 -0
- praisonai_code/cli/features/setup/handler.py +355 -0
- praisonai_code/cli/features/setup/templates.py +62 -0
- praisonai_code/cli/features/skills.py +940 -0
- praisonai_code/cli/features/slash_commands.py +692 -0
- praisonai_code/cli/features/telemetry.py +179 -0
- praisonai_code/cli/features/templates.py +1390 -0
- praisonai_code/cli/features/thinking.py +343 -0
- praisonai_code/cli/features/todo.py +334 -0
- praisonai_code/cli/features/tools.py +680 -0
- praisonai_code/cli/features/tui/__init__.py +83 -0
- praisonai_code/cli/features/tui/app.py +871 -0
- praisonai_code/cli/features/tui/cli.py +580 -0
- praisonai_code/cli/features/tui/config.py +150 -0
- praisonai_code/cli/features/tui/debug.py +526 -0
- praisonai_code/cli/features/tui/events.py +99 -0
- praisonai_code/cli/features/tui/mock_provider.py +328 -0
- praisonai_code/cli/features/tui/orchestrator.py +652 -0
- praisonai_code/cli/features/tui/screens/__init__.py +50 -0
- praisonai_code/cli/features/tui/screens/help.py +157 -0
- praisonai_code/cli/features/tui/screens/main.py +568 -0
- praisonai_code/cli/features/tui/screens/queue.py +174 -0
- praisonai_code/cli/features/tui/screens/session.py +124 -0
- praisonai_code/cli/features/tui/screens/settings.py +148 -0
- praisonai_code/cli/features/tui/session_store.py +198 -0
- praisonai_code/cli/features/tui/widgets/__init__.py +56 -0
- praisonai_code/cli/features/tui/widgets/chat.py +263 -0
- praisonai_code/cli/features/tui/widgets/command_popup.py +258 -0
- praisonai_code/cli/features/tui/widgets/composer.py +292 -0
- praisonai_code/cli/features/tui/widgets/file_popup.py +207 -0
- praisonai_code/cli/features/tui/widgets/queue_panel.py +223 -0
- praisonai_code/cli/features/tui/widgets/status.py +181 -0
- praisonai_code/cli/features/tui/widgets/tool_panel.py +307 -0
- praisonai_code/cli/features/wizard.py +289 -0
- praisonai_code/cli/features/workflow.py +802 -0
- praisonai_code/cli/features/yaml_utils.py +321 -0
- praisonai_code/cli/interactive/__init__.py +48 -0
- praisonai_code/cli/interactive/async_tui.py +1218 -0
- praisonai_code/cli/interactive/config.py +139 -0
- praisonai_code/cli/interactive/core.py +618 -0
- praisonai_code/cli/interactive/events.py +131 -0
- praisonai_code/cli/interactive/frontends/__init__.py +31 -0
- praisonai_code/cli/interactive/frontends/rich_frontend.py +462 -0
- praisonai_code/cli/interactive/frontends/textual_frontend.py +157 -0
- praisonai_code/cli/interactive/praison_io.py +502 -0
- praisonai_code/cli/interactive/repl.py +297 -0
- praisonai_code/cli/interactive/split_tui.py +456 -0
- praisonai_code/cli/interactive/tui_app.py +457 -0
- praisonai_code/cli/langfuse_client.py +360 -0
- praisonai_code/cli/main.py +7421 -0
- praisonai_code/cli/output/__init__.py +25 -0
- praisonai_code/cli/output/console.py +456 -0
- praisonai_code/cli/output/event_bridge.py +191 -0
- praisonai_code/cli/schedule_cli.py +54 -0
- praisonai_code/cli/schema_provider.py +23 -0
- praisonai_code/cli/session/__init__.py +16 -0
- praisonai_code/cli/session/resume.py +148 -0
- praisonai_code/cli/session/unified.py +548 -0
- praisonai_code/cli/state/__init__.py +31 -0
- praisonai_code/cli/state/identifiers.py +161 -0
- praisonai_code/cli/state/project_sessions.py +383 -0
- praisonai_code/cli/state/sessions.py +390 -0
- praisonai_code/cli/ui/__init__.py +160 -0
- praisonai_code/cli/ui/config.py +46 -0
- praisonai_code/cli/ui/events.py +61 -0
- praisonai_code/cli/ui/mg_backend.py +342 -0
- praisonai_code/cli/ui/plain.py +133 -0
- praisonai_code/cli/ui/rich_backend.py +162 -0
- praisonai_code/cli/unified_schema.py +655 -0
- praisonai_code/cli/utils/env_utils.py +126 -0
- praisonai_code/cli/utils/project.py +131 -0
- praisonai_code/cli_backends/__init__.py +73 -0
- praisonai_code/cli_backends/claude.py +373 -0
- praisonai_code/cli_backends/registry.py +113 -0
- praisonai_code/runtime/__init__.py +36 -0
- praisonai_code/runtime/__main__.py +81 -0
- praisonai_code/runtime/client.py +131 -0
- praisonai_code/runtime/descriptor.py +209 -0
- praisonai_code/runtime/server.py +356 -0
- praisonai_code-0.0.1.dist-info/METADATA +80 -0
- praisonai_code-0.0.1.dist-info/RECORD +309 -0
- praisonai_code-0.0.1.dist-info/WHEEL +5 -0
- 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)
|