ayder-cli 1.6.9__tar.gz → 1.8.3__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-1.6.9 → ayder_cli-1.8.3}/PKG-INFO +31 -66
- {ayder_cli-1.6.9 → ayder_cli-1.8.3}/README.md +29 -64
- {ayder_cli-1.6.9 → ayder_cli-1.8.3}/docs/PROJECT_STRUCTURE.md +4 -4
- {ayder_cli-1.6.9 → ayder_cli-1.8.3}/pyproject.toml +2 -2
- {ayder_cli-1.6.9 → ayder_cli-1.8.3}/src/ayder_cli/agents/callbacks.py +6 -0
- ayder_cli-1.8.3/src/ayder_cli/agents/config.py +74 -0
- {ayder_cli-1.6.9 → ayder_cli-1.8.3}/src/ayder_cli/agents/registry.py +46 -21
- {ayder_cli-1.6.9 → ayder_cli-1.8.3}/src/ayder_cli/agents/runner.py +17 -0
- {ayder_cli-1.6.9 → ayder_cli-1.8.3}/src/ayder_cli/agents/tool.py +33 -7
- {ayder_cli-1.6.9 → ayder_cli-1.8.3}/src/ayder_cli/application/runtime_factory.py +28 -11
- {ayder_cli-1.6.9 → ayder_cli-1.8.3}/src/ayder_cli/cli_runner.py +18 -3
- {ayder_cli-1.6.9 → ayder_cli-1.8.3}/src/ayder_cli/parser.py +8 -0
- {ayder_cli-1.6.9 → ayder_cli-1.8.3}/src/ayder_cli/prompts.py +13 -63
- {ayder_cli-1.6.9 → ayder_cli-1.8.3}/src/ayder_cli/providers/impl/ollama_drivers/matrix.py +22 -2
- {ayder_cli-1.6.9 → ayder_cli-1.8.3}/src/ayder_cli/providers/impl/ollama_drivers/minimax.py +9 -5
- {ayder_cli-1.6.9 → ayder_cli-1.8.3}/src/ayder_cli/themes/claude.py +40 -0
- {ayder_cli-1.6.9 → ayder_cli-1.8.3}/src/ayder_cli/themes/original.py +39 -0
- ayder_cli-1.8.3/src/ayder_cli/tools/builtins/context.py +344 -0
- ayder_cli-1.8.3/src/ayder_cli/tools/builtins/context_definitions.py +54 -0
- {ayder_cli-1.6.9 → ayder_cli-1.8.3}/src/ayder_cli/tools/execution.py +9 -1
- {ayder_cli-1.6.9 → ayder_cli-1.8.3}/src/ayder_cli/tools/registry.py +21 -3
- {ayder_cli-1.6.9 → ayder_cli-1.8.3}/src/ayder_cli/tui/app.py +85 -10
- {ayder_cli-1.6.9 → ayder_cli-1.8.3}/src/ayder_cli/tui/commands.py +121 -61
- {ayder_cli-1.6.9 → ayder_cli-1.8.3}/src/ayder_cli/tui/screens.py +178 -0
- {ayder_cli-1.6.9 → ayder_cli-1.8.3}/tests/agents/test_integration.py +7 -2
- {ayder_cli-1.6.9 → ayder_cli-1.8.3}/tests/agents/test_registry.py +99 -15
- {ayder_cli-1.6.9 → ayder_cli-1.8.3}/tests/agents/test_runner.py +32 -0
- {ayder_cli-1.6.9 → ayder_cli-1.8.3}/tests/agents/test_tool.py +43 -1
- {ayder_cli-1.6.9 → ayder_cli-1.8.3}/tests/application/test_message_contract.py +1 -2
- {ayder_cli-1.6.9 → ayder_cli-1.8.3}/tests/application/test_runtime_factory.py +2 -0
- {ayder_cli-1.6.9 → ayder_cli-1.8.3}/tests/core/test_parser.py +41 -0
- {ayder_cli-1.6.9 → ayder_cli-1.8.3}/tests/providers/ollama_drivers/test_matrix.py +2 -1
- ayder_cli-1.8.3/tests/providers/ollama_drivers/test_minimax.py +76 -0
- {ayder_cli-1.6.9 → ayder_cli-1.8.3}/tests/providers/test_ollama_xml_autoroute.py +1 -1
- ayder_cli-1.8.3/tests/test_context.py +453 -0
- {ayder_cli-1.6.9 → ayder_cli-1.8.3}/tests/tools/test_definition_discovery.py +2 -4
- ayder_cli-1.8.3/tests/tools/test_di_injection.py +50 -0
- {ayder_cli-1.6.9 → ayder_cli-1.8.3}/tests/tools/test_schemas.py +2 -2
- ayder_cli-1.8.3/tests/tui/__init__.py +1 -0
- ayder_cli-1.8.3/tests/tui/test_agent_list_screen.py +115 -0
- ayder_cli-1.8.3/tests/tui/test_do_clear_coordination.py +93 -0
- ayder_cli-1.8.3/tests/tui/test_pending_compact_consumer.py +148 -0
- ayder_cli-1.8.3/tests/ui/test_tui_commands_agent.py +108 -0
- ayder_cli-1.8.3/tests/ui/test_tui_widgets.py +28 -0
- ayder_cli-1.6.9/src/ayder_cli/agents/config.py +0 -14
- ayder_cli-1.6.9/src/ayder_cli/tools/builtins/memory.py +0 -155
- ayder_cli-1.6.9/src/ayder_cli/tools/builtins/memory_definitions.py +0 -105
- ayder_cli-1.6.9/tests/providers/ollama_drivers/test_minimax.py +0 -49
- ayder_cli-1.6.9/tests/test_memory.py +0 -123
- ayder_cli-1.6.9/tests/ui/test_tui_widgets.py +0 -28
- {ayder_cli-1.6.9 → ayder_cli-1.8.3}/.github/workflows/ci.yml +0 -0
- {ayder_cli-1.6.9 → ayder_cli-1.8.3}/.github/workflows/python-package.yml +0 -0
- {ayder_cli-1.6.9 → ayder_cli-1.8.3}/.gitignore +0 -0
- {ayder_cli-1.6.9 → ayder_cli-1.8.3}/.python-version +0 -0
- {ayder_cli-1.6.9 → ayder_cli-1.8.3}/AGENTS.md +0 -0
- {ayder_cli-1.6.9 → ayder_cli-1.8.3}/LICENSE +0 -0
- {ayder_cli-1.6.9 → ayder_cli-1.8.3}/docs/README_OLLAMA.md +0 -0
- {ayder_cli-1.6.9 → ayder_cli-1.8.3}/docs/cc.png +0 -0
- {ayder_cli-1.6.9 → ayder_cli-1.8.3}/docs/config.toml.example +0 -0
- {ayder_cli-1.6.9 → ayder_cli-1.8.3}/src/ayder_cli/__init__.py +0 -0
- {ayder_cli-1.6.9 → ayder_cli-1.8.3}/src/ayder_cli/__main__.py +0 -0
- {ayder_cli-1.6.9 → ayder_cli-1.8.3}/src/ayder_cli/agents/__init__.py +0 -0
- {ayder_cli-1.6.9 → ayder_cli-1.8.3}/src/ayder_cli/agents/summary.py +0 -0
- {ayder_cli-1.6.9 → ayder_cli-1.8.3}/src/ayder_cli/application/README.md +0 -0
- {ayder_cli-1.6.9 → ayder_cli-1.8.3}/src/ayder_cli/application/__init__.py +0 -0
- {ayder_cli-1.6.9 → ayder_cli-1.8.3}/src/ayder_cli/application/execution_policy.py +0 -0
- {ayder_cli-1.6.9 → ayder_cli-1.8.3}/src/ayder_cli/application/message_contract.py +0 -0
- {ayder_cli-1.6.9 → ayder_cli-1.8.3}/src/ayder_cli/application/validation.py +0 -0
- {ayder_cli-1.6.9 → ayder_cli-1.8.3}/src/ayder_cli/cli.py +0 -0
- {ayder_cli-1.6.9 → ayder_cli-1.8.3}/src/ayder_cli/cli_callbacks.py +0 -0
- {ayder_cli-1.6.9 → ayder_cli-1.8.3}/src/ayder_cli/console.py +0 -0
- {ayder_cli-1.6.9 → ayder_cli-1.8.3}/src/ayder_cli/core/cache_monitor.py +0 -0
- {ayder_cli-1.6.9 → ayder_cli-1.8.3}/src/ayder_cli/core/config.py +0 -0
- {ayder_cli-1.6.9 → ayder_cli-1.8.3}/src/ayder_cli/core/config_migration.py +0 -0
- {ayder_cli-1.6.9 → ayder_cli-1.8.3}/src/ayder_cli/core/context.py +0 -0
- {ayder_cli-1.6.9 → ayder_cli-1.8.3}/src/ayder_cli/core/context_manager.py +0 -0
- {ayder_cli-1.6.9 → ayder_cli-1.8.3}/src/ayder_cli/core/context_manager_factory.py +0 -0
- {ayder_cli-1.6.9 → ayder_cli-1.8.3}/src/ayder_cli/core/default_context_manager.py +0 -0
- {ayder_cli-1.6.9 → ayder_cli-1.8.3}/src/ayder_cli/core/ollama_context_manager.py +0 -0
- {ayder_cli-1.6.9 → ayder_cli-1.8.3}/src/ayder_cli/core/result.py +0 -0
- {ayder_cli-1.6.9 → ayder_cli-1.8.3}/src/ayder_cli/logging_config.py +0 -0
- {ayder_cli-1.6.9 → ayder_cli-1.8.3}/src/ayder_cli/loops/__init__.py +0 -0
- {ayder_cli-1.6.9 → ayder_cli-1.8.3}/src/ayder_cli/loops/chat_loop.py +0 -0
- {ayder_cli-1.6.9 → ayder_cli-1.8.3}/src/ayder_cli/process_manager.py +0 -0
- {ayder_cli-1.6.9 → ayder_cli-1.8.3}/src/ayder_cli/providers/__init__.py +0 -0
- {ayder_cli-1.6.9 → ayder_cli-1.8.3}/src/ayder_cli/providers/base.py +0 -0
- {ayder_cli-1.6.9 → ayder_cli-1.8.3}/src/ayder_cli/providers/impl/claude.py +0 -0
- {ayder_cli-1.6.9 → ayder_cli-1.8.3}/src/ayder_cli/providers/impl/deepseek.py +0 -0
- {ayder_cli-1.6.9 → ayder_cli-1.8.3}/src/ayder_cli/providers/impl/gemini.py +0 -0
- {ayder_cli-1.6.9 → ayder_cli-1.8.3}/src/ayder_cli/providers/impl/glm.py +0 -0
- {ayder_cli-1.6.9 → ayder_cli-1.8.3}/src/ayder_cli/providers/impl/ollama.py +0 -0
- {ayder_cli-1.6.9 → ayder_cli-1.8.3}/src/ayder_cli/providers/impl/ollama_drivers/__init__.py +0 -0
- {ayder_cli-1.6.9 → ayder_cli-1.8.3}/src/ayder_cli/providers/impl/ollama_drivers/_errors.py +0 -0
- {ayder_cli-1.6.9 → ayder_cli-1.8.3}/src/ayder_cli/providers/impl/ollama_drivers/base.py +0 -0
- {ayder_cli-1.6.9 → ayder_cli-1.8.3}/src/ayder_cli/providers/impl/ollama_drivers/deepseek.py +0 -0
- {ayder_cli-1.6.9 → ayder_cli-1.8.3}/src/ayder_cli/providers/impl/ollama_drivers/generic_native.py +0 -0
- {ayder_cli-1.6.9 → ayder_cli-1.8.3}/src/ayder_cli/providers/impl/ollama_drivers/generic_xml.py +0 -0
- {ayder_cli-1.6.9 → ayder_cli-1.8.3}/src/ayder_cli/providers/impl/ollama_drivers/qwen3.py +0 -0
- {ayder_cli-1.6.9 → ayder_cli-1.8.3}/src/ayder_cli/providers/impl/ollama_drivers/registry.py +0 -0
- {ayder_cli-1.6.9 → ayder_cli-1.8.3}/src/ayder_cli/providers/impl/ollama_inspector.py +0 -0
- {ayder_cli-1.6.9 → ayder_cli-1.8.3}/src/ayder_cli/providers/impl/openai.py +0 -0
- {ayder_cli-1.6.9 → ayder_cli-1.8.3}/src/ayder_cli/providers/impl/qwen.py +0 -0
- {ayder_cli-1.6.9 → ayder_cli-1.8.3}/src/ayder_cli/providers/orchestrator.py +0 -0
- {ayder_cli-1.6.9 → ayder_cli-1.8.3}/src/ayder_cli/providers/retry.py +0 -0
- {ayder_cli-1.6.9 → ayder_cli-1.8.3}/src/ayder_cli/services/__init__.py +0 -0
- {ayder_cli-1.6.9 → ayder_cli-1.8.3}/src/ayder_cli/services/interactions.py +0 -0
- {ayder_cli-1.6.9 → ayder_cli-1.8.3}/src/ayder_cli/themes/__init__.py +0 -0
- {ayder_cli-1.6.9 → ayder_cli-1.8.3}/src/ayder_cli/tools/__init__.py +0 -0
- {ayder_cli-1.6.9 → ayder_cli-1.8.3}/src/ayder_cli/tools/builtins/__init__.py +0 -0
- {ayder_cli-1.6.9 → ayder_cli-1.8.3}/src/ayder_cli/tools/builtins/filesystem.py +0 -0
- {ayder_cli-1.6.9 → ayder_cli-1.8.3}/src/ayder_cli/tools/builtins/filesystem_definitions.py +0 -0
- {ayder_cli-1.6.9 → ayder_cli-1.8.3}/src/ayder_cli/tools/builtins/notes.py +0 -0
- {ayder_cli-1.6.9 → ayder_cli-1.8.3}/src/ayder_cli/tools/builtins/notes_definitions.py +0 -0
- {ayder_cli-1.6.9 → ayder_cli-1.8.3}/src/ayder_cli/tools/builtins/process_manager_definitions.py +0 -0
- {ayder_cli-1.6.9 → ayder_cli-1.8.3}/src/ayder_cli/tools/builtins/search.py +0 -0
- {ayder_cli-1.6.9 → ayder_cli-1.8.3}/src/ayder_cli/tools/builtins/search_definitions.py +0 -0
- {ayder_cli-1.6.9 → ayder_cli-1.8.3}/src/ayder_cli/tools/builtins/shell.py +0 -0
- {ayder_cli-1.6.9 → ayder_cli-1.8.3}/src/ayder_cli/tools/builtins/shell_definitions.py +0 -0
- {ayder_cli-1.6.9 → ayder_cli-1.8.3}/src/ayder_cli/tools/builtins/tasks.py +0 -0
- {ayder_cli-1.6.9 → ayder_cli-1.8.3}/src/ayder_cli/tools/builtins/tasks_definitions.py +0 -0
- {ayder_cli-1.6.9 → ayder_cli-1.8.3}/src/ayder_cli/tools/builtins/utils_tools.py +0 -0
- {ayder_cli-1.6.9 → ayder_cli-1.8.3}/src/ayder_cli/tools/builtins/utils_tools_definitions.py +0 -0
- {ayder_cli-1.6.9 → ayder_cli-1.8.3}/src/ayder_cli/tools/builtins/web.py +0 -0
- {ayder_cli-1.6.9 → ayder_cli-1.8.3}/src/ayder_cli/tools/builtins/web_definitions.py +0 -0
- {ayder_cli-1.6.9 → ayder_cli-1.8.3}/src/ayder_cli/tools/definition.py +0 -0
- {ayder_cli-1.6.9 → ayder_cli-1.8.3}/src/ayder_cli/tools/hooks.py +0 -0
- {ayder_cli-1.6.9 → ayder_cli-1.8.3}/src/ayder_cli/tools/normalization.py +0 -0
- {ayder_cli-1.6.9 → ayder_cli-1.8.3}/src/ayder_cli/tools/plugin_api.py +0 -0
- {ayder_cli-1.6.9 → ayder_cli-1.8.3}/src/ayder_cli/tools/plugin_github.py +0 -0
- {ayder_cli-1.6.9 → ayder_cli-1.8.3}/src/ayder_cli/tools/plugin_manager.py +0 -0
- {ayder_cli-1.6.9 → ayder_cli-1.8.3}/src/ayder_cli/tools/schemas.py +0 -0
- {ayder_cli-1.6.9 → ayder_cli-1.8.3}/src/ayder_cli/tools/utils.py +0 -0
- {ayder_cli-1.6.9 → ayder_cli-1.8.3}/src/ayder_cli/tui/__init__.py +0 -0
- {ayder_cli-1.6.9 → ayder_cli-1.8.3}/src/ayder_cli/tui/adapter.py +0 -0
- {ayder_cli-1.6.9 → ayder_cli-1.8.3}/src/ayder_cli/tui/helpers.py +0 -0
- {ayder_cli-1.6.9 → ayder_cli-1.8.3}/src/ayder_cli/tui/keybindings.py +0 -0
- {ayder_cli-1.6.9 → ayder_cli-1.8.3}/src/ayder_cli/tui/parser.py +0 -0
- {ayder_cli-1.6.9 → ayder_cli-1.8.3}/src/ayder_cli/tui/theme_manager.py +0 -0
- {ayder_cli-1.6.9 → ayder_cli-1.8.3}/src/ayder_cli/tui/types.py +0 -0
- {ayder_cli-1.6.9 → ayder_cli-1.8.3}/src/ayder_cli/tui/widgets.py +0 -0
- {ayder_cli-1.6.9 → ayder_cli-1.8.3}/src/ayder_cli/ui.py +0 -0
- {ayder_cli-1.6.9 → ayder_cli-1.8.3}/src/ayder_cli/version.py +0 -0
- {ayder_cli-1.6.9 → ayder_cli-1.8.3}/tests/COVERAGE.md +0 -0
- {ayder_cli-1.6.9 → ayder_cli-1.8.3}/tests/__init__.py +0 -0
- {ayder_cli-1.6.9 → ayder_cli-1.8.3}/tests/agents/__init__.py +0 -0
- {ayder_cli-1.6.9 → ayder_cli-1.8.3}/tests/agents/test_callbacks.py +0 -0
- {ayder_cli-1.6.9 → ayder_cli-1.8.3}/tests/agents/test_config.py +0 -0
- {ayder_cli-1.6.9 → ayder_cli-1.8.3}/tests/agents/test_summary.py +0 -0
- {ayder_cli-1.6.9 → ayder_cli-1.8.3}/tests/client/test_main.py +0 -0
- {ayder_cli-1.6.9 → ayder_cli-1.8.3}/tests/convergence/__init__.py +0 -0
- {ayder_cli-1.6.9 → ayder_cli-1.8.3}/tests/convergence/test_execution_policy_parity.py +0 -0
- {ayder_cli-1.6.9 → ayder_cli-1.8.3}/tests/convergence/test_runtime_wiring.py +0 -0
- {ayder_cli-1.6.9 → ayder_cli-1.8.3}/tests/convergence/test_validation_path.py +0 -0
- {ayder_cli-1.6.9 → ayder_cli-1.8.3}/tests/core/test_cache_monitor.py +0 -0
- {ayder_cli-1.6.9 → ayder_cli-1.8.3}/tests/core/test_config.py +0 -0
- {ayder_cli-1.6.9 → ayder_cli-1.8.3}/tests/core/test_config_coverage.py +0 -0
- {ayder_cli-1.6.9 → ayder_cli-1.8.3}/tests/core/test_config_migration.py +0 -0
- {ayder_cli-1.6.9 → ayder_cli-1.8.3}/tests/core/test_config_retry.py +0 -0
- {ayder_cli-1.6.9 → ayder_cli-1.8.3}/tests/core/test_config_v2.py +0 -0
- {ayder_cli-1.6.9 → ayder_cli-1.8.3}/tests/core/test_context_manager_factory.py +0 -0
- {ayder_cli-1.6.9 → ayder_cli-1.8.3}/tests/core/test_default_context_manager.py +0 -0
- {ayder_cli-1.6.9 → ayder_cli-1.8.3}/tests/core/test_default_context_manager_should_compact.py +0 -0
- {ayder_cli-1.6.9 → ayder_cli-1.8.3}/tests/core/test_ollama_context_manager.py +0 -0
- {ayder_cli-1.6.9 → ayder_cli-1.8.3}/tests/core/test_ollama_context_manager_cache_monitor.py +0 -0
- {ayder_cli-1.6.9 → ayder_cli-1.8.3}/tests/core/test_ollama_context_manager_max_history.py +0 -0
- {ayder_cli-1.6.9 → ayder_cli-1.8.3}/tests/core/test_parameter_aliasing.py +0 -0
- {ayder_cli-1.6.9 → ayder_cli-1.8.3}/tests/loops/__init__.py +0 -0
- {ayder_cli-1.6.9 → ayder_cli-1.8.3}/tests/loops/test_base.py +0 -0
- {ayder_cli-1.6.9 → ayder_cli-1.8.3}/tests/loops/test_chat_loop_hook.py +0 -0
- {ayder_cli-1.6.9 → ayder_cli-1.8.3}/tests/loops/test_chat_loop_tool_truncation.py +0 -0
- {ayder_cli-1.6.9 → ayder_cli-1.8.3}/tests/manual_test_verbose.py +0 -0
- {ayder_cli-1.6.9 → ayder_cli-1.8.3}/tests/providers/__init__.py +0 -0
- {ayder_cli-1.6.9 → ayder_cli-1.8.3}/tests/providers/ollama_drivers/__init__.py +0 -0
- {ayder_cli-1.6.9 → ayder_cli-1.8.3}/tests/providers/ollama_drivers/test_base.py +0 -0
- {ayder_cli-1.6.9 → ayder_cli-1.8.3}/tests/providers/ollama_drivers/test_deepseek.py +0 -0
- {ayder_cli-1.6.9 → ayder_cli-1.8.3}/tests/providers/ollama_drivers/test_errors.py +0 -0
- {ayder_cli-1.6.9 → ayder_cli-1.8.3}/tests/providers/ollama_drivers/test_fallback.py +0 -0
- {ayder_cli-1.6.9 → ayder_cli-1.8.3}/tests/providers/ollama_drivers/test_generic_native.py +0 -0
- {ayder_cli-1.6.9 → ayder_cli-1.8.3}/tests/providers/ollama_drivers/test_generic_xml.py +0 -0
- {ayder_cli-1.6.9 → ayder_cli-1.8.3}/tests/providers/ollama_drivers/test_provider_integration.py +0 -0
- {ayder_cli-1.6.9 → ayder_cli-1.8.3}/tests/providers/ollama_drivers/test_qwen3.py +0 -0
- {ayder_cli-1.6.9 → ayder_cli-1.8.3}/tests/providers/ollama_drivers/test_registry.py +0 -0
- {ayder_cli-1.6.9 → ayder_cli-1.8.3}/tests/providers/test_glm_async.py +0 -0
- {ayder_cli-1.6.9 → ayder_cli-1.8.3}/tests/providers/test_ollama_inspector.py +0 -0
- {ayder_cli-1.6.9 → ayder_cli-1.8.3}/tests/providers/test_ollama_native.py +0 -0
- {ayder_cli-1.6.9 → ayder_cli-1.8.3}/tests/providers/test_ollama_xml.py +0 -0
- {ayder_cli-1.6.9 → ayder_cli-1.8.3}/tests/providers/test_ollama_xml_usage.py +0 -0
- {ayder_cli-1.6.9 → ayder_cli-1.8.3}/tests/providers/test_qwen_async.py +0 -0
- {ayder_cli-1.6.9 → ayder_cli-1.8.3}/tests/providers/test_retry_classifier.py +0 -0
- {ayder_cli-1.6.9 → ayder_cli-1.8.3}/tests/providers/test_retry_integration.py +0 -0
- {ayder_cli-1.6.9 → ayder_cli-1.8.3}/tests/providers/test_retrying_provider.py +0 -0
- {ayder_cli-1.6.9 → ayder_cli-1.8.3}/tests/services/test_boundary.py +0 -0
- {ayder_cli-1.6.9 → ayder_cli-1.8.3}/tests/services/test_interaction_sink.py +0 -0
- {ayder_cli-1.6.9 → ayder_cli-1.8.3}/tests/test_cli.py +0 -0
- {ayder_cli-1.6.9 → ayder_cli-1.8.3}/tests/test_cli_callbacks.py +0 -0
- {ayder_cli-1.6.9 → ayder_cli-1.8.3}/tests/test_env_manager.py +0 -0
- {ayder_cli-1.6.9 → ayder_cli-1.8.3}/tests/test_logging_config.py +0 -0
- {ayder_cli-1.6.9 → ayder_cli-1.8.3}/tests/test_notes.py +0 -0
- {ayder_cli-1.6.9 → ayder_cli-1.8.3}/tests/test_process_manager.py +0 -0
- {ayder_cli-1.6.9 → ayder_cli-1.8.3}/tests/test_tasks.py +0 -0
- {ayder_cli-1.6.9 → ayder_cli-1.8.3}/tests/tools/__init__.py +0 -0
- {ayder_cli-1.6.9 → ayder_cli-1.8.3}/tests/tools/test_impl.py +0 -0
- {ayder_cli-1.6.9 → ayder_cli-1.8.3}/tests/tools/test_impl_coverage.py +0 -0
- {ayder_cli-1.6.9 → ayder_cli-1.8.3}/tests/tools/test_path_security.py +0 -0
- {ayder_cli-1.6.9 → ayder_cli-1.8.3}/tests/tools/test_plugin_api.py +0 -0
- {ayder_cli-1.6.9 → ayder_cli-1.8.3}/tests/tools/test_plugin_github.py +0 -0
- {ayder_cli-1.6.9 → ayder_cli-1.8.3}/tests/tools/test_plugin_loading.py +0 -0
- {ayder_cli-1.6.9 → ayder_cli-1.8.3}/tests/tools/test_plugin_manager.py +0 -0
- {ayder_cli-1.6.9 → ayder_cli-1.8.3}/tests/tools/test_registry.py +0 -0
- {ayder_cli-1.6.9 → ayder_cli-1.8.3}/tests/tools/test_registry_coverage.py +0 -0
- {ayder_cli-1.6.9 → ayder_cli-1.8.3}/tests/tools/test_result.py +0 -0
- {ayder_cli-1.6.9 → ayder_cli-1.8.3}/tests/tools/test_search_codebase.py +0 -0
- {ayder_cli-1.6.9 → ayder_cli-1.8.3}/tests/tools/test_utils.py +0 -0
- {ayder_cli-1.6.9 → ayder_cli-1.8.3}/tests/tools/test_web.py +0 -0
- {ayder_cli-1.6.9 → ayder_cli-1.8.3}/tests/tui/test_follow_mode.py +0 -0
- {ayder_cli-1.6.9 → ayder_cli-1.8.3}/tests/tui/test_help_screen.py +0 -0
- {ayder_cli-1.6.9 → ayder_cli-1.8.3}/tests/tui/test_keybindings.py +0 -0
- {ayder_cli-1.6.9 → ayder_cli-1.8.3}/tests/tui/test_multi_select_screen.py +0 -0
- {ayder_cli-1.6.9 → ayder_cli-1.8.3}/tests/tui/test_multiline_input.py +0 -0
- {ayder_cli-1.6.9 → ayder_cli-1.8.3}/tests/tui/test_paste.py +0 -0
- {ayder_cli-1.6.9 → ayder_cli-1.8.3}/tests/tui/test_widgets.py +0 -0
- {ayder_cli-1.6.9 → ayder_cli-1.8.3}/tests/ui/test_confirm_screen.py +0 -0
- {ayder_cli-1.6.9 → ayder_cli-1.8.3}/tests/ui/test_diff_preview.py +0 -0
- {ayder_cli-1.6.9 → ayder_cli-1.8.3}/tests/ui/test_tui_assistant_sanitization.py +0 -0
- {ayder_cli-1.6.9 → ayder_cli-1.8.3}/tests/ui/test_tui_chat_loop.py +0 -0
- {ayder_cli-1.6.9 → ayder_cli-1.8.3}/tests/ui/test_tui_commands_logging.py +0 -0
- {ayder_cli-1.6.9 → ayder_cli-1.8.3}/tests/ui/test_tui_commands_provider.py +0 -0
- {ayder_cli-1.6.9 → ayder_cli-1.8.3}/tests/ui/test_tui_helpers.py +0 -0
- {ayder_cli-1.6.9 → ayder_cli-1.8.3}/tests/ui/test_tui_temporal_command.py +0 -0
- {ayder_cli-1.6.9 → ayder_cli-1.8.3}/tests/ui/test_ui.py +0 -0
- {ayder_cli-1.6.9 → ayder_cli-1.8.3}/tests/ui/test_ui_coverage.py +0 -0
- {ayder_cli-1.6.9 → ayder_cli-1.8.3}/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: 1.
|
|
3
|
+
Version: 1.8.3
|
|
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
|
|
@@ -19,7 +19,7 @@ Requires-Dist: google-genai
|
|
|
19
19
|
Requires-Dist: httpx
|
|
20
20
|
Requires-Dist: libcst>=1.0.0
|
|
21
21
|
Requires-Dist: loguru
|
|
22
|
-
Requires-Dist: ollama>=0.6.
|
|
22
|
+
Requires-Dist: ollama>=0.6.2
|
|
23
23
|
Requires-Dist: openai
|
|
24
24
|
Requires-Dist: python-dotenv>=1.0.0
|
|
25
25
|
Requires-Dist: rich>=13.0.0
|
|
@@ -54,39 +54,11 @@ Most AI coding assistants require cloud APIs, subscriptions, or heavy IDE plugin
|
|
|
54
54
|
- **Agentic workflow** -- the LLM reads files, edits code, runs shell commands, and iterates autonomously with configurable iteration limits per message.
|
|
55
55
|
- **Multi-agent** -- define specialized sub-agents in `config.toml`. Each agent runs independently with its own LLM, model, and context. Results are injected back into the main conversation when complete.
|
|
56
56
|
- **Textual TUI** -- an inline terminal interface with chat view, tool panel, thinking block toggle, slash command auto-completion, permission toggles, and tool confirmation modals with diff previews.
|
|
57
|
-
- **
|
|
58
|
-
|
|
59
|
-
### Tested Providers with Models
|
|
60
|
-
|
|
61
|
-
| Provider | Location | Model |
|
|
62
|
-
| -------- | -------- | ----- |
|
|
63
|
-
| ollama | Cloud | deepseek-v3.2:cloud |
|
|
64
|
-
| ollama | Cloud | gemini-3-pro-preview:latest |
|
|
65
|
-
| ollama | Local | glm-4.7-flash:latest |
|
|
66
|
-
| ollama | Cloud | glm-4.7:cloud |
|
|
67
|
-
| ollama | Cloud | glm-5:cloud |
|
|
68
|
-
| ollama | Local | glm-ocr:latest |
|
|
69
|
-
| ollama | Cloud | gpt-oss:120b-cloud |
|
|
70
|
-
| ollama | Cloud | kimi-k2.5:cloud |
|
|
71
|
-
| ollama | Cloud | minimax-m2.5:cloud |
|
|
72
|
-
| ollama | Local | ministral-3:14b |
|
|
73
|
-
| ollama | Cloud | qwen3-coder-next:cloud |
|
|
74
|
-
| ollama | Cloud | qwen3-coder:480b-cloud |
|
|
75
|
-
| ollama | Local | qwen3-coder:latest |
|
|
76
|
-
| anthropic | Cloud | claude-opus-4-6 |
|
|
77
|
-
| anthropic | Cloud | claude-sonnet-4-5-20250929 |
|
|
78
|
-
| anthropic | Cloud | claude-haiku-4-5-20251001 |
|
|
79
|
-
| openai | Cloud | GPT-5.3-Codex |
|
|
80
|
-
| openai | Cloud | GPT-5.3-Codex-Spark |
|
|
81
|
-
| openai | Cloud | GPT-5.2 |
|
|
82
|
-
| openai | Cloud | GPT-5 |
|
|
83
|
-
| gemini | Cloud | gemini-3-deep-think |
|
|
84
|
-
| gemini | Cloud | gemini-3-pro |
|
|
85
|
-
| gemini | Cloud | gemini-3-flash |
|
|
57
|
+
- **Batteries included** -- the OpenAI, Anthropic, Google, and Ollama SDKs all ship with ayder-cli, so every provider works out of the box. The terminal UI is built on Rich and Textual.
|
|
86
58
|
|
|
87
59
|
### Tools
|
|
88
60
|
|
|
89
|
-
LLMs on their own can only generate text. To be a useful coding assistant, the model needs to *act* on your codebase. ayder-cli
|
|
61
|
+
LLMs on their own can only generate text. To be a useful coding assistant, the model needs to *act* on your codebase. ayder-cli ships 16 built-in tools that the model can call, plus optional plugin toolsets (see [Plugins](#plugins)):
|
|
90
62
|
|
|
91
63
|
Each tool has an OpenAI-compatible JSON schema so models that support function calling can use them natively. For models that don't, ayder-cli also parses a custom XML-like syntax (`<function=name><parameter=key>value</parameter></function>`) as a fallback.
|
|
92
64
|
|
|
@@ -134,26 +106,16 @@ export OLLAMA_FLASH_ATTENTION=true
|
|
|
134
106
|
export OLLAMA_MAX_LOADED_MODELS=1
|
|
135
107
|
```
|
|
136
108
|
|
|
137
|
-
### Anthropic
|
|
109
|
+
### Cloud providers (Anthropic, OpenAI, Gemini)
|
|
138
110
|
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
# Set your API key in ~/.ayder/config.toml (see Configuration below)
|
|
144
|
-
# Then switch provider:
|
|
145
|
-
# /provider anthropic
|
|
146
|
-
```
|
|
147
|
-
|
|
148
|
-
### Gemini setup (optional)
|
|
111
|
+
The Anthropic, OpenAI, and Google SDKs ship with ayder-cli — no extra installs.
|
|
112
|
+
Just add an API key to a profile in `~/.ayder/config.toml` (see Configuration
|
|
113
|
+
below) and switch provider in the TUI:
|
|
149
114
|
|
|
150
115
|
```bash
|
|
151
|
-
#
|
|
152
|
-
pip install google-generativeai
|
|
116
|
+
/provider anthropic # or: openai, gemini
|
|
153
117
|
```
|
|
154
118
|
|
|
155
|
-
Set your API key in `~/.ayder/config.toml`, then switch provider: `/provider gemini`
|
|
156
|
-
|
|
157
119
|
### Configuration: Profiles and Drivers
|
|
158
120
|
|
|
159
121
|
ayder-cli uses a flexible profile-based configuration system. On the first run, it creates a config file at `~/.ayder/config.toml`.
|
|
@@ -218,7 +180,7 @@ rotation = "10 MB"
|
|
|
218
180
|
retention = "7 days"
|
|
219
181
|
|
|
220
182
|
[context_manager]
|
|
221
|
-
enabled =
|
|
183
|
+
enabled = true
|
|
222
184
|
max_context_tokens = 8192
|
|
223
185
|
|
|
224
186
|
[temporal]
|
|
@@ -316,12 +278,14 @@ ayder --implement-all
|
|
|
316
278
|
|
|
317
279
|
By default, every tool call requires user confirmation. Use permission flags to auto-approve tool categories:
|
|
318
280
|
|
|
319
|
-
| Flag | Category |
|
|
320
|
-
| ---- | -------- |
|
|
321
|
-
| `-r` | Read | `file_explorer`, `read_file`, `search_codebase`, `get_project_structure`, `
|
|
322
|
-
| `-w` | Write | `file_editor`, `
|
|
323
|
-
| `-x` | Execute | `run_shell_command`, `run_background_process`, `kill_background_process
|
|
324
|
-
| `--http` | Web/Network | `fetch_web
|
|
281
|
+
| Flag | Category | Built-in tools |
|
|
282
|
+
| ---- | -------- | -------------- |
|
|
283
|
+
| `-r` | Read | `file_explorer`, `read_file`, `search_codebase`, `get_project_structure`, `get_background_output`, `list_background_processes`, `list_tasks`, `show_task` |
|
|
284
|
+
| `-w` | Write | `file_editor`, `context`, `create_note`, `manage_environment_vars` |
|
|
285
|
+
| `-x` | Execute | `run_shell_command`, `run_background_process`, `kill_background_process` |
|
|
286
|
+
| `--http` | Web/Network | `fetch_web` |
|
|
287
|
+
|
|
288
|
+
Installed plugins extend these categories (e.g. `python_editor` → write, virtualenv tools → execute, `dbs_tool` → web).
|
|
325
289
|
|
|
326
290
|
```bash
|
|
327
291
|
# Auto-approve read-only tools
|
|
@@ -370,7 +334,7 @@ The context manager is configured under `[context_manager]` in `config.toml`:
|
|
|
370
334
|
| `max_tool_result_length` | `2048` | Maximum character length for a compressed tool result. |
|
|
371
335
|
| `compress_tool_results` | `true` | Enable automatic tool result compression. |
|
|
372
336
|
|
|
373
|
-
You can also manually manage context with `/save-
|
|
337
|
+
You can also manually manage context with the `context` tool and its slash-command shortcuts: `/save-context`, `/load-context`, `/list-contexts`, `/context-stats`, and `/compact`.
|
|
374
338
|
|
|
375
339
|
### Slash Commands
|
|
376
340
|
|
|
@@ -390,9 +354,11 @@ You can also manually manage context with `/save-memory`, `/load-memory`, and `/
|
|
|
390
354
|
| `/skill` | Activate a domain skill from `.ayder/skills/` |
|
|
391
355
|
| `/verbose` | Toggle verbose mode |
|
|
392
356
|
| `/logging` | Set log level for current session (NONE, ERROR, WARNING, INFO, DEBUG) |
|
|
393
|
-
| `/compact` | Summarize conversation, save
|
|
394
|
-
| `/save-
|
|
395
|
-
| `/load-
|
|
357
|
+
| `/compact` | Summarize conversation, save a context snapshot, clear, and reload |
|
|
358
|
+
| `/save-context` | Summarize conversation and save it to a named context slot (no clear) |
|
|
359
|
+
| `/load-context` | Load a saved context slot and restore it |
|
|
360
|
+
| `/list-contexts` | List saved context slots |
|
|
361
|
+
| `/context-stats` | Show current token and KV-cache usage |
|
|
396
362
|
| `/archive-completed-tasks` | Move completed tasks to `.ayder/task_archive/` |
|
|
397
363
|
| `/temporal` | Start/status Temporal queue worker |
|
|
398
364
|
| `/agent list` | List configured agents and their current status |
|
|
@@ -436,7 +402,7 @@ The standard mode for general coding and chat. Uses the system prompt.
|
|
|
436
402
|
> create a fibonacci function
|
|
437
403
|
```
|
|
438
404
|
|
|
439
|
-
Available tools:
|
|
405
|
+
Available tools: file read/write, shell commands, search, context, notes, tasks.
|
|
440
406
|
|
|
441
407
|
### Planning Mode (`/plan`)
|
|
442
408
|
|
|
@@ -486,24 +452,23 @@ The tool system:
|
|
|
486
452
|
- Supports tag-based filtering for dynamic enable/disable
|
|
487
453
|
- Injects tool-specific system prompts when enabled
|
|
488
454
|
|
|
489
|
-
**
|
|
455
|
+
**Built-in tools (16):**
|
|
490
456
|
|
|
491
457
|
| Category | Tools |
|
|
492
458
|
|----------|-------|
|
|
493
459
|
| **Filesystem** | `file_explorer`, `read_file`, `file_editor` |
|
|
494
460
|
| **Search** | `search_codebase`, `get_project_structure` |
|
|
495
461
|
| **Shell** | `run_shell_command` |
|
|
496
|
-
| **
|
|
497
|
-
| **Memory** | `save_memory`, `load_memory` |
|
|
462
|
+
| **Context** | `context` (save / load / list / stats / clear session context slots) |
|
|
498
463
|
| **Notes** | `create_note` |
|
|
499
464
|
| **Background Processes** | `run_background_process`, `get_background_output`, `kill_background_process`, `list_background_processes` |
|
|
500
465
|
| **Tasks** | `list_tasks`, `show_task` |
|
|
501
466
|
| **Environment** | `manage_environment_vars` |
|
|
502
|
-
| **Virtual Environments** | `create_virtualenv`, `install_requirements`, `list_virtualenvs`, `activate_virtualenv`, `remove_virtualenv` |
|
|
503
467
|
| **Web** | `fetch_web` |
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
468
|
+
|
|
469
|
+
When agents are configured, the `call_agent` tool is also registered so the main LLM can dispatch them (see [Multi-Agent System](#multi-agent-system)).
|
|
470
|
+
|
|
471
|
+
**Plugin tools** — `python_editor`, `dbs_tool`, `temporal_workflow`, virtualenv tools, and MCP integrations ship as optional plugins in the [ayder/ayder-plugins](https://github.com/ayder/ayder-plugins) repo (see [Plugins](#plugins)). Once installed they are auto-discovered exactly like built-ins.
|
|
507
472
|
|
|
508
473
|
## Multi-Agent System
|
|
509
474
|
|
|
@@ -25,39 +25,11 @@ Most AI coding assistants require cloud APIs, subscriptions, or heavy IDE plugin
|
|
|
25
25
|
- **Agentic workflow** -- the LLM reads files, edits code, runs shell commands, and iterates autonomously with configurable iteration limits per message.
|
|
26
26
|
- **Multi-agent** -- define specialized sub-agents in `config.toml`. Each agent runs independently with its own LLM, model, and context. Results are injected back into the main conversation when complete.
|
|
27
27
|
- **Textual TUI** -- an inline terminal interface with chat view, tool panel, thinking block toggle, slash command auto-completion, permission toggles, and tool confirmation modals with diff previews.
|
|
28
|
-
- **
|
|
29
|
-
|
|
30
|
-
### Tested Providers with Models
|
|
31
|
-
|
|
32
|
-
| Provider | Location | Model |
|
|
33
|
-
| -------- | -------- | ----- |
|
|
34
|
-
| ollama | Cloud | deepseek-v3.2:cloud |
|
|
35
|
-
| ollama | Cloud | gemini-3-pro-preview:latest |
|
|
36
|
-
| ollama | Local | glm-4.7-flash:latest |
|
|
37
|
-
| ollama | Cloud | glm-4.7:cloud |
|
|
38
|
-
| ollama | Cloud | glm-5:cloud |
|
|
39
|
-
| ollama | Local | glm-ocr:latest |
|
|
40
|
-
| ollama | Cloud | gpt-oss:120b-cloud |
|
|
41
|
-
| ollama | Cloud | kimi-k2.5:cloud |
|
|
42
|
-
| ollama | Cloud | minimax-m2.5:cloud |
|
|
43
|
-
| ollama | Local | ministral-3:14b |
|
|
44
|
-
| ollama | Cloud | qwen3-coder-next:cloud |
|
|
45
|
-
| ollama | Cloud | qwen3-coder:480b-cloud |
|
|
46
|
-
| ollama | Local | qwen3-coder:latest |
|
|
47
|
-
| anthropic | Cloud | claude-opus-4-6 |
|
|
48
|
-
| anthropic | Cloud | claude-sonnet-4-5-20250929 |
|
|
49
|
-
| anthropic | Cloud | claude-haiku-4-5-20251001 |
|
|
50
|
-
| openai | Cloud | GPT-5.3-Codex |
|
|
51
|
-
| openai | Cloud | GPT-5.3-Codex-Spark |
|
|
52
|
-
| openai | Cloud | GPT-5.2 |
|
|
53
|
-
| openai | Cloud | GPT-5 |
|
|
54
|
-
| gemini | Cloud | gemini-3-deep-think |
|
|
55
|
-
| gemini | Cloud | gemini-3-pro |
|
|
56
|
-
| gemini | Cloud | gemini-3-flash |
|
|
28
|
+
- **Batteries included** -- the OpenAI, Anthropic, Google, and Ollama SDKs all ship with ayder-cli, so every provider works out of the box. The terminal UI is built on Rich and Textual.
|
|
57
29
|
|
|
58
30
|
### Tools
|
|
59
31
|
|
|
60
|
-
LLMs on their own can only generate text. To be a useful coding assistant, the model needs to *act* on your codebase. ayder-cli
|
|
32
|
+
LLMs on their own can only generate text. To be a useful coding assistant, the model needs to *act* on your codebase. ayder-cli ships 16 built-in tools that the model can call, plus optional plugin toolsets (see [Plugins](#plugins)):
|
|
61
33
|
|
|
62
34
|
Each tool has an OpenAI-compatible JSON schema so models that support function calling can use them natively. For models that don't, ayder-cli also parses a custom XML-like syntax (`<function=name><parameter=key>value</parameter></function>`) as a fallback.
|
|
63
35
|
|
|
@@ -105,26 +77,16 @@ export OLLAMA_FLASH_ATTENTION=true
|
|
|
105
77
|
export OLLAMA_MAX_LOADED_MODELS=1
|
|
106
78
|
```
|
|
107
79
|
|
|
108
|
-
### Anthropic
|
|
80
|
+
### Cloud providers (Anthropic, OpenAI, Gemini)
|
|
109
81
|
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
# Set your API key in ~/.ayder/config.toml (see Configuration below)
|
|
115
|
-
# Then switch provider:
|
|
116
|
-
# /provider anthropic
|
|
117
|
-
```
|
|
118
|
-
|
|
119
|
-
### Gemini setup (optional)
|
|
82
|
+
The Anthropic, OpenAI, and Google SDKs ship with ayder-cli — no extra installs.
|
|
83
|
+
Just add an API key to a profile in `~/.ayder/config.toml` (see Configuration
|
|
84
|
+
below) and switch provider in the TUI:
|
|
120
85
|
|
|
121
86
|
```bash
|
|
122
|
-
#
|
|
123
|
-
pip install google-generativeai
|
|
87
|
+
/provider anthropic # or: openai, gemini
|
|
124
88
|
```
|
|
125
89
|
|
|
126
|
-
Set your API key in `~/.ayder/config.toml`, then switch provider: `/provider gemini`
|
|
127
|
-
|
|
128
90
|
### Configuration: Profiles and Drivers
|
|
129
91
|
|
|
130
92
|
ayder-cli uses a flexible profile-based configuration system. On the first run, it creates a config file at `~/.ayder/config.toml`.
|
|
@@ -189,7 +151,7 @@ rotation = "10 MB"
|
|
|
189
151
|
retention = "7 days"
|
|
190
152
|
|
|
191
153
|
[context_manager]
|
|
192
|
-
enabled =
|
|
154
|
+
enabled = true
|
|
193
155
|
max_context_tokens = 8192
|
|
194
156
|
|
|
195
157
|
[temporal]
|
|
@@ -287,12 +249,14 @@ ayder --implement-all
|
|
|
287
249
|
|
|
288
250
|
By default, every tool call requires user confirmation. Use permission flags to auto-approve tool categories:
|
|
289
251
|
|
|
290
|
-
| Flag | Category |
|
|
291
|
-
| ---- | -------- |
|
|
292
|
-
| `-r` | Read | `file_explorer`, `read_file`, `search_codebase`, `get_project_structure`, `
|
|
293
|
-
| `-w` | Write | `file_editor`, `
|
|
294
|
-
| `-x` | Execute | `run_shell_command`, `run_background_process`, `kill_background_process
|
|
295
|
-
| `--http` | Web/Network | `fetch_web
|
|
252
|
+
| Flag | Category | Built-in tools |
|
|
253
|
+
| ---- | -------- | -------------- |
|
|
254
|
+
| `-r` | Read | `file_explorer`, `read_file`, `search_codebase`, `get_project_structure`, `get_background_output`, `list_background_processes`, `list_tasks`, `show_task` |
|
|
255
|
+
| `-w` | Write | `file_editor`, `context`, `create_note`, `manage_environment_vars` |
|
|
256
|
+
| `-x` | Execute | `run_shell_command`, `run_background_process`, `kill_background_process` |
|
|
257
|
+
| `--http` | Web/Network | `fetch_web` |
|
|
258
|
+
|
|
259
|
+
Installed plugins extend these categories (e.g. `python_editor` → write, virtualenv tools → execute, `dbs_tool` → web).
|
|
296
260
|
|
|
297
261
|
```bash
|
|
298
262
|
# Auto-approve read-only tools
|
|
@@ -341,7 +305,7 @@ The context manager is configured under `[context_manager]` in `config.toml`:
|
|
|
341
305
|
| `max_tool_result_length` | `2048` | Maximum character length for a compressed tool result. |
|
|
342
306
|
| `compress_tool_results` | `true` | Enable automatic tool result compression. |
|
|
343
307
|
|
|
344
|
-
You can also manually manage context with `/save-
|
|
308
|
+
You can also manually manage context with the `context` tool and its slash-command shortcuts: `/save-context`, `/load-context`, `/list-contexts`, `/context-stats`, and `/compact`.
|
|
345
309
|
|
|
346
310
|
### Slash Commands
|
|
347
311
|
|
|
@@ -361,9 +325,11 @@ You can also manually manage context with `/save-memory`, `/load-memory`, and `/
|
|
|
361
325
|
| `/skill` | Activate a domain skill from `.ayder/skills/` |
|
|
362
326
|
| `/verbose` | Toggle verbose mode |
|
|
363
327
|
| `/logging` | Set log level for current session (NONE, ERROR, WARNING, INFO, DEBUG) |
|
|
364
|
-
| `/compact` | Summarize conversation, save
|
|
365
|
-
| `/save-
|
|
366
|
-
| `/load-
|
|
328
|
+
| `/compact` | Summarize conversation, save a context snapshot, clear, and reload |
|
|
329
|
+
| `/save-context` | Summarize conversation and save it to a named context slot (no clear) |
|
|
330
|
+
| `/load-context` | Load a saved context slot and restore it |
|
|
331
|
+
| `/list-contexts` | List saved context slots |
|
|
332
|
+
| `/context-stats` | Show current token and KV-cache usage |
|
|
367
333
|
| `/archive-completed-tasks` | Move completed tasks to `.ayder/task_archive/` |
|
|
368
334
|
| `/temporal` | Start/status Temporal queue worker |
|
|
369
335
|
| `/agent list` | List configured agents and their current status |
|
|
@@ -407,7 +373,7 @@ The standard mode for general coding and chat. Uses the system prompt.
|
|
|
407
373
|
> create a fibonacci function
|
|
408
374
|
```
|
|
409
375
|
|
|
410
|
-
Available tools:
|
|
376
|
+
Available tools: file read/write, shell commands, search, context, notes, tasks.
|
|
411
377
|
|
|
412
378
|
### Planning Mode (`/plan`)
|
|
413
379
|
|
|
@@ -457,24 +423,23 @@ The tool system:
|
|
|
457
423
|
- Supports tag-based filtering for dynamic enable/disable
|
|
458
424
|
- Injects tool-specific system prompts when enabled
|
|
459
425
|
|
|
460
|
-
**
|
|
426
|
+
**Built-in tools (16):**
|
|
461
427
|
|
|
462
428
|
| Category | Tools |
|
|
463
429
|
|----------|-------|
|
|
464
430
|
| **Filesystem** | `file_explorer`, `read_file`, `file_editor` |
|
|
465
431
|
| **Search** | `search_codebase`, `get_project_structure` |
|
|
466
432
|
| **Shell** | `run_shell_command` |
|
|
467
|
-
| **
|
|
468
|
-
| **Memory** | `save_memory`, `load_memory` |
|
|
433
|
+
| **Context** | `context` (save / load / list / stats / clear session context slots) |
|
|
469
434
|
| **Notes** | `create_note` |
|
|
470
435
|
| **Background Processes** | `run_background_process`, `get_background_output`, `kill_background_process`, `list_background_processes` |
|
|
471
436
|
| **Tasks** | `list_tasks`, `show_task` |
|
|
472
437
|
| **Environment** | `manage_environment_vars` |
|
|
473
|
-
| **Virtual Environments** | `create_virtualenv`, `install_requirements`, `list_virtualenvs`, `activate_virtualenv`, `remove_virtualenv` |
|
|
474
438
|
| **Web** | `fetch_web` |
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
439
|
+
|
|
440
|
+
When agents are configured, the `call_agent` tool is also registered so the main LLM can dispatch them (see [Multi-Agent System](#multi-agent-system)).
|
|
441
|
+
|
|
442
|
+
**Plugin tools** — `python_editor`, `dbs_tool`, `temporal_workflow`, virtualenv tools, and MCP integrations ship as optional plugins in the [ayder/ayder-plugins](https://github.com/ayder/ayder-plugins) repo (see [Plugins](#plugins)). Once installed they are auto-discovered exactly like built-ins.
|
|
478
443
|
|
|
479
444
|
## Multi-Agent System
|
|
480
445
|
|
|
@@ -219,7 +219,7 @@ cli.py:main()
|
|
|
219
219
|
| `tui/adapter.py` | Adapter glue between `AyderApp` and `ChatLoop` | callback wiring helpers |
|
|
220
220
|
| `tui/commands.py` | Slash command handlers | `COMMAND_MAP`, `handle_*()` |
|
|
221
221
|
| `tui/widgets.py` | Custom widgets | `ChatView`, `ToolPanel`, `CLIInputBar`, `StatusBar`, `AutoCompleteInput` |
|
|
222
|
-
| `tui/screens.py` | Modal screens | `CLIConfirmScreen`, `CLIHelpScreen`, `CLIPermissionScreen`, `CLISafeModeScreen`, `CLISelectScreen`, `TaskEditScreen` |
|
|
222
|
+
| `tui/screens.py` | Modal screens | `AgentListScreen`, `CLIConfirmScreen`, `CLIHelpScreen`, `CLIMultiSelectScreen`, `CLIPermissionScreen`, `CLISafeModeScreen`, `CLISelectScreen`, `TaskEditScreen` |
|
|
223
223
|
| `tui/parser.py` | TUI-specific parsing | `content_processor()` |
|
|
224
224
|
| `tui/helpers.py` | UI helpers | `create_tui_banner()` |
|
|
225
225
|
| `tui/keybindings.py` | Keybinding declarations | `BINDINGS` |
|
|
@@ -289,7 +289,7 @@ the design rationale.
|
|
|
289
289
|
| `tools/builtins/filesystem.py` | File system tool impls | `file_explorer()`, `read_file()`, `file_editor()` |
|
|
290
290
|
| `tools/builtins/search.py` | Search tool impls | `search_codebase()`, `get_project_structure()` |
|
|
291
291
|
| `tools/builtins/shell.py` | Shell execution impl | `run_shell_command()` |
|
|
292
|
-
| `tools/builtins/
|
|
292
|
+
| `tools/builtins/context.py` | Session context snapshots | `context` |
|
|
293
293
|
| `tools/builtins/notes.py` | Note-taking tool | `create_note()` |
|
|
294
294
|
| `tools/builtins/tasks.py` | Task-management tools | `list_tasks()`, `show_task()` |
|
|
295
295
|
| `tools/builtins/web.py` | HTTP fetch tool | `fetch_web()` |
|
|
@@ -642,11 +642,11 @@ Schema-driven tool definitions with auto-discovery:
|
|
|
642
642
|
- **Schema generation**: `to_openai_schema()` returns the OpenAI function-calling dict
|
|
643
643
|
- **Plugin loading**: `tools/plugin_manager.py` can augment `TOOL_DEFINITIONS` at runtime from local or GitHub-sourced plugins
|
|
644
644
|
|
|
645
|
-
|
|
645
|
+
16 built-in tools across 9 definition files:
|
|
646
646
|
- Filesystem (3): `file_explorer`, `read_file`, `file_editor`
|
|
647
647
|
- Search (2): `search_codebase`, `get_project_structure`
|
|
648
648
|
- Shell (1): `run_shell_command`
|
|
649
|
-
-
|
|
649
|
+
- Context (1): `context`
|
|
650
650
|
- Notes (1): `create_note`
|
|
651
651
|
- Background Processes (4): `run_background_process`, `get_background_output`, `kill_background_process`, `list_background_processes`
|
|
652
652
|
- Tasks (2): `list_tasks`, `show_task`
|
|
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "ayder-cli"
|
|
7
|
-
version = "1.
|
|
7
|
+
version = "1.8.3"
|
|
8
8
|
description = "AI agent for any LLMs"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.12"
|
|
@@ -23,7 +23,7 @@ dependencies = [
|
|
|
23
23
|
"openai",
|
|
24
24
|
"anthropic",
|
|
25
25
|
"google-genai",
|
|
26
|
-
"ollama>=0.6.
|
|
26
|
+
"ollama>=0.6.2",
|
|
27
27
|
"loguru",
|
|
28
28
|
"httpx",
|
|
29
29
|
"rich>=13.0.0",
|
|
@@ -41,6 +41,7 @@ class AgentCallbacks:
|
|
|
41
41
|
self._cancel_event = cancel_event
|
|
42
42
|
self._on_progress = on_progress
|
|
43
43
|
self.last_content: str = ""
|
|
44
|
+
self.last_system_error: str | None = None
|
|
44
45
|
|
|
45
46
|
def _emit(self, event: str, data: Any = None) -> None:
|
|
46
47
|
if self._on_progress:
|
|
@@ -87,6 +88,11 @@ class AgentCallbacks:
|
|
|
87
88
|
self._emit("tools_cleanup")
|
|
88
89
|
|
|
89
90
|
def on_system_message(self, text: str) -> None:
|
|
91
|
+
# ChatLoop reports stream/tool failures here. Capture them so the
|
|
92
|
+
# runner can promote them into AgentSummary.error instead of returning
|
|
93
|
+
# a misleading "completed" status with no content.
|
|
94
|
+
if isinstance(text, str) and text.lstrip().lower().startswith("error"):
|
|
95
|
+
self.last_system_error = text
|
|
90
96
|
self._emit("system_message", text)
|
|
91
97
|
|
|
92
98
|
async def request_confirmation(
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
"""AgentConfig — Pydantic model for agent definitions."""
|
|
2
|
+
|
|
3
|
+
from typing import Any
|
|
4
|
+
|
|
5
|
+
from pydantic import BaseModel, ConfigDict, model_validator
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class AgentConfig(BaseModel):
|
|
9
|
+
"""Configuration for a single agent, parsed from [agents.<name>] TOML sections.
|
|
10
|
+
|
|
11
|
+
Connection-level fields (base_url, api_key, num_ctx, temperature, think,
|
|
12
|
+
driver) are optional; when set they override the values pulled from the
|
|
13
|
+
parent provider profile. This lets one agent target an entirely different
|
|
14
|
+
endpoint than the main session without needing a separate [llm.<name>]
|
|
15
|
+
profile.
|
|
16
|
+
"""
|
|
17
|
+
|
|
18
|
+
model_config = ConfigDict(frozen=True, extra="forbid")
|
|
19
|
+
|
|
20
|
+
name: str
|
|
21
|
+
provider: str | None = None
|
|
22
|
+
model: str | None = None
|
|
23
|
+
system_prompt: str = ""
|
|
24
|
+
|
|
25
|
+
base_url: str | None = None
|
|
26
|
+
api_key: str | None = None
|
|
27
|
+
driver: str | None = None
|
|
28
|
+
num_ctx: int | None = None
|
|
29
|
+
temperature: float | None = None
|
|
30
|
+
max_output_tokens: int | None = None
|
|
31
|
+
think: str | None = None
|
|
32
|
+
|
|
33
|
+
@model_validator(mode="before")
|
|
34
|
+
@classmethod
|
|
35
|
+
def _coerce_aliases(cls, data: Any) -> Any:
|
|
36
|
+
"""Accept ``thinking`` as an alias for ``think`` and coerce numeric strings."""
|
|
37
|
+
if not isinstance(data, dict):
|
|
38
|
+
return data
|
|
39
|
+
new_data = dict(data)
|
|
40
|
+
if "thinking" in new_data and "think" not in new_data:
|
|
41
|
+
new_data["think"] = new_data.pop("thinking")
|
|
42
|
+
for key in ("temperature",):
|
|
43
|
+
val = new_data.get(key)
|
|
44
|
+
if isinstance(val, str) and val.strip():
|
|
45
|
+
try:
|
|
46
|
+
new_data[key] = float(val)
|
|
47
|
+
except ValueError:
|
|
48
|
+
pass
|
|
49
|
+
for key in ("num_ctx", "max_output_tokens"):
|
|
50
|
+
val = new_data.get(key)
|
|
51
|
+
if isinstance(val, str) and val.strip():
|
|
52
|
+
try:
|
|
53
|
+
new_data[key] = int(val)
|
|
54
|
+
except ValueError:
|
|
55
|
+
pass
|
|
56
|
+
return new_data
|
|
57
|
+
|
|
58
|
+
def overrides(self) -> dict[str, Any]:
|
|
59
|
+
"""Return non-None connection-level fields suitable for cfg.model_copy()."""
|
|
60
|
+
out: dict[str, Any] = {}
|
|
61
|
+
for field in (
|
|
62
|
+
"model",
|
|
63
|
+
"base_url",
|
|
64
|
+
"api_key",
|
|
65
|
+
"driver",
|
|
66
|
+
"num_ctx",
|
|
67
|
+
"temperature",
|
|
68
|
+
"max_output_tokens",
|
|
69
|
+
"think",
|
|
70
|
+
):
|
|
71
|
+
value = getattr(self, field)
|
|
72
|
+
if value is not None:
|
|
73
|
+
out[field] = value
|
|
74
|
+
return out
|
|
@@ -79,39 +79,42 @@ class AgentRegistry:
|
|
|
79
79
|
"""Count of currently active instances of the named agent."""
|
|
80
80
|
return sum(1 for r in self._active.values() if r.agent_name == name)
|
|
81
81
|
|
|
82
|
+
def list_agents(self) -> list[dict[str, Any]]:
|
|
83
|
+
"""Return configured agents with live status information."""
|
|
84
|
+
parent_model = getattr(self._parent_config, "model", None)
|
|
85
|
+
agents: list[dict[str, Any]] = []
|
|
86
|
+
for name, cfg in self.agents.items():
|
|
87
|
+
description = cfg.system_prompt[:200] if cfg.system_prompt else ""
|
|
88
|
+
resolved_model = cfg.model or parent_model
|
|
89
|
+
model = resolved_model if isinstance(resolved_model, str) else ""
|
|
90
|
+
agents.append({
|
|
91
|
+
"name": name,
|
|
92
|
+
"description": description,
|
|
93
|
+
"model": model,
|
|
94
|
+
"status": self.get_status(name) or "unknown",
|
|
95
|
+
"running_count": self.get_running_count(name),
|
|
96
|
+
})
|
|
97
|
+
return agents
|
|
98
|
+
|
|
82
99
|
def get_capability_prompts(self) -> str:
|
|
83
|
-
"""Generate capability
|
|
100
|
+
"""Generate generic agent capability guidance for the system prompt."""
|
|
84
101
|
if not self.agents:
|
|
85
102
|
return ""
|
|
86
103
|
|
|
87
|
-
agent_names = list(self.agents.keys())
|
|
88
|
-
|
|
89
104
|
lines = [
|
|
90
|
-
"\n##
|
|
91
|
-
"",
|
|
92
|
-
"You have specialized agents available. To use them, call the `call_agent` tool",
|
|
93
|
-
f"with the `name` parameter set to one of: {', '.join(repr(n) for n in agent_names)}.",
|
|
105
|
+
"\n## Agent Delegation",
|
|
94
106
|
"",
|
|
107
|
+
"Configured specialized agents may be available.",
|
|
108
|
+
"Use the `list_agents` tool to discover exact names and descriptions before `call_agent`.",
|
|
95
109
|
"Each agent runs in the background with its own LLM and tools.",
|
|
96
110
|
"You will receive the agent's summary when it completes.",
|
|
97
|
-
"",
|
|
98
|
-
"When asked to list agents, list the names below — do NOT search the codebase.",
|
|
99
|
-
"",
|
|
100
|
-
]
|
|
101
|
-
for name, cfg in self.agents.items():
|
|
102
|
-
provider = cfg.provider or "(inherited)"
|
|
103
|
-
model = cfg.model or "(inherited)"
|
|
104
|
-
desc = cfg.system_prompt[:150] if cfg.system_prompt else "(no description)"
|
|
105
|
-
lines.append(f"- **{name}** (provider: {provider}, model: {model}): {desc}")
|
|
106
|
-
|
|
107
|
-
lines.extend([
|
|
108
111
|
"",
|
|
109
112
|
"**Usage rules:**",
|
|
110
113
|
"- You CAN dispatch the same agent multiple times with different tasks.",
|
|
111
114
|
"- Only use the agent whose specialty matches the task. Do NOT use unrelated agents.",
|
|
112
115
|
"- Batch behavior: you will receive all agent summaries after all agents complete.",
|
|
113
116
|
"- On agent failure, handle the task yourself. Do NOT re-dispatch failed agents.",
|
|
114
|
-
]
|
|
117
|
+
]
|
|
115
118
|
|
|
116
119
|
return "\n".join(lines)
|
|
117
120
|
|
|
@@ -122,7 +125,17 @@ class AgentRegistry:
|
|
|
122
125
|
"""
|
|
123
126
|
if name not in self.agents:
|
|
124
127
|
logger.debug("dispatch rejected: agent '%s' not found", name)
|
|
125
|
-
|
|
128
|
+
available = ", ".join(sorted(self.agents))
|
|
129
|
+
if available:
|
|
130
|
+
return (
|
|
131
|
+
f"Error: Agent '{name}' not found. "
|
|
132
|
+
f"Available agents: {available}. "
|
|
133
|
+
f"Call list_agents for descriptions."
|
|
134
|
+
)
|
|
135
|
+
return (
|
|
136
|
+
f"Error: Agent '{name}' not found. "
|
|
137
|
+
f"No agents are configured. Call list_agents to verify availability."
|
|
138
|
+
)
|
|
126
139
|
# Re-dispatch guard: block agents that failed in this cycle
|
|
127
140
|
if name in self._settled and self._settled[name] in ("error", "timeout"):
|
|
128
141
|
logger.debug(
|
|
@@ -185,7 +198,19 @@ class AgentRegistry:
|
|
|
185
198
|
if self._loop is None:
|
|
186
199
|
self._active.pop(run_id, None)
|
|
187
200
|
return "Error: Agent registry not initialized (event loop not set)"
|
|
188
|
-
|
|
201
|
+
|
|
202
|
+
coro = _run_and_queue()
|
|
203
|
+
try:
|
|
204
|
+
asyncio.run_coroutine_threadsafe(coro, self._loop)
|
|
205
|
+
except Exception as exc:
|
|
206
|
+
# If scheduling fails (for example because the loop was closed),
|
|
207
|
+
# the coroutine object will never be awaited unless explicitly
|
|
208
|
+
# closed. Also remove the runner from active state so status does
|
|
209
|
+
# not remain stuck on "running".
|
|
210
|
+
coro.close()
|
|
211
|
+
self._active.pop(run_id, None)
|
|
212
|
+
logger.exception("failed to schedule agent run: agent='%s' run_id=%d", name, run_id)
|
|
213
|
+
return f"Error: Failed to schedule agent '{name}': {exc}"
|
|
189
214
|
|
|
190
215
|
return run_id
|
|
191
216
|
|
|
@@ -139,6 +139,23 @@ class AgentRunner:
|
|
|
139
139
|
error=f"Agent exceeded {self._timeout}s timeout",
|
|
140
140
|
)
|
|
141
141
|
|
|
142
|
+
# ChatLoop swallows stream/tool failures via on_system_message
|
|
143
|
+
# and returns normally. Promote any captured error into a real
|
|
144
|
+
# error AgentSummary so callers see the cause instead of a
|
|
145
|
+
# placeholder "completed with no summary".
|
|
146
|
+
if callbacks.last_system_error and not callbacks.last_content.strip():
|
|
147
|
+
self.status = "error"
|
|
148
|
+
logger.debug(
|
|
149
|
+
"run failed (captured via on_system_message): agent='%s' run_id=%d error='%s'",
|
|
150
|
+
self.agent_name, self.run_id, callbacks.last_system_error[:200],
|
|
151
|
+
)
|
|
152
|
+
return AgentSummary(
|
|
153
|
+
agent_name=self.agent_name,
|
|
154
|
+
status="error",
|
|
155
|
+
summary="Agent failed before producing output.",
|
|
156
|
+
error=callbacks.last_system_error,
|
|
157
|
+
)
|
|
158
|
+
|
|
142
159
|
# Completed successfully
|
|
143
160
|
self.status = "completed"
|
|
144
161
|
summary_text = self._parse_summary(callbacks.last_content)
|