ayder-cli 2.1.2__tar.gz → 2.1.5__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.
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/PKG-INFO +6 -3
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/README.md +3 -2
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/docs/config.toml.example +6 -1
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/pyproject.toml +2 -1
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/src/ayder_cli/application/runtime_factory.py +8 -1
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/src/ayder_cli/cli.py +74 -16
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/src/ayder_cli/cli_runner.py +19 -4
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/src/ayder_cli/core/config.py +16 -1
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/src/ayder_cli/core/ollama_context_manager.py +2 -2
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/src/ayder_cli/themes/claude.py +27 -0
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/src/ayder_cli/themes/original.py +21 -0
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/src/ayder_cli/tools/definition.py +10 -4
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/src/ayder_cli/tools/plugin_manager.py +9 -4
- ayder_cli-2.1.5/src/ayder_cli/tools/plugin_status.py +33 -0
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/src/ayder_cli/tui/__init__.py +4 -1
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/src/ayder_cli/tui/app.py +94 -31
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/src/ayder_cli/tui/commands.py +38 -8
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/src/ayder_cli/tui/keybindings.py +3 -3
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/src/ayder_cli/tui/widgets.py +147 -14
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/tests/application/test_runtime_factory.py +62 -0
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/tests/core/test_config_coverage.py +13 -9
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/tests/core/test_config_v2.py +38 -0
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/tests/core/test_ollama_context_manager.py +15 -0
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/tests/test_cli.py +208 -26
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/tests/tools/test_plugin_manager.py +82 -0
- ayder_cli-2.1.5/tests/tools/test_plugin_status.py +36 -0
- ayder_cli-2.1.5/tests/tui/test_input_box.py +114 -0
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/tests/tui/test_multiline_input.py +37 -40
- ayder_cli-2.1.5/tests/tui/test_status_bar_badges.py +70 -0
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/tests/tui/test_widgets.py +77 -1
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/tests/ui/test_confirm_screen.py +2 -0
- ayder_cli-2.1.5/tests/ui/test_plugin_autoenable.py +44 -0
- ayder_cli-2.1.5/tests/ui/test_tui_commands_plugin.py +72 -0
- ayder_cli-2.1.2/CHANGELOG.md +0 -14
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/.github/workflows/ci.yml +0 -0
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/.github/workflows/python-package.yml +0 -0
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/.gitignore +0 -0
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/.python-version +0 -0
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/AGENTS.md +0 -0
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/LICENSE +0 -0
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/docs/PROJECT_STRUCTURE.md +0 -0
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/docs/README_AGENT_WORKFLOW.md +0 -0
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/docs/README_OLLAMA.md +0 -0
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/docs/cc.png +0 -0
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/src/ayder_cli/__init__.py +0 -0
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/src/ayder_cli/__main__.py +0 -0
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/src/ayder_cli/agents/__init__.py +0 -0
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/src/ayder_cli/agents/callbacks.py +0 -0
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/src/ayder_cli/agents/config.py +0 -0
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/src/ayder_cli/agents/registry.py +0 -0
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/src/ayder_cli/agents/run.py +0 -0
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/src/ayder_cli/agents/runner.py +0 -0
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/src/ayder_cli/agents/tool.py +0 -0
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/src/ayder_cli/application/README.md +0 -0
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/src/ayder_cli/application/__init__.py +0 -0
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/src/ayder_cli/application/execution_policy.py +0 -0
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/src/ayder_cli/application/message_contract.py +0 -0
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/src/ayder_cli/application/validation.py +0 -0
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/src/ayder_cli/cli_callbacks.py +0 -0
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/src/ayder_cli/console.py +0 -0
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/src/ayder_cli/core/cache_monitor.py +0 -0
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/src/ayder_cli/core/config_migration.py +0 -0
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/src/ayder_cli/core/context.py +0 -0
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/src/ayder_cli/core/context_manager.py +0 -0
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/src/ayder_cli/core/context_manager_factory.py +0 -0
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/src/ayder_cli/core/default_context_manager.py +0 -0
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/src/ayder_cli/core/result.py +0 -0
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/src/ayder_cli/logging_config.py +0 -0
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/src/ayder_cli/loops/__init__.py +0 -0
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/src/ayder_cli/loops/chat_loop.py +0 -0
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/src/ayder_cli/parser.py +0 -0
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/src/ayder_cli/process_manager.py +0 -0
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/src/ayder_cli/prompts.py +0 -0
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/src/ayder_cli/providers/__init__.py +0 -0
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/src/ayder_cli/providers/base.py +0 -0
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/src/ayder_cli/providers/impl/claude.py +0 -0
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/src/ayder_cli/providers/impl/deepseek.py +0 -0
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/src/ayder_cli/providers/impl/gemini.py +0 -0
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/src/ayder_cli/providers/impl/glm.py +0 -0
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/src/ayder_cli/providers/impl/ollama.py +0 -0
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/src/ayder_cli/providers/impl/ollama_drivers/__init__.py +0 -0
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/src/ayder_cli/providers/impl/ollama_drivers/_errors.py +0 -0
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/src/ayder_cli/providers/impl/ollama_drivers/base.py +0 -0
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/src/ayder_cli/providers/impl/ollama_drivers/deepseek.py +0 -0
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/src/ayder_cli/providers/impl/ollama_drivers/generic_native.py +0 -0
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/src/ayder_cli/providers/impl/ollama_drivers/generic_xml.py +0 -0
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/src/ayder_cli/providers/impl/ollama_drivers/matrix.py +0 -0
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/src/ayder_cli/providers/impl/ollama_drivers/minimax.py +0 -0
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/src/ayder_cli/providers/impl/ollama_drivers/qwen3.py +0 -0
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/src/ayder_cli/providers/impl/ollama_drivers/registry.py +0 -0
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/src/ayder_cli/providers/impl/ollama_inspector.py +0 -0
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/src/ayder_cli/providers/impl/openai.py +0 -0
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/src/ayder_cli/providers/impl/qwen.py +0 -0
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/src/ayder_cli/providers/orchestrator.py +0 -0
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/src/ayder_cli/providers/retry.py +0 -0
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/src/ayder_cli/services/__init__.py +0 -0
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/src/ayder_cli/services/interactions.py +0 -0
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/src/ayder_cli/themes/__init__.py +0 -0
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/src/ayder_cli/tools/__init__.py +0 -0
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/src/ayder_cli/tools/builtins/__init__.py +0 -0
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/src/ayder_cli/tools/builtins/context.py +0 -0
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/src/ayder_cli/tools/builtins/context_definitions.py +0 -0
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/src/ayder_cli/tools/builtins/filesystem.py +0 -0
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/src/ayder_cli/tools/builtins/filesystem_definitions.py +0 -0
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/src/ayder_cli/tools/builtins/notes.py +0 -0
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/src/ayder_cli/tools/builtins/notes_definitions.py +0 -0
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/src/ayder_cli/tools/builtins/process_manager_definitions.py +0 -0
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/src/ayder_cli/tools/builtins/search.py +0 -0
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/src/ayder_cli/tools/builtins/search_definitions.py +0 -0
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/src/ayder_cli/tools/builtins/shell.py +0 -0
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/src/ayder_cli/tools/builtins/shell_definitions.py +0 -0
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/src/ayder_cli/tools/builtins/tasks.py +0 -0
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/src/ayder_cli/tools/builtins/tasks_definitions.py +0 -0
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/src/ayder_cli/tools/builtins/utils_tools.py +0 -0
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/src/ayder_cli/tools/builtins/utils_tools_definitions.py +0 -0
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/src/ayder_cli/tools/builtins/web.py +0 -0
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/src/ayder_cli/tools/builtins/web_definitions.py +0 -0
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/src/ayder_cli/tools/execution.py +0 -0
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/src/ayder_cli/tools/hooks.py +0 -0
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/src/ayder_cli/tools/normalization.py +0 -0
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/src/ayder_cli/tools/plugin_api.py +0 -0
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/src/ayder_cli/tools/plugin_github.py +0 -0
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/src/ayder_cli/tools/registry.py +0 -0
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/src/ayder_cli/tools/schemas.py +0 -0
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/src/ayder_cli/tools/utils.py +0 -0
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/src/ayder_cli/tui/adapter.py +0 -0
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/src/ayder_cli/tui/helpers.py +0 -0
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/src/ayder_cli/tui/parser.py +0 -0
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/src/ayder_cli/tui/screens.py +0 -0
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/src/ayder_cli/tui/theme_manager.py +0 -0
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/src/ayder_cli/tui/types.py +0 -0
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/src/ayder_cli/ui.py +0 -0
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/src/ayder_cli/version.py +0 -0
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/tests/COVERAGE.md +0 -0
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/tests/__init__.py +0 -0
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/tests/agents/__init__.py +0 -0
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/tests/agents/test_agent_tools.py +0 -0
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/tests/agents/test_callbacks.py +0 -0
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/tests/agents/test_config.py +0 -0
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/tests/agents/test_integration.py +0 -0
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/tests/agents/test_registry.py +0 -0
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/tests/agents/test_run.py +0 -0
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/tests/agents/test_runner.py +0 -0
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/tests/agents/test_runner_provider_unavailable.py +0 -0
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/tests/agents/test_tool.py +0 -0
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/tests/application/test_message_contract.py +0 -0
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/tests/client/test_main.py +0 -0
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/tests/convergence/__init__.py +0 -0
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/tests/convergence/test_execution_policy_parity.py +0 -0
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/tests/convergence/test_runtime_wiring.py +0 -0
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/tests/convergence/test_validation_path.py +0 -0
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/tests/core/test_cache_monitor.py +0 -0
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/tests/core/test_config.py +0 -0
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/tests/core/test_config_migration.py +0 -0
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/tests/core/test_config_provider_logging.py +0 -0
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/tests/core/test_config_retry.py +0 -0
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/tests/core/test_context_manager_factory.py +0 -0
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/tests/core/test_default_context_manager.py +0 -0
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/tests/core/test_default_context_manager_should_compact.py +0 -0
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/tests/core/test_ollama_context_manager_cache_monitor.py +0 -0
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/tests/core/test_ollama_context_manager_max_history.py +0 -0
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/tests/core/test_parameter_aliasing.py +0 -0
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/tests/core/test_parser.py +0 -0
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/tests/loops/__init__.py +0 -0
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/tests/loops/test_base.py +0 -0
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/tests/loops/test_chat_loop_hook.py +0 -0
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/tests/loops/test_chat_loop_tool_truncation.py +0 -0
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/tests/providers/__init__.py +0 -0
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/tests/providers/ollama_drivers/__init__.py +0 -0
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/tests/providers/ollama_drivers/test_base.py +0 -0
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/tests/providers/ollama_drivers/test_deepseek.py +0 -0
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/tests/providers/ollama_drivers/test_errors.py +0 -0
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/tests/providers/ollama_drivers/test_fallback.py +0 -0
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/tests/providers/ollama_drivers/test_generic_native.py +0 -0
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/tests/providers/ollama_drivers/test_generic_xml.py +0 -0
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/tests/providers/ollama_drivers/test_matrix.py +0 -0
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/tests/providers/ollama_drivers/test_minimax.py +0 -0
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/tests/providers/ollama_drivers/test_provider_integration.py +0 -0
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/tests/providers/ollama_drivers/test_qwen3.py +0 -0
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/tests/providers/ollama_drivers/test_registry.py +0 -0
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/tests/providers/test_glm_async.py +0 -0
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/tests/providers/test_ollama_inspector.py +0 -0
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/tests/providers/test_ollama_native.py +0 -0
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/tests/providers/test_ollama_xml.py +0 -0
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/tests/providers/test_ollama_xml_autoroute.py +0 -0
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/tests/providers/test_ollama_xml_usage.py +0 -0
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/tests/providers/test_orchestrator_capabilities.py +0 -0
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/tests/providers/test_qwen_async.py +0 -0
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/tests/providers/test_retry_classifier.py +0 -0
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/tests/providers/test_retry_integration.py +0 -0
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/tests/providers/test_retrying_provider.py +0 -0
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/tests/services/test_boundary.py +0 -0
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/tests/services/test_interaction_sink.py +0 -0
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/tests/test_cli_callbacks.py +0 -0
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/tests/test_context.py +0 -0
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/tests/test_env_manager.py +0 -0
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/tests/test_logging_config.py +0 -0
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/tests/test_notes.py +0 -0
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/tests/test_process_manager.py +0 -0
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/tests/test_tasks.py +0 -0
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/tests/tools/__init__.py +0 -0
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/tests/tools/test_agent_notes.py +0 -0
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/tests/tools/test_definition_discovery.py +0 -0
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/tests/tools/test_di_injection.py +0 -0
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/tests/tools/test_impl.py +0 -0
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/tests/tools/test_impl_coverage.py +0 -0
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/tests/tools/test_path_security.py +0 -0
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/tests/tools/test_plugin_api.py +0 -0
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/tests/tools/test_plugin_github.py +0 -0
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/tests/tools/test_plugin_loading.py +0 -0
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/tests/tools/test_registry.py +0 -0
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/tests/tools/test_registry_coverage.py +0 -0
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/tests/tools/test_result.py +0 -0
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/tests/tools/test_schemas.py +0 -0
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/tests/tools/test_search_codebase.py +0 -0
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/tests/tools/test_utils.py +0 -0
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/tests/tools/test_web.py +0 -0
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/tests/tui/__init__.py +0 -0
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/tests/tui/test_agent_list_screen.py +0 -0
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/tests/tui/test_do_clear_coordination.py +0 -0
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/tests/tui/test_follow_mode.py +0 -0
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/tests/tui/test_help_screen.py +0 -0
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/tests/tui/test_keybindings.py +0 -0
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/tests/tui/test_multi_select_screen.py +0 -0
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/tests/tui/test_paste.py +0 -0
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/tests/tui/test_pending_compact_consumer.py +0 -0
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/tests/tui/test_pull_delivery.py +0 -0
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/tests/tui/test_turn_consumer.py +0 -0
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/tests/ui/test_diff_preview.py +0 -0
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/tests/ui/test_provider_switch.py +0 -0
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/tests/ui/test_run_tui_startup.py +0 -0
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/tests/ui/test_tui_assistant_sanitization.py +0 -0
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/tests/ui/test_tui_chat_loop.py +0 -0
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/tests/ui/test_tui_commands_agent.py +0 -0
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/tests/ui/test_tui_commands_logging.py +0 -0
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/tests/ui/test_tui_commands_provider.py +0 -0
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/tests/ui/test_tui_helpers.py +0 -0
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/tests/ui/test_tui_temporal_command.py +0 -0
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/tests/ui/test_tui_widgets.py +0 -0
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/tests/ui/test_ui.py +0 -0
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/tests/ui/test_ui_coverage.py +0 -0
- {ayder_cli-2.1.2 → ayder_cli-2.1.5}/tests/ui/test_ui_verbose.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: ayder-cli
|
|
3
|
-
Version: 2.1.
|
|
3
|
+
Version: 2.1.5
|
|
4
4
|
Summary: AI agent for any LLMs
|
|
5
5
|
Project-URL: Homepage, https://github.com/ayder/ayder-cli
|
|
6
6
|
Project-URL: Repository, https://github.com/ayder/ayder-cli.git
|
|
@@ -34,6 +34,8 @@ Provides-Extra: glm
|
|
|
34
34
|
Requires-Dist: zhipuai; extra == 'glm'
|
|
35
35
|
Provides-Extra: google
|
|
36
36
|
Requires-Dist: google-genai; extra == 'google'
|
|
37
|
+
Provides-Extra: mcp
|
|
38
|
+
Requires-Dist: mcp; extra == 'mcp'
|
|
37
39
|
Provides-Extra: qwen
|
|
38
40
|
Requires-Dist: dashscope; extra == 'qwen'
|
|
39
41
|
Description-Content-Type: text/markdown
|
|
@@ -286,8 +288,9 @@ ayder -f instructions.txt
|
|
|
286
288
|
# Explicit stdin mode
|
|
287
289
|
ayder --stdin < prompt.txt
|
|
288
290
|
|
|
289
|
-
#
|
|
290
|
-
|
|
291
|
+
# Override the main LLM system prompt with a file
|
|
292
|
+
# (tool instructions + project structure are still appended)
|
|
293
|
+
ayder --system-prompt prompt-file.md "refactor this code"
|
|
291
294
|
```
|
|
292
295
|
|
|
293
296
|
### Task Commands (CLI Mode)
|
|
@@ -246,8 +246,9 @@ ayder -f instructions.txt
|
|
|
246
246
|
# Explicit stdin mode
|
|
247
247
|
ayder --stdin < prompt.txt
|
|
248
248
|
|
|
249
|
-
#
|
|
250
|
-
|
|
249
|
+
# Override the main LLM system prompt with a file
|
|
250
|
+
# (tool instructions + project structure are still appended)
|
|
251
|
+
ayder --system-prompt prompt-file.md "refactor this code"
|
|
251
252
|
```
|
|
252
253
|
|
|
253
254
|
### Task Commands (CLI Mode)
|
|
@@ -82,7 +82,12 @@ verbose = false
|
|
|
82
82
|
prompt = "STANDARD" # MINIMAL | STANDARD | EXTENDED
|
|
83
83
|
max_background_processes = 5 # cap on concurrent background processes (e.g. test runs)
|
|
84
84
|
max_output_tokens = 8192 # orchestrator response cap
|
|
85
|
-
|
|
85
|
+
# Max conversation messages kept per turn. 0 = unlimited (default): the context
|
|
86
|
+
# manager's token budget + compaction are the bound, so the model uses its real
|
|
87
|
+
# window. A small fixed cap (the old default was 30) thrashes a tiny history
|
|
88
|
+
# window on a large-context model and wastes most of it. Set a finite number
|
|
89
|
+
# only if you want a hard message cap regardless of window size.
|
|
90
|
+
max_history_messages = 0
|
|
86
91
|
agent_timeout = 1800 # seconds before a background agent is cancelled (30 min; reasoning+coding can be slow)
|
|
87
92
|
# Tools the agents inherit. A coding harness needs file/shell/search (core),
|
|
88
93
|
# tasks/notes (metadata), background process control for test suites
|
|
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "ayder-cli"
|
|
7
|
-
version = "2.1.
|
|
7
|
+
version = "2.1.5"
|
|
8
8
|
description = "AI agent for any LLMs"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.12"
|
|
@@ -37,6 +37,7 @@ google = ["google-genai"]
|
|
|
37
37
|
qwen = ["dashscope"]
|
|
38
38
|
glm = ["zhipuai"]
|
|
39
39
|
all = ["ayder-cli[anthropic,google,qwen,glm]"]
|
|
40
|
+
mcp = ["mcp"]
|
|
40
41
|
|
|
41
42
|
[project.urls]
|
|
42
43
|
Homepage = "https://github.com/ayder/ayder-cli"
|
|
@@ -44,6 +44,7 @@ def create_runtime(
|
|
|
44
44
|
project_root: str = ".",
|
|
45
45
|
model_name: str | None = None,
|
|
46
46
|
prompt_tier: str | None = None,
|
|
47
|
+
system_prompt_override: str | None = None,
|
|
47
48
|
) -> RuntimeComponents:
|
|
48
49
|
"""Assemble and return all shared runtime components.
|
|
49
50
|
|
|
@@ -53,6 +54,9 @@ def create_runtime(
|
|
|
53
54
|
model_name: Override model name from config when provided.
|
|
54
55
|
prompt_tier: Override the system-prompt tier from config when provided
|
|
55
56
|
(e.g. "AGENTIC" for `ayder-cli --agent`). See prompts.get_system_prompt.
|
|
57
|
+
system_prompt_override: When set, use this text as the system-prompt base
|
|
58
|
+
instead of prompts.get_system_prompt (ayder --system-prompt FILE). Tool
|
|
59
|
+
prompts and the project-structure macro are still appended.
|
|
56
60
|
|
|
57
61
|
Returns:
|
|
58
62
|
RuntimeComponents with all dependencies wired.
|
|
@@ -84,7 +88,10 @@ def create_runtime(
|
|
|
84
88
|
macro = ""
|
|
85
89
|
|
|
86
90
|
# Format the final prompt (protocol injection now handled dynamically by chat_loop and protocols)
|
|
87
|
-
|
|
91
|
+
if system_prompt_override is not None:
|
|
92
|
+
base_prompt = system_prompt_override
|
|
93
|
+
else:
|
|
94
|
+
base_prompt = get_system_prompt(cfg.prompt)
|
|
88
95
|
tool_tags = frozenset(cfg.tool_tags) if cfg.tool_tags else None
|
|
89
96
|
tool_prompts = tool_registry.get_system_prompts(tags=tool_tags)
|
|
90
97
|
system_prompt = base_prompt + tool_prompts + macro
|
|
@@ -56,11 +56,28 @@ def _add_common_args(parser: argparse.ArgumentParser) -> None:
|
|
|
56
56
|
"--stdin", action="store_true", help="Read prompt from stdin"
|
|
57
57
|
)
|
|
58
58
|
parser.add_argument(
|
|
59
|
-
"--prompt",
|
|
59
|
+
"--temporal-prompt",
|
|
60
60
|
type=str,
|
|
61
61
|
default=None,
|
|
62
62
|
metavar="FILE",
|
|
63
|
-
help="
|
|
63
|
+
help="Prompt file for the Temporal worker (only used with --temporal-task-queue)",
|
|
64
|
+
)
|
|
65
|
+
parser.add_argument(
|
|
66
|
+
"--system-prompt",
|
|
67
|
+
type=str,
|
|
68
|
+
default=None,
|
|
69
|
+
metavar="FILE",
|
|
70
|
+
help="Use FILE's contents as the main LLM system prompt, overriding the "
|
|
71
|
+
"built-in prompt from prompts.py (tool instructions and project structure "
|
|
72
|
+
"are still appended)",
|
|
73
|
+
)
|
|
74
|
+
parser.add_argument(
|
|
75
|
+
"-c",
|
|
76
|
+
"--config",
|
|
77
|
+
type=str,
|
|
78
|
+
default=None,
|
|
79
|
+
metavar="FILE",
|
|
80
|
+
help="Path to a config.toml to use instead of ~/.ayder/config.toml",
|
|
64
81
|
)
|
|
65
82
|
|
|
66
83
|
# Permission flags: r=read, w=write, x=execute, http=web/network
|
|
@@ -93,13 +110,10 @@ def _add_common_args(parser: argparse.ArgumentParser) -> None:
|
|
|
93
110
|
|
|
94
111
|
parser.add_argument(
|
|
95
112
|
"--verbose",
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
choices=LOG_LEVELS,
|
|
101
|
-
metavar="LEVEL",
|
|
102
|
-
help="Enable verbose console output and logging; default level is INFO",
|
|
113
|
+
action="store_true",
|
|
114
|
+
help="Show logs on the console. The level comes from --logging-level (or "
|
|
115
|
+
"config); if neither is set, defaults to INFO. Does not otherwise change "
|
|
116
|
+
"the log level.",
|
|
103
117
|
)
|
|
104
118
|
parser.add_argument(
|
|
105
119
|
"--logging-level",
|
|
@@ -214,6 +228,16 @@ def main():
|
|
|
214
228
|
args = parser.parse_args()
|
|
215
229
|
args.subcommand = None
|
|
216
230
|
|
|
231
|
+
# Apply the -c/--config override before anything reads the config file.
|
|
232
|
+
if getattr(args, "config", None):
|
|
233
|
+
from ayder_cli.core.config import set_config_path
|
|
234
|
+
|
|
235
|
+
config_file = Path(args.config).expanduser()
|
|
236
|
+
if not config_file.is_file():
|
|
237
|
+
print(f"Error: Config file not found: {args.config}", file=sys.stderr)
|
|
238
|
+
sys.exit(1)
|
|
239
|
+
set_config_path(config_file)
|
|
240
|
+
|
|
217
241
|
# Handle plugin subcommands
|
|
218
242
|
if args.subcommand == "install-plugin":
|
|
219
243
|
from ayder_cli.tools.plugin_manager import (
|
|
@@ -310,13 +334,17 @@ def main():
|
|
|
310
334
|
|
|
311
335
|
cfg = load_config(notify_migration=True, output=print)
|
|
312
336
|
|
|
313
|
-
#
|
|
314
|
-
|
|
315
|
-
|
|
337
|
+
# --verbose only enables console output; the level comes from --logging-level
|
|
338
|
+
# (or config.logging_level). When --verbose is used with no level configured
|
|
339
|
+
# anywhere, default the console to INFO so it isn't empty.
|
|
340
|
+
effective_log_level = args.logging_level
|
|
341
|
+
if args.verbose and effective_log_level is None and cfg.logging_level is None:
|
|
342
|
+
effective_log_level = "INFO"
|
|
343
|
+
|
|
316
344
|
setup_logging(
|
|
317
345
|
cfg,
|
|
318
346
|
level_override=effective_log_level,
|
|
319
|
-
console_stream=sys.stdout if args.verbose
|
|
347
|
+
console_stream=sys.stdout if args.verbose else None,
|
|
320
348
|
)
|
|
321
349
|
|
|
322
350
|
# --agent: warn early if the harness has nothing to orchestrate.
|
|
@@ -342,11 +370,30 @@ def main():
|
|
|
342
370
|
sys.exit(
|
|
343
371
|
_run_temporal_queue_cli(
|
|
344
372
|
queue_name=args.temporal_task_queue,
|
|
345
|
-
prompt_path=args.
|
|
373
|
+
prompt_path=args.temporal_prompt,
|
|
346
374
|
permissions=granted,
|
|
347
375
|
)
|
|
348
376
|
)
|
|
349
377
|
|
|
378
|
+
# Read the --system-prompt override file (overrides prompts.py base prompt).
|
|
379
|
+
system_prompt_override = None
|
|
380
|
+
if args.system_prompt:
|
|
381
|
+
sp_file = Path(args.system_prompt).expanduser()
|
|
382
|
+
try:
|
|
383
|
+
system_prompt_override = sp_file.read_text()
|
|
384
|
+
except FileNotFoundError:
|
|
385
|
+
print(
|
|
386
|
+
f"Error: System prompt file not found: {args.system_prompt}",
|
|
387
|
+
file=sys.stderr,
|
|
388
|
+
)
|
|
389
|
+
sys.exit(1)
|
|
390
|
+
except Exception as e:
|
|
391
|
+
print(
|
|
392
|
+
f"Error reading system prompt file {args.system_prompt}: {e}",
|
|
393
|
+
file=sys.stderr,
|
|
394
|
+
)
|
|
395
|
+
sys.exit(1)
|
|
396
|
+
|
|
350
397
|
# Handle file/stdin input
|
|
351
398
|
context = None
|
|
352
399
|
question = args.command
|
|
@@ -376,10 +423,21 @@ def main():
|
|
|
376
423
|
# Default: TUI mode
|
|
377
424
|
from ayder_cli.tui import run_tui
|
|
378
425
|
|
|
379
|
-
run_tui(
|
|
426
|
+
run_tui(
|
|
427
|
+
permissions=granted,
|
|
428
|
+
agent_mode=args.agent,
|
|
429
|
+
system_prompt_override=system_prompt_override,
|
|
430
|
+
)
|
|
380
431
|
return
|
|
381
432
|
|
|
382
|
-
sys.exit(
|
|
433
|
+
sys.exit(
|
|
434
|
+
run_command(
|
|
435
|
+
prompt,
|
|
436
|
+
permissions=granted,
|
|
437
|
+
agent_mode=args.agent,
|
|
438
|
+
system_prompt_override=system_prompt_override,
|
|
439
|
+
)
|
|
440
|
+
)
|
|
383
441
|
|
|
384
442
|
|
|
385
443
|
if __name__ == "__main__":
|
|
@@ -36,6 +36,7 @@ def _run_loop(
|
|
|
36
36
|
prompt: str,
|
|
37
37
|
permissions: set | None = None,
|
|
38
38
|
agent_mode: bool = False,
|
|
39
|
+
system_prompt_override: str | None = None,
|
|
39
40
|
) -> int:
|
|
40
41
|
"""Create a ChatLoop with CliCallbacks and run it.
|
|
41
42
|
|
|
@@ -47,11 +48,16 @@ def _run_loop(
|
|
|
47
48
|
permissions: Granted permission categories.
|
|
48
49
|
agent_mode: When True, inject the AGENTIC orchestrator system prompt
|
|
49
50
|
(ayder-cli --agent) so the main LLM drives the multi-agent harness.
|
|
51
|
+
system_prompt_override: When set, use this text as the system prompt base
|
|
52
|
+
instead of the built-in prompts.py prompt (ayder --system-prompt FILE).
|
|
50
53
|
|
|
51
54
|
Returns:
|
|
52
55
|
Exit code (0 for success, 1 for error).
|
|
53
56
|
"""
|
|
54
|
-
rt = create_runtime(
|
|
57
|
+
rt = create_runtime(
|
|
58
|
+
prompt_tier="AGENTIC" if agent_mode else None,
|
|
59
|
+
system_prompt_override=system_prompt_override,
|
|
60
|
+
)
|
|
55
61
|
|
|
56
62
|
messages: list[dict] = [
|
|
57
63
|
{"role": "system", "content": rt.system_prompt},
|
|
@@ -119,10 +125,12 @@ def _run_loop(
|
|
|
119
125
|
class CommandRunner:
|
|
120
126
|
"""Runner for single command execution mode."""
|
|
121
127
|
|
|
122
|
-
def __init__(self, prompt: str, permissions=None, agent_mode: bool = False
|
|
128
|
+
def __init__(self, prompt: str, permissions=None, agent_mode: bool = False,
|
|
129
|
+
system_prompt_override: str | None = None):
|
|
123
130
|
self.prompt = prompt
|
|
124
131
|
self.permissions = permissions
|
|
125
132
|
self.agent_mode = agent_mode
|
|
133
|
+
self.system_prompt_override = system_prompt_override
|
|
126
134
|
|
|
127
135
|
def run(self) -> int:
|
|
128
136
|
"""Execute the command and return exit code.
|
|
@@ -135,6 +143,7 @@ class CommandRunner:
|
|
|
135
143
|
self.prompt,
|
|
136
144
|
permissions=self.permissions,
|
|
137
145
|
agent_mode=self.agent_mode,
|
|
146
|
+
system_prompt_override=self.system_prompt_override,
|
|
138
147
|
)
|
|
139
148
|
except ProviderUnavailableError as e:
|
|
140
149
|
print(str(e), file=sys.stderr) # message already starts with "Error:"
|
|
@@ -144,18 +153,24 @@ class CommandRunner:
|
|
|
144
153
|
return 1
|
|
145
154
|
|
|
146
155
|
|
|
147
|
-
def run_command(prompt: str, permissions=None, agent_mode: bool = False
|
|
156
|
+
def run_command(prompt: str, permissions=None, agent_mode: bool = False,
|
|
157
|
+
system_prompt_override: str | None = None) -> int:
|
|
148
158
|
"""Execute a single command and return exit code.
|
|
149
159
|
|
|
150
160
|
Args:
|
|
151
161
|
prompt: The command/prompt to execute
|
|
152
162
|
permissions: Set of granted permission categories (e.g. {"r", "w", "x", "http"})
|
|
153
163
|
agent_mode: When True, inject the AGENTIC orchestrator system prompt (ayder-cli --agent).
|
|
164
|
+
system_prompt_override: When set, use this text as the system prompt base
|
|
165
|
+
instead of the built-in prompts.py prompt (ayder --system-prompt FILE).
|
|
154
166
|
|
|
155
167
|
Returns:
|
|
156
168
|
Exit code (0 for success, 1 for error)
|
|
157
169
|
"""
|
|
158
|
-
runner = CommandRunner(
|
|
170
|
+
runner = CommandRunner(
|
|
171
|
+
prompt, permissions=permissions, agent_mode=agent_mode,
|
|
172
|
+
system_prompt_override=system_prompt_override,
|
|
173
|
+
)
|
|
159
174
|
return runner.run()
|
|
160
175
|
|
|
161
176
|
|
|
@@ -9,6 +9,18 @@ logger = logging.getLogger(__name__)
|
|
|
9
9
|
CONFIG_DIR = Path("~/.ayder").expanduser()
|
|
10
10
|
CONFIG_PATH = CONFIG_DIR / "config.toml"
|
|
11
11
|
|
|
12
|
+
|
|
13
|
+
def set_config_path(path: "str | Path") -> None:
|
|
14
|
+
"""Redirect the global config file location (used by the ``-c/--config`` flag).
|
|
15
|
+
|
|
16
|
+
Updates CONFIG_PATH and CONFIG_DIR so every subsequent ``load_config`` (and the
|
|
17
|
+
provider/profile loaders, which read these module globals at call time) use
|
|
18
|
+
*path* instead of the default ``~/.ayder/config.toml``.
|
|
19
|
+
"""
|
|
20
|
+
global CONFIG_PATH, CONFIG_DIR
|
|
21
|
+
CONFIG_PATH = Path(path).expanduser().resolve()
|
|
22
|
+
CONFIG_DIR = CONFIG_PATH.parent
|
|
23
|
+
|
|
12
24
|
# Maintained for test compatibility and initial file generation
|
|
13
25
|
DEFAULTS: Dict[str, Any] = {
|
|
14
26
|
"provider": "openai",
|
|
@@ -288,7 +300,10 @@ class Config(BaseModel):
|
|
|
288
300
|
logging_retention: str = Field(default="7 days")
|
|
289
301
|
max_background_processes: int = Field(default=5)
|
|
290
302
|
max_output_tokens: int = Field(default=4096)
|
|
291
|
-
|
|
303
|
+
# 0 = unlimited: let the context manager's token budget + compaction be the
|
|
304
|
+
# bound. The old fixed 30 predates large-context models and thrashes a tiny
|
|
305
|
+
# history window on a big context.
|
|
306
|
+
max_history_messages: int = Field(default=0)
|
|
292
307
|
prompt: str = Field(default="STANDARD")
|
|
293
308
|
chat_protocol: str = Field(default="ollama")
|
|
294
309
|
stop_sequences: list[str] = Field(default_factory=list)
|
|
@@ -237,8 +237,8 @@ class OllamaContextManager:
|
|
|
237
237
|
cache_state = f", cache={status.state}({status.hit_ratio:.0%})"
|
|
238
238
|
|
|
239
239
|
logger.info(
|
|
240
|
-
"Context: %d/%d tokens (%.0f%%), completion=%d, speed=%s%s",
|
|
241
|
-
self._real_prompt_tokens, ceiling, utilization,
|
|
240
|
+
"Context[%s]: %d/%d tokens (%.0f%%), completion=%d, speed=%s%s",
|
|
241
|
+
self._model or "?", self._real_prompt_tokens, ceiling, utilization,
|
|
242
242
|
self._real_completion_tokens, prompt_speed, cache_state,
|
|
243
243
|
)
|
|
244
244
|
|
|
@@ -633,6 +633,27 @@ AgentPanel .agent-detail {
|
|
|
633
633
|
padding: 0 0 0 4;
|
|
634
634
|
}
|
|
635
635
|
|
|
636
|
+
/* ThinkingPanel - Scrollable panel showing the model's reasoning stream.
|
|
637
|
+
Toggled with Ctrl+T. Taller than the tool/agent panels because reasoning is
|
|
638
|
+
long-form. Targets 'ThinkingPanel' in widgets.py. */
|
|
639
|
+
ThinkingPanel {
|
|
640
|
+
layout: vertical;
|
|
641
|
+
height: auto;
|
|
642
|
+
max-height: 60%;
|
|
643
|
+
background: #0a0a18;
|
|
644
|
+
border-top: solid #333350;
|
|
645
|
+
padding: 1 1;
|
|
646
|
+
overflow-y: scroll;
|
|
647
|
+
display: none;
|
|
648
|
+
}
|
|
649
|
+
|
|
650
|
+
ThinkingPanel .thinking-content {
|
|
651
|
+
height: auto;
|
|
652
|
+
color: #8888aa;
|
|
653
|
+
text-style: italic;
|
|
654
|
+
padding: 0 1;
|
|
655
|
+
}
|
|
656
|
+
|
|
636
657
|
/* AyderApp - The root application screen. */
|
|
637
658
|
Screen {
|
|
638
659
|
layout: vertical;
|
|
@@ -669,6 +690,12 @@ Screen:inline {
|
|
|
669
690
|
width: 100%;
|
|
670
691
|
}
|
|
671
692
|
|
|
693
|
+
#thinking-panel {
|
|
694
|
+
min-height: 0;
|
|
695
|
+
max-height: 60%;
|
|
696
|
+
width: 100%;
|
|
697
|
+
}
|
|
698
|
+
|
|
672
699
|
#input-bar {
|
|
673
700
|
height: auto;
|
|
674
701
|
min-height: 1;
|
|
@@ -514,6 +514,27 @@ ToolPanel .tool-item.completed {
|
|
|
514
514
|
color: $success;
|
|
515
515
|
}
|
|
516
516
|
|
|
517
|
+
/* ThinkingPanel - Scrollable reasoning stream, toggled with Ctrl+T.
|
|
518
|
+
Taller than the tool/agent panels because reasoning is long-form. */
|
|
519
|
+
ThinkingPanel {
|
|
520
|
+
layout: vertical;
|
|
521
|
+
height: auto;
|
|
522
|
+
min-height: 6;
|
|
523
|
+
max-height: 24;
|
|
524
|
+
background: $surface-darken-1;
|
|
525
|
+
border-top: heavy $primary;
|
|
526
|
+
padding: 1 1;
|
|
527
|
+
overflow-y: scroll;
|
|
528
|
+
display: none;
|
|
529
|
+
}
|
|
530
|
+
|
|
531
|
+
ThinkingPanel .thinking-content {
|
|
532
|
+
height: auto;
|
|
533
|
+
color: $text-muted;
|
|
534
|
+
text-style: italic;
|
|
535
|
+
padding: 0 1;
|
|
536
|
+
}
|
|
537
|
+
|
|
517
538
|
/* AyderApp - Main application */
|
|
518
539
|
Screen {
|
|
519
540
|
layout: vertical;
|
|
@@ -168,7 +168,15 @@ def _discover_definitions() -> Tuple["ToolDefinition", ...]:
|
|
|
168
168
|
|
|
169
169
|
_BUILTIN_DEFINITIONS: Tuple[ToolDefinition, ...] = _discover_definitions()
|
|
170
170
|
|
|
171
|
-
# Phase 1: Merge global plugins at import time
|
|
171
|
+
# Phase 1: Merge global plugins at import time.
|
|
172
|
+
#
|
|
173
|
+
# Discovery runs *inside this module's own body*, so a plugin whose definitions
|
|
174
|
+
# module reads ``TOOL_DEFINITIONS`` at import time (e.g. to avoid tool-name
|
|
175
|
+
# collisions, as mcp-tool does) would otherwise hit a circular import — the name
|
|
176
|
+
# isn't bound yet. Bind it provisionally to the builtins first; those are the
|
|
177
|
+
# only definitions that exist during discovery anyway. It is reassigned to the
|
|
178
|
+
# full set (builtins + plugins) immediately after discovery completes.
|
|
179
|
+
TOOL_DEFINITIONS: Tuple[ToolDefinition, ...] = _BUILTIN_DEFINITIONS
|
|
172
180
|
_GLOBAL_PLUGIN_DEFS: Tuple[ToolDefinition, ...] = ()
|
|
173
181
|
_PLUGIN_HANDLERS: Dict[str, Any] = {}
|
|
174
182
|
|
|
@@ -179,9 +187,7 @@ try:
|
|
|
179
187
|
except Exception as e:
|
|
180
188
|
logger.warning(f"Failed to load global plugins: {e}")
|
|
181
189
|
|
|
182
|
-
TOOL_DEFINITIONS
|
|
183
|
-
_BUILTIN_DEFINITIONS + _GLOBAL_PLUGIN_DEFS
|
|
184
|
-
)
|
|
190
|
+
TOOL_DEFINITIONS = _BUILTIN_DEFINITIONS + _GLOBAL_PLUGIN_DEFS
|
|
185
191
|
TOOL_DEFINITIONS_BY_NAME: Dict[str, ToolDefinition] = {
|
|
186
192
|
td.name: td for td in TOOL_DEFINITIONS
|
|
187
193
|
}
|
|
@@ -147,10 +147,15 @@ def install_plugin_from_local(
|
|
|
147
147
|
"Use --force to overwrite."
|
|
148
148
|
)
|
|
149
149
|
|
|
150
|
-
# Copy plugin files
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
150
|
+
# Copy plugin files. When the source IS the install target — e.g. reinstalling
|
|
151
|
+
# an already-installed plugin from its own directory with --force, which is
|
|
152
|
+
# exactly what the missing-dependency warning recommends — the files are
|
|
153
|
+
# already in place. Skip the copy so we don't rmtree the source out from under
|
|
154
|
+
# ourselves (the dependency reinstall + registry refresh below still run).
|
|
155
|
+
if source_dir.resolve() != target_dir.resolve():
|
|
156
|
+
if target_dir.exists():
|
|
157
|
+
shutil.rmtree(target_dir)
|
|
158
|
+
shutil.copytree(source_dir, target_dir)
|
|
154
159
|
|
|
155
160
|
# Update plugins.json
|
|
156
161
|
data = read_plugins_json(plugins_dir)
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
"""Plugin status-badge registry.
|
|
2
|
+
|
|
3
|
+
A lightweight, process-global registry that plugins use to publish a status
|
|
4
|
+
badge (a short label plus a colour) for display in the TUI status bar. The
|
|
5
|
+
mcp-tool plugin, for example, calls ``set_status("mcp", "MCP: news-digest",
|
|
6
|
+
"green")`` once it connects to its MCP servers, and ``set_status("mcp", "MCP",
|
|
7
|
+
"red")`` when configured servers are unreachable.
|
|
8
|
+
|
|
9
|
+
The TUI ``StatusBar`` reads :func:`get_all` to render the badges. Keeping this
|
|
10
|
+
in ayder core (rather than inside a plugin) means the badge survives even when
|
|
11
|
+
the plugin's own modules are loaded under throwaway names during discovery, and
|
|
12
|
+
gives the plugin a stable import target instead of a no-op fallback.
|
|
13
|
+
"""
|
|
14
|
+
|
|
15
|
+
from __future__ import annotations
|
|
16
|
+
|
|
17
|
+
# plugin name -> (label, colour). Colour is a Rich colour/style name ("green").
|
|
18
|
+
_status: dict[str, tuple[str, str]] = {}
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def set_status(name: str, label: str, color: str) -> None:
|
|
22
|
+
"""Register or update a plugin's status badge."""
|
|
23
|
+
_status[name] = (label, color)
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def get_all() -> dict[str, tuple[str, str]]:
|
|
27
|
+
"""Return a copy of all registered status badges (name -> (label, color))."""
|
|
28
|
+
return dict(_status)
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def clear() -> None:
|
|
32
|
+
"""Remove all registered badges (primarily for tests)."""
|
|
33
|
+
_status.clear()
|
|
@@ -32,6 +32,7 @@ def run_tui(
|
|
|
32
32
|
safe_mode: bool = False,
|
|
33
33
|
permissions: set | None = None,
|
|
34
34
|
agent_mode: bool = False,
|
|
35
|
+
system_prompt_override: str | None = None,
|
|
35
36
|
) -> None:
|
|
36
37
|
"""
|
|
37
38
|
Run the CLI-style TUI application.
|
|
@@ -42,6 +43,8 @@ def run_tui(
|
|
|
42
43
|
permissions: Set of granted permission levels ("r", "w", "x")
|
|
43
44
|
agent_mode: When True, inject the AGENTIC orchestrator system prompt
|
|
44
45
|
so the main LLM drives the multi-agent harness (ayder-cli --agent).
|
|
46
|
+
system_prompt_override: When set, use this text as the system-prompt base
|
|
47
|
+
instead of the built-in prompts.py prompt (ayder --system-prompt FILE).
|
|
45
48
|
"""
|
|
46
49
|
import sys
|
|
47
50
|
from ayder_cli.providers import ProviderUnavailableError
|
|
@@ -49,7 +52,7 @@ def run_tui(
|
|
|
49
52
|
try:
|
|
50
53
|
app = AyderApp(
|
|
51
54
|
model=model, safe_mode=safe_mode, permissions=permissions,
|
|
52
|
-
agent_mode=agent_mode,
|
|
55
|
+
agent_mode=agent_mode, system_prompt_override=system_prompt_override,
|
|
53
56
|
)
|
|
54
57
|
except ProviderUnavailableError as e:
|
|
55
58
|
print(str(e), file=sys.stderr)
|