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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (490) hide show
  1. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/PKG-INFO +1 -1
  2. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/drydock/cli/commands.py +5 -0
  3. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/drydock/cli/textual_ui/app.py +49 -1
  4. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/drydock/cli/textual_ui/app.tcss +2 -2
  5. drydock_cli-1.1.1/drydock/core/session/agent_memory.py +123 -0
  6. drydock_cli-1.1.1/drydock/core/tools/builtins/cron.py +164 -0
  7. drydock_cli-1.1.1/drydock/core/tools/builtins/lsp.py +202 -0
  8. drydock_cli-1.1.1/drydock/core/tools/builtins/mcp_resources.py +118 -0
  9. drydock_cli-1.1.1/drydock/core/tools/builtins/powershell.py +116 -0
  10. drydock_cli-1.1.1/drydock/core/tools/builtins/prompts/cron.md +5 -0
  11. drydock_cli-1.1.1/drydock/core/tools/builtins/prompts/lsp.md +9 -0
  12. drydock_cli-1.1.1/drydock/core/tools/builtins/prompts/mcp_resources.md +4 -0
  13. drydock_cli-1.1.1/drydock/core/tools/builtins/prompts/powershell.md +6 -0
  14. drydock_cli-1.1.1/drydock/core/tools/builtins/prompts/tool_search.md +7 -0
  15. drydock_cli-1.1.1/drydock/core/tools/builtins/tool_search.py +120 -0
  16. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/pyproject.toml +1 -1
  17. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/.github/CODEOWNERS +0 -0
  18. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/.github/DISCUSSION_TEMPLATE/ideas.yml +0 -0
  19. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/.github/ISSUE_TEMPLATE/bug-report.yml +0 -0
  20. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/.github/ISSUE_TEMPLATE/config.yml +0 -0
  21. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/.github/workflows/build-and-upload.yml +0 -0
  22. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/.github/workflows/ci.yml +0 -0
  23. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/.github/workflows/issue-labeler.yml +0 -0
  24. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/.github/workflows/release.yml +0 -0
  25. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/.gitignore +0 -0
  26. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/.pre-commit-config.yaml +0 -0
  27. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/.python-version +0 -0
  28. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/.typos.toml +0 -0
  29. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/.vscode/extensions.json +0 -0
  30. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/.vscode/launch.json +0 -0
  31. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/.vscode/settings.json +0 -0
  32. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/AGENTS.md +0 -0
  33. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/CHANGELOG.md +0 -0
  34. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/CLAUDE.md +0 -0
  35. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/CONTRIBUTING.md +0 -0
  36. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/Drydock_rebrand.md +0 -0
  37. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/LICENSE +0 -0
  38. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/NOTICE +0 -0
  39. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/PRD.md +0 -0
  40. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/README.md +0 -0
  41. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/action.yml +0 -0
  42. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/distribution/zed/LICENSE +0 -0
  43. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/distribution/zed/extension.toml +0 -0
  44. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/distribution/zed/icons/mistral_vibe.svg +0 -0
  45. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/docs/README.md +0 -0
  46. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/docs/acp-setup.md +0 -0
  47. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/docs/proxy-setup.md +0 -0
  48. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/drydock/__init__.py +0 -0
  49. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/drydock/acp/__init__.py +0 -0
  50. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/drydock/acp/acp_agent_loop.py +0 -0
  51. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/drydock/acp/acp_logger.py +0 -0
  52. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/drydock/acp/entrypoint.py +0 -0
  53. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/drydock/acp/tools/__init__.py +0 -0
  54. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/drydock/acp/tools/base.py +0 -0
  55. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/drydock/acp/tools/builtins/bash.py +0 -0
  56. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/drydock/acp/tools/builtins/read_file.py +0 -0
  57. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/drydock/acp/tools/builtins/search_replace.py +0 -0
  58. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/drydock/acp/tools/builtins/todo.py +0 -0
  59. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/drydock/acp/tools/builtins/write_file.py +0 -0
  60. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/drydock/acp/tools/session_update.py +0 -0
  61. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/drydock/acp/utils.py +0 -0
  62. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/drydock/cli/__init__.py +0 -0
  63. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/drydock/cli/autocompletion/__init__.py +0 -0
  64. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/drydock/cli/autocompletion/base.py +0 -0
  65. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/drydock/cli/autocompletion/path_completion.py +0 -0
  66. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/drydock/cli/autocompletion/slash_command.py +0 -0
  67. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/drydock/cli/cli.py +0 -0
  68. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/drydock/cli/clipboard.py +0 -0
  69. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/drydock/cli/entrypoint.py +0 -0
  70. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/drydock/cli/history_manager.py +0 -0
  71. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/drydock/cli/plan_offer/adapters/http_whoami_gateway.py +0 -0
  72. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/drydock/cli/plan_offer/decide_plan_offer.py +0 -0
  73. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/drydock/cli/plan_offer/ports/whoami_gateway.py +0 -0
  74. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/drydock/cli/terminal_setup.py +0 -0
  75. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/drydock/cli/textual_ui/__init__.py +0 -0
  76. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/drydock/cli/textual_ui/ansi_markdown.py +0 -0
  77. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/drydock/cli/textual_ui/external_editor.py +0 -0
  78. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/drydock/cli/textual_ui/handlers/__init__.py +0 -0
  79. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/drydock/cli/textual_ui/handlers/event_handler.py +0 -0
  80. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/drydock/cli/textual_ui/notifications/__init__.py +0 -0
  81. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/drydock/cli/textual_ui/notifications/adapters/__init__.py +0 -0
  82. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/drydock/cli/textual_ui/notifications/adapters/textual_notification_adapter.py +0 -0
  83. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/drydock/cli/textual_ui/notifications/ports/__init__.py +0 -0
  84. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/drydock/cli/textual_ui/notifications/ports/notification_port.py +0 -0
  85. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/drydock/cli/textual_ui/widgets/__init__.py +0 -0
  86. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/drydock/cli/textual_ui/widgets/approval_app.py +0 -0
  87. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/drydock/cli/textual_ui/widgets/banner/banner.py +0 -0
  88. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/drydock/cli/textual_ui/widgets/banner/petit_chat.py +0 -0
  89. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/drydock/cli/textual_ui/widgets/braille_renderer.py +0 -0
  90. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/drydock/cli/textual_ui/widgets/chat_input/__init__.py +0 -0
  91. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/drydock/cli/textual_ui/widgets/chat_input/body.py +0 -0
  92. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/drydock/cli/textual_ui/widgets/chat_input/completion_manager.py +0 -0
  93. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/drydock/cli/textual_ui/widgets/chat_input/completion_popup.py +0 -0
  94. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/drydock/cli/textual_ui/widgets/chat_input/container.py +0 -0
  95. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/drydock/cli/textual_ui/widgets/chat_input/text_area.py +0 -0
  96. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/drydock/cli/textual_ui/widgets/compact.py +0 -0
  97. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/drydock/cli/textual_ui/widgets/config_app.py +0 -0
  98. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/drydock/cli/textual_ui/widgets/context_progress.py +0 -0
  99. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/drydock/cli/textual_ui/widgets/load_more.py +0 -0
  100. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/drydock/cli/textual_ui/widgets/loading.py +0 -0
  101. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/drydock/cli/textual_ui/widgets/messages.py +0 -0
  102. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/drydock/cli/textual_ui/widgets/no_markup_static.py +0 -0
  103. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/drydock/cli/textual_ui/widgets/path_display.py +0 -0
  104. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/drydock/cli/textual_ui/widgets/proxy_setup_app.py +0 -0
  105. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/drydock/cli/textual_ui/widgets/question_app.py +0 -0
  106. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/drydock/cli/textual_ui/widgets/session_picker.py +0 -0
  107. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/drydock/cli/textual_ui/widgets/spinner.py +0 -0
  108. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/drydock/cli/textual_ui/widgets/status_message.py +0 -0
  109. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/drydock/cli/textual_ui/widgets/teleport_message.py +0 -0
  110. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/drydock/cli/textual_ui/widgets/tool_widgets.py +0 -0
  111. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/drydock/cli/textual_ui/widgets/tools.py +0 -0
  112. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/drydock/cli/textual_ui/widgets/vscode_compat.py +0 -0
  113. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/drydock/cli/textual_ui/windowing/__init__.py +0 -0
  114. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/drydock/cli/textual_ui/windowing/history.py +0 -0
  115. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/drydock/cli/textual_ui/windowing/history_windowing.py +0 -0
  116. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/drydock/cli/textual_ui/windowing/state.py +0 -0
  117. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/drydock/cli/update_notifier/__init__.py +0 -0
  118. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/drydock/cli/update_notifier/adapters/filesystem_update_cache_repository.py +0 -0
  119. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/drydock/cli/update_notifier/adapters/github_update_gateway.py +0 -0
  120. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/drydock/cli/update_notifier/adapters/pypi_update_gateway.py +0 -0
  121. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/drydock/cli/update_notifier/ports/update_cache_repository.py +0 -0
  122. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/drydock/cli/update_notifier/ports/update_gateway.py +0 -0
  123. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/drydock/cli/update_notifier/update.py +0 -0
  124. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/drydock/cli/update_notifier/whats_new.py +0 -0
  125. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/drydock/core/__init__.py +0 -0
  126. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/drydock/core/agent_loop.py +0 -0
  127. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/drydock/core/agents/__init__.py +0 -0
  128. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/drydock/core/agents/manager.py +0 -0
  129. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/drydock/core/agents/models.py +0 -0
  130. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/drydock/core/auth/__init__.py +0 -0
  131. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/drydock/core/auth/crypto.py +0 -0
  132. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/drydock/core/auth/github.py +0 -0
  133. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/drydock/core/autocompletion/__init__.py +0 -0
  134. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/drydock/core/autocompletion/completers.py +0 -0
  135. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/drydock/core/autocompletion/file_indexer/__init__.py +0 -0
  136. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/drydock/core/autocompletion/file_indexer/ignore_rules.py +0 -0
  137. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/drydock/core/autocompletion/file_indexer/indexer.py +0 -0
  138. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/drydock/core/autocompletion/file_indexer/store.py +0 -0
  139. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/drydock/core/autocompletion/file_indexer/watcher.py +0 -0
  140. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/drydock/core/autocompletion/fuzzy.py +0 -0
  141. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/drydock/core/autocompletion/path_prompt.py +0 -0
  142. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/drydock/core/autocompletion/path_prompt_adapter.py +0 -0
  143. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/drydock/core/config/__init__.py +0 -0
  144. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/drydock/core/config/_settings.py +0 -0
  145. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/drydock/core/config/harness_files/__init__.py +0 -0
  146. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/drydock/core/config/harness_files/_harness_manager.py +0 -0
  147. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/drydock/core/config/harness_files/_paths.py +0 -0
  148. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/drydock/core/consultant.py +0 -0
  149. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/drydock/core/drydock_states.py +0 -0
  150. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/drydock/core/hooks.py +0 -0
  151. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/drydock/core/llm/__init__.py +0 -0
  152. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/drydock/core/llm/backend/anthropic.py +0 -0
  153. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/drydock/core/llm/backend/base.py +0 -0
  154. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/drydock/core/llm/backend/factory.py +0 -0
  155. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/drydock/core/llm/backend/generic.py +0 -0
  156. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/drydock/core/llm/backend/mistral.py +0 -0
  157. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/drydock/core/llm/backend/reasoning_adapter.py +0 -0
  158. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/drydock/core/llm/backend/vertex.py +0 -0
  159. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/drydock/core/llm/exceptions.py +0 -0
  160. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/drydock/core/llm/format.py +0 -0
  161. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/drydock/core/llm/message_utils.py +0 -0
  162. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/drydock/core/llm/types.py +0 -0
  163. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/drydock/core/logger.py +0 -0
  164. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/drydock/core/middleware.py +0 -0
  165. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/drydock/core/output_formatters.py +0 -0
  166. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/drydock/core/paths/__init__.py +0 -0
  167. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/drydock/core/paths/_local_config_walk.py +0 -0
  168. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/drydock/core/paths/_vibe_home.py +0 -0
  169. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/drydock/core/paths/conventions.py +0 -0
  170. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/drydock/core/plan_session.py +0 -0
  171. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/drydock/core/programmatic.py +0 -0
  172. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/drydock/core/prompts/__init__.py +0 -0
  173. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/drydock/core/prompts/cli.md +0 -0
  174. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/drydock/core/prompts/compact.md +0 -0
  175. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/drydock/core/prompts/dangerous_directory.md +0 -0
  176. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/drydock/core/prompts/diagnostic.md +0 -0
  177. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/drydock/core/prompts/explore.md +0 -0
  178. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/drydock/core/prompts/planner.md +0 -0
  179. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/drydock/core/prompts/project_context.md +0 -0
  180. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/drydock/core/prompts/tests.md +0 -0
  181. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/drydock/core/proxy_setup.py +0 -0
  182. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/drydock/core/session/session_loader.py +0 -0
  183. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/drydock/core/session/session_logger.py +0 -0
  184. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/drydock/core/session/session_migration.py +0 -0
  185. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/drydock/core/session/state_file.py +0 -0
  186. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/drydock/core/skills/__init__.py +0 -0
  187. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/drydock/core/skills/manager.py +0 -0
  188. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/drydock/core/skills/models.py +0 -0
  189. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/drydock/core/skills/parser.py +0 -0
  190. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/drydock/core/slug.py +0 -0
  191. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/drydock/core/system_prompt.py +0 -0
  192. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/drydock/core/telemetry/__init__.py +0 -0
  193. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/drydock/core/telemetry/send.py +0 -0
  194. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/drydock/core/teleport/errors.py +0 -0
  195. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/drydock/core/teleport/git.py +0 -0
  196. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/drydock/core/teleport/nuage.py +0 -0
  197. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/drydock/core/teleport/teleport.py +0 -0
  198. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/drydock/core/teleport/types.py +0 -0
  199. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/drydock/core/tools/base.py +0 -0
  200. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/drydock/core/tools/builtins/ask_user_question.py +0 -0
  201. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/drydock/core/tools/builtins/bash.py +0 -0
  202. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/drydock/core/tools/builtins/exit_plan_mode.py +0 -0
  203. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/drydock/core/tools/builtins/glob_tool.py +0 -0
  204. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/drydock/core/tools/builtins/grep.py +0 -0
  205. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/drydock/core/tools/builtins/invoke_skill.py +0 -0
  206. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/drydock/core/tools/builtins/notebook_edit.py +0 -0
  207. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/drydock/core/tools/builtins/prompts/__init__.py +0 -0
  208. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/drydock/core/tools/builtins/prompts/ask_user_question.md +0 -0
  209. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/drydock/core/tools/builtins/prompts/bash.md +0 -0
  210. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/drydock/core/tools/builtins/prompts/glob.md +0 -0
  211. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/drydock/core/tools/builtins/prompts/grep.md +0 -0
  212. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/drydock/core/tools/builtins/prompts/invoke_skill.md +0 -0
  213. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/drydock/core/tools/builtins/prompts/notebook_edit.md +0 -0
  214. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/drydock/core/tools/builtins/prompts/read_file.md +0 -0
  215. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/drydock/core/tools/builtins/prompts/search_replace.md +0 -0
  216. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/drydock/core/tools/builtins/prompts/swe_bench.md +0 -0
  217. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/drydock/core/tools/builtins/prompts/task.md +0 -0
  218. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/drydock/core/tools/builtins/prompts/task_manager.md +0 -0
  219. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/drydock/core/tools/builtins/prompts/todo.md +0 -0
  220. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/drydock/core/tools/builtins/prompts/webfetch.md +0 -0
  221. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/drydock/core/tools/builtins/prompts/websearch.md +0 -0
  222. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/drydock/core/tools/builtins/prompts/worktree.md +0 -0
  223. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/drydock/core/tools/builtins/prompts/write_file.md +0 -0
  224. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/drydock/core/tools/builtins/read_file.py +0 -0
  225. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/drydock/core/tools/builtins/search_replace.py +0 -0
  226. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/drydock/core/tools/builtins/task.py +0 -0
  227. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/drydock/core/tools/builtins/task_manager.py +0 -0
  228. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/drydock/core/tools/builtins/todo.py +0 -0
  229. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/drydock/core/tools/builtins/webfetch.py +0 -0
  230. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/drydock/core/tools/builtins/websearch.py +0 -0
  231. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/drydock/core/tools/builtins/worktree.py +0 -0
  232. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/drydock/core/tools/builtins/write_file.py +0 -0
  233. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/drydock/core/tools/injection_guard.py +0 -0
  234. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/drydock/core/tools/manager.py +0 -0
  235. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/drydock/core/tools/mcp/__init__.py +0 -0
  236. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/drydock/core/tools/mcp/registry.py +0 -0
  237. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/drydock/core/tools/mcp/tools.py +0 -0
  238. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/drydock/core/tools/mcp_sampling.py +0 -0
  239. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/drydock/core/tools/ui.py +0 -0
  240. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/drydock/core/tools/utils.py +0 -0
  241. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/drydock/core/trusted_folders.py +0 -0
  242. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/drydock/core/types.py +0 -0
  243. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/drydock/core/utils.py +0 -0
  244. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/drydock/setup/onboarding/__init__.py +0 -0
  245. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/drydock/setup/onboarding/base.py +0 -0
  246. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/drydock/setup/onboarding/onboarding.tcss +0 -0
  247. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/drydock/setup/onboarding/screens/__init__.py +0 -0
  248. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/drydock/setup/onboarding/screens/api_key.py +0 -0
  249. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/drydock/setup/onboarding/screens/welcome.py +0 -0
  250. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/drydock/setup/trusted_folders/trust_folder_dialog.py +0 -0
  251. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/drydock/setup/trusted_folders/trust_folder_dialog.tcss +0 -0
  252. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/drydock/skills/__init__.py +0 -0
  253. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/drydock/skills/batch/SKILL.md +0 -0
  254. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/drydock/skills/create-presentation/SKILL.md +0 -0
  255. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/drydock/skills/deep-research/SKILL.md +0 -0
  256. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/drydock/skills/investigate/SKILL.md +0 -0
  257. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/drydock/skills/review/SKILL.md +0 -0
  258. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/drydock/skills/ship/SKILL.md +0 -0
  259. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/drydock/skills/simplify/SKILL.md +0 -0
  260. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/drydock/whats_new.md +0 -0
  261. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/drydock-acp.spec +0 -0
  262. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/drydock_terms.md +0 -0
  263. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/flake.lock +0 -0
  264. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/flake.nix +0 -0
  265. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/scripts/README.md +0 -0
  266. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/scripts/backup.sh +0 -0
  267. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/scripts/bump_version.py +0 -0
  268. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/scripts/deploy_to_github.sh +0 -0
  269. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/scripts/install.sh +0 -0
  270. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/scripts/prepare_release.py +0 -0
  271. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/scripts/publish_to_pypi.sh +0 -0
  272. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/tests/__init__.py +0 -0
  273. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/tests/acp/conftest.py +0 -0
  274. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/tests/acp/test_acp.py +0 -0
  275. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/tests/acp/test_agent_thought.py +0 -0
  276. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/tests/acp/test_bash.py +0 -0
  277. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/tests/acp/test_compact_session_updates.py +0 -0
  278. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/tests/acp/test_content.py +0 -0
  279. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/tests/acp/test_initialize.py +0 -0
  280. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/tests/acp/test_list_sessions.py +0 -0
  281. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/tests/acp/test_load_session.py +0 -0
  282. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/tests/acp/test_multi_session.py +0 -0
  283. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/tests/acp/test_new_session.py +0 -0
  284. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/tests/acp/test_proxy_setup_acp.py +0 -0
  285. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/tests/acp/test_read_file.py +0 -0
  286. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/tests/acp/test_search_replace.py +0 -0
  287. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/tests/acp/test_set_config_option.py +0 -0
  288. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/tests/acp/test_set_mode.py +0 -0
  289. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/tests/acp/test_set_model.py +0 -0
  290. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/tests/acp/test_tool_call_session_update.py +0 -0
  291. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/tests/acp/test_utils.py +0 -0
  292. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/tests/acp/test_write_file.py +0 -0
  293. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/tests/autocompletion/test_file_indexer.py +0 -0
  294. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/tests/autocompletion/test_fuzzy.py +0 -0
  295. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/tests/autocompletion/test_path_completer_fuzzy.py +0 -0
  296. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/tests/autocompletion/test_path_completer_recursive.py +0 -0
  297. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/tests/autocompletion/test_path_completion_controller.py +0 -0
  298. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/tests/autocompletion/test_path_prompt_transformer.py +0 -0
  299. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/tests/autocompletion/test_slash_command_controller.py +0 -0
  300. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/tests/autocompletion/test_ui_chat_autocompletion.py +0 -0
  301. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/tests/backend/__init__.py +0 -0
  302. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/tests/backend/data/__init__.py +0 -0
  303. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/tests/backend/data/fireworks.py +0 -0
  304. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/tests/backend/data/mistral.py +0 -0
  305. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/tests/backend/test_anthropic_adapter.py +0 -0
  306. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/tests/backend/test_backend.py +0 -0
  307. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/tests/backend/test_reasoning_adapter.py +0 -0
  308. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/tests/backend/test_vertex_anthropic_adapter.py +0 -0
  309. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/tests/cli/plan_offer/adapters/fake_whoami_gateway.py +0 -0
  310. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/tests/cli/plan_offer/test_decide_plan_offer.py +0 -0
  311. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/tests/cli/plan_offer/test_http_whoami_gateway.py +0 -0
  312. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/tests/cli/test_bell_notifications.py +0 -0
  313. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/tests/cli/test_braille_renderer.py +0 -0
  314. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/tests/cli/test_clipboard.py +0 -0
  315. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/tests/cli/test_commands.py +0 -0
  316. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/tests/cli/test_copy_shortcuts.py +0 -0
  317. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/tests/cli/test_external_editor.py +0 -0
  318. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/tests/cli/test_no_markup_static.py +0 -0
  319. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/tests/cli/test_question_app.py +0 -0
  320. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/tests/cli/test_spinner.py +0 -0
  321. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/tests/cli/test_switching_mode.py +0 -0
  322. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/tests/cli/test_ui_clipboard_notifications.py +0 -0
  323. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/tests/cli/test_ui_session_incremental_renderer.py +0 -0
  324. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/tests/cli/test_ui_session_resume.py +0 -0
  325. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/tests/cli/test_ui_skill_dispatch.py +0 -0
  326. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/tests/cli/textual_ui/__init__.py +0 -0
  327. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/tests/cli/textual_ui/test_session_picker.py +0 -0
  328. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/tests/conftest.py +0 -0
  329. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/tests/core/test_agents.py +0 -0
  330. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/tests/core/test_auth_crypto.py +0 -0
  331. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/tests/core/test_auth_github.py +0 -0
  332. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/tests/core/test_config_load_dotenv.py +0 -0
  333. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/tests/core/test_config_paths.py +0 -0
  334. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/tests/core/test_config_resolution.py +0 -0
  335. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/tests/core/test_file_logging.py +0 -0
  336. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/tests/core/test_plan_session.py +0 -0
  337. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/tests/core/test_proxy_setup.py +0 -0
  338. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/tests/core/test_slug.py +0 -0
  339. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/tests/core/test_telemetry_send.py +0 -0
  340. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/tests/core/test_teleport_git.py +0 -0
  341. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/tests/core/test_teleport_nuage.py +0 -0
  342. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/tests/core/test_teleport_service.py +0 -0
  343. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/tests/core/test_trusted_folders.py +0 -0
  344. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/tests/core/test_utils.py +0 -0
  345. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/tests/e2e/common.py +0 -0
  346. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/tests/e2e/conftest.py +0 -0
  347. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/tests/e2e/mock_server.py +0 -0
  348. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/tests/e2e/test_cli_tui_onboarding.py +0 -0
  349. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/tests/e2e/test_cli_tui_streaming.py +0 -0
  350. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/tests/e2e/test_cli_tui_tool_approval.py +0 -0
  351. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/tests/mock/__init__.py +0 -0
  352. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/tests/mock/mock_backend_factory.py +0 -0
  353. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/tests/mock/mock_entrypoint.py +0 -0
  354. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/tests/mock/utils.py +0 -0
  355. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/tests/onboarding/test_run_onboarding.py +0 -0
  356. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/tests/onboarding/test_ui_onboarding.py +0 -0
  357. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/tests/session/test_session_loader.py +0 -0
  358. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/tests/session/test_session_logger.py +0 -0
  359. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/tests/session/test_session_migration.py +0 -0
  360. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/tests/skills/conftest.py +0 -0
  361. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/tests/skills/test_manager.py +0 -0
  362. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/tests/skills/test_models.py +0 -0
  363. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/tests/skills/test_parser.py +0 -0
  364. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/tests/snapshots/__snapshots__/test_ui_snapshot_ask_user_question/test_snapshot_ask_user_question_collapsed.svg +0 -0
  365. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/tests/snapshots/__snapshots__/test_ui_snapshot_ask_user_question/test_snapshot_ask_user_question_expanded.svg +0 -0
  366. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/tests/snapshots/__snapshots__/test_ui_snapshot_basic_conversation/test_snapshot_shows_basic_conversation.svg +0 -0
  367. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/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-1.0.0 → drydock_cli-1.1.1}/tests/snapshots/__snapshots__/test_ui_snapshot_empty_assistant_before_reasoning/test_snapshot_empty_assistant_removed_when_reasoning_starts.svg +0 -0
  369. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/tests/snapshots/__snapshots__/test_ui_snapshot_modes/test_snapshot_cycle_to_accept_edits_mode.svg +0 -0
  370. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/tests/snapshots/__snapshots__/test_ui_snapshot_modes/test_snapshot_cycle_to_auto_approve_mode.svg +0 -0
  371. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/tests/snapshots/__snapshots__/test_ui_snapshot_modes/test_snapshot_cycle_to_plan_mode.svg +0 -0
  372. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/tests/snapshots/__snapshots__/test_ui_snapshot_modes/test_snapshot_cycle_wraps_to_default.svg +0 -0
  373. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/tests/snapshots/__snapshots__/test_ui_snapshot_modes/test_snapshot_default_mode.svg +0 -0
  374. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/tests/snapshots/__snapshots__/test_ui_snapshot_parallel_tool_calls/test_snapshot_parallel_tool_calls_pending.svg +0 -0
  375. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/tests/snapshots/__snapshots__/test_ui_snapshot_parallel_tool_calls/test_snapshot_parallel_tool_calls_resolved.svg +0 -0
  376. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/tests/snapshots/__snapshots__/test_ui_snapshot_proxy_setup/test_snapshot_proxy_setup_cancel_discards_changes.svg +0 -0
  377. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/tests/snapshots/__snapshots__/test_ui_snapshot_proxy_setup/test_snapshot_proxy_setup_edit_existing_values.svg +0 -0
  378. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/tests/snapshots/__snapshots__/test_ui_snapshot_proxy_setup/test_snapshot_proxy_setup_initial_empty.svg +0 -0
  379. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/tests/snapshots/__snapshots__/test_ui_snapshot_proxy_setup/test_snapshot_proxy_setup_initial_with_values.svg +0 -0
  380. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/tests/snapshots/__snapshots__/test_ui_snapshot_proxy_setup/test_snapshot_proxy_setup_save_error.svg +0 -0
  381. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/tests/snapshots/__snapshots__/test_ui_snapshot_proxy_setup/test_snapshot_proxy_setup_save_new_values.svg +0 -0
  382. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_question_answer_first_advance.svg +0 -0
  383. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_question_first_answered_checkmark.svg +0 -0
  384. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_question_initial.svg +0 -0
  385. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_question_navigate_left_wraps.svg +0 -0
  386. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_question_navigate_right.svg +0 -0
  387. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_question_tab_to_second.svg +0 -0
  388. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_select_initial.svg +0 -0
  389. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_select_mixed_selection.svg +0 -0
  390. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_select_navigate_to_submit.svg +0 -0
  391. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_select_other_with_text.svg +0 -0
  392. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_select_toggle_first.svg +0 -0
  393. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_select_toggle_multiple.svg +0 -0
  394. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_select_untoggle.svg +0 -0
  395. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_question_app_initial.svg +0 -0
  396. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_question_app_navigate_down.svg +0 -0
  397. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_question_app_navigate_to_other.svg +0 -0
  398. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_question_app_navigate_to_third_option.svg +0 -0
  399. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_question_app_navigate_up_wraps.svg +0 -0
  400. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_question_app_other_typing.svg +0 -0
  401. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/tests/snapshots/__snapshots__/test_ui_snapshot_reasoning_content/test_snapshot_buffered_reasoning_yields_before_content.svg +0 -0
  402. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/tests/snapshots/__snapshots__/test_ui_snapshot_reasoning_content/test_snapshot_shows_interleaved_reasoning.svg +0 -0
  403. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/tests/snapshots/__snapshots__/test_ui_snapshot_reasoning_content/test_snapshot_shows_reasoning_content.svg +0 -0
  404. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/tests/snapshots/__snapshots__/test_ui_snapshot_reasoning_content/test_snapshot_shows_reasoning_content_expanded.svg +0 -0
  405. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/tests/snapshots/__snapshots__/test_ui_snapshot_release_update_notification/test_snapshot_shows_release_update_notification.svg +0 -0
  406. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/tests/snapshots/__snapshots__/test_ui_snapshot_session_resume/test_snapshot_shows_resumed_session_messages.svg +0 -0
  407. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/tests/snapshots/__snapshots__/test_ui_snapshot_streaming_tool_call/test_snapshot_tool_call_partial.svg +0 -0
  408. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/tests/snapshots/__snapshots__/test_ui_snapshot_streaming_tool_call/test_snapshot_tool_call_updated.svg +0 -0
  409. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_push_confirmation_cancel_selected.svg +0 -0
  410. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_push_confirmation_multiple_commits.svg +0 -0
  411. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_push_confirmation_single_commit.svg +0 -0
  412. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_status_auth_complete.svg +0 -0
  413. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_status_auth_required.svg +0 -0
  414. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_status_checking_git.svg +0 -0
  415. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_status_complete.svg +0 -0
  416. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_status_error.svg +0 -0
  417. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_status_pushing.svg +0 -0
  418. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_status_sending_token.svg +0 -0
  419. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_status_starting_workflow.svg +0 -0
  420. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/tests/snapshots/__snapshots__/test_ui_snapshot_whats_new/test_snapshot_shows_no_plan_message.svg +0 -0
  421. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/tests/snapshots/__snapshots__/test_ui_snapshot_whats_new/test_snapshot_shows_switch_message.svg +0 -0
  422. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/tests/snapshots/__snapshots__/test_ui_snapshot_whats_new/test_snapshot_shows_upgrade_message.svg +0 -0
  423. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/tests/snapshots/__snapshots__/test_ui_snapshot_whats_new/test_snapshot_shows_whats_new_message.svg +0 -0
  424. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/tests/snapshots/base_snapshot_test_app.py +0 -0
  425. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/tests/snapshots/conftest.py +0 -0
  426. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/tests/snapshots/snap_compare.py +0 -0
  427. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/tests/snapshots/test_ui_snapshot_ask_user_question.py +0 -0
  428. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/tests/snapshots/test_ui_snapshot_basic_conversation.py +0 -0
  429. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/tests/snapshots/test_ui_snapshot_code_block_horizontal_scrolling.py +0 -0
  430. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/tests/snapshots/test_ui_snapshot_empty_assistant_before_reasoning.py +0 -0
  431. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/tests/snapshots/test_ui_snapshot_modes.py +0 -0
  432. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/tests/snapshots/test_ui_snapshot_parallel_tool_calls.py +0 -0
  433. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/tests/snapshots/test_ui_snapshot_proxy_setup.py +0 -0
  434. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/tests/snapshots/test_ui_snapshot_question_app.py +0 -0
  435. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/tests/snapshots/test_ui_snapshot_reasoning_content.py +0 -0
  436. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/tests/snapshots/test_ui_snapshot_release_update_notification.py +0 -0
  437. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/tests/snapshots/test_ui_snapshot_session_resume.py +0 -0
  438. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/tests/snapshots/test_ui_snapshot_streaming_tool_call.py +0 -0
  439. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/tests/snapshots/test_ui_snapshot_teleport.py +0 -0
  440. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/tests/snapshots/test_ui_snapshot_whats_new.py +0 -0
  441. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/tests/stubs/fake_backend.py +0 -0
  442. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/tests/stubs/fake_client.py +0 -0
  443. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/tests/stubs/fake_tool.py +0 -0
  444. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/tests/test_agent_auto_compact.py +0 -0
  445. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/tests/test_agent_backend.py +0 -0
  446. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/tests/test_agent_observer_streaming.py +0 -0
  447. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/tests/test_agent_stats.py +0 -0
  448. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/tests/test_agent_tasks.py +0 -0
  449. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/tests/test_agent_tool_call.py +0 -0
  450. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/tests/test_agents.py +0 -0
  451. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/tests/test_cli_programmatic_preload.py +0 -0
  452. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/tests/test_current_bugs.py +0 -0
  453. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/tests/test_drydock_regression.py +0 -0
  454. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/tests/test_drydock_tasks.py +0 -0
  455. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/tests/test_history_manager.py +0 -0
  456. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/tests/test_integration.py +0 -0
  457. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/tests/test_loop_detection.py +0 -0
  458. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/tests/test_message_id.py +0 -0
  459. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/tests/test_message_merging.py +0 -0
  460. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/tests/test_middleware.py +0 -0
  461. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/tests/test_real_failures.py +0 -0
  462. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/tests/test_real_issues.py +0 -0
  463. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/tests/test_reasoning_content.py +0 -0
  464. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/tests/test_system_prompt.py +0 -0
  465. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/tests/test_tagged_text.py +0 -0
  466. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/tests/test_ui_external_editor.py +0 -0
  467. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/tests/test_ui_input_history.py +0 -0
  468. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/tests/test_user_issues.py +0 -0
  469. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/tests/tools/test_ask_user_question.py +0 -0
  470. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/tests/tools/test_bash.py +0 -0
  471. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/tests/tools/test_exit_plan_mode.py +0 -0
  472. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/tests/tools/test_grep.py +0 -0
  473. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/tests/tools/test_invoke_context.py +0 -0
  474. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/tests/tools/test_manager_get_tool_config.py +0 -0
  475. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/tests/tools/test_mcp.py +0 -0
  476. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/tests/tools/test_mcp_sampling.py +0 -0
  477. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/tests/tools/test_task.py +0 -0
  478. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/tests/tools/test_ui_bash_execution.py +0 -0
  479. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/tests/tools/test_webfetch.py +0 -0
  480. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/tests/tools/test_websearch.py +0 -0
  481. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/tests/update_notifier/adapters/fake_update_cache_repository.py +0 -0
  482. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/tests/update_notifier/adapters/fake_update_gateway.py +0 -0
  483. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/tests/update_notifier/test_do_update.py +0 -0
  484. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/tests/update_notifier/test_filesystem_update_cache_repository.py +0 -0
  485. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/tests/update_notifier/test_github_update_gateway.py +0 -0
  486. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/tests/update_notifier/test_pypi_update_gateway.py +0 -0
  487. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/tests/update_notifier/test_ui_update_notification.py +0 -0
  488. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/tests/update_notifier/test_update_use_case.py +0 -0
  489. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/tests/update_notifier/test_whats_new.py +0 -0
  490. {drydock_cli-1.0.0 → drydock_cli-1.1.1}/uv.lock +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: drydock-cli
