drydock-cli 0.7.3__tar.gz → 0.8.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/PKG-INFO +2 -1
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/cli/cli.py +1 -1
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/cli/textual_ui/external_editor.py +1 -1
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/core/agent_loop.py +43 -9
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/core/auth/github.py +1 -1
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/core/config/_settings.py +1 -1
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/core/logger.py +1 -1
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/core/programmatic.py +1 -1
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/core/tools/builtins/search_replace.py +6 -3
- drydock_cli-0.8.0/drydock/core/tools/builtins/websearch.py +133 -0
- drydock_cli-0.8.0/drydock/skills/investigate/SKILL.md +67 -0
- drydock_cli-0.8.0/drydock/skills/review/SKILL.md +67 -0
- drydock_cli-0.8.0/drydock/skills/ship/SKILL.md +65 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/pyproject.toml +5 -1
- drydock_cli-0.8.0/scripts/backup.sh +84 -0
- drydock_cli-0.8.0/tests/test_current_bugs.py +150 -0
- drydock_cli-0.7.3/drydock/core/tools/builtins/websearch.py +0 -158
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/.github/CODEOWNERS +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/.github/DISCUSSION_TEMPLATE/ideas.yml +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/.github/ISSUE_TEMPLATE/bug-report.yml +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/.github/ISSUE_TEMPLATE/config.yml +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/.github/workflows/build-and-upload.yml +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/.github/workflows/ci.yml +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/.github/workflows/issue-labeler.yml +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/.github/workflows/release.yml +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/.gitignore +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/.pre-commit-config.yaml +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/.python-version +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/.typos.toml +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/.vscode/extensions.json +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/.vscode/launch.json +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/.vscode/settings.json +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/AGENTS.md +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/CHANGELOG.md +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/CLAUDE.md +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/CONTRIBUTING.md +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/Drydock_rebrand.md +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/LICENSE +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/NOTICE +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/PRD.md +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/README.md +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/action.yml +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/distribution/zed/LICENSE +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/distribution/zed/extension.toml +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/distribution/zed/icons/mistral_vibe.svg +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/docs/README.md +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/docs/acp-setup.md +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/docs/proxy-setup.md +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/__init__.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/acp/__init__.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/acp/acp_agent_loop.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/acp/acp_logger.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/acp/entrypoint.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/acp/tools/__init__.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/acp/tools/base.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/acp/tools/builtins/bash.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/acp/tools/builtins/read_file.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/acp/tools/builtins/search_replace.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/acp/tools/builtins/todo.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/acp/tools/builtins/write_file.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/acp/tools/session_update.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/acp/utils.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/cli/__init__.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/cli/autocompletion/__init__.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/cli/autocompletion/base.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/cli/autocompletion/path_completion.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/cli/autocompletion/slash_command.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/cli/clipboard.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/cli/commands.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/cli/entrypoint.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/cli/history_manager.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/cli/plan_offer/adapters/http_whoami_gateway.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/cli/plan_offer/decide_plan_offer.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/cli/plan_offer/ports/whoami_gateway.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/cli/terminal_setup.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/cli/textual_ui/__init__.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/cli/textual_ui/ansi_markdown.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/cli/textual_ui/app.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/cli/textual_ui/app.tcss +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/cli/textual_ui/handlers/__init__.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/cli/textual_ui/handlers/event_handler.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/cli/textual_ui/notifications/__init__.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/cli/textual_ui/notifications/adapters/__init__.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/cli/textual_ui/notifications/adapters/textual_notification_adapter.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/cli/textual_ui/notifications/ports/__init__.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/cli/textual_ui/notifications/ports/notification_port.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/cli/textual_ui/widgets/__init__.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/cli/textual_ui/widgets/approval_app.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/cli/textual_ui/widgets/banner/banner.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/cli/textual_ui/widgets/banner/petit_chat.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/cli/textual_ui/widgets/braille_renderer.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/cli/textual_ui/widgets/chat_input/__init__.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/cli/textual_ui/widgets/chat_input/body.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/cli/textual_ui/widgets/chat_input/completion_manager.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/cli/textual_ui/widgets/chat_input/completion_popup.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/cli/textual_ui/widgets/chat_input/container.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/cli/textual_ui/widgets/chat_input/text_area.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/cli/textual_ui/widgets/compact.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/cli/textual_ui/widgets/config_app.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/cli/textual_ui/widgets/context_progress.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/cli/textual_ui/widgets/load_more.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/cli/textual_ui/widgets/loading.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/cli/textual_ui/widgets/messages.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/cli/textual_ui/widgets/no_markup_static.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/cli/textual_ui/widgets/path_display.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/cli/textual_ui/widgets/proxy_setup_app.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/cli/textual_ui/widgets/question_app.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/cli/textual_ui/widgets/session_picker.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/cli/textual_ui/widgets/spinner.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/cli/textual_ui/widgets/status_message.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/cli/textual_ui/widgets/teleport_message.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/cli/textual_ui/widgets/tool_widgets.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/cli/textual_ui/widgets/tools.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/cli/textual_ui/widgets/vscode_compat.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/cli/textual_ui/windowing/__init__.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/cli/textual_ui/windowing/history.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/cli/textual_ui/windowing/history_windowing.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/cli/textual_ui/windowing/state.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/cli/update_notifier/__init__.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/cli/update_notifier/adapters/filesystem_update_cache_repository.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/cli/update_notifier/adapters/github_update_gateway.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/cli/update_notifier/adapters/pypi_update_gateway.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/cli/update_notifier/ports/update_cache_repository.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/cli/update_notifier/ports/update_gateway.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/cli/update_notifier/update.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/cli/update_notifier/whats_new.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/core/__init__.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/core/agents/__init__.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/core/agents/manager.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/core/agents/models.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/core/auth/__init__.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/core/auth/crypto.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/core/autocompletion/__init__.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/core/autocompletion/completers.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/core/autocompletion/file_indexer/__init__.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/core/autocompletion/file_indexer/ignore_rules.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/core/autocompletion/file_indexer/indexer.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/core/autocompletion/file_indexer/store.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/core/autocompletion/file_indexer/watcher.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/core/autocompletion/fuzzy.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/core/autocompletion/path_prompt.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/core/autocompletion/path_prompt_adapter.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/core/config/__init__.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/core/config/harness_files/__init__.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/core/config/harness_files/_harness_manager.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/core/config/harness_files/_paths.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/core/consultant.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/core/drydock_states.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/core/llm/__init__.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/core/llm/backend/anthropic.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/core/llm/backend/base.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/core/llm/backend/factory.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/core/llm/backend/generic.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/core/llm/backend/mistral.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/core/llm/backend/reasoning_adapter.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/core/llm/backend/vertex.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/core/llm/exceptions.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/core/llm/format.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/core/llm/message_utils.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/core/llm/types.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/core/middleware.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/core/output_formatters.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/core/paths/__init__.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/core/paths/_local_config_walk.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/core/paths/_vibe_home.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/core/paths/conventions.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/core/plan_session.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/core/prompts/__init__.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/core/prompts/cli.md +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/core/prompts/compact.md +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/core/prompts/dangerous_directory.md +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/core/prompts/diagnostic.md +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/core/prompts/explore.md +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/core/prompts/planner.md +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/core/prompts/project_context.md +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/core/prompts/tests.md +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/core/proxy_setup.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/core/session/session_loader.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/core/session/session_logger.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/core/session/session_migration.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/core/session/state_file.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/core/skills/__init__.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/core/skills/manager.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/core/skills/models.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/core/skills/parser.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/core/slug.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/core/system_prompt.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/core/telemetry/__init__.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/core/telemetry/send.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/core/teleport/errors.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/core/teleport/git.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/core/teleport/nuage.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/core/teleport/teleport.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/core/teleport/types.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/core/tools/base.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/core/tools/builtins/ask_user_question.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/core/tools/builtins/bash.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/core/tools/builtins/exit_plan_mode.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/core/tools/builtins/grep.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/core/tools/builtins/prompts/__init__.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/core/tools/builtins/prompts/ask_user_question.md +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/core/tools/builtins/prompts/bash.md +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/core/tools/builtins/prompts/grep.md +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/core/tools/builtins/prompts/read_file.md +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/core/tools/builtins/prompts/search_replace.md +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/core/tools/builtins/prompts/swe_bench.md +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/core/tools/builtins/prompts/task.md +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/core/tools/builtins/prompts/todo.md +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/core/tools/builtins/prompts/webfetch.md +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/core/tools/builtins/prompts/websearch.md +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/core/tools/builtins/prompts/write_file.md +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/core/tools/builtins/read_file.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/core/tools/builtins/task.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/core/tools/builtins/todo.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/core/tools/builtins/webfetch.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/core/tools/builtins/write_file.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/core/tools/injection_guard.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/core/tools/manager.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/core/tools/mcp/__init__.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/core/tools/mcp/registry.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/core/tools/mcp/tools.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/core/tools/mcp_sampling.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/core/tools/ui.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/core/tools/utils.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/core/trusted_folders.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/core/types.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/core/utils.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/setup/onboarding/__init__.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/setup/onboarding/base.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/setup/onboarding/onboarding.tcss +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/setup/onboarding/screens/__init__.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/setup/onboarding/screens/api_key.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/setup/onboarding/screens/welcome.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/setup/trusted_folders/trust_folder_dialog.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/setup/trusted_folders/trust_folder_dialog.tcss +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/skills/__init__.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/skills/create-presentation/SKILL.md +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/skills/deep-research/SKILL.md +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/whats_new.md +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock-acp.spec +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock_terms.md +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/flake.lock +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/flake.nix +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/scripts/README.md +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/scripts/bump_version.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/scripts/deploy_to_github.sh +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/scripts/install.sh +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/scripts/prepare_release.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/scripts/publish_to_pypi.sh +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/__init__.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/acp/conftest.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/acp/test_acp.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/acp/test_agent_thought.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/acp/test_bash.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/acp/test_compact_session_updates.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/acp/test_content.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/acp/test_initialize.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/acp/test_list_sessions.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/acp/test_load_session.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/acp/test_multi_session.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/acp/test_new_session.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/acp/test_proxy_setup_acp.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/acp/test_read_file.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/acp/test_search_replace.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/acp/test_set_config_option.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/acp/test_set_mode.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/acp/test_set_model.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/acp/test_tool_call_session_update.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/acp/test_utils.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/acp/test_write_file.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/autocompletion/test_file_indexer.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/autocompletion/test_fuzzy.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/autocompletion/test_path_completer_fuzzy.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/autocompletion/test_path_completer_recursive.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/autocompletion/test_path_completion_controller.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/autocompletion/test_path_prompt_transformer.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/autocompletion/test_slash_command_controller.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/autocompletion/test_ui_chat_autocompletion.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/backend/__init__.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/backend/data/__init__.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/backend/data/fireworks.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/backend/data/mistral.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/backend/test_anthropic_adapter.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/backend/test_backend.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/backend/test_reasoning_adapter.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/backend/test_vertex_anthropic_adapter.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/cli/plan_offer/adapters/fake_whoami_gateway.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/cli/plan_offer/test_decide_plan_offer.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/cli/plan_offer/test_http_whoami_gateway.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/cli/test_bell_notifications.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/cli/test_braille_renderer.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/cli/test_clipboard.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/cli/test_commands.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/cli/test_copy_shortcuts.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/cli/test_external_editor.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/cli/test_no_markup_static.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/cli/test_question_app.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/cli/test_spinner.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/cli/test_switching_mode.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/cli/test_ui_clipboard_notifications.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/cli/test_ui_session_incremental_renderer.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/cli/test_ui_session_resume.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/cli/test_ui_skill_dispatch.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/cli/textual_ui/__init__.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/cli/textual_ui/test_session_picker.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/conftest.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/core/test_agents.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/core/test_auth_crypto.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/core/test_auth_github.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/core/test_config_load_dotenv.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/core/test_config_paths.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/core/test_config_resolution.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/core/test_file_logging.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/core/test_plan_session.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/core/test_proxy_setup.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/core/test_slug.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/core/test_telemetry_send.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/core/test_teleport_git.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/core/test_teleport_nuage.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/core/test_teleport_service.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/core/test_trusted_folders.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/core/test_utils.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/e2e/common.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/e2e/conftest.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/e2e/mock_server.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/e2e/test_cli_tui_onboarding.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/e2e/test_cli_tui_streaming.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/e2e/test_cli_tui_tool_approval.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/mock/__init__.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/mock/mock_backend_factory.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/mock/mock_entrypoint.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/mock/utils.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/onboarding/test_run_onboarding.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/onboarding/test_ui_onboarding.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/session/test_session_loader.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/session/test_session_logger.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/session/test_session_migration.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/skills/conftest.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/skills/test_manager.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/skills/test_models.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/skills/test_parser.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/snapshots/__snapshots__/test_ui_snapshot_ask_user_question/test_snapshot_ask_user_question_collapsed.svg +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/snapshots/__snapshots__/test_ui_snapshot_ask_user_question/test_snapshot_ask_user_question_expanded.svg +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/snapshots/__snapshots__/test_ui_snapshot_basic_conversation/test_snapshot_shows_basic_conversation.svg +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/snapshots/__snapshots__/test_ui_snapshot_code_block_horizontal_scrolling/test_snapshot_allows_horizontal_scrolling_for_long_code_blocks.svg +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/snapshots/__snapshots__/test_ui_snapshot_empty_assistant_before_reasoning/test_snapshot_empty_assistant_removed_when_reasoning_starts.svg +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/snapshots/__snapshots__/test_ui_snapshot_modes/test_snapshot_cycle_to_accept_edits_mode.svg +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/snapshots/__snapshots__/test_ui_snapshot_modes/test_snapshot_cycle_to_auto_approve_mode.svg +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/snapshots/__snapshots__/test_ui_snapshot_modes/test_snapshot_cycle_to_plan_mode.svg +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/snapshots/__snapshots__/test_ui_snapshot_modes/test_snapshot_cycle_wraps_to_default.svg +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/snapshots/__snapshots__/test_ui_snapshot_modes/test_snapshot_default_mode.svg +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/snapshots/__snapshots__/test_ui_snapshot_parallel_tool_calls/test_snapshot_parallel_tool_calls_pending.svg +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/snapshots/__snapshots__/test_ui_snapshot_parallel_tool_calls/test_snapshot_parallel_tool_calls_resolved.svg +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/snapshots/__snapshots__/test_ui_snapshot_proxy_setup/test_snapshot_proxy_setup_cancel_discards_changes.svg +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/snapshots/__snapshots__/test_ui_snapshot_proxy_setup/test_snapshot_proxy_setup_edit_existing_values.svg +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/snapshots/__snapshots__/test_ui_snapshot_proxy_setup/test_snapshot_proxy_setup_initial_empty.svg +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/snapshots/__snapshots__/test_ui_snapshot_proxy_setup/test_snapshot_proxy_setup_initial_with_values.svg +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/snapshots/__snapshots__/test_ui_snapshot_proxy_setup/test_snapshot_proxy_setup_save_error.svg +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/snapshots/__snapshots__/test_ui_snapshot_proxy_setup/test_snapshot_proxy_setup_save_new_values.svg +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_question_answer_first_advance.svg +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_question_first_answered_checkmark.svg +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_question_initial.svg +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_question_navigate_left_wraps.svg +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_question_navigate_right.svg +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_question_tab_to_second.svg +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_select_initial.svg +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_select_mixed_selection.svg +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_select_navigate_to_submit.svg +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_select_other_with_text.svg +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_select_toggle_first.svg +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_select_toggle_multiple.svg +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_select_untoggle.svg +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_question_app_initial.svg +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_question_app_navigate_down.svg +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_question_app_navigate_to_other.svg +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_question_app_navigate_to_third_option.svg +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_question_app_navigate_up_wraps.svg +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_question_app_other_typing.svg +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/snapshots/__snapshots__/test_ui_snapshot_reasoning_content/test_snapshot_buffered_reasoning_yields_before_content.svg +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/snapshots/__snapshots__/test_ui_snapshot_reasoning_content/test_snapshot_shows_interleaved_reasoning.svg +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/snapshots/__snapshots__/test_ui_snapshot_reasoning_content/test_snapshot_shows_reasoning_content.svg +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/snapshots/__snapshots__/test_ui_snapshot_reasoning_content/test_snapshot_shows_reasoning_content_expanded.svg +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/snapshots/__snapshots__/test_ui_snapshot_release_update_notification/test_snapshot_shows_release_update_notification.svg +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/snapshots/__snapshots__/test_ui_snapshot_session_resume/test_snapshot_shows_resumed_session_messages.svg +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/snapshots/__snapshots__/test_ui_snapshot_streaming_tool_call/test_snapshot_tool_call_partial.svg +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/snapshots/__snapshots__/test_ui_snapshot_streaming_tool_call/test_snapshot_tool_call_updated.svg +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_push_confirmation_cancel_selected.svg +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_push_confirmation_multiple_commits.svg +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_push_confirmation_single_commit.svg +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_status_auth_complete.svg +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_status_auth_required.svg +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_status_checking_git.svg +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_status_complete.svg +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_status_error.svg +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_status_pushing.svg +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_status_sending_token.svg +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_status_starting_workflow.svg +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/snapshots/__snapshots__/test_ui_snapshot_whats_new/test_snapshot_shows_no_plan_message.svg +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/snapshots/__snapshots__/test_ui_snapshot_whats_new/test_snapshot_shows_switch_message.svg +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/snapshots/__snapshots__/test_ui_snapshot_whats_new/test_snapshot_shows_upgrade_message.svg +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/snapshots/__snapshots__/test_ui_snapshot_whats_new/test_snapshot_shows_whats_new_message.svg +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/snapshots/base_snapshot_test_app.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/snapshots/conftest.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/snapshots/snap_compare.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/snapshots/test_ui_snapshot_ask_user_question.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/snapshots/test_ui_snapshot_basic_conversation.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/snapshots/test_ui_snapshot_code_block_horizontal_scrolling.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/snapshots/test_ui_snapshot_empty_assistant_before_reasoning.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/snapshots/test_ui_snapshot_modes.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/snapshots/test_ui_snapshot_parallel_tool_calls.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/snapshots/test_ui_snapshot_proxy_setup.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/snapshots/test_ui_snapshot_question_app.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/snapshots/test_ui_snapshot_reasoning_content.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/snapshots/test_ui_snapshot_release_update_notification.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/snapshots/test_ui_snapshot_session_resume.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/snapshots/test_ui_snapshot_streaming_tool_call.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/snapshots/test_ui_snapshot_teleport.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/snapshots/test_ui_snapshot_whats_new.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/stubs/fake_backend.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/stubs/fake_client.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/stubs/fake_tool.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/test_agent_auto_compact.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/test_agent_backend.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/test_agent_observer_streaming.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/test_agent_stats.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/test_agent_tasks.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/test_agent_tool_call.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/test_agents.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/test_cli_programmatic_preload.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/test_drydock_regression.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/test_drydock_tasks.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/test_history_manager.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/test_integration.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/test_loop_detection.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/test_message_id.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/test_message_merging.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/test_middleware.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/test_real_failures.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/test_real_issues.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/test_reasoning_content.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/test_system_prompt.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/test_tagged_text.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/test_ui_external_editor.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/test_ui_input_history.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/test_user_issues.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/tools/test_ask_user_question.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/tools/test_bash.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/tools/test_exit_plan_mode.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/tools/test_grep.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/tools/test_invoke_context.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/tools/test_manager_get_tool_config.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/tools/test_mcp.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/tools/test_mcp_sampling.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/tools/test_task.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/tools/test_ui_bash_execution.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/tools/test_webfetch.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/tools/test_websearch.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/update_notifier/adapters/fake_update_cache_repository.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/update_notifier/adapters/fake_update_gateway.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/update_notifier/test_do_update.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/update_notifier/test_filesystem_update_cache_repository.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/update_notifier/test_github_update_gateway.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/update_notifier/test_pypi_update_gateway.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/update_notifier/test_ui_update_notification.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/update_notifier/test_update_use_case.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/update_notifier/test_whats_new.py +0 -0
- {drydock_cli-0.7.3 → drydock_cli-0.8.0}/uv.lock +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: drydock-cli
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.8.0
|
|
4
4
|
Summary: Drydock — nautical CLI coding agent
|
|
5
5
|
Project-URL: Homepage, https://github.com/fbobe321/drydock
|
|
6
6
|
Project-URL: Repository, https://github.com/fbobe321/drydock
|
|
@@ -24,6 +24,7 @@ Classifier: Topic :: Utilities
|
|
|
24
24
|
Requires-Python: >=3.12
|
|
25
25
|
Requires-Dist: agent-client-protocol==0.8.1
|
|
26
26
|
Requires-Dist: anyio>=4.12.0
|
|
27
|
+
Requires-Dist: beautifulsoup4>=4.12.0
|
|
27
28
|
Requires-Dist: cachetools>=5.5.0
|
|
28
29
|
Requires-Dist: cryptography<=46.0.3,>=44.0.0
|
|
29
30
|
Requires-Dist: gitpython>=3.1.46
|
|
@@ -196,7 +196,7 @@ def run_cli(args: argparse.Namespace) -> None:
|
|
|
196
196
|
entrypoint_metadata=EntrypointMetadata(
|
|
197
197
|
agent_entrypoint="cli",
|
|
198
198
|
agent_version=__version__,
|
|
199
|
-
client_name="
|
|
199
|
+
client_name="drydock_cli",
|
|
200
200
|
client_version=__version__,
|
|
201
201
|
),
|
|
202
202
|
)
|
|
@@ -16,7 +16,7 @@ class ExternalEditor:
|
|
|
16
16
|
|
|
17
17
|
def edit(self, initial_content: str = "") -> str | None:
|
|
18
18
|
editor = self.get_editor()
|
|
19
|
-
fd, filepath = tempfile.mkstemp(suffix=".md", prefix="
|
|
19
|
+
fd, filepath = tempfile.mkstemp(suffix=".md", prefix="drydock_")
|
|
20
20
|
try:
|
|
21
21
|
with os.fdopen(fd, "w") as f:
|
|
22
22
|
f.write(initial_content)
|
|
@@ -482,6 +482,7 @@ class AgentLoop:
|
|
|
482
482
|
bash_count = 0 # Track consecutive bash calls without an edit
|
|
483
483
|
search_replace_failures = 0 # Track failed search_replace attempts
|
|
484
484
|
files_explored: list[str] = [] # Track files read for context state
|
|
485
|
+
files_modified: list[str] = [] # Track files edited for blast radius
|
|
485
486
|
context_summary_injected = False
|
|
486
487
|
while not should_break_loop:
|
|
487
488
|
# Loop protection: prevent infinite tool-call loops
|
|
@@ -551,6 +552,14 @@ class AgentLoop:
|
|
|
551
552
|
if tc.function.name in ("search_replace", "write_file"):
|
|
552
553
|
has_made_edit = True
|
|
553
554
|
bash_count = 0 # Reset on successful edit
|
|
555
|
+
# Track blast radius
|
|
556
|
+
try:
|
|
557
|
+
edit_args = json.loads(tc.function.arguments or "{}")
|
|
558
|
+
edit_path = edit_args.get("file_path", edit_args.get("path", ""))
|
|
559
|
+
if edit_path and edit_path not in files_modified:
|
|
560
|
+
files_modified.append(edit_path)
|
|
561
|
+
except (json.JSONDecodeError, AttributeError):
|
|
562
|
+
pass
|
|
554
563
|
if tc.function.name == "read_file":
|
|
555
564
|
try:
|
|
556
565
|
args = json.loads(tc.function.arguments or "{}")
|
|
@@ -569,6 +578,15 @@ class AgentLoop:
|
|
|
569
578
|
if "search_replace" in content.lower() and "error" in content.lower():
|
|
570
579
|
search_replace_failures += 1
|
|
571
580
|
|
|
581
|
+
# Blast radius check: warn when touching 5+ files
|
|
582
|
+
if len(files_modified) >= 5 and len(files_modified) % 5 == 0:
|
|
583
|
+
self._inject_system_note(
|
|
584
|
+
f"BLAST RADIUS WARNING: You have modified {len(files_modified)} files. "
|
|
585
|
+
f"Files: {', '.join(files_modified[-5:])}. "
|
|
586
|
+
f"This is a large change. Are you sure all these edits are needed? "
|
|
587
|
+
f"Consider stopping to verify your approach."
|
|
588
|
+
)
|
|
589
|
+
|
|
572
590
|
# Bash abuse detection: if model keeps using bash instead of
|
|
573
591
|
# search_replace/read_file, redirect it to the proper tools
|
|
574
592
|
if not has_made_edit and bash_count >= 10 and bash_count % 5 == 0:
|
|
@@ -579,14 +597,26 @@ class AgentLoop:
|
|
|
579
597
|
"Call search_replace NOW with your fix."
|
|
580
598
|
)
|
|
581
599
|
|
|
582
|
-
# search_replace keeps failing
|
|
583
|
-
if search_replace_failures >= 3
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
600
|
+
# 3-Strike Rule: search_replace keeps failing
|
|
601
|
+
if search_replace_failures >= 3:
|
|
602
|
+
if search_replace_failures == 3:
|
|
603
|
+
# Strike 3: STOP and ask user
|
|
604
|
+
self.messages.append(LLMMessage(
|
|
605
|
+
role=Role.user,
|
|
606
|
+
content=(
|
|
607
|
+
f"3-STRIKE RULE: Your search_replace has failed {search_replace_failures} times. "
|
|
608
|
+
"You have exhausted your attempts. STOP trying the same approach. "
|
|
609
|
+
"Either: (1) use read_file to get the EXACT text first, "
|
|
610
|
+
"(2) try a completely different file, or "
|
|
611
|
+
"(3) ask the user for help with /consult."
|
|
612
|
+
)
|
|
613
|
+
))
|
|
614
|
+
elif search_replace_failures % 3 == 0:
|
|
615
|
+
# Every 3 more failures, escalate
|
|
616
|
+
self.messages.append(LLMMessage(
|
|
617
|
+
role=Role.user,
|
|
618
|
+
content=f"STOP: {search_replace_failures} failed edits. You are stuck. Ask the user for help."
|
|
619
|
+
))
|
|
590
620
|
|
|
591
621
|
# Context budget warning: after 7 tool turns without an edit,
|
|
592
622
|
# warn that context is being consumed without progress
|
|
@@ -647,7 +677,11 @@ class AgentLoop:
|
|
|
647
677
|
should_break_loop = True
|
|
648
678
|
nudge_text = None
|
|
649
679
|
if nudge_text:
|
|
650
|
-
|
|
680
|
+
# Inject as user message so the model actually sees it
|
|
681
|
+
# (inject_system_note buries it in old tool results)
|
|
682
|
+
self.messages.append(
|
|
683
|
+
LLMMessage(role=Role.user, content=nudge_text)
|
|
684
|
+
)
|
|
651
685
|
logger.info("Model gave text without editing — nudging (attempt %d)", text_without_action)
|
|
652
686
|
|
|
653
687
|
# If model has been investigating for too long without making an edit,
|
|
@@ -11,7 +11,7 @@ import keyring.errors
|
|
|
11
11
|
|
|
12
12
|
GITHUB_CLIENT_ID = "Ov23liJ7sk5kFDMEyvDT"
|
|
13
13
|
|
|
14
|
-
_SERVICE_NAME = "
|
|
14
|
+
_SERVICE_NAME = "drydock"
|
|
15
15
|
_KEYRING_USERNAME = "github_token"
|
|
16
16
|
_DEVICE_CODE_URL = "https://github.com/login/device/code"
|
|
17
17
|
_TOKEN_URL = "https://github.com/login/oauth/access_token"
|
|
@@ -21,7 +21,7 @@ from drydock.core.types import (
|
|
|
21
21
|
)
|
|
22
22
|
from drydock.core.utils import ConversationLimitException
|
|
23
23
|
|
|
24
|
-
_DEFAULT_CLIENT_METADATA = ClientMetadata(name="
|
|
24
|
+
_DEFAULT_CLIENT_METADATA = ClientMetadata(name="drydock_programmatic", version=__version__)
|
|
25
25
|
|
|
26
26
|
|
|
27
27
|
def run_programmatic(
|
|
@@ -119,12 +119,15 @@ class SearchReplace(
|
|
|
119
119
|
) -> AsyncGenerator[ToolStreamEvent | SearchReplaceResult, None]:
|
|
120
120
|
file_path, search_replace_blocks = self._prepare_and_validate_args(args)
|
|
121
121
|
|
|
122
|
-
#
|
|
122
|
+
# BLOCK editing test files — the bug is in source code, not tests
|
|
123
123
|
file_str = str(file_path)
|
|
124
124
|
if ("/tests/" in file_str or "/test_" in file_str or
|
|
125
125
|
file_str.endswith("_test.py") or "/testing/" in file_str):
|
|
126
|
-
|
|
127
|
-
|
|
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
|
+
)
|
|
128
131
|
|
|
129
132
|
# Injection guard: scan replacement content for suspicious patterns
|
|
130
133
|
from drydock.core.tools.injection_guard import check_content_for_injection
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from collections.abc import AsyncGenerator
|
|
4
|
+
import os
|
|
5
|
+
import urllib.parse
|
|
6
|
+
from typing import ClassVar, final
|
|
7
|
+
|
|
8
|
+
from pydantic import BaseModel, Field
|
|
9
|
+
from bs4 import BeautifulSoup
|
|
10
|
+
|
|
11
|
+
from drydock.core.tools.base import (
|
|
12
|
+
BaseTool,
|
|
13
|
+
BaseToolConfig,
|
|
14
|
+
BaseToolState,
|
|
15
|
+
InvokeContext,
|
|
16
|
+
ToolError,
|
|
17
|
+
ToolPermission,
|
|
18
|
+
)
|
|
19
|
+
from drydock.core.tools.ui import ToolCallDisplay, ToolResultDisplay, ToolUIData
|
|
20
|
+
from drydock.core.types import ToolStreamEvent
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
class WebSearchSource(BaseModel):
|
|
24
|
+
title: str
|
|
25
|
+
url: str
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
class WebSearchArgs(BaseModel):
|
|
29
|
+
query: str = Field(min_length=1)
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
class WebSearchResult(BaseModel):
|
|
33
|
+
answer: str
|
|
34
|
+
sources: list[WebSearchSource] = Field(default_factory=list)
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
class WebSearchConfig(BaseToolConfig):
|
|
38
|
+
permission: ToolPermission = ToolPermission.ASK
|
|
39
|
+
timeout: int = Field(default=30, description="HTTP timeout in seconds.")
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
class WebSearch(
|
|
43
|
+
BaseTool[WebSearchArgs, WebSearchResult, WebSearchConfig, BaseToolState],
|
|
44
|
+
ToolUIData[WebSearchArgs, WebSearchResult],
|
|
45
|
+
):
|
|
46
|
+
description: ClassVar[str] = "Search the web directly without an API key to find current information."
|
|
47
|
+
|
|
48
|
+
@classmethod
|
|
49
|
+
def is_available(cls) -> bool:
|
|
50
|
+
# Always available! No API key required.
|
|
51
|
+
return True
|
|
52
|
+
|
|
53
|
+
@final
|
|
54
|
+
async def run(
|
|
55
|
+
self, args: WebSearchArgs, ctx: InvokeContext | None = None
|
|
56
|
+
) -> AsyncGenerator[ToolStreamEvent | WebSearchResult, None]:
|
|
57
|
+
|
|
58
|
+
import httpx
|
|
59
|
+
|
|
60
|
+
# Grab your proxy settings
|
|
61
|
+
proxy_url = os.getenv("HTTPS_PROXY") or os.getenv("https_proxy") or os.getenv("HTTP_PROXY") or os.getenv("http_proxy")
|
|
62
|
+
|
|
63
|
+
headers = {
|
|
64
|
+
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
|
|
65
|
+
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
try:
|
|
69
|
+
# Respect DRYDOCK_INSECURE flag for SSL bypass
|
|
70
|
+
verify_ssl = os.environ.get("DRYDOCK_INSECURE") != "1"
|
|
71
|
+
async with httpx.AsyncClient(proxy=proxy_url, verify=not verify_ssl if verify_ssl else False, headers=headers) as client:
|
|
72
|
+
response = await client.post(
|
|
73
|
+
"https://html.duckduckgo.com/html/",
|
|
74
|
+
data={"q": args.query},
|
|
75
|
+
timeout=self.config.timeout
|
|
76
|
+
)
|
|
77
|
+
response.raise_for_status()
|
|
78
|
+
except Exception as e:
|
|
79
|
+
raise ToolError(f"Failed to fetch search results: {str(e)}")
|
|
80
|
+
|
|
81
|
+
# Parse the DuckDuckGo HTML results
|
|
82
|
+
soup = BeautifulSoup(response.text, "html.parser")
|
|
83
|
+
results = soup.find_all("div", class_="result")
|
|
84
|
+
|
|
85
|
+
text_parts = []
|
|
86
|
+
sources = []
|
|
87
|
+
|
|
88
|
+
# Extract the top 5 results
|
|
89
|
+
for res in results[:5]:
|
|
90
|
+
title_tag = res.find("a", class_="result__url")
|
|
91
|
+
snippet_tag = res.find("a", class_="result__snippet")
|
|
92
|
+
|
|
93
|
+
if title_tag and snippet_tag:
|
|
94
|
+
title = title_tag.text.strip()
|
|
95
|
+
snippet = snippet_tag.text.strip()
|
|
96
|
+
raw_url = title_tag.get("href", "")
|
|
97
|
+
|
|
98
|
+
# Clean up DuckDuckGo's redirect URLs
|
|
99
|
+
if "uddg=" in raw_url:
|
|
100
|
+
clean_url = urllib.parse.unquote(raw_url.split("uddg=")[1].split("&")[0])
|
|
101
|
+
else:
|
|
102
|
+
clean_url = raw_url
|
|
103
|
+
|
|
104
|
+
sources.append(WebSearchSource(title=title, url=clean_url))
|
|
105
|
+
text_parts.append(f"Source: {title}\nURL: {clean_url}\nInformation: {snippet}\n")
|
|
106
|
+
|
|
107
|
+
if not text_parts:
|
|
108
|
+
answer = "No relevant information found on the web."
|
|
109
|
+
else:
|
|
110
|
+
# We bundle the snippets into a single text block for your local model to read
|
|
111
|
+
answer = "Here is the raw information retrieved from the web:\n\n" + "\n".join(text_parts)
|
|
112
|
+
|
|
113
|
+
yield WebSearchResult(answer=answer, sources=sources)
|
|
114
|
+
|
|
115
|
+
@classmethod
|
|
116
|
+
def get_call_display(cls, event: ToolCallEvent) -> ToolCallDisplay:
|
|
117
|
+
if event.args is None or not isinstance(event.args, WebSearchArgs):
|
|
118
|
+
return ToolCallDisplay(summary="websearch")
|
|
119
|
+
return ToolCallDisplay(summary=f"Searching DuckDuckGo for: '{event.args.query}'")
|
|
120
|
+
|
|
121
|
+
@classmethod
|
|
122
|
+
def get_result_display(cls, event: ToolResultEvent) -> ToolResultDisplay:
|
|
123
|
+
if not isinstance(event.result, WebSearchResult):
|
|
124
|
+
return ToolResultDisplay(
|
|
125
|
+
success=False, message=event.error or event.skip_reason or "No result"
|
|
126
|
+
)
|
|
127
|
+
return ToolResultDisplay(
|
|
128
|
+
success=True, message=f"{len(event.result.sources)} web sources retrieved for the local model."
|
|
129
|
+
)
|
|
130
|
+
|
|
131
|
+
@classmethod
|
|
132
|
+
def get_status_text(cls) -> str:
|
|
133
|
+
return "Scraping the web..."
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: investigate
|
|
3
|
+
description: Systematic debugging with 3-strike rule. Investigate → Analyze → Hypothesize → Fix. Stops after 3 failed hypotheses.
|
|
4
|
+
user-invocable: true
|
|
5
|
+
allowed-tools:
|
|
6
|
+
- bash
|
|
7
|
+
- grep
|
|
8
|
+
- read_file
|
|
9
|
+
- search_replace
|
|
10
|
+
- write_file
|
|
11
|
+
- ask_user_question
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
# Investigate
|
|
15
|
+
|
|
16
|
+
Systematic debugging workflow. You are a senior debugger.
|
|
17
|
+
|
|
18
|
+
## Iron Law
|
|
19
|
+
|
|
20
|
+
**Never fix without root cause.** If you don't understand WHY the bug happens, you don't fix it.
|
|
21
|
+
|
|
22
|
+
## Workflow
|
|
23
|
+
|
|
24
|
+
### Phase 1: INVESTIGATE
|
|
25
|
+
- Read the error message / bug report carefully
|
|
26
|
+
- Identify the module and function where the bug manifests
|
|
27
|
+
- grep for the relevant code paths
|
|
28
|
+
- Read the specific functions involved
|
|
29
|
+
|
|
30
|
+
### Phase 2: ANALYZE
|
|
31
|
+
- Trace the data flow from input to the point of failure
|
|
32
|
+
- Identify what value is wrong and where it diverges from expected
|
|
33
|
+
- Check edge cases: null, empty, boundary values
|
|
34
|
+
|
|
35
|
+
### Phase 3: HYPOTHESIZE
|
|
36
|
+
State your hypothesis clearly:
|
|
37
|
+
```
|
|
38
|
+
HYPOTHESIS: The bug is caused by [X] in [file:line] because [reason].
|
|
39
|
+
EXPECTED: [what should happen]
|
|
40
|
+
ACTUAL: [what happens instead]
|
|
41
|
+
FIX: [what change to make]
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
### Phase 4: IMPLEMENT
|
|
45
|
+
- Make the minimal fix
|
|
46
|
+
- Read back the changed code to verify
|
|
47
|
+
- If the fix doesn't work, go back to Phase 3
|
|
48
|
+
|
|
49
|
+
## 3-Strike Rule
|
|
50
|
+
|
|
51
|
+
Track your failed hypotheses:
|
|
52
|
+
- Strike 1: "Hypothesis 1 failed because [reason]. Trying different approach."
|
|
53
|
+
- Strike 2: "Hypothesis 2 failed because [reason]. One more attempt."
|
|
54
|
+
- Strike 3: **STOP.** Ask the user: "I've tried 3 approaches and none worked. Here's what I've learned: [summary]. What should I try next?"
|
|
55
|
+
|
|
56
|
+
Do NOT continue past 3 strikes. Ask for help.
|
|
57
|
+
|
|
58
|
+
## Scope Lock
|
|
59
|
+
|
|
60
|
+
Once you identify the module, **stay in that module**. Do not wander to other parts of the codebase unless the bug clearly crosses module boundaries.
|
|
61
|
+
|
|
62
|
+
## Blast Radius Check
|
|
63
|
+
|
|
64
|
+
Before applying a fix, count the files you're about to change:
|
|
65
|
+
- 1-2 files: proceed
|
|
66
|
+
- 3-4 files: mention it to the user first
|
|
67
|
+
- 5+ files: **STOP and ask.** "This fix touches {N} files. Should I proceed?"
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: review
|
|
3
|
+
description: Automated code review. Two-pass (critical then informational), scope drift detection, fix-first.
|
|
4
|
+
user-invocable: true
|
|
5
|
+
allowed-tools:
|
|
6
|
+
- bash
|
|
7
|
+
- grep
|
|
8
|
+
- read_file
|
|
9
|
+
- search_replace
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
# Code Review
|
|
13
|
+
|
|
14
|
+
You are a senior code reviewer. Review the current changes.
|
|
15
|
+
|
|
16
|
+
## Two-Pass Review
|
|
17
|
+
|
|
18
|
+
### Pass 1: CRITICAL (must fix before merge)
|
|
19
|
+
- Security vulnerabilities (injection, XSS, auth bypass)
|
|
20
|
+
- Data loss risks (missing transactions, race conditions)
|
|
21
|
+
- Breaking changes to public APIs
|
|
22
|
+
- Missing error handling that could crash
|
|
23
|
+
- Tests missing for new functionality
|
|
24
|
+
|
|
25
|
+
### Pass 2: INFORMATIONAL (nice to have)
|
|
26
|
+
- Code style and naming
|
|
27
|
+
- Performance suggestions
|
|
28
|
+
- Refactoring opportunities
|
|
29
|
+
- Documentation gaps
|
|
30
|
+
|
|
31
|
+
## Workflow
|
|
32
|
+
|
|
33
|
+
1. Run `git diff` to see what changed
|
|
34
|
+
2. Read each changed file
|
|
35
|
+
3. For each issue found:
|
|
36
|
+
- **Critical**: Fix it immediately with search_replace
|
|
37
|
+
- **Judgment call**: Ask the user with options
|
|
38
|
+
- **Informational**: Note it but don't block
|
|
39
|
+
|
|
40
|
+
## Scope Drift Detection
|
|
41
|
+
|
|
42
|
+
If the diff contains changes unrelated to the stated goal:
|
|
43
|
+
- Flag: "These files seem unrelated to the task: [list]"
|
|
44
|
+
- Ask: "Should these be in a separate commit?"
|
|
45
|
+
|
|
46
|
+
## Fix-First Philosophy
|
|
47
|
+
|
|
48
|
+
- Mechanical issues (typos, missing imports, obvious bugs): fix silently
|
|
49
|
+
- Style issues: fix if trivial, note if subjective
|
|
50
|
+
- Architecture decisions: always ask
|
|
51
|
+
|
|
52
|
+
## Output Format
|
|
53
|
+
|
|
54
|
+
```
|
|
55
|
+
## Review Summary
|
|
56
|
+
|
|
57
|
+
### Critical (must fix)
|
|
58
|
+
- [ ] [file:line] Issue description
|
|
59
|
+
|
|
60
|
+
### Informational
|
|
61
|
+
- [file:line] Suggestion
|
|
62
|
+
|
|
63
|
+
### Scope
|
|
64
|
+
- Files changed: N
|
|
65
|
+
- Lines added: N, removed: N
|
|
66
|
+
- Test coverage: [assessed/not assessed]
|
|
67
|
+
```
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: ship
|
|
3
|
+
description: Automated shipping pipeline. Test → Review → Commit → Push → PR. Non-interactive.
|
|
4
|
+
user-invocable: true
|
|
5
|
+
allowed-tools:
|
|
6
|
+
- bash
|
|
7
|
+
- grep
|
|
8
|
+
- read_file
|
|
9
|
+
- write_file
|
|
10
|
+
- search_replace
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
# Ship
|
|
14
|
+
|
|
15
|
+
Automated shipping pipeline. You are a release engineer.
|
|
16
|
+
|
|
17
|
+
## Verification Gate
|
|
18
|
+
|
|
19
|
+
**Never claim completion without fresh test evidence.**
|
|
20
|
+
|
|
21
|
+
## Pipeline
|
|
22
|
+
|
|
23
|
+
### Step 1: Pre-flight checks
|
|
24
|
+
```bash
|
|
25
|
+
git status
|
|
26
|
+
git diff --stat
|
|
27
|
+
```
|
|
28
|
+
- If working tree is dirty, ask what to include
|
|
29
|
+
- If on main/master, ask to create a branch first
|
|
30
|
+
|
|
31
|
+
### Step 2: Run tests
|
|
32
|
+
```bash
|
|
33
|
+
python3 -m pytest tests/ -q --tb=short 2>&1 | tail -20
|
|
34
|
+
```
|
|
35
|
+
- If tests fail: **STOP.** Fix the failures first.
|
|
36
|
+
- If no test runner found, note it and continue.
|
|
37
|
+
|
|
38
|
+
### Step 3: Review diff
|
|
39
|
+
- Run `/review` mentally (check for critical issues)
|
|
40
|
+
- If >5 files changed, confirm with user
|
|
41
|
+
|
|
42
|
+
### Step 4: Commit
|
|
43
|
+
- Write a clear commit message following conventional commits:
|
|
44
|
+
- `feat:` for new features
|
|
45
|
+
- `fix:` for bug fixes
|
|
46
|
+
- `refactor:` for code changes that aren't fixes or features
|
|
47
|
+
- `docs:` for documentation
|
|
48
|
+
- `test:` for test changes
|
|
49
|
+
- Each commit should be bisectable (tests pass at every commit)
|
|
50
|
+
|
|
51
|
+
### Step 5: Push and PR
|
|
52
|
+
```bash
|
|
53
|
+
git push origin HEAD
|
|
54
|
+
```
|
|
55
|
+
- If `gh` CLI is available, create a PR:
|
|
56
|
+
```bash
|
|
57
|
+
gh pr create --title "..." --body "..."
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
## Rules
|
|
61
|
+
|
|
62
|
+
- Never force push to main/master
|
|
63
|
+
- Never skip tests
|
|
64
|
+
- Never commit secrets, tokens, or credentials
|
|
65
|
+
- Always include what changed and why in the commit message
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "drydock-cli"
|
|
3
|
-
version = "0.
|
|
3
|
+
version = "0.8.0"
|
|
4
4
|
description = "Drydock — nautical CLI coding agent"
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
requires-python = ">=3.12"
|
|
@@ -30,6 +30,7 @@ classifiers = [
|
|
|
30
30
|
dependencies = [
|
|
31
31
|
"agent-client-protocol==0.8.1",
|
|
32
32
|
"anyio>=4.12.0",
|
|
33
|
+
"beautifulsoup4>=4.12.0",
|
|
33
34
|
"cachetools>=5.5.0",
|
|
34
35
|
"cryptography>=44.0.0,<=46.0.3",
|
|
35
36
|
"gitpython>=3.1.46",
|
|
@@ -77,6 +78,9 @@ include = ["drydock/"]
|
|
|
77
78
|
[tool.hatch.build.targets.wheel.force-include]
|
|
78
79
|
"drydock/skills/create-presentation" = "drydock/skills/create-presentation"
|
|
79
80
|
"drydock/skills/deep-research" = "drydock/skills/deep-research"
|
|
81
|
+
"drydock/skills/investigate" = "drydock/skills/investigate"
|
|
82
|
+
"drydock/skills/review" = "drydock/skills/review"
|
|
83
|
+
"drydock/skills/ship" = "drydock/skills/ship"
|
|
80
84
|
|
|
81
85
|
|
|
82
86
|
[project.scripts]
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# Backup DryDock project to NAS
|
|
3
|
+
# Cron: 0 3 * * * /data3/drydock/scripts/backup.sh >> /data3/drydock/logs/backup.log 2>&1
|
|
4
|
+
|
|
5
|
+
set -euo pipefail
|
|
6
|
+
|
|
7
|
+
DRYDOCK_SRC="/data3/drydock"
|
|
8
|
+
BENCH_DIR="/data3/swe_bench_runs"
|
|
9
|
+
NAS_MOUNT="/mnt/nas_backups"
|
|
10
|
+
BACKUP_DIR="$NAS_MOUNT/drydock"
|
|
11
|
+
DATE=$(date +%Y%m%d)
|
|
12
|
+
LOGDIR="$DRYDOCK_SRC/logs"
|
|
13
|
+
|
|
14
|
+
mkdir -p "$LOGDIR"
|
|
15
|
+
|
|
16
|
+
log() { echo "[$(date '+%Y-%m-%d %H:%M:%S')] $*"; }
|
|
17
|
+
|
|
18
|
+
# Check NAS is mounted
|
|
19
|
+
if ! mountpoint -q "$NAS_MOUNT" 2>/dev/null; then
|
|
20
|
+
log "NAS not mounted. Attempting mount..."
|
|
21
|
+
sudo mount "$NAS_MOUNT" 2>/dev/null || {
|
|
22
|
+
log "ERROR: Cannot mount NAS at $NAS_MOUNT. Skipping backup."
|
|
23
|
+
exit 1
|
|
24
|
+
}
|
|
25
|
+
fi
|
|
26
|
+
|
|
27
|
+
mkdir -p "$BACKUP_DIR"
|
|
28
|
+
|
|
29
|
+
log "Starting backup..."
|
|
30
|
+
|
|
31
|
+
# Backup 1: DryDock source code (excluding __pycache__, .git objects)
|
|
32
|
+
rsync -rlpt --delete --no-group --no-owner \
|
|
33
|
+
--exclude='__pycache__/' \
|
|
34
|
+
--exclude='.pytest_cache/' \
|
|
35
|
+
--exclude='dist/' \
|
|
36
|
+
--exclude='*.egg-info/' \
|
|
37
|
+
--exclude='.git/objects/' \
|
|
38
|
+
--exclude='logs/' \
|
|
39
|
+
"$DRYDOCK_SRC/" "$BACKUP_DIR/source/"
|
|
40
|
+
|
|
41
|
+
log "Source backed up."
|
|
42
|
+
|
|
43
|
+
# Backup 2: SWE-bench results and state (not the repos — too large)
|
|
44
|
+
rsync -rlpt --delete --no-group --no-owner \
|
|
45
|
+
--exclude='repos/' \
|
|
46
|
+
--exclude='tasks/*/repo/' \
|
|
47
|
+
--exclude='__pycache__/' \
|
|
48
|
+
"$BENCH_DIR/continuous_bench_state.json" \
|
|
49
|
+
"$BENCH_DIR/auto_improve_state.json" \
|
|
50
|
+
"$BENCH_DIR/harness.py" \
|
|
51
|
+
"$BENCH_DIR/continuous_bench.sh" \
|
|
52
|
+
"$BENCH_DIR/analyze_batch.py" \
|
|
53
|
+
"$BACKUP_DIR/bench/" 2>/dev/null || true
|
|
54
|
+
|
|
55
|
+
# Backup results directories (small — just JSON)
|
|
56
|
+
rsync -rlpt --no-group --no-owner \
|
|
57
|
+
--include='*/' \
|
|
58
|
+
--include='results.json' \
|
|
59
|
+
--exclude='*' \
|
|
60
|
+
"$BENCH_DIR/results/" "$BACKUP_DIR/bench/results/" 2>/dev/null || true
|
|
61
|
+
|
|
62
|
+
log "Bench state backed up."
|
|
63
|
+
|
|
64
|
+
# Backup 3: Config files
|
|
65
|
+
mkdir -p "$BACKUP_DIR/config/drydock_config" "$BACKUP_DIR/config/drydock_home"
|
|
66
|
+
rsync -rlpt --no-group --no-owner "$HOME/.config/drydock/" "$BACKUP_DIR/config/drydock_config/" 2>/dev/null || true
|
|
67
|
+
rsync -rlpt --no-group --no-owner --exclude='logs/' "$HOME/.drydock/" "$BACKUP_DIR/config/drydock_home/" 2>/dev/null || true
|
|
68
|
+
|
|
69
|
+
log "Config backed up."
|
|
70
|
+
|
|
71
|
+
# Backup 4: Crontab
|
|
72
|
+
crontab -l > "$BACKUP_DIR/crontab_$(hostname).txt" 2>/dev/null || true
|
|
73
|
+
|
|
74
|
+
# Write backup manifest
|
|
75
|
+
cat > "$BACKUP_DIR/MANIFEST.txt" << EOF
|
|
76
|
+
DryDock Backup
|
|
77
|
+
Date: $(date)
|
|
78
|
+
Host: $(hostname)
|
|
79
|
+
Source: $DRYDOCK_SRC
|
|
80
|
+
Bench: $BENCH_DIR
|
|
81
|
+
Version: $(python3 -c "import sys; sys.path.insert(0,'$DRYDOCK_SRC'); from drydock import __version__; print(__version__)" 2>/dev/null || echo "unknown")
|
|
82
|
+
EOF
|
|
83
|
+
|
|
84
|
+
log "Backup complete to $BACKUP_DIR"
|