drydock-cli 1.0.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-1.0.0 → drydock_cli-1.1.0}/PKG-INFO +1 -1
  2. drydock_cli-1.1.0/drydock/core/session/agent_memory.py +123 -0
  3. drydock_cli-1.1.0/drydock/core/tools/builtins/cron.py +164 -0
  4. drydock_cli-1.1.0/drydock/core/tools/builtins/lsp.py +202 -0
  5. drydock_cli-1.1.0/drydock/core/tools/builtins/mcp_resources.py +118 -0
  6. drydock_cli-1.1.0/drydock/core/tools/builtins/powershell.py +116 -0
  7. drydock_cli-1.1.0/drydock/core/tools/builtins/prompts/cron.md +5 -0
  8. drydock_cli-1.1.0/drydock/core/tools/builtins/prompts/lsp.md +9 -0
  9. drydock_cli-1.1.0/drydock/core/tools/builtins/prompts/mcp_resources.md +4 -0
  10. drydock_cli-1.1.0/drydock/core/tools/builtins/prompts/powershell.md +6 -0
  11. drydock_cli-1.1.0/drydock/core/tools/builtins/prompts/tool_search.md +7 -0
  12. drydock_cli-1.1.0/drydock/core/tools/builtins/tool_search.py +120 -0
  13. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/pyproject.toml +1 -1
  14. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/.github/CODEOWNERS +0 -0
  15. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/.github/DISCUSSION_TEMPLATE/ideas.yml +0 -0
  16. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/.github/ISSUE_TEMPLATE/bug-report.yml +0 -0
  17. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/.github/ISSUE_TEMPLATE/config.yml +0 -0
  18. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/.github/workflows/build-and-upload.yml +0 -0
  19. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/.github/workflows/ci.yml +0 -0
  20. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/.github/workflows/issue-labeler.yml +0 -0
  21. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/.github/workflows/release.yml +0 -0
  22. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/.gitignore +0 -0
  23. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/.pre-commit-config.yaml +0 -0
  24. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/.python-version +0 -0
  25. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/.typos.toml +0 -0
  26. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/.vscode/extensions.json +0 -0
  27. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/.vscode/launch.json +0 -0
  28. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/.vscode/settings.json +0 -0
  29. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/AGENTS.md +0 -0
  30. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/CHANGELOG.md +0 -0
  31. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/CLAUDE.md +0 -0
  32. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/CONTRIBUTING.md +0 -0
  33. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/Drydock_rebrand.md +0 -0
  34. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/LICENSE +0 -0
  35. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/NOTICE +0 -0
  36. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/PRD.md +0 -0
  37. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/README.md +0 -0
  38. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/action.yml +0 -0
  39. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/distribution/zed/LICENSE +0 -0
  40. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/distribution/zed/extension.toml +0 -0
  41. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/distribution/zed/icons/mistral_vibe.svg +0 -0
  42. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/docs/README.md +0 -0
  43. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/docs/acp-setup.md +0 -0
  44. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/docs/proxy-setup.md +0 -0
  45. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/drydock/__init__.py +0 -0
  46. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/drydock/acp/__init__.py +0 -0
  47. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/drydock/acp/acp_agent_loop.py +0 -0
  48. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/drydock/acp/acp_logger.py +0 -0
  49. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/drydock/acp/entrypoint.py +0 -0
  50. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/drydock/acp/tools/__init__.py +0 -0
  51. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/drydock/acp/tools/base.py +0 -0
  52. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/drydock/acp/tools/builtins/bash.py +0 -0
  53. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/drydock/acp/tools/builtins/read_file.py +0 -0
  54. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/drydock/acp/tools/builtins/search_replace.py +0 -0
  55. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/drydock/acp/tools/builtins/todo.py +0 -0
  56. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/drydock/acp/tools/builtins/write_file.py +0 -0
  57. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/drydock/acp/tools/session_update.py +0 -0
  58. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/drydock/acp/utils.py +0 -0
  59. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/drydock/cli/__init__.py +0 -0
  60. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/drydock/cli/autocompletion/__init__.py +0 -0
  61. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/drydock/cli/autocompletion/base.py +0 -0
  62. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/drydock/cli/autocompletion/path_completion.py +0 -0
  63. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/drydock/cli/autocompletion/slash_command.py +0 -0
  64. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/drydock/cli/cli.py +0 -0
  65. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/drydock/cli/clipboard.py +0 -0
  66. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/drydock/cli/commands.py +0 -0
  67. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/drydock/cli/entrypoint.py +0 -0
  68. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/drydock/cli/history_manager.py +0 -0
  69. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/drydock/cli/plan_offer/adapters/http_whoami_gateway.py +0 -0
  70. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/drydock/cli/plan_offer/decide_plan_offer.py +0 -0
  71. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/drydock/cli/plan_offer/ports/whoami_gateway.py +0 -0
  72. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/drydock/cli/terminal_setup.py +0 -0
  73. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/drydock/cli/textual_ui/__init__.py +0 -0
  74. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/drydock/cli/textual_ui/ansi_markdown.py +0 -0
  75. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/drydock/cli/textual_ui/app.py +0 -0
  76. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/drydock/cli/textual_ui/app.tcss +0 -0
  77. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/drydock/cli/textual_ui/external_editor.py +0 -0
  78. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/drydock/cli/textual_ui/handlers/__init__.py +0 -0
  79. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/drydock/cli/textual_ui/handlers/event_handler.py +0 -0
  80. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/drydock/cli/textual_ui/notifications/__init__.py +0 -0
  81. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/drydock/cli/textual_ui/notifications/adapters/__init__.py +0 -0
  82. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/drydock/cli/textual_ui/notifications/adapters/textual_notification_adapter.py +0 -0
  83. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/drydock/cli/textual_ui/notifications/ports/__init__.py +0 -0
  84. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/drydock/cli/textual_ui/notifications/ports/notification_port.py +0 -0
  85. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/drydock/cli/textual_ui/widgets/__init__.py +0 -0
  86. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/drydock/cli/textual_ui/widgets/approval_app.py +0 -0
  87. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/drydock/cli/textual_ui/widgets/banner/banner.py +0 -0
  88. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/drydock/cli/textual_ui/widgets/banner/petit_chat.py +0 -0
  89. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/drydock/cli/textual_ui/widgets/braille_renderer.py +0 -0
  90. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/drydock/cli/textual_ui/widgets/chat_input/__init__.py +0 -0
  91. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/drydock/cli/textual_ui/widgets/chat_input/body.py +0 -0
  92. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/drydock/cli/textual_ui/widgets/chat_input/completion_manager.py +0 -0
  93. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/drydock/cli/textual_ui/widgets/chat_input/completion_popup.py +0 -0
  94. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/drydock/cli/textual_ui/widgets/chat_input/container.py +0 -0
  95. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/drydock/cli/textual_ui/widgets/chat_input/text_area.py +0 -0
  96. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/drydock/cli/textual_ui/widgets/compact.py +0 -0
  97. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/drydock/cli/textual_ui/widgets/config_app.py +0 -0
  98. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/drydock/cli/textual_ui/widgets/context_progress.py +0 -0
  99. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/drydock/cli/textual_ui/widgets/load_more.py +0 -0
  100. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/drydock/cli/textual_ui/widgets/loading.py +0 -0
  101. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/drydock/cli/textual_ui/widgets/messages.py +0 -0
  102. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/drydock/cli/textual_ui/widgets/no_markup_static.py +0 -0
  103. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/drydock/cli/textual_ui/widgets/path_display.py +0 -0
  104. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/drydock/cli/textual_ui/widgets/proxy_setup_app.py +0 -0
  105. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/drydock/cli/textual_ui/widgets/question_app.py +0 -0
  106. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/drydock/cli/textual_ui/widgets/session_picker.py +0 -0
  107. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/drydock/cli/textual_ui/widgets/spinner.py +0 -0
  108. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/drydock/cli/textual_ui/widgets/status_message.py +0 -0
  109. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/drydock/cli/textual_ui/widgets/teleport_message.py +0 -0
  110. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/drydock/cli/textual_ui/widgets/tool_widgets.py +0 -0
  111. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/drydock/cli/textual_ui/widgets/tools.py +0 -0
  112. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/drydock/cli/textual_ui/widgets/vscode_compat.py +0 -0
  113. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/drydock/cli/textual_ui/windowing/__init__.py +0 -0
  114. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/drydock/cli/textual_ui/windowing/history.py +0 -0
  115. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/drydock/cli/textual_ui/windowing/history_windowing.py +0 -0
  116. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/drydock/cli/textual_ui/windowing/state.py +0 -0
  117. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/drydock/cli/update_notifier/__init__.py +0 -0
  118. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/drydock/cli/update_notifier/adapters/filesystem_update_cache_repository.py +0 -0
  119. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/drydock/cli/update_notifier/adapters/github_update_gateway.py +0 -0
  120. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/drydock/cli/update_notifier/adapters/pypi_update_gateway.py +0 -0
  121. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/drydock/cli/update_notifier/ports/update_cache_repository.py +0 -0
  122. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/drydock/cli/update_notifier/ports/update_gateway.py +0 -0
  123. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/drydock/cli/update_notifier/update.py +0 -0
  124. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/drydock/cli/update_notifier/whats_new.py +0 -0
  125. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/drydock/core/__init__.py +0 -0
  126. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/drydock/core/agent_loop.py +0 -0
  127. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/drydock/core/agents/__init__.py +0 -0
  128. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/drydock/core/agents/manager.py +0 -0
  129. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/drydock/core/agents/models.py +0 -0
  130. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/drydock/core/auth/__init__.py +0 -0
  131. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/drydock/core/auth/crypto.py +0 -0
  132. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/drydock/core/auth/github.py +0 -0
  133. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/drydock/core/autocompletion/__init__.py +0 -0
  134. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/drydock/core/autocompletion/completers.py +0 -0
  135. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/drydock/core/autocompletion/file_indexer/__init__.py +0 -0
  136. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/drydock/core/autocompletion/file_indexer/ignore_rules.py +0 -0
  137. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/drydock/core/autocompletion/file_indexer/indexer.py +0 -0
  138. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/drydock/core/autocompletion/file_indexer/store.py +0 -0
  139. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/drydock/core/autocompletion/file_indexer/watcher.py +0 -0
  140. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/drydock/core/autocompletion/fuzzy.py +0 -0
  141. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/drydock/core/autocompletion/path_prompt.py +0 -0
  142. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/drydock/core/autocompletion/path_prompt_adapter.py +0 -0
  143. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/drydock/core/config/__init__.py +0 -0
  144. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/drydock/core/config/_settings.py +0 -0
  145. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/drydock/core/config/harness_files/__init__.py +0 -0
  146. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/drydock/core/config/harness_files/_harness_manager.py +0 -0
  147. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/drydock/core/config/harness_files/_paths.py +0 -0
  148. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/drydock/core/consultant.py +0 -0
  149. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/drydock/core/drydock_states.py +0 -0
  150. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/drydock/core/hooks.py +0 -0
  151. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/drydock/core/llm/__init__.py +0 -0
  152. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/drydock/core/llm/backend/anthropic.py +0 -0
  153. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/drydock/core/llm/backend/base.py +0 -0
  154. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/drydock/core/llm/backend/factory.py +0 -0
  155. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/drydock/core/llm/backend/generic.py +0 -0
  156. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/drydock/core/llm/backend/mistral.py +0 -0
  157. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/drydock/core/llm/backend/reasoning_adapter.py +0 -0
  158. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/drydock/core/llm/backend/vertex.py +0 -0
  159. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/drydock/core/llm/exceptions.py +0 -0
  160. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/drydock/core/llm/format.py +0 -0
  161. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/drydock/core/llm/message_utils.py +0 -0
  162. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/drydock/core/llm/types.py +0 -0
  163. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/drydock/core/logger.py +0 -0
  164. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/drydock/core/middleware.py +0 -0
  165. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/drydock/core/output_formatters.py +0 -0
  166. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/drydock/core/paths/__init__.py +0 -0
  167. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/drydock/core/paths/_local_config_walk.py +0 -0
  168. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/drydock/core/paths/_vibe_home.py +0 -0
  169. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/drydock/core/paths/conventions.py +0 -0
  170. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/drydock/core/plan_session.py +0 -0
  171. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/drydock/core/programmatic.py +0 -0
  172. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/drydock/core/prompts/__init__.py +0 -0
  173. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/drydock/core/prompts/cli.md +0 -0
  174. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/drydock/core/prompts/compact.md +0 -0
  175. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/drydock/core/prompts/dangerous_directory.md +0 -0
  176. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/drydock/core/prompts/diagnostic.md +0 -0
  177. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/drydock/core/prompts/explore.md +0 -0
  178. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/drydock/core/prompts/planner.md +0 -0
  179. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/drydock/core/prompts/project_context.md +0 -0
  180. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/drydock/core/prompts/tests.md +0 -0
  181. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/drydock/core/proxy_setup.py +0 -0
  182. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/drydock/core/session/session_loader.py +0 -0
  183. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/drydock/core/session/session_logger.py +0 -0
  184. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/drydock/core/session/session_migration.py +0 -0
  185. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/drydock/core/session/state_file.py +0 -0
  186. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/drydock/core/skills/__init__.py +0 -0
  187. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/drydock/core/skills/manager.py +0 -0
  188. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/drydock/core/skills/models.py +0 -0
  189. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/drydock/core/skills/parser.py +0 -0
  190. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/drydock/core/slug.py +0 -0
  191. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/drydock/core/system_prompt.py +0 -0
  192. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/drydock/core/telemetry/__init__.py +0 -0
  193. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/drydock/core/telemetry/send.py +0 -0
  194. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/drydock/core/teleport/errors.py +0 -0
  195. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/drydock/core/teleport/git.py +0 -0
  196. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/drydock/core/teleport/nuage.py +0 -0
  197. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/drydock/core/teleport/teleport.py +0 -0
  198. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/drydock/core/teleport/types.py +0 -0
  199. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/drydock/core/tools/base.py +0 -0
  200. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/drydock/core/tools/builtins/ask_user_question.py +0 -0
  201. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/drydock/core/tools/builtins/bash.py +0 -0
  202. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/drydock/core/tools/builtins/exit_plan_mode.py +0 -0
  203. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/drydock/core/tools/builtins/glob_tool.py +0 -0
  204. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/drydock/core/tools/builtins/grep.py +0 -0
  205. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/drydock/core/tools/builtins/invoke_skill.py +0 -0
  206. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/drydock/core/tools/builtins/notebook_edit.py +0 -0
  207. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/drydock/core/tools/builtins/prompts/__init__.py +0 -0
  208. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/drydock/core/tools/builtins/prompts/ask_user_question.md +0 -0
  209. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/drydock/core/tools/builtins/prompts/bash.md +0 -0
  210. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/drydock/core/tools/builtins/prompts/glob.md +0 -0
  211. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/drydock/core/tools/builtins/prompts/grep.md +0 -0
  212. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/drydock/core/tools/builtins/prompts/invoke_skill.md +0 -0
  213. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/drydock/core/tools/builtins/prompts/notebook_edit.md +0 -0
  214. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/drydock/core/tools/builtins/prompts/read_file.md +0 -0
  215. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/drydock/core/tools/builtins/prompts/search_replace.md +0 -0
  216. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/drydock/core/tools/builtins/prompts/swe_bench.md +0 -0
  217. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/drydock/core/tools/builtins/prompts/task.md +0 -0
  218. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/drydock/core/tools/builtins/prompts/task_manager.md +0 -0
  219. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/drydock/core/tools/builtins/prompts/todo.md +0 -0
  220. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/drydock/core/tools/builtins/prompts/webfetch.md +0 -0
  221. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/drydock/core/tools/builtins/prompts/websearch.md +0 -0
  222. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/drydock/core/tools/builtins/prompts/worktree.md +0 -0
  223. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/drydock/core/tools/builtins/prompts/write_file.md +0 -0
  224. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/drydock/core/tools/builtins/read_file.py +0 -0
  225. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/drydock/core/tools/builtins/search_replace.py +0 -0
  226. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/drydock/core/tools/builtins/task.py +0 -0
  227. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/drydock/core/tools/builtins/task_manager.py +0 -0
  228. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/drydock/core/tools/builtins/todo.py +0 -0
  229. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/drydock/core/tools/builtins/webfetch.py +0 -0
  230. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/drydock/core/tools/builtins/websearch.py +0 -0
  231. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/drydock/core/tools/builtins/worktree.py +0 -0
  232. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/drydock/core/tools/builtins/write_file.py +0 -0
  233. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/drydock/core/tools/injection_guard.py +0 -0
  234. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/drydock/core/tools/manager.py +0 -0
  235. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/drydock/core/tools/mcp/__init__.py +0 -0
  236. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/drydock/core/tools/mcp/registry.py +0 -0
  237. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/drydock/core/tools/mcp/tools.py +0 -0
  238. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/drydock/core/tools/mcp_sampling.py +0 -0
  239. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/drydock/core/tools/ui.py +0 -0
  240. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/drydock/core/tools/utils.py +0 -0
  241. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/drydock/core/trusted_folders.py +0 -0
  242. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/drydock/core/types.py +0 -0
  243. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/drydock/core/utils.py +0 -0
  244. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/drydock/setup/onboarding/__init__.py +0 -0
  245. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/drydock/setup/onboarding/base.py +0 -0
  246. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/drydock/setup/onboarding/onboarding.tcss +0 -0
  247. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/drydock/setup/onboarding/screens/__init__.py +0 -0
  248. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/drydock/setup/onboarding/screens/api_key.py +0 -0
  249. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/drydock/setup/onboarding/screens/welcome.py +0 -0
  250. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/drydock/setup/trusted_folders/trust_folder_dialog.py +0 -0
  251. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/drydock/setup/trusted_folders/trust_folder_dialog.tcss +0 -0
  252. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/drydock/skills/__init__.py +0 -0
  253. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/drydock/skills/batch/SKILL.md +0 -0
  254. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/drydock/skills/create-presentation/SKILL.md +0 -0
  255. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/drydock/skills/deep-research/SKILL.md +0 -0
  256. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/drydock/skills/investigate/SKILL.md +0 -0
  257. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/drydock/skills/review/SKILL.md +0 -0
  258. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/drydock/skills/ship/SKILL.md +0 -0
  259. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/drydock/skills/simplify/SKILL.md +0 -0
  260. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/drydock/whats_new.md +0 -0
  261. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/drydock-acp.spec +0 -0
  262. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/drydock_terms.md +0 -0
  263. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/flake.lock +0 -0
  264. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/flake.nix +0 -0
  265. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/scripts/README.md +0 -0
  266. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/scripts/backup.sh +0 -0
  267. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/scripts/bump_version.py +0 -0
  268. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/scripts/deploy_to_github.sh +0 -0
  269. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/scripts/install.sh +0 -0
  270. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/scripts/prepare_release.py +0 -0
  271. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/scripts/publish_to_pypi.sh +0 -0
  272. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/tests/__init__.py +0 -0
  273. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/tests/acp/conftest.py +0 -0
  274. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/tests/acp/test_acp.py +0 -0
  275. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/tests/acp/test_agent_thought.py +0 -0
  276. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/tests/acp/test_bash.py +0 -0
  277. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/tests/acp/test_compact_session_updates.py +0 -0
  278. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/tests/acp/test_content.py +0 -0
  279. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/tests/acp/test_initialize.py +0 -0
  280. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/tests/acp/test_list_sessions.py +0 -0
  281. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/tests/acp/test_load_session.py +0 -0
  282. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/tests/acp/test_multi_session.py +0 -0
  283. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/tests/acp/test_new_session.py +0 -0
  284. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/tests/acp/test_proxy_setup_acp.py +0 -0
  285. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/tests/acp/test_read_file.py +0 -0
  286. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/tests/acp/test_search_replace.py +0 -0
  287. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/tests/acp/test_set_config_option.py +0 -0
  288. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/tests/acp/test_set_mode.py +0 -0
  289. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/tests/acp/test_set_model.py +0 -0
  290. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/tests/acp/test_tool_call_session_update.py +0 -0
  291. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/tests/acp/test_utils.py +0 -0
  292. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/tests/acp/test_write_file.py +0 -0
  293. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/tests/autocompletion/test_file_indexer.py +0 -0
  294. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/tests/autocompletion/test_fuzzy.py +0 -0
  295. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/tests/autocompletion/test_path_completer_fuzzy.py +0 -0
  296. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/tests/autocompletion/test_path_completer_recursive.py +0 -0
  297. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/tests/autocompletion/test_path_completion_controller.py +0 -0
  298. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/tests/autocompletion/test_path_prompt_transformer.py +0 -0
  299. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/tests/autocompletion/test_slash_command_controller.py +0 -0
  300. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/tests/autocompletion/test_ui_chat_autocompletion.py +0 -0
  301. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/tests/backend/__init__.py +0 -0
  302. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/tests/backend/data/__init__.py +0 -0
  303. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/tests/backend/data/fireworks.py +0 -0
  304. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/tests/backend/data/mistral.py +0 -0
  305. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/tests/backend/test_anthropic_adapter.py +0 -0
  306. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/tests/backend/test_backend.py +0 -0
  307. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/tests/backend/test_reasoning_adapter.py +0 -0
  308. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/tests/backend/test_vertex_anthropic_adapter.py +0 -0
  309. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/tests/cli/plan_offer/adapters/fake_whoami_gateway.py +0 -0
  310. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/tests/cli/plan_offer/test_decide_plan_offer.py +0 -0
  311. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/tests/cli/plan_offer/test_http_whoami_gateway.py +0 -0
  312. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/tests/cli/test_bell_notifications.py +0 -0
  313. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/tests/cli/test_braille_renderer.py +0 -0
  314. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/tests/cli/test_clipboard.py +0 -0
  315. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/tests/cli/test_commands.py +0 -0
  316. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/tests/cli/test_copy_shortcuts.py +0 -0
  317. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/tests/cli/test_external_editor.py +0 -0
  318. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/tests/cli/test_no_markup_static.py +0 -0
  319. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/tests/cli/test_question_app.py +0 -0
  320. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/tests/cli/test_spinner.py +0 -0
  321. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/tests/cli/test_switching_mode.py +0 -0
  322. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/tests/cli/test_ui_clipboard_notifications.py +0 -0
  323. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/tests/cli/test_ui_session_incremental_renderer.py +0 -0
  324. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/tests/cli/test_ui_session_resume.py +0 -0
  325. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/tests/cli/test_ui_skill_dispatch.py +0 -0
  326. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/tests/cli/textual_ui/__init__.py +0 -0
  327. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/tests/cli/textual_ui/test_session_picker.py +0 -0
  328. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/tests/conftest.py +0 -0
  329. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/tests/core/test_agents.py +0 -0
  330. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/tests/core/test_auth_crypto.py +0 -0
  331. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/tests/core/test_auth_github.py +0 -0
  332. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/tests/core/test_config_load_dotenv.py +0 -0
  333. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/tests/core/test_config_paths.py +0 -0
  334. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/tests/core/test_config_resolution.py +0 -0
  335. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/tests/core/test_file_logging.py +0 -0
  336. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/tests/core/test_plan_session.py +0 -0
  337. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/tests/core/test_proxy_setup.py +0 -0
  338. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/tests/core/test_slug.py +0 -0
  339. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/tests/core/test_telemetry_send.py +0 -0
  340. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/tests/core/test_teleport_git.py +0 -0
  341. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/tests/core/test_teleport_nuage.py +0 -0
  342. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/tests/core/test_teleport_service.py +0 -0
  343. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/tests/core/test_trusted_folders.py +0 -0
  344. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/tests/core/test_utils.py +0 -0
  345. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/tests/e2e/common.py +0 -0
  346. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/tests/e2e/conftest.py +0 -0
  347. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/tests/e2e/mock_server.py +0 -0
  348. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/tests/e2e/test_cli_tui_onboarding.py +0 -0
  349. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/tests/e2e/test_cli_tui_streaming.py +0 -0
  350. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/tests/e2e/test_cli_tui_tool_approval.py +0 -0
  351. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/tests/mock/__init__.py +0 -0
  352. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/tests/mock/mock_backend_factory.py +0 -0
  353. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/tests/mock/mock_entrypoint.py +0 -0
  354. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/tests/mock/utils.py +0 -0
  355. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/tests/onboarding/test_run_onboarding.py +0 -0
  356. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/tests/onboarding/test_ui_onboarding.py +0 -0
  357. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/tests/session/test_session_loader.py +0 -0
  358. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/tests/session/test_session_logger.py +0 -0
  359. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/tests/session/test_session_migration.py +0 -0
  360. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/tests/skills/conftest.py +0 -0
  361. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/tests/skills/test_manager.py +0 -0
  362. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/tests/skills/test_models.py +0 -0
  363. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/tests/skills/test_parser.py +0 -0
  364. {drydock_cli-1.0.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-1.0.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-1.0.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-1.0.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-1.0.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-1.0.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-1.0.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-1.0.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-1.0.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-1.0.0 → drydock_cli-1.1.0}/tests/snapshots/__snapshots__/test_ui_snapshot_modes/test_snapshot_default_mode.svg +0 -0
  374. {drydock_cli-1.0.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-1.0.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-1.0.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-1.0.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-1.0.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-1.0.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-1.0.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-1.0.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-1.0.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-1.0.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-1.0.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-1.0.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-1.0.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-1.0.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-1.0.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-1.0.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-1.0.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-1.0.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-1.0.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-1.0.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-1.0.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-1.0.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-1.0.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-1.0.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-1.0.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-1.0.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-1.0.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-1.0.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-1.0.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-1.0.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-1.0.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-1.0.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-1.0.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-1.0.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-1.0.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-1.0.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-1.0.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-1.0.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-1.0.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-1.0.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-1.0.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-1.0.0 → drydock_cli-1.1.0}/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.0}/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.0}/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.0}/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.0}/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.0}/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.0}/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.0}/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.0}/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.0}/tests/snapshots/base_snapshot_test_app.py +0 -0
  425. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/tests/snapshots/conftest.py +0 -0
  426. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/tests/snapshots/snap_compare.py +0 -0
  427. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/tests/snapshots/test_ui_snapshot_ask_user_question.py +0 -0
  428. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/tests/snapshots/test_ui_snapshot_basic_conversation.py +0 -0
  429. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/tests/snapshots/test_ui_snapshot_code_block_horizontal_scrolling.py +0 -0
  430. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/tests/snapshots/test_ui_snapshot_empty_assistant_before_reasoning.py +0 -0
  431. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/tests/snapshots/test_ui_snapshot_modes.py +0 -0
  432. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/tests/snapshots/test_ui_snapshot_parallel_tool_calls.py +0 -0
  433. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/tests/snapshots/test_ui_snapshot_proxy_setup.py +0 -0
  434. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/tests/snapshots/test_ui_snapshot_question_app.py +0 -0
  435. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/tests/snapshots/test_ui_snapshot_reasoning_content.py +0 -0
  436. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/tests/snapshots/test_ui_snapshot_release_update_notification.py +0 -0
  437. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/tests/snapshots/test_ui_snapshot_session_resume.py +0 -0
  438. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/tests/snapshots/test_ui_snapshot_streaming_tool_call.py +0 -0
  439. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/tests/snapshots/test_ui_snapshot_teleport.py +0 -0
  440. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/tests/snapshots/test_ui_snapshot_whats_new.py +0 -0
  441. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/tests/stubs/fake_backend.py +0 -0
  442. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/tests/stubs/fake_client.py +0 -0
  443. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/tests/stubs/fake_tool.py +0 -0
  444. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/tests/test_agent_auto_compact.py +0 -0
  445. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/tests/test_agent_backend.py +0 -0
  446. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/tests/test_agent_observer_streaming.py +0 -0
  447. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/tests/test_agent_stats.py +0 -0
  448. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/tests/test_agent_tasks.py +0 -0
  449. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/tests/test_agent_tool_call.py +0 -0
  450. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/tests/test_agents.py +0 -0
  451. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/tests/test_cli_programmatic_preload.py +0 -0
  452. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/tests/test_current_bugs.py +0 -0
  453. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/tests/test_drydock_regression.py +0 -0
  454. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/tests/test_drydock_tasks.py +0 -0
  455. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/tests/test_history_manager.py +0 -0
  456. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/tests/test_integration.py +0 -0
  457. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/tests/test_loop_detection.py +0 -0
  458. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/tests/test_message_id.py +0 -0
  459. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/tests/test_message_merging.py +0 -0
  460. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/tests/test_middleware.py +0 -0
  461. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/tests/test_real_failures.py +0 -0
  462. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/tests/test_real_issues.py +0 -0
  463. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/tests/test_reasoning_content.py +0 -0
  464. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/tests/test_system_prompt.py +0 -0
  465. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/tests/test_tagged_text.py +0 -0
  466. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/tests/test_ui_external_editor.py +0 -0
  467. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/tests/test_ui_input_history.py +0 -0
  468. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/tests/test_user_issues.py +0 -0
  469. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/tests/tools/test_ask_user_question.py +0 -0
  470. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/tests/tools/test_bash.py +0 -0
  471. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/tests/tools/test_exit_plan_mode.py +0 -0
  472. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/tests/tools/test_grep.py +0 -0
  473. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/tests/tools/test_invoke_context.py +0 -0
  474. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/tests/tools/test_manager_get_tool_config.py +0 -0
  475. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/tests/tools/test_mcp.py +0 -0
  476. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/tests/tools/test_mcp_sampling.py +0 -0
  477. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/tests/tools/test_task.py +0 -0
  478. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/tests/tools/test_ui_bash_execution.py +0 -0
  479. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/tests/tools/test_webfetch.py +0 -0
  480. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/tests/tools/test_websearch.py +0 -0
  481. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/tests/update_notifier/adapters/fake_update_cache_repository.py +0 -0
  482. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/tests/update_notifier/adapters/fake_update_gateway.py +0 -0
  483. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/tests/update_notifier/test_do_update.py +0 -0
  484. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/tests/update_notifier/test_filesystem_update_cache_repository.py +0 -0
  485. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/tests/update_notifier/test_github_update_gateway.py +0 -0
  486. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/tests/update_notifier/test_pypi_update_gateway.py +0 -0
  487. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/tests/update_notifier/test_ui_update_notification.py +0 -0
  488. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/tests/update_notifier/test_update_use_case.py +0 -0
  489. {drydock_cli-1.0.0 → drydock_cli-1.1.0}/tests/update_notifier/test_whats_new.py +0 -0
  490. {drydock_cli-1.0.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: 1.0.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
@@ -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)
@@ -0,0 +1,118 @@
1
+ """MCP Resource tools — list and read MCP server resources.
2
+
3
+ MCP servers can expose resources (files, data) in addition to tools.
4
+ These tools let the agent discover and read them.
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 ListMcpResourcesArgs(BaseModel):
22
+ server_name: str = Field(default="", description="MCP server name (empty = all servers)")
23
+
24
+
25
+ class McpResource(BaseModel):
26
+ uri: str
27
+ name: str
28
+ description: str = ""
29
+ mime_type: str = ""
30
+ server: str = ""
31
+
32
+
33
+ class ListMcpResourcesResult(BaseModel):
34
+ resources: list[McpResource]
35
+ count: int
36
+
37
+
38
+ class ListMcpResources(
39
+ BaseTool[ListMcpResourcesArgs, ListMcpResourcesResult, BaseToolConfig, BaseToolState],
40
+ ToolUIData[ListMcpResourcesArgs, ListMcpResourcesResult],
41
+ ):
42
+ description: ClassVar[str] = "List resources available from MCP servers."
43
+
44
+ @classmethod
45
+ def format_call_display(cls, args: ListMcpResourcesArgs) -> ToolCallDisplay:
46
+ return ToolCallDisplay(summary=f"list_mcp_resources: {args.server_name or 'all'}")
47
+
48
+ @classmethod
49
+ def get_result_display(cls, event: ToolResultEvent) -> ToolResultDisplay:
50
+ if isinstance(event.result, ListMcpResourcesResult):
51
+ return ToolResultDisplay(success=True, message=f"{event.result.count} resources")
52
+ return ToolResultDisplay(success=True, message="Resources listed")
53
+
54
+ @classmethod
55
+ def get_status_text(cls) -> str:
56
+ return "Listing MCP resources"
57
+
58
+ def resolve_permission(self, args: ListMcpResourcesArgs) -> ToolPermission | None:
59
+ return ToolPermission.ALWAYS
60
+
61
+ @final
62
+ async def run(
63
+ self, args: ListMcpResourcesArgs, ctx: InvokeContext | None = None
64
+ ) -> AsyncGenerator[ToolStreamEvent | ListMcpResourcesResult, None]:
65
+ # MCP resource listing is handled by the MCP registry
66
+ # For now, return empty — full implementation requires MCP protocol changes
67
+ resources: list[McpResource] = []
68
+
69
+ try:
70
+ if ctx and hasattr(ctx, 'agent_manager') and ctx.agent_manager:
71
+ # Try to list resources from connected MCP servers
72
+ from drydock.core.tools.mcp import MCPRegistry
73
+ # This would need MCP servers to implement resources
74
+ pass
75
+ except Exception:
76
+ pass
77
+
78
+ yield ListMcpResourcesResult(resources=resources, count=len(resources))
79
+
80
+
81
+ class ReadMcpResourceArgs(BaseModel):
82
+ uri: str = Field(description="Resource URI to read")
83
+ server_name: str = Field(default="", description="MCP server name")
84
+
85
+
86
+ class ReadMcpResourceResult(BaseModel):
87
+ uri: str
88
+ content: str
89
+ mime_type: str = ""
90
+
91
+
92
+ class ReadMcpResource(
93
+ BaseTool[ReadMcpResourceArgs, ReadMcpResourceResult, BaseToolConfig, BaseToolState],
94
+ ToolUIData[ReadMcpResourceArgs, ReadMcpResourceResult],
95
+ ):
96
+ description: ClassVar[str] = "Read a resource from an MCP server by URI."
97
+
98
+ @classmethod
99
+ def format_call_display(cls, args: ReadMcpResourceArgs) -> ToolCallDisplay:
100
+ return ToolCallDisplay(summary=f"read_mcp_resource: {args.uri[:50]}")
101
+
102
+ @classmethod
103
+ def get_result_display(cls, event: ToolResultEvent) -> ToolResultDisplay:
104
+ return ToolResultDisplay(success=True, message="Resource read")
105
+
106
+ @classmethod
107
+ def get_status_text(cls) -> str:
108
+ return "Reading MCP resource"
109
+
110
+ @final
111
+ async def run(
112
+ self, args: ReadMcpResourceArgs, ctx: InvokeContext | None = None
113
+ ) -> AsyncGenerator[ToolStreamEvent | ReadMcpResourceResult, None]:
114
+ # Full MCP resource reading requires protocol-level support
115
+ raise ToolError(
116
+ f"MCP resource reading not yet connected to MCP servers. "
117
+ f"URI: {args.uri}. Configure an MCP server that exposes resources."
118
+ )