ayder-cli 2.4.1__tar.gz → 2.5.0__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.4.1 → ayder_cli-2.5.0}/PKG-INFO +45 -6
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/README.md +44 -5
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/docs/GATE.md +1 -1
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/docs/PROJECT_STRUCTURE.md +8 -2
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/docs/config.toml.example +6 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/pyproject.toml +1 -1
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/scripts/check_exception_handlers.py +1 -1
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/scripts/check_log_arguments.py +7 -7
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/scripts/log_argument_baseline.txt +5 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/src/ayder_cli/agents/config.py +10 -2
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/src/ayder_cli/application/runtime_factory.py +27 -12
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/src/ayder_cli/core/config.py +38 -1
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/src/ayder_cli/core/default_context_manager.py +73 -31
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/src/ayder_cli/core/ollama_context_manager.py +73 -6
- ayder_cli-2.5.0/src/ayder_cli/core/skills.py +498 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/src/ayder_cli/loops/chat_loop.py +4 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/src/ayder_cli/prompts.py +14 -106
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/src/ayder_cli/providers/impl/ollama_drivers/generic_xml.py +1 -1
- ayder_cli-2.5.0/src/ayder_cli/skills/engineering/SKILL.md +35 -0
- ayder_cli-2.5.0/src/ayder_cli/tools/builtins/skill.py +150 -0
- ayder_cli-2.5.0/src/ayder_cli/tools/builtins/skill_definitions.py +54 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/src/ayder_cli/tools/execution.py +4 -1
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/src/ayder_cli/tools/registry.py +25 -9
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/src/ayder_cli/tui/app.py +5 -66
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/src/ayder_cli/tui/commands.py +62 -45
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/tests/application/test_runtime_factory.py +7 -25
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/tests/conftest.py +16 -0
- ayder_cli-2.5.0/tests/core/test_config_skills.py +78 -0
- ayder_cli-2.5.0/tests/core/test_default_context_skill_resupply.py +178 -0
- ayder_cli-2.5.0/tests/core/test_ollama_skill_resupply.py +151 -0
- ayder_cli-2.5.0/tests/core/test_skills.py +237 -0
- ayder_cli-2.5.0/tests/core/test_skills_builtin_sync.py +147 -0
- ayder_cli-2.5.0/tests/providers/test_skill_load_prefix.py +90 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/tests/scripts/test_exception_gate.py +9 -5
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/tests/scripts/test_log_argument_gate.py +16 -16
- ayder_cli-2.5.0/tests/test_prompts_general.py +33 -0
- ayder_cli-2.5.0/tests/tools/test_skill_catalog_and_filter.py +182 -0
- ayder_cli-2.5.0/tests/tools/test_skill_scope_wiring.py +57 -0
- ayder_cli-2.5.0/tests/tools/test_skill_tool.py +178 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/tests/tui/test_turn_consumer.py +0 -66
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/tests/ui/test_tui_commands_provider.py +3 -0
- ayder_cli-2.5.0/tests/ui/test_tui_commands_skill.py +155 -0
- ayder_cli-2.5.0/tests/ui/test_tui_system_prompt_no_structure.py +44 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/uv.lock +1 -1
- ayder_cli-2.4.1/src/ayder_cli/tools/builtins/skill.py +0 -238
- ayder_cli-2.4.1/src/ayder_cli/tools/builtins/skill_definitions.py +0 -47
- ayder_cli-2.4.1/tests/tools/test_skill_tool.py +0 -220
- ayder_cli-2.4.1/tests/ui/test_tui_commands_skill.py +0 -116
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/.github/workflows/ci.yml +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/.github/workflows/python-package.yml +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/.gitignore +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/.python-version +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/AGENTS.md +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/LICENSE +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/docs/README_AGENT_WORKFLOW.md +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/docs/README_OLLAMA.md +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/docs/cc.png +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/docs/superpowers/plans/2026-06-26-file-editor-improvements.md +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/docs/superpowers/plans/2026-06-26-session-save-resume.md +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/docs/superpowers/specs/2026-06-26-file-editor-improvements-design.md +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/docs/superpowers/specs/2026-06-26-session-save-resume-design.md +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/scripts/check_logging_imports.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/scripts/exception_baseline.txt +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/scripts/find_percent_logging.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/scripts/logging_gates.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/src/ayder_cli/__init__.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/src/ayder_cli/__main__.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/src/ayder_cli/agents/__init__.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/src/ayder_cli/agents/callbacks.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/src/ayder_cli/agents/registry.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/src/ayder_cli/agents/run.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/src/ayder_cli/agents/runner.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/src/ayder_cli/agents/tool.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/src/ayder_cli/agents/worktree.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/src/ayder_cli/application/README.md +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/src/ayder_cli/application/__init__.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/src/ayder_cli/application/execution_policy.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/src/ayder_cli/application/message_contract.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/src/ayder_cli/application/validation.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/src/ayder_cli/cli.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/src/ayder_cli/cli_callbacks.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/src/ayder_cli/cli_runner.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/src/ayder_cli/console.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/src/ayder_cli/core/cache_monitor.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/src/ayder_cli/core/config_migration.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/src/ayder_cli/core/context.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/src/ayder_cli/core/context_manager.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/src/ayder_cli/core/context_manager_factory.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/src/ayder_cli/core/reasoning.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/src/ayder_cli/core/result.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/src/ayder_cli/core/session.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/src/ayder_cli/diagnostics.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/src/ayder_cli/log.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/src/ayder_cli/logging_config.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/src/ayder_cli/loops/__init__.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/src/ayder_cli/masking.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/src/ayder_cli/parser.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/src/ayder_cli/process_manager.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/src/ayder_cli/providers/__init__.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/src/ayder_cli/providers/base.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/src/ayder_cli/providers/evren.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/src/ayder_cli/providers/impl/claude.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/src/ayder_cli/providers/impl/deepseek.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/src/ayder_cli/providers/impl/gemini.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/src/ayder_cli/providers/impl/glm.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/src/ayder_cli/providers/impl/ollama.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/src/ayder_cli/providers/impl/ollama_drivers/__init__.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/src/ayder_cli/providers/impl/ollama_drivers/_errors.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/src/ayder_cli/providers/impl/ollama_drivers/base.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/src/ayder_cli/providers/impl/ollama_drivers/deepseek.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/src/ayder_cli/providers/impl/ollama_drivers/generic_native.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/src/ayder_cli/providers/impl/ollama_drivers/matrix.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/src/ayder_cli/providers/impl/ollama_drivers/minimax.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/src/ayder_cli/providers/impl/ollama_drivers/qwen3.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/src/ayder_cli/providers/impl/ollama_drivers/registry.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/src/ayder_cli/providers/impl/ollama_inspector.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/src/ayder_cli/providers/impl/openai.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/src/ayder_cli/providers/impl/qwen.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/src/ayder_cli/providers/orchestrator.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/src/ayder_cli/providers/retry.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/src/ayder_cli/services/__init__.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/src/ayder_cli/services/interactions.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/src/ayder_cli/services/messaging_inbox.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/src/ayder_cli/themes/__init__.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/src/ayder_cli/themes/ayder.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/src/ayder_cli/themes/claude.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/src/ayder_cli/tools/__init__.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/src/ayder_cli/tools/builtins/__init__.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/src/ayder_cli/tools/builtins/background_process_tool.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/src/ayder_cli/tools/builtins/context.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/src/ayder_cli/tools/builtins/context_definitions.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/src/ayder_cli/tools/builtins/filesystem.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/src/ayder_cli/tools/builtins/filesystem_definitions.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/src/ayder_cli/tools/builtins/note_tool.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/src/ayder_cli/tools/builtins/notes.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/src/ayder_cli/tools/builtins/notes_definitions.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/src/ayder_cli/tools/builtins/process_manager_definitions.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/src/ayder_cli/tools/builtins/search.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/src/ayder_cli/tools/builtins/search_definitions.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/src/ayder_cli/tools/builtins/shell.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/src/ayder_cli/tools/builtins/shell_definitions.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/src/ayder_cli/tools/builtins/task_definitions.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/src/ayder_cli/tools/builtins/task_tool.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/src/ayder_cli/tools/builtins/tasks.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/src/ayder_cli/tools/builtins/utils_tools.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/src/ayder_cli/tools/builtins/utils_tools_definitions.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/src/ayder_cli/tools/builtins/web.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/src/ayder_cli/tools/builtins/web_definitions.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/src/ayder_cli/tools/definition.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/src/ayder_cli/tools/hooks.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/src/ayder_cli/tools/mcp.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/src/ayder_cli/tools/mcp_client.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/src/ayder_cli/tools/normalization.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/src/ayder_cli/tools/plugin_api.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/src/ayder_cli/tools/plugin_github.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/src/ayder_cli/tools/plugin_manager.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/src/ayder_cli/tools/plugin_status.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/src/ayder_cli/tools/schemas.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/src/ayder_cli/tools/utils.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/src/ayder_cli/tui/__init__.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/src/ayder_cli/tui/adapter.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/src/ayder_cli/tui/helpers.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/src/ayder_cli/tui/keybindings.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/src/ayder_cli/tui/parser.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/src/ayder_cli/tui/rendering.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/src/ayder_cli/tui/screens.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/src/ayder_cli/tui/theme_manager.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/src/ayder_cli/tui/types.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/src/ayder_cli/tui/widgets.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/src/ayder_cli/ui.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/src/ayder_cli/version.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/tests/COVERAGE.md +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/tests/__init__.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/tests/agents/__init__.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/tests/agents/test_agent_consolidated.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/tests/agents/test_agent_severity.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/tests/agents/test_agent_tools.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/tests/agents/test_callbacks.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/tests/agents/test_config.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/tests/agents/test_integration.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/tests/agents/test_queue.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/tests/agents/test_registry.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/tests/agents/test_run.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/tests/agents/test_runner.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/tests/agents/test_runner_provider_unavailable.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/tests/agents/test_tool.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/tests/agents/test_worktree_helpers.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/tests/agents/test_worktree_isolation.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/tests/application/test_argument_canonicalization.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/tests/application/test_execution_result_truthfulness.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/tests/application/test_message_contract.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/tests/client/test_main.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/tests/convergence/__init__.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/tests/convergence/test_execution_policy_parity.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/tests/convergence/test_runtime_wiring.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/tests/convergence/test_validation_path.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/tests/core/test_asyncio_bridge.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/tests/core/test_cache_monitor.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/tests/core/test_config.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/tests/core/test_config_coverage.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/tests/core/test_config_migration.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/tests/core/test_config_provider_logging.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/tests/core/test_config_retry.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/tests/core/test_config_v2.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/tests/core/test_context_manager_factory.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/tests/core/test_default_config_evren.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/tests/core/test_default_context_manager.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/tests/core/test_default_context_manager_should_compact.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/tests/core/test_default_context_newest_unit.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/tests/core/test_event_emission.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/tests/core/test_event_stream.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/tests/core/test_exception_guarantee.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/tests/core/test_exception_hooks.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/tests/core/test_log_facade.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/tests/core/test_logging_config_keys.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/tests/core/test_logging_sinks.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/tests/core/test_loguru_caplog.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/tests/core/test_max_output_tokens_default.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/tests/core/test_ollama_compaction_persistence.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/tests/core/test_ollama_context_manager.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/tests/core/test_ollama_context_manager_cache_monitor.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/tests/core/test_ollama_context_manager_max_history.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/tests/core/test_parameter_aliasing.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/tests/core/test_parser.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/tests/core/test_reasoning_config.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/tests/core/test_session.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/tests/core/test_session_id_threading.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/tests/core/test_sink_masking.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/tests/loops/__init__.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/tests/loops/test_base.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/tests/loops/test_chat_loop_hook.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/tests/loops/test_chat_loop_tool_truncation.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/tests/loops/test_loop_severity.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/tests/loops/test_required_args_aliases.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/tests/loops/test_tool_argument_integrity.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/tests/loops/test_tool_batch_cancellation.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/tests/providers/__init__.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/tests/providers/ollama_drivers/__init__.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/tests/providers/ollama_drivers/test_base.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/tests/providers/ollama_drivers/test_deepseek.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/tests/providers/ollama_drivers/test_errors.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/tests/providers/ollama_drivers/test_fallback.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/tests/providers/ollama_drivers/test_generic_native.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/tests/providers/ollama_drivers/test_generic_xml.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/tests/providers/ollama_drivers/test_matrix.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/tests/providers/ollama_drivers/test_minimax.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/tests/providers/ollama_drivers/test_provider_integration.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/tests/providers/ollama_drivers/test_qwen3.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/tests/providers/ollama_drivers/test_registry.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/tests/providers/test_claude_stream_tool_calls.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/tests/providers/test_evren.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/tests/providers/test_gemini_function_calls.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/tests/providers/test_glm_async.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/tests/providers/test_ollama_inspector.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/tests/providers/test_ollama_native.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/tests/providers/test_ollama_parallel_tool_call_ids.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/tests/providers/test_ollama_xml.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/tests/providers/test_ollama_xml_autoroute.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/tests/providers/test_ollama_xml_usage.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/tests/providers/test_openai_list_models.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/tests/providers/test_orchestrator_capabilities.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/tests/providers/test_provider_channel_binding.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/tests/providers/test_provider_severity.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/tests/providers/test_qwen_async.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/tests/providers/test_reasoning_effort.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/tests/providers/test_retry_classifier.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/tests/providers/test_retry_integration.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/tests/providers/test_retrying_provider.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/tests/scripts/test_logging_policy_gates.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/tests/scripts/test_loguru_private_shape.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/tests/services/test_boundary.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/tests/services/test_interaction_sink.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/tests/services/test_messaging_inbox.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/tests/test_cli.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/tests/test_cli_callbacks.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/tests/test_context.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/tests/test_env_manager.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/tests/test_logging_config.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/tests/test_notes.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/tests/test_process_manager.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/tests/test_tasks.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/tests/tools/__init__.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/tests/tools/test_agent_notes.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/tests/tools/test_background_process_tool.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/tests/tools/test_bash_tool.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/tests/tools/test_context_storage_confinement.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/tests/tools/test_definition_discovery.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/tests/tools/test_di_injection.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/tests/tools/test_file_editor_hardening.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/tests/tools/test_file_editor_size_limit.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/tests/tools/test_impl.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/tests/tools/test_impl_coverage.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/tests/tools/test_mcp.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/tests/tools/test_mcp_client.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/tests/tools/test_note_tool.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/tests/tools/test_notes_api.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/tests/tools/test_notes_confinement.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/tests/tools/test_path_security.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/tests/tools/test_plugin_api.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/tests/tools/test_plugin_github.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/tests/tools/test_plugin_loading.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/tests/tools/test_plugin_manager.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/tests/tools/test_plugin_status.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/tests/tools/test_registry.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/tests/tools/test_registry_coverage.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/tests/tools/test_result.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/tests/tools/test_schemas.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/tests/tools/test_search_codebase.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/tests/tools/test_search_hardening.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/tests/tools/test_task_path_confinement.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/tests/tools/test_task_tool.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/tests/tools/test_tool_severity.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/tests/tools/test_unexpected_args.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/tests/tools/test_utils.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/tests/tools/test_web.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/tests/tui/__init__.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/tests/tui/test_agent_list_screen.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/tests/tui/test_do_clear_coordination.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/tests/tui/test_evren_terms.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/tests/tui/test_follow_mode.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/tests/tui/test_help_screen.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/tests/tui/test_input_box.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/tests/tui/test_keybindings.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/tests/tui/test_multi_select_screen.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/tests/tui/test_multiline_input.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/tests/tui/test_paste.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/tests/tui/test_peer_message_turn.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/tests/tui/test_pending_compact_consumer.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/tests/tui/test_pull_delivery.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/tests/tui/test_resume.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/tests/tui/test_status_bar_badges.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/tests/tui/test_themes.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/tests/tui/test_widgets.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/tests/ui/test_confirm_screen.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/tests/ui/test_diff_preview.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/tests/ui/test_plugin_autoenable.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/tests/ui/test_provider_switch.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/tests/ui/test_run_tui_startup.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/tests/ui/test_tui_assistant_sanitization.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/tests/ui/test_tui_chat_loop.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/tests/ui/test_tui_commands_agent.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/tests/ui/test_tui_commands_effort.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/tests/ui/test_tui_commands_logging.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/tests/ui/test_tui_commands_plugin.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/tests/ui/test_tui_helpers.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/tests/ui/test_tui_temporal_command.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/tests/ui/test_tui_widgets.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/tests/ui/test_ui.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/tests/ui/test_ui_coverage.py +0 -0
- {ayder_cli-2.4.1 → ayder_cli-2.5.0}/tests/ui/test_ui_verbose.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: ayder-cli
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.5.0
|
|
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
|
|
@@ -208,6 +208,7 @@ max_output_tokens = 32768 # Max tokens in LLM response
|
|
|
208
208
|
max_history_messages = 30 # Messages kept in history
|
|
209
209
|
prompt = "STANDARD" # System prompt tier: MINIMAL, STANDARD, EXTENDED
|
|
210
210
|
tool_tags = ["core", "metadata"] # Enabled tool tags (see /plugin)
|
|
211
|
+
# skills = ["engineering"] # or "none"; default: the built-in skills
|
|
211
212
|
agent_timeout = 300 # Seconds before a background agent is cancelled
|
|
212
213
|
|
|
213
214
|
[logging]
|
|
@@ -353,7 +354,7 @@ ayder -f instructions.txt
|
|
|
353
354
|
ayder --stdin < prompt.txt
|
|
354
355
|
|
|
355
356
|
# Override the main LLM system prompt with a file
|
|
356
|
-
# (tool instructions
|
|
357
|
+
# (tool instructions are still appended)
|
|
357
358
|
ayder --system-prompt prompt-file.md "refactor this code"
|
|
358
359
|
```
|
|
359
360
|
|
|
@@ -452,7 +453,7 @@ You can also manually manage context with the `context` tool and its slash-comma
|
|
|
452
453
|
| `/tasks` | Browse and implement tasks from `.ayder/tasks/` |
|
|
453
454
|
| `/implement [id]` | Interactive task picker, or implement by ID (e.g., `/implement 1`) |
|
|
454
455
|
| `/notes` | Browse and edit markdown notes |
|
|
455
|
-
| `/skill` |
|
|
456
|
+
| `/skill` | Load a skill as a user message: `/skill <name> [request]`, or pick one |
|
|
456
457
|
| `/verbose` | Toggle verbose mode |
|
|
457
458
|
| `/logging` | Set log level for current session (NONE, ERROR, WARNING, INFO, DEBUG, TRACE) |
|
|
458
459
|
| `/compact` | Summarize conversation, save a context snapshot, clear, and reload |
|
|
@@ -466,10 +467,47 @@ You can also manually manage context with the `context` tool and its slash-comma
|
|
|
466
467
|
| `/agent <name> <task>` | Dispatch an agent to run a task in the background |
|
|
467
468
|
| `/agent cancel <name>` | Cancel a running agent |
|
|
468
469
|
|
|
469
|
-
###
|
|
470
|
+
### Skills
|
|
471
|
+
|
|
472
|
+
A skill is a directory with a `SKILL.md` file, optionally starting with
|
|
473
|
+
`name:` and `description:` frontmatter. ayder looks in three places, and a
|
|
474
|
+
later one overrides an earlier one with the same name:
|
|
475
|
+
|
|
476
|
+
1. built-in skills in `~/.ayder/builtin/skills/`, managed by ayder and
|
|
477
|
+
replaced on upgrade; to customize one, copy it to `~/.ayder/skills/<name>/`
|
|
478
|
+
2. your skills in `~/.ayder/skills/<name>/`
|
|
479
|
+
3. project skills in `<project>/.ayder/skills/<name>/`
|
|
480
|
+
|
|
481
|
+
ayder ships an `engineering` skill (build, change, debug or review code;
|
|
482
|
+
research; plan multi-step work). The system prompt is a general assistant;
|
|
483
|
+
when a skill fits the request, the model loads it itself.
|
|
484
|
+
|
|
485
|
+
The skills enabled for a session are listed in the system prompt under
|
|
486
|
+
"### Skills" (name and description), and only those can be loaded by the
|
|
487
|
+
model. The `skills` setting chooses them:
|
|
488
|
+
|
|
489
|
+
| `skills` | Enabled skills |
|
|
490
|
+
|---|---|
|
|
491
|
+
| not set | the built-in skills (`engineering`), including your or the project's copy of the same name |
|
|
492
|
+
| `"none"` or `[]` | none: no skill tool, no catalog |
|
|
493
|
+
| `["a", "b"]` | exactly these names, from any layer |
|
|
494
|
+
|
|
495
|
+
The main session reads `[llm.<provider>].skills`, then `[app].skills`. An
|
|
496
|
+
agent reads `[agents.<name>].skills`, then its provider profile's; never
|
|
497
|
+
`[app]`. The `/skill` command loads any discovered skill, including project
|
|
498
|
+
skills that are not in the catalog.
|
|
499
|
+
|
|
500
|
+
The model loads one with `skill(action="load", name=...)`; the instructions
|
|
501
|
+
come back as the tool result, so the conversation's earlier messages (and the
|
|
502
|
+
provider's KV cache) are unchanged. Several skills can be active; other files
|
|
503
|
+
in a skill's directory are read on demand with `skill(action="read")`.
|
|
504
|
+
A skill directory or `SKILL.md` that links outside its skills directory is
|
|
505
|
+
listed but never read or loaded; copy the skill instead of symlinking it.
|
|
506
|
+
A loaded skill stays in context for the whole session: when trimming or
|
|
507
|
+
compaction removes it, ayder adds it back right after the system prompt, or
|
|
508
|
+
inside the Ollama summary.
|
|
470
509
|
|
|
471
|
-
|
|
472
|
-
automatically when a request clearly matches an available project skill.
|
|
510
|
+
### Logging
|
|
473
511
|
|
|
474
512
|
- Errors are always captured to `.ayder/log/errors.log`, even when
|
|
475
513
|
`logging_level` is `NONE`. Set `file_enabled = false` under `[logging]` to
|
|
@@ -670,6 +708,7 @@ Each agent field:
|
|
|
670
708
|
| `system_prompt` | Yes | The agent's role and instructions |
|
|
671
709
|
| `provider` | No | LLM provider profile name (inherits from `[app]` if omitted) |
|
|
672
710
|
| `model` | No | Model name override (inherits from provider profile if omitted) |
|
|
711
|
+
| `skills` | No | `"none"` or a list of skill names (inherits from the provider profile; default: the built-in skills) |
|
|
673
712
|
|
|
674
713
|
### Using Agents
|
|
675
714
|
|
|
@@ -165,6 +165,7 @@ max_output_tokens = 32768 # Max tokens in LLM response
|
|
|
165
165
|
max_history_messages = 30 # Messages kept in history
|
|
166
166
|
prompt = "STANDARD" # System prompt tier: MINIMAL, STANDARD, EXTENDED
|
|
167
167
|
tool_tags = ["core", "metadata"] # Enabled tool tags (see /plugin)
|
|
168
|
+
# skills = ["engineering"] # or "none"; default: the built-in skills
|
|
168
169
|
agent_timeout = 300 # Seconds before a background agent is cancelled
|
|
169
170
|
|
|
170
171
|
[logging]
|
|
@@ -310,7 +311,7 @@ ayder -f instructions.txt
|
|
|
310
311
|
ayder --stdin < prompt.txt
|
|
311
312
|
|
|
312
313
|
# Override the main LLM system prompt with a file
|
|
313
|
-
# (tool instructions
|
|
314
|
+
# (tool instructions are still appended)
|
|
314
315
|
ayder --system-prompt prompt-file.md "refactor this code"
|
|
315
316
|
```
|
|
316
317
|
|
|
@@ -409,7 +410,7 @@ You can also manually manage context with the `context` tool and its slash-comma
|
|
|
409
410
|
| `/tasks` | Browse and implement tasks from `.ayder/tasks/` |
|
|
410
411
|
| `/implement [id]` | Interactive task picker, or implement by ID (e.g., `/implement 1`) |
|
|
411
412
|
| `/notes` | Browse and edit markdown notes |
|
|
412
|
-
| `/skill` |
|
|
413
|
+
| `/skill` | Load a skill as a user message: `/skill <name> [request]`, or pick one |
|
|
413
414
|
| `/verbose` | Toggle verbose mode |
|
|
414
415
|
| `/logging` | Set log level for current session (NONE, ERROR, WARNING, INFO, DEBUG, TRACE) |
|
|
415
416
|
| `/compact` | Summarize conversation, save a context snapshot, clear, and reload |
|
|
@@ -423,10 +424,47 @@ You can also manually manage context with the `context` tool and its slash-comma
|
|
|
423
424
|
| `/agent <name> <task>` | Dispatch an agent to run a task in the background |
|
|
424
425
|
| `/agent cancel <name>` | Cancel a running agent |
|
|
425
426
|
|
|
426
|
-
###
|
|
427
|
+
### Skills
|
|
428
|
+
|
|
429
|
+
A skill is a directory with a `SKILL.md` file, optionally starting with
|
|
430
|
+
`name:` and `description:` frontmatter. ayder looks in three places, and a
|
|
431
|
+
later one overrides an earlier one with the same name:
|
|
432
|
+
|
|
433
|
+
1. built-in skills in `~/.ayder/builtin/skills/`, managed by ayder and
|
|
434
|
+
replaced on upgrade; to customize one, copy it to `~/.ayder/skills/<name>/`
|
|
435
|
+
2. your skills in `~/.ayder/skills/<name>/`
|
|
436
|
+
3. project skills in `<project>/.ayder/skills/<name>/`
|
|
437
|
+
|
|
438
|
+
ayder ships an `engineering` skill (build, change, debug or review code;
|
|
439
|
+
research; plan multi-step work). The system prompt is a general assistant;
|
|
440
|
+
when a skill fits the request, the model loads it itself.
|
|
441
|
+
|
|
442
|
+
The skills enabled for a session are listed in the system prompt under
|
|
443
|
+
"### Skills" (name and description), and only those can be loaded by the
|
|
444
|
+
model. The `skills` setting chooses them:
|
|
445
|
+
|
|
446
|
+
| `skills` | Enabled skills |
|
|
447
|
+
|---|---|
|
|
448
|
+
| not set | the built-in skills (`engineering`), including your or the project's copy of the same name |
|
|
449
|
+
| `"none"` or `[]` | none: no skill tool, no catalog |
|
|
450
|
+
| `["a", "b"]` | exactly these names, from any layer |
|
|
451
|
+
|
|
452
|
+
The main session reads `[llm.<provider>].skills`, then `[app].skills`. An
|
|
453
|
+
agent reads `[agents.<name>].skills`, then its provider profile's; never
|
|
454
|
+
`[app]`. The `/skill` command loads any discovered skill, including project
|
|
455
|
+
skills that are not in the catalog.
|
|
456
|
+
|
|
457
|
+
The model loads one with `skill(action="load", name=...)`; the instructions
|
|
458
|
+
come back as the tool result, so the conversation's earlier messages (and the
|
|
459
|
+
provider's KV cache) are unchanged. Several skills can be active; other files
|
|
460
|
+
in a skill's directory are read on demand with `skill(action="read")`.
|
|
461
|
+
A skill directory or `SKILL.md` that links outside its skills directory is
|
|
462
|
+
listed but never read or loaded; copy the skill instead of symlinking it.
|
|
463
|
+
A loaded skill stays in context for the whole session: when trimming or
|
|
464
|
+
compaction removes it, ayder adds it back right after the system prompt, or
|
|
465
|
+
inside the Ollama summary.
|
|
427
466
|
|
|
428
|
-
|
|
429
|
-
automatically when a request clearly matches an available project skill.
|
|
467
|
+
### Logging
|
|
430
468
|
|
|
431
469
|
- Errors are always captured to `.ayder/log/errors.log`, even when
|
|
432
470
|
`logging_level` is `NONE`. Set `file_enabled = false` under `[logging]` to
|
|
@@ -627,6 +665,7 @@ Each agent field:
|
|
|
627
665
|
| `system_prompt` | Yes | The agent's role and instructions |
|
|
628
666
|
| `provider` | No | LLM provider profile name (inherits from `[app]` if omitted) |
|
|
629
667
|
| `model` | No | Model name override (inherits from provider profile if omitted) |
|
|
668
|
+
| `skills` | No | `"none"` or a list of skill names (inherits from the provider profile; default: the built-in skills) |
|
|
630
669
|
|
|
631
670
|
### Using Agents
|
|
632
671
|
|
|
@@ -12,7 +12,7 @@ Input: the candidate SHA.
|
|
|
12
12
|
gates and the test suite, and stops at the first failing task.
|
|
13
13
|
4. Copy the final pytest summary line (`=== N passed, M skipped in …s ===`) verbatim.
|
|
14
14
|
|
|
15
|
-
Last measured: `
|
|
15
|
+
Last measured: `2707 passed, 2 skipped` on `chore/prompt-tests-injection-only` (2026-10-16).
|
|
16
16
|
|
|
17
17
|
## Report format
|
|
18
18
|
|
|
@@ -72,6 +72,7 @@ ayder-cli is an AI agent chat client with a modular, layered architecture:
|
|
|
72
72
|
│ core/config.py (Pydantic Config) │
|
|
73
73
|
│ core/context.py (ProjectContext, sandboxing) │
|
|
74
74
|
│ core/result.py (ToolSuccess, ToolError) │
|
|
75
|
+
│ core/skills.py (skill discovery, delivery) │
|
|
75
76
|
│ core/context_manager.py (ContextManagerProtocol) │
|
|
76
77
|
│ core/default_context_manager.py │
|
|
77
78
|
│ core/ollama_context_manager.py (KV-cache-aware) │
|
|
@@ -154,6 +155,8 @@ cli.py:main()
|
|
|
154
155
|
| `core/config_migration.py` | TOML config migration helpers | migration routines for schema changes |
|
|
155
156
|
| `core/context.py` | Project sandboxing | `ProjectContext` |
|
|
156
157
|
| `core/result.py` | Tool result types | `ToolSuccess`, `ToolError` |
|
|
158
|
+
| `core/skills.py` | Skill discovery, delivery, built-in sync and the session filter | `SkillInfo`, `SkillScope`, `discover_all()`, `render_skill_block()`, `active_skills()`, `builtin_skills_root()`, `build_scope()`, `format_catalog()` |
|
|
159
|
+
| `skills/<name>/SKILL.md` | Packaged built-in skills (data only, shipped in the wheel); synced to `~/.ayder/builtin/skills` when `~/.ayder/builtin/STAMP` (version + SHA-256) differs | - |
|
|
157
160
|
| `core/context_manager.py` | ContextManager Protocol + shared utilities | `ContextManagerProtocol`, `ContextStats`, `truncate_tool_result()` |
|
|
158
161
|
| `core/default_context_manager.py` | Tiered context manager for non-Ollama providers | `DefaultContextManager`, `TokenCounter`, `MessageTier` |
|
|
159
162
|
| `core/ollama_context_manager.py` | KV-cache-aware context manager for Ollama | `OllamaContextManager`, `OllamaContextStats` |
|
|
@@ -294,6 +297,7 @@ the design rationale.
|
|
|
294
297
|
| `tools/builtins/context.py` | Session context snapshots | `context` |
|
|
295
298
|
| `tools/builtins/notes.py` | Note-taking tool | `create_note()` |
|
|
296
299
|
| `tools/builtins/tasks.py` | Task-management tools | `list_tasks()`, `show_task()` |
|
|
300
|
+
| `tools/builtins/skill.py` | Skill tool impl | `skill()`, `discover_skills()` |
|
|
297
301
|
| `tools/builtins/web.py` | HTTP fetch tool | `fetch_web()` |
|
|
298
302
|
| `tools/builtins/utils_tools.py` | Misc utility tools | `manage_environment_vars()` |
|
|
299
303
|
| `tools/builtins/*_definitions.py` | Per-domain tool definitions (9 files) | `TOOL_DEFINITIONS` tuples auto-discovered at import |
|
|
@@ -303,7 +307,7 @@ the design rationale.
|
|
|
303
307
|
| Module | Purpose | Key Classes/Functions |
|
|
304
308
|
|--------|---------|----------------------|
|
|
305
309
|
| `process_manager.py` | Background processes | `ProcessManager`, `background_process()` |
|
|
306
|
-
| `prompts.py` | System prompts | `SYSTEM_PROMPT`, `PLANNING_PROMPT_TEMPLATE`, `get_system_prompt()
|
|
310
|
+
| `prompts.py` | System prompts | `SYSTEM_PROMPT`, `PLANNING_PROMPT_TEMPLATE`, `get_system_prompt()` |
|
|
307
311
|
| `parser.py` | XML tool-call parsing | `parse_custom_tool_calls()` |
|
|
308
312
|
|
|
309
313
|
### Theme Modules
|
|
@@ -590,7 +594,7 @@ AyderApp is the main Textual application implementing a chat-style interface:
|
|
|
590
594
|
The application manages:
|
|
591
595
|
- LLM provider setup and configuration
|
|
592
596
|
- Tool registry initialization with middleware
|
|
593
|
-
- System prompt construction
|
|
597
|
+
- System prompt construction (base prompt + tool prompts + skill catalog; no project tree)
|
|
594
598
|
- Process manager for background operations
|
|
595
599
|
|
|
596
600
|
### Chat Loop Summary (src/ayder_cli/loops/chat_loop.py)
|
|
@@ -719,6 +723,8 @@ Schema-driven tool definitions with auto-discovery:
|
|
|
719
723
|
- `OllamaContextManager` (`core/ollama_context_manager.py`) — stable-prefix + real-token accounting, uses `prompt_eval_count` / `prompt_eval_duration` directly.
|
|
720
724
|
- `CacheMonitor` (`core/cache_monitor.py`) — timing-based KV-cache hit detection driving adaptive compaction thresholds.
|
|
721
725
|
|
|
726
|
+
Both managers re-supply active skills that a trim or compaction removed (`core/skills.py` `active_skills`).
|
|
727
|
+
|
|
722
728
|
Selection lives in `core/context_manager_factory.py` (driver → class path registry). `create_runtime()` owns instantiation and calls `freeze_system_prompt()` once.
|
|
723
729
|
|
|
724
730
|
### Phase — opus47 critical fixes (2026-04-16)
|
|
@@ -97,6 +97,10 @@ agent_timeout = 1800 # seconds before a background agent is cancel
|
|
|
97
97
|
# tasks/notes (metadata), background process control for test suites
|
|
98
98
|
# (background), and web fetch (http). See /plugin for the full tag list.
|
|
99
99
|
tool_tags = ["core", "metadata", "background", "http"]
|
|
100
|
+
# Skills the session's model may load (listed under "### Skills" in the system
|
|
101
|
+
# prompt). Not set = the built-in skills; "none" = no skill tool; or a strict
|
|
102
|
+
# list. A [llm.*] profile's skills wins over this one for the session.
|
|
103
|
+
# skills = ["engineering"]
|
|
100
104
|
|
|
101
105
|
[ui]
|
|
102
106
|
# TUI layout (theme) — picks the chrome/layout:
|
|
@@ -180,6 +184,7 @@ driver = "ollama"
|
|
|
180
184
|
base_url = "http://localhost:11434"
|
|
181
185
|
model = "qwen3.6:35b-a3b-coding-nvfp4"
|
|
182
186
|
num_ctx = 32768 # keep modest: local VRAM is the constraint
|
|
187
|
+
# skills = "none" # wins over [app].skills; agents on this profile inherit it
|
|
183
188
|
reasoning_effort = "default"
|
|
184
189
|
think = true # default; set false if the selected model rejects thinking
|
|
185
190
|
|
|
@@ -224,6 +229,7 @@ think = true # default; set false if the selected model r
|
|
|
224
229
|
[agents.pm_spec]
|
|
225
230
|
provider = "ollama_cloud"
|
|
226
231
|
model = "glm-5.2:cloud"
|
|
232
|
+
# skills = ["engineering"] # wins over the provider profile's skills; [app] is never read
|
|
227
233
|
temperature = 0.4
|
|
228
234
|
max_output_tokens = 8192
|
|
229
235
|
reasoning_effort = "high"
|
|
@@ -24,7 +24,7 @@ DEFAULT_BASELINE = REPO / "scripts" / "exception_baseline.txt"
|
|
|
24
24
|
|
|
25
25
|
# Frozen census (§C10). A different number means the gate is looking at the
|
|
26
26
|
# wrong tree, or the census moved without the plan being updated.
|
|
27
|
-
EXPECTED_BROAD =
|
|
27
|
+
EXPECTED_BROAD = 134
|
|
28
28
|
BRANCHING = (ast.If, ast.Try, ast.For, ast.While, ast.With, ast.Match)
|
|
29
29
|
TERMINAL = (ast.Return, ast.Break, ast.Continue, ast.Pass)
|
|
30
30
|
|
|
@@ -203,13 +203,13 @@ FROZEN_CHAIN_SITES: dict[tuple[str, str, str, str], tuple[str, int]] = {
|
|
|
203
203
|
("log.py", "emit_event", "bind", "**"): ("Name(id='fields', ctx=Load())", 1),
|
|
204
204
|
}
|
|
205
205
|
|
|
206
|
-
# The
|
|
207
|
-
# package-wide shape/count rule rather than
|
|
206
|
+
# The 98 `exception=True` inputs are homogeneous, so they are governed as one
|
|
207
|
+
# package-wide shape/count rule rather than 98 site identities - their per-site
|
|
208
208
|
# discipline is C10's.
|
|
209
|
-
FROZEN_EXCEPTION_TRUE =
|
|
209
|
+
FROZEN_EXCEPTION_TRUE = 98
|
|
210
210
|
|
|
211
211
|
# Live chain inputs, counted per method. Printed on every run.
|
|
212
|
-
CHAIN_TALLY: dict[str, int] = {"bind": 6, "opt":
|
|
212
|
+
CHAIN_TALLY: dict[str, int] = {"bind": 6, "opt": 102, "patch": 0}
|
|
213
213
|
|
|
214
214
|
# The reviewed composition of THE COMMITTED baseline, frozen by the Phase 5
|
|
215
215
|
# census: 252 retained non-path + 22 paths + 2 deferred interpolated rows, plus
|
|
@@ -218,12 +218,12 @@ CHAIN_TALLY: dict[str, int] = {"bind": 6, "opt": 105, "patch": 0}
|
|
|
218
218
|
# unchanged - so the composition is gated too. Caller-supplied baselines (the
|
|
219
219
|
# gate's own synthetic fixtures) are exempt: this is a fact about one file.
|
|
220
220
|
FROZEN_TALLY: dict[str, int] = {
|
|
221
|
-
"R-name":
|
|
221
|
+
"R-name": 99,
|
|
222
222
|
"R-id": 40,
|
|
223
223
|
"R-count": 90,
|
|
224
224
|
"R-status": 27,
|
|
225
|
-
"R-class":
|
|
226
|
-
"R-path":
|
|
225
|
+
"R-class": 11,
|
|
226
|
+
"R-path": 25,
|
|
227
227
|
# Both 5-04 deferrals are closed: the two asyncio rows now interpolate the
|
|
228
228
|
# B2-prime normalized value, and the bridge's dynamic message is masked by
|
|
229
229
|
# the prose sinks it reaches.
|
|
@@ -83,6 +83,7 @@
|
|
|
83
83
|
{"class":"R-name","site":{"arg_index":"pos:0","expr":"name","message":"Uninstalled plugin '{}'","method":"info","path":"tools/plugin_manager.py","qualname":"uninstall_plugin"}}
|
|
84
84
|
{"class":"R-name","site":{"arg_index":"pos:0","expr":"name","message":"cancel: agent='{}' \u2014 no running/queued instances","method":"debug","path":"agents/registry.py","qualname":"AgentRegistry.cancel"}}
|
|
85
85
|
{"class":"R-name","site":{"arg_index":"pos:0","expr":"name","message":"cancel: agent='{}' cancelled {} instance(s): {}","method":"debug","path":"agents/registry.py","qualname":"AgentRegistry.cancel"}}
|
|
86
|
+
{"class":"R-name","site":{"arg_index":"pos:0","expr":"name","message":"skills lists {!r}, but no skill directory provides it","method":"warning","path":"core/skills.py","qualname":"build_scope"}}
|
|
86
87
|
{"class":"R-status","site":{"arg_index":"pos:0","expr":"normalized","message":"Unhandled asyncio error: {}","method":"error","path":"diagnostics.py","qualname":"_handle_asyncio"}}
|
|
87
88
|
{"class":"R-status","site":{"arg_index":"pos:0","expr":"normalized","message":"Unhandled asyncio exception: {}","method":"critical","path":"diagnostics.py","qualname":"_handle_asyncio"}}
|
|
88
89
|
{"class":"R-count","site":{"arg_index":"pos:0","expr":"num_ctx","message":"Context budget: {} tokens (derived from num_ctx; max_context_tokens unset)","method":"info","path":"core/default_context_manager.py","qualname":"DefaultContextManager.__init__"}}
|
|
@@ -138,7 +139,9 @@
|
|
|
138
139
|
{"class":"R-status","site":{"arg_index":"pos:0","expr":"self.config.chat_protocol","message":"Ollama chat_protocol={!r} is not recognized; forcing generic_xml fallback","method":"warning","path":"providers/impl/ollama.py","qualname":"OllamaProvider.stream_with_tools"}}
|
|
139
140
|
{"class":"R-name","site":{"arg_index":"pos:0","expr":"self.config.model","message":"LLM returned empty response (possible connection drop). model={}, provider={}","method":"error","path":"loops/chat_loop.py","qualname":"ChatLoop.run"}}
|
|
140
141
|
{"class":"R-status","site":{"arg_index":"pos:0","expr":"signal.Signals(signum).name","message":"Received signal {}; flushing logs","method":"warning","path":"diagnostics.py","qualname":"install_exception_hooks._chained_signal"}}
|
|
142
|
+
{"class":"R-name","site":{"arg_index":"pos:0","expr":"skill_dir.name","message":"Skill directory {!r} declares name {!r}; the directory name is used","method":"debug","path":"core/skills.py","qualname":"read_skill_info"}}
|
|
141
143
|
{"class":"R-name","site":{"arg_index":"pos:0","expr":"source.repo","message":"Downloading '{}' at {}","method":"info","path":"tools/plugin_github.py","qualname":"download_plugin"}}
|
|
144
|
+
{"class":"R-path","site":{"arg_index":"pos:0","expr":"target","message":"Built-in skills were not synced to {} ({}); reading the packaged copy","method":"warning","path":"core/skills.py","qualname":"_sync_builtin_skills"}}
|
|
142
145
|
{"class":"R-name","site":{"arg_index":"pos:0","expr":"tc.function.name","message":"Tool '{}' called with missing args {} ({} chars raw)","method":"warning","path":"loops/chat_loop.py","qualname":"ChatLoop._execute_tool_calls"}}
|
|
143
146
|
{"class":"R-name","site":{"arg_index":"pos:0","expr":"tc_entry['function'].get('name', '?')","message":"Malformed tool arguments for '{}': {} chars \u2014 repairing before storing in history","method":"warning","path":"loops/chat_loop.py","qualname":"ChatLoop.run"}}
|
|
144
147
|
{"class":"R-name","site":{"arg_index":"pos:0","expr":"tc_obj.function.name","message":"Tool execution cancelled: {}","method":"warning","path":"loops/chat_loop.py","qualname":"ChatLoop._execute_tool_calls._safe_exec"}}
|
|
@@ -160,6 +163,7 @@
|
|
|
160
163
|
{"class":"R-status","site":{"arg_index":"pos:1","expr":"', '.join(valid)","message":"Unsupported driver (value_chars={}); must be one of: {}. Fix the driver in your [llm.<provider>] profile.","method":"error","path":"core/config.py","qualname":"Config.validate_driver"}}
|
|
161
164
|
{"class":"R-name","site":{"arg_index":"pos:1","expr":"agent_name","message":"Agent panel could not show run {} of agent {}","method":"debug","path":"tui/commands.py","qualname":"handle_agent"}}
|
|
162
165
|
{"class":"R-id","site":{"arg_index":"pos:1","expr":"commit_sha[:7]","message":"Downloading '{}' at {}","method":"info","path":"tools/plugin_github.py","qualname":"download_plugin"}}
|
|
166
|
+
{"class":"R-name","site":{"arg_index":"pos:1","expr":"declared","message":"Skill directory {!r} declares name {!r}; the directory name is used","method":"debug","path":"core/skills.py","qualname":"read_skill_info"}}
|
|
163
167
|
{"class":"R-count","site":{"arg_index":"pos:1","expr":"delay","message":"Provider stream failed ({}); retrying in {:.2f}s ({} attempts left)","method":"info","path":"providers/retry.py","qualname":"RetryingProvider.stream_with_tools"}}
|
|
164
168
|
{"class":"R-status","site":{"arg_index":"pos:1","expr":"driver.mode.value","message":"Ollama driver={} mode={} for {!r}","method":"info","path":"providers/impl/ollama.py","qualname":"OllamaProvider.stream_with_tools"}}
|
|
165
169
|
{"class":"R-status","site":{"arg_index":"pos:1","expr":"driver.mode.value","message":"{} ({}) failed mid-stream (error_type={}); transparently retrying with {} ({})","method":"info","path":"providers/impl/ollama.py","qualname":"OllamaProvider.stream_with_tools"}}
|
|
@@ -222,6 +226,7 @@
|
|
|
222
226
|
{"class":"R-name","site":{"arg_index":"pos:1","expr":"tc.name","message":"Tool call id reused by a different tool ({} then {}); calls would merge","method":"warning","path":"loops/chat_loop.py","qualname":"ChatLoop.run"}}
|
|
223
227
|
{"class":"R-status","site":{"arg_index":"pos:1","expr":"think","message":"Ollama model {!r} rejected think={!r}; retrying with think=False","method":"info","path":"providers/impl/ollama.py","qualname":"OllamaProvider._stream_in_content"}}
|
|
224
228
|
{"class":"R-status","site":{"arg_index":"pos:1","expr":"think","message":"Ollama model {!r} rejected think={!r}; retrying with think=False","method":"info","path":"providers/impl/ollama.py","qualname":"OllamaProvider._stream_native"}}
|
|
229
|
+
{"class":"R-class","site":{"arg_index":"pos:1","expr":"type(exc).__name__","message":"Built-in skills were not synced to {} ({}); reading the packaged copy","method":"warning","path":"core/skills.py","qualname":"_sync_builtin_skills"}}
|
|
225
230
|
{"class":"R-class","site":{"arg_index":"pos:1","expr":"type(exc).__name__","message":"Provider retry budget exhausted after {} attempts; raising {}","method":"warning","path":"providers/retry.py","qualname":"RetryingProvider.stream_with_tools"}}
|
|
226
231
|
{"class":"R-class","site":{"arg_index":"pos:1","expr":"type(exc).__name__","message":"Unreadable context slot at {}: {}","method":"warning","path":"tools/builtins/context.py","qualname":"_scan_context_dir"}}
|
|
227
232
|
{"class":"R-name","site":{"arg_index":"pos:2","expr":"', '.join(discovered_modules)","message":"Auto-discovered {} tool definitions from {} modules: {}","method":"info","path":"tools/definition.py","qualname":"_discover_definitions"}}
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
"""AgentConfig — Pydantic model for agent definitions."""
|
|
2
2
|
|
|
3
|
-
from typing import Any
|
|
3
|
+
from typing import Any, Literal
|
|
4
4
|
|
|
5
|
-
from pydantic import BaseModel, ConfigDict, model_validator
|
|
5
|
+
from pydantic import BaseModel, ConfigDict, field_validator, model_validator
|
|
6
6
|
|
|
7
|
+
from ayder_cli.core.config import _coerce_skills_setting
|
|
7
8
|
from ayder_cli.core.reasoning import ReasoningEffort, ThinkOption
|
|
8
9
|
|
|
9
10
|
|
|
@@ -32,6 +33,13 @@ class AgentConfig(BaseModel):
|
|
|
32
33
|
max_output_tokens: int | None = None
|
|
33
34
|
think: ThinkOption = None
|
|
34
35
|
reasoning_effort: ReasoningEffort = None
|
|
36
|
+
# None: the provider profile's setting; "none" or a list: see Config.skills.
|
|
37
|
+
skills: list[str] | Literal["none"] | None = None
|
|
38
|
+
|
|
39
|
+
@field_validator("skills", mode="before")
|
|
40
|
+
@classmethod
|
|
41
|
+
def _validate_skills(cls, v: Any) -> Any:
|
|
42
|
+
return _coerce_skills_setting(v)
|
|
35
43
|
|
|
36
44
|
@model_validator(mode="before")
|
|
37
45
|
@classmethod
|
|
@@ -7,6 +7,7 @@ eliminating the duplicate `_build_services()` / `AyderApp.__init__()` wiring.
|
|
|
7
7
|
from __future__ import annotations
|
|
8
8
|
|
|
9
9
|
from dataclasses import dataclass, field
|
|
10
|
+
from pathlib import Path
|
|
10
11
|
from typing import TYPE_CHECKING, Any
|
|
11
12
|
|
|
12
13
|
from ayder_cli.core.config import Config, load_config, load_config_for_provider
|
|
@@ -16,13 +17,13 @@ from ayder_cli.core.context_manager_factory import context_manager_factory
|
|
|
16
17
|
if TYPE_CHECKING:
|
|
17
18
|
from ayder_cli.agents.config import AgentConfig
|
|
18
19
|
from ayder_cli.core.context import ProjectContext
|
|
20
|
+
from ayder_cli.core.skills import build_scope
|
|
19
21
|
from ayder_cli.providers import AIProvider, provider_orchestrator
|
|
20
22
|
from ayder_cli.providers.retry import RetryConfig, RetryingProvider
|
|
21
23
|
from ayder_cli.tools.registry import ToolRegistry, create_default_registry
|
|
22
24
|
from ayder_cli.process_manager import ProcessManager
|
|
23
25
|
from ayder_cli.prompts import (
|
|
24
26
|
get_system_prompt,
|
|
25
|
-
PROJECT_STRUCTURE_MACRO_TEMPLATE,
|
|
26
27
|
)
|
|
27
28
|
from ayder_cli.log import get_logger
|
|
28
29
|
|
|
@@ -42,6 +43,25 @@ class RuntimeComponents:
|
|
|
42
43
|
context_manager: Any = field(default=None) # ContextManagerProtocol
|
|
43
44
|
|
|
44
45
|
|
|
46
|
+
def apply_skill_setting(
|
|
47
|
+
tool_registry: ToolRegistry,
|
|
48
|
+
project_ctx: ProjectContext,
|
|
49
|
+
setting: Any,
|
|
50
|
+
messages: list[dict] | None = None,
|
|
51
|
+
) -> None:
|
|
52
|
+
"""Scope the registry's skills; hide the skill tool for "none", show it otherwise.
|
|
53
|
+
|
|
54
|
+
Called at runtime construction and again on a provider switch, where
|
|
55
|
+
``messages`` is the live history (ChatLoop binds it only once).
|
|
56
|
+
"""
|
|
57
|
+
tool_registry.skill_scope = build_scope(Path(project_ctx.root), setting)
|
|
58
|
+
tool_registry.skill_scope.messages = messages
|
|
59
|
+
if setting == "none":
|
|
60
|
+
tool_registry.excluded_tools.add("skill")
|
|
61
|
+
else:
|
|
62
|
+
tool_registry.excluded_tools.discard("skill")
|
|
63
|
+
|
|
64
|
+
|
|
45
65
|
def create_runtime(
|
|
46
66
|
*,
|
|
47
67
|
config: Config | None = None,
|
|
@@ -60,7 +80,7 @@ def create_runtime(
|
|
|
60
80
|
(e.g. "AGENTIC" for `ayder-cli --agent`). See prompts.get_system_prompt.
|
|
61
81
|
system_prompt_override: When set, use this text as the system-prompt base
|
|
62
82
|
instead of prompts.get_system_prompt (ayder --system-prompt FILE). Tool
|
|
63
|
-
prompts
|
|
83
|
+
prompts are still appended.
|
|
64
84
|
|
|
65
85
|
Returns:
|
|
66
86
|
RuntimeComponents with all dependencies wired.
|
|
@@ -84,15 +104,7 @@ def create_runtime(
|
|
|
84
104
|
process_manager=process_manager,
|
|
85
105
|
context_manager=context_mgr,
|
|
86
106
|
)
|
|
87
|
-
|
|
88
|
-
try:
|
|
89
|
-
structure = tool_registry.execute("get_project_structure", {"max_depth": 3})
|
|
90
|
-
macro = PROJECT_STRUCTURE_MACRO_TEMPLATE.format(project_structure=structure)
|
|
91
|
-
except Exception: # noqa: BLE001 - tool boundary: the project-structure macro is optional, so runtime construction continues without it
|
|
92
|
-
logger.opt(exception=True).warning(
|
|
93
|
-
"Project-structure macro unavailable; continuing without it"
|
|
94
|
-
)
|
|
95
|
-
macro = ""
|
|
107
|
+
apply_skill_setting(tool_registry, project_ctx, cfg.session_skills())
|
|
96
108
|
|
|
97
109
|
# Format the final prompt (protocol injection now handled dynamically by chat_loop and protocols)
|
|
98
110
|
if system_prompt_override is not None:
|
|
@@ -101,7 +113,7 @@ def create_runtime(
|
|
|
101
113
|
base_prompt = get_system_prompt(cfg.prompt)
|
|
102
114
|
tool_tags = frozenset(cfg.tool_tags) if cfg.tool_tags else None
|
|
103
115
|
tool_prompts = tool_registry.get_system_prompts(tags=tool_tags)
|
|
104
|
-
system_prompt = base_prompt + tool_prompts
|
|
116
|
+
system_prompt = base_prompt + tool_prompts
|
|
105
117
|
|
|
106
118
|
# Freeze system prompt after tool schemas are known.
|
|
107
119
|
tool_schemas = tool_registry.get_schemas(tags=tool_tags)
|
|
@@ -196,6 +208,9 @@ def create_agent_runtime(
|
|
|
196
208
|
process_manager=process_manager,
|
|
197
209
|
context_manager=context_mgr,
|
|
198
210
|
)
|
|
211
|
+
# An agent reads its own setting, then its provider profile's; never [app].
|
|
212
|
+
skills_setting = agent_config.skills if agent_config.skills is not None else cfg.profile_skills
|
|
213
|
+
apply_skill_setting(tool_registry, project_ctx, skills_setting)
|
|
199
214
|
|
|
200
215
|
# 5. Build agent system prompt
|
|
201
216
|
identity_prefix = (
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import tomllib
|
|
2
2
|
from pathlib import Path
|
|
3
3
|
from pydantic import BaseModel, ConfigDict, Field, field_validator, model_validator
|
|
4
|
-
from typing import Any, Callable, Dict
|
|
4
|
+
from typing import Any, Callable, Dict, Literal
|
|
5
5
|
|
|
6
6
|
from ayder_cli.core.reasoning import ReasoningEffort, ThinkOption, validate_effort
|
|
7
7
|
from ayder_cli.log import get_logger
|
|
@@ -315,6 +315,23 @@ class TemporalConfig(BaseModel):
|
|
|
315
315
|
return v
|
|
316
316
|
|
|
317
317
|
|
|
318
|
+
def _coerce_skills_setting(value: Any) -> Any:
|
|
319
|
+
"""Accept None, a list of names, or "none" (any case). [] means "none"."""
|
|
320
|
+
if value is None:
|
|
321
|
+
return None
|
|
322
|
+
if isinstance(value, str):
|
|
323
|
+
if value.strip().lower() == "none":
|
|
324
|
+
return "none"
|
|
325
|
+
raise ValueError('skills must be "none" or a list of skill names')
|
|
326
|
+
if isinstance(value, list):
|
|
327
|
+
if not value:
|
|
328
|
+
return "none"
|
|
329
|
+
if not all(isinstance(item, str) and item.strip() for item in value):
|
|
330
|
+
raise ValueError("skills must list non-empty skill names")
|
|
331
|
+
return [item.strip() for item in value]
|
|
332
|
+
raise ValueError('skills must be "none" or a list of skill names')
|
|
333
|
+
|
|
334
|
+
|
|
318
335
|
class Config(BaseModel):
|
|
319
336
|
"""Unified configuration model with validation."""
|
|
320
337
|
|
|
@@ -366,6 +383,12 @@ class Config(BaseModel):
|
|
|
366
383
|
reasoning_effort: ReasoningEffort = None
|
|
367
384
|
stop_sequences: list[str] = Field(default_factory=list)
|
|
368
385
|
tool_tags: list[str] = Field(default_factory=lambda: ["core", "metadata"])
|
|
386
|
+
# Skills the model may use: None = the built-in skills, "none" = no skill
|
|
387
|
+
# tool, or a strict list of names. `skills` comes from [app];
|
|
388
|
+
# `profile_skills` from the active [llm.<provider>] profile and wins over
|
|
389
|
+
# it. Agents read [agents.<name>].skills, then their own profile_skills.
|
|
390
|
+
skills: list[str] | Literal["none"] | None = Field(default=None)
|
|
391
|
+
profile_skills: list[str] | Literal["none"] | None = Field(default=None)
|
|
369
392
|
temporal: TemporalConfig = Field(default_factory=TemporalConfig)
|
|
370
393
|
context_manager: ContextManagerConfigSection = Field(default_factory=ContextManagerConfigSection)
|
|
371
394
|
retry: RetryConfigSection = Field(default_factory=RetryConfigSection)
|
|
@@ -422,6 +445,11 @@ class Config(BaseModel):
|
|
|
422
445
|
provider, provider, DEFAULTS["provider"], available, provider,
|
|
423
446
|
)
|
|
424
447
|
if isinstance(profile, dict):
|
|
448
|
+
profile = dict(profile)
|
|
449
|
+
if "skills" in profile:
|
|
450
|
+
# Kept apart from [app]'s value so agents can tell a
|
|
451
|
+
# provider's setting from the session's (spec 4.10).
|
|
452
|
+
new_data["profile_skills"] = profile.pop("skills")
|
|
425
453
|
new_data.update(profile)
|
|
426
454
|
new_data.pop("llm", None)
|
|
427
455
|
|
|
@@ -460,6 +488,15 @@ class Config(BaseModel):
|
|
|
460
488
|
|
|
461
489
|
return new_data
|
|
462
490
|
|
|
491
|
+
@field_validator("skills", "profile_skills", mode="before")
|
|
492
|
+
@classmethod
|
|
493
|
+
def validate_skills(cls, v: Any) -> Any:
|
|
494
|
+
return _coerce_skills_setting(v)
|
|
495
|
+
|
|
496
|
+
def session_skills(self) -> list[str] | Literal["none"] | None:
|
|
497
|
+
"""The main session's setting: the profile's, else [app]'s."""
|
|
498
|
+
return self.profile_skills if self.profile_skills is not None else self.skills
|
|
499
|
+
|
|
463
500
|
@field_validator("provider")
|
|
464
501
|
@classmethod
|
|
465
502
|
def validate_provider(cls, v: str) -> str:
|