drydock-cli 0.7.4__tar.gz → 0.8.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (467) hide show
  1. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/PKG-INFO +2 -1
  2. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/drydock/cli/cli.py +1 -1
  3. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/drydock/cli/textual_ui/external_editor.py +1 -1
  4. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/drydock/core/agent_loop.py +50 -8
  5. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/drydock/core/auth/github.py +1 -1
  6. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/drydock/core/config/_settings.py +1 -1
  7. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/drydock/core/logger.py +1 -1
  8. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/drydock/core/programmatic.py +1 -1
  9. drydock_cli-0.8.1/drydock/core/tools/builtins/websearch.py +133 -0
  10. drydock_cli-0.8.1/drydock/skills/investigate/SKILL.md +67 -0
  11. drydock_cli-0.8.1/drydock/skills/review/SKILL.md +67 -0
  12. drydock_cli-0.8.1/drydock/skills/ship/SKILL.md +65 -0
  13. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/pyproject.toml +5 -1
  14. drydock_cli-0.8.1/tests/test_current_bugs.py +150 -0
  15. drydock_cli-0.7.4/drydock/core/tools/builtins/websearch.py +0 -158
  16. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/.github/CODEOWNERS +0 -0
  17. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/.github/DISCUSSION_TEMPLATE/ideas.yml +0 -0
  18. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/.github/ISSUE_TEMPLATE/bug-report.yml +0 -0
  19. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/.github/ISSUE_TEMPLATE/config.yml +0 -0
  20. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/.github/workflows/build-and-upload.yml +0 -0
  21. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/.github/workflows/ci.yml +0 -0
  22. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/.github/workflows/issue-labeler.yml +0 -0
  23. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/.github/workflows/release.yml +0 -0
  24. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/.gitignore +0 -0
  25. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/.pre-commit-config.yaml +0 -0
  26. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/.python-version +0 -0
  27. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/.typos.toml +0 -0
  28. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/.vscode/extensions.json +0 -0
  29. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/.vscode/launch.json +0 -0
  30. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/.vscode/settings.json +0 -0
  31. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/AGENTS.md +0 -0
  32. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/CHANGELOG.md +0 -0
  33. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/CLAUDE.md +0 -0
  34. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/CONTRIBUTING.md +0 -0
  35. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/Drydock_rebrand.md +0 -0
  36. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/LICENSE +0 -0
  37. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/NOTICE +0 -0
  38. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/PRD.md +0 -0
  39. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/README.md +0 -0
  40. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/action.yml +0 -0
  41. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/distribution/zed/LICENSE +0 -0
  42. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/distribution/zed/extension.toml +0 -0
  43. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/distribution/zed/icons/mistral_vibe.svg +0 -0
  44. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/docs/README.md +0 -0
  45. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/docs/acp-setup.md +0 -0
  46. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/docs/proxy-setup.md +0 -0
  47. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/drydock/__init__.py +0 -0
  48. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/drydock/acp/__init__.py +0 -0
  49. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/drydock/acp/acp_agent_loop.py +0 -0
  50. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/drydock/acp/acp_logger.py +0 -0
  51. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/drydock/acp/entrypoint.py +0 -0
  52. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/drydock/acp/tools/__init__.py +0 -0
  53. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/drydock/acp/tools/base.py +0 -0
  54. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/drydock/acp/tools/builtins/bash.py +0 -0
  55. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/drydock/acp/tools/builtins/read_file.py +0 -0
  56. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/drydock/acp/tools/builtins/search_replace.py +0 -0
  57. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/drydock/acp/tools/builtins/todo.py +0 -0
  58. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/drydock/acp/tools/builtins/write_file.py +0 -0
  59. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/drydock/acp/tools/session_update.py +0 -0
  60. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/drydock/acp/utils.py +0 -0
  61. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/drydock/cli/__init__.py +0 -0
  62. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/drydock/cli/autocompletion/__init__.py +0 -0
  63. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/drydock/cli/autocompletion/base.py +0 -0
  64. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/drydock/cli/autocompletion/path_completion.py +0 -0
  65. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/drydock/cli/autocompletion/slash_command.py +0 -0
  66. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/drydock/cli/clipboard.py +0 -0
  67. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/drydock/cli/commands.py +0 -0
  68. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/drydock/cli/entrypoint.py +0 -0
  69. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/drydock/cli/history_manager.py +0 -0
  70. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/drydock/cli/plan_offer/adapters/http_whoami_gateway.py +0 -0
  71. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/drydock/cli/plan_offer/decide_plan_offer.py +0 -0
  72. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/drydock/cli/plan_offer/ports/whoami_gateway.py +0 -0
  73. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/drydock/cli/terminal_setup.py +0 -0
  74. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/drydock/cli/textual_ui/__init__.py +0 -0
  75. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/drydock/cli/textual_ui/ansi_markdown.py +0 -0
  76. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/drydock/cli/textual_ui/app.py +0 -0
  77. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/drydock/cli/textual_ui/app.tcss +0 -0
  78. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/drydock/cli/textual_ui/handlers/__init__.py +0 -0
  79. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/drydock/cli/textual_ui/handlers/event_handler.py +0 -0
  80. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/drydock/cli/textual_ui/notifications/__init__.py +0 -0
  81. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/drydock/cli/textual_ui/notifications/adapters/__init__.py +0 -0
  82. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/drydock/cli/textual_ui/notifications/adapters/textual_notification_adapter.py +0 -0
  83. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/drydock/cli/textual_ui/notifications/ports/__init__.py +0 -0
  84. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/drydock/cli/textual_ui/notifications/ports/notification_port.py +0 -0
  85. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/drydock/cli/textual_ui/widgets/__init__.py +0 -0
  86. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/drydock/cli/textual_ui/widgets/approval_app.py +0 -0
  87. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/drydock/cli/textual_ui/widgets/banner/banner.py +0 -0
  88. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/drydock/cli/textual_ui/widgets/banner/petit_chat.py +0 -0
  89. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/drydock/cli/textual_ui/widgets/braille_renderer.py +0 -0
  90. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/drydock/cli/textual_ui/widgets/chat_input/__init__.py +0 -0
  91. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/drydock/cli/textual_ui/widgets/chat_input/body.py +0 -0
  92. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/drydock/cli/textual_ui/widgets/chat_input/completion_manager.py +0 -0
  93. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/drydock/cli/textual_ui/widgets/chat_input/completion_popup.py +0 -0
  94. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/drydock/cli/textual_ui/widgets/chat_input/container.py +0 -0
  95. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/drydock/cli/textual_ui/widgets/chat_input/text_area.py +0 -0
  96. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/drydock/cli/textual_ui/widgets/compact.py +0 -0
  97. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/drydock/cli/textual_ui/widgets/config_app.py +0 -0
  98. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/drydock/cli/textual_ui/widgets/context_progress.py +0 -0
  99. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/drydock/cli/textual_ui/widgets/load_more.py +0 -0
  100. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/drydock/cli/textual_ui/widgets/loading.py +0 -0
  101. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/drydock/cli/textual_ui/widgets/messages.py +0 -0
  102. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/drydock/cli/textual_ui/widgets/no_markup_static.py +0 -0
  103. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/drydock/cli/textual_ui/widgets/path_display.py +0 -0
  104. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/drydock/cli/textual_ui/widgets/proxy_setup_app.py +0 -0
  105. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/drydock/cli/textual_ui/widgets/question_app.py +0 -0
  106. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/drydock/cli/textual_ui/widgets/session_picker.py +0 -0
  107. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/drydock/cli/textual_ui/widgets/spinner.py +0 -0
  108. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/drydock/cli/textual_ui/widgets/status_message.py +0 -0
  109. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/drydock/cli/textual_ui/widgets/teleport_message.py +0 -0
  110. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/drydock/cli/textual_ui/widgets/tool_widgets.py +0 -0
  111. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/drydock/cli/textual_ui/widgets/tools.py +0 -0
  112. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/drydock/cli/textual_ui/widgets/vscode_compat.py +0 -0
  113. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/drydock/cli/textual_ui/windowing/__init__.py +0 -0
  114. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/drydock/cli/textual_ui/windowing/history.py +0 -0
  115. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/drydock/cli/textual_ui/windowing/history_windowing.py +0 -0
  116. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/drydock/cli/textual_ui/windowing/state.py +0 -0
  117. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/drydock/cli/update_notifier/__init__.py +0 -0
  118. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/drydock/cli/update_notifier/adapters/filesystem_update_cache_repository.py +0 -0
  119. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/drydock/cli/update_notifier/adapters/github_update_gateway.py +0 -0
  120. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/drydock/cli/update_notifier/adapters/pypi_update_gateway.py +0 -0
  121. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/drydock/cli/update_notifier/ports/update_cache_repository.py +0 -0
  122. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/drydock/cli/update_notifier/ports/update_gateway.py +0 -0
  123. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/drydock/cli/update_notifier/update.py +0 -0
  124. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/drydock/cli/update_notifier/whats_new.py +0 -0
  125. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/drydock/core/__init__.py +0 -0
  126. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/drydock/core/agents/__init__.py +0 -0
  127. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/drydock/core/agents/manager.py +0 -0
  128. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/drydock/core/agents/models.py +0 -0
  129. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/drydock/core/auth/__init__.py +0 -0
  130. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/drydock/core/auth/crypto.py +0 -0
  131. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/drydock/core/autocompletion/__init__.py +0 -0
  132. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/drydock/core/autocompletion/completers.py +0 -0
  133. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/drydock/core/autocompletion/file_indexer/__init__.py +0 -0
  134. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/drydock/core/autocompletion/file_indexer/ignore_rules.py +0 -0
  135. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/drydock/core/autocompletion/file_indexer/indexer.py +0 -0
  136. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/drydock/core/autocompletion/file_indexer/store.py +0 -0
  137. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/drydock/core/autocompletion/file_indexer/watcher.py +0 -0
  138. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/drydock/core/autocompletion/fuzzy.py +0 -0
  139. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/drydock/core/autocompletion/path_prompt.py +0 -0
  140. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/drydock/core/autocompletion/path_prompt_adapter.py +0 -0
  141. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/drydock/core/config/__init__.py +0 -0
  142. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/drydock/core/config/harness_files/__init__.py +0 -0
  143. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/drydock/core/config/harness_files/_harness_manager.py +0 -0
  144. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/drydock/core/config/harness_files/_paths.py +0 -0
  145. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/drydock/core/consultant.py +0 -0
  146. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/drydock/core/drydock_states.py +0 -0
  147. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/drydock/core/llm/__init__.py +0 -0
  148. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/drydock/core/llm/backend/anthropic.py +0 -0
  149. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/drydock/core/llm/backend/base.py +0 -0
  150. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/drydock/core/llm/backend/factory.py +0 -0
  151. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/drydock/core/llm/backend/generic.py +0 -0
  152. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/drydock/core/llm/backend/mistral.py +0 -0
  153. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/drydock/core/llm/backend/reasoning_adapter.py +0 -0
  154. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/drydock/core/llm/backend/vertex.py +0 -0
  155. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/drydock/core/llm/exceptions.py +0 -0
  156. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/drydock/core/llm/format.py +0 -0
  157. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/drydock/core/llm/message_utils.py +0 -0
  158. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/drydock/core/llm/types.py +0 -0
  159. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/drydock/core/middleware.py +0 -0
  160. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/drydock/core/output_formatters.py +0 -0
  161. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/drydock/core/paths/__init__.py +0 -0
  162. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/drydock/core/paths/_local_config_walk.py +0 -0
  163. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/drydock/core/paths/_vibe_home.py +0 -0
  164. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/drydock/core/paths/conventions.py +0 -0
  165. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/drydock/core/plan_session.py +0 -0
  166. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/drydock/core/prompts/__init__.py +0 -0
  167. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/drydock/core/prompts/cli.md +0 -0
  168. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/drydock/core/prompts/compact.md +0 -0
  169. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/drydock/core/prompts/dangerous_directory.md +0 -0
  170. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/drydock/core/prompts/diagnostic.md +0 -0
  171. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/drydock/core/prompts/explore.md +0 -0
  172. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/drydock/core/prompts/planner.md +0 -0
  173. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/drydock/core/prompts/project_context.md +0 -0
  174. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/drydock/core/prompts/tests.md +0 -0
  175. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/drydock/core/proxy_setup.py +0 -0
  176. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/drydock/core/session/session_loader.py +0 -0
  177. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/drydock/core/session/session_logger.py +0 -0
  178. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/drydock/core/session/session_migration.py +0 -0
  179. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/drydock/core/session/state_file.py +0 -0
  180. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/drydock/core/skills/__init__.py +0 -0
  181. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/drydock/core/skills/manager.py +0 -0
  182. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/drydock/core/skills/models.py +0 -0
  183. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/drydock/core/skills/parser.py +0 -0
  184. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/drydock/core/slug.py +0 -0
  185. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/drydock/core/system_prompt.py +0 -0
  186. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/drydock/core/telemetry/__init__.py +0 -0
  187. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/drydock/core/telemetry/send.py +0 -0
  188. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/drydock/core/teleport/errors.py +0 -0
  189. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/drydock/core/teleport/git.py +0 -0
  190. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/drydock/core/teleport/nuage.py +0 -0
  191. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/drydock/core/teleport/teleport.py +0 -0
  192. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/drydock/core/teleport/types.py +0 -0
  193. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/drydock/core/tools/base.py +0 -0
  194. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/drydock/core/tools/builtins/ask_user_question.py +0 -0
  195. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/drydock/core/tools/builtins/bash.py +0 -0
  196. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/drydock/core/tools/builtins/exit_plan_mode.py +0 -0
  197. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/drydock/core/tools/builtins/grep.py +0 -0
  198. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/drydock/core/tools/builtins/prompts/__init__.py +0 -0
  199. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/drydock/core/tools/builtins/prompts/ask_user_question.md +0 -0
  200. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/drydock/core/tools/builtins/prompts/bash.md +0 -0
  201. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/drydock/core/tools/builtins/prompts/grep.md +0 -0
  202. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/drydock/core/tools/builtins/prompts/read_file.md +0 -0
  203. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/drydock/core/tools/builtins/prompts/search_replace.md +0 -0
  204. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/drydock/core/tools/builtins/prompts/swe_bench.md +0 -0
  205. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/drydock/core/tools/builtins/prompts/task.md +0 -0
  206. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/drydock/core/tools/builtins/prompts/todo.md +0 -0
  207. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/drydock/core/tools/builtins/prompts/webfetch.md +0 -0
  208. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/drydock/core/tools/builtins/prompts/websearch.md +0 -0
  209. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/drydock/core/tools/builtins/prompts/write_file.md +0 -0
  210. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/drydock/core/tools/builtins/read_file.py +0 -0
  211. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/drydock/core/tools/builtins/search_replace.py +0 -0
  212. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/drydock/core/tools/builtins/task.py +0 -0
  213. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/drydock/core/tools/builtins/todo.py +0 -0
  214. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/drydock/core/tools/builtins/webfetch.py +0 -0
  215. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/drydock/core/tools/builtins/write_file.py +0 -0
  216. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/drydock/core/tools/injection_guard.py +0 -0
  217. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/drydock/core/tools/manager.py +0 -0
  218. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/drydock/core/tools/mcp/__init__.py +0 -0
  219. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/drydock/core/tools/mcp/registry.py +0 -0
  220. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/drydock/core/tools/mcp/tools.py +0 -0
  221. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/drydock/core/tools/mcp_sampling.py +0 -0
  222. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/drydock/core/tools/ui.py +0 -0
  223. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/drydock/core/tools/utils.py +0 -0
  224. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/drydock/core/trusted_folders.py +0 -0
  225. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/drydock/core/types.py +0 -0
  226. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/drydock/core/utils.py +0 -0
  227. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/drydock/setup/onboarding/__init__.py +0 -0
  228. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/drydock/setup/onboarding/base.py +0 -0
  229. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/drydock/setup/onboarding/onboarding.tcss +0 -0
  230. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/drydock/setup/onboarding/screens/__init__.py +0 -0
  231. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/drydock/setup/onboarding/screens/api_key.py +0 -0
  232. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/drydock/setup/onboarding/screens/welcome.py +0 -0
  233. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/drydock/setup/trusted_folders/trust_folder_dialog.py +0 -0
  234. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/drydock/setup/trusted_folders/trust_folder_dialog.tcss +0 -0
  235. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/drydock/skills/__init__.py +0 -0
  236. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/drydock/skills/create-presentation/SKILL.md +0 -0
  237. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/drydock/skills/deep-research/SKILL.md +0 -0
  238. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/drydock/whats_new.md +0 -0
  239. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/drydock-acp.spec +0 -0
  240. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/drydock_terms.md +0 -0
  241. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/flake.lock +0 -0
  242. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/flake.nix +0 -0
  243. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/scripts/README.md +0 -0
  244. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/scripts/backup.sh +0 -0
  245. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/scripts/bump_version.py +0 -0
  246. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/scripts/deploy_to_github.sh +0 -0
  247. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/scripts/install.sh +0 -0
  248. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/scripts/prepare_release.py +0 -0
  249. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/scripts/publish_to_pypi.sh +0 -0
  250. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/tests/__init__.py +0 -0
  251. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/tests/acp/conftest.py +0 -0
  252. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/tests/acp/test_acp.py +0 -0
  253. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/tests/acp/test_agent_thought.py +0 -0
  254. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/tests/acp/test_bash.py +0 -0
  255. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/tests/acp/test_compact_session_updates.py +0 -0
  256. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/tests/acp/test_content.py +0 -0
  257. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/tests/acp/test_initialize.py +0 -0
  258. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/tests/acp/test_list_sessions.py +0 -0
  259. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/tests/acp/test_load_session.py +0 -0
  260. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/tests/acp/test_multi_session.py +0 -0
  261. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/tests/acp/test_new_session.py +0 -0
  262. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/tests/acp/test_proxy_setup_acp.py +0 -0
  263. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/tests/acp/test_read_file.py +0 -0
  264. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/tests/acp/test_search_replace.py +0 -0
  265. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/tests/acp/test_set_config_option.py +0 -0
  266. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/tests/acp/test_set_mode.py +0 -0
  267. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/tests/acp/test_set_model.py +0 -0
  268. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/tests/acp/test_tool_call_session_update.py +0 -0
  269. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/tests/acp/test_utils.py +0 -0
  270. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/tests/acp/test_write_file.py +0 -0
  271. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/tests/autocompletion/test_file_indexer.py +0 -0
  272. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/tests/autocompletion/test_fuzzy.py +0 -0
  273. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/tests/autocompletion/test_path_completer_fuzzy.py +0 -0
  274. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/tests/autocompletion/test_path_completer_recursive.py +0 -0
  275. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/tests/autocompletion/test_path_completion_controller.py +0 -0
  276. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/tests/autocompletion/test_path_prompt_transformer.py +0 -0
  277. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/tests/autocompletion/test_slash_command_controller.py +0 -0
  278. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/tests/autocompletion/test_ui_chat_autocompletion.py +0 -0
  279. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/tests/backend/__init__.py +0 -0
  280. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/tests/backend/data/__init__.py +0 -0
  281. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/tests/backend/data/fireworks.py +0 -0
  282. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/tests/backend/data/mistral.py +0 -0
  283. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/tests/backend/test_anthropic_adapter.py +0 -0
  284. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/tests/backend/test_backend.py +0 -0
  285. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/tests/backend/test_reasoning_adapter.py +0 -0
  286. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/tests/backend/test_vertex_anthropic_adapter.py +0 -0
  287. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/tests/cli/plan_offer/adapters/fake_whoami_gateway.py +0 -0
  288. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/tests/cli/plan_offer/test_decide_plan_offer.py +0 -0
  289. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/tests/cli/plan_offer/test_http_whoami_gateway.py +0 -0
  290. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/tests/cli/test_bell_notifications.py +0 -0
  291. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/tests/cli/test_braille_renderer.py +0 -0
  292. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/tests/cli/test_clipboard.py +0 -0
  293. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/tests/cli/test_commands.py +0 -0
  294. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/tests/cli/test_copy_shortcuts.py +0 -0
  295. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/tests/cli/test_external_editor.py +0 -0
  296. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/tests/cli/test_no_markup_static.py +0 -0
  297. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/tests/cli/test_question_app.py +0 -0
  298. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/tests/cli/test_spinner.py +0 -0
  299. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/tests/cli/test_switching_mode.py +0 -0
  300. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/tests/cli/test_ui_clipboard_notifications.py +0 -0
  301. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/tests/cli/test_ui_session_incremental_renderer.py +0 -0
  302. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/tests/cli/test_ui_session_resume.py +0 -0
  303. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/tests/cli/test_ui_skill_dispatch.py +0 -0
  304. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/tests/cli/textual_ui/__init__.py +0 -0
  305. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/tests/cli/textual_ui/test_session_picker.py +0 -0
  306. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/tests/conftest.py +0 -0
  307. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/tests/core/test_agents.py +0 -0
  308. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/tests/core/test_auth_crypto.py +0 -0
  309. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/tests/core/test_auth_github.py +0 -0
  310. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/tests/core/test_config_load_dotenv.py +0 -0
  311. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/tests/core/test_config_paths.py +0 -0
  312. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/tests/core/test_config_resolution.py +0 -0
  313. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/tests/core/test_file_logging.py +0 -0
  314. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/tests/core/test_plan_session.py +0 -0
  315. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/tests/core/test_proxy_setup.py +0 -0
  316. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/tests/core/test_slug.py +0 -0
  317. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/tests/core/test_telemetry_send.py +0 -0
  318. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/tests/core/test_teleport_git.py +0 -0
  319. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/tests/core/test_teleport_nuage.py +0 -0
  320. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/tests/core/test_teleport_service.py +0 -0
  321. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/tests/core/test_trusted_folders.py +0 -0
  322. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/tests/core/test_utils.py +0 -0
  323. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/tests/e2e/common.py +0 -0
  324. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/tests/e2e/conftest.py +0 -0
  325. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/tests/e2e/mock_server.py +0 -0
  326. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/tests/e2e/test_cli_tui_onboarding.py +0 -0
  327. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/tests/e2e/test_cli_tui_streaming.py +0 -0
  328. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/tests/e2e/test_cli_tui_tool_approval.py +0 -0
  329. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/tests/mock/__init__.py +0 -0
  330. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/tests/mock/mock_backend_factory.py +0 -0
  331. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/tests/mock/mock_entrypoint.py +0 -0
  332. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/tests/mock/utils.py +0 -0
  333. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/tests/onboarding/test_run_onboarding.py +0 -0
  334. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/tests/onboarding/test_ui_onboarding.py +0 -0
  335. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/tests/session/test_session_loader.py +0 -0
  336. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/tests/session/test_session_logger.py +0 -0
  337. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/tests/session/test_session_migration.py +0 -0
  338. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/tests/skills/conftest.py +0 -0
  339. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/tests/skills/test_manager.py +0 -0
  340. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/tests/skills/test_models.py +0 -0
  341. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/tests/skills/test_parser.py +0 -0
  342. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/tests/snapshots/__snapshots__/test_ui_snapshot_ask_user_question/test_snapshot_ask_user_question_collapsed.svg +0 -0
  343. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/tests/snapshots/__snapshots__/test_ui_snapshot_ask_user_question/test_snapshot_ask_user_question_expanded.svg +0 -0
  344. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/tests/snapshots/__snapshots__/test_ui_snapshot_basic_conversation/test_snapshot_shows_basic_conversation.svg +0 -0
  345. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/tests/snapshots/__snapshots__/test_ui_snapshot_code_block_horizontal_scrolling/test_snapshot_allows_horizontal_scrolling_for_long_code_blocks.svg +0 -0
  346. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/tests/snapshots/__snapshots__/test_ui_snapshot_empty_assistant_before_reasoning/test_snapshot_empty_assistant_removed_when_reasoning_starts.svg +0 -0
  347. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/tests/snapshots/__snapshots__/test_ui_snapshot_modes/test_snapshot_cycle_to_accept_edits_mode.svg +0 -0
  348. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/tests/snapshots/__snapshots__/test_ui_snapshot_modes/test_snapshot_cycle_to_auto_approve_mode.svg +0 -0
  349. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/tests/snapshots/__snapshots__/test_ui_snapshot_modes/test_snapshot_cycle_to_plan_mode.svg +0 -0
  350. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/tests/snapshots/__snapshots__/test_ui_snapshot_modes/test_snapshot_cycle_wraps_to_default.svg +0 -0
  351. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/tests/snapshots/__snapshots__/test_ui_snapshot_modes/test_snapshot_default_mode.svg +0 -0
  352. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/tests/snapshots/__snapshots__/test_ui_snapshot_parallel_tool_calls/test_snapshot_parallel_tool_calls_pending.svg +0 -0
  353. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/tests/snapshots/__snapshots__/test_ui_snapshot_parallel_tool_calls/test_snapshot_parallel_tool_calls_resolved.svg +0 -0
  354. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/tests/snapshots/__snapshots__/test_ui_snapshot_proxy_setup/test_snapshot_proxy_setup_cancel_discards_changes.svg +0 -0
  355. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/tests/snapshots/__snapshots__/test_ui_snapshot_proxy_setup/test_snapshot_proxy_setup_edit_existing_values.svg +0 -0
  356. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/tests/snapshots/__snapshots__/test_ui_snapshot_proxy_setup/test_snapshot_proxy_setup_initial_empty.svg +0 -0
  357. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/tests/snapshots/__snapshots__/test_ui_snapshot_proxy_setup/test_snapshot_proxy_setup_initial_with_values.svg +0 -0
  358. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/tests/snapshots/__snapshots__/test_ui_snapshot_proxy_setup/test_snapshot_proxy_setup_save_error.svg +0 -0
  359. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/tests/snapshots/__snapshots__/test_ui_snapshot_proxy_setup/test_snapshot_proxy_setup_save_new_values.svg +0 -0
  360. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_question_answer_first_advance.svg +0 -0
  361. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_question_first_answered_checkmark.svg +0 -0
  362. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_question_initial.svg +0 -0
  363. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_question_navigate_left_wraps.svg +0 -0
  364. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_question_navigate_right.svg +0 -0
  365. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_question_tab_to_second.svg +0 -0
  366. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_select_initial.svg +0 -0
  367. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_select_mixed_selection.svg +0 -0
  368. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_select_navigate_to_submit.svg +0 -0
  369. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_select_other_with_text.svg +0 -0
  370. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_select_toggle_first.svg +0 -0
  371. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_select_toggle_multiple.svg +0 -0
  372. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_select_untoggle.svg +0 -0
  373. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_question_app_initial.svg +0 -0
  374. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_question_app_navigate_down.svg +0 -0
  375. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_question_app_navigate_to_other.svg +0 -0
  376. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_question_app_navigate_to_third_option.svg +0 -0
  377. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_question_app_navigate_up_wraps.svg +0 -0
  378. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_question_app_other_typing.svg +0 -0
  379. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/tests/snapshots/__snapshots__/test_ui_snapshot_reasoning_content/test_snapshot_buffered_reasoning_yields_before_content.svg +0 -0
  380. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/tests/snapshots/__snapshots__/test_ui_snapshot_reasoning_content/test_snapshot_shows_interleaved_reasoning.svg +0 -0
  381. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/tests/snapshots/__snapshots__/test_ui_snapshot_reasoning_content/test_snapshot_shows_reasoning_content.svg +0 -0
  382. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/tests/snapshots/__snapshots__/test_ui_snapshot_reasoning_content/test_snapshot_shows_reasoning_content_expanded.svg +0 -0
  383. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/tests/snapshots/__snapshots__/test_ui_snapshot_release_update_notification/test_snapshot_shows_release_update_notification.svg +0 -0
  384. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/tests/snapshots/__snapshots__/test_ui_snapshot_session_resume/test_snapshot_shows_resumed_session_messages.svg +0 -0
  385. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/tests/snapshots/__snapshots__/test_ui_snapshot_streaming_tool_call/test_snapshot_tool_call_partial.svg +0 -0
  386. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/tests/snapshots/__snapshots__/test_ui_snapshot_streaming_tool_call/test_snapshot_tool_call_updated.svg +0 -0
  387. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_push_confirmation_cancel_selected.svg +0 -0
  388. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_push_confirmation_multiple_commits.svg +0 -0
  389. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_push_confirmation_single_commit.svg +0 -0
  390. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_status_auth_complete.svg +0 -0
  391. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_status_auth_required.svg +0 -0
  392. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_status_checking_git.svg +0 -0
  393. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_status_complete.svg +0 -0
  394. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_status_error.svg +0 -0
  395. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_status_pushing.svg +0 -0
  396. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_status_sending_token.svg +0 -0
  397. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_status_starting_workflow.svg +0 -0
  398. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/tests/snapshots/__snapshots__/test_ui_snapshot_whats_new/test_snapshot_shows_no_plan_message.svg +0 -0
  399. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/tests/snapshots/__snapshots__/test_ui_snapshot_whats_new/test_snapshot_shows_switch_message.svg +0 -0
  400. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/tests/snapshots/__snapshots__/test_ui_snapshot_whats_new/test_snapshot_shows_upgrade_message.svg +0 -0
  401. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/tests/snapshots/__snapshots__/test_ui_snapshot_whats_new/test_snapshot_shows_whats_new_message.svg +0 -0
  402. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/tests/snapshots/base_snapshot_test_app.py +0 -0
  403. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/tests/snapshots/conftest.py +0 -0
  404. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/tests/snapshots/snap_compare.py +0 -0
  405. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/tests/snapshots/test_ui_snapshot_ask_user_question.py +0 -0
  406. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/tests/snapshots/test_ui_snapshot_basic_conversation.py +0 -0
  407. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/tests/snapshots/test_ui_snapshot_code_block_horizontal_scrolling.py +0 -0
  408. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/tests/snapshots/test_ui_snapshot_empty_assistant_before_reasoning.py +0 -0
  409. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/tests/snapshots/test_ui_snapshot_modes.py +0 -0
  410. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/tests/snapshots/test_ui_snapshot_parallel_tool_calls.py +0 -0
  411. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/tests/snapshots/test_ui_snapshot_proxy_setup.py +0 -0
  412. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/tests/snapshots/test_ui_snapshot_question_app.py +0 -0
  413. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/tests/snapshots/test_ui_snapshot_reasoning_content.py +0 -0
  414. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/tests/snapshots/test_ui_snapshot_release_update_notification.py +0 -0
  415. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/tests/snapshots/test_ui_snapshot_session_resume.py +0 -0
  416. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/tests/snapshots/test_ui_snapshot_streaming_tool_call.py +0 -0
  417. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/tests/snapshots/test_ui_snapshot_teleport.py +0 -0
  418. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/tests/snapshots/test_ui_snapshot_whats_new.py +0 -0
  419. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/tests/stubs/fake_backend.py +0 -0
  420. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/tests/stubs/fake_client.py +0 -0
  421. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/tests/stubs/fake_tool.py +0 -0
  422. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/tests/test_agent_auto_compact.py +0 -0
  423. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/tests/test_agent_backend.py +0 -0
  424. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/tests/test_agent_observer_streaming.py +0 -0
  425. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/tests/test_agent_stats.py +0 -0
  426. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/tests/test_agent_tasks.py +0 -0
  427. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/tests/test_agent_tool_call.py +0 -0
  428. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/tests/test_agents.py +0 -0
  429. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/tests/test_cli_programmatic_preload.py +0 -0
  430. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/tests/test_drydock_regression.py +0 -0
  431. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/tests/test_drydock_tasks.py +0 -0
  432. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/tests/test_history_manager.py +0 -0
  433. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/tests/test_integration.py +0 -0
  434. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/tests/test_loop_detection.py +0 -0
  435. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/tests/test_message_id.py +0 -0
  436. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/tests/test_message_merging.py +0 -0
  437. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/tests/test_middleware.py +0 -0
  438. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/tests/test_real_failures.py +0 -0
  439. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/tests/test_real_issues.py +0 -0
  440. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/tests/test_reasoning_content.py +0 -0
  441. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/tests/test_system_prompt.py +0 -0
  442. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/tests/test_tagged_text.py +0 -0
  443. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/tests/test_ui_external_editor.py +0 -0
  444. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/tests/test_ui_input_history.py +0 -0
  445. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/tests/test_user_issues.py +0 -0
  446. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/tests/tools/test_ask_user_question.py +0 -0
  447. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/tests/tools/test_bash.py +0 -0
  448. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/tests/tools/test_exit_plan_mode.py +0 -0
  449. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/tests/tools/test_grep.py +0 -0
  450. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/tests/tools/test_invoke_context.py +0 -0
  451. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/tests/tools/test_manager_get_tool_config.py +0 -0
  452. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/tests/tools/test_mcp.py +0 -0
  453. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/tests/tools/test_mcp_sampling.py +0 -0
  454. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/tests/tools/test_task.py +0 -0
  455. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/tests/tools/test_ui_bash_execution.py +0 -0
  456. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/tests/tools/test_webfetch.py +0 -0
  457. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/tests/tools/test_websearch.py +0 -0
  458. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/tests/update_notifier/adapters/fake_update_cache_repository.py +0 -0
  459. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/tests/update_notifier/adapters/fake_update_gateway.py +0 -0
  460. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/tests/update_notifier/test_do_update.py +0 -0
  461. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/tests/update_notifier/test_filesystem_update_cache_repository.py +0 -0
  462. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/tests/update_notifier/test_github_update_gateway.py +0 -0
  463. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/tests/update_notifier/test_pypi_update_gateway.py +0 -0
  464. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/tests/update_notifier/test_ui_update_notification.py +0 -0
  465. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/tests/update_notifier/test_update_use_case.py +0 -0
  466. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/tests/update_notifier/test_whats_new.py +0 -0
  467. {drydock_cli-0.7.4 → drydock_cli-0.8.1}/uv.lock +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: drydock-cli
