drydock-cli 0.9.0__tar.gz → 1.1.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 (490) hide show
  1. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/PKG-INFO +1 -1
  2. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/drydock/core/agents/models.py +47 -0
  3. drydock_cli-1.1.0/drydock/core/session/agent_memory.py +123 -0
  4. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/drydock/core/skills/models.py +18 -0
  5. drydock_cli-1.1.0/drydock/core/tools/builtins/cron.py +164 -0
  6. drydock_cli-1.1.0/drydock/core/tools/builtins/invoke_skill.py +100 -0
  7. drydock_cli-1.1.0/drydock/core/tools/builtins/lsp.py +202 -0
  8. drydock_cli-1.1.0/drydock/core/tools/builtins/mcp_resources.py +118 -0
  9. drydock_cli-1.1.0/drydock/core/tools/builtins/powershell.py +116 -0
  10. drydock_cli-1.1.0/drydock/core/tools/builtins/prompts/cron.md +5 -0
  11. drydock_cli-1.1.0/drydock/core/tools/builtins/prompts/invoke_skill.md +9 -0
  12. drydock_cli-1.1.0/drydock/core/tools/builtins/prompts/lsp.md +9 -0
  13. drydock_cli-1.1.0/drydock/core/tools/builtins/prompts/mcp_resources.md +4 -0
  14. drydock_cli-1.1.0/drydock/core/tools/builtins/prompts/powershell.md +6 -0
  15. drydock_cli-1.1.0/drydock/core/tools/builtins/prompts/tool_search.md +7 -0
  16. drydock_cli-1.1.0/drydock/core/tools/builtins/prompts/worktree.md +7 -0
  17. drydock_cli-1.1.0/drydock/core/tools/builtins/tool_search.py +120 -0
  18. drydock_cli-1.1.0/drydock/core/tools/builtins/worktree.py +166 -0
  19. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/pyproject.toml +1 -1
  20. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/.github/CODEOWNERS +0 -0
  21. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/.github/DISCUSSION_TEMPLATE/ideas.yml +0 -0
  22. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/.github/ISSUE_TEMPLATE/bug-report.yml +0 -0
  23. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/.github/ISSUE_TEMPLATE/config.yml +0 -0
  24. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/.github/workflows/build-and-upload.yml +0 -0
  25. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/.github/workflows/ci.yml +0 -0
  26. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/.github/workflows/issue-labeler.yml +0 -0
  27. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/.github/workflows/release.yml +0 -0
  28. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/.gitignore +0 -0
  29. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/.pre-commit-config.yaml +0 -0
  30. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/.python-version +0 -0
  31. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/.typos.toml +0 -0
  32. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/.vscode/extensions.json +0 -0
  33. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/.vscode/launch.json +0 -0
  34. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/.vscode/settings.json +0 -0
  35. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/AGENTS.md +0 -0
  36. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/CHANGELOG.md +0 -0
  37. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/CLAUDE.md +0 -0
  38. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/CONTRIBUTING.md +0 -0
  39. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/Drydock_rebrand.md +0 -0
  40. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/LICENSE +0 -0
  41. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/NOTICE +0 -0
  42. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/PRD.md +0 -0
  43. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/README.md +0 -0
  44. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/action.yml +0 -0
  45. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/distribution/zed/LICENSE +0 -0
  46. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/distribution/zed/extension.toml +0 -0
  47. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/distribution/zed/icons/mistral_vibe.svg +0 -0
  48. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/docs/README.md +0 -0
  49. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/docs/acp-setup.md +0 -0
  50. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/docs/proxy-setup.md +0 -0
  51. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/drydock/__init__.py +0 -0
  52. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/drydock/acp/__init__.py +0 -0
  53. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/drydock/acp/acp_agent_loop.py +0 -0
  54. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/drydock/acp/acp_logger.py +0 -0
  55. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/drydock/acp/entrypoint.py +0 -0
  56. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/drydock/acp/tools/__init__.py +0 -0
  57. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/drydock/acp/tools/base.py +0 -0
  58. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/drydock/acp/tools/builtins/bash.py +0 -0
  59. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/drydock/acp/tools/builtins/read_file.py +0 -0
  60. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/drydock/acp/tools/builtins/search_replace.py +0 -0
  61. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/drydock/acp/tools/builtins/todo.py +0 -0
  62. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/drydock/acp/tools/builtins/write_file.py +0 -0
  63. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/drydock/acp/tools/session_update.py +0 -0
  64. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/drydock/acp/utils.py +0 -0
  65. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/drydock/cli/__init__.py +0 -0
  66. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/drydock/cli/autocompletion/__init__.py +0 -0
  67. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/drydock/cli/autocompletion/base.py +0 -0
  68. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/drydock/cli/autocompletion/path_completion.py +0 -0
  69. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/drydock/cli/autocompletion/slash_command.py +0 -0
  70. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/drydock/cli/cli.py +0 -0
  71. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/drydock/cli/clipboard.py +0 -0
  72. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/drydock/cli/commands.py +0 -0
  73. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/drydock/cli/entrypoint.py +0 -0
  74. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/drydock/cli/history_manager.py +0 -0
  75. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/drydock/cli/plan_offer/adapters/http_whoami_gateway.py +0 -0
  76. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/drydock/cli/plan_offer/decide_plan_offer.py +0 -0
  77. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/drydock/cli/plan_offer/ports/whoami_gateway.py +0 -0
  78. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/drydock/cli/terminal_setup.py +0 -0
  79. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/drydock/cli/textual_ui/__init__.py +0 -0
  80. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/drydock/cli/textual_ui/ansi_markdown.py +0 -0
  81. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/drydock/cli/textual_ui/app.py +0 -0
  82. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/drydock/cli/textual_ui/app.tcss +0 -0
  83. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/drydock/cli/textual_ui/external_editor.py +0 -0
  84. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/drydock/cli/textual_ui/handlers/__init__.py +0 -0
  85. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/drydock/cli/textual_ui/handlers/event_handler.py +0 -0
  86. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/drydock/cli/textual_ui/notifications/__init__.py +0 -0
  87. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/drydock/cli/textual_ui/notifications/adapters/__init__.py +0 -0
  88. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/drydock/cli/textual_ui/notifications/adapters/textual_notification_adapter.py +0 -0
  89. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/drydock/cli/textual_ui/notifications/ports/__init__.py +0 -0
  90. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/drydock/cli/textual_ui/notifications/ports/notification_port.py +0 -0
  91. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/drydock/cli/textual_ui/widgets/__init__.py +0 -0
  92. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/drydock/cli/textual_ui/widgets/approval_app.py +0 -0
  93. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/drydock/cli/textual_ui/widgets/banner/banner.py +0 -0
  94. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/drydock/cli/textual_ui/widgets/banner/petit_chat.py +0 -0
  95. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/drydock/cli/textual_ui/widgets/braille_renderer.py +0 -0
  96. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/drydock/cli/textual_ui/widgets/chat_input/__init__.py +0 -0
  97. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/drydock/cli/textual_ui/widgets/chat_input/body.py +0 -0
  98. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/drydock/cli/textual_ui/widgets/chat_input/completion_manager.py +0 -0
  99. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/drydock/cli/textual_ui/widgets/chat_input/completion_popup.py +0 -0
  100. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/drydock/cli/textual_ui/widgets/chat_input/container.py +0 -0
  101. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/drydock/cli/textual_ui/widgets/chat_input/text_area.py +0 -0
  102. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/drydock/cli/textual_ui/widgets/compact.py +0 -0
  103. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/drydock/cli/textual_ui/widgets/config_app.py +0 -0
  104. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/drydock/cli/textual_ui/widgets/context_progress.py +0 -0
  105. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/drydock/cli/textual_ui/widgets/load_more.py +0 -0
  106. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/drydock/cli/textual_ui/widgets/loading.py +0 -0
  107. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/drydock/cli/textual_ui/widgets/messages.py +0 -0
  108. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/drydock/cli/textual_ui/widgets/no_markup_static.py +0 -0
  109. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/drydock/cli/textual_ui/widgets/path_display.py +0 -0
  110. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/drydock/cli/textual_ui/widgets/proxy_setup_app.py +0 -0
  111. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/drydock/cli/textual_ui/widgets/question_app.py +0 -0
  112. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/drydock/cli/textual_ui/widgets/session_picker.py +0 -0
  113. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/drydock/cli/textual_ui/widgets/spinner.py +0 -0
  114. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/drydock/cli/textual_ui/widgets/status_message.py +0 -0
  115. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/drydock/cli/textual_ui/widgets/teleport_message.py +0 -0
  116. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/drydock/cli/textual_ui/widgets/tool_widgets.py +0 -0
  117. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/drydock/cli/textual_ui/widgets/tools.py +0 -0
  118. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/drydock/cli/textual_ui/widgets/vscode_compat.py +0 -0
  119. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/drydock/cli/textual_ui/windowing/__init__.py +0 -0
  120. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/drydock/cli/textual_ui/windowing/history.py +0 -0
  121. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/drydock/cli/textual_ui/windowing/history_windowing.py +0 -0
  122. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/drydock/cli/textual_ui/windowing/state.py +0 -0
  123. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/drydock/cli/update_notifier/__init__.py +0 -0
  124. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/drydock/cli/update_notifier/adapters/filesystem_update_cache_repository.py +0 -0
  125. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/drydock/cli/update_notifier/adapters/github_update_gateway.py +0 -0
  126. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/drydock/cli/update_notifier/adapters/pypi_update_gateway.py +0 -0
  127. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/drydock/cli/update_notifier/ports/update_cache_repository.py +0 -0
  128. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/drydock/cli/update_notifier/ports/update_gateway.py +0 -0
  129. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/drydock/cli/update_notifier/update.py +0 -0
  130. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/drydock/cli/update_notifier/whats_new.py +0 -0
  131. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/drydock/core/__init__.py +0 -0
  132. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/drydock/core/agent_loop.py +0 -0
  133. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/drydock/core/agents/__init__.py +0 -0
  134. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/drydock/core/agents/manager.py +0 -0
  135. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/drydock/core/auth/__init__.py +0 -0
  136. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/drydock/core/auth/crypto.py +0 -0
  137. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/drydock/core/auth/github.py +0 -0
  138. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/drydock/core/autocompletion/__init__.py +0 -0
  139. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/drydock/core/autocompletion/completers.py +0 -0
  140. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/drydock/core/autocompletion/file_indexer/__init__.py +0 -0
  141. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/drydock/core/autocompletion/file_indexer/ignore_rules.py +0 -0
  142. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/drydock/core/autocompletion/file_indexer/indexer.py +0 -0
  143. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/drydock/core/autocompletion/file_indexer/store.py +0 -0
  144. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/drydock/core/autocompletion/file_indexer/watcher.py +0 -0
  145. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/drydock/core/autocompletion/fuzzy.py +0 -0
  146. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/drydock/core/autocompletion/path_prompt.py +0 -0
  147. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/drydock/core/autocompletion/path_prompt_adapter.py +0 -0
  148. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/drydock/core/config/__init__.py +0 -0
  149. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/drydock/core/config/_settings.py +0 -0
  150. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/drydock/core/config/harness_files/__init__.py +0 -0
  151. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/drydock/core/config/harness_files/_harness_manager.py +0 -0
  152. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/drydock/core/config/harness_files/_paths.py +0 -0
  153. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/drydock/core/consultant.py +0 -0
  154. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/drydock/core/drydock_states.py +0 -0
  155. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/drydock/core/hooks.py +0 -0
  156. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/drydock/core/llm/__init__.py +0 -0
  157. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/drydock/core/llm/backend/anthropic.py +0 -0
  158. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/drydock/core/llm/backend/base.py +0 -0
  159. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/drydock/core/llm/backend/factory.py +0 -0
  160. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/drydock/core/llm/backend/generic.py +0 -0
  161. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/drydock/core/llm/backend/mistral.py +0 -0
  162. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/drydock/core/llm/backend/reasoning_adapter.py +0 -0
  163. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/drydock/core/llm/backend/vertex.py +0 -0
  164. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/drydock/core/llm/exceptions.py +0 -0
  165. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/drydock/core/llm/format.py +0 -0
  166. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/drydock/core/llm/message_utils.py +0 -0
  167. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/drydock/core/llm/types.py +0 -0
  168. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/drydock/core/logger.py +0 -0
  169. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/drydock/core/middleware.py +0 -0
  170. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/drydock/core/output_formatters.py +0 -0
  171. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/drydock/core/paths/__init__.py +0 -0
  172. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/drydock/core/paths/_local_config_walk.py +0 -0
  173. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/drydock/core/paths/_vibe_home.py +0 -0
  174. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/drydock/core/paths/conventions.py +0 -0
  175. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/drydock/core/plan_session.py +0 -0
  176. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/drydock/core/programmatic.py +0 -0
  177. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/drydock/core/prompts/__init__.py +0 -0
  178. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/drydock/core/prompts/cli.md +0 -0
  179. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/drydock/core/prompts/compact.md +0 -0
  180. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/drydock/core/prompts/dangerous_directory.md +0 -0
  181. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/drydock/core/prompts/diagnostic.md +0 -0
  182. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/drydock/core/prompts/explore.md +0 -0
  183. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/drydock/core/prompts/planner.md +0 -0
  184. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/drydock/core/prompts/project_context.md +0 -0
  185. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/drydock/core/prompts/tests.md +0 -0
  186. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/drydock/core/proxy_setup.py +0 -0
  187. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/drydock/core/session/session_loader.py +0 -0
  188. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/drydock/core/session/session_logger.py +0 -0
  189. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/drydock/core/session/session_migration.py +0 -0
  190. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/drydock/core/session/state_file.py +0 -0
  191. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/drydock/core/skills/__init__.py +0 -0
  192. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/drydock/core/skills/manager.py +0 -0
  193. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/drydock/core/skills/parser.py +0 -0
  194. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/drydock/core/slug.py +0 -0
  195. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/drydock/core/system_prompt.py +0 -0
  196. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/drydock/core/telemetry/__init__.py +0 -0
  197. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/drydock/core/telemetry/send.py +0 -0
  198. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/drydock/core/teleport/errors.py +0 -0
  199. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/drydock/core/teleport/git.py +0 -0
  200. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/drydock/core/teleport/nuage.py +0 -0
  201. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/drydock/core/teleport/teleport.py +0 -0
  202. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/drydock/core/teleport/types.py +0 -0
  203. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/drydock/core/tools/base.py +0 -0
  204. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/drydock/core/tools/builtins/ask_user_question.py +0 -0
  205. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/drydock/core/tools/builtins/bash.py +0 -0
  206. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/drydock/core/tools/builtins/exit_plan_mode.py +0 -0
  207. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/drydock/core/tools/builtins/glob_tool.py +0 -0
  208. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/drydock/core/tools/builtins/grep.py +0 -0
  209. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/drydock/core/tools/builtins/notebook_edit.py +0 -0
  210. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/drydock/core/tools/builtins/prompts/__init__.py +0 -0
  211. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/drydock/core/tools/builtins/prompts/ask_user_question.md +0 -0
  212. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/drydock/core/tools/builtins/prompts/bash.md +0 -0
  213. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/drydock/core/tools/builtins/prompts/glob.md +0 -0
  214. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/drydock/core/tools/builtins/prompts/grep.md +0 -0
  215. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/drydock/core/tools/builtins/prompts/notebook_edit.md +0 -0
  216. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/drydock/core/tools/builtins/prompts/read_file.md +0 -0
  217. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/drydock/core/tools/builtins/prompts/search_replace.md +0 -0
  218. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/drydock/core/tools/builtins/prompts/swe_bench.md +0 -0
  219. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/drydock/core/tools/builtins/prompts/task.md +0 -0
  220. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/drydock/core/tools/builtins/prompts/task_manager.md +0 -0
  221. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/drydock/core/tools/builtins/prompts/todo.md +0 -0
  222. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/drydock/core/tools/builtins/prompts/webfetch.md +0 -0
  223. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/drydock/core/tools/builtins/prompts/websearch.md +0 -0
  224. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/drydock/core/tools/builtins/prompts/write_file.md +0 -0
  225. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/drydock/core/tools/builtins/read_file.py +0 -0
  226. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/drydock/core/tools/builtins/search_replace.py +0 -0
  227. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/drydock/core/tools/builtins/task.py +0 -0
  228. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/drydock/core/tools/builtins/task_manager.py +0 -0
  229. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/drydock/core/tools/builtins/todo.py +0 -0
  230. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/drydock/core/tools/builtins/webfetch.py +0 -0
  231. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/drydock/core/tools/builtins/websearch.py +0 -0
  232. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/drydock/core/tools/builtins/write_file.py +0 -0
  233. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/drydock/core/tools/injection_guard.py +0 -0
  234. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/drydock/core/tools/manager.py +0 -0
  235. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/drydock/core/tools/mcp/__init__.py +0 -0
  236. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/drydock/core/tools/mcp/registry.py +0 -0
  237. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/drydock/core/tools/mcp/tools.py +0 -0
  238. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/drydock/core/tools/mcp_sampling.py +0 -0
  239. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/drydock/core/tools/ui.py +0 -0
  240. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/drydock/core/tools/utils.py +0 -0
  241. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/drydock/core/trusted_folders.py +0 -0
  242. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/drydock/core/types.py +0 -0
  243. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/drydock/core/utils.py +0 -0
  244. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/drydock/setup/onboarding/__init__.py +0 -0
  245. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/drydock/setup/onboarding/base.py +0 -0
  246. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/drydock/setup/onboarding/onboarding.tcss +0 -0
  247. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/drydock/setup/onboarding/screens/__init__.py +0 -0
  248. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/drydock/setup/onboarding/screens/api_key.py +0 -0
  249. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/drydock/setup/onboarding/screens/welcome.py +0 -0
  250. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/drydock/setup/trusted_folders/trust_folder_dialog.py +0 -0
  251. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/drydock/setup/trusted_folders/trust_folder_dialog.tcss +0 -0
  252. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/drydock/skills/__init__.py +0 -0
  253. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/drydock/skills/batch/SKILL.md +0 -0
  254. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/drydock/skills/create-presentation/SKILL.md +0 -0
  255. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/drydock/skills/deep-research/SKILL.md +0 -0
  256. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/drydock/skills/investigate/SKILL.md +0 -0
  257. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/drydock/skills/review/SKILL.md +0 -0
  258. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/drydock/skills/ship/SKILL.md +0 -0
  259. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/drydock/skills/simplify/SKILL.md +0 -0
  260. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/drydock/whats_new.md +0 -0
  261. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/drydock-acp.spec +0 -0
  262. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/drydock_terms.md +0 -0
  263. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/flake.lock +0 -0
  264. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/flake.nix +0 -0
  265. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/scripts/README.md +0 -0
  266. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/scripts/backup.sh +0 -0
  267. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/scripts/bump_version.py +0 -0
  268. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/scripts/deploy_to_github.sh +0 -0
  269. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/scripts/install.sh +0 -0
  270. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/scripts/prepare_release.py +0 -0
  271. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/scripts/publish_to_pypi.sh +0 -0
  272. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/tests/__init__.py +0 -0
  273. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/tests/acp/conftest.py +0 -0
  274. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/tests/acp/test_acp.py +0 -0
  275. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/tests/acp/test_agent_thought.py +0 -0
  276. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/tests/acp/test_bash.py +0 -0
  277. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/tests/acp/test_compact_session_updates.py +0 -0
  278. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/tests/acp/test_content.py +0 -0
  279. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/tests/acp/test_initialize.py +0 -0
  280. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/tests/acp/test_list_sessions.py +0 -0
  281. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/tests/acp/test_load_session.py +0 -0
  282. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/tests/acp/test_multi_session.py +0 -0
  283. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/tests/acp/test_new_session.py +0 -0
  284. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/tests/acp/test_proxy_setup_acp.py +0 -0
  285. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/tests/acp/test_read_file.py +0 -0
  286. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/tests/acp/test_search_replace.py +0 -0
  287. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/tests/acp/test_set_config_option.py +0 -0
  288. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/tests/acp/test_set_mode.py +0 -0
  289. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/tests/acp/test_set_model.py +0 -0
  290. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/tests/acp/test_tool_call_session_update.py +0 -0
  291. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/tests/acp/test_utils.py +0 -0
  292. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/tests/acp/test_write_file.py +0 -0
  293. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/tests/autocompletion/test_file_indexer.py +0 -0
  294. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/tests/autocompletion/test_fuzzy.py +0 -0
  295. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/tests/autocompletion/test_path_completer_fuzzy.py +0 -0
  296. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/tests/autocompletion/test_path_completer_recursive.py +0 -0
  297. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/tests/autocompletion/test_path_completion_controller.py +0 -0
  298. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/tests/autocompletion/test_path_prompt_transformer.py +0 -0
  299. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/tests/autocompletion/test_slash_command_controller.py +0 -0
  300. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/tests/autocompletion/test_ui_chat_autocompletion.py +0 -0
  301. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/tests/backend/__init__.py +0 -0
  302. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/tests/backend/data/__init__.py +0 -0
  303. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/tests/backend/data/fireworks.py +0 -0
  304. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/tests/backend/data/mistral.py +0 -0
  305. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/tests/backend/test_anthropic_adapter.py +0 -0
  306. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/tests/backend/test_backend.py +0 -0
  307. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/tests/backend/test_reasoning_adapter.py +0 -0
  308. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/tests/backend/test_vertex_anthropic_adapter.py +0 -0
  309. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/tests/cli/plan_offer/adapters/fake_whoami_gateway.py +0 -0
  310. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/tests/cli/plan_offer/test_decide_plan_offer.py +0 -0
  311. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/tests/cli/plan_offer/test_http_whoami_gateway.py +0 -0
  312. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/tests/cli/test_bell_notifications.py +0 -0
  313. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/tests/cli/test_braille_renderer.py +0 -0
  314. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/tests/cli/test_clipboard.py +0 -0
  315. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/tests/cli/test_commands.py +0 -0
  316. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/tests/cli/test_copy_shortcuts.py +0 -0
  317. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/tests/cli/test_external_editor.py +0 -0
  318. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/tests/cli/test_no_markup_static.py +0 -0
  319. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/tests/cli/test_question_app.py +0 -0
  320. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/tests/cli/test_spinner.py +0 -0
  321. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/tests/cli/test_switching_mode.py +0 -0
  322. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/tests/cli/test_ui_clipboard_notifications.py +0 -0
  323. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/tests/cli/test_ui_session_incremental_renderer.py +0 -0
  324. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/tests/cli/test_ui_session_resume.py +0 -0
  325. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/tests/cli/test_ui_skill_dispatch.py +0 -0
  326. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/tests/cli/textual_ui/__init__.py +0 -0
  327. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/tests/cli/textual_ui/test_session_picker.py +0 -0
  328. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/tests/conftest.py +0 -0
  329. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/tests/core/test_agents.py +0 -0
  330. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/tests/core/test_auth_crypto.py +0 -0
  331. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/tests/core/test_auth_github.py +0 -0
  332. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/tests/core/test_config_load_dotenv.py +0 -0
  333. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/tests/core/test_config_paths.py +0 -0
  334. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/tests/core/test_config_resolution.py +0 -0
  335. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/tests/core/test_file_logging.py +0 -0
  336. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/tests/core/test_plan_session.py +0 -0
  337. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/tests/core/test_proxy_setup.py +0 -0
  338. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/tests/core/test_slug.py +0 -0
  339. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/tests/core/test_telemetry_send.py +0 -0
  340. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/tests/core/test_teleport_git.py +0 -0
  341. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/tests/core/test_teleport_nuage.py +0 -0
  342. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/tests/core/test_teleport_service.py +0 -0
  343. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/tests/core/test_trusted_folders.py +0 -0
  344. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/tests/core/test_utils.py +0 -0
  345. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/tests/e2e/common.py +0 -0
  346. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/tests/e2e/conftest.py +0 -0
  347. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/tests/e2e/mock_server.py +0 -0
  348. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/tests/e2e/test_cli_tui_onboarding.py +0 -0
  349. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/tests/e2e/test_cli_tui_streaming.py +0 -0
  350. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/tests/e2e/test_cli_tui_tool_approval.py +0 -0
  351. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/tests/mock/__init__.py +0 -0
  352. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/tests/mock/mock_backend_factory.py +0 -0
  353. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/tests/mock/mock_entrypoint.py +0 -0
  354. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/tests/mock/utils.py +0 -0
  355. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/tests/onboarding/test_run_onboarding.py +0 -0
  356. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/tests/onboarding/test_ui_onboarding.py +0 -0
  357. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/tests/session/test_session_loader.py +0 -0
  358. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/tests/session/test_session_logger.py +0 -0
  359. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/tests/session/test_session_migration.py +0 -0
  360. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/tests/skills/conftest.py +0 -0
  361. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/tests/skills/test_manager.py +0 -0
  362. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/tests/skills/test_models.py +0 -0
  363. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/tests/skills/test_parser.py +0 -0
  364. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/tests/snapshots/__snapshots__/test_ui_snapshot_ask_user_question/test_snapshot_ask_user_question_collapsed.svg +0 -0
  365. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/tests/snapshots/__snapshots__/test_ui_snapshot_ask_user_question/test_snapshot_ask_user_question_expanded.svg +0 -0
  366. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/tests/snapshots/__snapshots__/test_ui_snapshot_basic_conversation/test_snapshot_shows_basic_conversation.svg +0 -0
  367. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/tests/snapshots/__snapshots__/test_ui_snapshot_code_block_horizontal_scrolling/test_snapshot_allows_horizontal_scrolling_for_long_code_blocks.svg +0 -0
  368. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/tests/snapshots/__snapshots__/test_ui_snapshot_empty_assistant_before_reasoning/test_snapshot_empty_assistant_removed_when_reasoning_starts.svg +0 -0
  369. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/tests/snapshots/__snapshots__/test_ui_snapshot_modes/test_snapshot_cycle_to_accept_edits_mode.svg +0 -0
  370. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/tests/snapshots/__snapshots__/test_ui_snapshot_modes/test_snapshot_cycle_to_auto_approve_mode.svg +0 -0
  371. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/tests/snapshots/__snapshots__/test_ui_snapshot_modes/test_snapshot_cycle_to_plan_mode.svg +0 -0
  372. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/tests/snapshots/__snapshots__/test_ui_snapshot_modes/test_snapshot_cycle_wraps_to_default.svg +0 -0
  373. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/tests/snapshots/__snapshots__/test_ui_snapshot_modes/test_snapshot_default_mode.svg +0 -0
  374. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/tests/snapshots/__snapshots__/test_ui_snapshot_parallel_tool_calls/test_snapshot_parallel_tool_calls_pending.svg +0 -0
  375. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/tests/snapshots/__snapshots__/test_ui_snapshot_parallel_tool_calls/test_snapshot_parallel_tool_calls_resolved.svg +0 -0
  376. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/tests/snapshots/__snapshots__/test_ui_snapshot_proxy_setup/test_snapshot_proxy_setup_cancel_discards_changes.svg +0 -0
  377. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/tests/snapshots/__snapshots__/test_ui_snapshot_proxy_setup/test_snapshot_proxy_setup_edit_existing_values.svg +0 -0
  378. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/tests/snapshots/__snapshots__/test_ui_snapshot_proxy_setup/test_snapshot_proxy_setup_initial_empty.svg +0 -0
  379. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/tests/snapshots/__snapshots__/test_ui_snapshot_proxy_setup/test_snapshot_proxy_setup_initial_with_values.svg +0 -0
  380. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/tests/snapshots/__snapshots__/test_ui_snapshot_proxy_setup/test_snapshot_proxy_setup_save_error.svg +0 -0
  381. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/tests/snapshots/__snapshots__/test_ui_snapshot_proxy_setup/test_snapshot_proxy_setup_save_new_values.svg +0 -0
  382. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_question_answer_first_advance.svg +0 -0
  383. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_question_first_answered_checkmark.svg +0 -0
  384. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_question_initial.svg +0 -0
  385. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_question_navigate_left_wraps.svg +0 -0
  386. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_question_navigate_right.svg +0 -0
  387. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_question_tab_to_second.svg +0 -0
  388. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_select_initial.svg +0 -0
  389. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_select_mixed_selection.svg +0 -0
  390. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_select_navigate_to_submit.svg +0 -0
  391. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_select_other_with_text.svg +0 -0
  392. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_select_toggle_first.svg +0 -0
  393. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_select_toggle_multiple.svg +0 -0
  394. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_select_untoggle.svg +0 -0
  395. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_question_app_initial.svg +0 -0
  396. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_question_app_navigate_down.svg +0 -0
  397. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_question_app_navigate_to_other.svg +0 -0
  398. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_question_app_navigate_to_third_option.svg +0 -0
  399. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_question_app_navigate_up_wraps.svg +0 -0
  400. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_question_app_other_typing.svg +0 -0
  401. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/tests/snapshots/__snapshots__/test_ui_snapshot_reasoning_content/test_snapshot_buffered_reasoning_yields_before_content.svg +0 -0
  402. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/tests/snapshots/__snapshots__/test_ui_snapshot_reasoning_content/test_snapshot_shows_interleaved_reasoning.svg +0 -0
  403. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/tests/snapshots/__snapshots__/test_ui_snapshot_reasoning_content/test_snapshot_shows_reasoning_content.svg +0 -0
  404. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/tests/snapshots/__snapshots__/test_ui_snapshot_reasoning_content/test_snapshot_shows_reasoning_content_expanded.svg +0 -0
  405. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/tests/snapshots/__snapshots__/test_ui_snapshot_release_update_notification/test_snapshot_shows_release_update_notification.svg +0 -0
  406. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/tests/snapshots/__snapshots__/test_ui_snapshot_session_resume/test_snapshot_shows_resumed_session_messages.svg +0 -0
  407. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/tests/snapshots/__snapshots__/test_ui_snapshot_streaming_tool_call/test_snapshot_tool_call_partial.svg +0 -0
  408. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/tests/snapshots/__snapshots__/test_ui_snapshot_streaming_tool_call/test_snapshot_tool_call_updated.svg +0 -0
  409. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_push_confirmation_cancel_selected.svg +0 -0
  410. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_push_confirmation_multiple_commits.svg +0 -0
  411. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_push_confirmation_single_commit.svg +0 -0
  412. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_status_auth_complete.svg +0 -0
  413. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_status_auth_required.svg +0 -0
  414. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_status_checking_git.svg +0 -0
  415. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_status_complete.svg +0 -0
  416. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_status_error.svg +0 -0
  417. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_status_pushing.svg +0 -0
  418. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_status_sending_token.svg +0 -0
  419. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_status_starting_workflow.svg +0 -0
  420. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/tests/snapshots/__snapshots__/test_ui_snapshot_whats_new/test_snapshot_shows_no_plan_message.svg +0 -0
  421. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/tests/snapshots/__snapshots__/test_ui_snapshot_whats_new/test_snapshot_shows_switch_message.svg +0 -0
  422. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/tests/snapshots/__snapshots__/test_ui_snapshot_whats_new/test_snapshot_shows_upgrade_message.svg +0 -0
  423. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/tests/snapshots/__snapshots__/test_ui_snapshot_whats_new/test_snapshot_shows_whats_new_message.svg +0 -0
  424. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/tests/snapshots/base_snapshot_test_app.py +0 -0
  425. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/tests/snapshots/conftest.py +0 -0
  426. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/tests/snapshots/snap_compare.py +0 -0
  427. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/tests/snapshots/test_ui_snapshot_ask_user_question.py +0 -0
  428. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/tests/snapshots/test_ui_snapshot_basic_conversation.py +0 -0
  429. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/tests/snapshots/test_ui_snapshot_code_block_horizontal_scrolling.py +0 -0
  430. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/tests/snapshots/test_ui_snapshot_empty_assistant_before_reasoning.py +0 -0
  431. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/tests/snapshots/test_ui_snapshot_modes.py +0 -0
  432. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/tests/snapshots/test_ui_snapshot_parallel_tool_calls.py +0 -0
  433. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/tests/snapshots/test_ui_snapshot_proxy_setup.py +0 -0
  434. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/tests/snapshots/test_ui_snapshot_question_app.py +0 -0
  435. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/tests/snapshots/test_ui_snapshot_reasoning_content.py +0 -0
  436. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/tests/snapshots/test_ui_snapshot_release_update_notification.py +0 -0
  437. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/tests/snapshots/test_ui_snapshot_session_resume.py +0 -0
  438. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/tests/snapshots/test_ui_snapshot_streaming_tool_call.py +0 -0
  439. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/tests/snapshots/test_ui_snapshot_teleport.py +0 -0
  440. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/tests/snapshots/test_ui_snapshot_whats_new.py +0 -0
  441. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/tests/stubs/fake_backend.py +0 -0
  442. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/tests/stubs/fake_client.py +0 -0
  443. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/tests/stubs/fake_tool.py +0 -0
  444. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/tests/test_agent_auto_compact.py +0 -0
  445. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/tests/test_agent_backend.py +0 -0
  446. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/tests/test_agent_observer_streaming.py +0 -0
  447. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/tests/test_agent_stats.py +0 -0
  448. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/tests/test_agent_tasks.py +0 -0
  449. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/tests/test_agent_tool_call.py +0 -0
  450. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/tests/test_agents.py +0 -0
  451. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/tests/test_cli_programmatic_preload.py +0 -0
  452. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/tests/test_current_bugs.py +0 -0
  453. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/tests/test_drydock_regression.py +0 -0
  454. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/tests/test_drydock_tasks.py +0 -0
  455. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/tests/test_history_manager.py +0 -0
  456. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/tests/test_integration.py +0 -0
  457. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/tests/test_loop_detection.py +0 -0
  458. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/tests/test_message_id.py +0 -0
  459. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/tests/test_message_merging.py +0 -0
  460. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/tests/test_middleware.py +0 -0
  461. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/tests/test_real_failures.py +0 -0
  462. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/tests/test_real_issues.py +0 -0
  463. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/tests/test_reasoning_content.py +0 -0
  464. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/tests/test_system_prompt.py +0 -0
  465. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/tests/test_tagged_text.py +0 -0
  466. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/tests/test_ui_external_editor.py +0 -0
  467. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/tests/test_ui_input_history.py +0 -0
  468. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/tests/test_user_issues.py +0 -0
  469. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/tests/tools/test_ask_user_question.py +0 -0
  470. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/tests/tools/test_bash.py +0 -0
  471. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/tests/tools/test_exit_plan_mode.py +0 -0
  472. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/tests/tools/test_grep.py +0 -0
  473. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/tests/tools/test_invoke_context.py +0 -0
  474. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/tests/tools/test_manager_get_tool_config.py +0 -0
  475. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/tests/tools/test_mcp.py +0 -0
  476. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/tests/tools/test_mcp_sampling.py +0 -0
  477. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/tests/tools/test_task.py +0 -0
  478. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/tests/tools/test_ui_bash_execution.py +0 -0
  479. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/tests/tools/test_webfetch.py +0 -0
  480. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/tests/tools/test_websearch.py +0 -0
  481. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/tests/update_notifier/adapters/fake_update_cache_repository.py +0 -0
  482. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/tests/update_notifier/adapters/fake_update_gateway.py +0 -0
  483. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/tests/update_notifier/test_do_update.py +0 -0
  484. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/tests/update_notifier/test_filesystem_update_cache_repository.py +0 -0
  485. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/tests/update_notifier/test_github_update_gateway.py +0 -0
  486. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/tests/update_notifier/test_pypi_update_gateway.py +0 -0
  487. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/tests/update_notifier/test_ui_update_notification.py +0 -0
  488. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/tests/update_notifier/test_update_use_case.py +0 -0
  489. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/tests/update_notifier/test_whats_new.py +0 -0
  490. {drydock_cli-0.9.0 → drydock_cli-1.1.0}/uv.lock +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: drydock-cli
