drydock-cli 0.8.2__tar.gz → 1.0.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (479) hide show
  1. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/PKG-INFO +1 -1
  2. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/drydock/core/agents/models.py +47 -0
  3. drydock_cli-1.0.0/drydock/core/hooks.py +179 -0
  4. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/drydock/core/skills/models.py +18 -0
  5. drydock_cli-1.0.0/drydock/core/tools/builtins/glob_tool.py +94 -0
  6. drydock_cli-1.0.0/drydock/core/tools/builtins/invoke_skill.py +100 -0
  7. drydock_cli-1.0.0/drydock/core/tools/builtins/notebook_edit.py +96 -0
  8. drydock_cli-1.0.0/drydock/core/tools/builtins/prompts/glob.md +9 -0
  9. drydock_cli-1.0.0/drydock/core/tools/builtins/prompts/invoke_skill.md +9 -0
  10. drydock_cli-1.0.0/drydock/core/tools/builtins/prompts/notebook_edit.md +7 -0
  11. drydock_cli-1.0.0/drydock/core/tools/builtins/prompts/task_manager.md +8 -0
  12. drydock_cli-1.0.0/drydock/core/tools/builtins/prompts/worktree.md +7 -0
  13. drydock_cli-1.0.0/drydock/core/tools/builtins/task_manager.py +169 -0
  14. drydock_cli-1.0.0/drydock/core/tools/builtins/worktree.py +166 -0
  15. drydock_cli-1.0.0/drydock/skills/batch/SKILL.md +45 -0
  16. drydock_cli-1.0.0/drydock/skills/simplify/SKILL.md +39 -0
  17. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/pyproject.toml +3 -1
  18. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/.github/CODEOWNERS +0 -0
  19. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/.github/DISCUSSION_TEMPLATE/ideas.yml +0 -0
  20. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/.github/ISSUE_TEMPLATE/bug-report.yml +0 -0
  21. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/.github/ISSUE_TEMPLATE/config.yml +0 -0
  22. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/.github/workflows/build-and-upload.yml +0 -0
  23. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/.github/workflows/ci.yml +0 -0
  24. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/.github/workflows/issue-labeler.yml +0 -0
  25. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/.github/workflows/release.yml +0 -0
  26. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/.gitignore +0 -0
  27. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/.pre-commit-config.yaml +0 -0
  28. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/.python-version +0 -0
  29. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/.typos.toml +0 -0
  30. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/.vscode/extensions.json +0 -0
  31. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/.vscode/launch.json +0 -0
  32. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/.vscode/settings.json +0 -0
  33. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/AGENTS.md +0 -0
  34. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/CHANGELOG.md +0 -0
  35. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/CLAUDE.md +0 -0
  36. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/CONTRIBUTING.md +0 -0
  37. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/Drydock_rebrand.md +0 -0
  38. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/LICENSE +0 -0
  39. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/NOTICE +0 -0
  40. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/PRD.md +0 -0
  41. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/README.md +0 -0
  42. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/action.yml +0 -0
  43. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/distribution/zed/LICENSE +0 -0
  44. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/distribution/zed/extension.toml +0 -0
  45. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/distribution/zed/icons/mistral_vibe.svg +0 -0
  46. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/docs/README.md +0 -0
  47. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/docs/acp-setup.md +0 -0
  48. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/docs/proxy-setup.md +0 -0
  49. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/drydock/__init__.py +0 -0
  50. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/drydock/acp/__init__.py +0 -0
  51. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/drydock/acp/acp_agent_loop.py +0 -0
  52. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/drydock/acp/acp_logger.py +0 -0
  53. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/drydock/acp/entrypoint.py +0 -0
  54. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/drydock/acp/tools/__init__.py +0 -0
  55. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/drydock/acp/tools/base.py +0 -0
  56. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/drydock/acp/tools/builtins/bash.py +0 -0
  57. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/drydock/acp/tools/builtins/read_file.py +0 -0
  58. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/drydock/acp/tools/builtins/search_replace.py +0 -0
  59. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/drydock/acp/tools/builtins/todo.py +0 -0
  60. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/drydock/acp/tools/builtins/write_file.py +0 -0
  61. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/drydock/acp/tools/session_update.py +0 -0
  62. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/drydock/acp/utils.py +0 -0
  63. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/drydock/cli/__init__.py +0 -0
  64. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/drydock/cli/autocompletion/__init__.py +0 -0
  65. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/drydock/cli/autocompletion/base.py +0 -0
  66. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/drydock/cli/autocompletion/path_completion.py +0 -0
  67. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/drydock/cli/autocompletion/slash_command.py +0 -0
  68. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/drydock/cli/cli.py +0 -0
  69. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/drydock/cli/clipboard.py +0 -0
  70. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/drydock/cli/commands.py +0 -0
  71. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/drydock/cli/entrypoint.py +0 -0
  72. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/drydock/cli/history_manager.py +0 -0
  73. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/drydock/cli/plan_offer/adapters/http_whoami_gateway.py +0 -0
  74. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/drydock/cli/plan_offer/decide_plan_offer.py +0 -0
  75. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/drydock/cli/plan_offer/ports/whoami_gateway.py +0 -0
  76. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/drydock/cli/terminal_setup.py +0 -0
  77. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/drydock/cli/textual_ui/__init__.py +0 -0
  78. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/drydock/cli/textual_ui/ansi_markdown.py +0 -0
  79. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/drydock/cli/textual_ui/app.py +0 -0
  80. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/drydock/cli/textual_ui/app.tcss +0 -0
  81. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/drydock/cli/textual_ui/external_editor.py +0 -0
  82. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/drydock/cli/textual_ui/handlers/__init__.py +0 -0
  83. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/drydock/cli/textual_ui/handlers/event_handler.py +0 -0
  84. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/drydock/cli/textual_ui/notifications/__init__.py +0 -0
  85. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/drydock/cli/textual_ui/notifications/adapters/__init__.py +0 -0
  86. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/drydock/cli/textual_ui/notifications/adapters/textual_notification_adapter.py +0 -0
  87. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/drydock/cli/textual_ui/notifications/ports/__init__.py +0 -0
  88. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/drydock/cli/textual_ui/notifications/ports/notification_port.py +0 -0
  89. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/drydock/cli/textual_ui/widgets/__init__.py +0 -0
  90. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/drydock/cli/textual_ui/widgets/approval_app.py +0 -0
  91. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/drydock/cli/textual_ui/widgets/banner/banner.py +0 -0
  92. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/drydock/cli/textual_ui/widgets/banner/petit_chat.py +0 -0
  93. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/drydock/cli/textual_ui/widgets/braille_renderer.py +0 -0
  94. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/drydock/cli/textual_ui/widgets/chat_input/__init__.py +0 -0
  95. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/drydock/cli/textual_ui/widgets/chat_input/body.py +0 -0
  96. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/drydock/cli/textual_ui/widgets/chat_input/completion_manager.py +0 -0
  97. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/drydock/cli/textual_ui/widgets/chat_input/completion_popup.py +0 -0
  98. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/drydock/cli/textual_ui/widgets/chat_input/container.py +0 -0
  99. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/drydock/cli/textual_ui/widgets/chat_input/text_area.py +0 -0
  100. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/drydock/cli/textual_ui/widgets/compact.py +0 -0
  101. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/drydock/cli/textual_ui/widgets/config_app.py +0 -0
  102. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/drydock/cli/textual_ui/widgets/context_progress.py +0 -0
  103. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/drydock/cli/textual_ui/widgets/load_more.py +0 -0
  104. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/drydock/cli/textual_ui/widgets/loading.py +0 -0
  105. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/drydock/cli/textual_ui/widgets/messages.py +0 -0
  106. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/drydock/cli/textual_ui/widgets/no_markup_static.py +0 -0
  107. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/drydock/cli/textual_ui/widgets/path_display.py +0 -0
  108. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/drydock/cli/textual_ui/widgets/proxy_setup_app.py +0 -0
  109. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/drydock/cli/textual_ui/widgets/question_app.py +0 -0
  110. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/drydock/cli/textual_ui/widgets/session_picker.py +0 -0
  111. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/drydock/cli/textual_ui/widgets/spinner.py +0 -0
  112. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/drydock/cli/textual_ui/widgets/status_message.py +0 -0
  113. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/drydock/cli/textual_ui/widgets/teleport_message.py +0 -0
  114. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/drydock/cli/textual_ui/widgets/tool_widgets.py +0 -0
  115. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/drydock/cli/textual_ui/widgets/tools.py +0 -0
  116. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/drydock/cli/textual_ui/widgets/vscode_compat.py +0 -0
  117. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/drydock/cli/textual_ui/windowing/__init__.py +0 -0
  118. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/drydock/cli/textual_ui/windowing/history.py +0 -0
  119. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/drydock/cli/textual_ui/windowing/history_windowing.py +0 -0
  120. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/drydock/cli/textual_ui/windowing/state.py +0 -0
  121. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/drydock/cli/update_notifier/__init__.py +0 -0
  122. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/drydock/cli/update_notifier/adapters/filesystem_update_cache_repository.py +0 -0
  123. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/drydock/cli/update_notifier/adapters/github_update_gateway.py +0 -0
  124. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/drydock/cli/update_notifier/adapters/pypi_update_gateway.py +0 -0
  125. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/drydock/cli/update_notifier/ports/update_cache_repository.py +0 -0
  126. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/drydock/cli/update_notifier/ports/update_gateway.py +0 -0
  127. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/drydock/cli/update_notifier/update.py +0 -0
  128. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/drydock/cli/update_notifier/whats_new.py +0 -0
  129. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/drydock/core/__init__.py +0 -0
  130. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/drydock/core/agent_loop.py +0 -0
  131. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/drydock/core/agents/__init__.py +0 -0
  132. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/drydock/core/agents/manager.py +0 -0
  133. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/drydock/core/auth/__init__.py +0 -0
  134. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/drydock/core/auth/crypto.py +0 -0
  135. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/drydock/core/auth/github.py +0 -0
  136. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/drydock/core/autocompletion/__init__.py +0 -0
  137. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/drydock/core/autocompletion/completers.py +0 -0
  138. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/drydock/core/autocompletion/file_indexer/__init__.py +0 -0
  139. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/drydock/core/autocompletion/file_indexer/ignore_rules.py +0 -0
  140. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/drydock/core/autocompletion/file_indexer/indexer.py +0 -0
  141. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/drydock/core/autocompletion/file_indexer/store.py +0 -0
  142. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/drydock/core/autocompletion/file_indexer/watcher.py +0 -0
  143. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/drydock/core/autocompletion/fuzzy.py +0 -0
  144. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/drydock/core/autocompletion/path_prompt.py +0 -0
  145. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/drydock/core/autocompletion/path_prompt_adapter.py +0 -0
  146. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/drydock/core/config/__init__.py +0 -0
  147. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/drydock/core/config/_settings.py +0 -0
  148. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/drydock/core/config/harness_files/__init__.py +0 -0
  149. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/drydock/core/config/harness_files/_harness_manager.py +0 -0
  150. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/drydock/core/config/harness_files/_paths.py +0 -0
  151. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/drydock/core/consultant.py +0 -0
  152. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/drydock/core/drydock_states.py +0 -0
  153. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/drydock/core/llm/__init__.py +0 -0
  154. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/drydock/core/llm/backend/anthropic.py +0 -0
  155. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/drydock/core/llm/backend/base.py +0 -0
  156. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/drydock/core/llm/backend/factory.py +0 -0
  157. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/drydock/core/llm/backend/generic.py +0 -0
  158. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/drydock/core/llm/backend/mistral.py +0 -0
  159. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/drydock/core/llm/backend/reasoning_adapter.py +0 -0
  160. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/drydock/core/llm/backend/vertex.py +0 -0
  161. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/drydock/core/llm/exceptions.py +0 -0
  162. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/drydock/core/llm/format.py +0 -0
  163. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/drydock/core/llm/message_utils.py +0 -0
  164. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/drydock/core/llm/types.py +0 -0
  165. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/drydock/core/logger.py +0 -0
  166. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/drydock/core/middleware.py +0 -0
  167. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/drydock/core/output_formatters.py +0 -0
  168. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/drydock/core/paths/__init__.py +0 -0
  169. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/drydock/core/paths/_local_config_walk.py +0 -0
  170. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/drydock/core/paths/_vibe_home.py +0 -0
  171. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/drydock/core/paths/conventions.py +0 -0
  172. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/drydock/core/plan_session.py +0 -0
  173. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/drydock/core/programmatic.py +0 -0
  174. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/drydock/core/prompts/__init__.py +0 -0
  175. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/drydock/core/prompts/cli.md +0 -0
  176. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/drydock/core/prompts/compact.md +0 -0
  177. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/drydock/core/prompts/dangerous_directory.md +0 -0
  178. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/drydock/core/prompts/diagnostic.md +0 -0
  179. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/drydock/core/prompts/explore.md +0 -0
  180. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/drydock/core/prompts/planner.md +0 -0
  181. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/drydock/core/prompts/project_context.md +0 -0
  182. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/drydock/core/prompts/tests.md +0 -0
  183. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/drydock/core/proxy_setup.py +0 -0
  184. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/drydock/core/session/session_loader.py +0 -0
  185. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/drydock/core/session/session_logger.py +0 -0
  186. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/drydock/core/session/session_migration.py +0 -0
  187. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/drydock/core/session/state_file.py +0 -0
  188. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/drydock/core/skills/__init__.py +0 -0
  189. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/drydock/core/skills/manager.py +0 -0
  190. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/drydock/core/skills/parser.py +0 -0
  191. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/drydock/core/slug.py +0 -0
  192. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/drydock/core/system_prompt.py +0 -0
  193. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/drydock/core/telemetry/__init__.py +0 -0
  194. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/drydock/core/telemetry/send.py +0 -0
  195. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/drydock/core/teleport/errors.py +0 -0
  196. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/drydock/core/teleport/git.py +0 -0
  197. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/drydock/core/teleport/nuage.py +0 -0
  198. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/drydock/core/teleport/teleport.py +0 -0
  199. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/drydock/core/teleport/types.py +0 -0
  200. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/drydock/core/tools/base.py +0 -0
  201. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/drydock/core/tools/builtins/ask_user_question.py +0 -0
  202. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/drydock/core/tools/builtins/bash.py +0 -0
  203. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/drydock/core/tools/builtins/exit_plan_mode.py +0 -0
  204. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/drydock/core/tools/builtins/grep.py +0 -0
  205. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/drydock/core/tools/builtins/prompts/__init__.py +0 -0
  206. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/drydock/core/tools/builtins/prompts/ask_user_question.md +0 -0
  207. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/drydock/core/tools/builtins/prompts/bash.md +0 -0
  208. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/drydock/core/tools/builtins/prompts/grep.md +0 -0
  209. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/drydock/core/tools/builtins/prompts/read_file.md +0 -0
  210. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/drydock/core/tools/builtins/prompts/search_replace.md +0 -0
  211. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/drydock/core/tools/builtins/prompts/swe_bench.md +0 -0
  212. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/drydock/core/tools/builtins/prompts/task.md +0 -0
  213. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/drydock/core/tools/builtins/prompts/todo.md +0 -0
  214. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/drydock/core/tools/builtins/prompts/webfetch.md +0 -0
  215. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/drydock/core/tools/builtins/prompts/websearch.md +0 -0
  216. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/drydock/core/tools/builtins/prompts/write_file.md +0 -0
  217. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/drydock/core/tools/builtins/read_file.py +0 -0
  218. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/drydock/core/tools/builtins/search_replace.py +0 -0
  219. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/drydock/core/tools/builtins/task.py +0 -0
  220. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/drydock/core/tools/builtins/todo.py +0 -0
  221. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/drydock/core/tools/builtins/webfetch.py +0 -0
  222. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/drydock/core/tools/builtins/websearch.py +0 -0
  223. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/drydock/core/tools/builtins/write_file.py +0 -0
  224. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/drydock/core/tools/injection_guard.py +0 -0
  225. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/drydock/core/tools/manager.py +0 -0
  226. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/drydock/core/tools/mcp/__init__.py +0 -0
  227. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/drydock/core/tools/mcp/registry.py +0 -0
  228. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/drydock/core/tools/mcp/tools.py +0 -0
  229. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/drydock/core/tools/mcp_sampling.py +0 -0
  230. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/drydock/core/tools/ui.py +0 -0
  231. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/drydock/core/tools/utils.py +0 -0
  232. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/drydock/core/trusted_folders.py +0 -0
  233. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/drydock/core/types.py +0 -0
  234. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/drydock/core/utils.py +0 -0
  235. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/drydock/setup/onboarding/__init__.py +0 -0
  236. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/drydock/setup/onboarding/base.py +0 -0
  237. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/drydock/setup/onboarding/onboarding.tcss +0 -0
  238. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/drydock/setup/onboarding/screens/__init__.py +0 -0
  239. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/drydock/setup/onboarding/screens/api_key.py +0 -0
  240. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/drydock/setup/onboarding/screens/welcome.py +0 -0
  241. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/drydock/setup/trusted_folders/trust_folder_dialog.py +0 -0
  242. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/drydock/setup/trusted_folders/trust_folder_dialog.tcss +0 -0
  243. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/drydock/skills/__init__.py +0 -0
  244. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/drydock/skills/create-presentation/SKILL.md +0 -0
  245. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/drydock/skills/deep-research/SKILL.md +0 -0
  246. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/drydock/skills/investigate/SKILL.md +0 -0
  247. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/drydock/skills/review/SKILL.md +0 -0
  248. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/drydock/skills/ship/SKILL.md +0 -0
  249. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/drydock/whats_new.md +0 -0
  250. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/drydock-acp.spec +0 -0
  251. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/drydock_terms.md +0 -0
  252. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/flake.lock +0 -0
  253. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/flake.nix +0 -0
  254. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/scripts/README.md +0 -0
  255. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/scripts/backup.sh +0 -0
  256. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/scripts/bump_version.py +0 -0
  257. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/scripts/deploy_to_github.sh +0 -0
  258. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/scripts/install.sh +0 -0
  259. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/scripts/prepare_release.py +0 -0
  260. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/scripts/publish_to_pypi.sh +0 -0
  261. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/tests/__init__.py +0 -0
  262. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/tests/acp/conftest.py +0 -0
  263. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/tests/acp/test_acp.py +0 -0
  264. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/tests/acp/test_agent_thought.py +0 -0
  265. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/tests/acp/test_bash.py +0 -0
  266. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/tests/acp/test_compact_session_updates.py +0 -0
  267. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/tests/acp/test_content.py +0 -0
  268. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/tests/acp/test_initialize.py +0 -0
  269. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/tests/acp/test_list_sessions.py +0 -0
  270. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/tests/acp/test_load_session.py +0 -0
  271. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/tests/acp/test_multi_session.py +0 -0
  272. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/tests/acp/test_new_session.py +0 -0
  273. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/tests/acp/test_proxy_setup_acp.py +0 -0
  274. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/tests/acp/test_read_file.py +0 -0
  275. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/tests/acp/test_search_replace.py +0 -0
  276. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/tests/acp/test_set_config_option.py +0 -0
  277. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/tests/acp/test_set_mode.py +0 -0
  278. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/tests/acp/test_set_model.py +0 -0
  279. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/tests/acp/test_tool_call_session_update.py +0 -0
  280. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/tests/acp/test_utils.py +0 -0
  281. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/tests/acp/test_write_file.py +0 -0
  282. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/tests/autocompletion/test_file_indexer.py +0 -0
  283. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/tests/autocompletion/test_fuzzy.py +0 -0
  284. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/tests/autocompletion/test_path_completer_fuzzy.py +0 -0
  285. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/tests/autocompletion/test_path_completer_recursive.py +0 -0
  286. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/tests/autocompletion/test_path_completion_controller.py +0 -0
  287. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/tests/autocompletion/test_path_prompt_transformer.py +0 -0
  288. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/tests/autocompletion/test_slash_command_controller.py +0 -0
  289. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/tests/autocompletion/test_ui_chat_autocompletion.py +0 -0
  290. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/tests/backend/__init__.py +0 -0
  291. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/tests/backend/data/__init__.py +0 -0
  292. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/tests/backend/data/fireworks.py +0 -0
  293. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/tests/backend/data/mistral.py +0 -0
  294. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/tests/backend/test_anthropic_adapter.py +0 -0
  295. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/tests/backend/test_backend.py +0 -0
  296. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/tests/backend/test_reasoning_adapter.py +0 -0
  297. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/tests/backend/test_vertex_anthropic_adapter.py +0 -0
  298. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/tests/cli/plan_offer/adapters/fake_whoami_gateway.py +0 -0
  299. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/tests/cli/plan_offer/test_decide_plan_offer.py +0 -0
  300. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/tests/cli/plan_offer/test_http_whoami_gateway.py +0 -0
  301. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/tests/cli/test_bell_notifications.py +0 -0
  302. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/tests/cli/test_braille_renderer.py +0 -0
  303. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/tests/cli/test_clipboard.py +0 -0
  304. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/tests/cli/test_commands.py +0 -0
  305. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/tests/cli/test_copy_shortcuts.py +0 -0
  306. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/tests/cli/test_external_editor.py +0 -0
  307. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/tests/cli/test_no_markup_static.py +0 -0
  308. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/tests/cli/test_question_app.py +0 -0
  309. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/tests/cli/test_spinner.py +0 -0
  310. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/tests/cli/test_switching_mode.py +0 -0
  311. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/tests/cli/test_ui_clipboard_notifications.py +0 -0
  312. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/tests/cli/test_ui_session_incremental_renderer.py +0 -0
  313. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/tests/cli/test_ui_session_resume.py +0 -0
  314. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/tests/cli/test_ui_skill_dispatch.py +0 -0
  315. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/tests/cli/textual_ui/__init__.py +0 -0
  316. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/tests/cli/textual_ui/test_session_picker.py +0 -0
  317. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/tests/conftest.py +0 -0
  318. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/tests/core/test_agents.py +0 -0
  319. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/tests/core/test_auth_crypto.py +0 -0
  320. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/tests/core/test_auth_github.py +0 -0
  321. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/tests/core/test_config_load_dotenv.py +0 -0
  322. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/tests/core/test_config_paths.py +0 -0
  323. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/tests/core/test_config_resolution.py +0 -0
  324. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/tests/core/test_file_logging.py +0 -0
  325. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/tests/core/test_plan_session.py +0 -0
  326. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/tests/core/test_proxy_setup.py +0 -0
  327. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/tests/core/test_slug.py +0 -0
  328. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/tests/core/test_telemetry_send.py +0 -0
  329. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/tests/core/test_teleport_git.py +0 -0
  330. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/tests/core/test_teleport_nuage.py +0 -0
  331. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/tests/core/test_teleport_service.py +0 -0
  332. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/tests/core/test_trusted_folders.py +0 -0
  333. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/tests/core/test_utils.py +0 -0
  334. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/tests/e2e/common.py +0 -0
  335. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/tests/e2e/conftest.py +0 -0
  336. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/tests/e2e/mock_server.py +0 -0
  337. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/tests/e2e/test_cli_tui_onboarding.py +0 -0
  338. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/tests/e2e/test_cli_tui_streaming.py +0 -0
  339. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/tests/e2e/test_cli_tui_tool_approval.py +0 -0
  340. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/tests/mock/__init__.py +0 -0
  341. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/tests/mock/mock_backend_factory.py +0 -0
  342. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/tests/mock/mock_entrypoint.py +0 -0
  343. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/tests/mock/utils.py +0 -0
  344. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/tests/onboarding/test_run_onboarding.py +0 -0
  345. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/tests/onboarding/test_ui_onboarding.py +0 -0
  346. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/tests/session/test_session_loader.py +0 -0
  347. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/tests/session/test_session_logger.py +0 -0
  348. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/tests/session/test_session_migration.py +0 -0
  349. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/tests/skills/conftest.py +0 -0
  350. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/tests/skills/test_manager.py +0 -0
  351. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/tests/skills/test_models.py +0 -0
  352. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/tests/skills/test_parser.py +0 -0
  353. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/tests/snapshots/__snapshots__/test_ui_snapshot_ask_user_question/test_snapshot_ask_user_question_collapsed.svg +0 -0
  354. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/tests/snapshots/__snapshots__/test_ui_snapshot_ask_user_question/test_snapshot_ask_user_question_expanded.svg +0 -0
  355. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/tests/snapshots/__snapshots__/test_ui_snapshot_basic_conversation/test_snapshot_shows_basic_conversation.svg +0 -0
  356. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/tests/snapshots/__snapshots__/test_ui_snapshot_code_block_horizontal_scrolling/test_snapshot_allows_horizontal_scrolling_for_long_code_blocks.svg +0 -0
  357. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/tests/snapshots/__snapshots__/test_ui_snapshot_empty_assistant_before_reasoning/test_snapshot_empty_assistant_removed_when_reasoning_starts.svg +0 -0
  358. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/tests/snapshots/__snapshots__/test_ui_snapshot_modes/test_snapshot_cycle_to_accept_edits_mode.svg +0 -0
  359. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/tests/snapshots/__snapshots__/test_ui_snapshot_modes/test_snapshot_cycle_to_auto_approve_mode.svg +0 -0
  360. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/tests/snapshots/__snapshots__/test_ui_snapshot_modes/test_snapshot_cycle_to_plan_mode.svg +0 -0
  361. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/tests/snapshots/__snapshots__/test_ui_snapshot_modes/test_snapshot_cycle_wraps_to_default.svg +0 -0
  362. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/tests/snapshots/__snapshots__/test_ui_snapshot_modes/test_snapshot_default_mode.svg +0 -0
  363. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/tests/snapshots/__snapshots__/test_ui_snapshot_parallel_tool_calls/test_snapshot_parallel_tool_calls_pending.svg +0 -0
  364. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/tests/snapshots/__snapshots__/test_ui_snapshot_parallel_tool_calls/test_snapshot_parallel_tool_calls_resolved.svg +0 -0
  365. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/tests/snapshots/__snapshots__/test_ui_snapshot_proxy_setup/test_snapshot_proxy_setup_cancel_discards_changes.svg +0 -0
  366. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/tests/snapshots/__snapshots__/test_ui_snapshot_proxy_setup/test_snapshot_proxy_setup_edit_existing_values.svg +0 -0
  367. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/tests/snapshots/__snapshots__/test_ui_snapshot_proxy_setup/test_snapshot_proxy_setup_initial_empty.svg +0 -0
  368. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/tests/snapshots/__snapshots__/test_ui_snapshot_proxy_setup/test_snapshot_proxy_setup_initial_with_values.svg +0 -0
  369. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/tests/snapshots/__snapshots__/test_ui_snapshot_proxy_setup/test_snapshot_proxy_setup_save_error.svg +0 -0
  370. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/tests/snapshots/__snapshots__/test_ui_snapshot_proxy_setup/test_snapshot_proxy_setup_save_new_values.svg +0 -0
  371. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_question_answer_first_advance.svg +0 -0
  372. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_question_first_answered_checkmark.svg +0 -0
  373. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_question_initial.svg +0 -0
  374. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_question_navigate_left_wraps.svg +0 -0
  375. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_question_navigate_right.svg +0 -0
  376. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_question_tab_to_second.svg +0 -0
  377. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_select_initial.svg +0 -0
  378. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_select_mixed_selection.svg +0 -0
  379. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_select_navigate_to_submit.svg +0 -0
  380. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_select_other_with_text.svg +0 -0
  381. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_select_toggle_first.svg +0 -0
  382. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_select_toggle_multiple.svg +0 -0
  383. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_select_untoggle.svg +0 -0
  384. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_question_app_initial.svg +0 -0
  385. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_question_app_navigate_down.svg +0 -0
  386. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_question_app_navigate_to_other.svg +0 -0
  387. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_question_app_navigate_to_third_option.svg +0 -0
  388. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_question_app_navigate_up_wraps.svg +0 -0
  389. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_question_app_other_typing.svg +0 -0
  390. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/tests/snapshots/__snapshots__/test_ui_snapshot_reasoning_content/test_snapshot_buffered_reasoning_yields_before_content.svg +0 -0
  391. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/tests/snapshots/__snapshots__/test_ui_snapshot_reasoning_content/test_snapshot_shows_interleaved_reasoning.svg +0 -0
  392. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/tests/snapshots/__snapshots__/test_ui_snapshot_reasoning_content/test_snapshot_shows_reasoning_content.svg +0 -0
  393. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/tests/snapshots/__snapshots__/test_ui_snapshot_reasoning_content/test_snapshot_shows_reasoning_content_expanded.svg +0 -0
  394. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/tests/snapshots/__snapshots__/test_ui_snapshot_release_update_notification/test_snapshot_shows_release_update_notification.svg +0 -0
  395. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/tests/snapshots/__snapshots__/test_ui_snapshot_session_resume/test_snapshot_shows_resumed_session_messages.svg +0 -0
  396. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/tests/snapshots/__snapshots__/test_ui_snapshot_streaming_tool_call/test_snapshot_tool_call_partial.svg +0 -0
  397. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/tests/snapshots/__snapshots__/test_ui_snapshot_streaming_tool_call/test_snapshot_tool_call_updated.svg +0 -0
  398. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_push_confirmation_cancel_selected.svg +0 -0
  399. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_push_confirmation_multiple_commits.svg +0 -0
  400. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_push_confirmation_single_commit.svg +0 -0
  401. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_status_auth_complete.svg +0 -0
  402. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_status_auth_required.svg +0 -0
  403. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_status_checking_git.svg +0 -0
  404. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_status_complete.svg +0 -0
  405. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_status_error.svg +0 -0
  406. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_status_pushing.svg +0 -0
  407. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_status_sending_token.svg +0 -0
  408. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_status_starting_workflow.svg +0 -0
  409. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/tests/snapshots/__snapshots__/test_ui_snapshot_whats_new/test_snapshot_shows_no_plan_message.svg +0 -0
  410. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/tests/snapshots/__snapshots__/test_ui_snapshot_whats_new/test_snapshot_shows_switch_message.svg +0 -0
  411. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/tests/snapshots/__snapshots__/test_ui_snapshot_whats_new/test_snapshot_shows_upgrade_message.svg +0 -0
  412. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/tests/snapshots/__snapshots__/test_ui_snapshot_whats_new/test_snapshot_shows_whats_new_message.svg +0 -0
  413. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/tests/snapshots/base_snapshot_test_app.py +0 -0
  414. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/tests/snapshots/conftest.py +0 -0
  415. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/tests/snapshots/snap_compare.py +0 -0
  416. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/tests/snapshots/test_ui_snapshot_ask_user_question.py +0 -0
  417. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/tests/snapshots/test_ui_snapshot_basic_conversation.py +0 -0
  418. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/tests/snapshots/test_ui_snapshot_code_block_horizontal_scrolling.py +0 -0
  419. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/tests/snapshots/test_ui_snapshot_empty_assistant_before_reasoning.py +0 -0
  420. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/tests/snapshots/test_ui_snapshot_modes.py +0 -0
  421. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/tests/snapshots/test_ui_snapshot_parallel_tool_calls.py +0 -0
  422. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/tests/snapshots/test_ui_snapshot_proxy_setup.py +0 -0
  423. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/tests/snapshots/test_ui_snapshot_question_app.py +0 -0
  424. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/tests/snapshots/test_ui_snapshot_reasoning_content.py +0 -0
  425. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/tests/snapshots/test_ui_snapshot_release_update_notification.py +0 -0
  426. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/tests/snapshots/test_ui_snapshot_session_resume.py +0 -0
  427. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/tests/snapshots/test_ui_snapshot_streaming_tool_call.py +0 -0
  428. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/tests/snapshots/test_ui_snapshot_teleport.py +0 -0
  429. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/tests/snapshots/test_ui_snapshot_whats_new.py +0 -0
  430. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/tests/stubs/fake_backend.py +0 -0
  431. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/tests/stubs/fake_client.py +0 -0
  432. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/tests/stubs/fake_tool.py +0 -0
  433. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/tests/test_agent_auto_compact.py +0 -0
  434. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/tests/test_agent_backend.py +0 -0
  435. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/tests/test_agent_observer_streaming.py +0 -0
  436. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/tests/test_agent_stats.py +0 -0
  437. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/tests/test_agent_tasks.py +0 -0
  438. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/tests/test_agent_tool_call.py +0 -0
  439. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/tests/test_agents.py +0 -0
  440. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/tests/test_cli_programmatic_preload.py +0 -0
  441. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/tests/test_current_bugs.py +0 -0
  442. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/tests/test_drydock_regression.py +0 -0
  443. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/tests/test_drydock_tasks.py +0 -0
  444. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/tests/test_history_manager.py +0 -0
  445. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/tests/test_integration.py +0 -0
  446. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/tests/test_loop_detection.py +0 -0
  447. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/tests/test_message_id.py +0 -0
  448. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/tests/test_message_merging.py +0 -0
  449. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/tests/test_middleware.py +0 -0
  450. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/tests/test_real_failures.py +0 -0
  451. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/tests/test_real_issues.py +0 -0
  452. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/tests/test_reasoning_content.py +0 -0
  453. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/tests/test_system_prompt.py +0 -0
  454. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/tests/test_tagged_text.py +0 -0
  455. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/tests/test_ui_external_editor.py +0 -0
  456. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/tests/test_ui_input_history.py +0 -0
  457. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/tests/test_user_issues.py +0 -0
  458. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/tests/tools/test_ask_user_question.py +0 -0
  459. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/tests/tools/test_bash.py +0 -0
  460. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/tests/tools/test_exit_plan_mode.py +0 -0
  461. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/tests/tools/test_grep.py +0 -0
  462. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/tests/tools/test_invoke_context.py +0 -0
  463. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/tests/tools/test_manager_get_tool_config.py +0 -0
  464. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/tests/tools/test_mcp.py +0 -0
  465. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/tests/tools/test_mcp_sampling.py +0 -0
  466. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/tests/tools/test_task.py +0 -0
  467. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/tests/tools/test_ui_bash_execution.py +0 -0
  468. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/tests/tools/test_webfetch.py +0 -0
  469. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/tests/tools/test_websearch.py +0 -0
  470. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/tests/update_notifier/adapters/fake_update_cache_repository.py +0 -0
  471. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/tests/update_notifier/adapters/fake_update_gateway.py +0 -0
  472. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/tests/update_notifier/test_do_update.py +0 -0
  473. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/tests/update_notifier/test_filesystem_update_cache_repository.py +0 -0
  474. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/tests/update_notifier/test_github_update_gateway.py +0 -0
  475. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/tests/update_notifier/test_pypi_update_gateway.py +0 -0
  476. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/tests/update_notifier/test_ui_update_notification.py +0 -0
  477. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/tests/update_notifier/test_update_use_case.py +0 -0
  478. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/tests/update_notifier/test_whats_new.py +0 -0
  479. {drydock_cli-0.8.2 → drydock_cli-1.0.0}/uv.lock +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: drydock-cli
