drydock-cli 1.4.0__tar.gz → 1.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.
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/PKG-INFO +1 -1
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/PRD.md +32 -1
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/agent_loop.py +136 -17
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/prompts/cli.md +22 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/tools/builtins/search_replace.py +0 -10
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/pyproject.toml +1 -1
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/scripts/deploy_to_github.sh +2 -1
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/scripts/publish_to_pypi.sh +2 -1
- drydock_cli-1.5.1/scripts/test_bank.sh +78 -0
- drydock_cli-1.5.1/tests/test_bank_build.py +572 -0
- drydock_cli-1.5.1/tests/test_bank_debug.py +1111 -0
- drydock_cli-1.5.1/tests/test_bank_multiagent.py +698 -0
- drydock_cli-1.5.1/tests/test_bank_tools.py +472 -0
- drydock_cli-1.5.1/tests/test_bank_update.py +938 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/test_drydock_regression.py +2 -2
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/test_drydock_tasks.py +36 -12
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/test_loop_detection.py +65 -35
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/test_smoke.py +2 -3
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/test_user_issues.py +16 -11
- drydock_cli-1.5.1/tests/test_workloads.py +441 -0
- drydock_cli-1.5.1/tests/testbank_helpers.py +967 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/.github/CODEOWNERS +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/.github/DISCUSSION_TEMPLATE/ideas.yml +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/.github/ISSUE_TEMPLATE/bug-report.yml +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/.github/ISSUE_TEMPLATE/config.yml +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/.github/workflows/build-and-upload.yml +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/.github/workflows/ci.yml +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/.github/workflows/issue-labeler.yml +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/.github/workflows/release.yml +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/.gitignore +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/.pre-commit-config.yaml +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/.python-version +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/.typos.toml +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/.vscode/extensions.json +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/.vscode/launch.json +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/.vscode/settings.json +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/AGENTS.md +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/CHANGELOG.md +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/CLAUDE.md +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/CONTRIBUTING.md +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/Drydock_rebrand.md +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/LICENSE +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/NOTICE +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/README.md +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/action.yml +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/distribution/zed/LICENSE +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/distribution/zed/extension.toml +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/distribution/zed/icons/mistral_vibe.svg +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/docs/README.md +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/docs/acp-setup.md +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/docs/proxy-setup.md +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/__init__.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/acp/__init__.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/acp/acp_agent_loop.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/acp/acp_logger.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/acp/entrypoint.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/acp/tools/__init__.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/acp/tools/base.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/acp/tools/builtins/bash.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/acp/tools/builtins/read_file.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/acp/tools/builtins/search_replace.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/acp/tools/builtins/todo.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/acp/tools/builtins/write_file.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/acp/tools/session_update.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/acp/utils.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/cli/__init__.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/cli/autocompletion/__init__.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/cli/autocompletion/base.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/cli/autocompletion/path_completion.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/cli/autocompletion/slash_command.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/cli/cli.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/cli/clipboard.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/cli/commands.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/cli/entrypoint.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/cli/history_manager.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/cli/plan_offer/adapters/http_whoami_gateway.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/cli/plan_offer/decide_plan_offer.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/cli/plan_offer/ports/whoami_gateway.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/cli/terminal_setup.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/cli/textual_ui/__init__.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/cli/textual_ui/ansi_markdown.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/cli/textual_ui/app.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/cli/textual_ui/app.tcss +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/cli/textual_ui/external_editor.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/cli/textual_ui/handlers/__init__.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/cli/textual_ui/handlers/event_handler.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/cli/textual_ui/notifications/__init__.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/cli/textual_ui/notifications/adapters/__init__.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/cli/textual_ui/notifications/adapters/textual_notification_adapter.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/cli/textual_ui/notifications/ports/__init__.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/cli/textual_ui/notifications/ports/notification_port.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/cli/textual_ui/widgets/__init__.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/cli/textual_ui/widgets/approval_app.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/cli/textual_ui/widgets/banner/banner.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/cli/textual_ui/widgets/banner/petit_chat.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/cli/textual_ui/widgets/braille_renderer.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/cli/textual_ui/widgets/chat_input/__init__.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/cli/textual_ui/widgets/chat_input/body.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/cli/textual_ui/widgets/chat_input/completion_manager.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/cli/textual_ui/widgets/chat_input/completion_popup.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/cli/textual_ui/widgets/chat_input/container.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/cli/textual_ui/widgets/chat_input/text_area.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/cli/textual_ui/widgets/compact.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/cli/textual_ui/widgets/config_app.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/cli/textual_ui/widgets/context_progress.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/cli/textual_ui/widgets/load_more.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/cli/textual_ui/widgets/loading.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/cli/textual_ui/widgets/messages.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/cli/textual_ui/widgets/no_markup_static.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/cli/textual_ui/widgets/path_display.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/cli/textual_ui/widgets/proxy_setup_app.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/cli/textual_ui/widgets/question_app.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/cli/textual_ui/widgets/session_picker.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/cli/textual_ui/widgets/spinner.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/cli/textual_ui/widgets/status_message.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/cli/textual_ui/widgets/teleport_message.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/cli/textual_ui/widgets/tool_widgets.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/cli/textual_ui/widgets/tools.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/cli/textual_ui/widgets/vscode_compat.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/cli/textual_ui/windowing/__init__.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/cli/textual_ui/windowing/history.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/cli/textual_ui/windowing/history_windowing.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/cli/textual_ui/windowing/state.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/cli/update_notifier/__init__.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/cli/update_notifier/adapters/filesystem_update_cache_repository.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/cli/update_notifier/adapters/github_update_gateway.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/cli/update_notifier/adapters/pypi_update_gateway.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/cli/update_notifier/ports/update_cache_repository.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/cli/update_notifier/ports/update_gateway.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/cli/update_notifier/update.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/cli/update_notifier/whats_new.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/__init__.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/agents/__init__.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/agents/manager.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/agents/models.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/auth/__init__.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/auth/crypto.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/auth/github.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/autocompletion/__init__.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/autocompletion/completers.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/autocompletion/file_indexer/__init__.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/autocompletion/file_indexer/ignore_rules.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/autocompletion/file_indexer/indexer.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/autocompletion/file_indexer/store.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/autocompletion/file_indexer/watcher.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/autocompletion/fuzzy.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/autocompletion/path_prompt.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/autocompletion/path_prompt_adapter.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/config/__init__.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/config/_settings.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/config/harness_files/__init__.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/config/harness_files/_harness_manager.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/config/harness_files/_paths.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/consultant.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/drydock_states.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/hooks.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/llm/__init__.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/llm/backend/anthropic.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/llm/backend/base.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/llm/backend/factory.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/llm/backend/generic.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/llm/backend/mistral.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/llm/backend/reasoning_adapter.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/llm/backend/vertex.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/llm/exceptions.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/llm/format.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/llm/message_utils.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/llm/types.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/logger.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/middleware.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/output_formatters.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/paths/__init__.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/paths/_local_config_walk.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/paths/_vibe_home.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/paths/conventions.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/plan_session.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/plugins.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/programmatic.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/prompts/__init__.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/prompts/compact.md +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/prompts/dangerous_directory.md +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/prompts/diagnostic.md +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/prompts/explore.md +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/prompts/planner.md +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/prompts/project_context.md +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/prompts/tests.md +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/proxy_setup.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/session/agent_memory.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/session/checkpoints.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/session/session_loader.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/session/session_logger.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/session/session_migration.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/session/state_file.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/skills/__init__.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/skills/manager.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/skills/models.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/skills/parser.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/slug.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/system_prompt.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/telemetry/__init__.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/telemetry/send.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/teleport/errors.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/teleport/git.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/teleport/nuage.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/teleport/teleport.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/teleport/types.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/tools/base.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/tools/builtins/ask_user_question.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/tools/builtins/bash.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/tools/builtins/cron.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/tools/builtins/exit_plan_mode.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/tools/builtins/glob_tool.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/tools/builtins/grep.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/tools/builtins/invoke_skill.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/tools/builtins/lsp.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/tools/builtins/mcp_resources.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/tools/builtins/notebook_edit.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/tools/builtins/powershell.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/tools/builtins/prompts/__init__.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/tools/builtins/prompts/ask_user_question.md +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/tools/builtins/prompts/bash.md +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/tools/builtins/prompts/cron.md +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/tools/builtins/prompts/glob.md +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/tools/builtins/prompts/grep.md +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/tools/builtins/prompts/invoke_skill.md +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/tools/builtins/prompts/lsp.md +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/tools/builtins/prompts/mcp_resources.md +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/tools/builtins/prompts/notebook_edit.md +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/tools/builtins/prompts/powershell.md +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/tools/builtins/prompts/read_file.md +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/tools/builtins/prompts/search_replace.md +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/tools/builtins/prompts/swe_bench.md +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/tools/builtins/prompts/task.md +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/tools/builtins/prompts/task_manager.md +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/tools/builtins/prompts/todo.md +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/tools/builtins/prompts/tool_search.md +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/tools/builtins/prompts/webfetch.md +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/tools/builtins/prompts/websearch.md +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/tools/builtins/prompts/worktree.md +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/tools/builtins/prompts/write_file.md +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/tools/builtins/read_file.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/tools/builtins/task.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/tools/builtins/task_manager.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/tools/builtins/todo.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/tools/builtins/tool_search.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/tools/builtins/webfetch.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/tools/builtins/websearch.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/tools/builtins/worktree.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/tools/builtins/write_file.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/tools/injection_guard.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/tools/manager.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/tools/mcp/__init__.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/tools/mcp/registry.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/tools/mcp/tools.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/tools/mcp_sampling.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/tools/ui.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/tools/utils.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/trusted_folders.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/types.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/utils.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/setup/onboarding/__init__.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/setup/onboarding/base.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/setup/onboarding/onboarding.tcss +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/setup/onboarding/screens/__init__.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/setup/onboarding/screens/api_key.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/setup/onboarding/screens/welcome.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/setup/trusted_folders/trust_folder_dialog.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/setup/trusted_folders/trust_folder_dialog.tcss +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/skills/__init__.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/skills/batch/SKILL.md +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/skills/create-presentation/SKILL.md +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/skills/deep-research/SKILL.md +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/skills/investigate/SKILL.md +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/skills/review/SKILL.md +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/skills/ship/SKILL.md +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/skills/simplify/SKILL.md +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/whats_new.md +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock-acp.spec +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock_terms.md +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/flake.lock +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/flake.nix +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/scripts/README.md +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/scripts/backup.sh +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/scripts/bump_version.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/scripts/install.sh +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/scripts/prepare_release.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/scripts/test_full.sh +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/scripts/test_smoke.sh +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/__init__.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/acp/conftest.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/acp/test_acp.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/acp/test_agent_thought.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/acp/test_bash.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/acp/test_compact_session_updates.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/acp/test_content.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/acp/test_initialize.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/acp/test_list_sessions.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/acp/test_load_session.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/acp/test_multi_session.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/acp/test_new_session.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/acp/test_proxy_setup_acp.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/acp/test_read_file.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/acp/test_search_replace.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/acp/test_set_config_option.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/acp/test_set_mode.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/acp/test_set_model.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/acp/test_tool_call_session_update.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/acp/test_utils.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/acp/test_write_file.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/autocompletion/test_file_indexer.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/autocompletion/test_fuzzy.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/autocompletion/test_path_completer_fuzzy.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/autocompletion/test_path_completer_recursive.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/autocompletion/test_path_completion_controller.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/autocompletion/test_path_prompt_transformer.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/autocompletion/test_slash_command_controller.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/autocompletion/test_ui_chat_autocompletion.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/backend/__init__.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/backend/data/__init__.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/backend/data/fireworks.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/backend/data/mistral.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/backend/test_anthropic_adapter.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/backend/test_backend.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/backend/test_reasoning_adapter.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/backend/test_vertex_anthropic_adapter.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/cli/plan_offer/adapters/fake_whoami_gateway.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/cli/plan_offer/test_decide_plan_offer.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/cli/plan_offer/test_http_whoami_gateway.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/cli/test_bell_notifications.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/cli/test_braille_renderer.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/cli/test_clipboard.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/cli/test_commands.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/cli/test_copy_shortcuts.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/cli/test_external_editor.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/cli/test_no_markup_static.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/cli/test_question_app.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/cli/test_spinner.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/cli/test_switching_mode.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/cli/test_ui_clipboard_notifications.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/cli/test_ui_session_incremental_renderer.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/cli/test_ui_session_resume.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/cli/test_ui_skill_dispatch.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/cli/textual_ui/__init__.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/cli/textual_ui/test_session_picker.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/conftest.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/core/test_agents.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/core/test_auth_crypto.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/core/test_auth_github.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/core/test_config_load_dotenv.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/core/test_config_paths.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/core/test_config_resolution.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/core/test_file_logging.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/core/test_plan_session.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/core/test_proxy_setup.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/core/test_slug.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/core/test_telemetry_send.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/core/test_teleport_git.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/core/test_teleport_nuage.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/core/test_teleport_service.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/core/test_trusted_folders.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/core/test_utils.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/e2e/common.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/e2e/conftest.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/e2e/mock_server.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/e2e/test_cli_tui_onboarding.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/e2e/test_cli_tui_streaming.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/e2e/test_cli_tui_tool_approval.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/mock/__init__.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/mock/mock_backend_factory.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/mock/mock_entrypoint.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/mock/utils.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/onboarding/test_run_onboarding.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/onboarding/test_ui_onboarding.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/session/test_session_loader.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/session/test_session_logger.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/session/test_session_migration.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/skills/conftest.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/skills/test_manager.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/skills/test_models.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/skills/test_parser.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/snapshots/__snapshots__/test_ui_snapshot_ask_user_question/test_snapshot_ask_user_question_collapsed.svg +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/snapshots/__snapshots__/test_ui_snapshot_ask_user_question/test_snapshot_ask_user_question_expanded.svg +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/snapshots/__snapshots__/test_ui_snapshot_basic_conversation/test_snapshot_shows_basic_conversation.svg +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/snapshots/__snapshots__/test_ui_snapshot_code_block_horizontal_scrolling/test_snapshot_allows_horizontal_scrolling_for_long_code_blocks.svg +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/snapshots/__snapshots__/test_ui_snapshot_empty_assistant_before_reasoning/test_snapshot_empty_assistant_removed_when_reasoning_starts.svg +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/snapshots/__snapshots__/test_ui_snapshot_modes/test_snapshot_cycle_to_accept_edits_mode.svg +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/snapshots/__snapshots__/test_ui_snapshot_modes/test_snapshot_cycle_to_auto_approve_mode.svg +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/snapshots/__snapshots__/test_ui_snapshot_modes/test_snapshot_cycle_to_plan_mode.svg +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/snapshots/__snapshots__/test_ui_snapshot_modes/test_snapshot_cycle_wraps_to_default.svg +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/snapshots/__snapshots__/test_ui_snapshot_modes/test_snapshot_default_mode.svg +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/snapshots/__snapshots__/test_ui_snapshot_parallel_tool_calls/test_snapshot_parallel_tool_calls_pending.svg +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/snapshots/__snapshots__/test_ui_snapshot_parallel_tool_calls/test_snapshot_parallel_tool_calls_resolved.svg +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/snapshots/__snapshots__/test_ui_snapshot_proxy_setup/test_snapshot_proxy_setup_cancel_discards_changes.svg +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/snapshots/__snapshots__/test_ui_snapshot_proxy_setup/test_snapshot_proxy_setup_edit_existing_values.svg +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/snapshots/__snapshots__/test_ui_snapshot_proxy_setup/test_snapshot_proxy_setup_initial_empty.svg +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/snapshots/__snapshots__/test_ui_snapshot_proxy_setup/test_snapshot_proxy_setup_initial_with_values.svg +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/snapshots/__snapshots__/test_ui_snapshot_proxy_setup/test_snapshot_proxy_setup_save_error.svg +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/snapshots/__snapshots__/test_ui_snapshot_proxy_setup/test_snapshot_proxy_setup_save_new_values.svg +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_question_answer_first_advance.svg +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_question_first_answered_checkmark.svg +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_question_initial.svg +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_question_navigate_left_wraps.svg +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_question_navigate_right.svg +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_question_tab_to_second.svg +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_select_initial.svg +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_select_mixed_selection.svg +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_select_navigate_to_submit.svg +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_select_other_with_text.svg +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_select_toggle_first.svg +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_select_toggle_multiple.svg +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_select_untoggle.svg +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_question_app_initial.svg +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_question_app_navigate_down.svg +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_question_app_navigate_to_other.svg +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_question_app_navigate_to_third_option.svg +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_question_app_navigate_up_wraps.svg +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_question_app_other_typing.svg +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/snapshots/__snapshots__/test_ui_snapshot_reasoning_content/test_snapshot_buffered_reasoning_yields_before_content.svg +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/snapshots/__snapshots__/test_ui_snapshot_reasoning_content/test_snapshot_shows_interleaved_reasoning.svg +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/snapshots/__snapshots__/test_ui_snapshot_reasoning_content/test_snapshot_shows_reasoning_content.svg +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/snapshots/__snapshots__/test_ui_snapshot_reasoning_content/test_snapshot_shows_reasoning_content_expanded.svg +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/snapshots/__snapshots__/test_ui_snapshot_release_update_notification/test_snapshot_shows_release_update_notification.svg +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/snapshots/__snapshots__/test_ui_snapshot_session_resume/test_snapshot_shows_resumed_session_messages.svg +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/snapshots/__snapshots__/test_ui_snapshot_streaming_tool_call/test_snapshot_tool_call_partial.svg +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/snapshots/__snapshots__/test_ui_snapshot_streaming_tool_call/test_snapshot_tool_call_updated.svg +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_push_confirmation_cancel_selected.svg +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_push_confirmation_multiple_commits.svg +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_push_confirmation_single_commit.svg +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_status_auth_complete.svg +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_status_auth_required.svg +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_status_checking_git.svg +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_status_complete.svg +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_status_error.svg +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_status_pushing.svg +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_status_sending_token.svg +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_status_starting_workflow.svg +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/snapshots/__snapshots__/test_ui_snapshot_whats_new/test_snapshot_shows_no_plan_message.svg +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/snapshots/__snapshots__/test_ui_snapshot_whats_new/test_snapshot_shows_switch_message.svg +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/snapshots/__snapshots__/test_ui_snapshot_whats_new/test_snapshot_shows_upgrade_message.svg +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/snapshots/__snapshots__/test_ui_snapshot_whats_new/test_snapshot_shows_whats_new_message.svg +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/snapshots/base_snapshot_test_app.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/snapshots/conftest.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/snapshots/snap_compare.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/snapshots/test_ui_snapshot_ask_user_question.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/snapshots/test_ui_snapshot_basic_conversation.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/snapshots/test_ui_snapshot_code_block_horizontal_scrolling.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/snapshots/test_ui_snapshot_empty_assistant_before_reasoning.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/snapshots/test_ui_snapshot_modes.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/snapshots/test_ui_snapshot_parallel_tool_calls.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/snapshots/test_ui_snapshot_proxy_setup.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/snapshots/test_ui_snapshot_question_app.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/snapshots/test_ui_snapshot_reasoning_content.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/snapshots/test_ui_snapshot_release_update_notification.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/snapshots/test_ui_snapshot_session_resume.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/snapshots/test_ui_snapshot_streaming_tool_call.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/snapshots/test_ui_snapshot_teleport.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/snapshots/test_ui_snapshot_whats_new.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/stubs/fake_backend.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/stubs/fake_client.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/stubs/fake_tool.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/test_agent_auto_compact.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/test_agent_backend.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/test_agent_observer_streaming.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/test_agent_stats.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/test_agent_tasks.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/test_agent_tool_call.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/test_agents.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/test_build_projects.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/test_cli_programmatic_preload.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/test_current_bugs.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/test_full_regression.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/test_history_manager.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/test_integration.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/test_message_id.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/test_message_merging.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/test_middleware.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/test_multi_agent.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/test_real_failures.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/test_real_issues.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/test_real_workflow.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/test_reasoning_content.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/test_system_prompt.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/test_tagged_text.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/test_ui_external_editor.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/test_ui_input_history.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/tools/test_ask_user_question.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/tools/test_bash.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/tools/test_exit_plan_mode.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/tools/test_grep.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/tools/test_invoke_context.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/tools/test_manager_get_tool_config.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/tools/test_mcp.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/tools/test_mcp_sampling.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/tools/test_task.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/tools/test_ui_bash_execution.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/tools/test_webfetch.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/tools/test_websearch.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/update_notifier/adapters/fake_update_cache_repository.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/update_notifier/adapters/fake_update_gateway.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/update_notifier/test_do_update.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/update_notifier/test_filesystem_update_cache_repository.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/update_notifier/test_github_update_gateway.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/update_notifier/test_pypi_update_gateway.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/update_notifier/test_ui_update_notification.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/update_notifier/test_update_use_case.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/update_notifier/test_whats_new.py +0 -0
- {drydock_cli-1.4.0 → drydock_cli-1.5.1}/uv.lock +0 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# DryDock — Local CLI Coding Agent
|
|
2
2
|
|
|
3
3
|
**Repository:** https://github.com/fbobe321/drydock
|
|
4
|
-
**PyPI:** https://pypi.org/project/drydock-cli/ (v1.
|
|
4
|
+
**PyPI:** https://pypi.org/project/drydock-cli/ (v1.5.0)
|
|
5
5
|
**License:** Apache 2.0 (fork of [mistralai/mistral-vibe](https://github.com/mistralai/mistral-vibe))
|
|
6
6
|
**Status:** Active development — continuous improvement running
|
|
7
7
|
|
|
@@ -21,6 +21,7 @@ Every change follows this pipeline:
|
|
|
21
21
|
Scripts:
|
|
22
22
|
- `scripts/test_smoke.sh` — quick smoke tests (every deploy)
|
|
23
23
|
- `scripts/test_full.sh` — smoke + full regression (nightly)
|
|
24
|
+
- `scripts/test_bank.sh` — 83-test regression bank (10-18 hours, real vLLM)
|
|
24
25
|
- `scripts/deploy_to_github.sh` — smoke tests → sync to GitHub (daily 4 AM)
|
|
25
26
|
- `scripts/publish_to_pypi.sh` — smoke tests → bump → build → PyPI → GitHub
|
|
26
27
|
- `scripts/backup.sh` — rsync to NAS (daily 3 AM)
|
|
@@ -248,3 +249,33 @@ Adding Python tools/agents doesn't matter if the prompt doesn't tell the model t
|
|
|
248
249
|
- Shows exact syntax for delegation
|
|
249
250
|
- Explicit WHEN to delegate rules (3+ files, reviews, bugs, planning)
|
|
250
251
|
- WHEN NOT to delegate (simple fixes, quick questions)
|
|
252
|
+
|
|
253
|
+
### Phase 11 (Mar 28): Agent Loop Hardening + 83-Test Regression Bank
|
|
254
|
+
|
|
255
|
+
User reported DryDock was unusable — model looped 12+ times running the same command, search_replace blocked legitimate files, basic tasks couldn't complete.
|
|
256
|
+
|
|
257
|
+
**Agent loop fixes (5 bugs):**
|
|
258
|
+
- Empty model response: retry 3x with nudge (model sometimes returns nothing)
|
|
259
|
+
- Invalid tool name recovery: model hallucinates `task_agent:`, now gets correct tool list
|
|
260
|
+
- Bash traceback guidance: extracts file:line from crash, directs model to read source
|
|
261
|
+
- Circuit breaker for successful repeats: blocks after 4 identical bash calls (was unlimited)
|
|
262
|
+
- Tighter loop detection: warning at 4 (was 8), force-stop at 8 (was 25)
|
|
263
|
+
|
|
264
|
+
**System prompt improvements:**
|
|
265
|
+
- Added debugging best practices: RUN → READ → FIX → VERIFY cycle
|
|
266
|
+
- Common bug pattern hints (TypeError, KeyError, IndexError, off-by-one)
|
|
267
|
+
|
|
268
|
+
**83-test regression bank (real vLLM backend, ~90 min):**
|
|
269
|
+
|
|
270
|
+
| Suite | Tests | Pass Rate |
|
|
271
|
+
|---|---|---|
|
|
272
|
+
| BUILD (easy/medium/hard) | 25 | 100% |
|
|
273
|
+
| DEBUG (easy/medium/hard) | 20 | 75% |
|
|
274
|
+
| UPDATE (easy/medium/hard) | 15 | 100% |
|
|
275
|
+
| MULTIAGENT | 10 | 100% |
|
|
276
|
+
| TOOLS | 13 | 100% |
|
|
277
|
+
| **Total** | **83** | **94%** |
|
|
278
|
+
|
|
279
|
+
Run with: `./scripts/test_bank.sh` (full) or `./scripts/test_bank.sh quick` (easy only, ~2h)
|
|
280
|
+
|
|
281
|
+
**Removed:** False-positive test file guard in search_replace that blocked any file in a directory containing "test" in its name.
|
|
@@ -124,8 +124,8 @@ class ToolDecision(BaseModel):
|
|
|
124
124
|
|
|
125
125
|
MAX_TOOL_TURNS = 200 # Bug fixes rarely need more than 50 turns; 200 is generous ceiling
|
|
126
126
|
MAX_API_ERRORS = 5
|
|
127
|
-
REPEAT_WARNING_THRESHOLD =
|
|
128
|
-
REPEAT_FORCE_STOP_THRESHOLD =
|
|
127
|
+
REPEAT_WARNING_THRESHOLD = 4 # Same exact call 4+ times before warning
|
|
128
|
+
REPEAT_FORCE_STOP_THRESHOLD = 8 # Same exact call 8+ times before force-stop
|
|
129
129
|
|
|
130
130
|
logger = logging.getLogger(__name__)
|
|
131
131
|
|
|
@@ -192,6 +192,7 @@ class AgentLoop:
|
|
|
192
192
|
# Key: hash(tool_name + args), Value: (count, last_result_snippet)
|
|
193
193
|
self._tool_call_history: dict[str, tuple[int, str]] = {}
|
|
194
194
|
self._consecutive_circuit_breaker_fires: int = 0
|
|
195
|
+
self._empty_responses: int = 0
|
|
195
196
|
|
|
196
197
|
system_prompt = get_universal_system_prompt(
|
|
197
198
|
self.tool_manager, self.config, self.skill_manager, self.agent_manager
|
|
@@ -534,9 +535,19 @@ class AgentLoop:
|
|
|
534
535
|
stopped_by_middleware=True,
|
|
535
536
|
)
|
|
536
537
|
return
|
|
537
|
-
#
|
|
538
|
-
|
|
539
|
-
|
|
538
|
+
# Check if the error is about invalid function/tool name
|
|
539
|
+
error_str = str(e)
|
|
540
|
+
if "Function name" in error_str or "function" in error_str.lower() and "must be" in error_str.lower():
|
|
541
|
+
# Model hallucinated a tool name — give it the correct list
|
|
542
|
+
available = ", ".join(sorted(self.tool_manager.available_tools.keys())[:15])
|
|
543
|
+
error_text = (
|
|
544
|
+
f"ERROR: You tried to call a tool that does not exist. "
|
|
545
|
+
f"Available tools: {available}. "
|
|
546
|
+
f"Use one of these exact tool names. "
|
|
547
|
+
f"For subagent delegation, use 'task'. For file search, use 'grep'."
|
|
548
|
+
)
|
|
549
|
+
else:
|
|
550
|
+
error_text = f"API error occurred: {e}. Please continue with your task."
|
|
540
551
|
self._inject_system_note(error_text)
|
|
541
552
|
continue
|
|
542
553
|
|
|
@@ -616,6 +627,41 @@ class AgentLoop:
|
|
|
616
627
|
f"Consider stopping to verify your approach."
|
|
617
628
|
)
|
|
618
629
|
|
|
630
|
+
# Post-edit bash loop: model made edits but now loops on bash
|
|
631
|
+
# trying to test code that keeps failing
|
|
632
|
+
if has_made_edit and bash_count >= 3:
|
|
633
|
+
# Count consecutive bash calls at end of tool history
|
|
634
|
+
consecutive_bash = 0
|
|
635
|
+
for tc_name in reversed(self._recent_tool_names()):
|
|
636
|
+
if tc_name in ("bash", "run_command"):
|
|
637
|
+
consecutive_bash += 1
|
|
638
|
+
else:
|
|
639
|
+
break
|
|
640
|
+
if consecutive_bash >= 4:
|
|
641
|
+
self._inject_system_note(
|
|
642
|
+
"You have run 4+ bash commands in a row after editing files. "
|
|
643
|
+
"Each one failed or gave the same result. STOP running bash. "
|
|
644
|
+
"Read the error message carefully, then use search_replace "
|
|
645
|
+
"to fix the actual code. Running the same command again will "
|
|
646
|
+
"not give a different result."
|
|
647
|
+
)
|
|
648
|
+
|
|
649
|
+
# Detect bash file creation (touch, echo >, cat <<)
|
|
650
|
+
for msg in reversed(self.messages[-3:]):
|
|
651
|
+
if msg.role == Role.assistant and msg.tool_calls:
|
|
652
|
+
for tc in msg.tool_calls:
|
|
653
|
+
if tc.function and tc.function.name in ("bash", "run_command"):
|
|
654
|
+
cmd = ""
|
|
655
|
+
try:
|
|
656
|
+
cmd = json.loads(tc.function.arguments or "{}").get("command", "")
|
|
657
|
+
except (json.JSONDecodeError, AttributeError):
|
|
658
|
+
pass
|
|
659
|
+
if any(kw in cmd for kw in ("touch ", "echo ", "cat <<", "printf ", "> ")):
|
|
660
|
+
self._inject_system_note(
|
|
661
|
+
f"Do NOT use bash to create files. Use write_file instead. "
|
|
662
|
+
f"bash touch/echo/cat does not create proper code files."
|
|
663
|
+
)
|
|
664
|
+
|
|
619
665
|
# Bash abuse detection: model uses bash instead of proper tools
|
|
620
666
|
if not has_made_edit and bash_count >= 3:
|
|
621
667
|
if bash_count == 3:
|
|
@@ -670,10 +716,26 @@ class AgentLoop:
|
|
|
670
716
|
|
|
671
717
|
should_break_loop = last_message.role != Role.tool
|
|
672
718
|
|
|
719
|
+
# Handle empty response (no content AND no tools) — retry
|
|
720
|
+
if (should_break_loop and last_message.role == Role.assistant
|
|
721
|
+
and not last_message.content and not last_message.tool_calls):
|
|
722
|
+
empty_response_count = getattr(self, '_empty_responses', 0) + 1
|
|
723
|
+
self._empty_responses = empty_response_count
|
|
724
|
+
if empty_response_count <= 3:
|
|
725
|
+
should_break_loop = False
|
|
726
|
+
self._inject_system_note(
|
|
727
|
+
"Your response was empty. You MUST call a tool. "
|
|
728
|
+
"Start by reading the relevant file with read_file, "
|
|
729
|
+
"or run the failing command with bash to see the error."
|
|
730
|
+
)
|
|
731
|
+
logger.warning("Empty model response — nudging (attempt %d)", empty_response_count)
|
|
732
|
+
continue
|
|
733
|
+
# After 3 empty responses, let it exit
|
|
734
|
+
|
|
673
735
|
# If model gives text without tool calls and hasn't edited anything,
|
|
674
736
|
# nudge it to make an edit instead of just describing what to do.
|
|
675
737
|
# Never let the agent exit without at least attempting an edit.
|
|
676
|
-
if should_break_loop and not has_made_edit and tool_turns >=
|
|
738
|
+
if should_break_loop and not has_made_edit and tool_turns >= 1:
|
|
677
739
|
text_without_action += 1
|
|
678
740
|
# Always continue — don't let the agent exit without editing
|
|
679
741
|
should_break_loop = False
|
|
@@ -742,8 +804,8 @@ class AgentLoop:
|
|
|
742
804
|
if rep == "FORCE_STOP":
|
|
743
805
|
repeat_warnings += 1
|
|
744
806
|
logger.warning("Detected infinite loop: same tool call %d+ times (warning %d)", REPEAT_FORCE_STOP_THRESHOLD, repeat_warnings)
|
|
745
|
-
if repeat_warnings >=
|
|
746
|
-
#
|
|
807
|
+
if repeat_warnings >= 5:
|
|
808
|
+
# Stop after 5 redirects — model is not recovering
|
|
747
809
|
yield AssistantEvent(
|
|
748
810
|
content="\n\n[Stopping: exhausted all retry attempts.]\n",
|
|
749
811
|
stopped_by_middleware=True,
|
|
@@ -773,7 +835,7 @@ class AgentLoop:
|
|
|
773
835
|
else:
|
|
774
836
|
repeat_warnings += 1
|
|
775
837
|
logger.warning("Detected repeated tool calls (warning %.1f, investigation=%s)", repeat_warnings, is_investigation_warning)
|
|
776
|
-
if repeat_warnings >=
|
|
838
|
+
if repeat_warnings >= 6:
|
|
777
839
|
yield AssistantEvent(
|
|
778
840
|
content="\n\n[Stopping: too many repeated actions despite warnings.]\n",
|
|
779
841
|
stopped_by_middleware=True,
|
|
@@ -792,7 +854,13 @@ class AgentLoop:
|
|
|
792
854
|
elif stuck_tool in ("grep",):
|
|
793
855
|
nudge = " You have been SEARCHING repeatedly. Pick the most relevant file from your search results and READ it, then make your edit."
|
|
794
856
|
elif stuck_tool in ("bash", "run_command"):
|
|
795
|
-
nudge =
|
|
857
|
+
nudge = (
|
|
858
|
+
" You have been running the SAME bash command repeatedly. "
|
|
859
|
+
"Running the same command again will give the same result. "
|
|
860
|
+
"If it succeeded but didn't do what you expected, READ the source code "
|
|
861
|
+
"to understand WHY, then FIX the code with search_replace. "
|
|
862
|
+
"If it failed, try a DIFFERENT command or approach."
|
|
863
|
+
)
|
|
796
864
|
if repeat_warnings >= 4:
|
|
797
865
|
# Escalated: replace tool result with strong directive
|
|
798
866
|
warning_text = (
|
|
@@ -935,10 +1003,19 @@ class AgentLoop:
|
|
|
935
1003
|
count, last_result = self._tool_call_history.get(sig, (0, ""))
|
|
936
1004
|
is_failed = last_result.startswith("FAILED:") if last_result else False
|
|
937
1005
|
|
|
938
|
-
#
|
|
939
|
-
#
|
|
940
|
-
#
|
|
941
|
-
|
|
1006
|
+
# Block failed commands after 2 repeats.
|
|
1007
|
+
# Block SUCCESSFUL commands after 4 repeats — the model should not
|
|
1008
|
+
# run the exact same command with the exact same args 5+ times.
|
|
1009
|
+
# Read-only checks (ls, pwd, git status) get a higher threshold.
|
|
1010
|
+
tool_name = tool_call.tool_name
|
|
1011
|
+
is_readonly = tool_name in ("grep", "read_file", "glob", "ls")
|
|
1012
|
+
success_threshold = 6 if is_readonly else 4
|
|
1013
|
+
|
|
1014
|
+
if is_failed and count >= 2:
|
|
1015
|
+
pass # will be blocked below
|
|
1016
|
+
elif not is_failed and count >= success_threshold:
|
|
1017
|
+
pass # will be blocked below
|
|
1018
|
+
else:
|
|
942
1019
|
return None
|
|
943
1020
|
|
|
944
1021
|
if count >= 2:
|
|
@@ -1161,6 +1238,35 @@ class AgentLoop:
|
|
|
1161
1238
|
"Add more surrounding context lines to old_str to make it unique.]"
|
|
1162
1239
|
)
|
|
1163
1240
|
|
|
1241
|
+
# RECOVERY: Relative import error — tell model to use absolute imports or -m
|
|
1242
|
+
if tool_call.tool_name in ("bash", "run_command") and "relative import with no known parent" in str(exc):
|
|
1243
|
+
self._inject_system_note(
|
|
1244
|
+
"The error 'relative import with no known parent package' means you are "
|
|
1245
|
+
"running a package file directly (python3 pkg/file.py). Fix: either "
|
|
1246
|
+
"(1) change 'from .module import X' to 'from pkg.module import X' (absolute imports), or "
|
|
1247
|
+
"(2) run with 'python3 -m pkg' instead of 'python3 pkg/file.py'. "
|
|
1248
|
+
"Use search_replace to change the imports to absolute imports NOW."
|
|
1249
|
+
)
|
|
1250
|
+
|
|
1251
|
+
# RECOVERY: After bash failure with traceback, extract file/line and
|
|
1252
|
+
# inject a STRONG system note (not just error text) to force read→fix
|
|
1253
|
+
if tool_call.tool_name in ("bash", "run_command") and "Traceback" in str(exc):
|
|
1254
|
+
import re
|
|
1255
|
+
tb_matches = re.findall(r'File "([^"]+)", line (\d+)', str(exc))
|
|
1256
|
+
if tb_matches:
|
|
1257
|
+
tb_file, tb_line = tb_matches[-1]
|
|
1258
|
+
if not tb_file.startswith("/home") and "site-packages" not in tb_file:
|
|
1259
|
+
error_msg += (
|
|
1260
|
+
f"\n\n[NEXT STEP: Read {tb_file} around line {tb_line} "
|
|
1261
|
+
f"with read_file, then fix it with search_replace.]"
|
|
1262
|
+
)
|
|
1263
|
+
# Also inject as system note — harder for model to ignore
|
|
1264
|
+
self._inject_system_note(
|
|
1265
|
+
f"STOP running bash. The error is at {tb_file}:{tb_line}. "
|
|
1266
|
+
f"Use read_file to read that file, then search_replace to fix the bug. "
|
|
1267
|
+
f"Do NOT run another bash command until you have fixed the code."
|
|
1268
|
+
)
|
|
1269
|
+
|
|
1164
1270
|
yield ToolResultEvent(
|
|
1165
1271
|
tool_name=tool_call.tool_name,
|
|
1166
1272
|
tool_class=tool_call.tool_class,
|
|
@@ -1485,11 +1591,11 @@ class AgentLoop:
|
|
|
1485
1591
|
# Lower thresholds catch loops where the model uses the same tool
|
|
1486
1592
|
# with slightly different args (e.g., grep with different paths).
|
|
1487
1593
|
if last_tool in ("bash", "run_command"):
|
|
1488
|
-
same_tool_limit =
|
|
1594
|
+
same_tool_limit = 5
|
|
1489
1595
|
elif last_tool in ("grep", "read_file"):
|
|
1490
|
-
same_tool_limit =
|
|
1596
|
+
same_tool_limit = 7 # investigation tools need some room
|
|
1491
1597
|
else:
|
|
1492
|
-
same_tool_limit =
|
|
1598
|
+
same_tool_limit = 5
|
|
1493
1599
|
if (
|
|
1494
1600
|
len(tool_names) >= same_tool_limit
|
|
1495
1601
|
and all(n == tool_names[-1] for n in tool_names[-same_tool_limit:])
|
|
@@ -1529,6 +1635,19 @@ class AgentLoop:
|
|
|
1529
1635
|
|
|
1530
1636
|
return None
|
|
1531
1637
|
|
|
1638
|
+
def _recent_tool_names(self, limit: int = 10) -> list[str]:
|
|
1639
|
+
"""Return recent tool names from message history (most recent last)."""
|
|
1640
|
+
names: list[str] = []
|
|
1641
|
+
for msg in reversed(self.messages):
|
|
1642
|
+
if msg.role == Role.assistant and msg.tool_calls:
|
|
1643
|
+
for tc in msg.tool_calls:
|
|
1644
|
+
if tc.function and tc.function.name:
|
|
1645
|
+
names.append(tc.function.name)
|
|
1646
|
+
if len(names) >= limit:
|
|
1647
|
+
break
|
|
1648
|
+
names.reverse()
|
|
1649
|
+
return names
|
|
1650
|
+
|
|
1532
1651
|
def _prune_repeated_tool_calls(self) -> None:
|
|
1533
1652
|
"""Remove duplicate tool call/result pairs from recent history.
|
|
1534
1653
|
|
|
@@ -223,6 +223,28 @@ Error Handling:
|
|
|
223
223
|
- After ANY error, your next action must be DIFFERENT from what just failed.
|
|
224
224
|
- Never run the same failing command twice — the result won't change.
|
|
225
225
|
|
|
226
|
+
Python Package Rules:
|
|
227
|
+
When creating Python packages (directories with __init__.py):
|
|
228
|
+
- Use ABSOLUTE imports, not relative. Write `from mypackage.module import X`, NOT `from .module import X`
|
|
229
|
+
- To run a package: `python3 -m mypackage` (requires __main__.py), NOT `python3 mypackage/main.py`
|
|
230
|
+
- Relative imports (from .foo) ONLY work with `python3 -m`, not direct file execution
|
|
231
|
+
- If you get "attempted relative import with no known parent package", switch to absolute imports
|
|
232
|
+
|
|
233
|
+
Debugging Best Practices:
|
|
234
|
+
When fixing bugs, follow this cycle: RUN → READ → FIX → VERIFY.
|
|
235
|
+
1. RUN the failing command to see the exact error (traceback, assertion, etc.)
|
|
236
|
+
2. READ the source file at the line mentioned in the traceback
|
|
237
|
+
3. FIX the bug with search_replace — common patterns:
|
|
238
|
+
- TypeError (str + int): add type conversion (int(), float(), str())
|
|
239
|
+
- KeyError: add .get() with default, or check key existence
|
|
240
|
+
- IndexError: fix loop bounds or add bounds check
|
|
241
|
+
- ImportError: fix the import path, use absolute imports, or run with python3 -m
|
|
242
|
+
- Off-by-one: check if index starts at 0 or 1
|
|
243
|
+
- Missing return value: check if function returns in all paths
|
|
244
|
+
4. VERIFY by running the command again — if it still fails, read the NEW error
|
|
245
|
+
|
|
246
|
+
CRITICAL: After fixing a bug, ALWAYS run the command again to verify. Never assume your fix worked.
|
|
247
|
+
|
|
226
248
|
Context Budget:
|
|
227
249
|
Your context window is your most important resource. Every grep result and file read consumes it.
|
|
228
250
|
Performance degrades as context fills. Budget your investigation:
|
|
@@ -119,16 +119,6 @@ class SearchReplace(
|
|
|
119
119
|
) -> AsyncGenerator[ToolStreamEvent | SearchReplaceResult, None]:
|
|
120
120
|
file_path, search_replace_blocks = self._prepare_and_validate_args(args)
|
|
121
121
|
|
|
122
|
-
# BLOCK editing test files — the bug is in source code, not tests
|
|
123
|
-
file_str = str(file_path)
|
|
124
|
-
if ("/tests/" in file_str or "/test_" in file_str or
|
|
125
|
-
file_str.endswith("_test.py") or "/testing/" in file_str):
|
|
126
|
-
raise ToolError(
|
|
127
|
-
f"BLOCKED: You are trying to edit a test file ({file_path.name}). "
|
|
128
|
-
f"The bug is in LIBRARY SOURCE code, not tests. "
|
|
129
|
-
f"Use grep to find the corresponding source file and edit that instead."
|
|
130
|
-
)
|
|
131
|
-
|
|
132
122
|
# Injection guard: scan replacement content for suspicious patterns
|
|
133
123
|
from drydock.core.tools.injection_guard import check_content_for_injection
|
|
134
124
|
if warning := check_content_for_injection(args.content, args.file_path):
|
|
@@ -37,7 +37,8 @@ AUTH_URL="https://${GITHUB_TOKEN}@github.com/fbobe321/drydock.git"
|
|
|
37
37
|
|
|
38
38
|
log "Running regression tests..."
|
|
39
39
|
cd "$DRYDOCK_SRC"
|
|
40
|
-
|
|
40
|
+
python3 -m pip install -q "pytest>=9.0" 2>/dev/null
|
|
41
|
+
if ! python3 -m pytest tests/test_drydock_regression.py tests/test_drydock_tasks.py tests/test_loop_detection.py tests/test_agent_tasks.py tests/test_integration.py tests/test_user_issues.py tests/test_real_issues.py \
|
|
41
42
|
-p no:xdist -p no:cov --override-ini="addopts=" -q 2>&1; then
|
|
42
43
|
log "TESTS FAILED — deploy aborted. Fix the tests before deploying."
|
|
43
44
|
exit 1
|
|
@@ -25,7 +25,8 @@ PYPI_TOKEN=$(cat "$TOKEN_FILE")
|
|
|
25
25
|
|
|
26
26
|
# --- Run tests ---
|
|
27
27
|
log "Running regression tests..."
|
|
28
|
-
|
|
28
|
+
$PYTHON -m pip install -q "pytest>=9.0" 2>/dev/null
|
|
29
|
+
if ! $PYTHON -m pytest tests/test_drydock_regression.py tests/test_drydock_tasks.py tests/test_loop_detection.py tests/test_agent_tasks.py tests/test_integration.py tests/test_user_issues.py tests/test_real_issues.py \
|
|
29
30
|
-p no:xdist -p no:cov --override-ini="addopts=" -q 2>&1; then
|
|
30
31
|
log "TESTS FAILED — publish aborted."
|
|
31
32
|
exit 1
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# TEST BANK — Full regression suite against real vLLM backend.
|
|
3
|
+
# Requires vLLM at localhost:8000. Takes 10-18 hours.
|
|
4
|
+
#
|
|
5
|
+
# Usage:
|
|
6
|
+
# ./scripts/test_bank.sh # Run everything
|
|
7
|
+
# ./scripts/test_bank.sh build # Run only build tests
|
|
8
|
+
# ./scripts/test_bank.sh debug # Run only debug tests
|
|
9
|
+
# ./scripts/test_bank.sh update # Run only update tests
|
|
10
|
+
# ./scripts/test_bank.sh multi # Run only multi-agent tests
|
|
11
|
+
# ./scripts/test_bank.sh tools # Run only tool integration tests
|
|
12
|
+
# ./scripts/test_bank.sh quick # Run only easy tests (~2 hours)
|
|
13
|
+
|
|
14
|
+
set -euo pipefail
|
|
15
|
+
cd "$(dirname "$0")/.."
|
|
16
|
+
|
|
17
|
+
pip install -q "pytest>=9.0" pytest-asyncio httpx 2>/dev/null
|
|
18
|
+
|
|
19
|
+
COMMON_ARGS="-v -s -p no:xdist -p no:cov --override-ini=addopts="
|
|
20
|
+
CATEGORY="${1:-all}"
|
|
21
|
+
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
|
|
22
|
+
LOG_DIR="test_bank_results"
|
|
23
|
+
mkdir -p "$LOG_DIR"
|
|
24
|
+
|
|
25
|
+
run_suite() {
|
|
26
|
+
local name="$1"
|
|
27
|
+
local file="$2"
|
|
28
|
+
local extra="${3:-}"
|
|
29
|
+
echo ""
|
|
30
|
+
echo "================================================================"
|
|
31
|
+
echo " $name — $(date)"
|
|
32
|
+
echo "================================================================"
|
|
33
|
+
local logfile="$LOG_DIR/${name}_${TIMESTAMP}.log"
|
|
34
|
+
python3 -m pytest "$file" $COMMON_ARGS $extra 2>&1 | tee "$logfile"
|
|
35
|
+
echo ""
|
|
36
|
+
echo "Results saved to: $logfile"
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
case "$CATEGORY" in
|
|
40
|
+
build)
|
|
41
|
+
run_suite "BUILD" "tests/test_bank_build.py"
|
|
42
|
+
;;
|
|
43
|
+
debug)
|
|
44
|
+
run_suite "DEBUG" "tests/test_bank_debug.py"
|
|
45
|
+
;;
|
|
46
|
+
update)
|
|
47
|
+
run_suite "UPDATE" "tests/test_bank_update.py"
|
|
48
|
+
;;
|
|
49
|
+
multi)
|
|
50
|
+
run_suite "MULTI-AGENT" "tests/test_bank_multiagent.py"
|
|
51
|
+
;;
|
|
52
|
+
tools)
|
|
53
|
+
run_suite "TOOLS" "tests/test_bank_tools.py"
|
|
54
|
+
;;
|
|
55
|
+
quick)
|
|
56
|
+
echo "=== QUICK TEST BANK (Easy tests only, ~2 hours) ==="
|
|
57
|
+
run_suite "BUILD-EASY" "tests/test_bank_build.py" "-k TestBuildEasy"
|
|
58
|
+
run_suite "DEBUG-EASY" "tests/test_bank_debug.py" "-k TestDebugEasy"
|
|
59
|
+
run_suite "UPDATE-EASY" "tests/test_bank_update.py" "-k TestUpdateEasy"
|
|
60
|
+
run_suite "TOOLS" "tests/test_bank_tools.py"
|
|
61
|
+
;;
|
|
62
|
+
all)
|
|
63
|
+
echo "=== FULL TEST BANK — Estimated 10-18 hours ==="
|
|
64
|
+
echo "=== Started: $(date) ==="
|
|
65
|
+
run_suite "BUILD" "tests/test_bank_build.py"
|
|
66
|
+
run_suite "DEBUG" "tests/test_bank_debug.py"
|
|
67
|
+
run_suite "UPDATE" "tests/test_bank_update.py"
|
|
68
|
+
run_suite "MULTI-AGENT" "tests/test_bank_multiagent.py"
|
|
69
|
+
run_suite "TOOLS" "tests/test_bank_tools.py"
|
|
70
|
+
echo ""
|
|
71
|
+
echo "=== FULL TEST BANK COMPLETE — $(date) ==="
|
|
72
|
+
echo "Results in: $LOG_DIR/"
|
|
73
|
+
;;
|
|
74
|
+
*)
|
|
75
|
+
echo "Usage: $0 {all|build|debug|update|multi|tools|quick}"
|
|
76
|
+
exit 1
|
|
77
|
+
;;
|
|
78
|
+
esac
|