3
- Version: 0.7.4
3
+ Version: 0.8.1
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="vibe_cli",
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="vibe_")
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
@@ -549,8 +550,28 @@ class AgentLoop:
549
550
  if not tc.function:
550
551
  continue
551
552
  if tc.function.name in ("search_replace", "write_file"):
553
+ first_edit = not has_made_edit
552
554
  has_made_edit = True
553
555
  bash_count = 0 # Reset on successful edit
556
+ # Track blast radius
557
+ try:
558
+ edit_args = json.loads(tc.function.arguments or "{}")
559
+ edit_path = edit_args.get("file_path", edit_args.get("path", ""))
560
+ if edit_path and edit_path not in files_modified:
561
+ files_modified.append(edit_path)
562
+ except (json.JSONDecodeError, AttributeError):
563
+ edit_path = ""
564
+
565
+ # After first edit: prompt to check related files
566
+ if first_edit and edit_path:
567
+ self._inject_system_note(
568
+ f"Good — you edited {edit_path}. Now check: "
569
+ f"does this bug have a RELATED file that also needs changes? "
570
+ f"Common patterns: if you edited a model, check the serializer/migration. "
571
+ f"If you edited a base class, check subclasses. "
572
+ f"If you edited a util, check callers. "
573
+ f"Use grep to search for imports of the function/class you changed."
574
+ )
554
575
  if tc.function.name == "read_file":