3
- Version: 0.9.0
3
+ Version: 1.1.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,123 @@
1
+ """Subagent persistent memory — cross-session learning.
2
+
3
+ Each subagent can store and recall memories that persist across sessions.
4
+ Memories are stored as markdown files in ~/.drydock/agent_memory/<agent_name>/.
5
+
6
+ Types:
7
+ - user: Info about the user's preferences and context
8
+ - project: Project-specific decisions and state
9
+ - feedback: Corrections and confirmed approaches
10
+ """
11
+
12
+ from __future__ import annotations
13
+
14
+ import logging
15
+ from datetime import datetime
16
+ from pathlib import Path
17
+
18
+ logger = logging.getLogger(__name__)
19
+
20
+
21
+ def _get_memory_dir(agent_name: str) -> Path:
22
+ """Get the memory directory for a specific agent."""
23
+ try:
24
+ from drydock.core.paths import VIBE_HOME
25
+ base = VIBE_HOME.path / "agent_memory" / agent_name
26
+ except Exception:
27
+ base = Path.home() / ".drydock" / "agent_memory" / agent_name
28
+ base.mkdir(parents=True, exist_ok=True)
29
+ return base
30
+
31
+
32
+ def save_memory(
33
+ agent_name: str,
34
+ key: str,
35
+ content: str,
36
+ memory_type: str = "project",
37
+ ) -> None:
38
+ """Save a memory for an agent."""
39
+ mem_dir = _get_memory_dir(agent_name)
40
+ mem_file = mem_dir / f"{key}.md"
41
+
42
+ text = f"""---
43
+ key: {key}
44
+ type: {memory_type}
45
+ updated: {datetime.now().isoformat()}
46
+ agent: {agent_name}
47
+ ---
48
+
49
+ {content}
50
+ """
51
+ try:
52
+ mem_file.write_text(text, encoding="utf-8")
53
+ logger.info("Saved memory '%s' for agent '%s'", key, agent_name)
54
+ except (OSError, PermissionError) as e:
55
+ logger.warning("Could not save memory: %s", e)
56
+
57
+
58
+ def load_memories(agent_name: str, memory_type: str = "") -> dict[str, str]:
59
+ """Load all memories for an agent, optionally filtered by type."""
60
+ mem_dir = _get_memory_dir(agent_name)
61
+ memories: dict[str, str] = {}
62
+
63
+ try:
64
+ for f in sorted(mem_dir.glob("*.md")):
65
+ content = f.read_text(encoding="utf-8")
66
+ # Check type filter
67
+ if memory_type and f"type: {memory_type}" not in content:
68
+ continue
69
+ # Strip frontmatter
70
+ if content.startswith("---"):
71
+ parts = content.split("---", 2)
72
+ body = parts[2].strip() if len(parts) >= 3 else content
73
+ else:
74
+ body = content
75
+ memories[f.stem] = body
76
+ except (OSError, PermissionError):
77
+ pass
78
+
79
+ return memories
80
+
81
+
82
+ def load_all_memories_as_context(agent_name: str, max_chars: int = 2000) -> str:
83
+ """Load all memories as a context string for injection into prompts."""
84
+ memories = load_memories(agent_name)
85
+ if not memories:
86
+ return ""
87
+
88
+ lines = [f"## Agent Memory ({agent_name})"]
89
+ chars = 0
90
+ for key, content in memories.items():
91
+ entry = f"\n### {key}\n{content[:300]}"
92
+ if chars + len(entry) > max_chars:
93
+ break
94
+ lines.append(entry)
95
+ chars += len(entry)
96
+
97
+ return "\n".join(lines)
98
+
99
+
100
+ def delete_memory(agent_name: str, key: str) -> bool:
101
+ """Delete a specific memory."""
102
+ mem_dir = _get_memory_dir(agent_name)
103
+ mem_file = mem_dir / f"{key}.md"
104
+ try:
105
+ if mem_file.exists():
106
+ mem_file.unlink()
107
+ return True
108
+ except (OSError, PermissionError):
109
+ pass
110
+ return False
111
+
112
+
113
+ def clear_agent_memories(agent_name: str) -> int:
114
+ """Clear all memories for an agent. Returns count of deleted."""
115
+ mem_dir = _get_memory_dir(agent_name)
116
+ count = 0
117
+ try:
118
+ for f in mem_dir.glob("*.md"):
119
+ f.unlink()
120
+ count += 1
121
+ except (OSError, PermissionError):
122
+ pass
123
+ return count
@@ -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,164 @@
1
+ """Cron tools — schedule recurring or one-shot prompts.
2
+
3
+ CronCreate: Schedule a prompt to run on an interval
4
+ CronList: List active scheduled prompts
5
+ CronDelete: Remove a scheduled prompt
6
+ """
7
+
8
+ from __future__ import annotations
9
+
10
+ import asyncio
11
+ from collections.abc import AsyncGenerator
12
+ from typing import ClassVar, final
13
+ from uuid import uuid4
14
+
15
+ from pydantic import BaseModel, Field
16
+
17
+ from drydock.core.tools.base import (
18
+ BaseTool, BaseToolConfig, BaseToolState, InvokeContext, ToolError, ToolPermission,
19
+ )
20
+ from drydock.core.tools.ui import ToolCallDisplay, ToolResultDisplay, ToolUIData
21
+ from drydock.core.types import ToolStreamEvent, ToolResultEvent
22
+
23
+ # In-memory cron store (per session)
24
+ _CRONS: dict[str, dict] = {}
25
+ _CRON_TASKS: dict[str, asyncio.Task] = {}
26
+
27
+
28
+ class CronCreateArgs(BaseModel):
29
+ prompt: str = Field(description="The prompt to run on schedule")
30
+ interval_minutes: int = Field(default=10, description="Interval in minutes between runs")
31
+ name: str = Field(default="", description="Optional name for the cron job")
32
+ max_runs: int = Field(default=0, description="Max runs (0 = unlimited)")
33
+
34
+
35
+ class CronCreateResult(BaseModel):
36
+ cron_id: str
37
+ name: str
38
+ interval_minutes: int
39
+ prompt: str
40
+
41
+
42
+ class CronCreate(
43
+ BaseTool[CronCreateArgs, CronCreateResult, BaseToolConfig, BaseToolState],
44
+ ToolUIData[CronCreateArgs, CronCreateResult],
45
+ ):
46
+ description: ClassVar[str] = "Schedule a prompt to run on a recurring interval."
47
+
48
+ @classmethod
49
+ def format_call_display(cls, args: CronCreateArgs) -> ToolCallDisplay:
50
+ return ToolCallDisplay(summary=f"cron_create: every {args.interval_minutes}m")
51
+
52
+ @classmethod
53
+ def get_result_display(cls, event: ToolResultEvent) -> ToolResultDisplay:
54
+ if isinstance(event.result, CronCreateResult):
55
+ return ToolResultDisplay(success=True, message=f"Cron '{event.result.name}' created")
56
+ return ToolResultDisplay(success=True, message="Cron created")
57
+
58
+ @classmethod
59
+ def get_status_text(cls) -> str:
60
+ return "Creating cron"
61
+
62
+ @final
63
+ async def run(
64
+ self, args: CronCreateArgs, ctx: InvokeContext | None = None
65
+ ) -> AsyncGenerator[ToolStreamEvent | CronCreateResult, None]:
66
+ cron_id = str(uuid4())[:8]
67
+ name = args.name or f"cron-{cron_id}"
68
+
69
+ _CRONS[cron_id] = {
70
+ "id": cron_id,
71
+ "name": name,
72
+ "prompt": args.prompt,
73
+ "interval_minutes": args.interval_minutes,
74
+ "max_runs": args.max_runs,
75
+ "runs": 0,
76
+ "status": "active",
77
+ }
78
+
79
+ yield CronCreateResult(
80
+ cron_id=cron_id, name=name,
81
+ interval_minutes=args.interval_minutes, prompt=args.prompt,
82
+ )
83
+
84
+
85
+ class CronListArgs(BaseModel):
86
+ pass
87
+
88
+
89
+ class CronListResult(BaseModel):
90
+ crons: list[dict]
91
+ count: int
92
+
93
+
94
+ class CronList(
95
+ BaseTool[CronListArgs, CronListResult, BaseToolConfig, BaseToolState],
96
+ ToolUIData[CronListArgs, CronListResult],
97
+ ):
98
+ description: ClassVar[str] = "List all scheduled cron jobs."
99
+
100
+ @classmethod
101
+ def format_call_display(cls, args: CronListArgs) -> ToolCallDisplay:
102
+ return ToolCallDisplay(summary="cron_list")
103
+
104
+ @classmethod
105
+ def get_result_display(cls, event: ToolResultEvent) -> ToolResultDisplay:
106
+ if isinstance(event.result, CronListResult):
107
+ return ToolResultDisplay(success=True, message=f"{event.result.count} crons")
108
+ return ToolResultDisplay(success=True, message="Crons listed")
109
+
110
+ @classmethod
111
+ def get_status_text(cls) -> str:
112
+ return "Listing crons"
113
+
114
+ def resolve_permission(self, args: CronListArgs) -> ToolPermission | None:
115
+ return ToolPermission.ALWAYS
116
+
117
+ @final
118
+ async def run(
119
+ self, args: CronListArgs, ctx: InvokeContext | None = None
120
+ ) -> AsyncGenerator[ToolStreamEvent | CronListResult, None]:
121
+ yield CronListResult(crons=list(_CRONS.values()), count=len(_CRONS))
122
+
123
+
124
+ class CronDeleteArgs(BaseModel):
125
+ cron_id: str = Field(description="ID of the cron job to delete")
126
+
127
+
128
+ class CronDeleteResult(BaseModel):
129
+ cron_id: str
130
+ deleted: bool
131
+
132
+
133
+ class CronDelete(
134
+ BaseTool[CronDeleteArgs, CronDeleteResult, BaseToolConfig, BaseToolState],
135
+ ToolUIData[CronDeleteArgs, CronDeleteResult],
136
+ ):
137
+ description: ClassVar[str] = "Delete a scheduled cron job."
138
+
139
+ @classmethod
140
+ def format_call_display(cls, args: CronDeleteArgs) -> ToolCallDisplay:
141
+ return ToolCallDisplay(summary=f"cron_delete: {args.cron_id}")
142
+
143
+ @classmethod
144
+ def get_result_display(cls, event: ToolResultEvent) -> ToolResultDisplay:
145
+ return ToolResultDisplay(success=True, message="Cron deleted")
146
+
147
+ @classmethod
148
+ def get_status_text(cls) -> str:
149
+ return "Deleting cron"
150
+
151
+ @final
152
+ async def run(
153
+ self, args: CronDeleteArgs, ctx: InvokeContext | None = None
154
+ ) -> AsyncGenerator[ToolStreamEvent | CronDeleteResult, None]:
155
+ if args.cron_id not in _CRONS:
156
+ raise ToolError(f"Cron '{args.cron_id}' not found")
157
+
158
+ # Cancel async task if running
159
+ if args.cron_id in _CRON_TASKS:
160
+ _CRON_TASKS[args.cron_id].cancel()
161
+ del _CRON_TASKS[args.cron_id]
162
+
163
+ del _CRONS[args.cron_id]
164
+ yield CronDeleteResult(cron_id=args.cron_id, deleted=True)
@@ -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,202 @@
1
+ """LSP tool — Language Server Protocol integration.
2
+
3
+ Provides type checking, go-to-definition, find-references,
4
+ and symbol listing via LSP servers (pyright, tsserver, etc.).
5
+ """
6
+
7
+ from __future__ import annotations
8
+
9
+ import asyncio
10
+ import json
11
+ from collections.abc import AsyncGenerator
12
+ from pathlib import Path
13
+ from typing import ClassVar, final
14
+
15
+ from pydantic import BaseModel, Field
16
+
17
+ from drydock.core.tools.base import (
18
+ BaseTool, BaseToolConfig, BaseToolState, InvokeContext, ToolError, ToolPermission,
19
+ )
20
+ from drydock.core.tools.ui import ToolCallDisplay, ToolResultDisplay, ToolUIData
21
+ from drydock.core.types import ToolStreamEvent, ToolResultEvent
22
+
23
+
24
+ class LspArgs(BaseModel):
25
+ action: str = Field(description="Action: 'diagnostics', 'definition', 'references', 'symbols', 'hover'")
26
+ file: str = Field(description="File path")
27
+ line: int = Field(default=0, description="Line number (0-based, for definition/references/hover)")
28
+ column: int = Field(default=0, description="Column number (0-based)")
29
+ symbol: str = Field(default="", description="Symbol name (for symbols action)")
30
+
31
+
32
+ class LspResult(BaseModel):
33
+ action: str
34
+ results: list[dict]
35
+ count: int
36
+ error: str = ""
37
+
38
+
39
+ class LspConfig(BaseToolConfig):
40
+ permission: ToolPermission = ToolPermission.ALWAYS
41
+ pyright_path: str = "pyright"
42
+ timeout: int = 30
43
+
44
+
45
+ class Lsp(
46
+ BaseTool[LspArgs, LspResult, LspConfig, BaseToolState],
47
+ ToolUIData[LspArgs, LspResult],
48
+ ):
49
+ description: ClassVar[str] = (
50
+ "Language server integration: type checking, go-to-definition, "
51
+ "find-references, list symbols. Requires pyright or similar LSP."
52
+ )
53
+
54
+ @classmethod
55
+ def format_call_display(cls, args: LspArgs) -> ToolCallDisplay:
56
+ return ToolCallDisplay(summary=f"lsp: {args.action} {args.file}")
57
+
58
+ @classmethod
59
+ def get_result_display(cls, event: ToolResultEvent) -> ToolResultDisplay:
60
+ if isinstance(event.result, LspResult):
61
+ return ToolResultDisplay(success=True, message=f"{event.result.count} results")
62
+ return ToolResultDisplay(success=True, message="LSP complete")
63
+
64
+ @classmethod
65
+ def get_status_text(cls) -> str:
66
+ return "Running LSP"
67
+
68
+ def resolve_permission(self, args: LspArgs) -> ToolPermission | None:
69
+ return ToolPermission.ALWAYS
70
+
71
+ @final
72
+ async def run(
73
+ self, args: LspArgs, ctx: InvokeContext | None = None
74
+ ) -> AsyncGenerator[ToolStreamEvent | LspResult, None]:
75
+ file_path = Path(args.file).expanduser()
76
+ if not file_path.is_absolute():
77
+ file_path = Path.cwd() / file_path
78
+
79
+ if not file_path.exists():
80
+ raise ToolError(f"File not found: {file_path}")
81
+
82
+ match args.action:
83
+ case "diagnostics":
84
+ yield await self._diagnostics(file_path)
85
+ case "definition":
86
+ yield await self._definition(file_path, args.line, args.column)
87
+ case "references":
88
+ yield await self._references(file_path, args.line, args.column, args.symbol)
89
+ case "symbols":
90
+ yield await self._symbols(file_path)
91
+ case "hover":
92
+ yield await self._hover(file_path, args.line, args.column)
93
+ case _:
94
+ raise ToolError(f"Unknown LSP action: {args.action}. Use: diagnostics, definition, references, symbols, hover")
95
+
96
+ async def _diagnostics(self, file_path: Path) -> LspResult:
97
+ """Run type checking on a file using pyright."""
98
+ try:
99
+ proc = await asyncio.create_subprocess_exec(
100
+ self.config.pyright_path, "--outputjson", str(file_path),
101
+ stdout=asyncio.subprocess.PIPE, stderr=asyncio.subprocess.PIPE,
102
+ )
103
+ stdout, _ = await asyncio.wait_for(proc.communicate(), timeout=self.config.timeout)
104
+ data = json.loads(stdout.decode())
105
+ diags = []
106
+ for d in data.get("generalDiagnostics", []):
107
+ diags.append({
108
+ "file": d.get("file", str(file_path)),
109
+ "line": d.get("range", {}).get("start", {}).get("line", 0),
110
+ "severity": d.get("severity", "error"),
111
+ "message": d.get("message", ""),
112
+ })
113
+ return LspResult(action="diagnostics", results=diags[:50], count=len(diags))
114
+ except FileNotFoundError:
115
+ return LspResult(action="diagnostics", results=[], count=0,
116
+ error=f"pyright not found. Install: pip install pyright")
117
+ except Exception as e:
118
+ return LspResult(action="diagnostics", results=[], count=0, error=str(e))
119
+
120
+ async def _definition(self, file_path: Path, line: int, col: int) -> LspResult:
121
+ """Find definition of symbol at position (uses grep as fallback)."""
122
+ # Read the line to get the symbol
123
+ try:
124
+ lines = file_path.read_text().split("\n")
125
+ if line < len(lines):
126
+ text = lines[line]
127
+ # Extract word at column
128
+ import re
129
+ words = re.findall(r'\b\w+\b', text)
130
+ symbol = ""
131
+ pos = 0
132
+ for w in words:
133
+ idx = text.find(w, pos)
134
+ if idx <= col <= idx + len(w):
135
+ symbol = w
136
+ break
137
+ pos = idx + len(w)
138
+
139
+ if symbol:
140
+ # grep for definition
141
+ proc = await asyncio.create_subprocess_exec(
142
+ "grep", "-rn", f"def {symbol}\\|class {symbol}", str(file_path.parent),
143
+ stdout=asyncio.subprocess.PIPE, stderr=asyncio.subprocess.PIPE,
144
+ )
145
+ stdout, _ = await asyncio.wait_for(proc.communicate(), timeout=10)
146
+ results = []
147
+ for hit in stdout.decode().strip().split("\n")[:10]:
148
+ if hit:
149
+ results.append({"location": hit})
150
+ return LspResult(action="definition", results=results, count=len(results))
151
+ except Exception as e:
152
+ return LspResult(action="definition", results=[], count=0, error=str(e))
153
+
154
+ return LspResult(action="definition", results=[], count=0)
155
+
156
+ async def _references(self, file_path: Path, line: int, col: int, symbol: str) -> LspResult:
157
+ """Find all references to a symbol."""
158
+ if not symbol:
159
+ return LspResult(action="references", results=[], count=0, error="No symbol specified")
160
+
161
+ try:
162
+ proc = await asyncio.create_subprocess_exec(
163
+ "grep", "-rn", f"\\b{symbol}\\b", str(file_path.parent),
164
+ "--include=*.py",
165
+ stdout=asyncio.subprocess.PIPE, stderr=asyncio.subprocess.PIPE,
166
+ )
167
+ stdout, _ = await asyncio.wait_for(proc.communicate(), timeout=10)
168
+ results = []
169
+ for hit in stdout.decode().strip().split("\n")[:30]:
170
+ if hit:
171
+ results.append({"reference": hit})
172
+ return LspResult(action="references", results=results, count=len(results))
173
+ except Exception as e:
174
+ return LspResult(action="references", results=[], count=0, error=str(e))
175
+
176
+ async def _symbols(self, file_path: Path) -> LspResult:
177
+ """List symbols (functions, classes) in a file."""
178
+ try:
179
+ content = file_path.read_text()
180
+ import re
181
+ symbols = []
182
+ for i, line in enumerate(content.split("\n")):
183
+ if match := re.match(r'^(class|def|async def)\s+(\w+)', line):
184
+ symbols.append({
185
+ "kind": match.group(1),
186
+ "name": match.group(2),
187
+ "line": i,
188
+ })
189
+ return LspResult(action="symbols", results=symbols, count=len(symbols))
190
+ except Exception as e:
191
+ return LspResult(action="symbols", results=[], count=0, error=str(e))
192
+
193
+ async def _hover(self, file_path: Path, line: int, col: int) -> LspResult:
194
+ """Get type info for symbol at position."""
195
+ # Fallback: parse the file for type annotations
196
+ try:
197
+ lines = file_path.read_text().split("\n")
198
+ if line < len(lines):
199
+ return LspResult(action="hover", results=[{"line": lines[line].strip()}], count=1)
200
+ except Exception:
201
+ pass
202
+ return LspResult(action="hover", results=[], count=0)