3
- Version: 1.0.0
3
+ Version: 1.1.1
4
4
  Summary: Drydock — nautical CLI coding agent
5
5
  Project-URL: Homepage, https://github.com/fbobe321/drydock
6
6
  Project-URL: Repository, https://github.com/fbobe321/drydock
@@ -77,6 +77,11 @@ class CommandRegistry:
77
77
  description="Ask a smarter model for advice (response visible to local model)",
78
78
  handler="_consult_command",
79
79
  ),
80
+ "rewind": Command(
81
+ aliases=frozenset(["/rewind"]),
82
+ description="Undo the last assistant turn and its tool calls",
83
+ handler="_rewind_command",
84
+ ),
80
85
  "resume": Command(
81
86
  aliases=frozenset(["/resume", "/continue"]),
82
87
  description="Browse and resume past sessions",
@@ -143,12 +143,32 @@ class BottomApp(StrEnum):
143
143
 
144
144
 
145
145
  class ChatScroll(VerticalScroll):
146
- """Optimized scroll container that skips cascading style recalculations."""
146
+ """Scroll container for chat messages.
147
+
148
+ Captures mouse scroll to scroll chat history (not terminal history).
149
+ Auto-scrolls to bottom when new messages arrive, unless user has
150
+ scrolled up to review previous messages.
151
+ """
152
+
153
+ can_focus = True # Required for mouse scroll capture
147
154
 
148
155
  @property
149
156
  def is_at_bottom(self) -> bool:
150
157
  return self.scroll_offset.y >= (self.max_scroll_y - 3)
151
158
 
159
+ def on_mount(self) -> None:
160
+ self.focus() # Focus on mount so scroll events go here
161
+
162
+ def on_mouse_scroll_down(self, event: object) -> None:
163
+ """Scroll down in chat history."""
164
+ self.scroll_down(3)
165
+ event.stop() # Prevent terminal from scrolling
166
+
167
+ def on_mouse_scroll_up(self, event: object) -> None:
168
+ """Scroll up in chat history."""
169
+ self.scroll_up(3)
170
+ event.stop() # Prevent terminal from scrolling
171
+
152
172
  def update_node_styles(self, animate: bool = True) -> None:
153
173
  pass
154
174
 
@@ -922,6 +942,34 @@ class VibeApp(App): # noqa: PLR0904
922
942
  help_text = self.commands.get_help_text()
923
943
  await self._mount_and_scroll(UserCommandMessage(help_text))
924
944
 
945
+ async def _rewind_command(self, args: str = "") -> None:
946
+ """Undo the last assistant turn and its tool calls."""
947
+ if self._agent_running:
948
+ await self._mount_and_scroll(
949
+ ErrorMessage("Cannot rewind while agent is running.", collapsed=self._tools_collapsed)
950
+ )
951
+ return
952
+
953
+ # Find and remove the last assistant turn (assistant + tool messages)
954
+ removed = 0
955
+ while len(self.agent_loop.messages) > 1:
956
+ last = self.agent_loop.messages[-1]
957
+ if last.role == Role.system:
958
+ break
959
+ if last.role == Role.user and removed > 0:
960
+ break # Stop before the user message that triggered the turn
961
+ self.agent_loop.messages.reset(list(self.agent_loop.messages[:-1]))
962
+ removed += 1
963
+
964
+ if removed > 0:
965
+ await self._mount_and_scroll(
966
+ UserCommandMessage(f"Rewound {removed} messages. You can now re-prompt.")
967
+ )
968
+ else:
969
+ await self._mount_and_scroll(
970
+ UserCommandMessage("Nothing to rewind.")
971
+ )
972
+
925
973
  async def _show_status(self) -> None:
926
974
  stats = self.agent_loop.stats
927
975
  status_text = f"""## Agent Statistics
@@ -24,12 +24,12 @@ TextArea > .text-area--cursor {
24
24
  }
25
25
 
26
26
  #chat {
27
- layout: stream;
28
27
  height: 1fr;
29
28
  width: 100%;
30
29
  background: transparent;
31
30
  padding: 0;
32
- align-vertical: bottom;
31
+ overflow-y: scroll;
32
+ scrollbar-size-vertical: 1;
33
33
  }
34
34
 
35
35
  #loading-area {
@@ -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
@@ -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,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)