555
576
  try:
556
577
  args = json.loads(tc.function.arguments or "{}")
@@ -569,6 +590,15 @@ class AgentLoop:
569
590
  if "search_replace" in content.lower() and "error" in content.lower():
570
591
  search_replace_failures += 1
571
592
 
593
+ # Blast radius check: warn when touching 5+ files
594
+ if len(files_modified) >= 5 and len(files_modified) % 5 == 0:
595
+ self._inject_system_note(
596
+ f"BLAST RADIUS WARNING: You have modified {len(files_modified)} files. "
597
+ f"Files: {', '.join(files_modified[-5:])}. "
598
+ f"This is a large change. Are you sure all these edits are needed? "
599
+ f"Consider stopping to verify your approach."
600
+ )
601
+
572
602
  # Bash abuse detection: if model keeps using bash instead of
573
603
  # search_replace/read_file, redirect it to the proper tools
574
604
  if not has_made_edit and bash_count >= 10 and bash_count % 5 == 0:
@@ -579,14 +609,26 @@ class AgentLoop:
579
609
  "Call search_replace NOW with your fix."
580
610
  )
581
611
 
582
- # search_replace keeps failing — suggest re-reading the file
583
- if search_replace_failures >= 3 and search_replace_failures % 2 == 1:
584
- self._inject_system_note(
585
- f"Your search_replace has failed {search_replace_failures} times. "
586
- "The text you're searching for doesn't match the file. STOP guessing. "
587
- "Use read_file with offset/limit to see the EXACT current text, "
588
- "then copy it precisely into search_replace old_str."
589
- )
612
+ # 3-Strike Rule: search_replace keeps failing
613
+ if search_replace_failures >= 3:
614
+ if search_replace_failures == 3:
615
+ # Strike 3: STOP and ask user
616
+ self.messages.append(LLMMessage(
617
+ role=Role.user,
618
+ content=(
619
+ f"3-STRIKE RULE: Your search_replace has failed {search_replace_failures} times. "
620
+ "You have exhausted your attempts. STOP trying the same approach. "
621
+ "Either: (1) use read_file to get the EXACT text first, "
622
+ "(2) try a completely different file, or "
623
+ "(3) ask the user for help with /consult."
624
+ )
625
+ ))
626
+ elif search_replace_failures % 3 == 0:
627
+ # Every 3 more failures, escalate
628
+ self.messages.append(LLMMessage(
629
+ role=Role.user,
630
+ content=f"STOP: {search_replace_failures} failed edits. You are stuck. Ask the user for help."
631
+ ))
590
632
 