3
- Version: 0.8.2
3
+ Version: 1.0.0
4
4
  Summary: Drydock — nautical CLI coding agent
5
5
  Project-URL: Homepage, https://github.com/fbobe321/drydock
6
6
  Project-URL: Repository, https://github.com/fbobe321/drydock
@@ -53,11 +53,22 @@ class AgentProfile:
53
53
  safety: AgentSafety
54
54
  agent_type: AgentType = AgentType.AGENT
55
55
  overrides: dict[str, Any] = field(default_factory=dict)
56
+ # New fields for feature parity with Claude Code
57
+ model: str = "" # Per-subagent model selection (e.g., "gemini-2.5-pro")
58
+ max_turns: int | None = None # Per-subagent turn limit
59
+ background: bool = False # Run in background (non-blocking)
60
+ isolation: str = "" # "worktree" for git worktree isolation
61
+ initial_prompt: str = "" # Auto-run this prompt on start
62
+ allowed_tools: list[str] = field(default_factory=list) # Restrict tools
63
+ hooks: list[str] = field(default_factory=list) # Hook configs
56
64
 
57
65
  def apply_to_config(self, base: VibeConfig) -> VibeConfig:
58
66
  from drydock.core.config import VibeConfig as VC
59
67
 
60
68
  merged = _deep_merge(base.model_dump(), self.overrides)
