drydock-cli 1.1.0__tar.gz → 1.1.2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/PKG-INFO +1 -1
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/cli/commands.py +5 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/cli/textual_ui/app.py +49 -1
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/cli/textual_ui/app.tcss +2 -2
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/pyproject.toml +1 -1
- drydock_cli-1.1.2/scripts/test_full.sh +13 -0
- drydock_cli-1.1.2/scripts/test_smoke.sh +7 -0
- drydock_cli-1.1.2/tests/test_full_regression.py +191 -0
- drydock_cli-1.1.2/tests/test_smoke.py +173 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/.github/CODEOWNERS +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/.github/DISCUSSION_TEMPLATE/ideas.yml +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/.github/ISSUE_TEMPLATE/bug-report.yml +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/.github/ISSUE_TEMPLATE/config.yml +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/.github/workflows/build-and-upload.yml +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/.github/workflows/ci.yml +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/.github/workflows/issue-labeler.yml +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/.github/workflows/release.yml +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/.gitignore +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/.pre-commit-config.yaml +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/.python-version +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/.typos.toml +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/.vscode/extensions.json +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/.vscode/launch.json +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/.vscode/settings.json +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/AGENTS.md +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/CHANGELOG.md +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/CLAUDE.md +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/CONTRIBUTING.md +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/Drydock_rebrand.md +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/LICENSE +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/NOTICE +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/PRD.md +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/README.md +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/action.yml +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/distribution/zed/LICENSE +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/distribution/zed/extension.toml +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/distribution/zed/icons/mistral_vibe.svg +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/docs/README.md +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/docs/acp-setup.md +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/docs/proxy-setup.md +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/__init__.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/acp/__init__.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/acp/acp_agent_loop.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/acp/acp_logger.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/acp/entrypoint.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/acp/tools/__init__.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/acp/tools/base.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/acp/tools/builtins/bash.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/acp/tools/builtins/read_file.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/acp/tools/builtins/search_replace.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/acp/tools/builtins/todo.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/acp/tools/builtins/write_file.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/acp/tools/session_update.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/acp/utils.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/cli/__init__.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/cli/autocompletion/__init__.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/cli/autocompletion/base.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/cli/autocompletion/path_completion.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/cli/autocompletion/slash_command.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/cli/cli.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/cli/clipboard.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/cli/entrypoint.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/cli/history_manager.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/cli/plan_offer/adapters/http_whoami_gateway.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/cli/plan_offer/decide_plan_offer.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/cli/plan_offer/ports/whoami_gateway.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/cli/terminal_setup.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/cli/textual_ui/__init__.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/cli/textual_ui/ansi_markdown.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/cli/textual_ui/external_editor.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/cli/textual_ui/handlers/__init__.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/cli/textual_ui/handlers/event_handler.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/cli/textual_ui/notifications/__init__.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/cli/textual_ui/notifications/adapters/__init__.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/cli/textual_ui/notifications/adapters/textual_notification_adapter.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/cli/textual_ui/notifications/ports/__init__.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/cli/textual_ui/notifications/ports/notification_port.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/cli/textual_ui/widgets/__init__.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/cli/textual_ui/widgets/approval_app.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/cli/textual_ui/widgets/banner/banner.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/cli/textual_ui/widgets/banner/petit_chat.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/cli/textual_ui/widgets/braille_renderer.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/cli/textual_ui/widgets/chat_input/__init__.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/cli/textual_ui/widgets/chat_input/body.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/cli/textual_ui/widgets/chat_input/completion_manager.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/cli/textual_ui/widgets/chat_input/completion_popup.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/cli/textual_ui/widgets/chat_input/container.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/cli/textual_ui/widgets/chat_input/text_area.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/cli/textual_ui/widgets/compact.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/cli/textual_ui/widgets/config_app.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/cli/textual_ui/widgets/context_progress.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/cli/textual_ui/widgets/load_more.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/cli/textual_ui/widgets/loading.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/cli/textual_ui/widgets/messages.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/cli/textual_ui/widgets/no_markup_static.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/cli/textual_ui/widgets/path_display.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/cli/textual_ui/widgets/proxy_setup_app.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/cli/textual_ui/widgets/question_app.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/cli/textual_ui/widgets/session_picker.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/cli/textual_ui/widgets/spinner.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/cli/textual_ui/widgets/status_message.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/cli/textual_ui/widgets/teleport_message.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/cli/textual_ui/widgets/tool_widgets.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/cli/textual_ui/widgets/tools.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/cli/textual_ui/widgets/vscode_compat.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/cli/textual_ui/windowing/__init__.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/cli/textual_ui/windowing/history.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/cli/textual_ui/windowing/history_windowing.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/cli/textual_ui/windowing/state.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/cli/update_notifier/__init__.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/cli/update_notifier/adapters/filesystem_update_cache_repository.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/cli/update_notifier/adapters/github_update_gateway.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/cli/update_notifier/adapters/pypi_update_gateway.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/cli/update_notifier/ports/update_cache_repository.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/cli/update_notifier/ports/update_gateway.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/cli/update_notifier/update.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/cli/update_notifier/whats_new.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/core/__init__.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/core/agent_loop.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/core/agents/__init__.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/core/agents/manager.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/core/agents/models.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/core/auth/__init__.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/core/auth/crypto.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/core/auth/github.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/core/autocompletion/__init__.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/core/autocompletion/completers.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/core/autocompletion/file_indexer/__init__.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/core/autocompletion/file_indexer/ignore_rules.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/core/autocompletion/file_indexer/indexer.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/core/autocompletion/file_indexer/store.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/core/autocompletion/file_indexer/watcher.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/core/autocompletion/fuzzy.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/core/autocompletion/path_prompt.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/core/autocompletion/path_prompt_adapter.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/core/config/__init__.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/core/config/_settings.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/core/config/harness_files/__init__.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/core/config/harness_files/_harness_manager.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/core/config/harness_files/_paths.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/core/consultant.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/core/drydock_states.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/core/hooks.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/core/llm/__init__.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/core/llm/backend/anthropic.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/core/llm/backend/base.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/core/llm/backend/factory.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/core/llm/backend/generic.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/core/llm/backend/mistral.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/core/llm/backend/reasoning_adapter.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/core/llm/backend/vertex.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/core/llm/exceptions.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/core/llm/format.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/core/llm/message_utils.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/core/llm/types.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/core/logger.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/core/middleware.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/core/output_formatters.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/core/paths/__init__.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/core/paths/_local_config_walk.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/core/paths/_vibe_home.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/core/paths/conventions.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/core/plan_session.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/core/programmatic.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/core/prompts/__init__.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/core/prompts/cli.md +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/core/prompts/compact.md +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/core/prompts/dangerous_directory.md +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/core/prompts/diagnostic.md +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/core/prompts/explore.md +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/core/prompts/planner.md +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/core/prompts/project_context.md +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/core/prompts/tests.md +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/core/proxy_setup.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/core/session/agent_memory.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/core/session/session_loader.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/core/session/session_logger.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/core/session/session_migration.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/core/session/state_file.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/core/skills/__init__.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/core/skills/manager.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/core/skills/models.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/core/skills/parser.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/core/slug.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/core/system_prompt.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/core/telemetry/__init__.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/core/telemetry/send.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/core/teleport/errors.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/core/teleport/git.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/core/teleport/nuage.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/core/teleport/teleport.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/core/teleport/types.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/core/tools/base.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/core/tools/builtins/ask_user_question.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/core/tools/builtins/bash.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/core/tools/builtins/cron.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/core/tools/builtins/exit_plan_mode.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/core/tools/builtins/glob_tool.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/core/tools/builtins/grep.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/core/tools/builtins/invoke_skill.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/core/tools/builtins/lsp.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/core/tools/builtins/mcp_resources.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/core/tools/builtins/notebook_edit.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/core/tools/builtins/powershell.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/core/tools/builtins/prompts/__init__.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/core/tools/builtins/prompts/ask_user_question.md +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/core/tools/builtins/prompts/bash.md +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/core/tools/builtins/prompts/cron.md +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/core/tools/builtins/prompts/glob.md +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/core/tools/builtins/prompts/grep.md +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/core/tools/builtins/prompts/invoke_skill.md +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/core/tools/builtins/prompts/lsp.md +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/core/tools/builtins/prompts/mcp_resources.md +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/core/tools/builtins/prompts/notebook_edit.md +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/core/tools/builtins/prompts/powershell.md +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/core/tools/builtins/prompts/read_file.md +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/core/tools/builtins/prompts/search_replace.md +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/core/tools/builtins/prompts/swe_bench.md +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/core/tools/builtins/prompts/task.md +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/core/tools/builtins/prompts/task_manager.md +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/core/tools/builtins/prompts/todo.md +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/core/tools/builtins/prompts/tool_search.md +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/core/tools/builtins/prompts/webfetch.md +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/core/tools/builtins/prompts/websearch.md +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/core/tools/builtins/prompts/worktree.md +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/core/tools/builtins/prompts/write_file.md +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/core/tools/builtins/read_file.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/core/tools/builtins/search_replace.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/core/tools/builtins/task.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/core/tools/builtins/task_manager.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/core/tools/builtins/todo.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/core/tools/builtins/tool_search.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/core/tools/builtins/webfetch.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/core/tools/builtins/websearch.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/core/tools/builtins/worktree.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/core/tools/builtins/write_file.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/core/tools/injection_guard.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/core/tools/manager.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/core/tools/mcp/__init__.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/core/tools/mcp/registry.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/core/tools/mcp/tools.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/core/tools/mcp_sampling.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/core/tools/ui.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/core/tools/utils.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/core/trusted_folders.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/core/types.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/core/utils.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/setup/onboarding/__init__.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/setup/onboarding/base.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/setup/onboarding/onboarding.tcss +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/setup/onboarding/screens/__init__.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/setup/onboarding/screens/api_key.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/setup/onboarding/screens/welcome.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/setup/trusted_folders/trust_folder_dialog.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/setup/trusted_folders/trust_folder_dialog.tcss +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/skills/__init__.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/skills/batch/SKILL.md +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/skills/create-presentation/SKILL.md +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/skills/deep-research/SKILL.md +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/skills/investigate/SKILL.md +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/skills/review/SKILL.md +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/skills/ship/SKILL.md +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/skills/simplify/SKILL.md +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/whats_new.md +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock-acp.spec +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock_terms.md +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/flake.lock +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/flake.nix +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/scripts/README.md +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/scripts/backup.sh +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/scripts/bump_version.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/scripts/deploy_to_github.sh +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/scripts/install.sh +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/scripts/prepare_release.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/scripts/publish_to_pypi.sh +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/tests/__init__.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/tests/acp/conftest.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/tests/acp/test_acp.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/tests/acp/test_agent_thought.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/tests/acp/test_bash.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/tests/acp/test_compact_session_updates.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/tests/acp/test_content.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/tests/acp/test_initialize.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/tests/acp/test_list_sessions.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/tests/acp/test_load_session.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/tests/acp/test_multi_session.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/tests/acp/test_new_session.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/tests/acp/test_proxy_setup_acp.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/tests/acp/test_read_file.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/tests/acp/test_search_replace.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/tests/acp/test_set_config_option.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/tests/acp/test_set_mode.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/tests/acp/test_set_model.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/tests/acp/test_tool_call_session_update.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/tests/acp/test_utils.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/tests/acp/test_write_file.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/tests/autocompletion/test_file_indexer.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/tests/autocompletion/test_fuzzy.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/tests/autocompletion/test_path_completer_fuzzy.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/tests/autocompletion/test_path_completer_recursive.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/tests/autocompletion/test_path_completion_controller.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/tests/autocompletion/test_path_prompt_transformer.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/tests/autocompletion/test_slash_command_controller.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/tests/autocompletion/test_ui_chat_autocompletion.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/tests/backend/__init__.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/tests/backend/data/__init__.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/tests/backend/data/fireworks.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/tests/backend/data/mistral.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/tests/backend/test_anthropic_adapter.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/tests/backend/test_backend.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/tests/backend/test_reasoning_adapter.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/tests/backend/test_vertex_anthropic_adapter.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/tests/cli/plan_offer/adapters/fake_whoami_gateway.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/tests/cli/plan_offer/test_decide_plan_offer.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/tests/cli/plan_offer/test_http_whoami_gateway.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/tests/cli/test_bell_notifications.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/tests/cli/test_braille_renderer.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/tests/cli/test_clipboard.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/tests/cli/test_commands.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/tests/cli/test_copy_shortcuts.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/tests/cli/test_external_editor.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/tests/cli/test_no_markup_static.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/tests/cli/test_question_app.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/tests/cli/test_spinner.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/tests/cli/test_switching_mode.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/tests/cli/test_ui_clipboard_notifications.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/tests/cli/test_ui_session_incremental_renderer.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/tests/cli/test_ui_session_resume.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/tests/cli/test_ui_skill_dispatch.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/tests/cli/textual_ui/__init__.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/tests/cli/textual_ui/test_session_picker.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/tests/conftest.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/tests/core/test_agents.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/tests/core/test_auth_crypto.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/tests/core/test_auth_github.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/tests/core/test_config_load_dotenv.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/tests/core/test_config_paths.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/tests/core/test_config_resolution.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/tests/core/test_file_logging.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/tests/core/test_plan_session.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/tests/core/test_proxy_setup.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/tests/core/test_slug.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/tests/core/test_telemetry_send.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/tests/core/test_teleport_git.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/tests/core/test_teleport_nuage.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/tests/core/test_teleport_service.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/tests/core/test_trusted_folders.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/tests/core/test_utils.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/tests/e2e/common.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/tests/e2e/conftest.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/tests/e2e/mock_server.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/tests/e2e/test_cli_tui_onboarding.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/tests/e2e/test_cli_tui_streaming.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/tests/e2e/test_cli_tui_tool_approval.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/tests/mock/__init__.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/tests/mock/mock_backend_factory.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/tests/mock/mock_entrypoint.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/tests/mock/utils.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/tests/onboarding/test_run_onboarding.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/tests/onboarding/test_ui_onboarding.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/tests/session/test_session_loader.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/tests/session/test_session_logger.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/tests/session/test_session_migration.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/tests/skills/conftest.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/tests/skills/test_manager.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/tests/skills/test_models.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/tests/skills/test_parser.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/tests/snapshots/__snapshots__/test_ui_snapshot_ask_user_question/test_snapshot_ask_user_question_collapsed.svg +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/tests/snapshots/__snapshots__/test_ui_snapshot_ask_user_question/test_snapshot_ask_user_question_expanded.svg +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/tests/snapshots/__snapshots__/test_ui_snapshot_basic_conversation/test_snapshot_shows_basic_conversation.svg +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/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.1.0 → drydock_cli-1.1.2}/tests/snapshots/__snapshots__/test_ui_snapshot_empty_assistant_before_reasoning/test_snapshot_empty_assistant_removed_when_reasoning_starts.svg +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/tests/snapshots/__snapshots__/test_ui_snapshot_modes/test_snapshot_cycle_to_accept_edits_mode.svg +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/tests/snapshots/__snapshots__/test_ui_snapshot_modes/test_snapshot_cycle_to_auto_approve_mode.svg +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/tests/snapshots/__snapshots__/test_ui_snapshot_modes/test_snapshot_cycle_to_plan_mode.svg +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/tests/snapshots/__snapshots__/test_ui_snapshot_modes/test_snapshot_cycle_wraps_to_default.svg +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/tests/snapshots/__snapshots__/test_ui_snapshot_modes/test_snapshot_default_mode.svg +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/tests/snapshots/__snapshots__/test_ui_snapshot_parallel_tool_calls/test_snapshot_parallel_tool_calls_pending.svg +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/tests/snapshots/__snapshots__/test_ui_snapshot_parallel_tool_calls/test_snapshot_parallel_tool_calls_resolved.svg +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/tests/snapshots/__snapshots__/test_ui_snapshot_proxy_setup/test_snapshot_proxy_setup_cancel_discards_changes.svg +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/tests/snapshots/__snapshots__/test_ui_snapshot_proxy_setup/test_snapshot_proxy_setup_edit_existing_values.svg +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/tests/snapshots/__snapshots__/test_ui_snapshot_proxy_setup/test_snapshot_proxy_setup_initial_empty.svg +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/tests/snapshots/__snapshots__/test_ui_snapshot_proxy_setup/test_snapshot_proxy_setup_initial_with_values.svg +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/tests/snapshots/__snapshots__/test_ui_snapshot_proxy_setup/test_snapshot_proxy_setup_save_error.svg +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/tests/snapshots/__snapshots__/test_ui_snapshot_proxy_setup/test_snapshot_proxy_setup_save_new_values.svg +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_question_answer_first_advance.svg +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_question_first_answered_checkmark.svg +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_question_initial.svg +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_question_navigate_left_wraps.svg +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_question_navigate_right.svg +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_question_tab_to_second.svg +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_select_initial.svg +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_select_mixed_selection.svg +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_select_navigate_to_submit.svg +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_select_other_with_text.svg +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_select_toggle_first.svg +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_select_toggle_multiple.svg +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_select_untoggle.svg +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_question_app_initial.svg +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_question_app_navigate_down.svg +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_question_app_navigate_to_other.svg +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_question_app_navigate_to_third_option.svg +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_question_app_navigate_up_wraps.svg +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_question_app_other_typing.svg +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/tests/snapshots/__snapshots__/test_ui_snapshot_reasoning_content/test_snapshot_buffered_reasoning_yields_before_content.svg +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/tests/snapshots/__snapshots__/test_ui_snapshot_reasoning_content/test_snapshot_shows_interleaved_reasoning.svg +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/tests/snapshots/__snapshots__/test_ui_snapshot_reasoning_content/test_snapshot_shows_reasoning_content.svg +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/tests/snapshots/__snapshots__/test_ui_snapshot_reasoning_content/test_snapshot_shows_reasoning_content_expanded.svg +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/tests/snapshots/__snapshots__/test_ui_snapshot_release_update_notification/test_snapshot_shows_release_update_notification.svg +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/tests/snapshots/__snapshots__/test_ui_snapshot_session_resume/test_snapshot_shows_resumed_session_messages.svg +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/tests/snapshots/__snapshots__/test_ui_snapshot_streaming_tool_call/test_snapshot_tool_call_partial.svg +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/tests/snapshots/__snapshots__/test_ui_snapshot_streaming_tool_call/test_snapshot_tool_call_updated.svg +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_push_confirmation_cancel_selected.svg +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_push_confirmation_multiple_commits.svg +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_push_confirmation_single_commit.svg +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_status_auth_complete.svg +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_status_auth_required.svg +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_status_checking_git.svg +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_status_complete.svg +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_status_error.svg +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_status_pushing.svg +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_status_sending_token.svg +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_status_starting_workflow.svg +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/tests/snapshots/__snapshots__/test_ui_snapshot_whats_new/test_snapshot_shows_no_plan_message.svg +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/tests/snapshots/__snapshots__/test_ui_snapshot_whats_new/test_snapshot_shows_switch_message.svg +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/tests/snapshots/__snapshots__/test_ui_snapshot_whats_new/test_snapshot_shows_upgrade_message.svg +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/tests/snapshots/__snapshots__/test_ui_snapshot_whats_new/test_snapshot_shows_whats_new_message.svg +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/tests/snapshots/base_snapshot_test_app.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/tests/snapshots/conftest.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/tests/snapshots/snap_compare.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/tests/snapshots/test_ui_snapshot_ask_user_question.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/tests/snapshots/test_ui_snapshot_basic_conversation.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/tests/snapshots/test_ui_snapshot_code_block_horizontal_scrolling.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/tests/snapshots/test_ui_snapshot_empty_assistant_before_reasoning.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/tests/snapshots/test_ui_snapshot_modes.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/tests/snapshots/test_ui_snapshot_parallel_tool_calls.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/tests/snapshots/test_ui_snapshot_proxy_setup.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/tests/snapshots/test_ui_snapshot_question_app.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/tests/snapshots/test_ui_snapshot_reasoning_content.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/tests/snapshots/test_ui_snapshot_release_update_notification.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/tests/snapshots/test_ui_snapshot_session_resume.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/tests/snapshots/test_ui_snapshot_streaming_tool_call.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/tests/snapshots/test_ui_snapshot_teleport.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/tests/snapshots/test_ui_snapshot_whats_new.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/tests/stubs/fake_backend.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/tests/stubs/fake_client.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/tests/stubs/fake_tool.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/tests/test_agent_auto_compact.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/tests/test_agent_backend.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/tests/test_agent_observer_streaming.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/tests/test_agent_stats.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/tests/test_agent_tasks.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/tests/test_agent_tool_call.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/tests/test_agents.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/tests/test_cli_programmatic_preload.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/tests/test_current_bugs.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/tests/test_drydock_regression.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/tests/test_drydock_tasks.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/tests/test_history_manager.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/tests/test_integration.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/tests/test_loop_detection.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/tests/test_message_id.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/tests/test_message_merging.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/tests/test_middleware.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/tests/test_real_failures.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/tests/test_real_issues.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/tests/test_reasoning_content.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/tests/test_system_prompt.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/tests/test_tagged_text.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/tests/test_ui_external_editor.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/tests/test_ui_input_history.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/tests/test_user_issues.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/tests/tools/test_ask_user_question.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/tests/tools/test_bash.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/tests/tools/test_exit_plan_mode.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/tests/tools/test_grep.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/tests/tools/test_invoke_context.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/tests/tools/test_manager_get_tool_config.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/tests/tools/test_mcp.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/tests/tools/test_mcp_sampling.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/tests/tools/test_task.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/tests/tools/test_ui_bash_execution.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/tests/tools/test_webfetch.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/tests/tools/test_websearch.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/tests/update_notifier/adapters/fake_update_cache_repository.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/tests/update_notifier/adapters/fake_update_gateway.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/tests/update_notifier/test_do_update.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/tests/update_notifier/test_filesystem_update_cache_repository.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/tests/update_notifier/test_github_update_gateway.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/tests/update_notifier/test_pypi_update_gateway.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/tests/update_notifier/test_ui_update_notification.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/tests/update_notifier/test_update_use_case.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/tests/update_notifier/test_whats_new.py +0 -0
- {drydock_cli-1.1.0 → drydock_cli-1.1.2}/uv.lock +0 -0
|
@@ -77,6 +77,11 @@ class CommandRegistry:
|
|
|
77
77
|
description="Ask a smarter model for advice (response visible to local model)",
|
|
78
78
|
handler="_consult_command",
|
|
79
79
|
),
|
|
80
|
+
"rewind": Command(
|
|
81
|
+
aliases=frozenset(["/rewind"]),
|
|
82
|
+
description="Undo the last assistant turn and its tool calls",
|
|
83
|
+
handler="_rewind_command",
|
|
84
|
+
),
|
|
80
85
|
"resume": Command(
|
|
81
86
|
aliases=frozenset(["/resume", "/continue"]),
|
|
82
87
|
description="Browse and resume past sessions",
|
|
@@ -143,12 +143,32 @@ class BottomApp(StrEnum):
|
|
|
143
143
|
|
|
144
144
|
|
|
145
145
|
class ChatScroll(VerticalScroll):
|
|
146
|
-
"""
|
|
146
|
+
"""Scroll container for chat messages.
|
|
147
|
+
|
|
148
|
+
Captures mouse scroll to scroll chat history (not terminal history).
|
|
149
|
+
Auto-scrolls to bottom when new messages arrive, unless user has
|
|
150
|
+
scrolled up to review previous messages.
|
|
151
|
+
"""
|
|
152
|
+
|
|
153
|
+
can_focus = True # Required for mouse scroll capture
|
|
147
154
|
|
|
148
155
|
@property
|
|
149
156
|
def is_at_bottom(self) -> bool:
|
|
150
157
|
return self.scroll_offset.y >= (self.max_scroll_y - 3)
|
|
151
158
|
|
|
159
|
+
def on_mount(self) -> None:
|
|
160
|
+
self.focus() # Focus on mount so scroll events go here
|
|
161
|
+
|
|
162
|
+
def on_mouse_scroll_down(self, event: object) -> None:
|
|
163
|
+
"""Scroll down in chat history."""
|
|
164
|
+
self.scroll_down(3)
|
|
165
|
+
event.stop() # Prevent terminal from scrolling
|
|
166
|
+
|
|
167
|
+
def on_mouse_scroll_up(self, event: object) -> None:
|
|
168
|
+
"""Scroll up in chat history."""
|
|
169
|
+
self.scroll_up(3)
|
|
170
|
+
event.stop() # Prevent terminal from scrolling
|
|
171
|
+
|
|
152
172
|
def update_node_styles(self, animate: bool = True) -> None:
|
|
153
173
|
pass
|
|
154
174
|
|
|
@@ -922,6 +942,34 @@ class VibeApp(App): # noqa: PLR0904
|
|
|
922
942
|
help_text = self.commands.get_help_text()
|
|
923
943
|
await self._mount_and_scroll(UserCommandMessage(help_text))
|
|
924
944
|
|
|
945
|
+
async def _rewind_command(self, args: str = "") -> None:
|
|
946
|
+
"""Undo the last assistant turn and its tool calls."""
|
|
947
|
+
if self._agent_running:
|
|
948
|
+
await self._mount_and_scroll(
|
|
949
|
+
ErrorMessage("Cannot rewind while agent is running.", collapsed=self._tools_collapsed)
|
|
950
|
+
)
|
|
951
|
+
return
|
|
952
|
+
|
|
953
|
+
# Find and remove the last assistant turn (assistant + tool messages)
|
|
954
|
+
removed = 0
|
|
955
|
+
while len(self.agent_loop.messages) > 1:
|
|
956
|
+
last = self.agent_loop.messages[-1]
|
|
957
|
+
if last.role == Role.system:
|
|
958
|
+
break
|
|
959
|
+
if last.role == Role.user and removed > 0:
|
|
960
|
+
break # Stop before the user message that triggered the turn
|
|
961
|
+
self.agent_loop.messages.reset(list(self.agent_loop.messages[:-1]))
|
|
962
|
+
removed += 1
|
|
963
|
+
|
|
964
|
+
if removed > 0:
|
|
965
|
+
await self._mount_and_scroll(
|
|
966
|
+
UserCommandMessage(f"Rewound {removed} messages. You can now re-prompt.")
|
|
967
|
+
)
|
|
968
|
+
else:
|
|
969
|
+
await self._mount_and_scroll(
|
|
970
|
+
UserCommandMessage("Nothing to rewind.")
|
|
971
|
+
)
|
|
972
|
+
|
|
925
973
|
async def _show_status(self) -> None:
|
|
926
974
|
stats = self.agent_loop.stats
|
|
927
975
|
status_text = f"""## Agent Statistics
|
|
@@ -24,12 +24,12 @@ TextArea > .text-area--cursor {
|
|
|
24
24
|
}
|
|
25
25
|
|
|
26
26
|
#chat {
|
|
27
|
-
layout: stream;
|
|
28
27
|
height: 1fr;
|
|
29
28
|
width: 100%;
|
|
30
29
|
background: transparent;
|
|
31
30
|
padding: 0;
|
|
32
|
-
|
|
31
|
+
overflow-y: scroll;
|
|
32
|
+
scrollbar-size-vertical: 1;
|
|
33
33
|
}
|
|
34
34
|
|
|
35
35
|
#loading-area {
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# FULL REGRESSION — Run nightly or before releases (5-10 min)
|
|
3
|
+
# Requires vLLM at localhost:8000. Real backend, no mocks.
|
|
4
|
+
set -euo pipefail
|
|
5
|
+
cd "$(dirname "$0")/.."
|
|
6
|
+
pip install -q "pytest>=9.0" pytest-asyncio 2>/dev/null
|
|
7
|
+
|
|
8
|
+
echo "=== SMOKE TESTS ==="
|
|
9
|
+
python3 -m pytest tests/test_smoke.py -p no:xdist -p no:cov --override-ini="addopts=" -q
|
|
10
|
+
|
|
11
|
+
echo ""
|
|
12
|
+
echo "=== FULL REGRESSION (real backend) ==="
|
|
13
|
+
python3 -m pytest tests/test_full_regression.py -v -p no:xdist -p no:cov --override-ini="addopts="
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# SMOKE TESTS — Run on every code change (< 1 second)
|
|
3
|
+
# No backend needed. Checks imports, config, branding, safety guards.
|
|
4
|
+
set -euo pipefail
|
|
5
|
+
cd "$(dirname "$0")/.."
|
|
6
|
+
pip install -q "pytest>=9.0" 2>/dev/null
|
|
7
|
+
python3 -m pytest tests/test_smoke.py -p no:xdist -p no:cov --override-ini="addopts=" -q "$@"
|
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
"""FULL REGRESSION — Real backend tests (takes 5-10 min).
|
|
2
|
+
|
|
3
|
+
Run nightly or before releases. Hits the actual vLLM backend.
|
|
4
|
+
Skip if vLLM is not running.
|
|
5
|
+
|
|
6
|
+
Run: pytest tests/test_full_regression.py -v
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from __future__ import annotations
|
|
10
|
+
|
|
11
|
+
import asyncio
|
|
12
|
+
from pathlib import Path
|
|
13
|
+
|
|
14
|
+
import httpx
|
|
15
|
+
import pytest
|
|
16
|
+
|
|
17
|
+
from drydock.core.config.harness_files import init_harness_files_manager
|
|
18
|
+
try:
|
|
19
|
+
init_harness_files_manager("user", "project")
|
|
20
|
+
except RuntimeError:
|
|
21
|
+
pass
|
|
22
|
+
|
|
23
|
+
from drydock.core.agent_loop import AgentLoop
|
|
24
|
+
from drydock.core.agents.models import BuiltinAgentName
|
|
25
|
+
from drydock.core.config import Backend, ModelConfig, ProviderConfig, VibeConfig
|
|
26
|
+
from drydock.core.types import (
|
|
27
|
+
AssistantEvent, BaseEvent, Role, ToolCallEvent, ToolResultEvent,
|
|
28
|
+
)
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def _vllm_ok():
|
|
32
|
+
try:
|
|
33
|
+
return httpx.get("http://localhost:8000/v1/models", timeout=3).status_code == 200
|
|
34
|
+
except Exception:
|
|
35
|
+
return False
|
|
36
|
+
|
|
37
|
+
pytestmark = pytest.mark.skipif(not _vllm_ok(), reason="vLLM not running")
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def _config(tmp_path):
|
|
41
|
+
return VibeConfig(
|
|
42
|
+
active_model="devstral", auto_approve=True, enable_telemetry=False,
|
|
43
|
+
include_project_context=False, system_prompt_id="cli",
|
|
44
|
+
providers=[ProviderConfig(name="local", api_base="http://localhost:8000/v1", api_key_env_var="", backend=Backend.GENERIC)],
|
|
45
|
+
models=[ModelConfig(name="devstral", provider="local", input_price=0, output_price=0)],
|
|
46
|
+
session_logging={"enabled": False, "save_dir": str(tmp_path / "logs")},
|
|
47
|
+
)
|
|
48
|
+
|
|
49
|
+
def _agent(tmp_path, max_turns=8):
|
|
50
|
+
return AgentLoop(config=_config(tmp_path), agent_name=BuiltinAgentName.AUTO_APPROVE, max_turns=max_turns)
|
|
51
|
+
|
|
52
|
+
async def _run(agent, prompt, max_events=80):
|
|
53
|
+
events = []
|
|
54
|
+
async for ev in agent.act(prompt):
|
|
55
|
+
events.append(ev)
|
|
56
|
+
if len(events) >= max_events:
|
|
57
|
+
break
|
|
58
|
+
return events
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
# ============================================================================
|
|
62
|
+
# Tool execution doesn't crash
|
|
63
|
+
# ============================================================================
|
|
64
|
+
|
|
65
|
+
@pytest.mark.asyncio
|
|
66
|
+
async def test_bash_executes(tmp_path):
|
|
67
|
+
agent = _agent(tmp_path)
|
|
68
|
+
events = await _run(agent, "Run: echo 'hello from drydock test'")
|
|
69
|
+
assert any(isinstance(e, (ToolCallEvent, AssistantEvent)) for e in events)
|
|
70
|
+
for e in events:
|
|
71
|
+
if isinstance(e, ToolResultEvent) and e.error:
|
|
72
|
+
assert "AttributeError" not in str(e.error)
|
|
73
|
+
|
|
74
|
+
@pytest.mark.asyncio
|
|
75
|
+
async def test_grep_executes(tmp_path):
|
|
76
|
+
agent = _agent(tmp_path)
|
|
77
|
+
events = await _run(agent, "Search for 'def ' in the current directory")
|
|
78
|
+
assert len(events) >= 1
|
|
79
|
+
|
|
80
|
+
@pytest.mark.asyncio
|
|
81
|
+
async def test_read_file_executes(tmp_path):
|
|
82
|
+
test_file = tmp_path / "test.txt"
|
|
83
|
+
test_file.write_text("hello world\n")
|
|
84
|
+
agent = _agent(tmp_path)
|
|
85
|
+
events = await _run(agent, f"Read the file {test_file}")
|
|
86
|
+
assert len(events) >= 1
|
|
87
|
+
|
|
88
|
+
@pytest.mark.asyncio
|
|
89
|
+
async def test_write_file_executes(tmp_path):
|
|
90
|
+
agent = _agent(tmp_path)
|
|
91
|
+
events = await _run(agent, f"Write 'test content' to {tmp_path}/output.txt")
|
|
92
|
+
assert len(events) >= 1
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
# ============================================================================
|
|
96
|
+
# Circuit breaker works (THE critical test)
|
|
97
|
+
# ============================================================================
|
|
98
|
+
|
|
99
|
+
@pytest.mark.asyncio
|
|
100
|
+
async def test_circuit_breaker_stops_loops(tmp_path):
|
|
101
|
+
"""Model should not make 10+ identical tool calls."""
|
|
102
|
+
agent = _agent(tmp_path, max_turns=15)
|
|
103
|
+
events = await _run(agent, "Run 'echo test' exactly 10 times as separate bash calls", max_events=100)
|
|
104
|
+
|
|
105
|
+
cb_fires = [e for e in events if isinstance(e, ToolResultEvent) and e.error and "CIRCUIT" in str(e.error)]
|
|
106
|
+
if cb_fires:
|
|
107
|
+
# After circuit breaker fires, count remaining calls
|
|
108
|
+
first_cb = next(i for i, e in enumerate(events) if isinstance(e, ToolResultEvent) and e.error and "CIRCUIT" in str(e.error))
|
|
109
|
+
calls_after = [e for e in events[first_cb:] if isinstance(e, ToolCallEvent)]
|
|
110
|
+
assert len(calls_after) <= 5, f"Model made {len(calls_after)} calls after circuit breaker"
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
# ============================================================================
|
|
114
|
+
# Message ordering
|
|
115
|
+
# ============================================================================
|
|
116
|
+
|
|
117
|
+
@pytest.mark.asyncio
|
|
118
|
+
async def test_no_user_after_tool(tmp_path):
|
|
119
|
+
agent = _agent(tmp_path)
|
|
120
|
+
events = await _run(agent, "What Python version is installed?")
|
|
121
|
+
for i in range(1, len(agent.messages)):
|
|
122
|
+
assert not (agent.messages[i].role == Role.user and agent.messages[i-1].role == Role.tool), \
|
|
123
|
+
f"user after tool at {i}"
|
|
124
|
+
|
|
125
|
+
@pytest.mark.asyncio
|
|
126
|
+
async def test_messagelist_integrity(tmp_path):
|
|
127
|
+
from drydock.core.types import MessageList
|
|
128
|
+
agent = _agent(tmp_path)
|
|
129
|
+
await _run(agent, "Hello")
|
|
130
|
+
assert isinstance(agent.messages, MessageList)
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
# ============================================================================
|
|
134
|
+
# Agent behavior
|
|
135
|
+
# ============================================================================
|
|
136
|
+
|
|
137
|
+
@pytest.mark.asyncio
|
|
138
|
+
async def test_ambiguous_prompt_no_infinite_loop(tmp_path):
|
|
139
|
+
agent = _agent(tmp_path, max_turns=8)
|
|
140
|
+
events = await _run(agent, "test", max_events=50)
|
|
141
|
+
tool_calls = [e for e in events if isinstance(e, ToolCallEvent)]
|
|
142
|
+
assert len(tool_calls) < 20, f"Ambiguous 'test' caused {len(tool_calls)} tool calls"
|
|
143
|
+
|
|
144
|
+
@pytest.mark.asyncio
|
|
145
|
+
async def test_agent_stops_cleanly(tmp_path):
|
|
146
|
+
agent = _agent(tmp_path)
|
|
147
|
+
events = await _run(agent, "What is 2+2?", max_events=20)
|
|
148
|
+
assert len(events) < 20
|
|
149
|
+
|
|
150
|
+
@pytest.mark.asyncio
|
|
151
|
+
async def test_system_prompt_present(tmp_path):
|
|
152
|
+
agent = _agent(tmp_path)
|
|
153
|
+
await _run(agent, "hi")
|
|
154
|
+
assert agent.messages[0].role == Role.system
|
|
155
|
+
assert "DryDock" in agent.messages[0].content
|
|
156
|
+
|
|
157
|
+
@pytest.mark.asyncio
|
|
158
|
+
async def test_no_understood_in_messages(tmp_path):
|
|
159
|
+
agent = _agent(tmp_path)
|
|
160
|
+
events = await _run(agent, "Read /nonexistent/file.py")
|
|
161
|
+
for msg in agent.messages:
|
|
162
|
+
if msg.role == Role.assistant:
|
|
163
|
+
assert "Understood." not in (msg.content or "")
|
|
164
|
+
|
|
165
|
+
|
|
166
|
+
# ============================================================================
|
|
167
|
+
# Bash abuse prevention
|
|
168
|
+
# ============================================================================
|
|
169
|
+
|
|
170
|
+
@pytest.mark.asyncio
|
|
171
|
+
async def test_bash_abuse_limited(tmp_path):
|
|
172
|
+
"""Agent should not run 12+ bash commands without making an edit."""
|
|
173
|
+
agent = _agent(tmp_path, max_turns=15)
|
|
174
|
+
events = await _run(agent, "Explore the entire filesystem structure of this project", max_events=80)
|
|
175
|
+
bash_calls = [e for e in events if isinstance(e, ToolCallEvent) and e.tool_name == "bash"]
|
|
176
|
+
# Should be stopped before 12
|
|
177
|
+
assert len(bash_calls) <= 15, f"Agent ran {len(bash_calls)} bash commands"
|
|
178
|
+
|
|
179
|
+
|
|
180
|
+
# ============================================================================
|
|
181
|
+
# New tools work
|
|
182
|
+
# ============================================================================
|
|
183
|
+
|
|
184
|
+
@pytest.mark.asyncio
|
|
185
|
+
async def test_glob_tool_works(tmp_path):
|
|
186
|
+
"""Glob should find files."""
|
|
187
|
+
(tmp_path / "test1.py").write_text("# test")
|
|
188
|
+
(tmp_path / "test2.py").write_text("# test")
|
|
189
|
+
agent = _agent(tmp_path)
|
|
190
|
+
events = await _run(agent, f"Find all .py files in {tmp_path}")
|
|
191
|
+
assert len(events) >= 1
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
"""SMOKE TESTS — Run on every code change (< 5 seconds).
|
|
2
|
+
|
|
3
|
+
Absolute minimum checks that DryDock isn't broken.
|
|
4
|
+
No backend needed. Pure code/config validation.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
from pathlib import Path
|
|
10
|
+
|
|
11
|
+
import pytest
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
# ============================================================================
|
|
15
|
+
# 1. Package imports don't crash
|
|
16
|
+
# ============================================================================
|
|
17
|
+
|
|
18
|
+
class TestImports:
|
|
19
|
+
def test_core_imports(self):
|
|
20
|
+
from drydock.core.agent_loop import AgentLoop
|
|
21
|
+
from drydock.core.types import LLMMessage, MessageList, Role
|
|
22
|
+
assert AgentLoop
|
|
23
|
+
assert LLMMessage
|
|
24
|
+
assert MessageList
|
|
25
|
+
|
|
26
|
+
def test_config_imports(self):
|
|
27
|
+
from drydock.core.config import VibeConfig, ModelConfig, ProviderConfig
|
|
28
|
+
assert VibeConfig
|
|
29
|
+
|
|
30
|
+
def test_tool_imports(self):
|
|
31
|
+
from drydock.core.tools.builtins.bash import Bash
|
|
32
|
+
from drydock.core.tools.builtins.grep import Grep
|
|
33
|
+
from drydock.core.tools.builtins.search_replace import SearchReplace
|
|
34
|
+
from drydock.core.tools.builtins.glob_tool import Glob
|
|
35
|
+
from drydock.core.tools.builtins.notebook_edit import NotebookEdit
|
|
36
|
+
from drydock.core.tools.builtins.task_manager import TaskCreate
|
|
37
|
+
from drydock.core.tools.builtins.lsp import Lsp
|
|
38
|
+
from drydock.core.tools.builtins.cron import CronCreate
|
|
39
|
+
from drydock.core.tools.builtins.tool_search import ToolSearch
|
|
40
|
+
from drydock.core.tools.builtins.worktree import EnterWorktree
|
|
41
|
+
from drydock.core.tools.builtins.invoke_skill import InvokeSkill
|
|
42
|
+
assert Glob and Lsp and ToolSearch
|
|
43
|
+
|
|
44
|
+
def test_hook_imports(self):
|
|
45
|
+
from drydock.core.hooks import HookManager, HookEvent
|
|
46
|
+
assert HookManager
|
|
47
|
+
assert HookEvent.PRE_TOOL_USE
|
|
48
|
+
|
|
49
|
+
def test_consultant_imports(self):
|
|
50
|
+
from drydock.core.consultant import ask_consultant, is_consultant_available
|
|
51
|
+
assert ask_consultant
|
|
52
|
+
assert is_consultant_available
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
# ============================================================================
|
|
56
|
+
# 2. Branding correct
|
|
57
|
+
# ============================================================================
|
|
58
|
+
|
|
59
|
+
class TestBranding:
|
|
60
|
+
def test_system_prompt_says_drydock(self):
|
|
61
|
+
prompt = Path(__file__).parent.parent / "drydock" / "core" / "prompts" / "cli.md"
|
|
62
|
+
assert "DryDock" in prompt.read_text()
|
|
63
|
+
|
|
64
|
+
def test_no_vibe_in_defaults(self):
|
|
65
|
+
from drydock.core.config._settings import DEFAULT_MODELS
|
|
66
|
+
for m in DEFAULT_MODELS:
|
|
67
|
+
assert "vibe" not in m.name.lower()
|
|
68
|
+
|
|
69
|
+
def test_version_not_empty(self):
|
|
70
|
+
from drydock import __version__
|
|
71
|
+
assert __version__ and len(__version__) > 2
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
# ============================================================================
|
|
75
|
+
# 3. Critical safety checks
|
|
76
|
+
# ============================================================================
|
|
77
|
+
|
|
78
|
+
class TestSafety:
|
|
79
|
+
def test_circuit_breaker_exists(self):
|
|
80
|
+
from drydock.core.agent_loop import AgentLoop
|
|
81
|
+
assert hasattr(AgentLoop, "_circuit_breaker_check")
|
|
82
|
+
|
|
83
|
+
def test_message_ordering_exists(self):
|
|
84
|
+
from drydock.core.agent_loop import AgentLoop
|
|
85
|
+
assert hasattr(AgentLoop, "_sanitize_message_ordering")
|
|
86
|
+
|
|
87
|
+
def test_injection_guard_exists(self):
|
|
88
|
+
from drydock.core.tools.injection_guard import check_content_for_injection
|
|
89
|
+
assert check_content_for_injection("normal text") is None
|
|
90
|
+
|
|
91
|
+
def test_binary_file_guard(self):
|
|
92
|
+
from drydock.core.tools.builtins.write_file import WriteFile
|
|
93
|
+
assert hasattr(WriteFile, "_BINARY_EXTENSIONS")
|
|
94
|
+
assert ".pptx" in WriteFile._BINARY_EXTENSIONS
|
|
95
|
+
|
|
96
|
+
def test_test_file_blocked(self):
|
|
97
|
+
from drydock.core.tools.base import ToolError
|
|
98
|
+
from drydock.core.tools.builtins.search_replace import SearchReplace
|
|
99
|
+
import inspect
|
|
100
|
+
src = inspect.getsource(SearchReplace.run)
|
|
101
|
+
assert "BLOCKED" in src # Test files should be blocked
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
# ============================================================================
|
|
105
|
+
# 4. Tools have prompts
|
|
106
|
+
# ============================================================================
|
|
107
|
+
|
|
108
|
+
class TestToolPrompts:
|
|
109
|
+
def test_all_tools_have_prompts(self):
|
|
110
|
+
tools_dir = Path(__file__).parent.parent / "drydock" / "core" / "tools" / "builtins"
|
|
111
|
+
prompts_dir = tools_dir / "prompts"
|
|
112
|
+
tool_files = {f.stem for f in tools_dir.glob("*.py") if f.stem != "__init__"}
|
|
113
|
+
prompt_files = {f.stem for f in prompts_dir.glob("*.md") if f.stem != "__init__"}
|
|
114
|
+
|
|
115
|
+
# Not all tools need prompts (some are internal)
|
|
116
|
+
core_tools = {"bash", "grep", "read_file", "search_replace", "write_file",
|
|
117
|
+
"glob", "notebook_edit", "task_manager", "lsp", "cron",
|
|
118
|
+
"invoke_skill", "worktree", "tool_search"}
|
|
119
|
+
missing = core_tools - prompt_files
|
|
120
|
+
assert not missing, f"Missing prompt files for: {missing}"
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
# ============================================================================
|
|
124
|
+
# 5. Skills bundled
|
|
125
|
+
# ============================================================================
|
|
126
|
+
|
|
127
|
+
class TestSkills:
|
|
128
|
+
def test_all_skills_exist(self):
|
|
129
|
+
skills_dir = Path(__file__).parent.parent / "drydock" / "skills"
|
|
130
|
+
expected = {"create-presentation", "deep-research", "investigate", "review", "ship", "batch", "simplify"}
|
|
131
|
+
actual = {d.name for d in skills_dir.iterdir() if d.is_dir() and (d / "SKILL.md").exists()}
|
|
132
|
+
missing = expected - actual
|
|
133
|
+
assert not missing, f"Missing skills: {missing}"
|
|
134
|
+
|
|
135
|
+
def test_skills_have_valid_frontmatter(self):
|
|
136
|
+
from drydock.core.skills.parser import parse_frontmatter
|
|
137
|
+
skills_dir = Path(__file__).parent.parent / "drydock" / "skills"
|
|
138
|
+
for skill_dir in skills_dir.iterdir():
|
|
139
|
+
skill_file = skill_dir / "SKILL.md"
|
|
140
|
+
if skill_file.exists():
|
|
141
|
+
content = skill_file.read_text()
|
|
142
|
+
metadata, _ = parse_frontmatter(content)
|
|
143
|
+
assert "name" in metadata, f"Skill {skill_dir.name} missing 'name'"
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
# ============================================================================
|
|
147
|
+
# 6. Config
|
|
148
|
+
# ============================================================================
|
|
149
|
+
|
|
150
|
+
class TestConfig:
|
|
151
|
+
def test_consultant_model_field(self):
|
|
152
|
+
from drydock.core.config import VibeConfig
|
|
153
|
+
assert "consultant_model" in VibeConfig.model_fields
|
|
154
|
+
|
|
155
|
+
def test_drydock_home_default(self):
|
|
156
|
+
import inspect
|
|
157
|
+
from drydock.core.paths import _vibe_home
|
|
158
|
+
src = inspect.getsource(_vibe_home)
|
|
159
|
+
assert ".drydock" in src
|
|
160
|
+
|
|
161
|
+
|
|
162
|
+
# ============================================================================
|
|
163
|
+
# 7. Commands registered
|
|
164
|
+
# ============================================================================
|
|
165
|
+
|
|
166
|
+
class TestCommands:
|
|
167
|
+
def test_core_commands_registered(self):
|
|
168
|
+
from drydock.cli.commands import CommandRegistry
|
|
169
|
+
registry = CommandRegistry()
|
|
170
|
+
expected = {"help", "config", "clear", "compact", "exit", "status", "consult", "rewind"}
|
|
171
|
+
actual = set(registry.commands.keys())
|
|
172
|
+
missing = expected - actual
|
|
173
|
+
assert not missing, f"Missing commands: {missing}"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{drydock_cli-1.1.0 → drydock_cli-1.1.2}/drydock/cli/plan_offer/adapters/http_whoami_gateway.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|