591
633
  # Context budget warning: after 7 tool turns without an edit,
592
634
  # warn that context is being consumed without progress
@@ -11,7 +11,7 @@ import keyring.errors
11
11
 
12
12
  GITHUB_CLIENT_ID = "Ov23liJ7sk5kFDMEyvDT"
13
13
 
14
- _SERVICE_NAME = "vibe"
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"
@@ -267,7 +267,7 @@ DEFAULT_PROVIDERS = [
267
267
 
268
268
  DEFAULT_MODELS = [
269
269
  ModelConfig(
270
- name="mistral-vibe-cli-latest",
270
+ name="drydock-cli-latest",
271
271
  provider="mistral",
272
272
  alias="devstral-2",
273
273
  input_price=0.4,
@@ -9,7 +9,7 @@ from drydock.core.paths import LOG_DIR, LOG_FILE
9
9
 
10
10
  LOG_DIR.path.mkdir(parents=True, exist_ok=True)
11
11
 
12
- logger = logging.getLogger("vibe")
12
+ logger = logging.getLogger("drydock")
13
13
 
14
14
 
15
15
  class StructuredLogFormatter(logging.Formatter):
@@ -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="vibe_programmatic", version=__version__)
24
+ _DEFAULT_CLIENT_METADATA = ClientMetadata(name="drydock_programmatic", version=__version__)
25
25
 
26
26
 
27
27
  def run_programmatic(
@@ -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.7.4"
3
+ version = "0.8.1"
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,150 @@
1
+ """Tests for current bugs — must FAIL before fix, PASS after.
2
+
3
+ These reproduce real issues found by using DryDock.
4
+ All tests hit the real vLLM backend.
5
+ """
6
+
7
+ from __future__ import annotations
8
+
9
+ import asyncio
10
+ import os
11
+ from pathlib import Path
12
+
13
+ import httpx
14
+ import pytest
15
+
16
+ from drydock.core.config.harness_files import init_harness_files_manager
17
+ try:
18
+ init_harness_files_manager("user", "project")
19
+ except RuntimeError:
20
+ pass
21
+
22
+ from drydock.core.agent_loop import AgentLoop
23
+ from drydock.core.agents.models import BuiltinAgentName
24
+ from drydock.core.config import Backend, ModelConfig, ProviderConfig, VibeConfig
25
+ from drydock.core.types import (
26
+ AssistantEvent, BaseEvent, Role, ToolCallEvent, ToolResultEvent,
27
+ )
28
+
29
+
30
+ def _vllm_ok():
31
+ try:
32
+ return httpx.get("http://localhost:8000/v1/models", timeout=3).status_code == 200
33
+ except Exception:
34
+ return False
35
+
36
+ pytestmark = pytest.mark.skipif(not _vllm_ok(), reason="vLLM not running")
37
+
38
+
39
+ def _config(tmp_path):
40
+ return VibeConfig(
41
+ active_model="devstral", auto_approve=True, enable_telemetry=False,
42
+ include_project_context=False, system_prompt_id="cli",
43
+ providers=[ProviderConfig(name="local", api_base="http://localhost:8000/v1", api_key_env_var="", backend=Backend.GENERIC)],
44
+ models=[ModelConfig(name="devstral", provider="local", input_price=0, output_price=0)],
45
+ session_logging={"enabled": False, "save_dir": str(tmp_path / "logs")},
46
+ )
47
+
48
+ def _agent(tmp_path, max_turns=10):
49
+ return AgentLoop(config=_config(tmp_path), agent_name=BuiltinAgentName.AUTO_APPROVE, max_turns=max_turns)
50
+
51
+ async def _run(agent, prompt, max_events=100):
52
+ events = []
53
+ async for ev in agent.act(prompt):
54
+ events.append(ev)
55
+ if len(events) >= max_events:
56
+ break
57
+ return events
58
+
59
+
60
+ # ============================================================================
61
+ # BUG: "vibe" still referenced in config defaults
62
+ # ============================================================================
63
+
64
+ class TestVibeReferences:
65
+ def test_no_vibe_in_config_model_names(self):
66
+ """Default model name should not contain 'vibe'."""
67
+ from drydock.core.config._settings import DEFAULT_MODELS
68
+ for m in DEFAULT_MODELS:
69
+ assert "vibe" not in m.name.lower(), \
70
+ f"Model name '{m.name}' still references 'vibe'"
71
+
72
+ def test_no_vibe_in_logger_name(self):
73
+ """Logger should use 'drydock' not 'vibe'."""
74
+ from drydock.core.logger import logger
75
+ assert logger.name != "vibe", \
76
+ f"Logger name is '{logger.name}' — should be 'drydock'"
77
+
78
+ def test_no_vibe_in_client_metadata(self):
79
+ """Programmatic client should identify as drydock."""
80
+ from drydock.core.programmatic import _DEFAULT_CLIENT_METADATA
81
+ assert "vibe" not in _DEFAULT_CLIENT_METADATA.name.lower(), \
82
+ f"Client metadata '{_DEFAULT_CLIENT_METADATA.name}' still references 'vibe'"
83
+
84
+ def test_no_vibe_in_stop_event_tag(self):
85
+ """Internal tags should use drydock not vibe."""
86
+ from drydock.core.utils import VIBE_STOP_EVENT_TAG, VIBE_WARNING_TAG
87
+ # These are internal protocol tags — checking they exist
88
+ # but flagging the naming for awareness
89
+ assert VIBE_STOP_EVENT_TAG # exists
90
+ assert VIBE_WARNING_TAG # exists
91
+
92
+
93
+ # ============================================================================
94
+ # BUG: Websearch loops — model keeps searching the same thing
95
+ # ============================================================================
96
+
97
+ @pytest.mark.asyncio
98
+ async def test_websearch_doesnt_loop(tmp_path):
99
+ """Web search should not repeat the same query more than twice."""
100
+ agent = _agent(tmp_path, max_turns=10)
101
+ events = await _run(agent, "Search the web for 'Python asyncio best practices' and summarize", max_events=60)
102
+
103
+ websearch_calls = [e for e in events if isinstance(e, ToolCallEvent) and e.tool_name == "websearch"]
104
+ assert len(websearch_calls) <= 3, \
105
+ f"Websearch called {len(websearch_calls)} times — looping"
106
+
107
+
108
+ # ============================================================================
109
+ # BUG: Still looping reading files — reads same file over and over
110
+ # ============================================================================
111
+
112
+ @pytest.mark.asyncio
113
+ async def test_file_read_doesnt_loop(tmp_path):
114
+ """Agent should not read the same file more than 3 times."""
115
+ # Create a test file
116
+ test_file = tmp_path / "test_code.py"
117
+ test_file.write_text("def hello():\n print('hello world')\n\ndef goodbye():\n print('bye')\n")
118
+
119
+ agent = _agent(tmp_path, max_turns=10)
120
+ events = await _run(agent, f"Read {test_file} and explain what it does", max_events=60)
121
+
122
+ read_calls = [e for e in events if isinstance(e, ToolCallEvent) and e.tool_name == "read_file"]
123
+
124
+ # Should read the file once or twice, not 5+
125
+ assert len(read_calls) <= 3, \
126
+ f"read_file called {len(read_calls)} times for one file — looping"
127
+
128
+
129
+ # ============================================================================
130
+ # BUG: DuckDuckGo websearch respects --insecure flag
131
+ # ============================================================================
132
+
133
+ class TestWebSearchSSL:
134
+ def test_websearch_uses_insecure_env(self):
135
+ """New DuckDuckGo websearch should check DRYDOCK_INSECURE."""
136
+ import inspect
137
+ from drydock.core.tools.builtins.websearch import WebSearch
138
+ src = inspect.getsource(WebSearch)
139
+ assert "DRYDOCK_INSECURE" in src or "verify" in src, \
140
+ "WebSearch doesn't check DRYDOCK_INSECURE for SSL bypass"
141
+
142
+ def test_websearch_uses_duckduckgo(self):
143
+ """WebSearch should use DuckDuckGo, not Mistral API."""
144
+ import inspect
145
+ from drydock.core.tools.builtins.websearch import WebSearch
146
+ src = inspect.getsource(WebSearch)
147
+ assert "duckduckgo" in src.lower(), \
148
+ "WebSearch should use DuckDuckGo (your refactored version)"
149
+ assert "mistralai" not in src or "import mistralai" not in src, \
150
+ "WebSearch should not require Mistral API"