drydock-cli 0.6.2__tar.gz → 0.6.4__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.
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/PKG-INFO +1 -1
- drydock_cli-0.6.4/PRD.md +180 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/drydock/cli/textual_ui/app.py +18 -12
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/drydock/core/config/_settings.py +8 -0
- drydock_cli-0.6.4/drydock/core/consultant.py +183 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/drydock/core/paths/_vibe_home.py +32 -4
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/pyproject.toml +1 -1
- drydock_cli-0.6.2/PRD.md +0 -268
- drydock_cli-0.6.2/drydock/core/consultant.py +0 -141
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/.github/CODEOWNERS +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/.github/DISCUSSION_TEMPLATE/ideas.yml +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/.github/ISSUE_TEMPLATE/bug-report.yml +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/.github/ISSUE_TEMPLATE/config.yml +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/.github/workflows/build-and-upload.yml +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/.github/workflows/ci.yml +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/.github/workflows/issue-labeler.yml +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/.github/workflows/release.yml +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/.gitignore +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/.pre-commit-config.yaml +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/.python-version +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/.typos.toml +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/.vscode/extensions.json +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/.vscode/launch.json +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/.vscode/settings.json +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/AGENTS.md +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/CHANGELOG.md +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/CLAUDE.md +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/CONTRIBUTING.md +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/Drydock_rebrand.md +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/LICENSE +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/NOTICE +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/README.md +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/action.yml +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/distribution/zed/LICENSE +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/distribution/zed/extension.toml +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/distribution/zed/icons/mistral_vibe.svg +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/docs/README.md +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/docs/acp-setup.md +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/docs/proxy-setup.md +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/drydock/__init__.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/drydock/acp/__init__.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/drydock/acp/acp_agent_loop.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/drydock/acp/acp_logger.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/drydock/acp/entrypoint.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/drydock/acp/tools/__init__.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/drydock/acp/tools/base.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/drydock/acp/tools/builtins/bash.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/drydock/acp/tools/builtins/read_file.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/drydock/acp/tools/builtins/search_replace.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/drydock/acp/tools/builtins/todo.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/drydock/acp/tools/builtins/write_file.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/drydock/acp/tools/session_update.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/drydock/acp/utils.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/drydock/cli/__init__.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/drydock/cli/autocompletion/__init__.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/drydock/cli/autocompletion/base.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/drydock/cli/autocompletion/path_completion.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/drydock/cli/autocompletion/slash_command.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/drydock/cli/cli.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/drydock/cli/clipboard.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/drydock/cli/commands.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/drydock/cli/entrypoint.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/drydock/cli/history_manager.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/drydock/cli/plan_offer/adapters/http_whoami_gateway.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/drydock/cli/plan_offer/decide_plan_offer.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/drydock/cli/plan_offer/ports/whoami_gateway.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/drydock/cli/terminal_setup.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/drydock/cli/textual_ui/__init__.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/drydock/cli/textual_ui/ansi_markdown.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/drydock/cli/textual_ui/app.tcss +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/drydock/cli/textual_ui/external_editor.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/drydock/cli/textual_ui/handlers/__init__.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/drydock/cli/textual_ui/handlers/event_handler.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/drydock/cli/textual_ui/notifications/__init__.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/drydock/cli/textual_ui/notifications/adapters/__init__.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/drydock/cli/textual_ui/notifications/adapters/textual_notification_adapter.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/drydock/cli/textual_ui/notifications/ports/__init__.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/drydock/cli/textual_ui/notifications/ports/notification_port.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/drydock/cli/textual_ui/widgets/__init__.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/drydock/cli/textual_ui/widgets/approval_app.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/drydock/cli/textual_ui/widgets/banner/banner.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/drydock/cli/textual_ui/widgets/banner/petit_chat.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/drydock/cli/textual_ui/widgets/braille_renderer.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/drydock/cli/textual_ui/widgets/chat_input/__init__.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/drydock/cli/textual_ui/widgets/chat_input/body.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/drydock/cli/textual_ui/widgets/chat_input/completion_manager.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/drydock/cli/textual_ui/widgets/chat_input/completion_popup.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/drydock/cli/textual_ui/widgets/chat_input/container.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/drydock/cli/textual_ui/widgets/chat_input/text_area.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/drydock/cli/textual_ui/widgets/compact.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/drydock/cli/textual_ui/widgets/config_app.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/drydock/cli/textual_ui/widgets/context_progress.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/drydock/cli/textual_ui/widgets/load_more.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/drydock/cli/textual_ui/widgets/loading.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/drydock/cli/textual_ui/widgets/messages.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/drydock/cli/textual_ui/widgets/no_markup_static.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/drydock/cli/textual_ui/widgets/path_display.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/drydock/cli/textual_ui/widgets/proxy_setup_app.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/drydock/cli/textual_ui/widgets/question_app.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/drydock/cli/textual_ui/widgets/session_picker.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/drydock/cli/textual_ui/widgets/spinner.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/drydock/cli/textual_ui/widgets/status_message.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/drydock/cli/textual_ui/widgets/teleport_message.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/drydock/cli/textual_ui/widgets/tool_widgets.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/drydock/cli/textual_ui/widgets/tools.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/drydock/cli/textual_ui/widgets/vscode_compat.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/drydock/cli/textual_ui/windowing/__init__.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/drydock/cli/textual_ui/windowing/history.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/drydock/cli/textual_ui/windowing/history_windowing.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/drydock/cli/textual_ui/windowing/state.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/drydock/cli/update_notifier/__init__.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/drydock/cli/update_notifier/adapters/filesystem_update_cache_repository.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/drydock/cli/update_notifier/adapters/github_update_gateway.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/drydock/cli/update_notifier/adapters/pypi_update_gateway.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/drydock/cli/update_notifier/ports/update_cache_repository.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/drydock/cli/update_notifier/ports/update_gateway.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/drydock/cli/update_notifier/update.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/drydock/cli/update_notifier/whats_new.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/drydock/core/__init__.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/drydock/core/agent_loop.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/drydock/core/agents/__init__.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/drydock/core/agents/manager.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/drydock/core/agents/models.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/drydock/core/auth/__init__.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/drydock/core/auth/crypto.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/drydock/core/auth/github.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/drydock/core/autocompletion/__init__.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/drydock/core/autocompletion/completers.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/drydock/core/autocompletion/file_indexer/__init__.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/drydock/core/autocompletion/file_indexer/ignore_rules.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/drydock/core/autocompletion/file_indexer/indexer.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/drydock/core/autocompletion/file_indexer/store.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/drydock/core/autocompletion/file_indexer/watcher.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/drydock/core/autocompletion/fuzzy.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/drydock/core/autocompletion/path_prompt.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/drydock/core/autocompletion/path_prompt_adapter.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/drydock/core/config/__init__.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/drydock/core/config/harness_files/__init__.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/drydock/core/config/harness_files/_harness_manager.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/drydock/core/config/harness_files/_paths.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/drydock/core/drydock_states.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/drydock/core/llm/__init__.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/drydock/core/llm/backend/anthropic.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/drydock/core/llm/backend/base.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/drydock/core/llm/backend/factory.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/drydock/core/llm/backend/generic.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/drydock/core/llm/backend/mistral.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/drydock/core/llm/backend/reasoning_adapter.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/drydock/core/llm/backend/vertex.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/drydock/core/llm/exceptions.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/drydock/core/llm/format.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/drydock/core/llm/message_utils.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/drydock/core/llm/types.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/drydock/core/logger.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/drydock/core/middleware.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/drydock/core/output_formatters.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/drydock/core/paths/__init__.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/drydock/core/paths/_local_config_walk.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/drydock/core/paths/conventions.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/drydock/core/plan_session.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/drydock/core/programmatic.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/drydock/core/prompts/__init__.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/drydock/core/prompts/cli.md +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/drydock/core/prompts/compact.md +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/drydock/core/prompts/dangerous_directory.md +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/drydock/core/prompts/diagnostic.md +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/drydock/core/prompts/explore.md +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/drydock/core/prompts/planner.md +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/drydock/core/prompts/project_context.md +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/drydock/core/prompts/tests.md +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/drydock/core/proxy_setup.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/drydock/core/session/session_loader.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/drydock/core/session/session_logger.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/drydock/core/session/session_migration.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/drydock/core/session/state_file.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/drydock/core/skills/__init__.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/drydock/core/skills/manager.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/drydock/core/skills/models.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/drydock/core/skills/parser.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/drydock/core/slug.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/drydock/core/system_prompt.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/drydock/core/telemetry/__init__.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/drydock/core/telemetry/send.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/drydock/core/teleport/errors.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/drydock/core/teleport/git.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/drydock/core/teleport/nuage.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/drydock/core/teleport/teleport.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/drydock/core/teleport/types.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/drydock/core/tools/base.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/drydock/core/tools/builtins/ask_user_question.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/drydock/core/tools/builtins/bash.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/drydock/core/tools/builtins/exit_plan_mode.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/drydock/core/tools/builtins/grep.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/drydock/core/tools/builtins/prompts/__init__.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/drydock/core/tools/builtins/prompts/ask_user_question.md +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/drydock/core/tools/builtins/prompts/bash.md +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/drydock/core/tools/builtins/prompts/grep.md +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/drydock/core/tools/builtins/prompts/read_file.md +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/drydock/core/tools/builtins/prompts/search_replace.md +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/drydock/core/tools/builtins/prompts/swe_bench.md +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/drydock/core/tools/builtins/prompts/task.md +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/drydock/core/tools/builtins/prompts/todo.md +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/drydock/core/tools/builtins/prompts/webfetch.md +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/drydock/core/tools/builtins/prompts/websearch.md +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/drydock/core/tools/builtins/prompts/write_file.md +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/drydock/core/tools/builtins/read_file.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/drydock/core/tools/builtins/search_replace.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/drydock/core/tools/builtins/task.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/drydock/core/tools/builtins/todo.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/drydock/core/tools/builtins/webfetch.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/drydock/core/tools/builtins/websearch.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/drydock/core/tools/builtins/write_file.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/drydock/core/tools/injection_guard.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/drydock/core/tools/manager.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/drydock/core/tools/mcp/__init__.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/drydock/core/tools/mcp/registry.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/drydock/core/tools/mcp/tools.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/drydock/core/tools/mcp_sampling.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/drydock/core/tools/ui.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/drydock/core/tools/utils.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/drydock/core/trusted_folders.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/drydock/core/types.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/drydock/core/utils.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/drydock/setup/onboarding/__init__.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/drydock/setup/onboarding/base.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/drydock/setup/onboarding/onboarding.tcss +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/drydock/setup/onboarding/screens/__init__.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/drydock/setup/onboarding/screens/api_key.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/drydock/setup/onboarding/screens/welcome.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/drydock/setup/trusted_folders/trust_folder_dialog.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/drydock/setup/trusted_folders/trust_folder_dialog.tcss +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/drydock/skills/__init__.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/drydock/skills/create-presentation/SKILL.md +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/drydock/whats_new.md +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/drydock-acp.spec +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/drydock_terms.md +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/flake.lock +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/flake.nix +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/scripts/README.md +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/scripts/bump_version.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/scripts/deploy_to_github.sh +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/scripts/install.sh +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/scripts/prepare_release.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/scripts/publish_to_pypi.sh +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/tests/__init__.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/tests/acp/conftest.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/tests/acp/test_acp.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/tests/acp/test_agent_thought.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/tests/acp/test_bash.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/tests/acp/test_compact_session_updates.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/tests/acp/test_content.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/tests/acp/test_initialize.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/tests/acp/test_list_sessions.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/tests/acp/test_load_session.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/tests/acp/test_multi_session.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/tests/acp/test_new_session.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/tests/acp/test_proxy_setup_acp.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/tests/acp/test_read_file.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/tests/acp/test_search_replace.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/tests/acp/test_set_config_option.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/tests/acp/test_set_mode.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/tests/acp/test_set_model.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/tests/acp/test_tool_call_session_update.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/tests/acp/test_utils.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/tests/acp/test_write_file.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/tests/autocompletion/test_file_indexer.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/tests/autocompletion/test_fuzzy.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/tests/autocompletion/test_path_completer_fuzzy.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/tests/autocompletion/test_path_completer_recursive.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/tests/autocompletion/test_path_completion_controller.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/tests/autocompletion/test_path_prompt_transformer.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/tests/autocompletion/test_slash_command_controller.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/tests/autocompletion/test_ui_chat_autocompletion.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/tests/backend/__init__.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/tests/backend/data/__init__.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/tests/backend/data/fireworks.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/tests/backend/data/mistral.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/tests/backend/test_anthropic_adapter.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/tests/backend/test_backend.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/tests/backend/test_reasoning_adapter.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/tests/backend/test_vertex_anthropic_adapter.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/tests/cli/plan_offer/adapters/fake_whoami_gateway.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/tests/cli/plan_offer/test_decide_plan_offer.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/tests/cli/plan_offer/test_http_whoami_gateway.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/tests/cli/test_bell_notifications.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/tests/cli/test_braille_renderer.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/tests/cli/test_clipboard.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/tests/cli/test_commands.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/tests/cli/test_copy_shortcuts.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/tests/cli/test_external_editor.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/tests/cli/test_no_markup_static.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/tests/cli/test_question_app.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/tests/cli/test_spinner.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/tests/cli/test_switching_mode.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/tests/cli/test_ui_clipboard_notifications.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/tests/cli/test_ui_session_incremental_renderer.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/tests/cli/test_ui_session_resume.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/tests/cli/test_ui_skill_dispatch.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/tests/cli/textual_ui/__init__.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/tests/cli/textual_ui/test_session_picker.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/tests/conftest.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/tests/core/test_agents.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/tests/core/test_auth_crypto.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/tests/core/test_auth_github.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/tests/core/test_config_load_dotenv.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/tests/core/test_config_paths.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/tests/core/test_config_resolution.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/tests/core/test_file_logging.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/tests/core/test_plan_session.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/tests/core/test_proxy_setup.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/tests/core/test_slug.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/tests/core/test_telemetry_send.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/tests/core/test_teleport_git.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/tests/core/test_teleport_nuage.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/tests/core/test_teleport_service.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/tests/core/test_trusted_folders.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/tests/core/test_utils.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/tests/e2e/common.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/tests/e2e/conftest.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/tests/e2e/mock_server.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/tests/e2e/test_cli_tui_onboarding.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/tests/e2e/test_cli_tui_streaming.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/tests/e2e/test_cli_tui_tool_approval.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/tests/mock/__init__.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/tests/mock/mock_backend_factory.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/tests/mock/mock_entrypoint.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/tests/mock/utils.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/tests/onboarding/test_run_onboarding.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/tests/onboarding/test_ui_onboarding.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/tests/session/test_session_loader.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/tests/session/test_session_logger.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/tests/session/test_session_migration.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/tests/skills/conftest.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/tests/skills/test_manager.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/tests/skills/test_models.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/tests/skills/test_parser.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/tests/snapshots/__snapshots__/test_ui_snapshot_ask_user_question/test_snapshot_ask_user_question_collapsed.svg +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/tests/snapshots/__snapshots__/test_ui_snapshot_ask_user_question/test_snapshot_ask_user_question_expanded.svg +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/tests/snapshots/__snapshots__/test_ui_snapshot_basic_conversation/test_snapshot_shows_basic_conversation.svg +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/tests/snapshots/__snapshots__/test_ui_snapshot_code_block_horizontal_scrolling/test_snapshot_allows_horizontal_scrolling_for_long_code_blocks.svg +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/tests/snapshots/__snapshots__/test_ui_snapshot_empty_assistant_before_reasoning/test_snapshot_empty_assistant_removed_when_reasoning_starts.svg +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/tests/snapshots/__snapshots__/test_ui_snapshot_modes/test_snapshot_cycle_to_accept_edits_mode.svg +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/tests/snapshots/__snapshots__/test_ui_snapshot_modes/test_snapshot_cycle_to_auto_approve_mode.svg +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/tests/snapshots/__snapshots__/test_ui_snapshot_modes/test_snapshot_cycle_to_plan_mode.svg +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/tests/snapshots/__snapshots__/test_ui_snapshot_modes/test_snapshot_cycle_wraps_to_default.svg +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/tests/snapshots/__snapshots__/test_ui_snapshot_modes/test_snapshot_default_mode.svg +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/tests/snapshots/__snapshots__/test_ui_snapshot_parallel_tool_calls/test_snapshot_parallel_tool_calls_pending.svg +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/tests/snapshots/__snapshots__/test_ui_snapshot_parallel_tool_calls/test_snapshot_parallel_tool_calls_resolved.svg +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/tests/snapshots/__snapshots__/test_ui_snapshot_proxy_setup/test_snapshot_proxy_setup_cancel_discards_changes.svg +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/tests/snapshots/__snapshots__/test_ui_snapshot_proxy_setup/test_snapshot_proxy_setup_edit_existing_values.svg +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/tests/snapshots/__snapshots__/test_ui_snapshot_proxy_setup/test_snapshot_proxy_setup_initial_empty.svg +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/tests/snapshots/__snapshots__/test_ui_snapshot_proxy_setup/test_snapshot_proxy_setup_initial_with_values.svg +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/tests/snapshots/__snapshots__/test_ui_snapshot_proxy_setup/test_snapshot_proxy_setup_save_error.svg +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/tests/snapshots/__snapshots__/test_ui_snapshot_proxy_setup/test_snapshot_proxy_setup_save_new_values.svg +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_question_answer_first_advance.svg +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_question_first_answered_checkmark.svg +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_question_initial.svg +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_question_navigate_left_wraps.svg +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_question_navigate_right.svg +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_question_tab_to_second.svg +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_select_initial.svg +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_select_mixed_selection.svg +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_select_navigate_to_submit.svg +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_select_other_with_text.svg +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_select_toggle_first.svg +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_select_toggle_multiple.svg +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_select_untoggle.svg +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_question_app_initial.svg +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_question_app_navigate_down.svg +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_question_app_navigate_to_other.svg +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_question_app_navigate_to_third_option.svg +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_question_app_navigate_up_wraps.svg +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_question_app_other_typing.svg +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/tests/snapshots/__snapshots__/test_ui_snapshot_reasoning_content/test_snapshot_buffered_reasoning_yields_before_content.svg +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/tests/snapshots/__snapshots__/test_ui_snapshot_reasoning_content/test_snapshot_shows_interleaved_reasoning.svg +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/tests/snapshots/__snapshots__/test_ui_snapshot_reasoning_content/test_snapshot_shows_reasoning_content.svg +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/tests/snapshots/__snapshots__/test_ui_snapshot_reasoning_content/test_snapshot_shows_reasoning_content_expanded.svg +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/tests/snapshots/__snapshots__/test_ui_snapshot_release_update_notification/test_snapshot_shows_release_update_notification.svg +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/tests/snapshots/__snapshots__/test_ui_snapshot_session_resume/test_snapshot_shows_resumed_session_messages.svg +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/tests/snapshots/__snapshots__/test_ui_snapshot_streaming_tool_call/test_snapshot_tool_call_partial.svg +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/tests/snapshots/__snapshots__/test_ui_snapshot_streaming_tool_call/test_snapshot_tool_call_updated.svg +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_push_confirmation_cancel_selected.svg +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_push_confirmation_multiple_commits.svg +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_push_confirmation_single_commit.svg +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_status_auth_complete.svg +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_status_auth_required.svg +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_status_checking_git.svg +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_status_complete.svg +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_status_error.svg +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_status_pushing.svg +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_status_sending_token.svg +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_status_starting_workflow.svg +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/tests/snapshots/__snapshots__/test_ui_snapshot_whats_new/test_snapshot_shows_no_plan_message.svg +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/tests/snapshots/__snapshots__/test_ui_snapshot_whats_new/test_snapshot_shows_switch_message.svg +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/tests/snapshots/__snapshots__/test_ui_snapshot_whats_new/test_snapshot_shows_upgrade_message.svg +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/tests/snapshots/__snapshots__/test_ui_snapshot_whats_new/test_snapshot_shows_whats_new_message.svg +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/tests/snapshots/base_snapshot_test_app.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/tests/snapshots/conftest.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/tests/snapshots/snap_compare.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/tests/snapshots/test_ui_snapshot_ask_user_question.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/tests/snapshots/test_ui_snapshot_basic_conversation.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/tests/snapshots/test_ui_snapshot_code_block_horizontal_scrolling.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/tests/snapshots/test_ui_snapshot_empty_assistant_before_reasoning.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/tests/snapshots/test_ui_snapshot_modes.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/tests/snapshots/test_ui_snapshot_parallel_tool_calls.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/tests/snapshots/test_ui_snapshot_proxy_setup.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/tests/snapshots/test_ui_snapshot_question_app.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/tests/snapshots/test_ui_snapshot_reasoning_content.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/tests/snapshots/test_ui_snapshot_release_update_notification.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/tests/snapshots/test_ui_snapshot_session_resume.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/tests/snapshots/test_ui_snapshot_streaming_tool_call.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/tests/snapshots/test_ui_snapshot_teleport.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/tests/snapshots/test_ui_snapshot_whats_new.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/tests/stubs/fake_backend.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/tests/stubs/fake_client.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/tests/stubs/fake_tool.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/tests/test_agent_auto_compact.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/tests/test_agent_backend.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/tests/test_agent_observer_streaming.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/tests/test_agent_stats.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/tests/test_agent_tool_call.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/tests/test_agents.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/tests/test_cli_programmatic_preload.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/tests/test_drydock_regression.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/tests/test_drydock_tasks.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/tests/test_history_manager.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/tests/test_message_id.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/tests/test_message_merging.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/tests/test_middleware.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/tests/test_reasoning_content.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/tests/test_system_prompt.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/tests/test_tagged_text.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/tests/test_ui_external_editor.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/tests/test_ui_input_history.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/tests/tools/test_ask_user_question.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/tests/tools/test_bash.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/tests/tools/test_exit_plan_mode.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/tests/tools/test_grep.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/tests/tools/test_invoke_context.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/tests/tools/test_manager_get_tool_config.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/tests/tools/test_mcp.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/tests/tools/test_mcp_sampling.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/tests/tools/test_task.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/tests/tools/test_ui_bash_execution.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/tests/tools/test_webfetch.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/tests/tools/test_websearch.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/tests/update_notifier/adapters/fake_update_cache_repository.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/tests/update_notifier/adapters/fake_update_gateway.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/tests/update_notifier/test_do_update.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/tests/update_notifier/test_filesystem_update_cache_repository.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/tests/update_notifier/test_github_update_gateway.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/tests/update_notifier/test_pypi_update_gateway.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/tests/update_notifier/test_ui_update_notification.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/tests/update_notifier/test_update_use_case.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/tests/update_notifier/test_whats_new.py +0 -0
- {drydock_cli-0.6.2 → drydock_cli-0.6.4}/uv.lock +0 -0
drydock_cli-0.6.4/PRD.md
ADDED
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
# DryDock — Local CLI Coding Agent
|
|
2
|
+
|
|
3
|
+
**Repository:** https://github.com/fbobe321/drydock
|
|
4
|
+
**PyPI:** https://pypi.org/project/drydock-cli/ (v0.6.3)
|
|
5
|
+
**License:** Apache 2.0 (fork of [mistralai/mistral-vibe](https://github.com/mistralai/mistral-vibe))
|
|
6
|
+
**Status:** Active development — continuous improvement running
|
|
7
|
+
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
## Deployment Process
|
|
11
|
+
|
|
12
|
+
Every change follows this pipeline:
|
|
13
|
+
|
|
14
|
+
1. **Code** → modify files in `drydock/` package directory
|
|
15
|
+
2. **Syntax check** → `python3 -c "import ast; ast.parse(...)"`
|
|
16
|
+
3. **Regression tests** → 81 tests must pass (auto-run by deploy scripts)
|
|
17
|
+
4. **Commit** → descriptive message with Co-Authored-By
|
|
18
|
+
5. **Publish** → `./scripts/publish_to_pypi.sh` (tests → build → PyPI → GitHub)
|
|
19
|
+
|
|
20
|
+
Scripts:
|
|
21
|
+
- `scripts/deploy_to_github.sh` — runs tests, syncs to GitHub. Cron daily at 4 AM.
|
|
22
|
+
- `scripts/publish_to_pypi.sh` — runs tests, bumps version, builds wheel, uploads to PyPI, deploys to GitHub. Aborts on test failure.
|
|
23
|
+
|
|
24
|
+
Both scripts gate on the full 81-test regression suite. No deploy happens if tests fail.
|
|
25
|
+
|
|
26
|
+
---
|
|
27
|
+
|
|
28
|
+
## Regression Test Suite (81 tests)
|
|
29
|
+
|
|
30
|
+
Two test files, run in 0.3s:
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
pytest tests/test_drydock_regression.py tests/test_drydock_tasks.py -p no:xdist -p no:cov --override-ini="addopts="
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
**test_drydock_regression.py (37 tests):**
|
|
37
|
+
Message ordering (6), system note injection (3), wave spinner (2), config paths (3), state terms (4), Easter eggs (2), bash allowlist (5), conda detection (2), CLI flags (2), loop thresholds (1), write file safety (3), loop patterns (2), loading widget (2)
|
|
38
|
+
|
|
39
|
+
**test_drydock_tasks.py (44 tests):**
|
|
40
|
+
Binary file guard (5), unknown tool handling (1), loop thresholds (3), file I/O timeouts (4), skill discovery (3), config migration (2), system prompt content (3), bash allowlist (2), wave spinner (3), Easter eggs (1), injection guard (4), state file (4), context warnings (3), deviation rules (1), circuit breaker (2), CLI flags (2), thinking throttle (1)
|
|
41
|
+
|
|
42
|
+
---
|
|
43
|
+
|
|
44
|
+
## Continuous Improvement
|
|
45
|
+
|
|
46
|
+
DryDock improves itself automatically and survives restarts:
|
|
47
|
+
|
|
48
|
+
1. **`continuous_bench.sh`** runs SWE-bench batches in a loop (20 tasks, 600s timeout)
|
|
49
|
+
2. **`@reboot` cron** restarts 2 minutes after any system restart
|
|
50
|
+
3. **Every 6 hours** cron re-launches if the loop died
|
|
51
|
+
4. **Daily at 4 AM** deploys to GitHub (with test gate)
|
|
52
|
+
5. **State persists** in `continuous_bench_state.json`
|
|
53
|
+
|
|
54
|
+
**Latest results (Mar 25):**
|
|
55
|
+
- 520 task runs completed, 500/500 unique tasks covered
|
|
56
|
+
- **254/500 passed (50.8%)** — up from 207/500 baseline (41.4%)
|
|
57
|
+
- **+47 net improvement** (117 newly passing, 70 regressions from model non-determinism)
|
|
58
|
+
|
|
59
|
+
---
|
|
60
|
+
|
|
61
|
+
## Objective
|
|
62
|
+
|
|
63
|
+
| | Value |
|
|
64
|
+
|---|---|
|
|
65
|
+
| **Baseline (Mar 15)** | 207/500 (41.4%) |
|
|
66
|
+
| **Current (Mar 25)** | 254/500 (50.8%) |
|
|
67
|
+
| **Net improvement** | +47 tasks (+9.4%) |
|
|
68
|
+
| **Target** | 80%+ |
|
|
69
|
+
| **Hardware** | 2x RTX 4060 Ti 16GB, devstral-24B-AWQ-4bit via vLLM, 128k context |
|
|
70
|
+
|
|
71
|
+
---
|
|
72
|
+
|
|
73
|
+
## Development Progress
|
|
74
|
+
|
|
75
|
+
### Phase 1: Baseline & Analysis (Mar 14–20)
|
|
76
|
+
1,138 task runs across 254 unique SWE-bench Verified tasks. Identified top failure modes: message ordering crashes (9%), wrong file edits (15%), loop kills (28%), prose-only responses (11%).
|
|
77
|
+
|
|
78
|
+
### Phase 2: Core Agent Improvements (Mar 15–20)
|
|
79
|
+
10 features: failure recovery middleware, fuzzy search_replace, grep source-first sorting, smarter loop detection, diagnostic/planner subagents, "never edit tests" rule, SWE-bench workflow prompt, .codeignore, message ordering fix.
|
|
80
|
+
|
|
81
|
+
### Phase 3: Crash Elimination (Mar 23)
|
|
82
|
+
`_sanitize_message_ordering()` safety net, middleware safe injection, MessageList bug fix, loop threshold tuning, forced-edit nudges, ConversationLimitException exit 0. Result: zero crashes.
|
|
83
|
+
|
|
84
|
+
### Phase 4: Conda/Pip & Rebrand (Mar 23)
|
|
85
|
+
Bash tool allowlist (pip, conda, pytest auto-approve), conda environment detection via BASH_ENV, full Mistral Vibe → DryDock rebrand. Published to GitHub.
|
|
86
|
+
|
|
87
|
+
### Phase 5: UX Overhaul (Mar 24)
|
|
88
|
+
Wave spinner, .drydock config dir, double Ctrl-C, --dangerously-skip-permissions, nautical Easter eggs, status throttle, write file timeouts, binary file guard, pptx skill, bash abuse detection, alternating loop detection, progressive budget warnings, ambiguous prompt guard, message queuing, mouse scroll, ocean blue onboarding. 76 regression tests gating deploys.
|
|
89
|
+
|
|
90
|
+
### Phase 5b: Package Rename (Mar 24)
|
|
91
|
+
`vibe/` → `drydock/` directory rename (908 imports, 257 files). Published to PyPI as drydock-cli. Removed `vibe` CLI entry point.
|
|
92
|
+
|
|
93
|
+
### Phase 6: GSD Integration & Performance (Mar 25)
|
|
94
|
+
|
|
95
|
+
Inspired by [get-shit-done](https://github.com/gsd-build/get-shit-done) (41k stars):
|
|
96
|
+
|
|
97
|
+
| Feature | Details |
|
|
98
|
+
|---------|---------|
|
|
99
|
+
| Tiered context warnings | 4 levels at 50/65/75/85% usage, debounced every 5 calls |
|
|
100
|
+
| Prompt injection guard | Detects role overrides, invisible Unicode, hidden instructions |
|
|
101
|
+
| Structured state file | `.drydock/state.md` persists task context across sessions |
|
|
102
|
+
| Deviation handling rules | Auto-fix bugs/imports, ask user for architecture/scope decisions |
|
|
103
|
+
| Circuit breaker | Blocks exact same tool call after 2 attempts with "already attempted" summary |
|
|
104
|
+
| Thinking flicker fix | Status words change every 4s, not every token |
|
|
105
|
+
| Conda env protection | Preserves user's active environment in subprocesses |
|
|
106
|
+
| `--insecure` / `-k` flag | Disables SSL verification for corporate proxies |
|
|
107
|
+
| `/consult` command | Ask a smarter model for advice — response visible to local model |
|
|
108
|
+
| `consultant_model` config | Select consultant from configured models in config.toml |
|
|
109
|
+
| `.vibe` auto-migration | Copies ~/.vibe → ~/.drydock on first run |
|
|
110
|
+
|
|
111
|
+
---
|
|
112
|
+
|
|
113
|
+
## Architecture
|
|
114
|
+
|
|
115
|
+
```
|
|
116
|
+
drydock/
|
|
117
|
+
├── PRD.md ← This document
|
|
118
|
+
├── NOTICE ← Apache 2.0 attribution
|
|
119
|
+
├── drydock/
|
|
120
|
+
│ ├── core/
|
|
121
|
+
│ │ ├── agent_loop.py ← Loop detection, circuit breaker, message ordering
|
|
122
|
+
│ │ ├── consultant.py ← /consult command backend (read-only advisor)
|
|
123
|
+
│ │ ├── middleware.py ← Tiered context warnings
|
|
124
|
+
│ │ ├── programmatic.py ← Headless API entry point
|
|
125
|
+
│ │ ├── session/state_file.py ← Cross-session state persistence
|
|
126
|
+
│ │ ├── tools/injection_guard.py ← Prompt injection detection
|
|
127
|
+
│ │ ├── tools/builtins/bash.py ← Shell, conda/pip, allowlist/denylist
|
|
128
|
+
│ │ ├── tools/builtins/search_replace.py ← Fuzzy auto-apply, recovery hints
|
|
129
|
+
│ │ └── prompts/cli.md ← System prompt with deviation rules
|
|
130
|
+
│ ├── cli/
|
|
131
|
+
│ │ ├── entrypoint.py ← CLI flags (--insecure, --consultant, etc.)
|
|
132
|
+
│ │ ├── commands.py ← Slash commands (/consult, /help, etc.)
|
|
133
|
+
│ │ └── textual_ui/app.py ← TUI, message queuing, double Ctrl-C
|
|
134
|
+
│ └── skills/
|
|
135
|
+
│ └── create-presentation/SKILL.md ← Bundled pptx skill
|
|
136
|
+
├── tests/
|
|
137
|
+
│ ├── test_drydock_regression.py ← 37 component tests
|
|
138
|
+
│ └── test_drydock_tasks.py ← 44 behavior tests
|
|
139
|
+
└── scripts/
|
|
140
|
+
├── deploy_to_github.sh ← Test-gated GitHub deploy
|
|
141
|
+
└── publish_to_pypi.sh ← Test-gated PyPI publish
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
---
|
|
145
|
+
|
|
146
|
+
## Key Technical Decisions
|
|
147
|
+
|
|
148
|
+
**Circuit breaker:** Tracks tool call signatures (hash of name + args). After 2 identical calls, blocks execution and returns the cached result with "ALREADY ATTEMPTED" summary and suggestions to try different approaches.
|
|
149
|
+
|
|
150
|
+
**Consultant model:** `/consult` sends a question to a configured model using DryDock's own backend (same providers, same API keys). The consultant never calls tools — it only returns text advice that gets injected into the conversation so the local model can see and act on it.
|
|
151
|
+
|
|
152
|
+
**Tiered context warnings:** 4 warning levels (50%, 65%, 75%, 85% context used). Debounced every 5 tool calls. Messages escalate from "wrap up" to "STOP NOW."
|
|
153
|
+
|
|
154
|
+
**Config migration:** On first run, if `~/.vibe` exists but `~/.drydock` doesn't, auto-copies everything and leaves a `MIGRATED.txt` note.
|
|
155
|
+
|
|
156
|
+
---
|
|
157
|
+
|
|
158
|
+
## Lessons Learned
|
|
159
|
+
|
|
160
|
+
1. **Fix bugs before adding features.** The message ordering crash fix was worth more than all subagents combined.
|
|
161
|
+
2. **Non-determinism is real.** Run 500+ tasks to get stable numbers. 20-task batches are noise.
|
|
162
|
+
3. **The model needs hard guardrails, not suggestions.** The circuit breaker (block after 2) works better than warnings (which the model ignores).
|
|
163
|
+
4. **Test everything.** 81 regression tests catch issues before they ship. Gate deploys on tests.
|
|
164
|
+
5. **Users find different bugs than benchmarks.** SWE-bench found crash bugs. Real usage found UX bugs (flicker, loops, wrong config dirs).
|
|
165
|
+
|
|
166
|
+
---
|
|
167
|
+
|
|
168
|
+
## Next Steps
|
|
169
|
+
|
|
170
|
+
### P1: Startup optimization
|
|
171
|
+
20-second delay on launch. Profile imports, lazy-load heavy modules.
|
|
172
|
+
|
|
173
|
+
### P2: Expand to full SWE-bench (2,294 tasks)
|
|
174
|
+
Batch file ready. Switch continuous_bench.sh once Verified is stable.
|
|
175
|
+
|
|
176
|
+
### P3: Task queue UI
|
|
177
|
+
Show the user what the agent has planned in its execution pipeline.
|
|
178
|
+
|
|
179
|
+
### P4: Support more LLM backends
|
|
180
|
+
Test with Claude, GPT-4, Gemini to understand which improvements are model-specific.
|
|
@@ -948,22 +948,24 @@ class VibeApp(App): # noqa: PLR0904
|
|
|
948
948
|
)
|
|
949
949
|
return
|
|
950
950
|
|
|
951
|
-
# Get consultant model from config or env
|
|
951
|
+
# Get consultant model from config, CLI flag, or env
|
|
952
952
|
import os
|
|
953
|
-
consultant_model =
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
consultant_model = getattr(self.agent_loop.config, "consultant_model", "")
|
|
958
|
-
except Exception:
|
|
959
|
-
pass
|
|
953
|
+
consultant_model = (
|
|
954
|
+
getattr(self.agent_loop.config, "consultant_model", "")
|
|
955
|
+
or os.environ.get("DRYDOCK_CONSULTANT_MODEL", "")
|
|
956
|
+
)
|
|
960
957
|
|
|
961
958
|
if not consultant_model:
|
|
959
|
+
# List available models to help the user
|
|
960
|
+
model_names = [m.name for m in self.agent_loop.config.models]
|
|
962
961
|
await self._mount_and_scroll(
|
|
963
962
|
ErrorMessage(
|
|
964
|
-
"No consultant model configured.\n"
|
|
965
|
-
"
|
|
966
|
-
"
|
|
963
|
+
"No consultant model configured.\n\n"
|
|
964
|
+
f"Available models: {', '.join(model_names)}\n\n"
|
|
965
|
+
"Set in config.toml:\n"
|
|
966
|
+
" `consultant_model = \"gemini-2.5-pro\"`\n\n"
|
|
967
|
+
"Or via CLI:\n"
|
|
968
|
+
" `drydock --consultant gemini-2.5-pro`",
|
|
967
969
|
collapsed=self._tools_collapsed,
|
|
968
970
|
)
|
|
969
971
|
)
|
|
@@ -975,7 +977,11 @@ class VibeApp(App): # noqa: PLR0904
|
|
|
975
977
|
|
|
976
978
|
try:
|
|
977
979
|
from drydock.core.consultant import ask_consultant
|
|
978
|
-
advice = await ask_consultant(
|
|
980
|
+
advice = await ask_consultant(
|
|
981
|
+
question,
|
|
982
|
+
config=self.agent_loop.config,
|
|
983
|
+
model=consultant_model,
|
|
984
|
+
)
|
|
979
985
|
|
|
980
986
|
if not advice or advice.startswith("(Consultant unavailable"):
|
|
981
987
|
await self._mount_and_scroll(
|
|
@@ -310,6 +310,14 @@ class VibeConfig(BaseSettings):
|
|
|
310
310
|
enable_notifications: bool = True
|
|
311
311
|
api_timeout: float = 720.0
|
|
312
312
|
auto_compact_threshold: int = 200_000
|
|
313
|
+
consultant_model: str = Field(
|
|
314
|
+
default="",
|
|
315
|
+
description=(
|
|
316
|
+
"Model name for the /consult command. Must match a model defined in "
|
|
317
|
+
"your config. The consultant provides read-only advice — it never "
|
|
318
|
+
"calls tools. Leave empty to disable. Example: 'gemini-2.5-pro'"
|
|
319
|
+
),
|
|
320
|
+
)
|
|
313
321
|
|
|
314
322
|
# TODO(vibe-nuage): remove exclude=True once the feature is publicly available
|
|
315
323
|
nuage_enabled: bool = Field(default=False, exclude=True)
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
"""Consultant agent — asks a configured model for single-turn advice.
|
|
2
|
+
|
|
3
|
+
The consultant is a READ-ONLY advisor:
|
|
4
|
+
- Uses a model from DryDock's own config (providers + models)
|
|
5
|
+
- NEVER calls tools, writes files, or runs commands
|
|
6
|
+
- Only receives a question and returns reasoning/advice
|
|
7
|
+
- Response is injected into context so the local model can see it
|
|
8
|
+
|
|
9
|
+
Configure in config.toml:
|
|
10
|
+
consultant_model = "gemini-2.5-pro"
|
|
11
|
+
|
|
12
|
+
Or via CLI:
|
|
13
|
+
drydock --consultant gemini-2.5-pro
|
|
14
|
+
|
|
15
|
+
Or via /consult slash command:
|
|
16
|
+
/consult How should I fix this auth bug?
|
|
17
|
+
"""
|
|
18
|
+
|
|
19
|
+
from __future__ import annotations
|
|
20
|
+
|
|
21
|
+
import logging
|
|
22
|
+
import os
|
|
23
|
+
|
|
24
|
+
logger = logging.getLogger(__name__)
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
async def ask_consultant(
|
|
28
|
+
question: str,
|
|
29
|
+
config: object | None = None,
|
|
30
|
+
model: str | None = None,
|
|
31
|
+
) -> str:
|
|
32
|
+
"""Ask the consultant model a question using DryDock's backend.
|
|
33
|
+
|
|
34
|
+
Parameters
|
|
35
|
+
----------
|
|
36
|
+
question : str
|
|
37
|
+
The specific question to ask.
|
|
38
|
+
config : VibeConfig, optional
|
|
39
|
+
DryDock config with providers/models. If None, uses env vars.
|
|
40
|
+
model : str, optional
|
|
41
|
+
Model name override. If None, uses config.consultant_model or env var.
|
|
42
|
+
|
|
43
|
+
Returns
|
|
44
|
+
-------
|
|
45
|
+
str
|
|
46
|
+
The consultant's advice text, or an error message.
|
|
47
|
+
"""
|
|
48
|
+
# Resolve model name
|
|
49
|
+
model_name = model or os.environ.get("DRYDOCK_CONSULTANT_MODEL", "")
|
|
50
|
+
if not model_name and config:
|
|
51
|
+
model_name = getattr(config, "consultant_model", "")
|
|
52
|
+
if not model_name:
|
|
53
|
+
return ""
|
|
54
|
+
|
|
55
|
+
prompt = (
|
|
56
|
+
"You are a senior software engineering consultant. An AI coding agent is "
|
|
57
|
+
"asking for your advice. Give concise, actionable guidance. Do NOT provide "
|
|
58
|
+
"code unless specifically asked — just say WHAT to do and WHERE to look.\n\n"
|
|
59
|
+
f"QUESTION:\n{question}"
|
|
60
|
+
)
|
|
61
|
+
|
|
62
|
+
# Try to use DryDock's backend system
|
|
63
|
+
if config:
|
|
64
|
+
try:
|
|
65
|
+
return await _ask_via_backend(prompt, model_name, config)
|
|
66
|
+
except Exception as e:
|
|
67
|
+
logger.warning("Consultant via backend failed: %s — falling back to httpx", e)
|
|
68
|
+
|
|
69
|
+
# Fallback: direct API call
|
|
70
|
+
try:
|
|
71
|
+
return await _ask_via_httpx(prompt, model_name)
|
|
72
|
+
except Exception as e:
|
|
73
|
+
return f"(Consultant unavailable: {e})"
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
async def _ask_via_backend(prompt: str, model_name: str, config: object) -> str:
|
|
77
|
+
"""Use DryDock's configured backend to call the consultant model."""
|
|
78
|
+
from drydock.core.config import ModelConfig, ProviderConfig
|
|
79
|
+
from drydock.core.llm.backend.factory import BACKEND_FACTORY
|
|
80
|
+
from drydock.core.types import LLMMessage, Role
|
|
81
|
+
|
|
82
|
+
# Find the model and its provider in the config
|
|
83
|
+
target_model: ModelConfig | None = None
|
|
84
|
+
for m in config.models:
|
|
85
|
+
if m.name == model_name or m.alias == model_name:
|
|
86
|
+
target_model = m
|
|
87
|
+
break
|
|
88
|
+
|
|
89
|
+
if not target_model:
|
|
90
|
+
raise ValueError(f"Model '{model_name}' not found in config. Available: {[m.name for m in config.models]}")
|
|
91
|
+
|
|
92
|
+
# Find the provider
|
|
93
|
+
target_provider: ProviderConfig | None = None
|
|
94
|
+
for p in config.providers:
|
|
95
|
+
if p.name == target_model.provider:
|
|
96
|
+
target_provider = p
|
|
97
|
+
break
|
|
98
|
+
|
|
99
|
+
if not target_provider:
|
|
100
|
+
raise ValueError(f"Provider '{target_model.provider}' not found for model '{model_name}'")
|
|
101
|
+
|
|
102
|
+
# Create a one-shot backend
|
|
103
|
+
backend = BACKEND_FACTORY[target_provider.backend](
|
|
104
|
+
provider=target_provider,
|
|
105
|
+
timeout=30,
|
|
106
|
+
)
|
|
107
|
+
|
|
108
|
+
messages = [LLMMessage(role=Role.user, content=prompt)]
|
|
109
|
+
|
|
110
|
+
result = await backend.complete(
|
|
111
|
+
model=target_model,
|
|
112
|
+
messages=messages,
|
|
113
|
+
temperature=0.3,
|
|
114
|
+
tools=None, # NO tools — read-only
|
|
115
|
+
tool_choice=None,
|
|
116
|
+
max_tokens=500,
|
|
117
|
+
)
|
|
118
|
+
|
|
119
|
+
return result.message.content or ""
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
async def _ask_via_httpx(prompt: str, model_name: str) -> str:
|
|
123
|
+
"""Fallback: direct API call via httpx for models not in config."""
|
|
124
|
+
import httpx
|
|
125
|
+
|
|
126
|
+
api_key = _detect_api_key(model_name)
|
|
127
|
+
api_base = _detect_api_base(model_name)
|
|
128
|
+
|
|
129
|
+
if not api_key:
|
|
130
|
+
return f"(No API key found for '{model_name}')"
|
|
131
|
+
|
|
132
|
+
verify_ssl = os.environ.get("DRYDOCK_INSECURE") != "1"
|
|
133
|
+
async with httpx.AsyncClient(verify=verify_ssl, timeout=30.0) as client:
|
|
134
|
+
response = await client.post(
|
|
135
|
+
f"{api_base}/chat/completions",
|
|
136
|
+
headers={
|
|
137
|
+
"Authorization": f"Bearer {api_key}",
|
|
138
|
+
"Content-Type": "application/json",
|
|
139
|
+
},
|
|
140
|
+
json={
|
|
141
|
+
"model": model_name,
|
|
142
|
+
"messages": [{"role": "user", "content": prompt}],
|
|
143
|
+
"max_tokens": 500,
|
|
144
|
+
"temperature": 0.3,
|
|
145
|
+
},
|
|
146
|
+
)
|
|
147
|
+
response.raise_for_status()
|
|
148
|
+
return response.json()["choices"][0]["message"]["content"]
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+
def _detect_api_key(model: str) -> str:
|
|
152
|
+
model_lower = model.lower()
|
|
153
|
+
if "gemini" in model_lower:
|
|
154
|
+
return os.environ.get("GEMINI_API_KEY", os.environ.get("GOOGLE_API_KEY", ""))
|
|
155
|
+
if "gpt" in model_lower or "o1" in model_lower or "o3" in model_lower:
|
|
156
|
+
return os.environ.get("OPENAI_API_KEY", "")
|
|
157
|
+
if "claude" in model_lower:
|
|
158
|
+
return os.environ.get("ANTHROPIC_API_KEY", "")
|
|
159
|
+
if "mistral" in model_lower or "devstral" in model_lower:
|
|
160
|
+
return os.environ.get("MISTRAL_API_KEY", "")
|
|
161
|
+
return os.environ.get("DRYDOCK_CONSULTANT_API_KEY", "")
|
|
162
|
+
|
|
163
|
+
|
|
164
|
+
def _detect_api_base(model: str) -> str:
|
|
165
|
+
model_lower = model.lower()
|
|
166
|
+
if "gemini" in model_lower:
|
|
167
|
+
return "https://generativelanguage.googleapis.com/v1beta/openai"
|
|
168
|
+
if "gpt" in model_lower or "o1" in model_lower or "o3" in model_lower:
|
|
169
|
+
return "https://api.openai.com/v1"
|
|
170
|
+
if "claude" in model_lower:
|
|
171
|
+
return "https://api.anthropic.com/v1"
|
|
172
|
+
if "mistral" in model_lower or "devstral" in model_lower:
|
|
173
|
+
return os.environ.get("MISTRAL_API_BASE", "https://api.mistral.ai/v1")
|
|
174
|
+
return os.environ.get("DRYDOCK_CONSULTANT_API_BASE", "http://localhost:8000/v1")
|
|
175
|
+
|
|
176
|
+
|
|
177
|
+
def is_consultant_available(config: object | None = None) -> bool:
|
|
178
|
+
"""Check if a consultant model is configured."""
|
|
179
|
+
if os.environ.get("DRYDOCK_CONSULTANT_MODEL"):
|
|
180
|
+
return True
|
|
181
|
+
if config and getattr(config, "consultant_model", ""):
|
|
182
|
+
return True
|
|
183
|
+
return False
|
|
@@ -17,9 +17,36 @@ class GlobalPath:
|
|
|
17
17
|
|
|
18
18
|
|
|
19
19
|
_DEFAULT_DRYDOCK_HOME = Path.home() / ".drydock"
|
|
20
|
-
# Fall back to ~/.vibe if it exists and ~/.drydock doesn't (migration support)
|
|
21
20
|
_DEFAULT_VIBE_HOME = Path.home() / ".vibe"
|
|
22
21
|
|
|
22
|
+
_migration_done = False
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def _migrate_vibe_to_drydock() -> None:
|
|
26
|
+
"""Auto-migrate ~/.vibe → ~/.drydock if the user hasn't migrated yet."""
|
|
27
|
+
global _migration_done
|
|
28
|
+
if _migration_done:
|
|
29
|
+
return
|
|
30
|
+
_migration_done = True
|
|
31
|
+
|
|
32
|
+
if not _DEFAULT_VIBE_HOME.exists() or _DEFAULT_DRYDOCK_HOME.exists():
|
|
33
|
+
return # Nothing to migrate, or already migrated
|
|
34
|
+
|
|
35
|
+
import shutil
|
|
36
|
+
import logging
|
|
37
|
+
logger = logging.getLogger(__name__)
|
|
38
|
+
|
|
39
|
+
try:
|
|
40
|
+
shutil.copytree(_DEFAULT_VIBE_HOME, _DEFAULT_DRYDOCK_HOME)
|
|
41
|
+
logger.info("Migrated ~/.vibe → ~/.drydock")
|
|
42
|
+
# Leave a note in the old directory
|
|
43
|
+
(_DEFAULT_VIBE_HOME / "MIGRATED.txt").write_text(
|
|
44
|
+
"This config has been migrated to ~/.drydock/\n"
|
|
45
|
+
"You can safely delete this .vibe directory.\n"
|
|
46
|
+
)
|
|
47
|
+
except (OSError, PermissionError) as e:
|
|
48
|
+
logger.warning("Could not migrate ~/.vibe → ~/.drydock: %s", e)
|
|
49
|
+
|
|
23
50
|
|
|
24
51
|
def _get_vibe_home() -> Path:
|
|
25
52
|
# Check env vars: DRYDOCK_HOME takes priority, then VIBE_HOME for compat
|
|
@@ -27,11 +54,12 @@ def _get_vibe_home() -> Path:
|
|
|
27
54
|
return Path(drydock_home).expanduser().resolve()
|
|
28
55
|
if vibe_home := os.getenv("VIBE_HOME"):
|
|
29
56
|
return Path(vibe_home).expanduser().resolve()
|
|
30
|
-
|
|
57
|
+
|
|
58
|
+
# Auto-migrate ~/.vibe → ~/.drydock on first run
|
|
59
|
+
_migrate_vibe_to_drydock()
|
|
60
|
+
|
|
31
61
|
if _DEFAULT_DRYDOCK_HOME.exists():
|
|
32
62
|
return _DEFAULT_DRYDOCK_HOME
|
|
33
|
-
if _DEFAULT_VIBE_HOME.exists():
|
|
34
|
-
return _DEFAULT_VIBE_HOME
|
|
35
63
|
return _DEFAULT_DRYDOCK_HOME
|
|
36
64
|
|
|
37
65
|
|