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,332 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Chat command group for PraisonAI CLI.
|
|
3
|
+
|
|
4
|
+
Provides terminal-native interactive chat mode.
|
|
5
|
+
This command NEVER opens a browser - it runs entirely in the terminal.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from typing import List, Optional, Union
|
|
9
|
+
|
|
10
|
+
import typer
|
|
11
|
+
|
|
12
|
+
app = typer.Typer(help="Terminal-native interactive chat mode")
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def _parse_memory_flag(memory: Optional[str], no_memory: bool) -> Union[bool, str, None]:
|
|
16
|
+
"""
|
|
17
|
+
Parse memory CLI flag to value for Agent.
|
|
18
|
+
|
|
19
|
+
Precedence: --no-memory > --memory=value > --memory (flag) > None
|
|
20
|
+
|
|
21
|
+
Args:
|
|
22
|
+
memory: Memory flag value (None, "true", preset string, or URL)
|
|
23
|
+
no_memory: Whether --no-memory was specified
|
|
24
|
+
|
|
25
|
+
Returns:
|
|
26
|
+
- False if --no-memory
|
|
27
|
+
- True if --memory (flag only)
|
|
28
|
+
- str if --memory=preset or --memory=URL
|
|
29
|
+
- None if neither specified
|
|
30
|
+
"""
|
|
31
|
+
if no_memory:
|
|
32
|
+
return False
|
|
33
|
+
|
|
34
|
+
if memory is None:
|
|
35
|
+
return None
|
|
36
|
+
|
|
37
|
+
# --memory flag without value sets "true"
|
|
38
|
+
if memory.lower() == "true":
|
|
39
|
+
return True
|
|
40
|
+
|
|
41
|
+
# --memory=false explicitly disables
|
|
42
|
+
if memory.lower() == "false":
|
|
43
|
+
return False
|
|
44
|
+
|
|
45
|
+
# Otherwise it's a preset or URL string
|
|
46
|
+
return memory
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
@app.callback(invoke_without_command=True)
|
|
50
|
+
def chat_main(
|
|
51
|
+
ctx: typer.Context,
|
|
52
|
+
prompt: Optional[str] = typer.Argument(None, help="Initial prompt for chat"),
|
|
53
|
+
model: Optional[str] = typer.Option(None, "--model", "-m", help="LLM model to use"),
|
|
54
|
+
verbose: bool = typer.Option(False, "--verbose", "-v", help="Verbose output"),
|
|
55
|
+
memory: Optional[str] = typer.Option(
|
|
56
|
+
None, "--memory",
|
|
57
|
+
help="Enable memory. Use --memory for default, --memory=redis for preset, --memory=postgresql://... for URL",
|
|
58
|
+
is_flag=False,
|
|
59
|
+
flag_value="true",
|
|
60
|
+
),
|
|
61
|
+
no_memory: bool = typer.Option(False, "--no-memory", help="Disable memory"),
|
|
62
|
+
tools: Optional[str] = typer.Option(None, "--tools", "-t", help="Tools file path"),
|
|
63
|
+
toolset: Optional[str] = typer.Option(None, "--toolset", help="Named toolset groups (comma-separated, e.g., web,files)"),
|
|
64
|
+
user_id: Optional[str] = typer.Option(None, "--user-id", help="User ID for memory isolation"),
|
|
65
|
+
session_id: Optional[str] = typer.Option(None, "--session", "-s", help="Session ID to resume"),
|
|
66
|
+
continue_session: bool = typer.Option(False, "--continue", "-c", help="Continue last session"),
|
|
67
|
+
file: Optional[List[str]] = typer.Option(None, "--file", "-f", help="Attach file(s) to prompt"),
|
|
68
|
+
workspace: Optional[str] = typer.Option(None, "--workspace", "-w", help="Workspace directory"),
|
|
69
|
+
no_acp: bool = typer.Option(False, "--no-acp", help="Disable ACP tools"),
|
|
70
|
+
no_lsp: bool = typer.Option(False, "--no-lsp", help="Disable LSP tools"),
|
|
71
|
+
safe_mode: bool = typer.Option(False, "--safe", help="Safe mode: require approval for file writes and commands"),
|
|
72
|
+
autonomy: bool = typer.Option(True, "--autonomy/--no-autonomy", help="Enable agent autonomy for complex tasks"),
|
|
73
|
+
# NEW: Agent-like consolidated params for ALL GREEN consistency
|
|
74
|
+
knowledge: Optional[str] = typer.Option(
|
|
75
|
+
None, "--knowledge", "-k",
|
|
76
|
+
help="Enable knowledge/RAG. Use --knowledge for default, --knowledge=docs/ for sources",
|
|
77
|
+
is_flag=False,
|
|
78
|
+
flag_value="true",
|
|
79
|
+
),
|
|
80
|
+
guardrails: Optional[str] = typer.Option(
|
|
81
|
+
None, "--guardrails",
|
|
82
|
+
help="Enable guardrails. Use --guardrails for default, --guardrails=strict for preset",
|
|
83
|
+
is_flag=False,
|
|
84
|
+
flag_value="true",
|
|
85
|
+
),
|
|
86
|
+
web: Optional[str] = typer.Option(
|
|
87
|
+
None, "--web",
|
|
88
|
+
help="Enable web search. Use --web for default, --web=duckduckgo for preset",
|
|
89
|
+
is_flag=False,
|
|
90
|
+
flag_value="true",
|
|
91
|
+
),
|
|
92
|
+
reflection: Optional[str] = typer.Option(
|
|
93
|
+
None, "--reflection",
|
|
94
|
+
help="Enable self-reflection. Use --reflection for default, --reflection=thorough for preset",
|
|
95
|
+
is_flag=False,
|
|
96
|
+
flag_value="true",
|
|
97
|
+
),
|
|
98
|
+
# NEW: Additional consolidated params for ALL GREEN feature parity
|
|
99
|
+
planning: Optional[str] = typer.Option(
|
|
100
|
+
None, "--planning",
|
|
101
|
+
help="Enable planning mode. Use --planning for default, --planning=thorough for preset",
|
|
102
|
+
is_flag=False,
|
|
103
|
+
flag_value="true",
|
|
104
|
+
),
|
|
105
|
+
context: Optional[str] = typer.Option(
|
|
106
|
+
None, "--context",
|
|
107
|
+
help="Enable context management. Use --context for default",
|
|
108
|
+
is_flag=False,
|
|
109
|
+
flag_value="true",
|
|
110
|
+
),
|
|
111
|
+
output: Optional[str] = typer.Option(
|
|
112
|
+
None, "--output", "-o",
|
|
113
|
+
help="Output mode (default: actions). Options: actions, plain, verbose, json, silent",
|
|
114
|
+
),
|
|
115
|
+
execution: Optional[str] = typer.Option(
|
|
116
|
+
None, "--execution",
|
|
117
|
+
help="Execution preset. Use --execution=fast, --execution=thorough, --execution=unlimited",
|
|
118
|
+
),
|
|
119
|
+
hooks: Optional[str] = typer.Option(
|
|
120
|
+
None, "--hooks",
|
|
121
|
+
help="Hooks config file path for lifecycle callbacks",
|
|
122
|
+
),
|
|
123
|
+
caching: Optional[str] = typer.Option(
|
|
124
|
+
None, "--caching",
|
|
125
|
+
help="Enable caching. Use --caching for default, --caching=redis for preset",
|
|
126
|
+
is_flag=False,
|
|
127
|
+
flag_value="true",
|
|
128
|
+
),
|
|
129
|
+
approval: Optional[str] = typer.Option(None, "--approval", help="Approval backend: console, slack, telegram, discord, webhook, http, agent, auto, none"),
|
|
130
|
+
profile: bool = typer.Option(False, "--profile", help="Enable CLI profiling (timing breakdown)"),
|
|
131
|
+
profile_deep: bool = typer.Option(False, "--profile-deep", help="Enable deep profiling (cProfile stats, higher overhead)"),
|
|
132
|
+
debug: bool = typer.Option(False, "--debug", help="Enable debug logging to ~/.praisonai/async_tui_debug.log"),
|
|
133
|
+
# UI backend selection
|
|
134
|
+
ui_backend: str = typer.Option("auto", "--ui-backend", help="UI backend: auto, plain, rich, mg (middle-ground)"),
|
|
135
|
+
json_output: bool = typer.Option(False, "--json", help="Output JSON (forces plain backend)"),
|
|
136
|
+
no_color: bool = typer.Option(False, "--no-color", help="Disable colors"),
|
|
137
|
+
theme: str = typer.Option("default", "--theme", help="UI theme: default, dark, light, minimal"),
|
|
138
|
+
compact: bool = typer.Option(False, "--compact", help="Compact output mode"),
|
|
139
|
+
no_rules: bool = typer.Option(False, "--no-rules", help="Disable auto-injection of project instruction files"),
|
|
140
|
+
):
|
|
141
|
+
"""
|
|
142
|
+
Start terminal-native interactive chat mode.
|
|
143
|
+
|
|
144
|
+
This is a terminal REPL with streaming responses, slash commands,
|
|
145
|
+
and multi-turn conversation support. It NEVER opens a browser.
|
|
146
|
+
|
|
147
|
+
For browser-based chat UI, use: praisonai ui chat
|
|
148
|
+
|
|
149
|
+
Examples:
|
|
150
|
+
praisonai chat
|
|
151
|
+
praisonai chat "Hello, how are you?"
|
|
152
|
+
praisonai chat --model gpt-4o --memory
|
|
153
|
+
praisonai chat --continue # Resume last session
|
|
154
|
+
praisonai chat "Summarize this" --file README.md
|
|
155
|
+
praisonai chat "What is 2+2?" --profile
|
|
156
|
+
"""
|
|
157
|
+
import os
|
|
158
|
+
|
|
159
|
+
# Set workspace if provided
|
|
160
|
+
if workspace:
|
|
161
|
+
os.environ["PRAISONAI_WORKSPACE"] = workspace
|
|
162
|
+
|
|
163
|
+
# Handle profiling for single prompt mode
|
|
164
|
+
if prompt and (profile or profile_deep):
|
|
165
|
+
_run_profiled_chat(
|
|
166
|
+
prompt=prompt,
|
|
167
|
+
model=model,
|
|
168
|
+
verbose=verbose,
|
|
169
|
+
profile_deep=profile_deep,
|
|
170
|
+
)
|
|
171
|
+
return
|
|
172
|
+
|
|
173
|
+
# Warn if profiling requested without prompt (REPL mode doesn't support profiling)
|
|
174
|
+
if (profile or profile_deep) and not prompt:
|
|
175
|
+
typer.echo("⚠️ Profiling is only supported for single prompt mode.", err=True)
|
|
176
|
+
typer.echo(" Use: praisonai chat \"your prompt\" --profile", err=True)
|
|
177
|
+
|
|
178
|
+
# Parse memory flag: --no-memory takes precedence, then --memory value
|
|
179
|
+
# TODO: Pass memory_value to TUI when memory support is added
|
|
180
|
+
_parse_memory_flag(memory, no_memory)
|
|
181
|
+
|
|
182
|
+
# Set approval mode based on --safe flag
|
|
183
|
+
import os
|
|
184
|
+
if safe_mode:
|
|
185
|
+
os.environ["PRAISON_APPROVAL_MODE"] = "prompt"
|
|
186
|
+
else:
|
|
187
|
+
os.environ["PRAISON_APPROVAL_MODE"] = "auto"
|
|
188
|
+
|
|
189
|
+
# Wire --approval backend via global registry (TUI creates agents internally)
|
|
190
|
+
if approval:
|
|
191
|
+
from praisonai.cli.features.approval import resolve_approval_backend
|
|
192
|
+
try:
|
|
193
|
+
backend = resolve_approval_backend(approval)
|
|
194
|
+
if backend is not None:
|
|
195
|
+
from praisonaiagents.approval import get_approval_registry
|
|
196
|
+
get_approval_registry().set_backend(backend)
|
|
197
|
+
typer.echo(f"Approval backend: {approval}")
|
|
198
|
+
except ValueError as e:
|
|
199
|
+
typer.echo(f"Error: {e}", err=True)
|
|
200
|
+
raise typer.Exit(1)
|
|
201
|
+
|
|
202
|
+
# Use the async TUI (non-blocking, scrollable output)
|
|
203
|
+
from praisonai.cli.interactive.async_tui import AsyncTUI, AsyncTUIConfig
|
|
204
|
+
|
|
205
|
+
# Resolve a provider-aware default when no model was given:
|
|
206
|
+
# explicit --model > most-recently-used > provider credentials present.
|
|
207
|
+
try:
|
|
208
|
+
from ..configuration.model_resolver import resolve_default_model
|
|
209
|
+
resolved_model = resolve_default_model(model)
|
|
210
|
+
except Exception:
|
|
211
|
+
resolved_model = model or "gpt-4o-mini"
|
|
212
|
+
|
|
213
|
+
tui_config = AsyncTUIConfig(
|
|
214
|
+
model=resolved_model,
|
|
215
|
+
show_logo=not compact,
|
|
216
|
+
show_status_bar=not compact,
|
|
217
|
+
session_id=session_id,
|
|
218
|
+
workspace=workspace,
|
|
219
|
+
debug=debug,
|
|
220
|
+
autonomy_mode=autonomy,
|
|
221
|
+
no_rules=no_rules,
|
|
222
|
+
)
|
|
223
|
+
|
|
224
|
+
tui = AsyncTUI(config=tui_config)
|
|
225
|
+
|
|
226
|
+
if prompt:
|
|
227
|
+
# Single prompt mode - direct response, no streaming
|
|
228
|
+
response = tui.run_single(prompt)
|
|
229
|
+
if response:
|
|
230
|
+
print(response)
|
|
231
|
+
else:
|
|
232
|
+
# Interactive split-pane TUI mode
|
|
233
|
+
tui.run()
|
|
234
|
+
|
|
235
|
+
|
|
236
|
+
def _run_profiled_chat(
|
|
237
|
+
prompt: str,
|
|
238
|
+
model: Optional[str] = None,
|
|
239
|
+
verbose: bool = False,
|
|
240
|
+
profile_deep: bool = False,
|
|
241
|
+
):
|
|
242
|
+
"""Run chat with profiling enabled."""
|
|
243
|
+
from praisonai.cli.features.cli_profiler import (
|
|
244
|
+
CLIProfileConfig,
|
|
245
|
+
CLIProfiler,
|
|
246
|
+
)
|
|
247
|
+
|
|
248
|
+
config = CLIProfileConfig(enabled=True, deep=profile_deep)
|
|
249
|
+
profiler = CLIProfiler(config)
|
|
250
|
+
|
|
251
|
+
if profile_deep:
|
|
252
|
+
typer.echo("⚠️ Deep profiling enabled - this adds significant overhead", err=True)
|
|
253
|
+
|
|
254
|
+
profiler.start()
|
|
255
|
+
|
|
256
|
+
# Import phase
|
|
257
|
+
profiler.mark_import_start()
|
|
258
|
+
try:
|
|
259
|
+
from praisonaiagents import Agent
|
|
260
|
+
except ImportError:
|
|
261
|
+
typer.echo("Error: praisonaiagents not installed", err=True)
|
|
262
|
+
raise typer.Exit(1)
|
|
263
|
+
profiler.mark_import_end()
|
|
264
|
+
|
|
265
|
+
# Agent initialization phase
|
|
266
|
+
profiler.mark_init_start()
|
|
267
|
+
agent_config = {
|
|
268
|
+
"name": "ChatAgent",
|
|
269
|
+
"role": "Assistant",
|
|
270
|
+
"goal": "Help the user",
|
|
271
|
+
}
|
|
272
|
+
if model:
|
|
273
|
+
agent_config["llm"] = model
|
|
274
|
+
|
|
275
|
+
agent = Agent(**agent_config)
|
|
276
|
+
profiler.mark_init_end()
|
|
277
|
+
|
|
278
|
+
# Execution phase
|
|
279
|
+
profiler.mark_exec_start()
|
|
280
|
+
response = agent.start(prompt)
|
|
281
|
+
profiler.mark_exec_end()
|
|
282
|
+
|
|
283
|
+
profiler.stop()
|
|
284
|
+
|
|
285
|
+
# Print response
|
|
286
|
+
if response:
|
|
287
|
+
print(response)
|
|
288
|
+
|
|
289
|
+
# Print profiling report
|
|
290
|
+
profiler.print_report()
|
|
291
|
+
|
|
292
|
+
|
|
293
|
+
def _run_legacy_terminal_chat(
|
|
294
|
+
prompt: Optional[str] = None,
|
|
295
|
+
model: Optional[str] = None,
|
|
296
|
+
verbose: bool = False,
|
|
297
|
+
memory: bool = False,
|
|
298
|
+
tools: Optional[str] = None,
|
|
299
|
+
toolset: Optional[str] = None,
|
|
300
|
+
user_id: Optional[str] = None,
|
|
301
|
+
session_id: Optional[str] = None,
|
|
302
|
+
continue_session: bool = False,
|
|
303
|
+
workspace: Optional[str] = None,
|
|
304
|
+
no_acp: bool = False,
|
|
305
|
+
no_lsp: bool = False,
|
|
306
|
+
):
|
|
307
|
+
"""Run terminal-native chat using legacy _start_interactive_mode."""
|
|
308
|
+
import argparse
|
|
309
|
+
|
|
310
|
+
# Build args namespace for _start_interactive_mode
|
|
311
|
+
args = argparse.Namespace()
|
|
312
|
+
args.llm = model
|
|
313
|
+
args.verbose = verbose
|
|
314
|
+
args.memory = memory
|
|
315
|
+
args.tools = tools
|
|
316
|
+
args.toolset = toolset
|
|
317
|
+
args.user_id = user_id
|
|
318
|
+
args.resume_session = session_id if session_id else ('last' if continue_session else None)
|
|
319
|
+
args.no_acp = no_acp
|
|
320
|
+
args.no_lsp = no_lsp
|
|
321
|
+
|
|
322
|
+
# Import and run the terminal-native interactive mode
|
|
323
|
+
from praisonai.cli.main import PraisonAI
|
|
324
|
+
|
|
325
|
+
praison = PraisonAI()
|
|
326
|
+
|
|
327
|
+
if prompt:
|
|
328
|
+
# Single prompt mode - use _run_chat_mode
|
|
329
|
+
praison._run_chat_mode(prompt, args)
|
|
330
|
+
else:
|
|
331
|
+
# Interactive REPL mode - use _start_interactive_mode
|
|
332
|
+
praison._start_interactive_mode(args)
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Checkpoint command group for PraisonAI CLI.
|
|
3
|
+
|
|
4
|
+
Surfaces the core file-level checkpoint engine
|
|
5
|
+
(``praisonaiagents.checkpoints.CheckpointService``) as first-class CLI
|
|
6
|
+
commands, delegating to the existing :class:`CheckpointsHandler`.
|
|
7
|
+
|
|
8
|
+
Examples:
|
|
9
|
+
praisonai checkpoint save "before refactor"
|
|
10
|
+
praisonai checkpoint list
|
|
11
|
+
praisonai checkpoint restore <id|last>
|
|
12
|
+
praisonai checkpoint diff [from] [to]
|
|
13
|
+
praisonai checkpoint delete
|
|
14
|
+
"""
|
|
15
|
+
|
|
16
|
+
import asyncio
|
|
17
|
+
import os
|
|
18
|
+
from typing import Optional
|
|
19
|
+
|
|
20
|
+
import typer
|
|
21
|
+
|
|
22
|
+
app = typer.Typer(help="File-level checkpoint management (save / restore / diff)")
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def _resolve_storage_dir() -> Optional[str]:
|
|
26
|
+
"""Return a configured ``checkpoints.storage_dir`` if one is set.
|
|
27
|
+
|
|
28
|
+
Threading this through keeps the standalone ``praisonai checkpoint``
|
|
29
|
+
commands reading from the same store the interactive coding session
|
|
30
|
+
(``code --checkpoints``) writes to. Falls back to ``None`` (the default
|
|
31
|
+
store) when no config is present or it cannot be read.
|
|
32
|
+
"""
|
|
33
|
+
try:
|
|
34
|
+
from ..configuration.resolver import resolve_config
|
|
35
|
+
|
|
36
|
+
section = (resolve_config().extra or {}).get("checkpoints", {})
|
|
37
|
+
if isinstance(section, dict):
|
|
38
|
+
return section.get("storage_dir")
|
|
39
|
+
except Exception:
|
|
40
|
+
pass
|
|
41
|
+
return None
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def _handler(workspace: Optional[str] = None, verbose: bool = False):
|
|
45
|
+
"""Build a CheckpointsHandler for the current workspace."""
|
|
46
|
+
from praisonai.cli.features.checkpoints import CheckpointsHandler
|
|
47
|
+
|
|
48
|
+
return CheckpointsHandler(
|
|
49
|
+
workspace_dir=workspace or os.getcwd(),
|
|
50
|
+
verbose=verbose,
|
|
51
|
+
storage_dir=_resolve_storage_dir(),
|
|
52
|
+
)
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
async def _resolve_checkpoint_id(handler, ref: str) -> Optional[str]:
|
|
56
|
+
"""Resolve a checkpoint reference (an id/short_id or the literal 'last').
|
|
57
|
+
|
|
58
|
+
Resolution order: literal ``last``/``latest`` -> exact id/short_id ->
|
|
59
|
+
unique id prefix. Ambiguous prefixes (matching more than one checkpoint)
|
|
60
|
+
are rejected so a workspace-mutating restore never targets the wrong
|
|
61
|
+
checkpoint.
|
|
62
|
+
|
|
63
|
+
Returns the resolved checkpoint id, or ``None`` when no matching (or an
|
|
64
|
+
ambiguous) checkpoint reference is given.
|
|
65
|
+
"""
|
|
66
|
+
service = await handler._get_service()
|
|
67
|
+
checkpoints = await service.list_checkpoints(limit=100)
|
|
68
|
+
if not checkpoints:
|
|
69
|
+
return None
|
|
70
|
+
|
|
71
|
+
if ref in ("last", "latest"):
|
|
72
|
+
# list_checkpoints returns newest-first.
|
|
73
|
+
return checkpoints[0].id
|
|
74
|
+
|
|
75
|
+
exact = [cp.id for cp in checkpoints if cp.id == ref or cp.short_id == ref]
|
|
76
|
+
if exact:
|
|
77
|
+
return exact[0]
|
|
78
|
+
|
|
79
|
+
prefix_matches = [cp.id for cp in checkpoints if cp.id.startswith(ref)]
|
|
80
|
+
if len(prefix_matches) == 1:
|
|
81
|
+
return prefix_matches[0]
|
|
82
|
+
if len(prefix_matches) > 1:
|
|
83
|
+
handler._print_error(f"Ambiguous checkpoint reference: {ref}")
|
|
84
|
+
return None
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
@app.command("save")
|
|
88
|
+
def save(
|
|
89
|
+
message: str = typer.Argument(..., help="Checkpoint message"),
|
|
90
|
+
allow_empty: bool = typer.Option(False, "--allow-empty", help="Allow checkpoint with no changes"),
|
|
91
|
+
workspace: Optional[str] = typer.Option(None, "--workspace", "-w", help="Workspace directory"),
|
|
92
|
+
):
|
|
93
|
+
"""Save a checkpoint of the current workspace."""
|
|
94
|
+
handler = _handler(workspace)
|
|
95
|
+
ok = asyncio.run(handler.save(message, allow_empty=allow_empty))
|
|
96
|
+
if not ok:
|
|
97
|
+
raise typer.Exit(1)
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
@app.command("list")
|
|
101
|
+
def list_checkpoints(
|
|
102
|
+
limit: int = typer.Option(20, "--limit", "-n", help="Maximum checkpoints to show"),
|
|
103
|
+
workspace: Optional[str] = typer.Option(None, "--workspace", "-w", help="Workspace directory"),
|
|
104
|
+
):
|
|
105
|
+
"""List checkpoints for the workspace (newest first)."""
|
|
106
|
+
handler = _handler(workspace)
|
|
107
|
+
asyncio.run(handler.list_checkpoints(limit=limit))
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
@app.command("restore")
|
|
111
|
+
def restore(
|
|
112
|
+
checkpoint_id: str = typer.Argument(..., help="Checkpoint id, short id, or 'last'"),
|
|
113
|
+
workspace: Optional[str] = typer.Option(None, "--workspace", "-w", help="Workspace directory"),
|
|
114
|
+
):
|
|
115
|
+
"""Restore the workspace to a checkpoint (accepts 'last')."""
|
|
116
|
+
handler = _handler(workspace)
|
|
117
|
+
|
|
118
|
+
async def _run() -> bool:
|
|
119
|
+
resolved = await _resolve_checkpoint_id(handler, checkpoint_id)
|
|
120
|
+
if resolved is None:
|
|
121
|
+
handler._print_error(f"No checkpoint found for: {checkpoint_id}")
|
|
122
|
+
return False
|
|
123
|
+
return await handler.restore(resolved)
|
|
124
|
+
|
|
125
|
+
if not asyncio.run(_run()):
|
|
126
|
+
raise typer.Exit(1)
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
@app.command("diff")
|
|
130
|
+
def diff(
|
|
131
|
+
from_id: Optional[str] = typer.Argument(None, help="Starting checkpoint (default: previous)"),
|
|
132
|
+
to_id: Optional[str] = typer.Argument(None, help="Ending checkpoint (default: working directory)"),
|
|
133
|
+
workspace: Optional[str] = typer.Option(None, "--workspace", "-w", help="Workspace directory"),
|
|
134
|
+
):
|
|
135
|
+
"""Show the diff between checkpoints (or against the working directory)."""
|
|
136
|
+
handler = _handler(workspace)
|
|
137
|
+
|
|
138
|
+
async def _run() -> None:
|
|
139
|
+
# Resolve the same references restore accepts ('last'/short id/prefix)
|
|
140
|
+
# so `diff last` or `diff <short_id>` don't reach git as literal refs.
|
|
141
|
+
resolved_from = (
|
|
142
|
+
await _resolve_checkpoint_id(handler, from_id) if from_id else None
|
|
143
|
+
)
|
|
144
|
+
resolved_to = (
|
|
145
|
+
await _resolve_checkpoint_id(handler, to_id) if to_id else None
|
|
146
|
+
)
|
|
147
|
+
if from_id and resolved_from is None:
|
|
148
|
+
handler._print_error(f"No checkpoint found for: {from_id}")
|
|
149
|
+
return
|
|
150
|
+
if to_id and resolved_to is None:
|
|
151
|
+
handler._print_error(f"No checkpoint found for: {to_id}")
|
|
152
|
+
return
|
|
153
|
+
await handler.diff(resolved_from, resolved_to)
|
|
154
|
+
|
|
155
|
+
asyncio.run(_run())
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
@app.command("delete")
|
|
159
|
+
def delete(
|
|
160
|
+
yes: bool = typer.Option(False, "--yes", "-y", help="Skip confirmation prompt"),
|
|
161
|
+
workspace: Optional[str] = typer.Option(None, "--workspace", "-w", help="Workspace directory"),
|
|
162
|
+
):
|
|
163
|
+
"""Delete all checkpoints for the workspace."""
|
|
164
|
+
handler = _handler(workspace)
|
|
165
|
+
if not yes and not typer.confirm("Delete all checkpoints?"):
|
|
166
|
+
typer.echo("Cancelled")
|
|
167
|
+
return
|
|
168
|
+
ok = asyncio.run(handler.delete_all())
|
|
169
|
+
if not ok:
|
|
170
|
+
raise typer.Exit(1)
|