praisonai-code 0.0.30__tar.gz → 0.0.32__tar.gz
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-0.0.30 → praisonai_code-0.0.32}/PKG-INFO +1 -1
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/__init__.py +1 -1
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/approval_backend.py +138 -38
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/commands/run.py +4 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/configuration/credentials.py +39 -12
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/features/setup/handler.py +61 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code.egg-info/PKG-INFO +1 -1
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/pyproject.toml +1 -1
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/README.md +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/__main__.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/_bot_bridge.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/_framework_availability.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/_logging.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/_registry.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/_safe_loader.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/_version.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/_wrapper_bridge.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/__init__.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/_forward_shim.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/_paths.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/_warnings.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/_wrapper_reexport.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/app.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/branding.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/commands/__init__.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/commands/acp.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/commands/agent.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/commands/agents.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/commands/attach.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/commands/auth.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/commands/benchmark.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/commands/browser.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/commands/call.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/commands/chat.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/commands/checkpoint.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/commands/code.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/commands/command.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/commands/commit.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/commands/completion.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/commands/config.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/commands/daemon.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/commands/debug.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/commands/deploy.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/commands/diag.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/commands/doctor.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/commands/endpoints.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/commands/environment.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/commands/eval.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/commands/github.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/commands/hooks.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/commands/init.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/commands/loop.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/commands/lsp.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/commands/memory.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/commands/models.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/commands/obs.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/commands/package.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/commands/paths.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/commands/permissions.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/commands/plugins.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/commands/port.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/commands/publish.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/commands/registry.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/commands/research.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/commands/retrieval.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/commands/rules.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/commands/sandbox.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/commands/serve.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/commands/session.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/commands/setup.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/commands/skills.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/commands/templates.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/commands/test.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/commands/todo.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/commands/tools.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/commands/traces.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/commands/tracker.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/commands/ui.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/commands/up.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/commands/version.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/commands/workflow.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/config_loader.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/configuration/__init__.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/configuration/config.schema.json +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/configuration/loader.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/configuration/model_resolver.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/configuration/oauth.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/configuration/paths.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/configuration/resolver.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/configuration/schema.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/execution/__init__.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/execution/core.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/execution/profiler.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/execution/request.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/execution/result.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/fallback_schema.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/features/__init__.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/features/_approval_bridge.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/features/_endpoint_registry.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/features/_search_registry.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/features/action_orchestrator.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/features/agents.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/features/at_mentions.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/features/audit_cli.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/features/auto_memory.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/features/auto_mode.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/features/autonomy_mode.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/features/base.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/features/benchmark.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/features/capabilities.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/features/checkpoints.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/features/cli_profiler.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/features/code_intelligence.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/features/compaction.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/features/compare.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/features/config_hierarchy.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/features/context_manager.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/features/cost_tracker.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/features/csv_test_runner.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/features/custom_definitions.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/features/debug.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/features/diag.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/features/display_jsonl.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/features/doctor/__init__.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/features/doctor/checks/__init__.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/features/doctor/checks/_wrapper_checks.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/features/doctor/checks/acp_checks.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/features/doctor/checks/bot_checks.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/features/doctor/checks/config_checks.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/features/doctor/checks/db_checks.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/features/doctor/checks/env_checks.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/features/doctor/checks/gateway_checks.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/features/doctor/checks/lsp_checks.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/features/doctor/checks/mcp_checks.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/features/doctor/checks/memory_checks.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/features/doctor/checks/network_checks.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/features/doctor/checks/obs_checks.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/features/doctor/checks/packaging_checks.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/features/doctor/checks/performance_checks.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/features/doctor/checks/permissions_checks.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/features/doctor/checks/runtime_checks.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/features/doctor/checks/runtime_migration_checks.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/features/doctor/checks/selftest_checks.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/features/doctor/checks/serve_checks.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/features/doctor/checks/skills_checks.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/features/doctor/checks/tools_checks.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/features/doctor/engine.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/features/doctor/formatters.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/features/doctor/handler.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/features/doctor/models.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/features/doctor/registry.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/features/examples.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/features/external_agents.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/features/fast_context.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/features/file_history.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/features/flow_display.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/features/git_attribution.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/features/git_integration.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/features/guardrail.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/features/handoff.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/features/hooks.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/features/hybrid_workflow.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/features/image.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/features/interactive_core_headless.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/features/interactive_runtime.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/features/interactive_test_harness.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/features/interactive_tools.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/features/interactive_tui.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/features/job_workflow.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/features/jobs.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/features/knowledge.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/features/knowledge_cli.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/features/lite.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/features/logs.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/features/lsp_cli.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/features/lsp_diagnostics.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/features/mcp.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/features/message_queue.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/features/metrics.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/features/migrate.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/features/migration_flow.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/features/migration_spec.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/features/n8n.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/features/observability.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/features/output_modes.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/features/output_style.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/features/package.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/features/performance.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/features/profiler/__init__.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/features/profiler/core.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/features/profiler/optimizations.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/features/profiler/suite.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/features/queue/__init__.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/features/queue/manager.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/features/queue/models.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/features/queue/persistence.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/features/queue/scheduler.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/features/queue/worker.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/features/recipe_creator.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/features/recipe_prompts.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/features/repo_map.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/features/router.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/features/safe_shell.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/features/sandbox_executor.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/features/sdk_knowledge.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/features/session.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/features/session_checkpoints.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/features/setup/__init__.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/features/setup/templates.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/features/skills.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/features/slash_commands.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/features/telemetry.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/features/thinking.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/features/todo.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/features/tools.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/features/tui/__init__.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/features/tui/cli.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/features/tui/config.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/features/tui/debug.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/features/tui/events.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/features/tui/mock_provider.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/features/tui/orchestrator.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/features/tui/screens/__init__.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/features/tui/screens/help.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/features/tui/screens/main.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/features/tui/screens/queue.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/features/tui/screens/session.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/features/tui/screens/settings.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/features/tui/session_store.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/features/tui/widgets/__init__.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/features/tui/widgets/chat.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/features/tui/widgets/command_popup.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/features/tui/widgets/composer.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/features/tui/widgets/file_popup.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/features/tui/widgets/queue_panel.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/features/tui/widgets/status.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/features/tui/widgets/tool_panel.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/features/wizard.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/features/workflow.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/features/yaml_utils.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/interactive/__init__.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/interactive/async_tui.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/interactive/config.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/interactive/core.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/interactive/events.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/interactive/frontends/__init__.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/interactive/frontends/rich_frontend.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/interactive/frontends/textual_frontend.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/interactive/praison_io.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/interactive/repl.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/interactive/split_tui.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/interactive/tui_app.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/legacy/__init__.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/legacy/env_security.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/legacy/praison_ai.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/legacy/prompt_dispatch.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/main.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/output/__init__.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/output/console.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/output/event_bridge.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/schedule_cli.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/schema_provider.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/session/__init__.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/session/resume.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/session/unified.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/state/__init__.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/state/identifiers.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/state/project_sessions.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/state/sessions.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/ui/__init__.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/ui/config.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/ui/events.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/ui/mg_backend.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/ui/plain.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/ui/rich_backend.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/unified_schema.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/utils/env_utils.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/utils/project.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/utils/stdin.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli_backends/__init__.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli_backends/claude.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli_backends/registry.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/llm/__init__.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/llm/catalogue.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/llm/config.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/llm/credentials.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/llm/env.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/runtime/__init__.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/runtime/__main__.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/runtime/client.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/runtime/descriptor.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/runtime/server.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/tool_registry.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/tool_resolver.py +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code.egg-info/SOURCES.txt +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code.egg-info/dependency_links.txt +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code.egg-info/entry_points.txt +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code.egg-info/requires.txt +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code.egg-info/top_level.txt +0 -0
- {praisonai_code-0.0.30 → praisonai_code-0.0.32}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: praisonai-code
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.32
|
|
4
4
|
Summary: Agentic terminal CLI for PraisonAI — the terminal-native agent (run, chat, code, runtime, cli backends) extracted from the praisonai wrapper.
|
|
5
5
|
Author: Mervin Praison
|
|
6
6
|
License: MIT
|
|
@@ -87,17 +87,20 @@ class InteractiveCLIApprovalBackend:
|
|
|
87
87
|
|
|
88
88
|
return f"{tool_name}({args_display})"
|
|
89
89
|
|
|
90
|
-
def _prompt_user(self, request: ApprovalRequest) -> tuple[bool, bool]:
|
|
90
|
+
def _prompt_user(self, request: ApprovalRequest) -> tuple[bool, bool, str, Optional[str]]:
|
|
91
91
|
"""
|
|
92
92
|
Prompt user for approval decision.
|
|
93
|
-
|
|
93
|
+
|
|
94
94
|
Returns:
|
|
95
|
-
Tuple of (approved, persist_as_always)
|
|
95
|
+
Tuple of ``(approved, persist_as_always, scope, deny_reason)`` where
|
|
96
|
+
``scope`` is ``"command"`` (narrow, command-prefix) or ``"tool"``
|
|
97
|
+
(explicit blanket ``tool:*``) and ``deny_reason`` is optional
|
|
98
|
+
steering feedback captured on denial (``None`` when absent).
|
|
96
99
|
"""
|
|
97
100
|
if self.non_interactive:
|
|
98
101
|
# In non-interactive mode, we're only here if the check returned ASK
|
|
99
102
|
# (ALLOW/DENY are handled in request_approval), so default to deny
|
|
100
|
-
return (False, False)
|
|
103
|
+
return (False, False, "command", None)
|
|
101
104
|
|
|
102
105
|
# Interactive prompt
|
|
103
106
|
tool_display = self._format_tool_call(request)
|
|
@@ -113,10 +116,21 @@ class InteractiveCLIApprovalBackend:
|
|
|
113
116
|
print(f"Risk: {request.risk_level}")
|
|
114
117
|
if request.agent_name:
|
|
115
118
|
print(f"Agent: {request.agent_name}")
|
|
116
|
-
|
|
119
|
+
|
|
120
|
+
# Show a preview of the actual change for file-mutating tools so the
|
|
121
|
+
# user approves the concrete change, not just a tool name.
|
|
122
|
+
preview = self._render_preview(request)
|
|
123
|
+
if preview:
|
|
124
|
+
print(preview)
|
|
125
|
+
|
|
126
|
+
# Compute the narrow pattern once so the user can see exactly what a
|
|
127
|
+
# persisted "always" will grant.
|
|
128
|
+
narrow_pattern = self._create_pattern(request, scope="command")
|
|
129
|
+
|
|
117
130
|
print("\nOptions:")
|
|
118
131
|
print(" [a] Allow once")
|
|
119
|
-
print(" [A] Always allow (
|
|
132
|
+
print(f" [A] Always allow this command ({narrow_pattern})")
|
|
133
|
+
print(f" [T] Always allow ALL uses of {request.tool_name} ({request.tool_name}:*)")
|
|
120
134
|
print(" [d] Deny")
|
|
121
135
|
print(" [D] Always deny (persist rule)")
|
|
122
136
|
|
|
@@ -125,41 +139,117 @@ class InteractiveCLIApprovalBackend:
|
|
|
125
139
|
choice = input("\nYour choice: ").strip()
|
|
126
140
|
|
|
127
141
|
if choice == "a":
|
|
128
|
-
return (True, False)
|
|
142
|
+
return (True, False, "command", None)
|
|
129
143
|
elif choice == "A":
|
|
130
|
-
return (True, True)
|
|
144
|
+
return (True, True, "command", None)
|
|
145
|
+
elif choice == "T":
|
|
146
|
+
return (True, True, "tool", None)
|
|
131
147
|
elif choice == "d":
|
|
132
|
-
return (False, False)
|
|
148
|
+
return (False, False, "command", self._prompt_deny_reason())
|
|
133
149
|
elif choice == "D":
|
|
134
|
-
return (False, True)
|
|
150
|
+
return (False, True, "command", self._prompt_deny_reason())
|
|
135
151
|
else:
|
|
136
|
-
print("Invalid choice. Please enter a, A, d, or D.")
|
|
152
|
+
print("Invalid choice. Please enter a, A, T, d, or D.")
|
|
137
153
|
except (EOFError, KeyboardInterrupt):
|
|
138
154
|
print("\n\nApproval cancelled.")
|
|
139
|
-
return (False, False)
|
|
155
|
+
return (False, False, "command", None)
|
|
156
|
+
|
|
157
|
+
def _prompt_deny_reason(self) -> Optional[str]:
|
|
158
|
+
"""Optionally capture a denial reason to steer the agent.
|
|
159
|
+
|
|
160
|
+
Returns the trimmed reason string, or ``None`` if the user provides no
|
|
161
|
+
feedback (blank input) or input is unavailable.
|
|
162
|
+
"""
|
|
163
|
+
try:
|
|
164
|
+
reason = input("Reason for denial (optional, steers the agent): ").strip()
|
|
165
|
+
except (EOFError, KeyboardInterrupt):
|
|
166
|
+
return None
|
|
167
|
+
return reason or None
|
|
168
|
+
|
|
169
|
+
def _render_preview(self, request: ApprovalRequest) -> Optional[str]:
|
|
170
|
+
"""Render a change preview for file-mutating tools.
|
|
171
|
+
|
|
172
|
+
For ``edit``/``apply_patch`` a unified diff is shown when available;
|
|
173
|
+
for ``write`` the content (truncated) is shown. Returns ``None`` when
|
|
174
|
+
there is nothing meaningful to preview.
|
|
175
|
+
"""
|
|
176
|
+
tool_name = request.tool_name
|
|
177
|
+
args = request.arguments or {}
|
|
178
|
+
if tool_name not in ("edit", "write", "apply_patch"):
|
|
179
|
+
return None
|
|
180
|
+
|
|
181
|
+
# Prefer an already-computed diff if the caller supplied one.
|
|
182
|
+
diff = args.get("diff") or args.get("patch")
|
|
183
|
+
if isinstance(diff, str) and diff.strip():
|
|
184
|
+
return f"\nPreview (diff):\n{diff}"
|
|
185
|
+
|
|
186
|
+
if tool_name == "write":
|
|
187
|
+
content = args.get("content") or args.get("text")
|
|
188
|
+
path = args.get("path") or args.get("file_path") or ""
|
|
189
|
+
if isinstance(content, str):
|
|
190
|
+
shown = content if len(content) <= 2000 else content[:2000] + "\n... (truncated)"
|
|
191
|
+
header = f" to {path}" if path else ""
|
|
192
|
+
return f"\nPreview (content{header}):\n{shown}"
|
|
193
|
+
|
|
194
|
+
return None
|
|
140
195
|
|
|
141
|
-
def _create_pattern(self, request: ApprovalRequest) -> str:
|
|
142
|
-
"""Create a permission pattern from the request.
|
|
143
|
-
|
|
144
|
-
|
|
196
|
+
def _create_pattern(self, request: ApprovalRequest, scope: str = "command") -> str:
|
|
197
|
+
"""Create a permission pattern from the request.
|
|
198
|
+
|
|
199
|
+
Derives the *narrowest reasonable* persisted pattern so that approving a
|
|
200
|
+
single command does not silently grant unrestricted use of a tool.
|
|
201
|
+
|
|
202
|
+
Args:
|
|
203
|
+
request: The approval request.
|
|
204
|
+
scope: ``"command"`` (default) derives a command-prefix scope for
|
|
205
|
+
shell tools (e.g. ``bash:git status *``) and a per-argument
|
|
206
|
+
scope for other tools. ``"tool"`` is the explicit, clearly
|
|
207
|
+
labelled "allow all uses of this tool" choice which emits the
|
|
208
|
+
blanket ``tool_name:*`` pattern.
|
|
209
|
+
|
|
210
|
+
Returns:
|
|
211
|
+
A permission glob pattern. For ``scope="command"`` the result is
|
|
212
|
+
**never** the blanket ``tool_name:*``; malformed, missing, or
|
|
213
|
+
oversized arguments fall back to a literal (single-use) target so
|
|
214
|
+
the persisted rule can only match the exact invocation the user
|
|
215
|
+
approved, preserving a fail-closed posture. Only the explicit
|
|
216
|
+
``scope="tool"`` choice emits ``tool_name:*``.
|
|
217
|
+
"""
|
|
145
218
|
tool_name = request.tool_name
|
|
146
|
-
|
|
147
|
-
#
|
|
148
|
-
if
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
219
|
+
|
|
220
|
+
# Explicit, clearly-labelled "always allow all uses of this tool" only.
|
|
221
|
+
if scope == "tool":
|
|
222
|
+
return f"{tool_name}:*"
|
|
223
|
+
|
|
224
|
+
# Shell tools: derive a reusable command-prefix scope via the shared
|
|
225
|
+
# core helper so declarative (YAML/--allow) and interactive rules scope
|
|
226
|
+
# identically. Unknown/compound commands stay literal (fail-closed).
|
|
227
|
+
if tool_name in ("bash", "shell") and "command" in request.arguments:
|
|
228
|
+
command = request.arguments["command"]
|
|
229
|
+
if isinstance(command, str) and command.strip():
|
|
230
|
+
from praisonaiagents.permissions import derive_pattern
|
|
231
|
+
|
|
232
|
+
return derive_pattern(f"{tool_name}:{command}")
|
|
233
|
+
# Missing/blank/non-string command: fall back to a literal,
|
|
234
|
+
# single-use target rather than the blanket ``tool:*`` grant.
|
|
235
|
+
return f"{tool_name}:{command}"
|
|
236
|
+
|
|
237
|
+
# Non-shell tools: scope to the first argument value when it is a short
|
|
238
|
+
# string, otherwise fall back to a literal single-use target. This never
|
|
239
|
+
# over-grants beyond the specific invocation the user approved (and, on
|
|
240
|
+
# the deny path, never over-denies the entire tool).
|
|
241
|
+
if request.arguments:
|
|
242
|
+
first_arg = next(iter(request.arguments.values()), "")
|
|
243
|
+
if isinstance(first_arg, str) and first_arg and len(first_arg) < 100:
|
|
244
|
+
return f"{tool_name}:{first_arg}"
|
|
245
|
+
# Non-string / empty / oversized first argument: keep it literal so
|
|
246
|
+
# the rule matches only this exact value, not every use of the tool.
|
|
247
|
+
return f"{tool_name}:{first_arg}"
|
|
248
|
+
|
|
249
|
+
# No arguments at all: match only the bare (argument-less) invocation,
|
|
250
|
+
# never the wildcard. ``scope="tool"`` above remains the sole path to
|
|
251
|
+
# ``tool_name:*``.
|
|
252
|
+
return f"{tool_name}:"
|
|
163
253
|
|
|
164
254
|
def _decision_from_mode(self, request: ApprovalRequest) -> Optional[ApprovalDecision]:
|
|
165
255
|
"""
|
|
@@ -237,13 +327,13 @@ class InteractiveCLIApprovalBackend:
|
|
|
237
327
|
|
|
238
328
|
# Need to ask - run prompt in thread to avoid blocking
|
|
239
329
|
loop = asyncio.get_running_loop()
|
|
240
|
-
approved, persist = await loop.run_in_executor(
|
|
330
|
+
approved, persist, scope, deny_reason = await loop.run_in_executor(
|
|
241
331
|
None, self._prompt_user, request
|
|
242
332
|
)
|
|
243
333
|
|
|
244
334
|
# If user wants to persist the decision
|
|
245
335
|
if persist:
|
|
246
|
-
pattern = self._create_pattern(request)
|
|
336
|
+
pattern = self._create_pattern(request, scope=scope)
|
|
247
337
|
action = PermissionAction.ALLOW if approved else PermissionAction.DENY
|
|
248
338
|
|
|
249
339
|
# Create and add the rule
|
|
@@ -255,12 +345,22 @@ class InteractiveCLIApprovalBackend:
|
|
|
255
345
|
priority=100, # User rules have high priority
|
|
256
346
|
)
|
|
257
347
|
self.permission_manager.add_rule(rule)
|
|
258
|
-
|
|
348
|
+
|
|
349
|
+
# Surface any denial feedback so the agent can steer instead of just
|
|
350
|
+
# aborting. A denied approval with a reason becomes a correction.
|
|
351
|
+
metadata: Dict[str, Any] = {"persistent": persist}
|
|
352
|
+
if not approved and deny_reason:
|
|
353
|
+
metadata["feedback"] = deny_reason
|
|
354
|
+
|
|
355
|
+
reason_text = "User decision" + (" (persisted)" if persist else "")
|
|
356
|
+
if not approved and deny_reason:
|
|
357
|
+
reason_text = f"User denied: {deny_reason}"
|
|
358
|
+
|
|
259
359
|
return ApprovalDecision(
|
|
260
360
|
approved=approved,
|
|
261
|
-
reason=
|
|
361
|
+
reason=reason_text,
|
|
262
362
|
approver="user",
|
|
263
|
-
metadata=
|
|
363
|
+
metadata=metadata,
|
|
264
364
|
)
|
|
265
365
|
|
|
266
366
|
def set_permission_mode(self, mode: PermissionMode):
|
|
@@ -1195,6 +1195,10 @@ def _run_prompt(
|
|
|
1195
1195
|
)
|
|
1196
1196
|
|
|
1197
1197
|
# Add session support to Agent if needed
|
|
1198
|
+
# NOTE: build_cli_memory_config / apply_cli_session_continuity are
|
|
1199
|
+
# imported above from ..state.project_sessions. Do NOT re-import them
|
|
1200
|
+
# from ..utils.project here — that stale version lacks the auto_save
|
|
1201
|
+
# kwarg and would shadow the correct implementation.
|
|
1198
1202
|
memory_cfg = build_cli_memory_config(session_id=session_id, auto_save=auto_save_name)
|
|
1199
1203
|
if memory_cfg is not None:
|
|
1200
1204
|
agent_config["memory"] = memory_cfg
|
{praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/configuration/credentials.py
RENAMED
|
@@ -56,42 +56,69 @@ class ProviderCredential:
|
|
|
56
56
|
class CredentialStore:
|
|
57
57
|
"""
|
|
58
58
|
Secure credential storage with atomic writes and proper permissions.
|
|
59
|
-
|
|
60
|
-
Stores credentials in ~/.
|
|
61
|
-
for security. All write operations are atomic to prevent
|
|
59
|
+
|
|
60
|
+
Stores credentials in ~/.praisonai/credentials.json with 0o600
|
|
61
|
+
permissions for security. All write operations are atomic to prevent
|
|
62
|
+
corruption.
|
|
63
|
+
|
|
64
|
+
The legacy ~/.praison/credentials.json location is kept as a read-only
|
|
65
|
+
backward-compatibility fallback: if the canonical file does not yet exist
|
|
66
|
+
but the legacy one does, the legacy file is read so existing users keep
|
|
67
|
+
working during the deprecation window. Writes always target the canonical
|
|
68
|
+
location so credentials converge on a single source of truth.
|
|
62
69
|
"""
|
|
63
|
-
|
|
70
|
+
|
|
64
71
|
def __init__(self, credentials_path: Optional[Path] = None):
|
|
65
72
|
"""
|
|
66
73
|
Initialize credential store.
|
|
67
|
-
|
|
74
|
+
|
|
68
75
|
Args:
|
|
69
76
|
credentials_path: Optional custom path for credentials file.
|
|
70
|
-
Defaults to ~/.
|
|
77
|
+
Defaults to ~/.praisonai/credentials.json
|
|
71
78
|
"""
|
|
72
79
|
if credentials_path:
|
|
73
80
|
self.credentials_path = credentials_path
|
|
81
|
+
self.legacy_credentials_path: Optional[Path] = None
|
|
74
82
|
else:
|
|
75
83
|
home = Path.home()
|
|
76
|
-
self.credentials_path = home / ".
|
|
84
|
+
self.credentials_path = home / ".praisonai" / "credentials.json"
|
|
85
|
+
self.legacy_credentials_path = home / ".praison" / "credentials.json"
|
|
86
|
+
|
|
87
|
+
def _effective_read_path(self) -> Path:
|
|
88
|
+
"""Return the path to read credentials from.
|
|
89
|
+
|
|
90
|
+
Prefers the canonical location; only falls back to the legacy
|
|
91
|
+
~/.praison/credentials.json when the canonical file is absent.
|
|
92
|
+
"""
|
|
93
|
+
if self.credentials_path.exists():
|
|
94
|
+
return self.credentials_path
|
|
95
|
+
legacy = self.legacy_credentials_path
|
|
96
|
+
if legacy is not None and legacy.exists():
|
|
97
|
+
return legacy
|
|
98
|
+
return self.credentials_path
|
|
77
99
|
|
|
78
100
|
def _ensure_directory_exists(self) -> None:
|
|
79
101
|
"""Ensure parent directory exists, creating it if necessary."""
|
|
80
102
|
self.credentials_path.parent.mkdir(parents=True, exist_ok=True)
|
|
81
103
|
|
|
82
104
|
def _read_credentials(self) -> Dict[str, Dict[str, Any]]:
|
|
83
|
-
"""Read and parse credentials file.
|
|
105
|
+
"""Read and parse credentials file.
|
|
106
|
+
|
|
107
|
+
Reads from the canonical path when present, otherwise transparently
|
|
108
|
+
falls back to the legacy ~/.praison/credentials.json location.
|
|
109
|
+
"""
|
|
84
110
|
try:
|
|
85
|
-
|
|
111
|
+
read_path = self._effective_read_path()
|
|
112
|
+
if not read_path.exists():
|
|
86
113
|
return {}
|
|
87
114
|
|
|
88
115
|
# Check file permissions for security
|
|
89
|
-
file_stat =
|
|
116
|
+
file_stat = read_path.stat()
|
|
90
117
|
if file_stat.st_mode & 0o077: # Check if group/other have any permissions
|
|
91
118
|
# Fix permissions automatically
|
|
92
|
-
os.chmod(
|
|
119
|
+
os.chmod(read_path, 0o600)
|
|
93
120
|
|
|
94
|
-
with open(
|
|
121
|
+
with open(read_path, 'r') as f:
|
|
95
122
|
return json.load(f)
|
|
96
123
|
except (json.JSONDecodeError, FileNotFoundError, PermissionError):
|
|
97
124
|
# Return empty dict on any read error
|
{praisonai_code-0.0.30 → praisonai_code-0.0.32}/praisonai_code/cli/features/setup/handler.py
RENAMED
|
@@ -128,6 +128,7 @@ class SetupHandler(CommandHandler):
|
|
|
128
128
|
|
|
129
129
|
self._save_env(praison_home, env_vars, output)
|
|
130
130
|
self._save_config(praison_home, config, output)
|
|
131
|
+
self._save_credentials(praison_home, provider, env_key, api_key, model, output)
|
|
131
132
|
|
|
132
133
|
output.print_success("Setup complete")
|
|
133
134
|
output.console.print(f"Configuration saved to {praison_home}")
|
|
@@ -243,6 +244,14 @@ class SetupHandler(CommandHandler):
|
|
|
243
244
|
|
|
244
245
|
self._save_env(praison_home, env_vars, output)
|
|
245
246
|
self._save_config(praison_home, config, output)
|
|
247
|
+
self._save_credentials(
|
|
248
|
+
praison_home,
|
|
249
|
+
provider_id,
|
|
250
|
+
env_key,
|
|
251
|
+
env_vars.get(env_key) if env_key else None,
|
|
252
|
+
model,
|
|
253
|
+
output,
|
|
254
|
+
)
|
|
246
255
|
|
|
247
256
|
if create_starter:
|
|
248
257
|
self._create_starter_yaml(output, model)
|
|
@@ -493,6 +502,58 @@ class SetupHandler(CommandHandler):
|
|
|
493
502
|
config_file.chmod(0o600)
|
|
494
503
|
output.print_success(f"Configuration saved to {config_file}")
|
|
495
504
|
|
|
505
|
+
def _save_credentials(
|
|
506
|
+
self,
|
|
507
|
+
praison_home: Path,
|
|
508
|
+
provider: Optional[str],
|
|
509
|
+
env_key: Optional[str],
|
|
510
|
+
api_key: Optional[str],
|
|
511
|
+
model: Optional[str],
|
|
512
|
+
output,
|
|
513
|
+
) -> None:
|
|
514
|
+
"""Mirror the API key into the unified CredentialStore.
|
|
515
|
+
|
|
516
|
+
Historically ``setup`` only wrote keys to ``~/.praisonai/.env`` while
|
|
517
|
+
``auth`` / ``inject_credentials_into_env`` read from a separate
|
|
518
|
+
``CredentialStore``. Writing here too gives both code paths a single
|
|
519
|
+
source of truth so a key set via ``setup`` is picked up everywhere.
|
|
520
|
+
|
|
521
|
+
To stay a single source of truth, this writes to the *same* store that
|
|
522
|
+
``auth`` / ``inject_credentials_into_env`` read from. When
|
|
523
|
+
``PRAISONAI_HOME`` is not overridden we use the default
|
|
524
|
+
``CredentialStore()`` so its legacy ``~/.praison/credentials.json``
|
|
525
|
+
fallback is honoured and any pre-existing ``auth`` credentials are
|
|
526
|
+
transparently migrated onto the canonical file on this write (no data
|
|
527
|
+
loss). Only when ``PRAISONAI_HOME`` points somewhere other than the
|
|
528
|
+
default home do we anchor the store under that directory.
|
|
529
|
+
"""
|
|
530
|
+
# Only providers with a real API key can be stored; local providers
|
|
531
|
+
# (e.g. ollama) and empty keys are skipped silently.
|
|
532
|
+
if not provider or not env_key or not api_key:
|
|
533
|
+
return
|
|
534
|
+
|
|
535
|
+
try:
|
|
536
|
+
from ...configuration.credentials import CredentialStore
|
|
537
|
+
|
|
538
|
+
# Prefer the default store (canonical path + legacy fallback and
|
|
539
|
+
# migration) so setup and the auth/inject read paths converge on a
|
|
540
|
+
# single file. Fall back to an explicit path only when a custom
|
|
541
|
+
# PRAISONAI_HOME is in effect.
|
|
542
|
+
default_home = Path.home() / ".praisonai"
|
|
543
|
+
if praison_home.resolve() == default_home.resolve():
|
|
544
|
+
store = CredentialStore()
|
|
545
|
+
else:
|
|
546
|
+
store = CredentialStore(praison_home / "credentials.json")
|
|
547
|
+
store.store_credential(
|
|
548
|
+
provider=provider,
|
|
549
|
+
api_key=api_key,
|
|
550
|
+
model=model,
|
|
551
|
+
)
|
|
552
|
+
except Exception as e:
|
|
553
|
+
# Never fail setup because the credential mirror failed; the .env
|
|
554
|
+
# file has already been written as the primary artifact.
|
|
555
|
+
output.print_warning(f"Could not save to credential store: {e}")
|
|
556
|
+
|
|
496
557
|
def _create_starter_yaml(self, output, model: str) -> None:
|
|
497
558
|
"""Create a starter agents.yaml file in the current directory."""
|
|
498
559
|
agents_file = Path.cwd() / "agents.yaml"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: praisonai-code
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.32
|
|
4
4
|
Summary: Agentic terminal CLI for PraisonAI — the terminal-native agent (run, chat, code, runtime, cli backends) extracted from the praisonai wrapper.
|
|
5
5
|
Author: Mervin Praison
|
|
6
6
|
License: MIT
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "praisonai-code"
|
|
3
|
-
version = "0.0.
|
|
3
|
+
version = "0.0.32"
|
|
4
4
|
description = "Agentic terminal CLI for PraisonAI — the terminal-native agent (run, chat, code, runtime, cli backends) extracted from the praisonai wrapper."
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
license = {text = "MIT"}
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|