drydock-cli 0.6.0__tar.gz → 0.6.2__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (454) hide show
  1. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/PKG-INFO +1 -1
  2. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/cli/commands.py +19 -1
  3. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/cli/textual_ui/app.py +82 -2
  4. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/core/agent_loop.py +35 -5
  5. drydock_cli-0.6.2/drydock/core/consultant.py +141 -0
  6. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/pyproject.toml +1 -1
  7. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/test_drydock_tasks.py +2 -4
  8. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/.github/CODEOWNERS +0 -0
  9. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/.github/DISCUSSION_TEMPLATE/ideas.yml +0 -0
  10. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/.github/ISSUE_TEMPLATE/bug-report.yml +0 -0
  11. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/.github/ISSUE_TEMPLATE/config.yml +0 -0
  12. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/.github/workflows/build-and-upload.yml +0 -0
  13. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/.github/workflows/ci.yml +0 -0
  14. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/.github/workflows/issue-labeler.yml +0 -0
  15. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/.github/workflows/release.yml +0 -0
  16. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/.gitignore +0 -0
  17. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/.pre-commit-config.yaml +0 -0
  18. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/.python-version +0 -0
  19. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/.typos.toml +0 -0
  20. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/.vscode/extensions.json +0 -0
  21. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/.vscode/launch.json +0 -0
  22. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/.vscode/settings.json +0 -0
  23. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/AGENTS.md +0 -0
  24. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/CHANGELOG.md +0 -0
  25. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/CLAUDE.md +0 -0
  26. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/CONTRIBUTING.md +0 -0
  27. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/Drydock_rebrand.md +0 -0
  28. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/LICENSE +0 -0
  29. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/NOTICE +0 -0
  30. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/PRD.md +0 -0
  31. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/README.md +0 -0
  32. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/action.yml +0 -0
  33. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/distribution/zed/LICENSE +0 -0
  34. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/distribution/zed/extension.toml +0 -0
  35. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/distribution/zed/icons/mistral_vibe.svg +0 -0
  36. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/docs/README.md +0 -0
  37. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/docs/acp-setup.md +0 -0
  38. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/docs/proxy-setup.md +0 -0
  39. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/__init__.py +0 -0
  40. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/acp/__init__.py +0 -0
  41. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/acp/acp_agent_loop.py +0 -0
  42. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/acp/acp_logger.py +0 -0
  43. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/acp/entrypoint.py +0 -0
  44. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/acp/tools/__init__.py +0 -0
  45. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/acp/tools/base.py +0 -0
  46. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/acp/tools/builtins/bash.py +0 -0
  47. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/acp/tools/builtins/read_file.py +0 -0
  48. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/acp/tools/builtins/search_replace.py +0 -0
  49. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/acp/tools/builtins/todo.py +0 -0
  50. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/acp/tools/builtins/write_file.py +0 -0
  51. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/acp/tools/session_update.py +0 -0
  52. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/acp/utils.py +0 -0
  53. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/cli/__init__.py +0 -0
  54. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/cli/autocompletion/__init__.py +0 -0
  55. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/cli/autocompletion/base.py +0 -0
  56. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/cli/autocompletion/path_completion.py +0 -0
  57. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/cli/autocompletion/slash_command.py +0 -0
  58. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/cli/cli.py +0 -0
  59. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/cli/clipboard.py +0 -0
  60. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/cli/entrypoint.py +0 -0
  61. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/cli/history_manager.py +0 -0
  62. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/cli/plan_offer/adapters/http_whoami_gateway.py +0 -0
  63. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/cli/plan_offer/decide_plan_offer.py +0 -0
  64. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/cli/plan_offer/ports/whoami_gateway.py +0 -0
  65. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/cli/terminal_setup.py +0 -0
  66. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/cli/textual_ui/__init__.py +0 -0
  67. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/cli/textual_ui/ansi_markdown.py +0 -0
  68. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/cli/textual_ui/app.tcss +0 -0
  69. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/cli/textual_ui/external_editor.py +0 -0
  70. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/cli/textual_ui/handlers/__init__.py +0 -0
  71. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/cli/textual_ui/handlers/event_handler.py +0 -0
  72. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/cli/textual_ui/notifications/__init__.py +0 -0
  73. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/cli/textual_ui/notifications/adapters/__init__.py +0 -0
  74. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/cli/textual_ui/notifications/adapters/textual_notification_adapter.py +0 -0
  75. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/cli/textual_ui/notifications/ports/__init__.py +0 -0
  76. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/cli/textual_ui/notifications/ports/notification_port.py +0 -0
  77. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/cli/textual_ui/widgets/__init__.py +0 -0
  78. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/cli/textual_ui/widgets/approval_app.py +0 -0
  79. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/cli/textual_ui/widgets/banner/banner.py +0 -0
  80. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/cli/textual_ui/widgets/banner/petit_chat.py +0 -0
  81. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/cli/textual_ui/widgets/braille_renderer.py +0 -0
  82. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/cli/textual_ui/widgets/chat_input/__init__.py +0 -0
  83. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/cli/textual_ui/widgets/chat_input/body.py +0 -0
  84. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/cli/textual_ui/widgets/chat_input/completion_manager.py +0 -0
  85. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/cli/textual_ui/widgets/chat_input/completion_popup.py +0 -0
  86. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/cli/textual_ui/widgets/chat_input/container.py +0 -0
  87. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/cli/textual_ui/widgets/chat_input/text_area.py +0 -0
  88. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/cli/textual_ui/widgets/compact.py +0 -0
  89. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/cli/textual_ui/widgets/config_app.py +0 -0
  90. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/cli/textual_ui/widgets/context_progress.py +0 -0
  91. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/cli/textual_ui/widgets/load_more.py +0 -0
  92. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/cli/textual_ui/widgets/loading.py +0 -0
  93. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/cli/textual_ui/widgets/messages.py +0 -0
  94. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/cli/textual_ui/widgets/no_markup_static.py +0 -0
  95. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/cli/textual_ui/widgets/path_display.py +0 -0
  96. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/cli/textual_ui/widgets/proxy_setup_app.py +0 -0
  97. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/cli/textual_ui/widgets/question_app.py +0 -0
  98. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/cli/textual_ui/widgets/session_picker.py +0 -0
  99. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/cli/textual_ui/widgets/spinner.py +0 -0
  100. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/cli/textual_ui/widgets/status_message.py +0 -0
  101. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/cli/textual_ui/widgets/teleport_message.py +0 -0
  102. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/cli/textual_ui/widgets/tool_widgets.py +0 -0
  103. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/cli/textual_ui/widgets/tools.py +0 -0
  104. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/cli/textual_ui/widgets/vscode_compat.py +0 -0
  105. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/cli/textual_ui/windowing/__init__.py +0 -0
  106. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/cli/textual_ui/windowing/history.py +0 -0
  107. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/cli/textual_ui/windowing/history_windowing.py +0 -0
  108. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/cli/textual_ui/windowing/state.py +0 -0
  109. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/cli/update_notifier/__init__.py +0 -0
  110. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/cli/update_notifier/adapters/filesystem_update_cache_repository.py +0 -0
  111. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/cli/update_notifier/adapters/github_update_gateway.py +0 -0
  112. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/cli/update_notifier/adapters/pypi_update_gateway.py +0 -0
  113. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/cli/update_notifier/ports/update_cache_repository.py +0 -0
  114. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/cli/update_notifier/ports/update_gateway.py +0 -0
  115. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/cli/update_notifier/update.py +0 -0
  116. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/cli/update_notifier/whats_new.py +0 -0
  117. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/core/__init__.py +0 -0
  118. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/core/agents/__init__.py +0 -0
  119. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/core/agents/manager.py +0 -0
  120. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/core/agents/models.py +0 -0
  121. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/core/auth/__init__.py +0 -0
  122. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/core/auth/crypto.py +0 -0
  123. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/core/auth/github.py +0 -0
  124. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/core/autocompletion/__init__.py +0 -0
  125. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/core/autocompletion/completers.py +0 -0
  126. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/core/autocompletion/file_indexer/__init__.py +0 -0
  127. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/core/autocompletion/file_indexer/ignore_rules.py +0 -0
  128. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/core/autocompletion/file_indexer/indexer.py +0 -0
  129. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/core/autocompletion/file_indexer/store.py +0 -0
  130. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/core/autocompletion/file_indexer/watcher.py +0 -0
  131. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/core/autocompletion/fuzzy.py +0 -0
  132. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/core/autocompletion/path_prompt.py +0 -0
  133. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/core/autocompletion/path_prompt_adapter.py +0 -0
  134. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/core/config/__init__.py +0 -0
  135. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/core/config/_settings.py +0 -0
  136. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/core/config/harness_files/__init__.py +0 -0
  137. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/core/config/harness_files/_harness_manager.py +0 -0
  138. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/core/config/harness_files/_paths.py +0 -0
  139. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/core/drydock_states.py +0 -0
  140. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/core/llm/__init__.py +0 -0
  141. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/core/llm/backend/anthropic.py +0 -0
  142. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/core/llm/backend/base.py +0 -0
  143. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/core/llm/backend/factory.py +0 -0
  144. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/core/llm/backend/generic.py +0 -0
  145. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/core/llm/backend/mistral.py +0 -0
  146. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/core/llm/backend/reasoning_adapter.py +0 -0
  147. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/core/llm/backend/vertex.py +0 -0
  148. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/core/llm/exceptions.py +0 -0
  149. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/core/llm/format.py +0 -0
  150. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/core/llm/message_utils.py +0 -0
  151. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/core/llm/types.py +0 -0
  152. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/core/logger.py +0 -0
  153. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/core/middleware.py +0 -0
  154. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/core/output_formatters.py +0 -0
  155. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/core/paths/__init__.py +0 -0
  156. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/core/paths/_local_config_walk.py +0 -0
  157. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/core/paths/_vibe_home.py +0 -0
  158. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/core/paths/conventions.py +0 -0
  159. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/core/plan_session.py +0 -0
  160. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/core/programmatic.py +0 -0
  161. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/core/prompts/__init__.py +0 -0
  162. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/core/prompts/cli.md +0 -0
  163. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/core/prompts/compact.md +0 -0
  164. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/core/prompts/dangerous_directory.md +0 -0
  165. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/core/prompts/diagnostic.md +0 -0
  166. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/core/prompts/explore.md +0 -0
  167. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/core/prompts/planner.md +0 -0
  168. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/core/prompts/project_context.md +0 -0
  169. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/core/prompts/tests.md +0 -0
  170. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/core/proxy_setup.py +0 -0
  171. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/core/session/session_loader.py +0 -0
  172. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/core/session/session_logger.py +0 -0
  173. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/core/session/session_migration.py +0 -0
  174. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/core/session/state_file.py +0 -0
  175. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/core/skills/__init__.py +0 -0
  176. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/core/skills/manager.py +0 -0
  177. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/core/skills/models.py +0 -0
  178. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/core/skills/parser.py +0 -0
  179. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/core/slug.py +0 -0
  180. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/core/system_prompt.py +0 -0
  181. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/core/telemetry/__init__.py +0 -0
  182. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/core/telemetry/send.py +0 -0
  183. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/core/teleport/errors.py +0 -0
  184. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/core/teleport/git.py +0 -0
  185. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/core/teleport/nuage.py +0 -0
  186. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/core/teleport/teleport.py +0 -0
  187. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/core/teleport/types.py +0 -0
  188. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/core/tools/base.py +0 -0
  189. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/core/tools/builtins/ask_user_question.py +0 -0
  190. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/core/tools/builtins/bash.py +0 -0
  191. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/core/tools/builtins/exit_plan_mode.py +0 -0
  192. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/core/tools/builtins/grep.py +0 -0
  193. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/core/tools/builtins/prompts/__init__.py +0 -0
  194. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/core/tools/builtins/prompts/ask_user_question.md +0 -0
  195. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/core/tools/builtins/prompts/bash.md +0 -0
  196. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/core/tools/builtins/prompts/grep.md +0 -0
  197. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/core/tools/builtins/prompts/read_file.md +0 -0
  198. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/core/tools/builtins/prompts/search_replace.md +0 -0
  199. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/core/tools/builtins/prompts/swe_bench.md +0 -0
  200. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/core/tools/builtins/prompts/task.md +0 -0
  201. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/core/tools/builtins/prompts/todo.md +0 -0
  202. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/core/tools/builtins/prompts/webfetch.md +0 -0
  203. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/core/tools/builtins/prompts/websearch.md +0 -0
  204. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/core/tools/builtins/prompts/write_file.md +0 -0
  205. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/core/tools/builtins/read_file.py +0 -0
  206. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/core/tools/builtins/search_replace.py +0 -0
  207. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/core/tools/builtins/task.py +0 -0
  208. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/core/tools/builtins/todo.py +0 -0
  209. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/core/tools/builtins/webfetch.py +0 -0
  210. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/core/tools/builtins/websearch.py +0 -0
  211. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/core/tools/builtins/write_file.py +0 -0
  212. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/core/tools/injection_guard.py +0 -0
  213. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/core/tools/manager.py +0 -0
  214. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/core/tools/mcp/__init__.py +0 -0
  215. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/core/tools/mcp/registry.py +0 -0
  216. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/core/tools/mcp/tools.py +0 -0
  217. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/core/tools/mcp_sampling.py +0 -0
  218. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/core/tools/ui.py +0 -0
  219. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/core/tools/utils.py +0 -0
  220. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/core/trusted_folders.py +0 -0
  221. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/core/types.py +0 -0
  222. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/core/utils.py +0 -0
  223. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/setup/onboarding/__init__.py +0 -0
  224. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/setup/onboarding/base.py +0 -0
  225. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/setup/onboarding/onboarding.tcss +0 -0
  226. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/setup/onboarding/screens/__init__.py +0 -0
  227. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/setup/onboarding/screens/api_key.py +0 -0
  228. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/setup/onboarding/screens/welcome.py +0 -0
  229. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/setup/trusted_folders/trust_folder_dialog.py +0 -0
  230. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/setup/trusted_folders/trust_folder_dialog.tcss +0 -0
  231. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/skills/__init__.py +0 -0
  232. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/skills/create-presentation/SKILL.md +0 -0
  233. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/whats_new.md +0 -0
  234. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock-acp.spec +0 -0
  235. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock_terms.md +0 -0
  236. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/flake.lock +0 -0
  237. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/flake.nix +0 -0
  238. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/scripts/README.md +0 -0
  239. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/scripts/bump_version.py +0 -0
  240. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/scripts/deploy_to_github.sh +0 -0
  241. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/scripts/install.sh +0 -0
  242. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/scripts/prepare_release.py +0 -0
  243. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/scripts/publish_to_pypi.sh +0 -0
  244. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/__init__.py +0 -0
  245. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/acp/conftest.py +0 -0
  246. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/acp/test_acp.py +0 -0
  247. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/acp/test_agent_thought.py +0 -0
  248. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/acp/test_bash.py +0 -0
  249. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/acp/test_compact_session_updates.py +0 -0
  250. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/acp/test_content.py +0 -0
  251. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/acp/test_initialize.py +0 -0
  252. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/acp/test_list_sessions.py +0 -0
  253. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/acp/test_load_session.py +0 -0
  254. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/acp/test_multi_session.py +0 -0
  255. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/acp/test_new_session.py +0 -0
  256. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/acp/test_proxy_setup_acp.py +0 -0
  257. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/acp/test_read_file.py +0 -0
  258. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/acp/test_search_replace.py +0 -0
  259. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/acp/test_set_config_option.py +0 -0
  260. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/acp/test_set_mode.py +0 -0
  261. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/acp/test_set_model.py +0 -0
  262. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/acp/test_tool_call_session_update.py +0 -0
  263. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/acp/test_utils.py +0 -0
  264. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/acp/test_write_file.py +0 -0
  265. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/autocompletion/test_file_indexer.py +0 -0
  266. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/autocompletion/test_fuzzy.py +0 -0
  267. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/autocompletion/test_path_completer_fuzzy.py +0 -0
  268. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/autocompletion/test_path_completer_recursive.py +0 -0
  269. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/autocompletion/test_path_completion_controller.py +0 -0
  270. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/autocompletion/test_path_prompt_transformer.py +0 -0
  271. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/autocompletion/test_slash_command_controller.py +0 -0
  272. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/autocompletion/test_ui_chat_autocompletion.py +0 -0
  273. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/backend/__init__.py +0 -0
  274. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/backend/data/__init__.py +0 -0
  275. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/backend/data/fireworks.py +0 -0
  276. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/backend/data/mistral.py +0 -0
  277. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/backend/test_anthropic_adapter.py +0 -0
  278. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/backend/test_backend.py +0 -0
  279. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/backend/test_reasoning_adapter.py +0 -0
  280. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/backend/test_vertex_anthropic_adapter.py +0 -0
  281. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/cli/plan_offer/adapters/fake_whoami_gateway.py +0 -0
  282. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/cli/plan_offer/test_decide_plan_offer.py +0 -0
  283. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/cli/plan_offer/test_http_whoami_gateway.py +0 -0
  284. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/cli/test_bell_notifications.py +0 -0
  285. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/cli/test_braille_renderer.py +0 -0
  286. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/cli/test_clipboard.py +0 -0
  287. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/cli/test_commands.py +0 -0
  288. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/cli/test_copy_shortcuts.py +0 -0
  289. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/cli/test_external_editor.py +0 -0
  290. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/cli/test_no_markup_static.py +0 -0
  291. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/cli/test_question_app.py +0 -0
  292. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/cli/test_spinner.py +0 -0
  293. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/cli/test_switching_mode.py +0 -0
  294. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/cli/test_ui_clipboard_notifications.py +0 -0
  295. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/cli/test_ui_session_incremental_renderer.py +0 -0
  296. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/cli/test_ui_session_resume.py +0 -0
  297. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/cli/test_ui_skill_dispatch.py +0 -0
  298. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/cli/textual_ui/__init__.py +0 -0
  299. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/cli/textual_ui/test_session_picker.py +0 -0
  300. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/conftest.py +0 -0
  301. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/core/test_agents.py +0 -0
  302. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/core/test_auth_crypto.py +0 -0
  303. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/core/test_auth_github.py +0 -0
  304. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/core/test_config_load_dotenv.py +0 -0
  305. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/core/test_config_paths.py +0 -0
  306. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/core/test_config_resolution.py +0 -0
  307. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/core/test_file_logging.py +0 -0
  308. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/core/test_plan_session.py +0 -0
  309. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/core/test_proxy_setup.py +0 -0
  310. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/core/test_slug.py +0 -0
  311. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/core/test_telemetry_send.py +0 -0
  312. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/core/test_teleport_git.py +0 -0
  313. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/core/test_teleport_nuage.py +0 -0
  314. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/core/test_teleport_service.py +0 -0
  315. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/core/test_trusted_folders.py +0 -0
  316. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/core/test_utils.py +0 -0
  317. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/e2e/common.py +0 -0
  318. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/e2e/conftest.py +0 -0
  319. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/e2e/mock_server.py +0 -0
  320. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/e2e/test_cli_tui_onboarding.py +0 -0
  321. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/e2e/test_cli_tui_streaming.py +0 -0
  322. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/e2e/test_cli_tui_tool_approval.py +0 -0
  323. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/mock/__init__.py +0 -0
  324. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/mock/mock_backend_factory.py +0 -0
  325. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/mock/mock_entrypoint.py +0 -0
  326. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/mock/utils.py +0 -0
  327. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/onboarding/test_run_onboarding.py +0 -0
  328. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/onboarding/test_ui_onboarding.py +0 -0
  329. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/session/test_session_loader.py +0 -0
  330. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/session/test_session_logger.py +0 -0
  331. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/session/test_session_migration.py +0 -0
  332. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/skills/conftest.py +0 -0
  333. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/skills/test_manager.py +0 -0
  334. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/skills/test_models.py +0 -0
  335. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/skills/test_parser.py +0 -0
  336. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/snapshots/__snapshots__/test_ui_snapshot_ask_user_question/test_snapshot_ask_user_question_collapsed.svg +0 -0
  337. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/snapshots/__snapshots__/test_ui_snapshot_ask_user_question/test_snapshot_ask_user_question_expanded.svg +0 -0
  338. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/snapshots/__snapshots__/test_ui_snapshot_basic_conversation/test_snapshot_shows_basic_conversation.svg +0 -0
  339. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/snapshots/__snapshots__/test_ui_snapshot_code_block_horizontal_scrolling/test_snapshot_allows_horizontal_scrolling_for_long_code_blocks.svg +0 -0
  340. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/snapshots/__snapshots__/test_ui_snapshot_empty_assistant_before_reasoning/test_snapshot_empty_assistant_removed_when_reasoning_starts.svg +0 -0
  341. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/snapshots/__snapshots__/test_ui_snapshot_modes/test_snapshot_cycle_to_accept_edits_mode.svg +0 -0
  342. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/snapshots/__snapshots__/test_ui_snapshot_modes/test_snapshot_cycle_to_auto_approve_mode.svg +0 -0
  343. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/snapshots/__snapshots__/test_ui_snapshot_modes/test_snapshot_cycle_to_plan_mode.svg +0 -0
  344. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/snapshots/__snapshots__/test_ui_snapshot_modes/test_snapshot_cycle_wraps_to_default.svg +0 -0
  345. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/snapshots/__snapshots__/test_ui_snapshot_modes/test_snapshot_default_mode.svg +0 -0
  346. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/snapshots/__snapshots__/test_ui_snapshot_parallel_tool_calls/test_snapshot_parallel_tool_calls_pending.svg +0 -0
  347. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/snapshots/__snapshots__/test_ui_snapshot_parallel_tool_calls/test_snapshot_parallel_tool_calls_resolved.svg +0 -0
  348. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/snapshots/__snapshots__/test_ui_snapshot_proxy_setup/test_snapshot_proxy_setup_cancel_discards_changes.svg +0 -0
  349. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/snapshots/__snapshots__/test_ui_snapshot_proxy_setup/test_snapshot_proxy_setup_edit_existing_values.svg +0 -0
  350. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/snapshots/__snapshots__/test_ui_snapshot_proxy_setup/test_snapshot_proxy_setup_initial_empty.svg +0 -0
  351. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/snapshots/__snapshots__/test_ui_snapshot_proxy_setup/test_snapshot_proxy_setup_initial_with_values.svg +0 -0
  352. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/snapshots/__snapshots__/test_ui_snapshot_proxy_setup/test_snapshot_proxy_setup_save_error.svg +0 -0
  353. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/snapshots/__snapshots__/test_ui_snapshot_proxy_setup/test_snapshot_proxy_setup_save_new_values.svg +0 -0
  354. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_question_answer_first_advance.svg +0 -0
  355. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_question_first_answered_checkmark.svg +0 -0
  356. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_question_initial.svg +0 -0
  357. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_question_navigate_left_wraps.svg +0 -0
  358. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_question_navigate_right.svg +0 -0
  359. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_question_tab_to_second.svg +0 -0
  360. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_select_initial.svg +0 -0
  361. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_select_mixed_selection.svg +0 -0
  362. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_select_navigate_to_submit.svg +0 -0
  363. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_select_other_with_text.svg +0 -0
  364. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_select_toggle_first.svg +0 -0
  365. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_select_toggle_multiple.svg +0 -0
  366. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_select_untoggle.svg +0 -0
  367. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_question_app_initial.svg +0 -0
  368. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_question_app_navigate_down.svg +0 -0
  369. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_question_app_navigate_to_other.svg +0 -0
  370. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_question_app_navigate_to_third_option.svg +0 -0
  371. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_question_app_navigate_up_wraps.svg +0 -0
  372. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_question_app_other_typing.svg +0 -0
  373. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/snapshots/__snapshots__/test_ui_snapshot_reasoning_content/test_snapshot_buffered_reasoning_yields_before_content.svg +0 -0
  374. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/snapshots/__snapshots__/test_ui_snapshot_reasoning_content/test_snapshot_shows_interleaved_reasoning.svg +0 -0
  375. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/snapshots/__snapshots__/test_ui_snapshot_reasoning_content/test_snapshot_shows_reasoning_content.svg +0 -0
  376. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/snapshots/__snapshots__/test_ui_snapshot_reasoning_content/test_snapshot_shows_reasoning_content_expanded.svg +0 -0
  377. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/snapshots/__snapshots__/test_ui_snapshot_release_update_notification/test_snapshot_shows_release_update_notification.svg +0 -0
  378. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/snapshots/__snapshots__/test_ui_snapshot_session_resume/test_snapshot_shows_resumed_session_messages.svg +0 -0
  379. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/snapshots/__snapshots__/test_ui_snapshot_streaming_tool_call/test_snapshot_tool_call_partial.svg +0 -0
  380. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/snapshots/__snapshots__/test_ui_snapshot_streaming_tool_call/test_snapshot_tool_call_updated.svg +0 -0
  381. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_push_confirmation_cancel_selected.svg +0 -0
  382. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_push_confirmation_multiple_commits.svg +0 -0
  383. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_push_confirmation_single_commit.svg +0 -0
  384. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_status_auth_complete.svg +0 -0
  385. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_status_auth_required.svg +0 -0
  386. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_status_checking_git.svg +0 -0
  387. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_status_complete.svg +0 -0
  388. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_status_error.svg +0 -0
  389. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_status_pushing.svg +0 -0
  390. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_status_sending_token.svg +0 -0
  391. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_status_starting_workflow.svg +0 -0
  392. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/snapshots/__snapshots__/test_ui_snapshot_whats_new/test_snapshot_shows_no_plan_message.svg +0 -0
  393. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/snapshots/__snapshots__/test_ui_snapshot_whats_new/test_snapshot_shows_switch_message.svg +0 -0
  394. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/snapshots/__snapshots__/test_ui_snapshot_whats_new/test_snapshot_shows_upgrade_message.svg +0 -0
  395. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/snapshots/__snapshots__/test_ui_snapshot_whats_new/test_snapshot_shows_whats_new_message.svg +0 -0
  396. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/snapshots/base_snapshot_test_app.py +0 -0
  397. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/snapshots/conftest.py +0 -0
  398. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/snapshots/snap_compare.py +0 -0
  399. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/snapshots/test_ui_snapshot_ask_user_question.py +0 -0
  400. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/snapshots/test_ui_snapshot_basic_conversation.py +0 -0
  401. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/snapshots/test_ui_snapshot_code_block_horizontal_scrolling.py +0 -0
  402. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/snapshots/test_ui_snapshot_empty_assistant_before_reasoning.py +0 -0
  403. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/snapshots/test_ui_snapshot_modes.py +0 -0
  404. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/snapshots/test_ui_snapshot_parallel_tool_calls.py +0 -0
  405. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/snapshots/test_ui_snapshot_proxy_setup.py +0 -0
  406. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/snapshots/test_ui_snapshot_question_app.py +0 -0
  407. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/snapshots/test_ui_snapshot_reasoning_content.py +0 -0
  408. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/snapshots/test_ui_snapshot_release_update_notification.py +0 -0
  409. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/snapshots/test_ui_snapshot_session_resume.py +0 -0
  410. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/snapshots/test_ui_snapshot_streaming_tool_call.py +0 -0
  411. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/snapshots/test_ui_snapshot_teleport.py +0 -0
  412. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/snapshots/test_ui_snapshot_whats_new.py +0 -0
  413. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/stubs/fake_backend.py +0 -0
  414. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/stubs/fake_client.py +0 -0
  415. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/stubs/fake_tool.py +0 -0
  416. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/test_agent_auto_compact.py +0 -0
  417. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/test_agent_backend.py +0 -0
  418. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/test_agent_observer_streaming.py +0 -0
  419. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/test_agent_stats.py +0 -0
  420. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/test_agent_tool_call.py +0 -0
  421. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/test_agents.py +0 -0
  422. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/test_cli_programmatic_preload.py +0 -0
  423. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/test_drydock_regression.py +0 -0
  424. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/test_history_manager.py +0 -0
  425. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/test_message_id.py +0 -0
  426. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/test_message_merging.py +0 -0
  427. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/test_middleware.py +0 -0
  428. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/test_reasoning_content.py +0 -0
  429. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/test_system_prompt.py +0 -0
  430. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/test_tagged_text.py +0 -0
  431. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/test_ui_external_editor.py +0 -0
  432. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/test_ui_input_history.py +0 -0
  433. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/tools/test_ask_user_question.py +0 -0
  434. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/tools/test_bash.py +0 -0
  435. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/tools/test_exit_plan_mode.py +0 -0
  436. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/tools/test_grep.py +0 -0
  437. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/tools/test_invoke_context.py +0 -0
  438. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/tools/test_manager_get_tool_config.py +0 -0
  439. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/tools/test_mcp.py +0 -0
  440. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/tools/test_mcp_sampling.py +0 -0
  441. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/tools/test_task.py +0 -0
  442. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/tools/test_ui_bash_execution.py +0 -0
  443. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/tools/test_webfetch.py +0 -0
  444. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/tools/test_websearch.py +0 -0
  445. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/update_notifier/adapters/fake_update_cache_repository.py +0 -0
  446. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/update_notifier/adapters/fake_update_gateway.py +0 -0
  447. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/update_notifier/test_do_update.py +0 -0
  448. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/update_notifier/test_filesystem_update_cache_repository.py +0 -0
  449. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/update_notifier/test_github_update_gateway.py +0 -0
  450. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/update_notifier/test_pypi_update_gateway.py +0 -0
  451. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/update_notifier/test_ui_update_notification.py +0 -0
  452. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/update_notifier/test_update_use_case.py +0 -0
  453. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/update_notifier/test_whats_new.py +0 -0
  454. {drydock_cli-0.6.0 → drydock_cli-0.6.2}/uv.lock +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: drydock-cli
