ayder-cli 2.5.0__tar.gz → 2.5.1__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.1}/.github/workflows/python-package.yml +3 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/PKG-INFO +9 -7
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/README.md +8 -6
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/docs/GATE.md +1 -1
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/docs/PROJECT_STRUCTURE.md +2 -2
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/docs/config.toml.example +2 -2
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/pyproject.toml +1 -1
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/agents/registry.py +3 -1
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/application/runtime_factory.py +26 -3
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/core/context.py +65 -3
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/core/skills.py +2 -1
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/prompts.py +52 -0
- ayder_cli-2.5.1/src/ayder_cli/skills/development-workflow/SKILL.md +27 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/tools/builtins/filesystem_definitions.py +4 -4
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/tools/builtins/shell_definitions.py +2 -1
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/tools/builtins/task_definitions.py +12 -5
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/tools/builtins/task_tool.py +107 -12
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/tools/definition.py +22 -1
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/tui/app.py +3 -2
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/agents/test_worktree_isolation.py +27 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/application/test_runtime_factory.py +3 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/conftest.py +9 -0
- ayder_cli-2.5.1/tests/core/test_scratch_dir.py +115 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/core/test_skills.py +4 -1
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/core/test_skills_builtin_sync.py +4 -4
- ayder_cli-2.5.1/tests/test_prompts_environment.py +102 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/tools/test_definition_discovery.py +39 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/tools/test_skill_tool.py +1 -1
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/tools/test_task_tool.py +114 -3
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/ui/test_tui_system_prompt_no_structure.py +10 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/uv.lock +2 -2
- ayder_cli-2.5.0/src/ayder_cli/skills/engineering/SKILL.md +0 -35
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/.github/workflows/ci.yml +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/.gitignore +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/.python-version +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/AGENTS.md +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/LICENSE +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/docs/README_AGENT_WORKFLOW.md +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/docs/README_OLLAMA.md +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/docs/cc.png +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/docs/superpowers/plans/2026-06-26-file-editor-improvements.md +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/docs/superpowers/plans/2026-06-26-session-save-resume.md +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/docs/superpowers/specs/2026-06-26-file-editor-improvements-design.md +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/docs/superpowers/specs/2026-06-26-session-save-resume-design.md +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/scripts/check_exception_handlers.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/scripts/check_log_arguments.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/scripts/check_logging_imports.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/scripts/exception_baseline.txt +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/scripts/find_percent_logging.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/scripts/log_argument_baseline.txt +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/scripts/logging_gates.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/__init__.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/__main__.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/agents/__init__.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/agents/callbacks.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/agents/config.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/agents/run.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/agents/runner.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/agents/tool.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/agents/worktree.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/application/README.md +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/application/__init__.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/application/execution_policy.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/application/message_contract.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/application/validation.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/cli.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/cli_callbacks.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/cli_runner.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/console.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/core/cache_monitor.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/core/config.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/core/config_migration.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/core/context_manager.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/core/context_manager_factory.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/core/default_context_manager.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/core/ollama_context_manager.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/core/reasoning.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/core/result.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/core/session.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/diagnostics.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/log.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/logging_config.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/loops/__init__.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/loops/chat_loop.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/masking.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/parser.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/process_manager.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/providers/__init__.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/providers/base.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/providers/evren.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/providers/impl/claude.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/providers/impl/deepseek.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/providers/impl/gemini.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/providers/impl/glm.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/providers/impl/ollama.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/providers/impl/ollama_drivers/__init__.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/providers/impl/ollama_drivers/_errors.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/providers/impl/ollama_drivers/base.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/providers/impl/ollama_drivers/deepseek.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/providers/impl/ollama_drivers/generic_native.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/providers/impl/ollama_drivers/generic_xml.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/providers/impl/ollama_drivers/matrix.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/providers/impl/ollama_drivers/minimax.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/providers/impl/ollama_drivers/qwen3.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/providers/impl/ollama_drivers/registry.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/providers/impl/ollama_inspector.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/providers/impl/openai.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/providers/impl/qwen.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/providers/orchestrator.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/providers/retry.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/services/__init__.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/services/interactions.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/services/messaging_inbox.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/themes/__init__.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/themes/ayder.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/themes/claude.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/tools/__init__.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/tools/builtins/__init__.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/tools/builtins/background_process_tool.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/tools/builtins/context.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/tools/builtins/context_definitions.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/tools/builtins/filesystem.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/tools/builtins/note_tool.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/tools/builtins/notes.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/tools/builtins/notes_definitions.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/tools/builtins/process_manager_definitions.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/tools/builtins/search.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/tools/builtins/search_definitions.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/tools/builtins/shell.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/tools/builtins/skill.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/tools/builtins/skill_definitions.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/tools/builtins/tasks.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/tools/builtins/utils_tools.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/tools/builtins/utils_tools_definitions.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/tools/builtins/web.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/tools/builtins/web_definitions.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/tools/execution.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/tools/hooks.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/tools/mcp.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/tools/mcp_client.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/tools/normalization.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/tools/plugin_api.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/tools/plugin_github.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/tools/plugin_manager.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/tools/plugin_status.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/tools/registry.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/tools/schemas.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/tools/utils.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/tui/__init__.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/tui/adapter.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/tui/commands.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/tui/helpers.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/tui/keybindings.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/tui/parser.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/tui/rendering.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/tui/screens.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/tui/theme_manager.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/tui/types.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/tui/widgets.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/ui.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/version.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/COVERAGE.md +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/__init__.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/agents/__init__.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/agents/test_agent_consolidated.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/agents/test_agent_severity.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/agents/test_agent_tools.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/agents/test_callbacks.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/agents/test_config.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/agents/test_integration.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/agents/test_queue.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/agents/test_registry.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/agents/test_run.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/agents/test_runner.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/agents/test_runner_provider_unavailable.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/agents/test_tool.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/agents/test_worktree_helpers.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/application/test_argument_canonicalization.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/application/test_execution_result_truthfulness.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/application/test_message_contract.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/client/test_main.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/convergence/__init__.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/convergence/test_execution_policy_parity.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/convergence/test_runtime_wiring.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/convergence/test_validation_path.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/core/test_asyncio_bridge.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/core/test_cache_monitor.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/core/test_config.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/core/test_config_coverage.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/core/test_config_migration.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/core/test_config_provider_logging.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/core/test_config_retry.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/core/test_config_skills.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/core/test_config_v2.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/core/test_context_manager_factory.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/core/test_default_config_evren.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/core/test_default_context_manager.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/core/test_default_context_manager_should_compact.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/core/test_default_context_newest_unit.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/core/test_default_context_skill_resupply.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/core/test_event_emission.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/core/test_event_stream.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/core/test_exception_guarantee.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/core/test_exception_hooks.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/core/test_log_facade.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/core/test_logging_config_keys.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/core/test_logging_sinks.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/core/test_loguru_caplog.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/core/test_max_output_tokens_default.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/core/test_ollama_compaction_persistence.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/core/test_ollama_context_manager.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/core/test_ollama_context_manager_cache_monitor.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/core/test_ollama_context_manager_max_history.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/core/test_ollama_skill_resupply.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/core/test_parameter_aliasing.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/core/test_parser.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/core/test_reasoning_config.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/core/test_session.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/core/test_session_id_threading.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/core/test_sink_masking.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/loops/__init__.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/loops/test_base.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/loops/test_chat_loop_hook.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/loops/test_chat_loop_tool_truncation.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/loops/test_loop_severity.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/loops/test_required_args_aliases.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/loops/test_tool_argument_integrity.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/loops/test_tool_batch_cancellation.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/providers/__init__.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/providers/ollama_drivers/__init__.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/providers/ollama_drivers/test_base.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/providers/ollama_drivers/test_deepseek.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/providers/ollama_drivers/test_errors.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/providers/ollama_drivers/test_fallback.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/providers/ollama_drivers/test_generic_native.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/providers/ollama_drivers/test_generic_xml.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/providers/ollama_drivers/test_matrix.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/providers/ollama_drivers/test_minimax.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/providers/ollama_drivers/test_provider_integration.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/providers/ollama_drivers/test_qwen3.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/providers/ollama_drivers/test_registry.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/providers/test_claude_stream_tool_calls.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/providers/test_evren.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/providers/test_gemini_function_calls.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/providers/test_glm_async.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/providers/test_ollama_inspector.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/providers/test_ollama_native.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/providers/test_ollama_parallel_tool_call_ids.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/providers/test_ollama_xml.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/providers/test_ollama_xml_autoroute.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/providers/test_ollama_xml_usage.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/providers/test_openai_list_models.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/providers/test_orchestrator_capabilities.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/providers/test_provider_channel_binding.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/providers/test_provider_severity.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/providers/test_qwen_async.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/providers/test_reasoning_effort.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/providers/test_retry_classifier.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/providers/test_retry_integration.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/providers/test_retrying_provider.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/providers/test_skill_load_prefix.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/scripts/test_exception_gate.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/scripts/test_log_argument_gate.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/scripts/test_logging_policy_gates.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/scripts/test_loguru_private_shape.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/services/test_boundary.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/services/test_interaction_sink.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/services/test_messaging_inbox.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/test_cli.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/test_cli_callbacks.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/test_context.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/test_env_manager.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/test_logging_config.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/test_notes.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/test_process_manager.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/test_prompts_general.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/test_tasks.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/tools/__init__.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/tools/test_agent_notes.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/tools/test_background_process_tool.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/tools/test_bash_tool.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/tools/test_context_storage_confinement.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/tools/test_di_injection.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/tools/test_file_editor_hardening.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/tools/test_file_editor_size_limit.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/tools/test_impl.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/tools/test_impl_coverage.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/tools/test_mcp.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/tools/test_mcp_client.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/tools/test_note_tool.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/tools/test_notes_api.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/tools/test_notes_confinement.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/tools/test_path_security.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/tools/test_plugin_api.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/tools/test_plugin_github.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/tools/test_plugin_loading.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/tools/test_plugin_manager.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/tools/test_plugin_status.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/tools/test_registry.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/tools/test_registry_coverage.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/tools/test_result.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/tools/test_schemas.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/tools/test_search_codebase.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/tools/test_search_hardening.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/tools/test_skill_catalog_and_filter.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/tools/test_skill_scope_wiring.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/tools/test_task_path_confinement.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/tools/test_tool_severity.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/tools/test_unexpected_args.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/tools/test_utils.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/tools/test_web.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/tui/__init__.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/tui/test_agent_list_screen.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/tui/test_do_clear_coordination.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/tui/test_evren_terms.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/tui/test_follow_mode.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/tui/test_help_screen.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/tui/test_input_box.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/tui/test_keybindings.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/tui/test_multi_select_screen.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/tui/test_multiline_input.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/tui/test_paste.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/tui/test_peer_message_turn.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/tui/test_pending_compact_consumer.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/tui/test_pull_delivery.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/tui/test_resume.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/tui/test_status_bar_badges.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/tui/test_themes.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/tui/test_turn_consumer.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/tui/test_widgets.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/ui/test_confirm_screen.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/ui/test_diff_preview.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/ui/test_plugin_autoenable.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/ui/test_provider_switch.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/ui/test_run_tui_startup.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/ui/test_tui_assistant_sanitization.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/ui/test_tui_chat_loop.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/ui/test_tui_commands_agent.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/ui/test_tui_commands_effort.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/ui/test_tui_commands_logging.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/ui/test_tui_commands_plugin.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/ui/test_tui_commands_provider.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/ui/test_tui_commands_skill.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/ui/test_tui_helpers.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/ui/test_tui_temporal_command.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/ui/test_tui_widgets.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/ui/test_ui.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/ui/test_ui_coverage.py +0 -0
- {ayder_cli-2.5.0 → ayder_cli-2.5.1}/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
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: ayder-cli
|
|
3
|
-
Version: 2.5.
|
|
3
|
+
Version: 2.5.1
|
|
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.
|
|
@@ -208,7 +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 = ["
|
|
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
|
|
|
@@ -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.
|
|
@@ -165,7 +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 = ["
|
|
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
|
|
|
@@ -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: `2743 passed, 2 skipped` on `fix/session-environment-prompt` (2026-10-19, 2.5.1).
|
|
16
16
|
|
|
17
17
|
## Report format
|
|
18
18
|
|
|
@@ -100,7 +100,7 @@ ayder-cli is an AI agent chat client with a modular, layered architecture:
|
|
|
100
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
|
|
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`)
|
|
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
|
---
|
|
@@ -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.
|
|
598
598
|
- Process manager for background operations
|
|
599
599
|
|
|
600
600
|
### Chat Loop Summary (src/ayder_cli/loops/chat_loop.py)
|
|
@@ -100,7 +100,7 @@ tool_tags = ["core", "metadata", "background", "http"]
|
|
|
100
100
|
# Skills the session's model may load (listed under "### Skills" in the system
|
|
101
101
|
# prompt). Not set = the built-in skills; "none" = no skill tool; or a strict
|
|
102
102
|
# list. A [llm.*] profile's skills wins over this one for the session.
|
|
103
|
-
# skills = ["
|
|
103
|
+
# skills = ["development-workflow"]
|
|
104
104
|
|
|
105
105
|
[ui]
|
|
106
106
|
# TUI layout (theme) — picks the chrome/layout:
|
|
@@ -229,7 +229,7 @@ think = true # default; set false if the selected model r
|
|
|
229
229
|
[agents.pm_spec]
|
|
230
230
|
provider = "ollama_cloud"
|
|
231
231
|
model = "glm-5.2:cloud"
|
|
232
|
-
# skills = ["
|
|
232
|
+
# skills = ["development-workflow"] # wins over the provider profile's skills; [app] is never read
|
|
233
233
|
temperature = 0.4
|
|
234
234
|
max_output_tokens = 8192
|
|
235
235
|
reasoning_effort = "high"
|
|
@@ -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
|
)
|
|
@@ -6,7 +6,9 @@ eliminating the duplicate `_build_services()` / `AyderApp.__init__()` wiring.
|
|
|
6
6
|
|
|
7
7
|
from __future__ import annotations
|
|
8
8
|
|
|
9
|
+
import re
|
|
9
10
|
from dataclasses import dataclass, field
|
|
11
|
+
from datetime import datetime
|
|
10
12
|
from pathlib import Path
|
|
11
13
|
from typing import TYPE_CHECKING, Any
|
|
12
14
|
|
|
@@ -16,13 +18,14 @@ from ayder_cli.core.context_manager_factory import context_manager_factory
|
|
|
16
18
|
|
|
17
19
|
if TYPE_CHECKING:
|
|
18
20
|
from ayder_cli.agents.config import AgentConfig
|
|
19
|
-
from ayder_cli.core.context import ProjectContext
|
|
21
|
+
from ayder_cli.core.context import ProjectContext, new_scratch_dir
|
|
20
22
|
from ayder_cli.core.skills import build_scope
|
|
21
23
|
from ayder_cli.providers import AIProvider, provider_orchestrator
|
|
22
24
|
from ayder_cli.providers.retry import RetryConfig, RetryingProvider
|
|
23
25
|
from ayder_cli.tools.registry import ToolRegistry, create_default_registry
|
|
24
26
|
from ayder_cli.process_manager import ProcessManager
|
|
25
27
|
from ayder_cli.prompts import (
|
|
28
|
+
build_environment_prompt,
|
|
26
29
|
get_system_prompt,
|
|
27
30
|
)
|
|
28
31
|
from ayder_cli.log import get_logger
|
|
@@ -41,6 +44,7 @@ class RuntimeComponents:
|
|
|
41
44
|
tool_registry: ToolRegistry
|
|
42
45
|
system_prompt: str
|
|
43
46
|
context_manager: Any = field(default=None) # ContextManagerProtocol
|
|
47
|
+
environment_prompt: str = "" # frozen for the session; reused by TUI rebuilds
|
|
44
48
|
|
|
45
49
|
|
|
46
50
|
def apply_skill_setting(
|
|
@@ -95,6 +99,9 @@ def create_runtime(
|
|
|
95
99
|
|
|
96
100
|
llm_provider: AIProvider = provider_orchestrator.create(cfg)
|
|
97
101
|
project_ctx = ProjectContext(project_root)
|
|
102
|
+
scratch_dir = new_scratch_dir(project_ctx.root)
|
|
103
|
+
if scratch_dir is not None:
|
|
104
|
+
project_ctx.scratch_dir = scratch_dir.resolve()
|
|
98
105
|
process_manager = ProcessManager(max_processes=cfg.max_background_processes)
|
|
99
106
|
|
|
100
107
|
# Create context manager before registry so tools can receive it via DI.
|
|
@@ -111,9 +118,12 @@ def create_runtime(
|
|
|
111
118
|
base_prompt = system_prompt_override
|
|
112
119
|
else:
|
|
113
120
|
base_prompt = get_system_prompt(cfg.prompt)
|
|
121
|
+
environment_prompt = build_environment_prompt(
|
|
122
|
+
project_ctx.root, datetime.now().astimezone(), project_ctx.scratch_dir
|
|
123
|
+
)
|
|
114
124
|
tool_tags = frozenset(cfg.tool_tags) if cfg.tool_tags else None
|
|
115
125
|
tool_prompts = tool_registry.get_system_prompts(tags=tool_tags)
|
|
116
|
-
system_prompt = base_prompt + tool_prompts
|
|
126
|
+
system_prompt = base_prompt + environment_prompt + tool_prompts
|
|
117
127
|
|
|
118
128
|
# Freeze system prompt after tool schemas are known.
|
|
119
129
|
tool_schemas = tool_registry.get_schemas(tags=tool_tags)
|
|
@@ -129,6 +139,7 @@ def create_runtime(
|
|
|
129
139
|
tool_registry=tool_registry,
|
|
130
140
|
system_prompt=system_prompt,
|
|
131
141
|
context_manager=context_mgr,
|
|
142
|
+
environment_prompt=environment_prompt,
|
|
132
143
|
)
|
|
133
144
|
|
|
134
145
|
|
|
@@ -232,7 +243,19 @@ def create_agent_runtime(
|
|
|
232
243
|
)
|
|
233
244
|
tool_tags = frozenset(cfg.tool_tags) if cfg.tool_tags else None
|
|
234
245
|
tool_prompts = tool_registry.get_system_prompts(tags=tool_tags)
|
|
235
|
-
|
|
246
|
+
# Each run gets its own directory inside the session's scratch directory,
|
|
247
|
+
# which the shared ProjectContext already admits.
|
|
248
|
+
agent_scratch = None
|
|
249
|
+
if project_ctx.scratch_dir is not None:
|
|
250
|
+
label = "agent-" + re.sub(r"[^A-Za-z0-9_-]", "-", agent_config.name)
|
|
251
|
+
agent_scratch = new_scratch_dir(project_ctx.root, parent=project_ctx.scratch_dir, label=label)
|
|
252
|
+
environment_prompt = build_environment_prompt(
|
|
253
|
+
project_ctx.root, datetime.now().astimezone(), agent_scratch
|
|
254
|
+
)
|
|
255
|
+
system_prompt = (
|
|
256
|
+
identity_prefix + agent_config.system_prompt + environment_prompt
|
|
257
|
+
+ tool_prompts + deliverable_directive
|
|
258
|
+
)
|
|
236
259
|
|
|
237
260
|
# Freeze agent system prompt after tool schemas are known.
|
|
238
261
|
tool_schemas = tool_registry.get_schemas(tags=tool_tags)
|
|
@@ -1,7 +1,64 @@
|
|
|
1
|
+
import getpass
|
|
2
|
+
import hashlib
|
|
1
3
|
import os
|
|
4
|
+
import secrets
|
|
5
|
+
import stat
|
|
6
|
+
import tempfile
|
|
7
|
+
from datetime import datetime
|
|
2
8
|
from pathlib import Path
|
|
3
9
|
|
|
4
10
|
|
|
11
|
+
def _default_scratch_base() -> Path:
|
|
12
|
+
"""``/tmp/ayder-<uid>``: where models already look for temporary space."""
|
|
13
|
+
if hasattr(os, "getuid"):
|
|
14
|
+
return Path("/tmp") / f"ayder-{os.getuid()}"
|
|
15
|
+
return Path(tempfile.gettempdir()) / f"ayder-{getpass.getuser()}"
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
# Per-user parent of every session scratch directory; tests point it elsewhere.
|
|
19
|
+
SCRATCH_BASE = _default_scratch_base()
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def _owned_private_dir(path: Path) -> bool:
|
|
23
|
+
"""True when ``path`` itself (not a symlink) is a directory this user owns."""
|
|
24
|
+
st = os.lstat(path)
|
|
25
|
+
if not stat.S_ISDIR(st.st_mode):
|
|
26
|
+
return False
|
|
27
|
+
return not hasattr(os, "getuid") or st.st_uid == os.getuid()
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def new_scratch_dir(
|
|
31
|
+
project_root: Path | str, parent: Path | None = None, label: str = "agent"
|
|
32
|
+
) -> Path | None:
|
|
33
|
+
"""Create a private (0700) scratch directory and return it.
|
|
34
|
+
|
|
35
|
+
Without ``parent`` it is a session directory,
|
|
36
|
+
``SCRATCH_BASE/<project>-<hash>/<YYYYmmdd-HHMMSS>-<hex>``; with ``parent``
|
|
37
|
+
it is ``<parent>/<label>-<hex>``. Returns None when the per-user base is a
|
|
38
|
+
symlink, belongs to someone else, or cannot be created: the session then
|
|
39
|
+
runs without one and the sandbox stays the project root.
|
|
40
|
+
"""
|
|
41
|
+
try:
|
|
42
|
+
if parent is None:
|
|
43
|
+
SCRATCH_BASE.mkdir(mode=0o700, parents=True, exist_ok=True)
|
|
44
|
+
if not _owned_private_dir(SCRATCH_BASE):
|
|
45
|
+
return None
|
|
46
|
+
os.chmod(SCRATCH_BASE, 0o700)
|
|
47
|
+
root = Path(project_root).resolve()
|
|
48
|
+
digest = hashlib.sha256(str(root).encode("utf-8")).hexdigest()[:8]
|
|
49
|
+
folder = SCRATCH_BASE / f"{root.name}-{digest}"
|
|
50
|
+
folder.mkdir(mode=0o700, exist_ok=True)
|
|
51
|
+
name = f"{datetime.now():%Y%m%d-%H%M%S}-{secrets.token_hex(3)}"
|
|
52
|
+
else:
|
|
53
|
+
folder = Path(parent)
|
|
54
|
+
name = f"{label}-{secrets.token_hex(3)}"
|
|
55
|
+
path = folder / name
|
|
56
|
+
path.mkdir(mode=0o700)
|
|
57
|
+
return path
|
|
58
|
+
except OSError:
|
|
59
|
+
return None
|
|
60
|
+
|
|
61
|
+
|
|
5
62
|
class ProjectContext:
|
|
6
63
|
"""Handles path validation and translation between relative and absolute paths.
|
|
7
64
|
|
|
@@ -9,17 +66,21 @@ class ProjectContext:
|
|
|
9
66
|
macOS ~ paths.
|
|
10
67
|
"""
|
|
11
68
|
|
|
12
|
-
def __init__(self, root_dir: str = "."):
|
|
69
|
+
def __init__(self, root_dir: str = ".", scratch_dir: Path | str | None = None):
|
|
13
70
|
"""Initialize ProjectContext with a root directory.
|
|
14
71
|
|
|
15
72
|
Args:
|
|
16
73
|
root_dir: Root directory path (defaults to current directory)
|
|
74
|
+
scratch_dir: The session scratch directory, a second root the file
|
|
75
|
+
tools may use (see ``new_scratch_dir``); None allows only the root.
|
|
17
76
|
"""
|
|
18
77
|
expanded_root = os.path.expanduser(root_dir)
|
|
19
78
|
self.root = Path(expanded_root).resolve()
|
|
79
|
+
self.scratch_dir = Path(scratch_dir).resolve() if scratch_dir is not None else None
|
|
20
80
|
|
|
21
81
|
def validate_path(self, file_path: str) -> Path:
|
|
22
|
-
"""Validate and resolve a file path, ensuring it stays within the project root
|
|
82
|
+
"""Validate and resolve a file path, ensuring it stays within the project root
|
|
83
|
+
or the session scratch directory.
|
|
23
84
|
|
|
24
85
|
Args:
|
|
25
86
|
file_path: Path to validate (relative or absolute)
|
|
@@ -37,7 +98,8 @@ class ProjectContext:
|
|
|
37
98
|
else:
|
|
38
99
|
target_path = (self.root / clean_path).resolve()
|
|
39
100
|
|
|
40
|
-
|
|
101
|
+
in_scratch = self.scratch_dir is not None and target_path.is_relative_to(self.scratch_dir)
|
|
102
|
+
if not target_path.is_relative_to(self.root) and not in_scratch:
|
|
41
103
|
raise ValueError(
|
|
42
104
|
f"Security Alert: Path '{target_path}' is outside project root '{self.root}'"
|
|
43
105
|
)
|
|
@@ -365,7 +365,8 @@ def render_skill_block(info: SkillInfo) -> str | ToolError:
|
|
|
365
365
|
_, body = parse_frontmatter(text)
|
|
366
366
|
lines = [
|
|
367
367
|
f"{LOADED_MARKER}{info.name}",
|
|
368
|
-
|
|
368
|
+
# Layer only: models took the skill's absolute path for the project root.
|
|
369
|
+
f"Source: {info.layer}",
|
|
369
370
|
]
|
|
370
371
|
resources = skill_resources(info)
|
|
371
372
|
if resources:
|
|
@@ -4,6 +4,9 @@ Each prompt template is labeled with a comment indicating which module/function
|
|
|
4
4
|
is responsible for using it, along with the REASON for prompting the LLM.
|
|
5
5
|
"""
|
|
6
6
|
|
|
7
|
+
from datetime import datetime
|
|
8
|
+
from pathlib import Path
|
|
9
|
+
|
|
7
10
|
# =============================================================================
|
|
8
11
|
# CORE SYSTEM PROMPT
|
|
9
12
|
# =============================================================================
|
|
@@ -34,6 +37,55 @@ MINIMAL_SYSTEM_PROMPT = """You are a developer and coding assistant. Analyze und
|
|
|
34
37
|
|
|
35
38
|
EXTENDED_SYSTEM_PROMPT = STANDARD_SYSTEM_PROMPT
|
|
36
39
|
|
|
40
|
+
# =============================================================================
|
|
41
|
+
# SESSION ENVIRONMENT SECTION
|
|
42
|
+
# =============================================================================
|
|
43
|
+
# Used by: runtime_factory.create_runtime() / create_agent_runtime(), after the
|
|
44
|
+
# base prompt and before the tool prompts, for every tier and override.
|
|
45
|
+
# REASON: Without the project's absolute path a model guessed one (the home
|
|
46
|
+
# directory, from a skill header) and ran `git init` there. Built once per
|
|
47
|
+
# session so the frozen prompt and its cache prefix never change.
|
|
48
|
+
|
|
49
|
+
ENVIRONMENT_PROMPT = """
|
|
50
|
+
|
|
51
|
+
## Environment
|
|
52
|
+
Working directory: {working_directory}
|
|
53
|
+
Session start: {started_at}{scratch_line}
|
|
54
|
+
|
|
55
|
+
Your workspace is {workspace}.
|
|
56
|
+
Outside it, read only paths the user names or the task requires, and create,
|
|
57
|
+
modify or initialize nothing (including `git init`) without the user's consent.{scratch_rule}
|
|
58
|
+
"""
|
|
59
|
+
|
|
60
|
+
# REASON: Models put temporary files in /tmp by habit. A per-session directory
|
|
61
|
+
# there (core/context.py:new_scratch_dir) gives them a sanctioned place, and
|
|
62
|
+
# the file tools accept it. Omitted when the directory could not be created.
|
|
63
|
+
SCRATCH_LINE = "\nScratch directory: {scratch_dir}"
|
|
64
|
+
|
|
65
|
+
SCRATCH_RULE = "\nPut temporary files in the scratch directory, not in /tmp or ~/tmp."
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
def build_environment_prompt(
|
|
69
|
+
working_directory: Path, started_at: datetime, scratch_dir: Path | None = None
|
|
70
|
+
) -> str:
|
|
71
|
+
"""Render the session environment section for the system prompt.
|
|
72
|
+
|
|
73
|
+
``started_at`` should be timezone-aware local time; it renders as ISO 8601
|
|
74
|
+
to the minute with its UTC offset (e.g. 2026-10-19T03:33+03:00).
|
|
75
|
+
``scratch_dir`` adds the scratch directory line and its rule.
|
|
76
|
+
"""
|
|
77
|
+
return ENVIRONMENT_PROMPT.format(
|
|
78
|
+
working_directory=working_directory,
|
|
79
|
+
started_at=started_at.isoformat(timespec="minutes"),
|
|
80
|
+
workspace=(
|
|
81
|
+
"the working directory and the scratch directory"
|
|
82
|
+
if scratch_dir
|
|
83
|
+
else "the working directory"
|
|
84
|
+
),
|
|
85
|
+
scratch_line=SCRATCH_LINE.format(scratch_dir=scratch_dir) if scratch_dir else "",
|
|
86
|
+
scratch_rule=SCRATCH_RULE if scratch_dir else "",
|
|
87
|
+
)
|
|
88
|
+
|
|
37
89
|
# =============================================================================
|
|
38
90
|
# AGENTIC ORCHESTRATOR SYSTEM PROMPT
|
|
39
91
|
# =============================================================================
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: development-workflow
|
|
3
|
+
description: Multi-step software work - a new feature, a refactor, a bug whose cause is unknown, a change across several files. Not for small, obvious edits, quick fixes or questions that need no change.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Development workflow
|
|
7
|
+
|
|
8
|
+
1. Orient: read `AGENTS.md` and `README.md` if they exist, then the code the task touches.
|
|
9
|
+
2. Plan: write the plan with `note(action="create", note_id="plan-<slug>")`: the steps,
|
|
10
|
+
the files each step touches, and how each step is verified. Create one task per step,
|
|
11
|
+
in dependency order, with `task(action="create", title=..., body=..., dependencies=...)`.
|
|
12
|
+
Change no project files before the plan is approved.
|
|
13
|
+
3. Approve: show the user the steps and their verification, name the plan note, and end
|
|
14
|
+
your turn until the user approves. When the user asks for a reviewer agent, it
|
|
15
|
+
approves instead: find it with `agent(action="list")`, send it the plan with
|
|
16
|
+
`agent(action="call", name=..., task=...)`, and collect the verdict with
|
|
17
|
+
`agent(action="read_result", run_id=..., wait=true)`. On requested changes, update
|
|
18
|
+
the note and the tasks and ask again.
|
|
19
|
+
4. Execute: work through the tasks in order. Set each one `in_progress` with
|
|
20
|
+
`task(action="update_status", identifier=..., status="in_progress")` when you start
|
|
21
|
+
it, `done` when its verification passes, or `blocked` when you need the user, and
|
|
22
|
+
tell the user why. A large, parallelizable or specialized task can go to an agent with
|
|
23
|
+
`agent(action="call", task_id=...)`.
|
|
24
|
+
5. Report: one short line at plan created, task started, task done and final delivery.
|
|
25
|
+
The final delivery says what changed and how it was verified.
|
|
26
|
+
6. Finish: ask before committing, unless the user gave commit instructions. Then unload
|
|
27
|
+
this skill with `skill(action="unload", name="development-workflow")`.
|
|
@@ -115,21 +115,21 @@ TOOL_DEFINITIONS: Tuple[ToolDefinition, ...] = (
|
|
|
115
115
|
"content": {
|
|
116
116
|
"type": "string",
|
|
117
117
|
"description": (
|
|
118
|
-
"
|
|
118
|
+
"Required for 'write' (the complete file) and 'insert' (the line). "
|
|
119
119
|
"Accepted up to 10MB."
|
|
120
120
|
),
|
|
121
121
|
},
|
|
122
122
|
"old_string": {
|
|
123
123
|
"type": "string",
|
|
124
|
-
"description": "Exact string to find
|
|
124
|
+
"description": "Required for 'replace'. Exact string to find.",
|
|
125
125
|
},
|
|
126
126
|
"new_string": {
|
|
127
127
|
"type": "string",
|
|
128
|
-
"description": "New string to substitute
|
|
128
|
+
"description": "Required for 'replace'. New string to substitute.",
|
|
129
129
|
},
|
|
130
130
|
"line_number": {
|
|
131
131
|
"type": "integer",
|
|
132
|
-
"description": "
|
|
132
|
+
"description": "Required for 'insert' and 'delete'. Line number (1-based).",
|
|
133
133
|
},
|
|
134
134
|
"replace_all": {
|
|
135
135
|
"type": "boolean",
|
|
@@ -13,7 +13,8 @@ TOOL_DEFINITIONS: Tuple[ToolDefinition, ...] = (
|
|
|
13
13
|
name="bash",
|
|
14
14
|
description=(
|
|
15
15
|
"Run a shell command and return its exit code, stdout, and stderr. "
|
|
16
|
-
"Use for builds, tests, git, file inspection, and other terminal tasks."
|
|
16
|
+
"Use for builds, tests, git, file inspection, and other terminal tasks. "
|
|
17
|
+
"Each call starts in the working directory; a `cd` does not carry over."
|
|
17
18
|
),
|
|
18
19
|
description_template="Command `{command}` will be executed",
|
|
19
20
|
tags=("core",),
|
|
@@ -18,7 +18,8 @@ TOOL_DEFINITIONS: Tuple[ToolDefinition, ...] = (
|
|
|
18
18
|
name="task",
|
|
19
19
|
description=(
|
|
20
20
|
"Manage .ayder/tasks/ task files. Single tool, dispatched on "
|
|
21
|
-
"`action`: create | list | show | status | update_status | update
|
|
21
|
+
"`action`: create | list | show | status | update_status | update | "
|
|
22
|
+
"update_dependencies. "
|
|
22
23
|
"Output is bounded plain text (use offset/limit/max_chars/section to "
|
|
23
24
|
"page); prefer this over file_editor for all task operations."
|
|
24
25
|
),
|
|
@@ -39,12 +40,14 @@ TOOL_DEFINITIONS: Tuple[ToolDefinition, ...] = (
|
|
|
39
40
|
"status",
|
|
40
41
|
"update_status",
|
|
41
42
|
"update",
|
|
43
|
+
"update_dependencies",
|
|
42
44
|
],
|
|
43
45
|
"description": (
|
|
44
46
|
"Operation to perform. create: new task. list: paged "
|
|
45
47
|
"rows. show: bounded body/section. status: current "
|
|
46
48
|
"status. update_status: change status. update: replace "
|
|
47
|
-
"one PRD section."
|
|
49
|
+
"one PRD section. update_dependencies: replace the "
|
|
50
|
+
"dependency list."
|
|
48
51
|
),
|
|
49
52
|
},
|
|
50
53
|
"title": {
|
|
@@ -63,8 +66,11 @@ TOOL_DEFINITIONS: Tuple[ToolDefinition, ...] = (
|
|
|
63
66
|
"dependencies": {
|
|
64
67
|
"type": "string",
|
|
65
68
|
"description": (
|
|
66
|
-
"[create] Comma-separated
|
|
67
|
-
"'TASK-003,TASK-004'
|
|
69
|
+
"[create/update_dependencies] Comma-separated IDs of "
|
|
70
|
+
"existing tasks this one depends on, e.g. 'TASK-003,TASK-004' "
|
|
71
|
+
"or '3,4'. A task cannot depend on itself, on a task not yet "
|
|
72
|
+
"created, or close a cycle. [update_dependencies] Empty "
|
|
73
|
+
"clears the list."
|
|
68
74
|
),
|
|
69
75
|
},
|
|
70
76
|
"branch": {
|
|
@@ -85,7 +91,8 @@ TOOL_DEFINITIONS: Tuple[ToolDefinition, ...] = (
|
|
|
85
91
|
"identifier": {
|
|
86
92
|
"type": "string",
|
|
87
93
|
"description": (
|
|
88
|
-
"[show/status/update_status/update] Task
|
|
94
|
+
"[show/status/update_status/update/update_dependencies] Task "
|
|
95
|
+
"identifier: ID "
|
|
89
96
|
"('7', '007', 'TASK-007'), filename, path, or slug."
|
|
90
97
|
),
|
|
91
98
|
},
|