69
+ # Apply per-subagent model if set
70
+ if self.model:
71
+ merged["active_model"] = self.model
61
72
  return VC.model_validate(merged)
62
73
 
63
74
  @classmethod
@@ -70,9 +81,45 @@ class AgentProfile:
70
81
  description=data.pop("description", ""),
71
82
  safety=AgentSafety(data.pop("safety", AgentSafety.NEUTRAL)),
72
83
  agent_type=AgentType(data.pop("agent_type", AgentType.AGENT)),
84
+ model=data.pop("model", ""),
85
+ max_turns=data.pop("max_turns", None),
86
+ background=data.pop("background", False),
87
+ isolation=data.pop("isolation", ""),
88
+ initial_prompt=data.pop("initial_prompt", ""),
89
+ allowed_tools=data.pop("allowed_tools", []),
90
+ hooks=data.pop("hooks", []),
73
91
  overrides=data,
74
92
  )
75
93
 
94
+ @classmethod
95
+ def from_markdown(cls, path: Path) -> AgentProfile:
96
+ """Load agent profile from Markdown with YAML frontmatter."""
97
+ import yaml
98
+ content = path.read_text(encoding="utf-8")
99
+ if not content.startswith("---"):
100
+ raise ValueError(f"No YAML frontmatter in {path}")
101
+ parts = content.split("---", 2)
102
+ if len(parts) < 3:
103
+ raise ValueError(f"Invalid frontmatter in {path}")
104
+ meta = yaml.safe_load(parts[1]) or {}
105
+ body = parts[2].strip()
106
+
107
+ return cls(
108
+ name=meta.get("name", path.stem),
109
+ display_name=meta.get("display_name", meta.get("name", path.stem)),
110
+ description=meta.get("description", body[:200]),
111
+ safety=AgentSafety(meta.get("safety", AgentSafety.NEUTRAL)),
112
+ agent_type=AgentType(meta.get("agent_type", AgentType.SUBAGENT)),
113
+ model=meta.get("model", ""),
114
+ max_turns=meta.get("max_turns"),
115
+ background=meta.get("background", False),
116
+ isolation=meta.get("isolation", ""),
117
+ initial_prompt=meta.get("initial_prompt", ""),
118
+ allowed_tools=meta.get("allowed_tools") or meta.get("allowed-tools") or [],
119
+ hooks=meta.get("hooks", []),
120
+ overrides=meta.get("overrides", {}),
121
+ )
122
+
76
123
 