3
- Version: 0.6.0
3
+ Version: 0.6.2
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
@@ -72,6 +72,11 @@ class CommandRegistry:
72
72
  description="Configure proxy and SSL certificate settings",
73
73
  handler="_show_proxy_setup",
74
74
  ),
75
+ "consult": Command(
76
+ aliases=frozenset(["/consult"]),
77
+ description="Ask a smarter model for advice (response visible to local model)",
78
+ handler="_consult_command",
79
+ ),
75
80
  "resume": Command(
76
81
  aliases=frozenset(["/resume", "/continue"]),
77
82
  description="Browse and resume past sessions",
@@ -92,7 +97,20 @@ class CommandRegistry:
92
97
  return self.commands.get(cmd_name) if cmd_name else None
93
98
 
94
99
  def get_command_name(self, user_input: str) -> str | None:
95
- return self._alias_map.get(user_input.lower().strip())
100
+ stripped = user_input.lower().strip()
101
+ # Exact match first
102
+ if stripped in self._alias_map:
103
+ return self._alias_map[stripped]
104
+ # Prefix match for commands that take arguments (e.g., /consult <question>)
105
+ first_word = stripped.split()[0] if stripped else ""
106
+ if first_word in self._alias_map:
107
+ return self._alias_map[first_word]
108
+ return None
109
+
110
+ def get_command_args(self, user_input: str) -> str:
111
+ """Extract arguments after the command name."""
112
+ parts = user_input.strip().split(None, 1)
113
+ return parts[1] if len(parts) > 1 else ""
96
114
 
97
115
  def get_help_text(self) -> str:
98
116
  lines: list[str] = [
@@ -520,10 +520,18 @@ class VibeApp(App): # noqa: PLR0904
520
520
  )
521
521
  await self._mount_and_scroll(UserMessage(user_input))
522
522
  handler = getattr(self, command.handler)
523
+ # Pass command args to handlers that accept them
524
+ cmd_args = self.commands.get_command_args(user_input)
523
525
  if asyncio.iscoroutinefunction(handler):
524
- await handler()
526
+ try:
527
+ await handler(cmd_args)
528
+ except TypeError:
529
+ await handler() # Handler doesn't accept args
525
530
  else:
526
- handler()
531
+ try:
532
+ handler(cmd_args)
533
+ except TypeError:
534
+ handler()
527
535
  return True
528
536
  return False
529
537
 
@@ -927,6 +935,78 @@ class VibeApp(App): # noqa: PLR0904
927
935
  """
928
936
  await self._mount_and_scroll(UserCommandMessage(status_text))
929
937
 
938
+ async def _consult_command(self, question: str = "") -> None:
939
+ """Ask a consultant model for advice. Response goes into context."""
940
+ if not question:
941
+ await self._mount_and_scroll(
942
+ UserCommandMessage(
943
+ "Usage: `/consult <your question>`\n\n"
944
+ "Asks a smarter model for advice. The response appears in the "
945
+ "conversation so the local model can see and act on it.\n\n"
946
+ "Configure: set `consultant_model` in config.toml or use `--consultant MODEL`"
947
+ )
948
+ )
949
+ return
950
+
951
+ # Get consultant model from config or env
952
+ import os
953
+ consultant_model = os.environ.get("DRYDOCK_CONSULTANT_MODEL", "")
954
+ if not consultant_model:
955
+ # Check config for consultant_model setting
956
+ try:
957
+ consultant_model = getattr(self.agent_loop.config, "consultant_model", "")
958
+ except Exception:
959
+ pass
960
+
961
+ if not consultant_model:
962
+ await self._mount_and_scroll(
963
+ ErrorMessage(
964
+ "No consultant model configured.\n"
965
+ "Set via: `drydock --consultant gemini-2.5-pro` or "
966
+ "`export DRYDOCK_CONSULTANT_MODEL=gemini-2.5-pro`",
967
+ collapsed=self._tools_collapsed,
968
+ )
969
+ )
970
+ return
971
+
972
+ await self._mount_and_scroll(
973
+ UserCommandMessage(f"Consulting {consultant_model}...")
974
+ )
975
+
976
+ try:
977
+ from drydock.core.consultant import ask_consultant
978
+ advice = await ask_consultant(question, model=consultant_model)
979
+
980
+ if not advice or advice.startswith("(Consultant unavailable"):
981
+ await self._mount_and_scroll(
982
+ ErrorMessage(
983
+ f"Consultant ({consultant_model}) unavailable: {advice}",
984
+ collapsed=self._tools_collapsed,
985
+ )
986
+ )
987
+ return
988
+
989
+ # Show the advice in the UI
990
+ response_text = f"**Consultant ({consultant_model}):**\n\n{advice}"
991
+ await self._mount_and_scroll(UserCommandMessage(response_text))
992
+
993
+ # Inject into the message history so the LOCAL model can see it
994
+ from drydock.core.types import LLMMessage, Role
995
+ self.agent_loop.messages.append(
996
+ LLMMessage(
997
+ role=Role.user,
998
+ content=f"[CONSULTANT ADVICE from {consultant_model}]: {advice}"
999
+ )
1000
+ )
1001
+
1002
+ except Exception as e:
1003
+ await self._mount_and_scroll(
1004
+ ErrorMessage(
1005
+ f"Consultant error: {e}",
1006
+ collapsed=self._tools_collapsed,
1007
+ )
1008
+ )
1009
+
930
1010
  async def _show_config(self) -> None:
931
1011
  """Switch to the configuration app in the bottom panel."""
932
1012
  if self._current_bottom_app == BottomApp.Config:
@@ -835,6 +835,18 @@ class AgentLoop:
835
835
  )
836
836
  )
837
837
 
838
+ def _get_attempted_summary(self) -> str:
839
+ """Build a summary of what the agent has already tried."""
840
+ if not self._tool_call_history:
841
+ return ""
842
+ attempts = []
843
+ for sig, (count, result) in self._tool_call_history.items():
844
+ if count >= 2:
845
+ attempts.append(f" - Ran {count}x, result: {result[:80]}")
846
+ if attempts:
847
+ return "ALREADY ATTEMPTED (do NOT repeat):\n" + "\n".join(attempts[:10])
848
+ return ""
849
+
838
850
  def _circuit_breaker_check(self, tool_call: ResolvedToolCall) -> str | None:
839
851
  """Block exact-duplicate tool calls. Returns cached result or None."""
840
852
  sig = hashlib.md5(
@@ -843,12 +855,30 @@ class AgentLoop:
843
855
 
844
856
  count, last_result = self._tool_call_history.get(sig, (0, ""))
845
857
  if count >= 2:
846
- return (
847
- f"CIRCUIT BREAKER: You already ran this exact command {count} times "
848
- f"and got the same result. Previous result: {last_result[:300]}\n\n"
849
- f"Do NOT repeat. Try a DIFFERENT approach, different arguments, "
850
- f"or a different tool."
858
+ attempted = self._get_attempted_summary()
859
+ msg = (
860
+ f"CIRCUIT BREAKER: You already ran `{tool_call.tool_name}` with these "
861
+ f"exact arguments {count} times and got the same result each time.\n\n"
862
+ f"Previous result: {last_result[:200]}\n\n"
863
+ f"{attempted}\n\n"
864
+ f"STOP repeating. You MUST try something DIFFERENT:\n"
865
+ f"- Different arguments or search terms\n"
866
+ f"- A completely different tool\n"
867
+ f"- Ask the user for clarification"
851
868
  )
869
+
870
+ # Suggest using /consult if a consultant model is configured
871
+ try:
872
+ from drydock.core.consultant import is_consultant_available
873
+ if is_consultant_available():
874
+ msg += (
875
+ "\n\nTIP: A consultant model is available. "
876
+ "The user can type `/consult <question>` to ask it for advice."
877
+ )
878
+ except Exception:
879
+ pass
880
+
881
+ return msg
852
882
  return None
853
883
 
854
884
  def _circuit_breaker_record(self, tool_call: ResolvedToolCall, result_text: str) -> None:
@@ -0,0 +1,141 @@
1
+ """Consultant agent — asks a smarter model for single-turn advice.
2
+
3
+ The consultant is a READ-ONLY advisor:
4
+ - The local model stays in control of ALL tool calls
5
+ - The consultant NEVER calls tools, writes files, or runs commands
6
+ - It only receives a question and returns reasoning/advice
7
+ - Used when the local model is stuck, uncertain, or looping
8
+
9
+ Usage from agent_loop:
10
+ advice = await ask_consultant("I found 3 files that match. Which one likely contains the bug?")
11
+
12
+ The consultant model is configured via:
13
+ - CLI: drydock --consultant gemini-2.5-pro
14
+ - Env: DRYDOCK_CONSULTANT_MODEL=gemini-2.5-pro
15
+ """
16
+
17
+ from __future__ import annotations
18
+
19
+ import logging
20
+ import os
21
+ from typing import Any
22
+
23
+ import httpx
24
+
25
+ logger = logging.getLogger(__name__)
26
+
27
+
28
+ async def ask_consultant(
29
+ question: str,
30
+ context: str = "",
31
+ model: str | None = None,
32
+ api_key: str | None = None,
33
+ api_base: str | None = None,
34
+ ) -> str:
35
+ """Ask the consultant model a question and get text advice back.
36
+
37
+ Parameters
38
+ ----------
39
+ question : str
40
+ The specific question to ask.
41
+ context : str
42
+ Optional context (e.g., file contents, error messages).
43
+ model : str
44
+ Model name. Defaults to DRYDOCK_CONSULTANT_MODEL env var.
45
+ api_key : str
46
+ API key. Auto-detected from common env vars if not provided.
47
+ api_base : str
48
+ API base URL. Auto-detected based on model name if not provided.
49
+
50
+ Returns
51
+ -------
52
+ str
53
+ The consultant's advice text, or an error message.
54
+ """
55
+ model = model or os.environ.get("DRYDOCK_CONSULTANT_MODEL", "")
56
+ if not model:
57
+ return ""
58
+
59
+ # Auto-detect API key and base URL from model name
60
+ api_key = api_key or _detect_api_key(model)
61
+ api_base = api_base or _detect_api_base(model)
62
+
63
+ if not api_key:
64
+ logger.warning("No API key found for consultant model '%s'", model)
65
+ return ""
66
+
67
+ prompt = f"""You are a senior software engineering consultant. A junior AI coding agent is asking for your advice.
68
+ Give concise, actionable guidance. Do NOT provide code — just tell them WHAT to do and WHERE to look.
69
+
70
+ QUESTION:
71
+ {question}
72
+ """
73
+ if context:
74
+ prompt += f"\nCONTEXT:\n{context[:2000]}\n"
75
+
76
+ try:
77
+ # Use OpenAI-compatible API (works with Gemini, OpenAI, Mistral, local models)
78
+ verify_ssl = os.environ.get("DRYDOCK_INSECURE") != "1"
79
+ async with httpx.AsyncClient(verify=verify_ssl, timeout=30.0) as client:
80
+ response = await client.post(
81
+ f"{api_base}/chat/completions",
82
+ headers={
83
+ "Authorization": f"Bearer {api_key}",
84
+ "Content-Type": "application/json",
85
+ },
86
+ json={
87
+ "model": model,
88
+ "messages": [{"role": "user", "content": prompt}],
89
+ "max_tokens": 500,
90
+ "temperature": 0.3,
91
+ # NO tools — consultant is read-only
92
+ },
93
+ )
94
+ response.raise_for_status()
95
+ data = response.json()
96
+ advice = data["choices"][0]["message"]["content"]
97
+ logger.info("Consultant (%s) responded: %s", model, advice[:100])
98
+ return advice
99
+
100
+ except Exception as e:
101
+ logger.warning("Consultant call failed: %s", e)
102
+ return f"(Consultant unavailable: {e})"
103
+
104
+
105
+ def _detect_api_key(model: str) -> str:
106
+ """Auto-detect API key from environment based on model name."""
107
+ model_lower = model.lower()
108
+
109
+ if "gemini" in model_lower:
110
+ return os.environ.get("GEMINI_API_KEY", os.environ.get("GOOGLE_API_KEY", ""))
111
+ if "gpt" in model_lower or "o1" in model_lower or "o3" in model_lower:
112
+ return os.environ.get("OPENAI_API_KEY", "")
113
+ if "claude" in model_lower:
114
+ return os.environ.get("ANTHROPIC_API_KEY", "")
115
+ if "mistral" in model_lower or "devstral" in model_lower:
116
+ return os.environ.get("MISTRAL_API_KEY", "")
117
+
118
+ # Generic fallback
119
+ return os.environ.get("DRYDOCK_CONSULTANT_API_KEY", "")
120
+
121
+
122
+ def _detect_api_base(model: str) -> str:
123
+ """Auto-detect API base URL from model name."""
124
+ model_lower = model.lower()
125
+
126
+ if "gemini" in model_lower:
127
+ return "https://generativelanguage.googleapis.com/v1beta/openai"
128
+ if "gpt" in model_lower or "o1" in model_lower or "o3" in model_lower:
129
+ return "https://api.openai.com/v1"
130
+ if "claude" in model_lower:
131
+ return "https://api.anthropic.com/v1"
132
+ if "mistral" in model_lower or "devstral" in model_lower:
133
+ return os.environ.get("MISTRAL_API_BASE", "https://api.mistral.ai/v1")
134
+
135
+ # Try local vLLM
136
+ return os.environ.get("DRYDOCK_CONSULTANT_API_BASE", "http://localhost:8000/v1")
137
+
138
+
139
+ def is_consultant_available() -> bool:
140
+ """Check if a consultant model is configured."""
141
+ return bool(os.environ.get("DRYDOCK_CONSULTANT_MODEL"))
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "drydock-cli"
3
- version = "0.6.0"
3
+ version = "0.6.2"
4
4
  description = "Drydock — nautical CLI coding agent"
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.12"
@@ -391,6 +391,7 @@ class TestCircuitBreaker:
391
391
  """Prevents exact duplicate tool calls."""
392
392
 
393
393
  def test_circuit_breaker_blocks_after_2(self):
394
+ import asyncio
394
395
  from drydock.core.agent_loop import AgentLoop
395
396
  from drydock.core.types import MessageList
396
397
  from types import SimpleNamespace
@@ -399,21 +400,19 @@ class TestCircuitBreaker:
399
400
  al.messages = MessageList()
400
401
  al._tool_call_history = {}
401
402
 
402
- # Mock tool call with same name+args
403
403
  tc = SimpleNamespace(tool_name="bash", raw_arguments='{"command": "ls -ltr"}')
404
404
 
405
- # First two calls: no block
406
405
  assert al._circuit_breaker_check(tc) is None
407
406
  al._circuit_breaker_record(tc, "file1.py\nfile2.py")
408
407
  assert al._circuit_breaker_check(tc) is None
409
408
  al._circuit_breaker_record(tc, "file1.py\nfile2.py")
410
409
 
411
- # Third call: BLOCKED
412
410
  result = al._circuit_breaker_check(tc)
413
411
  assert result is not None
414
412
  assert "CIRCUIT BREAKER" in result
415
413
 
416
414
  def test_different_args_not_blocked(self):
415
+ import asyncio
417
416
  from drydock.core.agent_loop import AgentLoop
418
417
  from drydock.core.types import MessageList
419
418
  from types import SimpleNamespace
@@ -427,7 +426,6 @@ class TestCircuitBreaker:
427
426
 
428
427
  al._circuit_breaker_record(tc1, "result1")
429
428
  al._circuit_breaker_record(tc1, "result1")
430
- # tc1 blocked, tc2 still works
431
429
  assert al._circuit_breaker_check(tc1) is not None
432
430
  assert al._circuit_breaker_check(tc2) is None
433
431
 
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes