drydock-cli 0.6.0__tar.gz → 0.6.2__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.0 → drydock_cli-0.6.2}/PKG-INFO +1 -1
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/cli/commands.py +19 -1
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/cli/textual_ui/app.py +82 -2
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/core/agent_loop.py +35 -5
- drydock_cli-0.6.2/drydock/core/consultant.py +141 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/pyproject.toml +1 -1
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/test_drydock_tasks.py +2 -4
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/.github/CODEOWNERS +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/.github/DISCUSSION_TEMPLATE/ideas.yml +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/.github/ISSUE_TEMPLATE/bug-report.yml +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/.github/ISSUE_TEMPLATE/config.yml +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/.github/workflows/build-and-upload.yml +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/.github/workflows/ci.yml +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/.github/workflows/issue-labeler.yml +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/.github/workflows/release.yml +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/.gitignore +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/.pre-commit-config.yaml +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/.python-version +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/.typos.toml +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/.vscode/extensions.json +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/.vscode/launch.json +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/.vscode/settings.json +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/AGENTS.md +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/CHANGELOG.md +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/CLAUDE.md +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/CONTRIBUTING.md +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/Drydock_rebrand.md +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/LICENSE +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/NOTICE +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/PRD.md +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/README.md +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/action.yml +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/distribution/zed/LICENSE +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/distribution/zed/extension.toml +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/distribution/zed/icons/mistral_vibe.svg +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/docs/README.md +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/docs/acp-setup.md +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/docs/proxy-setup.md +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/__init__.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/acp/__init__.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/acp/acp_agent_loop.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/acp/acp_logger.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/acp/entrypoint.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/acp/tools/__init__.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/acp/tools/base.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/acp/tools/builtins/bash.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/acp/tools/builtins/read_file.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/acp/tools/builtins/search_replace.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/acp/tools/builtins/todo.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/acp/tools/builtins/write_file.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/acp/tools/session_update.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/acp/utils.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/cli/__init__.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/cli/autocompletion/__init__.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/cli/autocompletion/base.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/cli/autocompletion/path_completion.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/cli/autocompletion/slash_command.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/cli/cli.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/cli/clipboard.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/cli/entrypoint.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/cli/history_manager.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/cli/plan_offer/adapters/http_whoami_gateway.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/cli/plan_offer/decide_plan_offer.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/cli/plan_offer/ports/whoami_gateway.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/cli/terminal_setup.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/cli/textual_ui/__init__.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/cli/textual_ui/ansi_markdown.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/cli/textual_ui/app.tcss +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/cli/textual_ui/external_editor.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/cli/textual_ui/handlers/__init__.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/cli/textual_ui/handlers/event_handler.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/cli/textual_ui/notifications/__init__.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/cli/textual_ui/notifications/adapters/__init__.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/cli/textual_ui/notifications/adapters/textual_notification_adapter.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/cli/textual_ui/notifications/ports/__init__.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/cli/textual_ui/notifications/ports/notification_port.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/cli/textual_ui/widgets/__init__.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/cli/textual_ui/widgets/approval_app.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/cli/textual_ui/widgets/banner/banner.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/cli/textual_ui/widgets/banner/petit_chat.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/cli/textual_ui/widgets/braille_renderer.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/cli/textual_ui/widgets/chat_input/__init__.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/cli/textual_ui/widgets/chat_input/body.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/cli/textual_ui/widgets/chat_input/completion_manager.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/cli/textual_ui/widgets/chat_input/completion_popup.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/cli/textual_ui/widgets/chat_input/container.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/cli/textual_ui/widgets/chat_input/text_area.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/cli/textual_ui/widgets/compact.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/cli/textual_ui/widgets/config_app.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/cli/textual_ui/widgets/context_progress.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/cli/textual_ui/widgets/load_more.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/cli/textual_ui/widgets/loading.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/cli/textual_ui/widgets/messages.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/cli/textual_ui/widgets/no_markup_static.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/cli/textual_ui/widgets/path_display.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/cli/textual_ui/widgets/proxy_setup_app.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/cli/textual_ui/widgets/question_app.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/cli/textual_ui/widgets/session_picker.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/cli/textual_ui/widgets/spinner.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/cli/textual_ui/widgets/status_message.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/cli/textual_ui/widgets/teleport_message.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/cli/textual_ui/widgets/tool_widgets.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/cli/textual_ui/widgets/tools.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/cli/textual_ui/widgets/vscode_compat.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/cli/textual_ui/windowing/__init__.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/cli/textual_ui/windowing/history.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/cli/textual_ui/windowing/history_windowing.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/cli/textual_ui/windowing/state.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/cli/update_notifier/__init__.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/cli/update_notifier/adapters/filesystem_update_cache_repository.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/cli/update_notifier/adapters/github_update_gateway.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/cli/update_notifier/adapters/pypi_update_gateway.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/cli/update_notifier/ports/update_cache_repository.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/cli/update_notifier/ports/update_gateway.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/cli/update_notifier/update.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/cli/update_notifier/whats_new.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/core/__init__.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/core/agents/__init__.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/core/agents/manager.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/core/agents/models.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/core/auth/__init__.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/core/auth/crypto.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/core/auth/github.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/core/autocompletion/__init__.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/core/autocompletion/completers.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/core/autocompletion/file_indexer/__init__.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/core/autocompletion/file_indexer/ignore_rules.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/core/autocompletion/file_indexer/indexer.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/core/autocompletion/file_indexer/store.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/core/autocompletion/file_indexer/watcher.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/core/autocompletion/fuzzy.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/core/autocompletion/path_prompt.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/core/autocompletion/path_prompt_adapter.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/core/config/__init__.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/core/config/_settings.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/core/config/harness_files/__init__.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/core/config/harness_files/_harness_manager.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/core/config/harness_files/_paths.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/core/drydock_states.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/core/llm/__init__.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/core/llm/backend/anthropic.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/core/llm/backend/base.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/core/llm/backend/factory.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/core/llm/backend/generic.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/core/llm/backend/mistral.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/core/llm/backend/reasoning_adapter.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/core/llm/backend/vertex.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/core/llm/exceptions.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/core/llm/format.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/core/llm/message_utils.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/core/llm/types.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/core/logger.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/core/middleware.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/core/output_formatters.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/core/paths/__init__.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/core/paths/_local_config_walk.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/core/paths/_vibe_home.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/core/paths/conventions.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/core/plan_session.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/core/programmatic.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/core/prompts/__init__.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/core/prompts/cli.md +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/core/prompts/compact.md +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/core/prompts/dangerous_directory.md +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/core/prompts/diagnostic.md +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/core/prompts/explore.md +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/core/prompts/planner.md +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/core/prompts/project_context.md +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/core/prompts/tests.md +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/core/proxy_setup.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/core/session/session_loader.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/core/session/session_logger.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/core/session/session_migration.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/core/session/state_file.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/core/skills/__init__.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/core/skills/manager.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/core/skills/models.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/core/skills/parser.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/core/slug.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/core/system_prompt.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/core/telemetry/__init__.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/core/telemetry/send.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/core/teleport/errors.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/core/teleport/git.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/core/teleport/nuage.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/core/teleport/teleport.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/core/teleport/types.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/core/tools/base.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/core/tools/builtins/ask_user_question.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/core/tools/builtins/bash.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/core/tools/builtins/exit_plan_mode.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/core/tools/builtins/grep.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/core/tools/builtins/prompts/__init__.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/core/tools/builtins/prompts/ask_user_question.md +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/core/tools/builtins/prompts/bash.md +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/core/tools/builtins/prompts/grep.md +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/core/tools/builtins/prompts/read_file.md +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/core/tools/builtins/prompts/search_replace.md +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/core/tools/builtins/prompts/swe_bench.md +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/core/tools/builtins/prompts/task.md +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/core/tools/builtins/prompts/todo.md +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/core/tools/builtins/prompts/webfetch.md +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/core/tools/builtins/prompts/websearch.md +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/core/tools/builtins/prompts/write_file.md +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/core/tools/builtins/read_file.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/core/tools/builtins/search_replace.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/core/tools/builtins/task.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/core/tools/builtins/todo.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/core/tools/builtins/webfetch.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/core/tools/builtins/websearch.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/core/tools/builtins/write_file.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/core/tools/injection_guard.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/core/tools/manager.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/core/tools/mcp/__init__.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/core/tools/mcp/registry.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/core/tools/mcp/tools.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/core/tools/mcp_sampling.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/core/tools/ui.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/core/tools/utils.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/core/trusted_folders.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/core/types.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/core/utils.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/setup/onboarding/__init__.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/setup/onboarding/base.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/setup/onboarding/onboarding.tcss +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/setup/onboarding/screens/__init__.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/setup/onboarding/screens/api_key.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/setup/onboarding/screens/welcome.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/setup/trusted_folders/trust_folder_dialog.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/setup/trusted_folders/trust_folder_dialog.tcss +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/skills/__init__.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/skills/create-presentation/SKILL.md +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/whats_new.md +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock-acp.spec +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock_terms.md +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/flake.lock +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/flake.nix +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/scripts/README.md +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/scripts/bump_version.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/scripts/deploy_to_github.sh +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/scripts/install.sh +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/scripts/prepare_release.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/scripts/publish_to_pypi.sh +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/__init__.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/acp/conftest.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/acp/test_acp.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/acp/test_agent_thought.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/acp/test_bash.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/acp/test_compact_session_updates.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/acp/test_content.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/acp/test_initialize.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/acp/test_list_sessions.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/acp/test_load_session.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/acp/test_multi_session.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/acp/test_new_session.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/acp/test_proxy_setup_acp.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/acp/test_read_file.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/acp/test_search_replace.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/acp/test_set_config_option.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/acp/test_set_mode.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/acp/test_set_model.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/acp/test_tool_call_session_update.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/acp/test_utils.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/acp/test_write_file.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/autocompletion/test_file_indexer.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/autocompletion/test_fuzzy.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/autocompletion/test_path_completer_fuzzy.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/autocompletion/test_path_completer_recursive.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/autocompletion/test_path_completion_controller.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/autocompletion/test_path_prompt_transformer.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/autocompletion/test_slash_command_controller.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/autocompletion/test_ui_chat_autocompletion.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/backend/__init__.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/backend/data/__init__.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/backend/data/fireworks.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/backend/data/mistral.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/backend/test_anthropic_adapter.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/backend/test_backend.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/backend/test_reasoning_adapter.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/backend/test_vertex_anthropic_adapter.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/cli/plan_offer/adapters/fake_whoami_gateway.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/cli/plan_offer/test_decide_plan_offer.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/cli/plan_offer/test_http_whoami_gateway.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/cli/test_bell_notifications.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/cli/test_braille_renderer.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/cli/test_clipboard.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/cli/test_commands.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/cli/test_copy_shortcuts.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/cli/test_external_editor.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/cli/test_no_markup_static.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/cli/test_question_app.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/cli/test_spinner.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/cli/test_switching_mode.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/cli/test_ui_clipboard_notifications.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/cli/test_ui_session_incremental_renderer.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/cli/test_ui_session_resume.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/cli/test_ui_skill_dispatch.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/cli/textual_ui/__init__.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/cli/textual_ui/test_session_picker.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/conftest.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/core/test_agents.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/core/test_auth_crypto.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/core/test_auth_github.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/core/test_config_load_dotenv.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/core/test_config_paths.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/core/test_config_resolution.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/core/test_file_logging.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/core/test_plan_session.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/core/test_proxy_setup.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/core/test_slug.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/core/test_telemetry_send.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/core/test_teleport_git.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/core/test_teleport_nuage.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/core/test_teleport_service.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/core/test_trusted_folders.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/core/test_utils.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/e2e/common.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/e2e/conftest.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/e2e/mock_server.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/e2e/test_cli_tui_onboarding.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/e2e/test_cli_tui_streaming.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/e2e/test_cli_tui_tool_approval.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/mock/__init__.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/mock/mock_backend_factory.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/mock/mock_entrypoint.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/mock/utils.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/onboarding/test_run_onboarding.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/onboarding/test_ui_onboarding.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/session/test_session_loader.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/session/test_session_logger.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/session/test_session_migration.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/skills/conftest.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/skills/test_manager.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/skills/test_models.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/skills/test_parser.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/snapshots/__snapshots__/test_ui_snapshot_ask_user_question/test_snapshot_ask_user_question_collapsed.svg +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/snapshots/__snapshots__/test_ui_snapshot_ask_user_question/test_snapshot_ask_user_question_expanded.svg +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/snapshots/__snapshots__/test_ui_snapshot_basic_conversation/test_snapshot_shows_basic_conversation.svg +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/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.0 → drydock_cli-0.6.2}/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.0 → drydock_cli-0.6.2}/tests/snapshots/__snapshots__/test_ui_snapshot_modes/test_snapshot_cycle_to_accept_edits_mode.svg +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/snapshots/__snapshots__/test_ui_snapshot_modes/test_snapshot_cycle_to_auto_approve_mode.svg +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/snapshots/__snapshots__/test_ui_snapshot_modes/test_snapshot_cycle_to_plan_mode.svg +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/snapshots/__snapshots__/test_ui_snapshot_modes/test_snapshot_cycle_wraps_to_default.svg +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/snapshots/__snapshots__/test_ui_snapshot_modes/test_snapshot_default_mode.svg +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/snapshots/__snapshots__/test_ui_snapshot_parallel_tool_calls/test_snapshot_parallel_tool_calls_pending.svg +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/snapshots/__snapshots__/test_ui_snapshot_parallel_tool_calls/test_snapshot_parallel_tool_calls_resolved.svg +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/snapshots/__snapshots__/test_ui_snapshot_proxy_setup/test_snapshot_proxy_setup_cancel_discards_changes.svg +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/snapshots/__snapshots__/test_ui_snapshot_proxy_setup/test_snapshot_proxy_setup_edit_existing_values.svg +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/snapshots/__snapshots__/test_ui_snapshot_proxy_setup/test_snapshot_proxy_setup_initial_empty.svg +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/snapshots/__snapshots__/test_ui_snapshot_proxy_setup/test_snapshot_proxy_setup_initial_with_values.svg +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/snapshots/__snapshots__/test_ui_snapshot_proxy_setup/test_snapshot_proxy_setup_save_error.svg +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/snapshots/__snapshots__/test_ui_snapshot_proxy_setup/test_snapshot_proxy_setup_save_new_values.svg +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_question_answer_first_advance.svg +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_question_first_answered_checkmark.svg +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_question_initial.svg +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_question_navigate_left_wraps.svg +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_question_navigate_right.svg +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_question_tab_to_second.svg +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_select_initial.svg +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_select_mixed_selection.svg +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_select_navigate_to_submit.svg +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_select_other_with_text.svg +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_select_toggle_first.svg +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_select_toggle_multiple.svg +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_select_untoggle.svg +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_question_app_initial.svg +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_question_app_navigate_down.svg +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_question_app_navigate_to_other.svg +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_question_app_navigate_to_third_option.svg +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_question_app_navigate_up_wraps.svg +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_question_app_other_typing.svg +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/snapshots/__snapshots__/test_ui_snapshot_reasoning_content/test_snapshot_buffered_reasoning_yields_before_content.svg +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/snapshots/__snapshots__/test_ui_snapshot_reasoning_content/test_snapshot_shows_interleaved_reasoning.svg +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/snapshots/__snapshots__/test_ui_snapshot_reasoning_content/test_snapshot_shows_reasoning_content.svg +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/snapshots/__snapshots__/test_ui_snapshot_reasoning_content/test_snapshot_shows_reasoning_content_expanded.svg +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/snapshots/__snapshots__/test_ui_snapshot_release_update_notification/test_snapshot_shows_release_update_notification.svg +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/snapshots/__snapshots__/test_ui_snapshot_session_resume/test_snapshot_shows_resumed_session_messages.svg +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/snapshots/__snapshots__/test_ui_snapshot_streaming_tool_call/test_snapshot_tool_call_partial.svg +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/snapshots/__snapshots__/test_ui_snapshot_streaming_tool_call/test_snapshot_tool_call_updated.svg +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_push_confirmation_cancel_selected.svg +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_push_confirmation_multiple_commits.svg +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_push_confirmation_single_commit.svg +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_status_auth_complete.svg +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_status_auth_required.svg +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_status_checking_git.svg +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_status_complete.svg +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_status_error.svg +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_status_pushing.svg +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_status_sending_token.svg +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_status_starting_workflow.svg +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/snapshots/__snapshots__/test_ui_snapshot_whats_new/test_snapshot_shows_no_plan_message.svg +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/snapshots/__snapshots__/test_ui_snapshot_whats_new/test_snapshot_shows_switch_message.svg +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/snapshots/__snapshots__/test_ui_snapshot_whats_new/test_snapshot_shows_upgrade_message.svg +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/snapshots/__snapshots__/test_ui_snapshot_whats_new/test_snapshot_shows_whats_new_message.svg +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/snapshots/base_snapshot_test_app.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/snapshots/conftest.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/snapshots/snap_compare.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/snapshots/test_ui_snapshot_ask_user_question.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/snapshots/test_ui_snapshot_basic_conversation.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/snapshots/test_ui_snapshot_code_block_horizontal_scrolling.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/snapshots/test_ui_snapshot_empty_assistant_before_reasoning.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/snapshots/test_ui_snapshot_modes.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/snapshots/test_ui_snapshot_parallel_tool_calls.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/snapshots/test_ui_snapshot_proxy_setup.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/snapshots/test_ui_snapshot_question_app.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/snapshots/test_ui_snapshot_reasoning_content.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/snapshots/test_ui_snapshot_release_update_notification.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/snapshots/test_ui_snapshot_session_resume.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/snapshots/test_ui_snapshot_streaming_tool_call.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/snapshots/test_ui_snapshot_teleport.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/snapshots/test_ui_snapshot_whats_new.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/stubs/fake_backend.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/stubs/fake_client.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/stubs/fake_tool.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/test_agent_auto_compact.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/test_agent_backend.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/test_agent_observer_streaming.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/test_agent_stats.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/test_agent_tool_call.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/test_agents.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/test_cli_programmatic_preload.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/test_drydock_regression.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/test_history_manager.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/test_message_id.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/test_message_merging.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/test_middleware.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/test_reasoning_content.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/test_system_prompt.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/test_tagged_text.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/test_ui_external_editor.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/test_ui_input_history.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/tools/test_ask_user_question.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/tools/test_bash.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/tools/test_exit_plan_mode.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/tools/test_grep.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/tools/test_invoke_context.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/tools/test_manager_get_tool_config.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/tools/test_mcp.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/tools/test_mcp_sampling.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/tools/test_task.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/tools/test_ui_bash_execution.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/tools/test_webfetch.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/tools/test_websearch.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/update_notifier/adapters/fake_update_cache_repository.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/update_notifier/adapters/fake_update_gateway.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/update_notifier/test_do_update.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/update_notifier/test_filesystem_update_cache_repository.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/update_notifier/test_github_update_gateway.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/update_notifier/test_pypi_update_gateway.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/update_notifier/test_ui_update_notification.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/update_notifier/test_update_use_case.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/tests/update_notifier/test_whats_new.py +0 -0
- {drydock_cli-0.6.0 → drydock_cli-0.6.2}/uv.lock +0 -0
|
@@ -72,6 +72,11 @@ class CommandRegistry:
|
|
|
72
72
|
description="Configure proxy and SSL certificate settings",
|
|
73
73
|
handler="_show_proxy_setup",
|
|
74
74
|
),
|
|
75
|
+
"consult": Command(
|
|
76
|
+
aliases=frozenset(["/consult"]),
|
|
77
|
+
description="Ask a smarter model for advice (response visible to local model)",
|
|
78
|
+
handler="_consult_command",
|
|
79
|
+
),
|
|
75
80
|
"resume": Command(
|
|
76
81
|
aliases=frozenset(["/resume", "/continue"]),
|
|
77
82
|
description="Browse and resume past sessions",
|
|
@@ -92,7 +97,20 @@ class CommandRegistry:
|
|
|
92
97
|
return self.commands.get(cmd_name) if cmd_name else None
|
|
93
98
|
|
|
94
99
|
def get_command_name(self, user_input: str) -> str | None:
|
|
95
|
-
|
|
100
|
+
stripped = user_input.lower().strip()
|
|
101
|
+
# Exact match first
|
|
102
|
+
if stripped in self._alias_map:
|
|
103
|
+
return self._alias_map[stripped]
|
|
104
|
+
# Prefix match for commands that take arguments (e.g., /consult <question>)
|
|
105
|
+
first_word = stripped.split()[0] if stripped else ""
|
|
106
|
+
if first_word in self._alias_map:
|
|
107
|
+
return self._alias_map[first_word]
|
|
108
|
+
return None
|
|
109
|
+
|
|
110
|
+
def get_command_args(self, user_input: str) -> str:
|
|
111
|
+
"""Extract arguments after the command name."""
|
|
112
|
+
parts = user_input.strip().split(None, 1)
|
|
113
|
+
return parts[1] if len(parts) > 1 else ""
|
|
96
114
|
|
|
97
115
|
def get_help_text(self) -> str:
|
|
98
116
|
lines: list[str] = [
|
|
@@ -520,10 +520,18 @@ class VibeApp(App): # noqa: PLR0904
|
|
|
520
520
|
)
|
|
521
521
|
await self._mount_and_scroll(UserMessage(user_input))
|
|
522
522
|
handler = getattr(self, command.handler)
|
|
523
|
+
# Pass command args to handlers that accept them
|
|
524
|
+
cmd_args = self.commands.get_command_args(user_input)
|
|
523
525
|
if asyncio.iscoroutinefunction(handler):
|
|
524
|
-
|
|
526
|
+
try:
|
|
527
|
+
await handler(cmd_args)
|
|
528
|
+
except TypeError:
|
|
529
|
+
await handler() # Handler doesn't accept args
|
|
525
530
|
else:
|
|
526
|
-
|
|
531
|
+
try:
|
|
532
|
+
handler(cmd_args)
|
|
533
|
+
except TypeError:
|
|
534
|
+
handler()
|
|
527
535
|
return True
|
|
528
536
|
return False
|
|
529
537
|
|
|
@@ -927,6 +935,78 @@ class VibeApp(App): # noqa: PLR0904
|
|
|
927
935
|
"""
|
|
928
936
|
await self._mount_and_scroll(UserCommandMessage(status_text))
|
|
929
937
|
|
|
938
|
+
async def _consult_command(self, question: str = "") -> None:
|
|
939
|
+
"""Ask a consultant model for advice. Response goes into context."""
|
|
940
|
+
if not question:
|
|
941
|
+
await self._mount_and_scroll(
|
|
942
|
+
UserCommandMessage(
|
|
943
|
+
"Usage: `/consult <your question>`\n\n"
|
|
944
|
+
"Asks a smarter model for advice. The response appears in the "
|
|
945
|
+
"conversation so the local model can see and act on it.\n\n"
|
|
946
|
+
"Configure: set `consultant_model` in config.toml or use `--consultant MODEL`"
|
|
947
|
+
)
|
|
948
|
+
)
|
|
949
|
+
return
|
|
950
|
+
|
|
951
|
+
# Get consultant model from config or env
|
|
952
|
+
import os
|
|
953
|
+
consultant_model = os.environ.get("DRYDOCK_CONSULTANT_MODEL", "")
|
|
954
|
+
if not consultant_model:
|
|
955
|
+
# Check config for consultant_model setting
|
|
956
|
+
try:
|
|
957
|
+
consultant_model = getattr(self.agent_loop.config, "consultant_model", "")
|
|
958
|
+
except Exception:
|
|
959
|
+
pass
|
|
960
|
+
|
|
961
|
+
if not consultant_model:
|
|
962
|
+
await self._mount_and_scroll(
|
|
963
|
+
ErrorMessage(
|
|
964
|
+
"No consultant model configured.\n"
|
|
965
|
+
"Set via: `drydock --consultant gemini-2.5-pro` or "
|
|
966
|
+
"`export DRYDOCK_CONSULTANT_MODEL=gemini-2.5-pro`",
|
|
967
|
+
collapsed=self._tools_collapsed,
|
|
968
|
+
)
|
|
969
|
+
)
|
|
970
|
+
return
|
|
971
|
+
|
|
972
|
+
await self._mount_and_scroll(
|
|
973
|
+
UserCommandMessage(f"Consulting {consultant_model}...")
|
|
974
|
+
)
|
|
975
|
+
|
|
976
|
+
try:
|
|
977
|
+
from drydock.core.consultant import ask_consultant
|
|
978
|
+
advice = await ask_consultant(question, model=consultant_model)
|
|
979
|
+
|
|
980
|
+
if not advice or advice.startswith("(Consultant unavailable"):
|
|
981
|
+
await self._mount_and_scroll(
|
|
982
|
+
ErrorMessage(
|
|
983
|
+
f"Consultant ({consultant_model}) unavailable: {advice}",
|
|
984
|
+
collapsed=self._tools_collapsed,
|
|
985
|
+
)
|
|
986
|
+
)
|
|
987
|
+
return
|
|
988
|
+
|
|
989
|
+
# Show the advice in the UI
|
|
990
|
+
response_text = f"**Consultant ({consultant_model}):**\n\n{advice}"
|
|
991
|
+
await self._mount_and_scroll(UserCommandMessage(response_text))
|
|
992
|
+
|
|
993
|
+
# Inject into the message history so the LOCAL model can see it
|
|
994
|
+
from drydock.core.types import LLMMessage, Role
|
|
995
|
+
self.agent_loop.messages.append(
|
|
996
|
+
LLMMessage(
|
|
997
|
+
role=Role.user,
|
|
998
|
+
content=f"[CONSULTANT ADVICE from {consultant_model}]: {advice}"
|
|
999
|
+
)
|
|
1000
|
+
)
|
|
1001
|
+
|
|
1002
|
+
except Exception as e:
|
|
1003
|
+
await self._mount_and_scroll(
|
|
1004
|
+
ErrorMessage(
|
|
1005
|
+
f"Consultant error: {e}",
|
|
1006
|
+
collapsed=self._tools_collapsed,
|
|
1007
|
+
)
|
|
1008
|
+
)
|
|
1009
|
+
|
|
930
1010
|
async def _show_config(self) -> None:
|
|
931
1011
|
"""Switch to the configuration app in the bottom panel."""
|
|
932
1012
|
if self._current_bottom_app == BottomApp.Config:
|
|
@@ -835,6 +835,18 @@ class AgentLoop:
|
|
|
835
835
|
)
|
|
836
836
|
)
|
|
837
837
|
|
|
838
|
+
def _get_attempted_summary(self) -> str:
|
|
839
|
+
"""Build a summary of what the agent has already tried."""
|
|
840
|
+
if not self._tool_call_history:
|
|
841
|
+
return ""
|
|
842
|
+
attempts = []
|
|
843
|
+
for sig, (count, result) in self._tool_call_history.items():
|
|
844
|
+
if count >= 2:
|
|
845
|
+
attempts.append(f" - Ran {count}x, result: {result[:80]}")
|
|
846
|
+
if attempts:
|
|
847
|
+
return "ALREADY ATTEMPTED (do NOT repeat):\n" + "\n".join(attempts[:10])
|
|
848
|
+
return ""
|
|
849
|
+
|
|
838
850
|
def _circuit_breaker_check(self, tool_call: ResolvedToolCall) -> str | None:
|
|
839
851
|
"""Block exact-duplicate tool calls. Returns cached result or None."""
|
|
840
852
|
sig = hashlib.md5(
|
|
@@ -843,12 +855,30 @@ class AgentLoop:
|
|
|
843
855
|
|
|
844
856
|
count, last_result = self._tool_call_history.get(sig, (0, ""))
|
|
845
857
|
if count >= 2:
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
f"
|
|
849
|
-
f"
|
|
850
|
-
f"
|
|
858
|
+
attempted = self._get_attempted_summary()
|
|
859
|
+
msg = (
|
|
860
|
+
f"CIRCUIT BREAKER: You already ran `{tool_call.tool_name}` with these "
|
|
861
|
+
f"exact arguments {count} times and got the same result each time.\n\n"
|
|
862
|
+
f"Previous result: {last_result[:200]}\n\n"
|
|
863
|
+
f"{attempted}\n\n"
|
|
864
|
+
f"STOP repeating. You MUST try something DIFFERENT:\n"
|
|
865
|
+
f"- Different arguments or search terms\n"
|
|
866
|
+
f"- A completely different tool\n"
|
|
867
|
+
f"- Ask the user for clarification"
|
|
851
868
|
)
|
|
869
|
+
|
|
870
|
+
# Suggest using /consult if a consultant model is configured
|
|
871
|
+
try:
|
|
872
|
+
from drydock.core.consultant import is_consultant_available
|
|
873
|
+
if is_consultant_available():
|
|
874
|
+
msg += (
|
|
875
|
+
"\n\nTIP: A consultant model is available. "
|
|
876
|
+
"The user can type `/consult <question>` to ask it for advice."
|
|
877
|
+
)
|
|
878
|
+
except Exception:
|
|
879
|
+
pass
|
|
880
|
+
|
|
881
|
+
return msg
|
|
852
882
|
return None
|
|
853
883
|
|
|
854
884
|
def _circuit_breaker_record(self, tool_call: ResolvedToolCall, result_text: str) -> None:
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
"""Consultant agent — asks a smarter model for single-turn advice.
|
|
2
|
+
|
|
3
|
+
The consultant is a READ-ONLY advisor:
|
|
4
|
+
- The local model stays in control of ALL tool calls
|
|
5
|
+
- The consultant NEVER calls tools, writes files, or runs commands
|
|
6
|
+
- It only receives a question and returns reasoning/advice
|
|
7
|
+
- Used when the local model is stuck, uncertain, or looping
|
|
8
|
+
|
|
9
|
+
Usage from agent_loop:
|
|
10
|
+
advice = await ask_consultant("I found 3 files that match. Which one likely contains the bug?")
|
|
11
|
+
|
|
12
|
+
The consultant model is configured via:
|
|
13
|
+
- CLI: drydock --consultant gemini-2.5-pro
|
|
14
|
+
- Env: DRYDOCK_CONSULTANT_MODEL=gemini-2.5-pro
|
|
15
|
+
"""
|
|
16
|
+
|
|
17
|
+
from __future__ import annotations
|
|
18
|
+
|
|
19
|
+
import logging
|
|
20
|
+
import os
|
|
21
|
+
from typing import Any
|
|
22
|
+
|
|
23
|
+
import httpx
|
|
24
|
+
|
|
25
|
+
logger = logging.getLogger(__name__)
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
async def ask_consultant(
|
|
29
|
+
question: str,
|
|
30
|
+
context: str = "",
|
|
31
|
+
model: str | None = None,
|
|
32
|
+
api_key: str | None = None,
|
|
33
|
+
api_base: str | None = None,
|
|
34
|
+
) -> str:
|
|
35
|
+
"""Ask the consultant model a question and get text advice back.
|
|
36
|
+
|
|
37
|
+
Parameters
|
|
38
|
+
----------
|
|
39
|
+
question : str
|
|
40
|
+
The specific question to ask.
|
|
41
|
+
context : str
|
|
42
|
+
Optional context (e.g., file contents, error messages).
|
|
43
|
+
model : str
|
|
44
|
+
Model name. Defaults to DRYDOCK_CONSULTANT_MODEL env var.
|
|
45
|
+
api_key : str
|
|
46
|
+
API key. Auto-detected from common env vars if not provided.
|
|
47
|
+
api_base : str
|
|
48
|
+
API base URL. Auto-detected based on model name if not provided.
|
|
49
|
+
|
|
50
|
+
Returns
|
|
51
|
+
-------
|
|
52
|
+
str
|
|
53
|
+
The consultant's advice text, or an error message.
|
|
54
|
+
"""
|
|
55
|
+
model = model or os.environ.get("DRYDOCK_CONSULTANT_MODEL", "")
|
|
56
|
+
if not model:
|
|
57
|
+
return ""
|
|
58
|
+
|
|
59
|
+
# Auto-detect API key and base URL from model name
|
|
60
|
+
api_key = api_key or _detect_api_key(model)
|
|
61
|
+
api_base = api_base or _detect_api_base(model)
|
|
62
|
+
|
|
63
|
+
if not api_key:
|
|
64
|
+
logger.warning("No API key found for consultant model '%s'", model)
|
|
65
|
+
return ""
|
|
66
|
+
|
|
67
|
+
prompt = f"""You are a senior software engineering consultant. A junior AI coding agent is asking for your advice.
|
|
68
|
+
Give concise, actionable guidance. Do NOT provide code — just tell them WHAT to do and WHERE to look.
|
|
69
|
+
|
|
70
|
+
QUESTION:
|
|
71
|
+
{question}
|
|
72
|
+
"""
|
|
73
|
+
if context:
|
|
74
|
+
prompt += f"\nCONTEXT:\n{context[:2000]}\n"
|
|
75
|
+
|
|
76
|
+
try:
|
|
77
|
+
# Use OpenAI-compatible API (works with Gemini, OpenAI, Mistral, local models)
|
|
78
|
+
verify_ssl = os.environ.get("DRYDOCK_INSECURE") != "1"
|
|
79
|
+
async with httpx.AsyncClient(verify=verify_ssl, timeout=30.0) as client:
|
|
80
|
+
response = await client.post(
|
|
81
|
+
f"{api_base}/chat/completions",
|
|
82
|
+
headers={
|
|
83
|
+
"Authorization": f"Bearer {api_key}",
|
|
84
|
+
"Content-Type": "application/json",
|
|
85
|
+
},
|
|
86
|
+
json={
|
|
87
|
+
"model": model,
|
|
88
|
+
"messages": [{"role": "user", "content": prompt}],
|
|
89
|
+
"max_tokens": 500,
|
|
90
|
+
"temperature": 0.3,
|
|
91
|
+
# NO tools — consultant is read-only
|
|
92
|
+
},
|
|
93
|
+
)
|
|
94
|
+
response.raise_for_status()
|
|
95
|
+
data = response.json()
|
|
96
|
+
advice = data["choices"][0]["message"]["content"]
|
|
97
|
+
logger.info("Consultant (%s) responded: %s", model, advice[:100])
|
|
98
|
+
return advice
|
|
99
|
+
|
|
100
|
+
except Exception as e:
|
|
101
|
+
logger.warning("Consultant call failed: %s", e)
|
|
102
|
+
return f"(Consultant unavailable: {e})"
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
def _detect_api_key(model: str) -> str:
|
|
106
|
+
"""Auto-detect API key from environment based on model name."""
|
|
107
|
+
model_lower = model.lower()
|
|
108
|
+
|
|
109
|
+
if "gemini" in model_lower:
|
|
110
|
+
return os.environ.get("GEMINI_API_KEY", os.environ.get("GOOGLE_API_KEY", ""))
|
|
111
|
+
if "gpt" in model_lower or "o1" in model_lower or "o3" in model_lower:
|
|
112
|
+
return os.environ.get("OPENAI_API_KEY", "")
|
|
113
|
+
if "claude" in model_lower:
|
|
114
|
+
return os.environ.get("ANTHROPIC_API_KEY", "")
|
|
115
|
+
if "mistral" in model_lower or "devstral" in model_lower:
|
|
116
|
+
return os.environ.get("MISTRAL_API_KEY", "")
|
|
117
|
+
|
|
118
|
+
# Generic fallback
|
|
119
|
+
return os.environ.get("DRYDOCK_CONSULTANT_API_KEY", "")
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
def _detect_api_base(model: str) -> str:
|
|
123
|
+
"""Auto-detect API base URL from model name."""
|
|
124
|
+
model_lower = model.lower()
|
|
125
|
+
|
|
126
|
+
if "gemini" in model_lower:
|
|
127
|
+
return "https://generativelanguage.googleapis.com/v1beta/openai"
|
|
128
|
+
if "gpt" in model_lower or "o1" in model_lower or "o3" in model_lower:
|
|
129
|
+
return "https://api.openai.com/v1"
|
|
130
|
+
if "claude" in model_lower:
|
|
131
|
+
return "https://api.anthropic.com/v1"
|
|
132
|
+
if "mistral" in model_lower or "devstral" in model_lower:
|
|
133
|
+
return os.environ.get("MISTRAL_API_BASE", "https://api.mistral.ai/v1")
|
|
134
|
+
|
|
135
|
+
# Try local vLLM
|
|
136
|
+
return os.environ.get("DRYDOCK_CONSULTANT_API_BASE", "http://localhost:8000/v1")
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
def is_consultant_available() -> bool:
|
|
140
|
+
"""Check if a consultant model is configured."""
|
|
141
|
+
return bool(os.environ.get("DRYDOCK_CONSULTANT_MODEL"))
|
|
@@ -391,6 +391,7 @@ class TestCircuitBreaker:
|
|
|
391
391
|
"""Prevents exact duplicate tool calls."""
|
|
392
392
|
|
|
393
393
|
def test_circuit_breaker_blocks_after_2(self):
|
|
394
|
+
import asyncio
|
|
394
395
|
from drydock.core.agent_loop import AgentLoop
|
|
395
396
|
from drydock.core.types import MessageList
|
|
396
397
|
from types import SimpleNamespace
|
|
@@ -399,21 +400,19 @@ class TestCircuitBreaker:
|
|
|
399
400
|
al.messages = MessageList()
|
|
400
401
|
al._tool_call_history = {}
|
|
401
402
|
|
|
402
|
-
# Mock tool call with same name+args
|
|
403
403
|
tc = SimpleNamespace(tool_name="bash", raw_arguments='{"command": "ls -ltr"}')
|
|
404
404
|
|
|
405
|
-
# First two calls: no block
|
|
406
405
|
assert al._circuit_breaker_check(tc) is None
|
|
407
406
|
al._circuit_breaker_record(tc, "file1.py\nfile2.py")
|
|
408
407
|
assert al._circuit_breaker_check(tc) is None
|
|
409
408
|
al._circuit_breaker_record(tc, "file1.py\nfile2.py")
|
|
410
409
|
|
|
411
|
-
# Third call: BLOCKED
|
|
412
410
|
result = al._circuit_breaker_check(tc)
|
|
413
411
|
assert result is not None
|
|
414
412
|
assert "CIRCUIT BREAKER" in result
|
|
415
413
|
|
|
416
414
|
def test_different_args_not_blocked(self):
|
|
415
|
+
import asyncio
|
|
417
416
|
from drydock.core.agent_loop import AgentLoop
|
|
418
417
|
from drydock.core.types import MessageList
|
|
419
418
|
from types import SimpleNamespace
|
|
@@ -427,7 +426,6 @@ class TestCircuitBreaker:
|
|
|
427
426
|
|
|
428
427
|
al._circuit_breaker_record(tc1, "result1")
|
|
429
428
|
al._circuit_breaker_record(tc1, "result1")
|
|
430
|
-
# tc1 blocked, tc2 still works
|
|
431
429
|
assert al._circuit_breaker_check(tc1) is not None
|
|
432
430
|
assert al._circuit_breaker_check(tc2) is None
|
|
433
431
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/cli/plan_offer/adapters/http_whoami_gateway.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/cli/textual_ui/notifications/adapters/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
{drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/cli/textual_ui/notifications/ports/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/cli/textual_ui/widgets/chat_input/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/cli/textual_ui/widgets/chat_input/container.py
RENAMED
|
File without changes
|
{drydock_cli-0.6.0 → drydock_cli-0.6.2}/drydock/cli/textual_ui/widgets/chat_input/text_area.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|