77
124
  CHAT_AGENT_TOOLS = ["grep", "read_file", "ask_user_question", "task"]
78
125
  DIAGNOSTIC_AGENT_TOOLS = ["grep", "read_file", "bash"]
@@ -0,0 +1,179 @@
1
+ """Hook system for DryDock lifecycle events.
2
+
3
+ Hooks run shell scripts or Python callables at specific points
4
+ in the agent's workflow. They are deterministic — they always run,
5
+ unlike CLAUDE.md which is advisory.
6
+
7
+ Hook events:
8
+ - PreToolUse: Before any tool executes (can block with "deny")
9
+ - PostToolUse: After a tool completes
10
+ - SessionStart: When a new session begins
11
+ - SessionEnd: When session ends
12
+ - PreEdit: Before file write/edit (can block destructive patterns)
13
+ - PostEdit: After file is written/edited
14
+
15
+ Configure in ~/.drydock/hooks.json or .drydock/hooks.json:
16
+ {
17
+ "hooks": [
18
+ {
19
+ "event": "PreToolUse",
20
+ "command": "python3 /path/to/guard.py",
21
+ "tools": ["bash", "write_file"]
22
+ }
23
+ ]
24
+ }
25
+ """
26
+
27
+ from __future__ import annotations
28
+
29
+ import json
30
+ import logging
31
+ import subprocess
32
+ from dataclasses import dataclass, field
33
+ from enum import StrEnum, auto
34
+ from pathlib import Path
35
+ from typing import Any
36
+
37
+ logger = logging.getLogger(__name__)
38
+
39
+
40
+ class HookEvent(StrEnum):
41
+ PRE_TOOL_USE = auto()
42
+ POST_TOOL_USE = auto()
43
+ SESSION_START = auto()
44
+ SESSION_END = auto()
45
+ PRE_EDIT = auto()
46
+ POST_EDIT = auto()
47
+
48
+
49
+ class HookDecision(StrEnum):
50
+ ALLOW = auto()
51
+ DENY = auto()
52
+ ASK = auto()
53
+
54
+
55
+ @dataclass
56
+ class HookResult:
57
+ decision: HookDecision = HookDecision.ALLOW
58
+ message: str = ""
59
+
60
+
61
+ @dataclass
62
+ class HookConfig:
63
+ event: HookEvent
64
+ command: str
65
+ tools: list[str] = field(default_factory=list) # Empty = all tools
66
+ timeout: int = 10
67
+
68
+
69
+ class HookManager:
70
+ """Manages and executes lifecycle hooks."""
71
+
72
+ def __init__(self) -> None:
73
+ self._hooks: list[HookConfig] = []
74
+ self._loaded = False
75
+
76
+ def load_hooks(self, config_dir: Path | None = None) -> None:
77
+ """Load hooks from config files."""
78
+ if self._loaded:
79
+ return
80
+ self._loaded = True
81
+
82
+ search_paths = []
83
+ if config_dir:
84
+ search_paths.append(config_dir / "hooks.json")
85
+
86
+ # Check project and user dirs
87
+ project_hooks = Path.cwd() / ".drydock" / "hooks.json"
88
+ if project_hooks.exists():
89
+ search_paths.insert(0, project_hooks)
90
+
91
+ try:
92
+ from drydock.core.paths import VIBE_HOME
93
+ user_hooks = VIBE_HOME.path / "hooks.json"
94
+ if user_hooks.exists():
95
+ search_paths.append(user_hooks)
96
+ except Exception:
97
+ pass
98
+
99
+ for path in search_paths:
100
+ try:
101
+ if path.exists():
102
+ data = json.loads(path.read_text())
103
+ for h in data.get("hooks", []):
104
+ self._hooks.append(HookConfig(
105
+ event=HookEvent(h["event"].lower().replace("-", "_")),
106
+ command=h["command"],
107
+ tools=h.get("tools", []),
108
+ timeout=h.get("timeout", 10),
109
+ ))
110
+ logger.info("Loaded %d hooks from %s", len(data.get("hooks", [])), path)
111
+ except Exception as e:
112
+ logger.warning("Failed to load hooks from %s: %s", path, e)
113
+
114
+ def get_hooks(self, event: HookEvent, tool_name: str = "") -> list[HookConfig]:
115
+ """Get hooks matching an event and optional tool name."""
116
+ return [
117
+ h for h in self._hooks
118
+ if h.event == event
119
+ and (not h.tools or tool_name in h.tools)
120
+ ]
121
+
122
+ async def run_hooks(
123
+ self, event: HookEvent, tool_name: str = "", context: dict[str, Any] | None = None
124
+ ) -> HookResult:
125
+ """Execute all hooks for an event. Returns the most restrictive result."""
126
+ hooks = self.get_hooks(event, tool_name)
127
+ if not hooks:
128
+ return HookResult()
129
+
130
+ most_restrictive = HookResult()
131
+
132
+ for hook in hooks:
133
+ try:
134
+ result = await self._execute_hook(hook, context or {})
135
+ if result.decision == HookDecision.DENY:
136
+ return result # Deny immediately
137
+ if result.decision == HookDecision.ASK and most_restrictive.decision == HookDecision.ALLOW:
138
+ most_restrictive = result
139
+ except Exception as e:
140
+ logger.warning("Hook %s failed: %s", hook.command, e)
141
+
142
+ return most_restrictive
143
+
144
+ async def _execute_hook(self, hook: HookConfig, context: dict[str, Any]) -> HookResult:
145
+ """Execute a single hook command."""
146
+ import asyncio
147
+
148
+ env = {
149
+ **__import__("os").environ,
150
+ "DRYDOCK_HOOK_EVENT": hook.event.value,
151
+ "DRYDOCK_HOOK_CONTEXT": json.dumps(context, default=str),
152
+ }
153
+
154
+ try:
155
+ proc = await asyncio.create_subprocess_shell(
156
+ hook.command,
157
+ stdout=asyncio.subprocess.PIPE,
158
+ stderr=asyncio.subprocess.PIPE,
159
+ env=env,
160
+ )
161
+ stdout, stderr = await asyncio.wait_for(proc.communicate(), timeout=hook.timeout)
162
+
163
+ output = stdout.decode("utf-8", errors="replace").strip()
164
+
165
+ # Parse output for decision
166
+ if "DENY" in output.upper():
167
+ return HookResult(decision=HookDecision.DENY, message=output)
168
+ if "ASK" in output.upper():
169
+ return HookResult(decision=HookDecision.ASK, message=output)
170
+
171
+ return HookResult(decision=HookDecision.ALLOW, message=output)
172
+
173
+ except asyncio.TimeoutError:
174
+ logger.warning("Hook timed out: %s", hook.command)
175
+ return HookResult()
176
+
177
+
178
+ # Global hook manager instance
179
+ hook_manager = HookManager()
@@ -44,6 +44,24 @@ class SkillMetadata(BaseModel):
44
44
  validation_alias="user-invocable",
