ayder-cli 2.5.0__tar.gz → 2.5.2__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.5.0 → ayder_cli-2.5.2}/.github/workflows/python-package.yml +3 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/AGENTS.md +92 -84
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/PKG-INFO +23 -10
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/README.md +22 -9
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/docs/GATE.md +1 -1
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/docs/PROJECT_STRUCTURE.md +7 -6
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/docs/config.toml.example +5 -2
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/pyproject.toml +1 -1
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/src/ayder_cli/agents/config.py +3 -1
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/src/ayder_cli/agents/registry.py +3 -1
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/src/ayder_cli/agents/runner.py +8 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/src/ayder_cli/agents/tool.py +2 -1
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/src/ayder_cli/application/runtime_factory.py +26 -3
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/src/ayder_cli/cli.py +14 -1
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/src/ayder_cli/cli_runner.py +1 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/src/ayder_cli/core/config.py +9 -0
- ayder_cli-2.5.2/src/ayder_cli/core/context.py +158 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/src/ayder_cli/core/session.py +12 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/src/ayder_cli/core/skills.py +8 -6
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/src/ayder_cli/loops/chat_loop.py +152 -46
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/src/ayder_cli/process_manager.py +77 -48
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/src/ayder_cli/prompts.py +54 -0
- ayder_cli-2.5.2/src/ayder_cli/skills/development-workflow/SKILL.md +27 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/src/ayder_cli/tools/builtins/context.py +4 -2
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/src/ayder_cli/tools/builtins/context_definitions.py +2 -1
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/src/ayder_cli/tools/builtins/filesystem.py +99 -21
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/src/ayder_cli/tools/builtins/filesystem_definitions.py +12 -6
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/src/ayder_cli/tools/builtins/note_tool.py +4 -2
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/src/ayder_cli/tools/builtins/notes.py +4 -2
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/src/ayder_cli/tools/builtins/notes_definitions.py +2 -1
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/src/ayder_cli/tools/builtins/process_manager_definitions.py +2 -1
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/src/ayder_cli/tools/builtins/search.py +4 -2
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/src/ayder_cli/tools/builtins/search_definitions.py +2 -0
- ayder_cli-2.5.2/src/ayder_cli/tools/builtins/shell.py +146 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/src/ayder_cli/tools/builtins/shell_definitions.py +5 -1
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/src/ayder_cli/tools/builtins/skill.py +18 -4
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/src/ayder_cli/tools/builtins/skill_definitions.py +3 -1
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/src/ayder_cli/tools/builtins/task_definitions.py +14 -6
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/src/ayder_cli/tools/builtins/task_tool.py +158 -40
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/src/ayder_cli/tools/builtins/tasks.py +44 -12
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/src/ayder_cli/tools/builtins/utils_tools.py +4 -2
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/src/ayder_cli/tools/builtins/web_definitions.py +2 -1
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/src/ayder_cli/tools/definition.py +56 -2
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/src/ayder_cli/tools/execution.py +4 -2
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/src/ayder_cli/tools/mcp.py +28 -4
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/src/ayder_cli/tui/__init__.py +7 -1
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/src/ayder_cli/tui/app.py +20 -4
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/tests/agents/test_worktree_isolation.py +27 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/tests/application/test_runtime_factory.py +4 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/tests/conftest.py +9 -0
- ayder_cli-2.5.2/tests/core/test_scratch_dir.py +115 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/tests/core/test_session.py +32 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/tests/core/test_skills.py +4 -1
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/tests/core/test_skills_builtin_sync.py +4 -4
- ayder_cli-2.5.2/tests/loops/test_chat_loop_guards.py +282 -0
- ayder_cli-2.5.2/tests/loops/test_tool_batch_ordering.py +254 -0
- ayder_cli-2.5.2/tests/test_agents_md.py +114 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/tests/test_cli.py +55 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/tests/test_process_manager.py +2 -2
- ayder_cli-2.5.2/tests/test_prompts_environment.py +102 -0
- ayder_cli-2.5.2/tests/tools/test_bash_process_safety.py +198 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/tests/tools/test_bash_tool.py +34 -23
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/tests/tools/test_definition_discovery.py +39 -0
- ayder_cli-2.5.2/tests/tools/test_error_labels.py +103 -0
- ayder_cli-2.5.2/tests/tools/test_file_tool_output.py +182 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/tests/tools/test_impl.py +2 -2
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/tests/tools/test_impl_coverage.py +5 -3
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/tests/tools/test_mcp.py +21 -1
- ayder_cli-2.5.2/tests/tools/test_parallel_safe.py +91 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/tests/tools/test_path_security.py +2 -2
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/tests/tools/test_skill_tool.py +44 -1
- ayder_cli-2.5.2/tests/tools/test_task_integrity.py +193 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/tests/tools/test_task_tool.py +114 -3
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/tests/tools/test_utils.py +3 -3
- ayder_cli-2.5.2/tests/tui/test_resume.py +162 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/tests/ui/test_confirm_screen.py +2 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/tests/ui/test_tui_system_prompt_no_structure.py +10 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/uv.lock +2 -2
- ayder_cli-2.5.0/docs/superpowers/plans/2026-06-26-file-editor-improvements.md +0 -771
- ayder_cli-2.5.0/docs/superpowers/plans/2026-06-26-session-save-resume.md +0 -1047
- ayder_cli-2.5.0/docs/superpowers/specs/2026-06-26-file-editor-improvements-design.md +0 -180
- ayder_cli-2.5.0/docs/superpowers/specs/2026-06-26-session-save-resume-design.md +0 -319
- ayder_cli-2.5.0/src/ayder_cli/core/context.py +0 -92
- ayder_cli-2.5.0/src/ayder_cli/skills/engineering/SKILL.md +0 -35
- ayder_cli-2.5.0/src/ayder_cli/tools/builtins/shell.py +0 -109
- ayder_cli-2.5.0/tests/tui/test_resume.py +0 -86
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/.github/workflows/ci.yml +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/.gitignore +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/.python-version +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/LICENSE +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/docs/README_AGENT_WORKFLOW.md +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/docs/README_OLLAMA.md +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/docs/cc.png +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/scripts/check_exception_handlers.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/scripts/check_log_arguments.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/scripts/check_logging_imports.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/scripts/exception_baseline.txt +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/scripts/find_percent_logging.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/scripts/log_argument_baseline.txt +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/scripts/logging_gates.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/src/ayder_cli/__init__.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/src/ayder_cli/__main__.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/src/ayder_cli/agents/__init__.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/src/ayder_cli/agents/callbacks.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/src/ayder_cli/agents/run.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/src/ayder_cli/agents/worktree.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/src/ayder_cli/application/README.md +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/src/ayder_cli/application/__init__.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/src/ayder_cli/application/execution_policy.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/src/ayder_cli/application/message_contract.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/src/ayder_cli/application/validation.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/src/ayder_cli/cli_callbacks.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/src/ayder_cli/console.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/src/ayder_cli/core/cache_monitor.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/src/ayder_cli/core/config_migration.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/src/ayder_cli/core/context_manager.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/src/ayder_cli/core/context_manager_factory.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/src/ayder_cli/core/default_context_manager.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/src/ayder_cli/core/ollama_context_manager.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/src/ayder_cli/core/reasoning.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/src/ayder_cli/core/result.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/src/ayder_cli/diagnostics.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/src/ayder_cli/log.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/src/ayder_cli/logging_config.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/src/ayder_cli/loops/__init__.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/src/ayder_cli/masking.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/src/ayder_cli/parser.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/src/ayder_cli/providers/__init__.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/src/ayder_cli/providers/base.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/src/ayder_cli/providers/evren.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/src/ayder_cli/providers/impl/claude.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/src/ayder_cli/providers/impl/deepseek.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/src/ayder_cli/providers/impl/gemini.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/src/ayder_cli/providers/impl/glm.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/src/ayder_cli/providers/impl/ollama.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/src/ayder_cli/providers/impl/ollama_drivers/__init__.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/src/ayder_cli/providers/impl/ollama_drivers/_errors.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/src/ayder_cli/providers/impl/ollama_drivers/base.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/src/ayder_cli/providers/impl/ollama_drivers/deepseek.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/src/ayder_cli/providers/impl/ollama_drivers/generic_native.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/src/ayder_cli/providers/impl/ollama_drivers/generic_xml.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/src/ayder_cli/providers/impl/ollama_drivers/matrix.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/src/ayder_cli/providers/impl/ollama_drivers/minimax.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/src/ayder_cli/providers/impl/ollama_drivers/qwen3.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/src/ayder_cli/providers/impl/ollama_drivers/registry.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/src/ayder_cli/providers/impl/ollama_inspector.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/src/ayder_cli/providers/impl/openai.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/src/ayder_cli/providers/impl/qwen.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/src/ayder_cli/providers/orchestrator.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/src/ayder_cli/providers/retry.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/src/ayder_cli/services/__init__.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/src/ayder_cli/services/interactions.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/src/ayder_cli/services/messaging_inbox.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/src/ayder_cli/themes/__init__.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/src/ayder_cli/themes/ayder.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/src/ayder_cli/themes/claude.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/src/ayder_cli/tools/__init__.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/src/ayder_cli/tools/builtins/__init__.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/src/ayder_cli/tools/builtins/background_process_tool.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/src/ayder_cli/tools/builtins/utils_tools_definitions.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/src/ayder_cli/tools/builtins/web.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/src/ayder_cli/tools/hooks.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/src/ayder_cli/tools/mcp_client.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/src/ayder_cli/tools/normalization.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/src/ayder_cli/tools/plugin_api.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/src/ayder_cli/tools/plugin_github.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/src/ayder_cli/tools/plugin_manager.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/src/ayder_cli/tools/plugin_status.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/src/ayder_cli/tools/registry.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/src/ayder_cli/tools/schemas.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/src/ayder_cli/tools/utils.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/src/ayder_cli/tui/adapter.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/src/ayder_cli/tui/commands.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/src/ayder_cli/tui/helpers.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/src/ayder_cli/tui/keybindings.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/src/ayder_cli/tui/parser.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/src/ayder_cli/tui/rendering.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/src/ayder_cli/tui/screens.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/src/ayder_cli/tui/theme_manager.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/src/ayder_cli/tui/types.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/src/ayder_cli/tui/widgets.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/src/ayder_cli/ui.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/src/ayder_cli/version.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/tests/COVERAGE.md +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/tests/__init__.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/tests/agents/__init__.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/tests/agents/test_agent_consolidated.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/tests/agents/test_agent_severity.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/tests/agents/test_agent_tools.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/tests/agents/test_callbacks.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/tests/agents/test_config.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/tests/agents/test_integration.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/tests/agents/test_queue.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/tests/agents/test_registry.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/tests/agents/test_run.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/tests/agents/test_runner.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/tests/agents/test_runner_provider_unavailable.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/tests/agents/test_tool.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/tests/agents/test_worktree_helpers.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/tests/application/test_argument_canonicalization.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/tests/application/test_execution_result_truthfulness.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/tests/application/test_message_contract.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/tests/client/test_main.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/tests/convergence/__init__.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/tests/convergence/test_execution_policy_parity.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/tests/convergence/test_runtime_wiring.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/tests/convergence/test_validation_path.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/tests/core/test_asyncio_bridge.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/tests/core/test_cache_monitor.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/tests/core/test_config.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/tests/core/test_config_coverage.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/tests/core/test_config_migration.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/tests/core/test_config_provider_logging.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/tests/core/test_config_retry.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/tests/core/test_config_skills.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/tests/core/test_config_v2.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/tests/core/test_context_manager_factory.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/tests/core/test_default_config_evren.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/tests/core/test_default_context_manager.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/tests/core/test_default_context_manager_should_compact.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/tests/core/test_default_context_newest_unit.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/tests/core/test_default_context_skill_resupply.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/tests/core/test_event_emission.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/tests/core/test_event_stream.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/tests/core/test_exception_guarantee.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/tests/core/test_exception_hooks.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/tests/core/test_log_facade.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/tests/core/test_logging_config_keys.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/tests/core/test_logging_sinks.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/tests/core/test_loguru_caplog.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/tests/core/test_max_output_tokens_default.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/tests/core/test_ollama_compaction_persistence.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/tests/core/test_ollama_context_manager.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/tests/core/test_ollama_context_manager_cache_monitor.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/tests/core/test_ollama_context_manager_max_history.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/tests/core/test_ollama_skill_resupply.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/tests/core/test_parameter_aliasing.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/tests/core/test_parser.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/tests/core/test_reasoning_config.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/tests/core/test_session_id_threading.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/tests/core/test_sink_masking.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/tests/loops/__init__.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/tests/loops/test_base.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/tests/loops/test_chat_loop_hook.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/tests/loops/test_chat_loop_tool_truncation.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/tests/loops/test_loop_severity.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/tests/loops/test_required_args_aliases.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/tests/loops/test_tool_argument_integrity.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/tests/loops/test_tool_batch_cancellation.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/tests/providers/__init__.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/tests/providers/ollama_drivers/__init__.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/tests/providers/ollama_drivers/test_base.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/tests/providers/ollama_drivers/test_deepseek.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/tests/providers/ollama_drivers/test_errors.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/tests/providers/ollama_drivers/test_fallback.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/tests/providers/ollama_drivers/test_generic_native.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/tests/providers/ollama_drivers/test_generic_xml.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/tests/providers/ollama_drivers/test_matrix.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/tests/providers/ollama_drivers/test_minimax.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/tests/providers/ollama_drivers/test_provider_integration.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/tests/providers/ollama_drivers/test_qwen3.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/tests/providers/ollama_drivers/test_registry.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/tests/providers/test_claude_stream_tool_calls.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/tests/providers/test_evren.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/tests/providers/test_gemini_function_calls.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/tests/providers/test_glm_async.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/tests/providers/test_ollama_inspector.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/tests/providers/test_ollama_native.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/tests/providers/test_ollama_parallel_tool_call_ids.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/tests/providers/test_ollama_xml.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/tests/providers/test_ollama_xml_autoroute.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/tests/providers/test_ollama_xml_usage.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/tests/providers/test_openai_list_models.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/tests/providers/test_orchestrator_capabilities.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/tests/providers/test_provider_channel_binding.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/tests/providers/test_provider_severity.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/tests/providers/test_qwen_async.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/tests/providers/test_reasoning_effort.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/tests/providers/test_retry_classifier.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/tests/providers/test_retry_integration.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/tests/providers/test_retrying_provider.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/tests/providers/test_skill_load_prefix.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/tests/scripts/test_exception_gate.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/tests/scripts/test_log_argument_gate.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/tests/scripts/test_logging_policy_gates.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/tests/scripts/test_loguru_private_shape.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/tests/services/test_boundary.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/tests/services/test_interaction_sink.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/tests/services/test_messaging_inbox.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/tests/test_cli_callbacks.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/tests/test_context.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/tests/test_env_manager.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/tests/test_logging_config.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/tests/test_notes.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/tests/test_prompts_general.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/tests/test_tasks.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/tests/tools/__init__.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/tests/tools/test_agent_notes.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/tests/tools/test_background_process_tool.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/tests/tools/test_context_storage_confinement.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/tests/tools/test_di_injection.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/tests/tools/test_file_editor_hardening.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/tests/tools/test_file_editor_size_limit.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/tests/tools/test_mcp_client.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/tests/tools/test_note_tool.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/tests/tools/test_notes_api.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/tests/tools/test_notes_confinement.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/tests/tools/test_plugin_api.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/tests/tools/test_plugin_github.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/tests/tools/test_plugin_loading.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/tests/tools/test_plugin_manager.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/tests/tools/test_plugin_status.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/tests/tools/test_registry.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/tests/tools/test_registry_coverage.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/tests/tools/test_result.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/tests/tools/test_schemas.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/tests/tools/test_search_codebase.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/tests/tools/test_search_hardening.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/tests/tools/test_skill_catalog_and_filter.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/tests/tools/test_skill_scope_wiring.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/tests/tools/test_task_path_confinement.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/tests/tools/test_tool_severity.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/tests/tools/test_unexpected_args.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/tests/tools/test_web.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/tests/tui/__init__.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/tests/tui/test_agent_list_screen.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/tests/tui/test_do_clear_coordination.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/tests/tui/test_evren_terms.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/tests/tui/test_follow_mode.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/tests/tui/test_help_screen.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/tests/tui/test_input_box.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/tests/tui/test_keybindings.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/tests/tui/test_multi_select_screen.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/tests/tui/test_multiline_input.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/tests/tui/test_paste.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/tests/tui/test_peer_message_turn.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/tests/tui/test_pending_compact_consumer.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/tests/tui/test_pull_delivery.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/tests/tui/test_status_bar_badges.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/tests/tui/test_themes.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/tests/tui/test_turn_consumer.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/tests/tui/test_widgets.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/tests/ui/test_diff_preview.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/tests/ui/test_plugin_autoenable.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/tests/ui/test_provider_switch.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/tests/ui/test_run_tui_startup.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/tests/ui/test_tui_assistant_sanitization.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/tests/ui/test_tui_chat_loop.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/tests/ui/test_tui_commands_agent.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/tests/ui/test_tui_commands_effort.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/tests/ui/test_tui_commands_logging.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/tests/ui/test_tui_commands_plugin.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/tests/ui/test_tui_commands_provider.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/tests/ui/test_tui_commands_skill.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/tests/ui/test_tui_helpers.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/tests/ui/test_tui_temporal_command.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/tests/ui/test_tui_widgets.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/tests/ui/test_ui.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/tests/ui/test_ui_coverage.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.2}/tests/ui/test_ui_verbose.py +0 -0
|
@@ -11,6 +11,9 @@ on:
|
|
|
11
11
|
|
|
12
12
|
jobs:
|
|
13
13
|
build-and-publish:
|
|
14
|
+
# The pypi environment admits only main and release-*/beta-* tags, so on a
|
|
15
|
+
# pull request the job is refused before any step runs and the PR shows red.
|
|
16
|
+
if: github.event_name == 'push'
|
|
14
17
|
runs-on: ubuntu-latest
|
|
15
18
|
# This job only runs in the context of your 'pypi' environment
|
|
16
19
|
environment: pypi
|
|
@@ -50,115 +50,127 @@ This document provides coding standards, tool configurations, and workflows for
|
|
|
50
50
|
ayder-cli/
|
|
51
51
|
├── src/ayder_cli/ # Main source code
|
|
52
52
|
│ ├── cli.py # Entry point (argparse)
|
|
53
|
-
│ ├──
|
|
54
|
-
│ ├──
|
|
55
|
-
│ ├──
|
|
53
|
+
│ ├── __main__.py # `python -m ayder_cli`
|
|
54
|
+
│ ├── cli_runner.py # Single-command (non-TUI) runs and task commands
|
|
55
|
+
│ ├── cli_callbacks.py # CliCallbacks (ChatCallbacks for plain terminal runs)
|
|
56
56
|
│ ├── console.py # Rich console instance
|
|
57
57
|
│ ├── version.py # Version info
|
|
58
|
-
│ ├──
|
|
58
|
+
│ ├── log.py # Channel-scoped loguru accessors
|
|
59
|
+
│ ├── logging_config.py # Loguru sinks + stdlib-logging bridge
|
|
60
|
+
│ ├── masking.py # Credential masking for log text
|
|
61
|
+
│ ├── diagnostics.py # Process-level exception capture
|
|
62
|
+
│ ├── parser.py # Unified LLM output parser (ContentProcessor)
|
|
63
|
+
│ ├── process_manager.py # Background processes (own process group, group kill)
|
|
64
|
+
│ ├── prompts.py # System prompt templates + environment section
|
|
65
|
+
│ ├── ui.py # Rich terminal UI helpers
|
|
59
66
|
│ │
|
|
60
67
|
│ ├── core/ # Core infrastructure
|
|
61
68
|
│ │ ├── config.py # Pydantic config with validation
|
|
62
|
-
│ │ ├──
|
|
63
|
-
│ │
|
|
69
|
+
│ │ ├── config_migration.py # Config schema v2.0 migration
|
|
70
|
+
│ │ ├── context.py # ProjectContext (path sandboxing, scratch dir)
|
|
71
|
+
│ │ ├── result.py # ToolSuccess/ToolError types
|
|
72
|
+
│ │ ├── session.py # Save/restore TUI sessions (.ayder/sessions/)
|
|
73
|
+
│ │ ├── skills.py # Skill discovery, scope, load blocks, active set
|
|
74
|
+
│ │ ├── reasoning.py # Reasoning settings (think / reasoning_effort)
|
|
75
|
+
│ │ ├── context_manager.py # ContextManager protocol + shared helpers
|
|
76
|
+
│ │ ├── context_manager_factory.py # Picks the context manager per provider
|
|
77
|
+
│ │ ├── default_context_manager.py # Token-budget trimming (non-Ollama)
|
|
78
|
+
│ │ ├── ollama_context_manager.py # Cache-aware stable-prefix manager (Ollama)
|
|
79
|
+
│ │ └── cache_monitor.py # KV-cache hit detection
|
|
64
80
|
│ │
|
|
65
81
|
│ ├── agents/ # Multi-agent system
|
|
66
|
-
│ │ ├──
|
|
82
|
+
│ │ ├── config.py # AgentConfig ([agents.<name>])
|
|
83
|
+
│ │ ├── registry.py # AgentRegistry (dispatch, queue, lifecycle)
|
|
84
|
+
│ │ ├── run.py # AgentRun (per-dispatch state the main LLM polls)
|
|
85
|
+
│ │ ├── runner.py # AgentRunner (one isolated ChatLoop per dispatch)
|
|
67
86
|
│ │ ├── callbacks.py # AgentCallbacks (ChatCallbacks for agents)
|
|
68
|
-
│ │ ├──
|
|
69
|
-
│ │
|
|
70
|
-
│ │ ├── runner.py # AgentRunner (isolated ChatLoop execution)
|
|
71
|
-
│ │ ├── summary.py # AgentSummary (structured result)
|
|
72
|
-
│ │ └── tool.py # call_agent tool definition + handler
|
|
87
|
+
│ │ ├── worktree.py # Git worktree isolation for agents
|
|
88
|
+
│ │ └── tool.py # The `agent` tool definition + handler
|
|
73
89
|
│ │
|
|
74
90
|
│ ├── application/ # Shared application layer (CLI + TUI)
|
|
75
|
-
│ │ ├── execution_policy.py
|
|
76
|
-
│ │ ├── message_contract.py
|
|
77
|
-
│ │ ├── runtime_factory.py
|
|
78
|
-
│ │
|
|
79
|
-
│ │ ├── temporal_metadata.py # Temporal metadata types
|
|
80
|
-
│ │ └── validation.py # ValidationAuthority, SchemaValidator
|
|
91
|
+
│ │ ├── execution_policy.py # ExecutionPolicy, PermissionDeniedError
|
|
92
|
+
│ │ ├── message_contract.py # LLM message format contracts
|
|
93
|
+
│ │ ├── runtime_factory.py # create_runtime() + create_agent_runtime()
|
|
94
|
+
│ │ └── validation.py # ValidationAuthority, SchemaValidator
|
|
81
95
|
│ │
|
|
82
|
-
│ ├── loops/
|
|
83
|
-
│ │
|
|
84
|
-
│ │ ├── chat_loop.py # ChatLoop (async LLM + tool execution loop)
|
|
85
|
-
│ │ └── config.py # Shared LoopConfig dataclass
|
|
96
|
+
│ ├── loops/
|
|
97
|
+
│ │ └── chat_loop.py # ChatLoop, ChatLoopConfig, ChatCallbacks (the only loop)
|
|
86
98
|
│ │
|
|
87
99
|
│ ├── providers/ # LLM provider implementations
|
|
88
100
|
│ │ ├── base.py # AIProvider protocol, NormalizedStreamChunk
|
|
89
|
-
│ │ ├── orchestrator.py
|
|
101
|
+
│ │ ├── orchestrator.py # Factory: create(config) → provider
|
|
102
|
+
│ │ ├── retry.py # Retry wrapper (backoff + mid-stream recovery)
|
|
90
103
|
│ │ ├── evren.py # evren gateway terms-of-use acceptance (/model)
|
|
91
104
|
│ │ └── impl/ # Individual provider drivers
|
|
92
105
|
│ │ ├── openai.py # OpenAIProvider (base for most drivers)
|
|
93
|
-
│ │ ├── ollama.py # OllamaProvider (
|
|
106
|
+
│ │ ├── ollama.py # OllamaProvider (routes through ollama_drivers/)
|
|
107
|
+
│ │ ├── ollama_inspector.py # Model introspection + native tool-call probe
|
|
108
|
+
│ │ ├── ollama_drivers/ # Per-family Ollama chat drivers + resolution matrix
|
|
94
109
|
│ │ ├── claude.py # ClaudeProvider (Anthropic SDK)
|
|
95
110
|
│ │ ├── gemini.py # GeminiProvider (Google GenAI SDK)
|
|
96
111
|
│ │ ├── deepseek.py # DeepSeekProvider (OpenAI-compatible)
|
|
97
112
|
│ │ ├── qwen.py # QwenNativeProvider (DashScope SDK)
|
|
98
113
|
│ │ └── glm.py # GLMNativeProvider (ZhipuAI SDK)
|
|
99
114
|
│ │
|
|
100
|
-
│ ├── services/
|
|
101
|
-
│ │
|
|
115
|
+
│ ├── services/
|
|
116
|
+
│ │ ├── interactions.py # InteractionSink protocol (LLM debug events)
|
|
117
|
+
│ │ └── messaging_inbox.py # Unix-socket inbox for prompts from peer processes
|
|
102
118
|
│ │
|
|
103
|
-
│ ├── tools/ # Tool framework +
|
|
119
|
+
│ ├── tools/ # Tool framework + built-in tools
|
|
104
120
|
│ │ ├── definition.py # ToolDefinition dataclass + auto-discovery
|
|
105
|
-
│ │ ├── registry.py # ToolRegistry (
|
|
121
|
+
│ │ ├── registry.py # ToolRegistry (schemas, dispatch, system prompts)
|
|
106
122
|
│ │ ├── schemas.py # OpenAI-format JSON schemas
|
|
107
|
-
│ │ ├── execution.py # Tool execution
|
|
108
|
-
│ │ ├── hooks.py #
|
|
109
|
-
│ │ ├── normalization.py # Argument
|
|
123
|
+
│ │ ├── execution.py # Tool execution pipeline
|
|
124
|
+
│ │ ├── hooks.py # Middleware and execution callbacks
|
|
125
|
+
│ │ ├── normalization.py # Argument aliases, path resolution, coercion
|
|
110
126
|
│ │ ├── utils.py # Tool utilities
|
|
127
|
+
│ │ ├── mcp.py # Built-in MCP tools from .ayder/mcp.json
|
|
128
|
+
│ │ ├── mcp_client.py # MCP sessions + synchronous dispatch bridge
|
|
129
|
+
│ │ ├── plugin_manager.py # Install/update/load external plugins
|
|
130
|
+
│ │ ├── plugin_api.py # Plugin API version checks
|
|
131
|
+
│ │ ├── plugin_github.py # Plugin download from GitHub
|
|
132
|
+
│ │ ├── plugin_status.py # Plugin status badges
|
|
111
133
|
│ │ └── builtins/ # Built-in tool implementations
|
|
112
|
-
│ │ ├── *_definitions.py
|
|
113
|
-
│ │ ├── filesystem.py
|
|
114
|
-
│ │ ├──
|
|
115
|
-
│ │ ├──
|
|
116
|
-
│ │ ├── shell.py
|
|
117
|
-
│ │ ├──
|
|
118
|
-
│ │ ├──
|
|
119
|
-
│ │ ├──
|
|
120
|
-
│ │ ├──
|
|
121
|
-
│ │ ├──
|
|
122
|
-
│ │ ├── tasks.py
|
|
123
|
-
│ │ ├──
|
|
124
|
-
│ │ └──
|
|
134
|
+
│ │ ├── *_definitions.py # Tool definitions, auto-discovered
|
|
135
|
+
│ │ ├── filesystem.py # file_explorer, read_file, file_editor
|
|
136
|
+
│ │ ├── search.py # search_codebase
|
|
137
|
+
│ │ ├── utils_tools.py # get_project_structure, manage_environment_vars
|
|
138
|
+
│ │ ├── shell.py # bash
|
|
139
|
+
│ │ ├── background_process_tool.py # background_process
|
|
140
|
+
│ │ ├── context.py # context (stats, save/load, compact)
|
|
141
|
+
│ │ ├── note_tool.py # note
|
|
142
|
+
│ │ ├── notes.py # Note storage (.ayder/notes/)
|
|
143
|
+
│ │ ├── task_tool.py # task
|
|
144
|
+
│ │ ├── tasks.py # Task files (.ayder/tasks/)
|
|
145
|
+
│ │ ├── skill.py # skill
|
|
146
|
+
│ │ └── web.py # fetch_web
|
|
125
147
|
│ │
|
|
126
148
|
│ ├── tui/ # Textual TUI (main interface)
|
|
127
149
|
│ │ ├── __init__.py # run_tui() entry point
|
|
128
150
|
│ │ ├── app.py # AyderApp main application
|
|
129
|
-
│ │ ├──
|
|
130
|
-
│ │ ├──
|
|
151
|
+
│ │ ├── commands.py # Slash command handlers
|
|
152
|
+
│ │ ├── keybindings.py # Keybinding registry
|
|
131
153
|
│ │ ├── helpers.py # TUI helper functions
|
|
132
154
|
│ │ ├── adapter.py # TUIInteractionSink (verbose debug)
|
|
133
|
-
│ │ ├── parser.py #
|
|
134
|
-
│ │ ├──
|
|
155
|
+
│ │ ├── parser.py # Re-exports of the unified ContentProcessor
|
|
156
|
+
│ │ ├── rendering.py # Safe render helpers
|
|
157
|
+
│ │ ├── screens.py # Modal screens (confirm, select, permission, task edit, …)
|
|
135
158
|
│ │ ├── theme_manager.py # Theme loading and CSS
|
|
136
159
|
│ │ ├── types.py # MessageType, ConfirmResult
|
|
137
|
-
│ │ └── widgets.py # ChatView, ToolPanel, CLIInputBar, StatusBar
|
|
160
|
+
│ │ └── widgets.py # ChatView, ToolPanel, CLIInputBar, StatusBar, …
|
|
138
161
|
│ │
|
|
139
|
-
│ ├──
|
|
140
|
-
│ │ ├── __init__.py # Theme registry
|
|
141
|
-
│ │ ├── claude.py # Claude theme CSS (default, RGB)
|
|
142
|
-
│ │ └── ayder.py # ayder tokenised layout + ANSI/RGB palette overlay ([ui] palette)
|
|
162
|
+
│ ├── skills/ # Packaged built-in skills (development-workflow/SKILL.md)
|
|
143
163
|
│ │
|
|
144
|
-
│
|
|
145
|
-
│
|
|
146
|
-
│
|
|
147
|
-
│ └── ui.py # Rich terminal UI helpers
|
|
164
|
+
│ └── themes/ # TUI themes
|
|
165
|
+
│ ├── claude.py # Claude theme CSS (RGB)
|
|
166
|
+
│ └── ayder.py # ayder tokenised layout + ANSI/RGB palette ([ui] palette)
|
|
148
167
|
│
|
|
149
|
-
├── tests/ # Test suite (
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
│ ├── services/ # Services tests
|
|
153
|
-
│ ├── tools/ # Tool tests
|
|
154
|
-
│ ├── ui/ # TUI tests
|
|
155
|
-
│ └── *.py # Top-level tests
|
|
156
|
-
│
|
|
157
|
-
├── .ayder/ # Project-specific data (tasks, notes, memory, skills)
|
|
168
|
+
├── tests/ # Test suite, mirrors src/ (agents/, core/, loops/, tools/, tui/, …)
|
|
169
|
+
├── docs/ # GATE.md, PROJECT_STRUCTURE.md, config.toml.example, guides
|
|
170
|
+
├── .ayder/ # Project data (tasks, notes, sessions, skills); gitignored
|
|
158
171
|
├── pyproject.toml # Project configuration
|
|
159
172
|
├── AGENTS.md # This file
|
|
160
|
-
|
|
161
|
-
└── .claude/ # Claude Code configuration + skills
|
|
173
|
+
└── README.md # Project overview
|
|
162
174
|
```
|
|
163
175
|
|
|
164
176
|
### Key Files Reference
|
|
@@ -167,14 +179,12 @@ ayder-cli/
|
|
|
167
179
|
|------|---------|
|
|
168
180
|
| `cli.py` | Entry point, argument parsing |
|
|
169
181
|
| `tui/app.py` | Main TUI application (AyderApp) |
|
|
170
|
-
| `tui/commands.py` | Slash command handlers
|
|
182
|
+
| `tui/commands.py` | Slash command handlers |
|
|
171
183
|
| `loops/chat_loop.py` | Async LLM + tool execution loop (ChatLoop + ChatCallbacks protocol) |
|
|
172
|
-
| `
|
|
173
|
-
| `cli_runner.py` | CLI command execution + sync agent loop |
|
|
184
|
+
| `cli_runner.py` | Single-command (non-TUI) runs |
|
|
174
185
|
| `application/runtime_factory.py` | `create_runtime()` — single composition root for CLI + TUI |
|
|
175
186
|
| `application/execution_policy.py` | Shared permission + tool execution policy |
|
|
176
187
|
| `application/validation.py` | ValidationAuthority + SchemaValidator (single validation path) |
|
|
177
|
-
| `loops/base.py` | AgentLoopBase shared by CLI and TUI loops |
|
|
178
188
|
| `tools/definition.py` | ToolDefinition dataclass + auto-discovery from `*_definitions.py` |
|
|
179
189
|
| `tools/registry.py` | ToolRegistry: schemas, execution, system prompts, tag filtering |
|
|
180
190
|
| `core/config.py` | Configuration with Pydantic validation |
|
|
@@ -183,7 +193,7 @@ ayder-cli/
|
|
|
183
193
|
| `providers/impl/ollama_drivers/` | Per-family Ollama chat-driver package (matrix, registry, drivers, error classifier) |
|
|
184
194
|
| `providers/impl/ollama_inspector.py` | `OllamaInspector` with `probe_native_tool_calling()` for empirical model verification |
|
|
185
195
|
| `docs/README_OLLAMA.md` | **Ollama tool-call compatibility guide.** Read before adding/changing any matrix routing for an Ollama model. Covers the `OllamaInspector.probe_native_tool_calling()` API, equivalent `curl` recipes, the markup-leak detection table, and the decision flow for new families. |
|
|
186
|
-
| `docs/
|
|
196
|
+
| `docs/GATE.md` | The gate procedure every PR's final SHA passes |
|
|
187
197
|
|
|
188
198
|
## Environment Setup
|
|
189
199
|
|
|
@@ -431,7 +441,7 @@ class TestFeature:
|
|
|
431
441
|
|
|
432
442
|
### Runtime Factory
|
|
433
443
|
|
|
434
|
-
`application/runtime_factory.py` provides `create_runtime()` — the single composition root used by both CLI and TUI. It assembles a `RuntimeComponents` dataclass containing: `config`, `llm_provider`, `process_manager`, `project_ctx`, `tool_registry`, `
|
|
444
|
+
`application/runtime_factory.py` provides `create_runtime()` — the single composition root used by both CLI and TUI. It assembles a `RuntimeComponents` dataclass containing: `config`, `llm_provider`, `process_manager`, `project_ctx`, `tool_registry`, `system_prompt`, `context_manager`, `environment_prompt`.
|
|
435
445
|
|
|
436
446
|
### Pluggable Tool System
|
|
437
447
|
|
|
@@ -460,23 +470,21 @@ TOOL_DEFINITIONS: tuple[ToolDefinition, ...] = (
|
|
|
460
470
|
)
|
|
461
471
|
```
|
|
462
472
|
|
|
463
|
-
**
|
|
473
|
+
**Built-in Tools** (plugins and MCP servers add more at runtime; `tests/test_agents_md.py` keeps this table in step with the registry):
|
|
464
474
|
|
|
465
475
|
| Category | Tag | Tools |
|
|
466
476
|
|----------|-----|-------|
|
|
467
477
|
| **Filesystem** | `core` | `file_explorer`, `read_file`, `file_editor` |
|
|
468
478
|
| **Search** | `core` | `search_codebase`, `get_project_structure` |
|
|
469
|
-
| **Shell** | `core` | `
|
|
470
|
-
| **
|
|
471
|
-
| **
|
|
472
|
-
| **
|
|
473
|
-
| **
|
|
474
|
-
| **
|
|
475
|
-
| **
|
|
479
|
+
| **Shell** | `core` | `bash` |
|
|
480
|
+
| **Session context** | `core` | `context` |
|
|
481
|
+
| **Skills** | `core` | `skill` |
|
|
482
|
+
| **Agents** | `core` | `agent` (registered when agents are configured) |
|
|
483
|
+
| **Notes** | `metadata` | `note` |
|
|
484
|
+
| **Tasks** | `metadata` | `task` |
|
|
485
|
+
| **Background Processes** | `background` | `background_process` |
|
|
476
486
|
| **Web** | `http` | `fetch_web` |
|
|
477
|
-
| **DBS** | `dbs` | `dbs_tool` (RAG API for DBS issues) |
|
|
478
487
|
| **Environment** | `env` | `manage_environment_vars` |
|
|
479
|
-
| **Temporal** | `temporal` | `temporal_workflow` |
|
|
480
488
|
|
|
481
489
|
**Tag System:** Tools are filtered by tags. Default enabled tags: `["core", "metadata"]`. Use `/plugin` in TUI to toggle additional tags at runtime.
|
|
482
490
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: ayder-cli
|
|
3
|
-
Version: 2.5.
|
|
3
|
+
Version: 2.5.2
|
|
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
|
|
@@ -82,7 +82,7 @@ LLMs on their own can only generate text. To be a useful coding assistant, the m
|
|
|
82
82
|
|
|
83
83
|
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.
|
|
84
84
|
|
|
85
|
-
- **Path sandboxing**: All file operations are confined to the project root via `ProjectContext`. Path traversal attacks (`../`) and absolute paths outside the project are blocked.
|
|
85
|
+
- **Path sandboxing**: All file operations are confined to the project root via `ProjectContext`. Path traversal attacks (`../`) and absolute paths outside the project are blocked. The one exception is the session scratch directory, `/tmp/ayder-<uid>/<project>-<hash>/<session>/` (mode 0700, one subdirectory per agent run), which the system prompt names as the place for temporary files and which the file tools accept. It is not cleaned up; the OS clears `/tmp`.
|
|
86
86
|
- **Safe mode** (TUI): Blocks `file_editor`, `run_shell_command`, `run_background_process`, `kill_background_process`, and `fetch_web`.
|
|
87
87
|
- Every tool call requires your confirmation before it runs -- you always stay in control. Use `-r`, `-w`, `-x` flags to auto-approve tool categories.
|
|
88
88
|
- You may also prefer to run ayder-cli in a container for additional security.
|
|
@@ -203,12 +203,12 @@ provider = "openai" # Active provider profile name
|
|
|
203
203
|
editor = "vim" # Editor for /task-edit command
|
|
204
204
|
verbose = false # Show file contents after write + LLM debug
|
|
205
205
|
max_background_processes = 5 # Max concurrent background processes (1-20)
|
|
206
|
-
max_iterations =
|
|
206
|
+
max_iterations = 200 # LLM calls per message before the loop stops (0 = unlimited)
|
|
207
207
|
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 = ["
|
|
211
|
+
# skills = ["development-workflow"] # or "none"; default: the built-in skills
|
|
212
212
|
agent_timeout = 300 # Seconds before a background agent is cancelled
|
|
213
213
|
|
|
214
214
|
[logging]
|
|
@@ -354,7 +354,8 @@ ayder -f instructions.txt
|
|
|
354
354
|
ayder --stdin < prompt.txt
|
|
355
355
|
|
|
356
356
|
# Override the main LLM system prompt with a file
|
|
357
|
-
# (
|
|
357
|
+
# (the environment section with working directory and start time,
|
|
358
|
+
# and the tool instructions, are still appended)
|
|
358
359
|
ayder --system-prompt prompt-file.md "refactor this code"
|
|
359
360
|
```
|
|
360
361
|
|
|
@@ -478,8 +479,9 @@ later one overrides an earlier one with the same name:
|
|
|
478
479
|
2. your skills in `~/.ayder/skills/<name>/`
|
|
479
480
|
3. project skills in `<project>/.ayder/skills/<name>/`
|
|
480
481
|
|
|
481
|
-
ayder ships
|
|
482
|
-
|
|
482
|
+
ayder ships a `development-workflow` skill for multi-step software work: a plan
|
|
483
|
+
note and tasks, approval before any project file changes, then execution with
|
|
484
|
+
per-task status. Small edits and questions skip it. The system prompt is a general assistant;
|
|
483
485
|
when a skill fits the request, the model loads it itself.
|
|
484
486
|
|
|
485
487
|
The skills enabled for a session are listed in the system prompt under
|
|
@@ -488,7 +490,7 @@ model. The `skills` setting chooses them:
|
|
|
488
490
|
|
|
489
491
|
| `skills` | Enabled skills |
|
|
490
492
|
|---|---|
|
|
491
|
-
| not set | the built-in skills (`
|
|
493
|
+
| not set | the built-in skills (`development-workflow`), including your or the project's copy of the same name |
|
|
492
494
|
| `"none"` or `[]` | none: no skill tool, no catalog |
|
|
493
495
|
| `["a", "b"]` | exactly these names, from any layer |
|
|
494
496
|
|
|
@@ -584,7 +586,7 @@ ayder-cli includes a built-in task system:
|
|
|
584
586
|
|
|
585
587
|
Tasks are stored as markdown files in `.ayder/tasks/` using slug-based filenames (e.g., `TASK-001-add-auth-middleware.md`).
|
|
586
588
|
|
|
587
|
-
The `task` tool resolves identifiers (a path, filename, ID or slug) only to files inside `.ayder/tasks/`. An identifier that points elsewhere, including through a symlink, is not resolved. If `.ayder/tasks/`, `.ayder/context/` or `.ayder/notes/` itself resolves outside the project, those tools return a security error.
|
|
589
|
+
The `task` tool resolves identifiers (a path, filename, ID or slug) only to files inside `.ayder/tasks/`. An identifier that points elsewhere, including through a symlink, is not resolved. If `.ayder/tasks/`, `.ayder/context/` or `.ayder/notes/` itself resolves outside the project, those tools return a security error. An ID (`7`, `007`, `TASK-007`) matches only that task. A slug must match one task (an exact slug wins); if several match, the tool lists them and asks for the ID. `section` names a `##` heading; the `#` title is never a section.
|
|
588
590
|
|
|
589
591
|
```
|
|
590
592
|
> /tasks # Interactive task browser
|
|
@@ -774,7 +776,8 @@ project root, then start Ayder:
|
|
|
774
776
|
"local-tools": {
|
|
775
777
|
"command": "python",
|
|
776
778
|
"args": ["server.py"],
|
|
777
|
-
"env": {"EXAMPLE_SETTING": "value"}
|
|
779
|
+
"env": {"EXAMPLE_SETTING": "value"},
|
|
780
|
+
"parallel": false
|
|
778
781
|
},
|
|
779
782
|
"remote-tools": {
|
|
780
783
|
"url": "http://localhost:8000/mcp"
|
|
@@ -790,6 +793,16 @@ is needed. Tool calls retain the usual permissions: `x` for stdio servers and
|
|
|
790
793
|
`http` for HTTP servers. Configure only servers you intend Ayder to connect to:
|
|
791
794
|
local server commands start during runtime initialization to discover tools.
|
|
792
795
|
|
|
796
|
+
Calls to MCP tools in one response run at the same time by default. Set
|
|
797
|
+
`"parallel": false` on a server to run its calls one at a time, in the order the
|
|
798
|
+
model sent them. Do this for servers that write local files, so a read sent in
|
|
799
|
+
the same response cannot see the file before the write. `"parallel": true` runs
|
|
800
|
+
all of a server's tools concurrently, whatever the server declares. Without the
|
|
801
|
+
key, the server's own tool annotations decide: a tool marked `readOnlyHint`
|
|
802
|
+
runs concurrently, and one marked `readOnlyHint: false` or `destructiveHint`
|
|
803
|
+
runs alone. MCP calls always wait for built-in tools that change things
|
|
804
|
+
(`file_editor`, `bash`, ...) sent before them.
|
|
805
|
+
|
|
793
806
|
Tools keep their server-provided names unless they conflict with an existing
|
|
794
807
|
tool; conflicting names receive a `server__` prefix (and a numeric suffix if
|
|
795
808
|
needed). Unreachable servers are skipped so other tools remain available.
|
|
@@ -39,7 +39,7 @@ LLMs on their own can only generate text. To be a useful coding assistant, the m
|
|
|
39
39
|
|
|
40
40
|
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.
|
|
41
41
|
|
|
42
|
-
- **Path sandboxing**: All file operations are confined to the project root via `ProjectContext`. Path traversal attacks (`../`) and absolute paths outside the project are blocked.
|
|
42
|
+
- **Path sandboxing**: All file operations are confined to the project root via `ProjectContext`. Path traversal attacks (`../`) and absolute paths outside the project are blocked. The one exception is the session scratch directory, `/tmp/ayder-<uid>/<project>-<hash>/<session>/` (mode 0700, one subdirectory per agent run), which the system prompt names as the place for temporary files and which the file tools accept. It is not cleaned up; the OS clears `/tmp`.
|
|
43
43
|
- **Safe mode** (TUI): Blocks `file_editor`, `run_shell_command`, `run_background_process`, `kill_background_process`, and `fetch_web`.
|
|
44
44
|
- Every tool call requires your confirmation before it runs -- you always stay in control. Use `-r`, `-w`, `-x` flags to auto-approve tool categories.
|
|
45
45
|
- You may also prefer to run ayder-cli in a container for additional security.
|
|
@@ -160,12 +160,12 @@ provider = "openai" # Active provider profile name
|
|
|
160
160
|
editor = "vim" # Editor for /task-edit command
|
|
161
161
|
verbose = false # Show file contents after write + LLM debug
|
|
162
162
|
max_background_processes = 5 # Max concurrent background processes (1-20)
|
|
163
|
-
max_iterations =
|
|
163
|
+
max_iterations = 200 # LLM calls per message before the loop stops (0 = unlimited)
|
|
164
164
|
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 = ["
|
|
168
|
+
# skills = ["development-workflow"] # or "none"; default: the built-in skills
|
|
169
169
|
agent_timeout = 300 # Seconds before a background agent is cancelled
|
|
170
170
|
|
|
171
171
|
[logging]
|
|
@@ -311,7 +311,8 @@ ayder -f instructions.txt
|
|
|
311
311
|
ayder --stdin < prompt.txt
|
|
312
312
|
|
|
313
313
|
# Override the main LLM system prompt with a file
|
|
314
|
-
# (
|
|
314
|
+
# (the environment section with working directory and start time,
|
|
315
|
+
# and the tool instructions, are still appended)
|
|
315
316
|
ayder --system-prompt prompt-file.md "refactor this code"
|
|
316
317
|
```
|
|
317
318
|
|
|
@@ -435,8 +436,9 @@ later one overrides an earlier one with the same name:
|
|
|
435
436
|
2. your skills in `~/.ayder/skills/<name>/`
|
|
436
437
|
3. project skills in `<project>/.ayder/skills/<name>/`
|
|
437
438
|
|
|
438
|
-
ayder ships
|
|
439
|
-
|
|
439
|
+
ayder ships a `development-workflow` skill for multi-step software work: a plan
|
|
440
|
+
note and tasks, approval before any project file changes, then execution with
|
|
441
|
+
per-task status. Small edits and questions skip it. The system prompt is a general assistant;
|
|
440
442
|
when a skill fits the request, the model loads it itself.
|
|
441
443
|
|
|
442
444
|
The skills enabled for a session are listed in the system prompt under
|
|
@@ -445,7 +447,7 @@ model. The `skills` setting chooses them:
|
|
|
445
447
|
|
|
446
448
|
| `skills` | Enabled skills |
|
|
447
449
|
|---|---|
|
|
448
|
-
| not set | the built-in skills (`
|
|
450
|
+
| not set | the built-in skills (`development-workflow`), including your or the project's copy of the same name |
|
|
449
451
|
| `"none"` or `[]` | none: no skill tool, no catalog |
|
|
450
452
|
| `["a", "b"]` | exactly these names, from any layer |
|
|
451
453
|
|
|
@@ -541,7 +543,7 @@ ayder-cli includes a built-in task system:
|
|
|
541
543
|
|
|
542
544
|
Tasks are stored as markdown files in `.ayder/tasks/` using slug-based filenames (e.g., `TASK-001-add-auth-middleware.md`).
|
|
543
545
|
|
|
544
|
-
The `task` tool resolves identifiers (a path, filename, ID or slug) only to files inside `.ayder/tasks/`. An identifier that points elsewhere, including through a symlink, is not resolved. If `.ayder/tasks/`, `.ayder/context/` or `.ayder/notes/` itself resolves outside the project, those tools return a security error.
|
|
546
|
+
The `task` tool resolves identifiers (a path, filename, ID or slug) only to files inside `.ayder/tasks/`. An identifier that points elsewhere, including through a symlink, is not resolved. If `.ayder/tasks/`, `.ayder/context/` or `.ayder/notes/` itself resolves outside the project, those tools return a security error. An ID (`7`, `007`, `TASK-007`) matches only that task. A slug must match one task (an exact slug wins); if several match, the tool lists them and asks for the ID. `section` names a `##` heading; the `#` title is never a section.
|
|
545
547
|
|
|
546
548
|
```
|
|
547
549
|
> /tasks # Interactive task browser
|
|
@@ -731,7 +733,8 @@ project root, then start Ayder:
|
|
|
731
733
|
"local-tools": {
|
|
732
734
|
"command": "python",
|
|
733
735
|
"args": ["server.py"],
|
|
734
|
-
"env": {"EXAMPLE_SETTING": "value"}
|
|
736
|
+
"env": {"EXAMPLE_SETTING": "value"},
|
|
737
|
+
"parallel": false
|
|
735
738
|
},
|
|
736
739
|
"remote-tools": {
|
|
737
740
|
"url": "http://localhost:8000/mcp"
|
|
@@ -747,6 +750,16 @@ is needed. Tool calls retain the usual permissions: `x` for stdio servers and
|
|
|
747
750
|
`http` for HTTP servers. Configure only servers you intend Ayder to connect to:
|
|
748
751
|
local server commands start during runtime initialization to discover tools.
|
|
749
752
|
|
|
753
|
+
Calls to MCP tools in one response run at the same time by default. Set
|
|
754
|
+
`"parallel": false` on a server to run its calls one at a time, in the order the
|
|
755
|
+
model sent them. Do this for servers that write local files, so a read sent in
|
|
756
|
+
the same response cannot see the file before the write. `"parallel": true` runs
|
|
757
|
+
all of a server's tools concurrently, whatever the server declares. Without the
|
|
758
|
+
key, the server's own tool annotations decide: a tool marked `readOnlyHint`
|
|
759
|
+
runs concurrently, and one marked `readOnlyHint: false` or `destructiveHint`
|
|
760
|
+
runs alone. MCP calls always wait for built-in tools that change things
|
|
761
|
+
(`file_editor`, `bash`, ...) sent before them.
|
|
762
|
+
|
|
750
763
|
Tools keep their server-provided names unless they conflict with an existing
|
|
751
764
|
tool; conflicting names receive a `server__` prefix (and a numeric suffix if
|
|
752
765
|
needed). Unreachable servers are skipped so other tools remain available.
|
|
@@ -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: `2909 passed, 2 skipped` on `fix/docs-skill-list-2.5.2` (2026-10-22, release 2.5.2).
|
|
16
16
|
|
|
17
17
|
## Report format
|
|
18
18
|
|
|
@@ -97,10 +97,10 @@ ayder-cli is an AI agent chat client with a modular, layered architecture:
|
|
|
97
97
|
1. **Layered Architecture**: Clear separation between entry → app → service → core → tools
|
|
98
98
|
2. **Protocol-Based**: `ChatCallbacks` protocol decouples the chat loop from UI concerns; `InteractionSink` decouples LLM providers from UI for debug events
|
|
99
99
|
3. **Single Composition Root**: `application/runtime_factory.create_runtime()` assembles all dependencies — no duplicated wiring between CLI and TUI
|
|
100
|
-
4. **Single Loop**: `ChatLoop` (in `loops/chat_loop.py`) owns the full async LLM + tool execution loop; both CLI and TUI route through it
|
|
100
|
+
4. **Single Loop**: `ChatLoop` (in `loops/chat_loop.py`) owns the full async LLM + tool execution loop; both CLI and TUI route through it. A run ends on a text-only reply, a cancel, an error, `max_iterations` LLM calls (`[app]` 200, agents 100), or 3 reasoning-only replies in a row; from the 3rd identical tool call in a row, the result carries a `[harness]` note
|
|
101
101
|
5. **Single Execution Path**: `ExecutionPolicy.execute_with_registry()` is the sole tool execution entry point; validation → permission → execute, no inline policy in loop code
|
|
102
102
|
6. **Single Validation Path**: `ValidationAuthority → SchemaValidator` is the only validation stage; schema derived from live `TOOL_DEFINITIONS` registry (no hardcoded lists)
|
|
103
|
-
7. **Sandboxed Paths**: All file operations go through `ProjectContext` for security
|
|
103
|
+
7. **Sandboxed Paths**: All file operations go through `ProjectContext` for security (project root plus the session scratch directory from `new_scratch_dir`). Only a path outside the sandbox (`PathOutsideSandboxError`) is reported as a security error; other bad input, such as a binary file or a non-numeric line number, is a validation error
|
|
104
104
|
8. **Single Execution Engine**: Both TUI and CLI drive `ChatLoop.run()` through the `ChatCallbacks` protocol (`AppCallbacks` and `CliCallbacks` respectively); CLI runs it via `asyncio.run`
|
|
105
105
|
|
|
106
106
|
---
|
|
@@ -293,7 +293,7 @@ the design rationale.
|
|
|
293
293
|
| `tools/plugin_github.py` | GitHub-sourced plugin fetcher | remote-plugin loader |
|
|
294
294
|
| `tools/builtins/filesystem.py` | File system tool impls | `file_explorer()`, `read_file()`, `file_editor()` |
|
|
295
295
|
| `tools/builtins/search.py` | Search tool impls | `search_codebase()`, `get_project_structure()` |
|
|
296
|
-
| `tools/builtins/shell.py` | Shell execution impl | `bash()` |
|
|
296
|
+
| `tools/builtins/shell.py` | Shell execution impl: own session, closed stdin, prompts/pagers off (`GIT_TERMINAL_PROMPT=0`, `PAGER`/`GIT_PAGER=cat`; `environment` overrides), process-group kill on timeout with partial output, per-stream output bounds | `bash()` |
|
|
297
297
|
| `tools/builtins/context.py` | Session context snapshots | `context` |
|
|
298
298
|
| `tools/builtins/notes.py` | Note-taking tool | `create_note()` |
|
|
299
299
|
| `tools/builtins/tasks.py` | Task-management tools | `list_tasks()`, `show_task()` |
|
|
@@ -306,7 +306,7 @@ the design rationale.
|
|
|
306
306
|
|
|
307
307
|
| Module | Purpose | Key Classes/Functions |
|
|
308
308
|
|--------|---------|----------------------|
|
|
309
|
-
| `process_manager.py` | Background processes | `ProcessManager`, `background_process()` |
|
|
309
|
+
| `process_manager.py` | Background processes (closed stdin; `stop` and exit cleanup kill the whole process group, also after the leader exited) | `ProcessManager`, `background_process()` |
|
|
310
310
|
| `prompts.py` | System prompts | `SYSTEM_PROMPT`, `PLANNING_PROMPT_TEMPLATE`, `get_system_prompt()` |
|
|
311
311
|
| `parser.py` | XML tool-call parsing | `parse_custom_tool_calls()` |
|
|
312
312
|
|
|
@@ -594,7 +594,7 @@ AyderApp is the main Textual application implementing a chat-style interface:
|
|
|
594
594
|
The application manages:
|
|
595
595
|
- LLM provider setup and configuration
|
|
596
596
|
- Tool registry initialization with middleware
|
|
597
|
-
- System prompt construction (base prompt + tool prompts + skill catalog; no project tree)
|
|
597
|
+
- System prompt construction (base prompt + environment section + tool prompts + skill catalog; no project tree). The environment section (`prompts.build_environment_prompt`) gives the absolute working directory and the session start date and time (ISO 8601, local time with UTC offset). It is built once per session and reused on `/model` rebuilds. A resumed session (`--resume`) restores the provider it last used (the session file stores it; a provider no longer configured falls back to the default with a warning) and its `--system-prompt` text, keeps its history, and rebuilds the system prompt for the current session, so the scratch directory, start time, tool prompts and agent capability prompts are current; `/model` rebuilds keep the capability prompts.
|
|
598
598
|
- Process manager for background operations
|
|
599
599
|
|
|
600
600
|
### Chat Loop Summary (src/ayder_cli/loops/chat_loop.py)
|
|
@@ -609,7 +609,7 @@ previously-split `AgentLoopBase` and `LoopConfig` were merged back in):
|
|
|
609
609
|
- Routes *every* LLM response through the injected `ContextManagerProtocol` (`prepare_messages()` / `update_from_response()`); tool outputs are truncated at insertion time via `truncate_tool_result()` so the KV-cache prefix remains stable
|
|
610
610
|
|
|
611
611
|
Key features:
|
|
612
|
-
-
|
|
612
|
+
- Tool calls run in emission order. Consecutive calls that are parallel-safe (`ToolDefinition.parallel_safe`, default False) and auto-approved run concurrently (`asyncio.as_completed`). Every other call runs alone, after confirmation if required. Once the user answers a confirmation with instructions, no later call in the batch runs. MCP tools default to parallel-safe; `.ayder/mcp.json` `"parallel"` and the tools' annotations override that
|
|
613
613
|
- Confirmation gate applies to **both** OpenAI-format and XML/JSON custom tool calls
|
|
614
614
|
- `ExecutionPolicy.execute_with_registry()` is the single execution entry (object check → `canonicalize_arguments()` → validate → permission → execute). Canonicalization applies aliases and `"123"`/`"true"`/`"false"` coercion; the loop's required-argument gate uses the same function
|
|
615
615
|
- Argument integrity: `_parse_tool_arguments()` reports `ok`, `repaired` or `invalid`. Non-object arguments never run. Arguments repaired after being cut off (output token limit) run only for tools registered explicitly as `r`; other tools get an error asking the model to resend in smaller calls
|
|
@@ -645,6 +645,7 @@ Schema-driven tool definitions with auto-discovery:
|
|
|
645
645
|
- **Required-tool validation**: Raises `ImportError` if core tools (`file_explorer`, `read_file`, `file_editor`, `bash`) are absent
|
|
646
646
|
- **Permissions**: `"r"` (read), `"w"` (write), `"x"` (execute), `"http"` (network)
|
|
647
647
|
- **Safety flags**: `safe_mode_blocked`, `is_terminal` per definition
|
|
648
|
+
- **Scheduling**: `parallel_safe` per definition: a bool, or a predicate over the call's arguments (`parallel_safe_when("action", ...)`); unknown tools are never parallel-safe
|
|
648
649
|
- **Path parameters**: Names listed in `path_parameters` are automatically resolved via `ProjectContext`
|
|
649
650
|
- **Aliases**: `parameter_aliases` tuples for common name normalisation
|
|
650
651
|
- **Schema generation**: `to_openai_schema()` returns the OpenAI function-calling dict
|
|
@@ -92,6 +92,8 @@ max_output_tokens = 8192 # orchestrator response cap
|
|
|
92
92
|
# window on a large-context model and wastes most of it. Set a finite number
|
|
93
93
|
# only if you want a hard message cap regardless of window size.
|
|
94
94
|
max_history_messages = 0
|
|
95
|
+
# LLM calls per user message before the loop stops and asks for input. 0 = unlimited.
|
|
96
|
+
max_iterations = 200
|
|
95
97
|
agent_timeout = 1800 # seconds before a background agent is cancelled (30 min; reasoning+coding can be slow)
|
|
96
98
|
# Tools the agents inherit. A coding harness needs file/shell/search (core),
|
|
97
99
|
# tasks/notes (metadata), background process control for test suites
|
|
@@ -100,7 +102,7 @@ tool_tags = ["core", "metadata", "background", "http"]
|
|
|
100
102
|
# Skills the session's model may load (listed under "### Skills" in the system
|
|
101
103
|
# prompt). Not set = the built-in skills; "none" = no skill tool; or a strict
|
|
102
104
|
# list. A [llm.*] profile's skills wins over this one for the session.
|
|
103
|
-
# skills = ["
|
|
105
|
+
# skills = ["development-workflow"]
|
|
104
106
|
|
|
105
107
|
[ui]
|
|
106
108
|
# TUI layout (theme) — picks the chrome/layout:
|
|
@@ -229,9 +231,10 @@ think = true # default; set false if the selected model r
|
|
|
229
231
|
[agents.pm_spec]
|
|
230
232
|
provider = "ollama_cloud"
|
|
231
233
|
model = "glm-5.2:cloud"
|
|
232
|
-
# skills = ["
|
|
234
|
+
# skills = ["development-workflow"] # wins over the provider profile's skills; [app] is never read
|
|
233
235
|
temperature = 0.4
|
|
234
236
|
max_output_tokens = 8192
|
|
237
|
+
# max_iterations = 100 # LLM calls per run (default 100; 0 = unlimited)
|
|
235
238
|
reasoning_effort = "high"
|
|
236
239
|
system_prompt = """
|
|
237
240
|
You are Project Manager #1 — the requirements analyst and spec author.
|
|
@@ -31,6 +31,8 @@ class AgentConfig(BaseModel):
|
|
|
31
31
|
num_ctx: int | None = None
|
|
32
32
|
temperature: float | None = None
|
|
33
33
|
max_output_tokens: int | None = None
|
|
34
|
+
# LLM calls per run before the loop stops; None = 100, 0 = unlimited.
|
|
35
|
+
max_iterations: int | None = None
|
|
34
36
|
think: ThinkOption = None
|
|
35
37
|
reasoning_effort: ReasoningEffort = None
|
|
36
38
|
# None: the provider profile's setting; "none" or a list: see Config.skills.
|
|
@@ -57,7 +59,7 @@ class AgentConfig(BaseModel):
|
|
|
57
59
|
new_data[key] = float(val)
|
|
58
60
|
except ValueError:
|
|
59
61
|
pass
|
|
60
|
-
for key in ("num_ctx", "max_output_tokens"):
|
|
62
|
+
for key in ("num_ctx", "max_output_tokens", "max_iterations"):
|
|
61
63
|
val = new_data.get(key)
|
|
62
64
|
if isinstance(val, str) and val.strip():
|
|
63
65
|
try:
|
|
@@ -384,7 +384,9 @@ class AgentRegistry:
|
|
|
384
384
|
worktree_path = wt_dir
|
|
385
385
|
self._session_worktrees.add(wt_dir)
|
|
386
386
|
run.worktree_path = wt_dir
|
|
387
|
-
project_ctx = ProjectContext(
|
|
387
|
+
project_ctx = ProjectContext(
|
|
388
|
+
wt_dir, scratch_dir=self._project_ctx.scratch_dir
|
|
389
|
+
)
|
|
388
390
|
head_before = await asyncio.to_thread(
|
|
389
391
|
branch_head, repo_root, run.branch_name
|
|
390
392
|
)
|