45
45
  description="Controls whether the skill appears in the slash command menu.",
46
46
  )
47
+ # New fields for Claude Code parity
48
+ context: str = Field(
49
+ default="",
50
+ description="'fork' to run in a subagent with its own context window.",
51
+ )
52
+ agent: str = Field(
53
+ default="",
54
+ description="Subagent type to use when context is 'fork' (e.g., 'explore').",
55
+ )
56
+ model: str = Field(
57
+ default="",
58
+ description="Model to use for this skill (overrides active_model).",
59
+ )
60
+ disable_model_invocation: bool = Field(
61
+ default=False,
62
+ validation_alias="disable-model-invocation",
63
+ description="If true, only users can invoke this skill (not the model).",
64
+ )
47
65
 
48
66
  @field_validator("allowed_tools", mode="before")
49
67
  @classmethod
@@ -0,0 +1,94 @@
1
+ """Glob tool — fast file pattern matching.
2
+
3
+ Matches files by glob pattern (e.g., "**/*.py", "src/**/*.ts").
4
+ Returns sorted file paths. Read-only, always auto-approved.
5
+ """
6
+
7
+ from __future__ import annotations
8
+
9
+ from collections.abc import AsyncGenerator
10
+ from pathlib import Path
11
+ from typing import TYPE_CHECKING, ClassVar, final
12
+
13
+ from pydantic import BaseModel, Field
14
+
15
+ from drydock.core.tools.base import (
16
+ BaseTool, BaseToolConfig, BaseToolState, InvokeContext, ToolError, ToolPermission,
17
+ )
18
+ from drydock.core.tools.ui import ToolCallDisplay, ToolResultDisplay, ToolUIData
19
+ from drydock.core.types import ToolStreamEvent
20
+
21
+ if TYPE_CHECKING:
22
+ from drydock.core.types import ToolResultEvent
23
+
24
+
25
+ class GlobArgs(BaseModel):
26
+ pattern: str = Field(description="Glob pattern (e.g., '**/*.py', 'src/**/*.ts')")
27
+ path: str = Field(default=".", description="Directory to search in")
28
+
29
+
30
+ class GlobResult(BaseModel):
31
+ files: list[str]
32
+ count: int
33
+ truncated: bool = False
34
+
35
+
36
+ class GlobConfig(BaseToolConfig):
37
+ permission: ToolPermission = ToolPermission.ALWAYS
38
+ max_results: int = 200
39
+
40
+
41
+ class Glob(
42
+ BaseTool[GlobArgs, GlobResult, GlobConfig, BaseToolState],
43
+ ToolUIData[GlobArgs, GlobResult],
44
+ ):
45
+ description: ClassVar[str] = (
46
+ "Find files matching a glob pattern. Fast file discovery."
47
+ )
48
+
49
+ @classmethod
50
+ def format_call_display(cls, args: GlobArgs) -> ToolCallDisplay:
51
+ return ToolCallDisplay(summary=f"glob: {args.pattern}")
52
+
53
+ @classmethod
54
+ def get_result_display(cls, event: ToolResultEvent) -> ToolResultDisplay:
55
+ if isinstance(event.result, GlobResult):
56
+ return ToolResultDisplay(
57
+ success=True, message=f"Found {event.result.count} files"
58
+ )
59
+ return ToolResultDisplay(success=True, message="Glob complete")
60
+
61
+ @classmethod
62
+ def get_status_text(cls) -> str:
63
+ return "Searching files"
64
+
65
+ def resolve_permission(self, args: GlobArgs) -> ToolPermission | None:
66
+ return ToolPermission.ALWAYS
67
+
68
+ @final
69
+ async def run(
70
+ self, args: GlobArgs, ctx: InvokeContext | None = None
71
+ ) -> AsyncGenerator[ToolStreamEvent | GlobResult, None]:
72
+ search_dir = Path(args.path).expanduser()
73
+ if not search_dir.is_absolute():
74
+ search_dir = Path.cwd() / search_dir
75
+
76
+ if not search_dir.is_dir():
77
+ raise ToolError(f"Directory not found: {search_dir}")
78
+
79
+ try:
80
+ matches = sorted(
81
+ str(p.relative_to(search_dir))
82
+ for p in search_dir.glob(args.pattern)
83
+ if p.is_file()
84
+ and "__pycache__" not in str(p)
85
+ and ".git/" not in str(p)
86
+ and "node_modules/" not in str(p)
87
+ )
88
+ except Exception as e:
89
+ raise ToolError(f"Glob error: {e}") from e
90
+
91
+ truncated = len(matches) > self.config.max_results
92
+ files = matches[:self.config.max_results]
93
+
94
+ yield GlobResult(files=files, count=len(matches), truncated=truncated)
@@ -0,0 +1,100 @@
1
+ """Invoke Skill tool — lets the model call skills programmatically.
2
+
3
+ The model can invoke any registered skill by name, equivalent to
4
+ the user typing /skill-name in the chat.
5
+ """
6
+
7
+ from __future__ import annotations
8
+
9
+ from collections.abc import AsyncGenerator
10
+ from typing import ClassVar, final
11
+
12
+ from pydantic import BaseModel, Field
13
+
14
+ from drydock.core.tools.base import (
15
+ BaseTool, BaseToolConfig, BaseToolState, InvokeContext, ToolError, ToolPermission,
16
+ )
17
+ from drydock.core.tools.ui import ToolCallDisplay, ToolResultDisplay, ToolUIData
18
+ from drydock.core.types import ToolStreamEvent, ToolResultEvent
19
+
20
+
21
+ class InvokeSkillArgs(BaseModel):
22
+ skill_name: str = Field(description="Name of the skill to invoke (e.g., 'investigate', 'review')")
23
+ arguments: str = Field(default="", description="Arguments to pass to the skill")
24
+
25
+
26
+ class InvokeSkillResult(BaseModel):
27
+ skill_name: str
28
+ content: str
29
+ loaded: bool
30
+
31
+
32
+ class InvokeSkill(
33
+ BaseTool[InvokeSkillArgs, InvokeSkillResult, BaseToolConfig, BaseToolState],
34
+ ToolUIData[InvokeSkillArgs, InvokeSkillResult],
35
+ ):
36
+ description: ClassVar[str] = (
37
+ "Invoke a skill by name. Use this to activate specialized workflows "
38
+ "like /investigate, /review, /ship, /batch, etc."
39
+ )
40
+
41
+ @classmethod
42
+ def format_call_display(cls, args: InvokeSkillArgs) -> ToolCallDisplay:
43
+ return ToolCallDisplay(summary=f"skill: /{args.skill_name}")
44
+
45
+ @classmethod
46
+ def get_result_display(cls, event: ToolResultEvent) -> ToolResultDisplay:
47
+ if isinstance(event.result, InvokeSkillResult):
48
+ return ToolResultDisplay(success=event.result.loaded, message=f"/{event.result.skill_name}")
49
+ return ToolResultDisplay(success=True, message="Skill invoked")
50
+
51
+ @classmethod
52
+ def get_status_text(cls) -> str:
53
+ return "Loading skill"
54
+
55
+ def resolve_permission(self, args: InvokeSkillArgs) -> ToolPermission | None:
56
+ return ToolPermission.ALWAYS
57
+
58
+ @final
59
+ async def run(
60
+ self, args: InvokeSkillArgs, ctx: InvokeContext | None = None
61
+ ) -> AsyncGenerator[ToolStreamEvent | InvokeSkillResult, None]:
62
+ if not ctx or not ctx.agent_manager:
63
+ raise ToolError("No agent manager available")
64
+
65
+ # Find the skill
66
+ try:
67
+ from drydock.core.skills.manager import SkillManager
68
+ config = ctx.agent_manager.config
69
+ manager = SkillManager(lambda: config)
70
+ skills = manager.available_skills
71
+
72
+ if args.skill_name not in skills:
73
+ available = ", ".join(sorted(skills.keys()))
74
+ raise ToolError(
75
+ f"Skill '{args.skill_name}' not found. "
76
+ f"Available: {available}"
77
+ )
78
+
79
+ skill_info = skills[args.skill_name]
80
+ content = skill_info.skill_path.read_text(encoding="utf-8") if skill_info.skill_path else ""
81
+
82
+ # Strip frontmatter
83
+ if content.startswith("---"):
84
+ parts = content.split("---", 2)
85
+ content = parts[2].strip() if len(parts) >= 3 else content
86
+
87
+ # Prepend arguments if provided
88
+ if args.arguments:
89
+ content = f"{args.arguments}\n\n{content}"
90
+
91
+ yield InvokeSkillResult(
92
+ skill_name=args.skill_name,
93
+ content=content,
94
+ loaded=True,
95
+ )
96
+
97
+ except ToolError:
98
+ raise
99
+ except Exception as e:
100
+ raise ToolError(f"Failed to load skill: {e}") from e
@@ -0,0 +1,96 @@
1
+ """NotebookEdit tool — edit Jupyter notebook cells.
2
+
3
+ Supports editing code and markdown cells in .ipynb files.
4
+ """
5
+
6
+ from __future__ import annotations
7
+
8
+ import json
9
+ from collections.abc import AsyncGenerator
10
+ from pathlib import Path
11
+ from typing import ClassVar, final
12
+
13
+ from pydantic import BaseModel, Field
14
+
15
+ from drydock.core.tools.base import (
16
+ BaseTool, BaseToolConfig, BaseToolState, InvokeContext, ToolError, ToolPermission,
17
+ )
18
+ from drydock.core.tools.ui import ToolCallDisplay, ToolResultDisplay, ToolUIData
19
+ from drydock.core.types import ToolStreamEvent, ToolResultEvent
20
+
21
+
22
+ class NotebookEditArgs(BaseModel):
23
+ path: str = Field(description="Path to the .ipynb file")
24
+ cell_index: int = Field(description="Cell index to edit (0-based)")
25
+ new_source: str = Field(description="New source content for the cell")
26
+ cell_type: str = Field(default="code", description="Cell type: 'code' or 'markdown'")
27
+
28
+
29
+ class NotebookEditResult(BaseModel):
30
+ path: str
31
+ cell_index: int
32
+ cell_type: str
33
+ total_cells: int
34
+
35
+
36
+ class NotebookEdit(
37
+ BaseTool[NotebookEditArgs, NotebookEditResult, BaseToolConfig, BaseToolState],
38
+ ToolUIData[NotebookEditArgs, NotebookEditResult],
39
+ ):
40
+ description: ClassVar[str] = "Edit a cell in a Jupyter notebook (.ipynb file)."
41
+
42
+ @classmethod
43
+ def format_call_display(cls, args: NotebookEditArgs) -> ToolCallDisplay:
44
+ return ToolCallDisplay(summary=f"notebook_edit: cell {args.cell_index} in {args.path}")
45
+
46
+ @classmethod
47
+ def get_result_display(cls, event: ToolResultEvent) -> ToolResultDisplay:
48
+ if isinstance(event.result, NotebookEditResult):
49
+ return ToolResultDisplay(success=True, message=f"Edited cell {event.result.cell_index}")
50
+ return ToolResultDisplay(success=True, message="Notebook edited")
51
+
52
+ @classmethod
53
+ def get_status_text(cls) -> str:
54
+ return "Editing notebook"
55
+
56
+ @final
57
+ async def run(
58
+ self, args: NotebookEditArgs, ctx: InvokeContext | None = None
59
+ ) -> AsyncGenerator[ToolStreamEvent | NotebookEditResult, None]:
60
+ file_path = Path(args.path).expanduser()
61
+ if not file_path.is_absolute():
62
+ file_path = Path.cwd() / file_path
63
+
64
+ if not file_path.exists():
65
+ raise ToolError(f"Notebook not found: {file_path}")
66
+
67
+ if not str(file_path).endswith(".ipynb"):
68
+ raise ToolError("File must be a .ipynb notebook")
69
+
70
+ try:
71
+ with open(file_path, encoding="utf-8") as f:
72
+ notebook = json.load(f)
73
+ except (json.JSONDecodeError, OSError) as e:
74
+ raise ToolError(f"Cannot read notebook: {e}") from e
75
+
76
+ cells = notebook.get("cells", [])
77
+ if args.cell_index < 0 or args.cell_index >= len(cells):
78
+ raise ToolError(f"Cell index {args.cell_index} out of range (0-{len(cells)-1})")
79
+
80
+ # Update the cell
81
+ cell = cells[args.cell_index]
82
+ cell["source"] = args.new_source.split("\n")
83
+ cell["cell_type"] = args.cell_type
84
+
85
+ try:
86
+ with open(file_path, "w", encoding="utf-8") as f:
87
+ json.dump(notebook, f, indent=1, ensure_ascii=False)
88
+ except OSError as e:
89
+ raise ToolError(f"Cannot write notebook: {e}") from e
90
+
91
+ yield NotebookEditResult(
92
+ path=str(file_path),
93
+ cell_index=args.cell_index,
94
+ cell_type=args.cell_type,
95
+ total_cells=len(cells),
96
+ )
@@ -0,0 +1,9 @@
1
+ Find files matching a glob pattern. Returns sorted file paths.
2
+
3
+ Examples:
4
+ - `glob(pattern="**/*.py")` — all Python files
5
+ - `glob(pattern="src/**/*.ts", path=".")` — TypeScript files under src/
6
+ - `glob(pattern="*.md")` — markdown files in current directory
7
+ - `glob(pattern="**/test_*.py")` — all test files
8
+
9
+ Use this instead of `bash find` for file discovery.
@@ -0,0 +1,9 @@
1
+ Invoke a skill by name to activate specialized workflows.
2
+
3
+ Examples:
4
+ - `invoke_skill(skill_name="investigate", arguments="Fix the login timeout bug")`
5
+ - `invoke_skill(skill_name="review")` — run a code review
6
+ - `invoke_skill(skill_name="ship")` — run the shipping pipeline
7
+ - `invoke_skill(skill_name="batch", arguments="Add type hints to all files in src/")`
8
+
9
+ Available skills depend on what's installed. Use this to activate domain-specific workflows.
@@ -0,0 +1,7 @@
1
+ Edit a cell in a Jupyter notebook (.ipynb file).
2
+
3
+ Arguments:
4
+ - path: Path to the .ipynb file
5
+ - cell_index: Cell index to edit (0-based)
6
+ - new_source: New source content for the cell
7
+ - cell_type: "code" or "markdown" (default: "code")
@@ -0,0 +1,8 @@
1
+ Track work items during a session.
2
+
3
+ Tools:
4
+ - `task_create(title, description)` — Create a new task
5
+ - `task_list()` — List all tasks and their status
6
+ - `task_update(task_id, status, notes)` — Update status: pending, in_progress, completed, blocked
7
+
8
+ Use these to break complex work into trackable steps.
@@ -0,0 +1,7 @@
1
+ Git worktree tools for parallel work in isolated copies.
2
+
3
+ - `enter_worktree(branch="feature-x")` — Create isolated worktree and switch to it
4
+ - `exit_worktree(cleanup=true)` — Return to main directory, optionally remove worktree
5
+
6
+ Use worktrees when you need to make changes without affecting the main branch,
7
+ or to work on multiple things in parallel.