drydock-cli 0.7.2__tar.gz → 0.7.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.7.2 → drydock_cli-0.7.4}/PKG-INFO +1 -1
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/PRD.md +14 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/drydock/core/agent_loop.py +42 -2
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/drydock/core/tools/builtins/search_replace.py +6 -3
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/pyproject.toml +1 -1
- drydock_cli-0.7.4/scripts/backup.sh +84 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/scripts/deploy_to_github.sh +1 -1
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/scripts/publish_to_pypi.sh +1 -1
- drydock_cli-0.7.4/tests/test_real_failures.py +95 -0
- drydock_cli-0.7.4/tests/test_real_issues.py +252 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/.github/CODEOWNERS +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/.github/DISCUSSION_TEMPLATE/ideas.yml +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/.github/ISSUE_TEMPLATE/bug-report.yml +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/.github/ISSUE_TEMPLATE/config.yml +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/.github/workflows/build-and-upload.yml +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/.github/workflows/ci.yml +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/.github/workflows/issue-labeler.yml +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/.github/workflows/release.yml +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/.gitignore +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/.pre-commit-config.yaml +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/.python-version +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/.typos.toml +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/.vscode/extensions.json +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/.vscode/launch.json +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/.vscode/settings.json +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/AGENTS.md +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/CHANGELOG.md +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/CLAUDE.md +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/CONTRIBUTING.md +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/Drydock_rebrand.md +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/LICENSE +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/NOTICE +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/README.md +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/action.yml +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/distribution/zed/LICENSE +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/distribution/zed/extension.toml +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/distribution/zed/icons/mistral_vibe.svg +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/docs/README.md +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/docs/acp-setup.md +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/docs/proxy-setup.md +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/drydock/__init__.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/drydock/acp/__init__.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/drydock/acp/acp_agent_loop.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/drydock/acp/acp_logger.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/drydock/acp/entrypoint.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/drydock/acp/tools/__init__.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/drydock/acp/tools/base.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/drydock/acp/tools/builtins/bash.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/drydock/acp/tools/builtins/read_file.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/drydock/acp/tools/builtins/search_replace.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/drydock/acp/tools/builtins/todo.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/drydock/acp/tools/builtins/write_file.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/drydock/acp/tools/session_update.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/drydock/acp/utils.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/drydock/cli/__init__.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/drydock/cli/autocompletion/__init__.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/drydock/cli/autocompletion/base.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/drydock/cli/autocompletion/path_completion.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/drydock/cli/autocompletion/slash_command.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/drydock/cli/cli.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/drydock/cli/clipboard.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/drydock/cli/commands.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/drydock/cli/entrypoint.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/drydock/cli/history_manager.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/drydock/cli/plan_offer/adapters/http_whoami_gateway.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/drydock/cli/plan_offer/decide_plan_offer.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/drydock/cli/plan_offer/ports/whoami_gateway.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/drydock/cli/terminal_setup.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/drydock/cli/textual_ui/__init__.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/drydock/cli/textual_ui/ansi_markdown.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/drydock/cli/textual_ui/app.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/drydock/cli/textual_ui/app.tcss +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/drydock/cli/textual_ui/external_editor.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/drydock/cli/textual_ui/handlers/__init__.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/drydock/cli/textual_ui/handlers/event_handler.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/drydock/cli/textual_ui/notifications/__init__.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/drydock/cli/textual_ui/notifications/adapters/__init__.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/drydock/cli/textual_ui/notifications/adapters/textual_notification_adapter.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/drydock/cli/textual_ui/notifications/ports/__init__.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/drydock/cli/textual_ui/notifications/ports/notification_port.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/drydock/cli/textual_ui/widgets/__init__.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/drydock/cli/textual_ui/widgets/approval_app.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/drydock/cli/textual_ui/widgets/banner/banner.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/drydock/cli/textual_ui/widgets/banner/petit_chat.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/drydock/cli/textual_ui/widgets/braille_renderer.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/drydock/cli/textual_ui/widgets/chat_input/__init__.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/drydock/cli/textual_ui/widgets/chat_input/body.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/drydock/cli/textual_ui/widgets/chat_input/completion_manager.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/drydock/cli/textual_ui/widgets/chat_input/completion_popup.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/drydock/cli/textual_ui/widgets/chat_input/container.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/drydock/cli/textual_ui/widgets/chat_input/text_area.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/drydock/cli/textual_ui/widgets/compact.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/drydock/cli/textual_ui/widgets/config_app.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/drydock/cli/textual_ui/widgets/context_progress.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/drydock/cli/textual_ui/widgets/load_more.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/drydock/cli/textual_ui/widgets/loading.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/drydock/cli/textual_ui/widgets/messages.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/drydock/cli/textual_ui/widgets/no_markup_static.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/drydock/cli/textual_ui/widgets/path_display.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/drydock/cli/textual_ui/widgets/proxy_setup_app.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/drydock/cli/textual_ui/widgets/question_app.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/drydock/cli/textual_ui/widgets/session_picker.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/drydock/cli/textual_ui/widgets/spinner.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/drydock/cli/textual_ui/widgets/status_message.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/drydock/cli/textual_ui/widgets/teleport_message.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/drydock/cli/textual_ui/widgets/tool_widgets.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/drydock/cli/textual_ui/widgets/tools.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/drydock/cli/textual_ui/widgets/vscode_compat.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/drydock/cli/textual_ui/windowing/__init__.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/drydock/cli/textual_ui/windowing/history.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/drydock/cli/textual_ui/windowing/history_windowing.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/drydock/cli/textual_ui/windowing/state.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/drydock/cli/update_notifier/__init__.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/drydock/cli/update_notifier/adapters/filesystem_update_cache_repository.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/drydock/cli/update_notifier/adapters/github_update_gateway.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/drydock/cli/update_notifier/adapters/pypi_update_gateway.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/drydock/cli/update_notifier/ports/update_cache_repository.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/drydock/cli/update_notifier/ports/update_gateway.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/drydock/cli/update_notifier/update.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/drydock/cli/update_notifier/whats_new.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/drydock/core/__init__.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/drydock/core/agents/__init__.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/drydock/core/agents/manager.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/drydock/core/agents/models.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/drydock/core/auth/__init__.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/drydock/core/auth/crypto.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/drydock/core/auth/github.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/drydock/core/autocompletion/__init__.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/drydock/core/autocompletion/completers.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/drydock/core/autocompletion/file_indexer/__init__.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/drydock/core/autocompletion/file_indexer/ignore_rules.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/drydock/core/autocompletion/file_indexer/indexer.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/drydock/core/autocompletion/file_indexer/store.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/drydock/core/autocompletion/file_indexer/watcher.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/drydock/core/autocompletion/fuzzy.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/drydock/core/autocompletion/path_prompt.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/drydock/core/autocompletion/path_prompt_adapter.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/drydock/core/config/__init__.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/drydock/core/config/_settings.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/drydock/core/config/harness_files/__init__.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/drydock/core/config/harness_files/_harness_manager.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/drydock/core/config/harness_files/_paths.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/drydock/core/consultant.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/drydock/core/drydock_states.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/drydock/core/llm/__init__.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/drydock/core/llm/backend/anthropic.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/drydock/core/llm/backend/base.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/drydock/core/llm/backend/factory.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/drydock/core/llm/backend/generic.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/drydock/core/llm/backend/mistral.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/drydock/core/llm/backend/reasoning_adapter.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/drydock/core/llm/backend/vertex.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/drydock/core/llm/exceptions.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/drydock/core/llm/format.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/drydock/core/llm/message_utils.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/drydock/core/llm/types.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/drydock/core/logger.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/drydock/core/middleware.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/drydock/core/output_formatters.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/drydock/core/paths/__init__.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/drydock/core/paths/_local_config_walk.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/drydock/core/paths/_vibe_home.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/drydock/core/paths/conventions.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/drydock/core/plan_session.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/drydock/core/programmatic.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/drydock/core/prompts/__init__.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/drydock/core/prompts/cli.md +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/drydock/core/prompts/compact.md +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/drydock/core/prompts/dangerous_directory.md +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/drydock/core/prompts/diagnostic.md +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/drydock/core/prompts/explore.md +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/drydock/core/prompts/planner.md +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/drydock/core/prompts/project_context.md +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/drydock/core/prompts/tests.md +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/drydock/core/proxy_setup.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/drydock/core/session/session_loader.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/drydock/core/session/session_logger.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/drydock/core/session/session_migration.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/drydock/core/session/state_file.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/drydock/core/skills/__init__.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/drydock/core/skills/manager.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/drydock/core/skills/models.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/drydock/core/skills/parser.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/drydock/core/slug.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/drydock/core/system_prompt.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/drydock/core/telemetry/__init__.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/drydock/core/telemetry/send.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/drydock/core/teleport/errors.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/drydock/core/teleport/git.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/drydock/core/teleport/nuage.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/drydock/core/teleport/teleport.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/drydock/core/teleport/types.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/drydock/core/tools/base.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/drydock/core/tools/builtins/ask_user_question.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/drydock/core/tools/builtins/bash.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/drydock/core/tools/builtins/exit_plan_mode.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/drydock/core/tools/builtins/grep.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/drydock/core/tools/builtins/prompts/__init__.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/drydock/core/tools/builtins/prompts/ask_user_question.md +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/drydock/core/tools/builtins/prompts/bash.md +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/drydock/core/tools/builtins/prompts/grep.md +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/drydock/core/tools/builtins/prompts/read_file.md +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/drydock/core/tools/builtins/prompts/search_replace.md +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/drydock/core/tools/builtins/prompts/swe_bench.md +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/drydock/core/tools/builtins/prompts/task.md +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/drydock/core/tools/builtins/prompts/todo.md +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/drydock/core/tools/builtins/prompts/webfetch.md +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/drydock/core/tools/builtins/prompts/websearch.md +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/drydock/core/tools/builtins/prompts/write_file.md +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/drydock/core/tools/builtins/read_file.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/drydock/core/tools/builtins/task.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/drydock/core/tools/builtins/todo.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/drydock/core/tools/builtins/webfetch.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/drydock/core/tools/builtins/websearch.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/drydock/core/tools/builtins/write_file.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/drydock/core/tools/injection_guard.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/drydock/core/tools/manager.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/drydock/core/tools/mcp/__init__.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/drydock/core/tools/mcp/registry.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/drydock/core/tools/mcp/tools.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/drydock/core/tools/mcp_sampling.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/drydock/core/tools/ui.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/drydock/core/tools/utils.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/drydock/core/trusted_folders.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/drydock/core/types.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/drydock/core/utils.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/drydock/setup/onboarding/__init__.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/drydock/setup/onboarding/base.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/drydock/setup/onboarding/onboarding.tcss +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/drydock/setup/onboarding/screens/__init__.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/drydock/setup/onboarding/screens/api_key.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/drydock/setup/onboarding/screens/welcome.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/drydock/setup/trusted_folders/trust_folder_dialog.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/drydock/setup/trusted_folders/trust_folder_dialog.tcss +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/drydock/skills/__init__.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/drydock/skills/create-presentation/SKILL.md +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/drydock/skills/deep-research/SKILL.md +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/drydock/whats_new.md +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/drydock-acp.spec +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/drydock_terms.md +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/flake.lock +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/flake.nix +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/scripts/README.md +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/scripts/bump_version.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/scripts/install.sh +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/scripts/prepare_release.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/tests/__init__.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/tests/acp/conftest.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/tests/acp/test_acp.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/tests/acp/test_agent_thought.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/tests/acp/test_bash.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/tests/acp/test_compact_session_updates.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/tests/acp/test_content.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/tests/acp/test_initialize.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/tests/acp/test_list_sessions.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/tests/acp/test_load_session.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/tests/acp/test_multi_session.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/tests/acp/test_new_session.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/tests/acp/test_proxy_setup_acp.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/tests/acp/test_read_file.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/tests/acp/test_search_replace.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/tests/acp/test_set_config_option.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/tests/acp/test_set_mode.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/tests/acp/test_set_model.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/tests/acp/test_tool_call_session_update.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/tests/acp/test_utils.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/tests/acp/test_write_file.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/tests/autocompletion/test_file_indexer.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/tests/autocompletion/test_fuzzy.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/tests/autocompletion/test_path_completer_fuzzy.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/tests/autocompletion/test_path_completer_recursive.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/tests/autocompletion/test_path_completion_controller.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/tests/autocompletion/test_path_prompt_transformer.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/tests/autocompletion/test_slash_command_controller.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/tests/autocompletion/test_ui_chat_autocompletion.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/tests/backend/__init__.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/tests/backend/data/__init__.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/tests/backend/data/fireworks.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/tests/backend/data/mistral.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/tests/backend/test_anthropic_adapter.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/tests/backend/test_backend.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/tests/backend/test_reasoning_adapter.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/tests/backend/test_vertex_anthropic_adapter.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/tests/cli/plan_offer/adapters/fake_whoami_gateway.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/tests/cli/plan_offer/test_decide_plan_offer.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/tests/cli/plan_offer/test_http_whoami_gateway.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/tests/cli/test_bell_notifications.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/tests/cli/test_braille_renderer.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/tests/cli/test_clipboard.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/tests/cli/test_commands.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/tests/cli/test_copy_shortcuts.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/tests/cli/test_external_editor.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/tests/cli/test_no_markup_static.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/tests/cli/test_question_app.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/tests/cli/test_spinner.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/tests/cli/test_switching_mode.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/tests/cli/test_ui_clipboard_notifications.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/tests/cli/test_ui_session_incremental_renderer.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/tests/cli/test_ui_session_resume.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/tests/cli/test_ui_skill_dispatch.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/tests/cli/textual_ui/__init__.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/tests/cli/textual_ui/test_session_picker.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/tests/conftest.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/tests/core/test_agents.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/tests/core/test_auth_crypto.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/tests/core/test_auth_github.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/tests/core/test_config_load_dotenv.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/tests/core/test_config_paths.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/tests/core/test_config_resolution.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/tests/core/test_file_logging.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/tests/core/test_plan_session.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/tests/core/test_proxy_setup.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/tests/core/test_slug.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/tests/core/test_telemetry_send.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/tests/core/test_teleport_git.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/tests/core/test_teleport_nuage.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/tests/core/test_teleport_service.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/tests/core/test_trusted_folders.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/tests/core/test_utils.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/tests/e2e/common.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/tests/e2e/conftest.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/tests/e2e/mock_server.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/tests/e2e/test_cli_tui_onboarding.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/tests/e2e/test_cli_tui_streaming.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/tests/e2e/test_cli_tui_tool_approval.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/tests/mock/__init__.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/tests/mock/mock_backend_factory.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/tests/mock/mock_entrypoint.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/tests/mock/utils.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/tests/onboarding/test_run_onboarding.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/tests/onboarding/test_ui_onboarding.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/tests/session/test_session_loader.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/tests/session/test_session_logger.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/tests/session/test_session_migration.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/tests/skills/conftest.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/tests/skills/test_manager.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/tests/skills/test_models.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/tests/skills/test_parser.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/tests/snapshots/__snapshots__/test_ui_snapshot_ask_user_question/test_snapshot_ask_user_question_collapsed.svg +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/tests/snapshots/__snapshots__/test_ui_snapshot_ask_user_question/test_snapshot_ask_user_question_expanded.svg +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/tests/snapshots/__snapshots__/test_ui_snapshot_basic_conversation/test_snapshot_shows_basic_conversation.svg +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.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.7.2 → drydock_cli-0.7.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.7.2 → drydock_cli-0.7.4}/tests/snapshots/__snapshots__/test_ui_snapshot_modes/test_snapshot_cycle_to_accept_edits_mode.svg +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/tests/snapshots/__snapshots__/test_ui_snapshot_modes/test_snapshot_cycle_to_auto_approve_mode.svg +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/tests/snapshots/__snapshots__/test_ui_snapshot_modes/test_snapshot_cycle_to_plan_mode.svg +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/tests/snapshots/__snapshots__/test_ui_snapshot_modes/test_snapshot_cycle_wraps_to_default.svg +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/tests/snapshots/__snapshots__/test_ui_snapshot_modes/test_snapshot_default_mode.svg +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/tests/snapshots/__snapshots__/test_ui_snapshot_parallel_tool_calls/test_snapshot_parallel_tool_calls_pending.svg +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/tests/snapshots/__snapshots__/test_ui_snapshot_parallel_tool_calls/test_snapshot_parallel_tool_calls_resolved.svg +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/tests/snapshots/__snapshots__/test_ui_snapshot_proxy_setup/test_snapshot_proxy_setup_cancel_discards_changes.svg +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/tests/snapshots/__snapshots__/test_ui_snapshot_proxy_setup/test_snapshot_proxy_setup_edit_existing_values.svg +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/tests/snapshots/__snapshots__/test_ui_snapshot_proxy_setup/test_snapshot_proxy_setup_initial_empty.svg +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/tests/snapshots/__snapshots__/test_ui_snapshot_proxy_setup/test_snapshot_proxy_setup_initial_with_values.svg +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/tests/snapshots/__snapshots__/test_ui_snapshot_proxy_setup/test_snapshot_proxy_setup_save_error.svg +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/tests/snapshots/__snapshots__/test_ui_snapshot_proxy_setup/test_snapshot_proxy_setup_save_new_values.svg +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_question_answer_first_advance.svg +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_question_first_answered_checkmark.svg +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_question_initial.svg +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_question_navigate_left_wraps.svg +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_question_navigate_right.svg +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_question_tab_to_second.svg +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_select_initial.svg +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_select_mixed_selection.svg +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_select_navigate_to_submit.svg +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_select_other_with_text.svg +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_select_toggle_first.svg +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_select_toggle_multiple.svg +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_select_untoggle.svg +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_question_app_initial.svg +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_question_app_navigate_down.svg +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_question_app_navigate_to_other.svg +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_question_app_navigate_to_third_option.svg +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_question_app_navigate_up_wraps.svg +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_question_app_other_typing.svg +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/tests/snapshots/__snapshots__/test_ui_snapshot_reasoning_content/test_snapshot_buffered_reasoning_yields_before_content.svg +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/tests/snapshots/__snapshots__/test_ui_snapshot_reasoning_content/test_snapshot_shows_interleaved_reasoning.svg +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/tests/snapshots/__snapshots__/test_ui_snapshot_reasoning_content/test_snapshot_shows_reasoning_content.svg +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/tests/snapshots/__snapshots__/test_ui_snapshot_reasoning_content/test_snapshot_shows_reasoning_content_expanded.svg +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/tests/snapshots/__snapshots__/test_ui_snapshot_release_update_notification/test_snapshot_shows_release_update_notification.svg +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/tests/snapshots/__snapshots__/test_ui_snapshot_session_resume/test_snapshot_shows_resumed_session_messages.svg +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/tests/snapshots/__snapshots__/test_ui_snapshot_streaming_tool_call/test_snapshot_tool_call_partial.svg +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/tests/snapshots/__snapshots__/test_ui_snapshot_streaming_tool_call/test_snapshot_tool_call_updated.svg +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_push_confirmation_cancel_selected.svg +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_push_confirmation_multiple_commits.svg +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_push_confirmation_single_commit.svg +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_status_auth_complete.svg +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_status_auth_required.svg +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_status_checking_git.svg +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_status_complete.svg +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_status_error.svg +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_status_pushing.svg +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_status_sending_token.svg +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_status_starting_workflow.svg +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/tests/snapshots/__snapshots__/test_ui_snapshot_whats_new/test_snapshot_shows_no_plan_message.svg +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/tests/snapshots/__snapshots__/test_ui_snapshot_whats_new/test_snapshot_shows_switch_message.svg +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/tests/snapshots/__snapshots__/test_ui_snapshot_whats_new/test_snapshot_shows_upgrade_message.svg +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/tests/snapshots/__snapshots__/test_ui_snapshot_whats_new/test_snapshot_shows_whats_new_message.svg +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/tests/snapshots/base_snapshot_test_app.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/tests/snapshots/conftest.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/tests/snapshots/snap_compare.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/tests/snapshots/test_ui_snapshot_ask_user_question.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/tests/snapshots/test_ui_snapshot_basic_conversation.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/tests/snapshots/test_ui_snapshot_code_block_horizontal_scrolling.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/tests/snapshots/test_ui_snapshot_empty_assistant_before_reasoning.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/tests/snapshots/test_ui_snapshot_modes.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/tests/snapshots/test_ui_snapshot_parallel_tool_calls.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/tests/snapshots/test_ui_snapshot_proxy_setup.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/tests/snapshots/test_ui_snapshot_question_app.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/tests/snapshots/test_ui_snapshot_reasoning_content.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/tests/snapshots/test_ui_snapshot_release_update_notification.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/tests/snapshots/test_ui_snapshot_session_resume.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/tests/snapshots/test_ui_snapshot_streaming_tool_call.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/tests/snapshots/test_ui_snapshot_teleport.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/tests/snapshots/test_ui_snapshot_whats_new.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/tests/stubs/fake_backend.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/tests/stubs/fake_client.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/tests/stubs/fake_tool.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/tests/test_agent_auto_compact.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/tests/test_agent_backend.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/tests/test_agent_observer_streaming.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/tests/test_agent_stats.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/tests/test_agent_tasks.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/tests/test_agent_tool_call.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/tests/test_agents.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/tests/test_cli_programmatic_preload.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/tests/test_drydock_regression.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/tests/test_drydock_tasks.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/tests/test_history_manager.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/tests/test_integration.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/tests/test_loop_detection.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/tests/test_message_id.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/tests/test_message_merging.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/tests/test_middleware.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/tests/test_reasoning_content.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/tests/test_system_prompt.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/tests/test_tagged_text.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/tests/test_ui_external_editor.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/tests/test_ui_input_history.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/tests/test_user_issues.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/tests/tools/test_ask_user_question.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/tests/tools/test_bash.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/tests/tools/test_exit_plan_mode.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/tests/tools/test_grep.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/tests/tools/test_invoke_context.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/tests/tools/test_manager_get_tool_config.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/tests/tools/test_mcp.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/tests/tools/test_mcp_sampling.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/tests/tools/test_task.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/tests/tools/test_ui_bash_execution.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/tests/tools/test_webfetch.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/tests/tools/test_websearch.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/tests/update_notifier/adapters/fake_update_cache_repository.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/tests/update_notifier/adapters/fake_update_gateway.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/tests/update_notifier/test_do_update.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/tests/update_notifier/test_filesystem_update_cache_repository.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/tests/update_notifier/test_github_update_gateway.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/tests/update_notifier/test_pypi_update_gateway.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/tests/update_notifier/test_ui_update_notification.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/tests/update_notifier/test_update_use_case.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/tests/update_notifier/test_whats_new.py +0 -0
- {drydock_cli-0.7.2 → drydock_cli-0.7.4}/uv.lock +0 -0
|
@@ -178,3 +178,17 @@ Show the user what the agent has planned in its execution pipeline.
|
|
|
178
178
|
|
|
179
179
|
### P4: Support more LLM backends
|
|
180
180
|
Test with Claude, GPT-4, Gemini to understand which improvements are model-specific.
|
|
181
|
+
|
|
182
|
+
### Phase 7: Real Test-Driven Fixes (Mar 26)
|
|
183
|
+
|
|
184
|
+
Shifted to test-driven development with real vLLM backend — no more mocks for critical bugs.
|
|
185
|
+
|
|
186
|
+
| Issue | Test Result (before fix) | Fix | Test Result (after fix) |
|
|
187
|
+
|-------|------------------------|-----|----------------------|
|
|
188
|
+
| Circuit breaker fires but model keeps calling | FAILED: 20 bash calls, 17 breaker fires ignored | Force-stop conversation after 3 consecutive breaker fires + break tool loop | PASSED: stops within 3 calls |
|
|
189
|
+
|
|
190
|
+
**Testing methodology changed:**
|
|
191
|
+
- All critical tests run against real vLLM at localhost:8000
|
|
192
|
+
- Tests must FAIL first (proving the bug exists)
|
|
193
|
+
- Then fix code, re-run until PASS
|
|
194
|
+
- 166 total tests (155 mock + 11 real backend)
|
|
@@ -191,6 +191,7 @@ class AgentLoop:
|
|
|
191
191
|
# Circuit breaker: track tool call signatures to prevent exact repeats
|
|
192
192
|
# Key: hash(tool_name + args), Value: (count, last_result_snippet)
|
|
193
193
|
self._tool_call_history: dict[str, tuple[int, str]] = {}
|
|
194
|
+
self._consecutive_circuit_breaker_fires: int = 0
|
|
194
195
|
|
|
195
196
|
system_prompt = get_universal_system_prompt(
|
|
196
197
|
self.tool_manager, self.config, self.skill_manager, self.agent_manager
|
|
@@ -512,11 +513,16 @@ class AgentLoop:
|
|
|
512
513
|
self.stats.steps += 1
|
|
513
514
|
user_cancelled = False
|
|
514
515
|
try:
|
|
516
|
+
force_stopped = False
|
|
515
517
|
async for event in self._perform_llm_turn():
|
|
516
518
|
if is_user_cancellation_event(event):
|
|
517
519
|
user_cancelled = True
|
|
520
|
+
if isinstance(event, AssistantEvent) and event.stopped_by_middleware:
|
|
521
|
+
force_stopped = True
|
|
518
522
|
yield event
|
|
519
523
|
await self._save_messages()
|
|
524
|
+
if force_stopped:
|
|
525
|
+
return
|
|
520
526
|
# Reset API error count on successful turn
|
|
521
527
|
api_error_count = 0
|
|
522
528
|
except (RuntimeError, AgentLoopLLMResponseError) as e:
|
|
@@ -641,7 +647,11 @@ class AgentLoop:
|
|
|
641
647
|
should_break_loop = True
|
|
642
648
|
nudge_text = None
|
|
643
649
|
if nudge_text:
|
|
644
|
-
|
|
650
|
+
# Inject as user message so the model actually sees it
|
|
651
|
+
# (inject_system_note buries it in old tool results)
|
|
652
|
+
self.messages.append(
|
|
653
|
+
LLMMessage(role=Role.user, content=nudge_text)
|
|
654
|
+
)
|
|
645
655
|
logger.info("Model gave text without editing — nudging (attempt %d)", text_without_action)
|
|
646
656
|
|
|
647
657
|
# If model has been investigating for too long without making an edit,
|
|
@@ -896,6 +906,29 @@ class AgentLoop:
|
|
|
896
906
|
) -> AsyncGenerator[ToolResultEvent | ToolStreamEvent]:
|
|
897
907
|
# Circuit breaker: block exact duplicate calls after 2 attempts
|
|
898
908
|
if blocked := self._circuit_breaker_check(tool_call):
|
|
909
|
+
self._consecutive_circuit_breaker_fires += 1
|
|
910
|
+
|
|
911
|
+
if self._consecutive_circuit_breaker_fires >= 3:
|
|
912
|
+
# Model is ignoring the circuit breaker — force stop
|
|
913
|
+
force_msg = (
|
|
914
|
+
f"FORCED STOP: You ignored the circuit breaker {self._consecutive_circuit_breaker_fires} times. "
|
|
915
|
+
f"The session is being terminated because you keep running the same command. "
|
|
916
|
+
f"You MUST try a completely different approach."
|
|
917
|
+
)
|
|
918
|
+
yield ToolResultEvent(
|
|
919
|
+
tool_name=tool_call.tool_name,
|
|
920
|
+
tool_class=tool_call.tool_class,
|
|
921
|
+
error=force_msg,
|
|
922
|
+
tool_call_id=tool_call.call_id,
|
|
923
|
+
)
|
|
924
|
+
self._handle_tool_response(tool_call, force_msg, "failure")
|
|
925
|
+
# Inject stop signal into messages
|
|
926
|
+
yield AssistantEvent(
|
|
927
|
+
content=f"\n\n[{force_msg}]\n",
|
|
928
|
+
stopped_by_middleware=True,
|
|
929
|
+
)
|
|
930
|
+
return
|
|
931
|
+
|
|
899
932
|
yield ToolResultEvent(
|
|
900
933
|
tool_name=tool_call.tool_name,
|
|
901
934
|
tool_class=tool_call.tool_class,
|
|
@@ -904,6 +937,9 @@ class AgentLoop:
|
|
|
904
937
|
)
|
|
905
938
|
self._handle_tool_response(tool_call, blocked, "failure")
|
|
906
939
|
return
|
|
940
|
+
else:
|
|
941
|
+
# Reset consecutive fires when a non-blocked call happens
|
|
942
|
+
self._consecutive_circuit_breaker_fires = 0
|
|
907
943
|
|
|
908
944
|
try:
|
|
909
945
|
tool_instance = self.tool_manager.get(tool_call.tool_name)
|
|
@@ -1060,10 +1096,14 @@ class AgentLoop:
|
|
|
1060
1096
|
|
|
1061
1097
|
async def _handle_tool_calls(
|
|
1062
1098
|
self, resolved: ResolvedMessage
|
|
1063
|
-
) -> AsyncGenerator[ToolCallEvent | ToolResultEvent | ToolStreamEvent]:
|
|
1099
|
+
) -> AsyncGenerator[ToolCallEvent | ToolResultEvent | ToolStreamEvent | AssistantEvent]:
|
|
1064
1100
|
async for event in self._emit_failed_tool_events(resolved.failed_calls):
|
|
1065
1101
|
yield event
|
|
1066
1102
|
for tool_call in resolved.tool_calls:
|
|
1103
|
+
# Stop processing more tool calls if circuit breaker force-stopped
|
|
1104
|
+
if self._consecutive_circuit_breaker_fires >= 3:
|
|
1105
|
+
break
|
|
1106
|
+
|
|
1067
1107
|
yield ToolCallEvent(
|
|
1068
1108
|
tool_name=tool_call.tool_name,
|
|
1069
1109
|
tool_class=tool_call.tool_class,
|
|
@@ -119,12 +119,15 @@ class SearchReplace(
|
|
|
119
119
|
) -> AsyncGenerator[ToolStreamEvent | SearchReplaceResult, None]:
|
|
120
120
|
file_path, search_replace_blocks = self._prepare_and_validate_args(args)
|
|
121
121
|
|
|
122
|
-
#
|
|
122
|
+
# BLOCK editing test files — the bug is in source code, not tests
|
|
123
123
|
file_str = str(file_path)
|
|
124
124
|
if ("/tests/" in file_str or "/test_" in file_str or
|
|
125
125
|
file_str.endswith("_test.py") or "/testing/" in file_str):
|
|
126
|
-
|
|
127
|
-
|
|
126
|
+
raise ToolError(
|
|
127
|
+
f"BLOCKED: You are trying to edit a test file ({file_path.name}). "
|
|
128
|
+
f"The bug is in LIBRARY SOURCE code, not tests. "
|
|
129
|
+
f"Use grep to find the corresponding source file and edit that instead."
|
|
130
|
+
)
|
|
128
131
|
|
|
129
132
|
# Injection guard: scan replacement content for suspicious patterns
|
|
130
133
|
from drydock.core.tools.injection_guard import check_content_for_injection
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# Backup DryDock project to NAS
|
|
3
|
+
# Cron: 0 3 * * * /data3/drydock/scripts/backup.sh >> /data3/drydock/logs/backup.log 2>&1
|
|
4
|
+
|
|
5
|
+
set -euo pipefail
|
|
6
|
+
|
|
7
|
+
DRYDOCK_SRC="/data3/drydock"
|
|
8
|
+
BENCH_DIR="/data3/swe_bench_runs"
|
|
9
|
+
NAS_MOUNT="/mnt/nas_backups"
|
|
10
|
+
BACKUP_DIR="$NAS_MOUNT/drydock"
|
|
11
|
+
DATE=$(date +%Y%m%d)
|
|
12
|
+
LOGDIR="$DRYDOCK_SRC/logs"
|
|
13
|
+
|
|
14
|
+
mkdir -p "$LOGDIR"
|
|
15
|
+
|
|
16
|
+
log() { echo "[$(date '+%Y-%m-%d %H:%M:%S')] $*"; }
|
|
17
|
+
|
|
18
|
+
# Check NAS is mounted
|
|
19
|
+
if ! mountpoint -q "$NAS_MOUNT" 2>/dev/null; then
|
|
20
|
+
log "NAS not mounted. Attempting mount..."
|
|
21
|
+
sudo mount "$NAS_MOUNT" 2>/dev/null || {
|
|
22
|
+
log "ERROR: Cannot mount NAS at $NAS_MOUNT. Skipping backup."
|
|
23
|
+
exit 1
|
|
24
|
+
}
|
|
25
|
+
fi
|
|
26
|
+
|
|
27
|
+
mkdir -p "$BACKUP_DIR"
|
|
28
|
+
|
|
29
|
+
log "Starting backup..."
|
|
30
|
+
|
|
31
|
+
# Backup 1: DryDock source code (excluding __pycache__, .git objects)
|
|
32
|
+
rsync -rlpt --delete --no-group --no-owner \
|
|
33
|
+
--exclude='__pycache__/' \
|
|
34
|
+
--exclude='.pytest_cache/' \
|
|
35
|
+
--exclude='dist/' \
|
|
36
|
+
--exclude='*.egg-info/' \
|
|
37
|
+
--exclude='.git/objects/' \
|
|
38
|
+
--exclude='logs/' \
|
|
39
|
+
"$DRYDOCK_SRC/" "$BACKUP_DIR/source/"
|
|
40
|
+
|
|
41
|
+
log "Source backed up."
|
|
42
|
+
|
|
43
|
+
# Backup 2: SWE-bench results and state (not the repos — too large)
|
|
44
|
+
rsync -rlpt --delete --no-group --no-owner \
|
|
45
|
+
--exclude='repos/' \
|
|
46
|
+
--exclude='tasks/*/repo/' \
|
|
47
|
+
--exclude='__pycache__/' \
|
|
48
|
+
"$BENCH_DIR/continuous_bench_state.json" \
|
|
49
|
+
"$BENCH_DIR/auto_improve_state.json" \
|
|
50
|
+
"$BENCH_DIR/harness.py" \
|
|
51
|
+
"$BENCH_DIR/continuous_bench.sh" \
|
|
52
|
+
"$BENCH_DIR/analyze_batch.py" \
|
|
53
|
+
"$BACKUP_DIR/bench/" 2>/dev/null || true
|
|
54
|
+
|
|
55
|
+
# Backup results directories (small — just JSON)
|
|
56
|
+
rsync -rlpt --no-group --no-owner \
|
|
57
|
+
--include='*/' \
|
|
58
|
+
--include='results.json' \
|
|
59
|
+
--exclude='*' \
|
|
60
|
+
"$BENCH_DIR/results/" "$BACKUP_DIR/bench/results/" 2>/dev/null || true
|
|
61
|
+
|
|
62
|
+
log "Bench state backed up."
|
|
63
|
+
|
|
64
|
+
# Backup 3: Config files
|
|
65
|
+
mkdir -p "$BACKUP_DIR/config/drydock_config" "$BACKUP_DIR/config/drydock_home"
|
|
66
|
+
rsync -rlpt --no-group --no-owner "$HOME/.config/drydock/" "$BACKUP_DIR/config/drydock_config/" 2>/dev/null || true
|
|
67
|
+
rsync -rlpt --no-group --no-owner --exclude='logs/' "$HOME/.drydock/" "$BACKUP_DIR/config/drydock_home/" 2>/dev/null || true
|
|
68
|
+
|
|
69
|
+
log "Config backed up."
|
|
70
|
+
|
|
71
|
+
# Backup 4: Crontab
|
|
72
|
+
crontab -l > "$BACKUP_DIR/crontab_$(hostname).txt" 2>/dev/null || true
|
|
73
|
+
|
|
74
|
+
# Write backup manifest
|
|
75
|
+
cat > "$BACKUP_DIR/MANIFEST.txt" << EOF
|
|
76
|
+
DryDock Backup
|
|
77
|
+
Date: $(date)
|
|
78
|
+
Host: $(hostname)
|
|
79
|
+
Source: $DRYDOCK_SRC
|
|
80
|
+
Bench: $BENCH_DIR
|
|
81
|
+
Version: $(python3 -c "import sys; sys.path.insert(0,'$DRYDOCK_SRC'); from drydock import __version__; print(__version__)" 2>/dev/null || echo "unknown")
|
|
82
|
+
EOF
|
|
83
|
+
|
|
84
|
+
log "Backup complete to $BACKUP_DIR"
|
|
@@ -37,7 +37,7 @@ AUTH_URL="https://${GITHUB_TOKEN}@github.com/fbobe321/drydock.git"
|
|
|
37
37
|
|
|
38
38
|
log "Running regression tests..."
|
|
39
39
|
cd "$DRYDOCK_SRC"
|
|
40
|
-
if ! python3 -m pytest tests/test_drydock_regression.py tests/test_drydock_tasks.py tests/test_loop_detection.py tests/test_agent_tasks.py tests/test_integration.py tests/test_user_issues.py \
|
|
40
|
+
if ! python3 -m pytest tests/test_drydock_regression.py tests/test_drydock_tasks.py tests/test_loop_detection.py tests/test_agent_tasks.py tests/test_integration.py tests/test_user_issues.py tests/test_real_issues.py \
|
|
41
41
|
-p no:xdist -p no:cov --override-ini="addopts=" -q 2>&1; then
|
|
42
42
|
log "TESTS FAILED — deploy aborted. Fix the tests before deploying."
|
|
43
43
|
exit 1
|
|
@@ -25,7 +25,7 @@ PYPI_TOKEN=$(cat "$TOKEN_FILE")
|
|
|
25
25
|
|
|
26
26
|
# --- Run tests ---
|
|
27
27
|
log "Running regression tests..."
|
|
28
|
-
if ! $PYTHON -m pytest tests/test_drydock_regression.py tests/test_drydock_tasks.py tests/test_loop_detection.py tests/test_agent_tasks.py tests/test_integration.py tests/test_user_issues.py \
|
|
28
|
+
if ! $PYTHON -m pytest tests/test_drydock_regression.py tests/test_drydock_tasks.py tests/test_loop_detection.py tests/test_agent_tasks.py tests/test_integration.py tests/test_user_issues.py tests/test_real_issues.py \
|
|
29
29
|
-p no:xdist -p no:cov --override-ini="addopts=" -q 2>&1; then
|
|
30
30
|
log "TESTS FAILED — publish aborted."
|
|
31
31
|
exit 1
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
"""Tests that FAIL — proving real bugs exist.
|
|
2
|
+
|
|
3
|
+
These tests reproduce actual user-reported failures against the real backend.
|
|
4
|
+
They should FAIL until the underlying code is fixed.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
import asyncio
|
|
10
|
+
import os
|
|
11
|
+
from pathlib import Path
|
|
12
|
+
|
|
13
|
+
import httpx
|
|
14
|
+
import pytest
|
|
15
|
+
|
|
16
|
+
from drydock.core.config.harness_files import init_harness_files_manager
|
|
17
|
+
|
|
18
|
+
# Initialize harness before importing agent
|
|
19
|
+
try:
|
|
20
|
+
init_harness_files_manager("user", "project")
|
|
21
|
+
except RuntimeError:
|
|
22
|
+
pass
|
|
23
|
+
|
|
24
|
+
from drydock.core.agent_loop import AgentLoop
|
|
25
|
+
from drydock.core.agents.models import BuiltinAgentName
|
|
26
|
+
from drydock.core.config import Backend, ModelConfig, ProviderConfig, VibeConfig
|
|
27
|
+
from drydock.core.types import (
|
|
28
|
+
AssistantEvent,
|
|
29
|
+
BaseEvent,
|
|
30
|
+
Role,
|
|
31
|
+
ToolCallEvent,
|
|
32
|
+
ToolResultEvent,
|
|
33
|
+
)
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def _vllm_ok() -> bool:
|
|
37
|
+
try:
|
|
38
|
+
return httpx.get("http://localhost:8000/v1/models", timeout=3).status_code == 200
|
|
39
|
+
except Exception:
|
|
40
|
+
return False
|
|
41
|
+
|
|
42
|
+
pytestmark = pytest.mark.skipif(not _vllm_ok(), reason="vLLM not running")
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
def _config(tmp_path: Path) -> VibeConfig:
|
|
46
|
+
return VibeConfig(
|
|
47
|
+
active_model="devstral", auto_approve=True, enable_telemetry=False,
|
|
48
|
+
include_project_context=False, system_prompt_id="tests",
|
|
49
|
+
providers=[ProviderConfig(name="local", api_base="http://localhost:8000/v1", api_key_env_var="", backend=Backend.GENERIC)],
|
|
50
|
+
models=[ModelConfig(name="devstral", provider="local", input_price=0, output_price=0)],
|
|
51
|
+
session_logging={"enabled": False, "save_dir": str(tmp_path / "logs")},
|
|
52
|
+
)
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
def _agent(tmp_path: Path, max_turns: int = 15) -> AgentLoop:
|
|
56
|
+
return AgentLoop(config=_config(tmp_path), agent_name=BuiltinAgentName.AUTO_APPROVE, max_turns=max_turns)
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
async def _run(agent, prompt, max_events=100):
|
|
60
|
+
events = []
|
|
61
|
+
async for ev in agent.act(prompt):
|
|
62
|
+
events.append(ev)
|
|
63
|
+
if len(events) >= max_events:
|
|
64
|
+
break
|
|
65
|
+
return events
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
# ============================================================================
|
|
69
|
+
# ISSUE: Circuit breaker fires but model KEEPS calling the same tool
|
|
70
|
+
# The breaker returns an error, but the model ignores it and calls again.
|
|
71
|
+
# Proven: 20 bash calls despite 17 circuit breaker fires.
|
|
72
|
+
# ============================================================================
|
|
73
|
+
|
|
74
|
+
@pytest.mark.asyncio
|
|
75
|
+
async def test_circuit_breaker_actually_stops_execution(tmp_path):
|
|
76
|
+
"""After circuit breaker fires, model should NOT make more than 3 additional
|
|
77
|
+
identical calls. Currently it makes 17+."""
|
|
78
|
+
agent = _agent(tmp_path, max_turns=20)
|
|
79
|
+
events = await _run(agent, "Run the command 'echo hello' ten separate times", max_events=120)
|
|
80
|
+
|
|
81
|
+
tool_calls = [e for e in events if isinstance(e, ToolCallEvent)]
|
|
82
|
+
cb_fires = [e for e in events if isinstance(e, ToolResultEvent)
|
|
83
|
+
and e.error and "CIRCUIT" in str(e.error)]
|
|
84
|
+
|
|
85
|
+
# Circuit breaker should fire
|
|
86
|
+
if not cb_fires:
|
|
87
|
+
pytest.skip("Model didn't repeat — can't test circuit breaker")
|
|
88
|
+
|
|
89
|
+
# After first circuit breaker fire, model should stop within 3 more calls
|
|
90
|
+
first_cb_idx = next(i for i, e in enumerate(events) if isinstance(e, ToolResultEvent) and e.error and "CIRCUIT" in str(e.error))
|
|
91
|
+
calls_after_cb = [e for e in events[first_cb_idx:] if isinstance(e, ToolCallEvent)]
|
|
92
|
+
|
|
93
|
+
assert len(calls_after_cb) <= 3, \
|
|
94
|
+
f"Model made {len(calls_after_cb)} tool calls AFTER circuit breaker fired. " \
|
|
95
|
+
f"It should stop, not keep going. Total: {len(tool_calls)} calls, {len(cb_fires)} breaker fires."
|
|
@@ -0,0 +1,252 @@
|
|
|
1
|
+
"""Real backend tests for user-reported issues.
|
|
2
|
+
|
|
3
|
+
Every test hits the ACTUAL vLLM backend at localhost:8000.
|
|
4
|
+
NO mocks, NO fakes — real DryDock execution.
|
|
5
|
+
|
|
6
|
+
Skip if vLLM is not running.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from __future__ import annotations
|
|
10
|
+
|
|
11
|
+
import asyncio
|
|
12
|
+
import os
|
|
13
|
+
from pathlib import Path
|
|
14
|
+
|
|
15
|
+
import httpx
|
|
16
|
+
import pytest
|
|
17
|
+
|
|
18
|
+
from drydock.core.agent_loop import AgentLoop
|
|
19
|
+
from drydock.core.agents.models import BuiltinAgentName
|
|
20
|
+
from drydock.core.config import Backend, ModelConfig, ProviderConfig, VibeConfig
|
|
21
|
+
from drydock.core.types import (
|
|
22
|
+
AssistantEvent,
|
|
23
|
+
BaseEvent,
|
|
24
|
+
Role,
|
|
25
|
+
ToolCallEvent,
|
|
26
|
+
ToolResultEvent,
|
|
27
|
+
)
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def _vllm_available() -> bool:
|
|
31
|
+
try:
|
|
32
|
+
return httpx.get("http://localhost:8000/v1/models", timeout=3).status_code == 200
|
|
33
|
+
except Exception:
|
|
34
|
+
return False
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
pytestmark = pytest.mark.skipif(not _vllm_available(), reason="vLLM not running")
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def _config(tmp_path: Path) -> VibeConfig:
|
|
41
|
+
return VibeConfig(
|
|
42
|
+
active_model="devstral",
|
|
43
|
+
auto_approve=True,
|
|
44
|
+
enable_telemetry=False,
|
|
45
|
+
include_project_context=False,
|
|
46
|
+
system_prompt_id="cli",
|
|
47
|
+
providers=[ProviderConfig(
|
|
48
|
+
name="local", api_base="http://localhost:8000/v1",
|
|
49
|
+
api_key_env_var="", backend=Backend.GENERIC,
|
|
50
|
+
)],
|
|
51
|
+
models=[ModelConfig(
|
|
52
|
+
name="devstral", provider="local", alias="devstral",
|
|
53
|
+
input_price=0.0, output_price=0.0,
|
|
54
|
+
)],
|
|
55
|
+
session_logging={"enabled": False, "save_dir": str(tmp_path / "logs")},
|
|
56
|
+
)
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
def _agent(tmp_path: Path, max_turns: int = 5) -> AgentLoop:
|
|
60
|
+
return AgentLoop(
|
|
61
|
+
config=_config(tmp_path),
|
|
62
|
+
agent_name=BuiltinAgentName.AUTO_APPROVE,
|
|
63
|
+
max_turns=max_turns,
|
|
64
|
+
)
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
async def _run(agent: AgentLoop, prompt: str, max_events: int = 100) -> list[BaseEvent]:
|
|
68
|
+
events = []
|
|
69
|
+
async for ev in agent.act(prompt):
|
|
70
|
+
events.append(ev)
|
|
71
|
+
if len(events) >= max_events:
|
|
72
|
+
break
|
|
73
|
+
return events
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
# ============================================================================
|
|
77
|
+
# Test 1: "Understood" after error — agent should NOT stop with "Understood."
|
|
78
|
+
# ============================================================================
|
|
79
|
+
|
|
80
|
+
@pytest.mark.asyncio
|
|
81
|
+
async def test_no_understood_stops_agent(tmp_path):
|
|
82
|
+
"""Agent should never inject 'Understood.' into conversation."""
|
|
83
|
+
agent = _agent(tmp_path)
|
|
84
|
+
events = await _run(agent, "Read the file /nonexistent/path/fake.py")
|
|
85
|
+
|
|
86
|
+
# Check messages — none should contain "Understood."
|
|
87
|
+
for msg in agent.messages:
|
|
88
|
+
if msg.role == Role.assistant and msg.content:
|
|
89
|
+
assert "Understood." not in msg.content, \
|
|
90
|
+
f"Found 'Understood.' in assistant message — causes premature stops"
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
# ============================================================================
|
|
94
|
+
# Test 2: Circuit breaker actually blocks (not just warns)
|
|
95
|
+
# ============================================================================
|
|
96
|
+
|
|
97
|
+
@pytest.mark.asyncio
|
|
98
|
+
async def test_circuit_breaker_blocks_real(tmp_path):
|
|
99
|
+
"""After 2 identical tool calls, the 3rd should be blocked with error."""
|
|
100
|
+
agent = _agent(tmp_path, max_turns=10)
|
|
101
|
+
# Ask something that will likely trigger repeated tool calls
|
|
102
|
+
events = await _run(agent, "Run 'echo hello' five times in a row, each as a separate bash command")
|
|
103
|
+
|
|
104
|
+
tool_results = [e for e in events if isinstance(e, ToolResultEvent)]
|
|
105
|
+
# Should have some blocked results if circuit breaker works
|
|
106
|
+
errors = [e for e in tool_results if e.error and "CIRCUIT BREAKER" in str(e.error)]
|
|
107
|
+
|
|
108
|
+
# The model might not repeat exactly, but circuit breaker state should exist
|
|
109
|
+
assert hasattr(agent, "_tool_call_history")
|
|
110
|
+
assert isinstance(agent._tool_call_history, dict)
|
|
111
|
+
# At least verify no AttributeError crash
|
|
112
|
+
for e in tool_results:
|
|
113
|
+
if e.error:
|
|
114
|
+
assert "AttributeError" not in str(e.error), f"Crash: {e.error}"
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
# ============================================================================
|
|
118
|
+
# Test 3: Tool calls don't crash with AttributeError
|
|
119
|
+
# ============================================================================
|
|
120
|
+
|
|
121
|
+
@pytest.mark.asyncio
|
|
122
|
+
async def test_no_attribute_error_on_tools(tmp_path):
|
|
123
|
+
"""No AttributeError should occur during tool execution."""
|
|
124
|
+
agent = _agent(tmp_path)
|
|
125
|
+
events = await _run(agent, "List the files in the current directory")
|
|
126
|
+
|
|
127
|
+
for e in events:
|
|
128
|
+
if isinstance(e, ToolResultEvent) and e.error:
|
|
129
|
+
assert "AttributeError" not in str(e.error), \
|
|
130
|
+
f"AttributeError in tool result: {e.error}"
|
|
131
|
+
assert "raw_arguments" not in str(e.error), \
|
|
132
|
+
f"Old raw_arguments bug: {e.error}"
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
# ============================================================================
|
|
136
|
+
# Test 4: Agent doesn't loop on ambiguous prompt
|
|
137
|
+
# ============================================================================
|
|
138
|
+
|
|
139
|
+
@pytest.mark.asyncio
|
|
140
|
+
async def test_ambiguous_prompt_limited(tmp_path):
|
|
141
|
+
"""Typing 'test' should not cause 20+ tool calls."""
|
|
142
|
+
agent = _agent(tmp_path, max_turns=8)
|
|
143
|
+
events = await _run(agent, "test", max_events=60)
|
|
144
|
+
|
|
145
|
+
tool_calls = [e for e in events if isinstance(e, ToolCallEvent)]
|
|
146
|
+
assert len(tool_calls) < 25, \
|
|
147
|
+
f"Ambiguous prompt 'test' caused {len(tool_calls)} tool calls — too many"
|
|
148
|
+
|
|
149
|
+
|
|
150
|
+
# ============================================================================
|
|
151
|
+
# Test 5: Message ordering clean after real tool calls
|
|
152
|
+
# ============================================================================
|
|
153
|
+
|
|
154
|
+
@pytest.mark.asyncio
|
|
155
|
+
async def test_no_user_after_tool(tmp_path):
|
|
156
|
+
"""No user message should follow a tool message in the history."""
|
|
157
|
+
agent = _agent(tmp_path)
|
|
158
|
+
events = await _run(agent, "What Python version is installed? Run python3 --version")
|
|
159
|
+
|
|
160
|
+
for i in range(1, len(agent.messages)):
|
|
161
|
+
if agent.messages[i].role == Role.user and agent.messages[i-1].role == Role.tool:
|
|
162
|
+
pytest.fail(f"user after tool at position {i}: "
|
|
163
|
+
f"'{agent.messages[i].content[:50]}' after tool '{agent.messages[i-1].content[:50]}'")
|
|
164
|
+
|
|
165
|
+
|
|
166
|
+
# ============================================================================
|
|
167
|
+
# Test 6: Agent actually uses tools (not just text responses)
|
|
168
|
+
# ============================================================================
|
|
169
|
+
|
|
170
|
+
@pytest.mark.asyncio
|
|
171
|
+
async def test_agent_uses_tools(tmp_path):
|
|
172
|
+
"""Agent should call bash/grep/read_file when asked to do something concrete."""
|
|
173
|
+
agent = _agent(tmp_path)
|
|
174
|
+
events = await _run(agent, "Run: echo 'drydock integration test'")
|
|
175
|
+
|
|
176
|
+
tool_calls = [e for e in events if isinstance(e, ToolCallEvent)]
|
|
177
|
+
# Should have at least one tool call for a concrete command request
|
|
178
|
+
assert len(tool_calls) >= 1, \
|
|
179
|
+
"Agent gave text-only response when asked to run a command"
|
|
180
|
+
|
|
181
|
+
|
|
182
|
+
# ============================================================================
|
|
183
|
+
# Test 7: DryDock branding in system prompt (real check)
|
|
184
|
+
# ============================================================================
|
|
185
|
+
|
|
186
|
+
@pytest.mark.asyncio
|
|
187
|
+
async def test_system_prompt_branding(tmp_path):
|
|
188
|
+
"""System prompt should say 'DryDock' not 'Drydock' or 'Vibe'."""
|
|
189
|
+
agent = _agent(tmp_path)
|
|
190
|
+
# Don't even need to run — just check the system prompt
|
|
191
|
+
system_msg = agent.messages[0]
|
|
192
|
+
assert system_msg.role == Role.system
|
|
193
|
+
assert "DryDock" in system_msg.content, "System prompt missing 'DryDock'"
|
|
194
|
+
assert "Vibe" not in system_msg.content or "mistral-vibe" in system_msg.content, \
|
|
195
|
+
"System prompt still references 'Vibe'"
|
|
196
|
+
|
|
197
|
+
|
|
198
|
+
# ============================================================================
|
|
199
|
+
# Test 8: Write file doesn't hang (has timeout)
|
|
200
|
+
# ============================================================================
|
|
201
|
+
|
|
202
|
+
@pytest.mark.asyncio
|
|
203
|
+
async def test_write_file_timeout_exists(tmp_path):
|
|
204
|
+
"""write_file should complete within reasonable time, not hang."""
|
|
205
|
+
agent = _agent(tmp_path)
|
|
206
|
+
test_file = tmp_path / "test_write.txt"
|
|
207
|
+
|
|
208
|
+
events = await _run(agent,
|
|
209
|
+
f"Write the text 'hello world' to the file {test_file}")
|
|
210
|
+
|
|
211
|
+
# Should complete (not hang) — if it hangs, the test runner will timeout
|
|
212
|
+
assert len(events) >= 1
|
|
213
|
+
# Check if file was created (model might or might not do it)
|
|
214
|
+
# The important thing is it didn't hang
|
|
215
|
+
|
|
216
|
+
|
|
217
|
+
# ============================================================================
|
|
218
|
+
# Test 9: Agent stops cleanly (not infinite loop)
|
|
219
|
+
# ============================================================================
|
|
220
|
+
|
|
221
|
+
@pytest.mark.asyncio
|
|
222
|
+
async def test_agent_stops_cleanly(tmp_path):
|
|
223
|
+
"""Agent should stop after completing a task, not loop forever."""
|
|
224
|
+
agent = _agent(tmp_path, max_turns=5)
|
|
225
|
+
events = await _run(agent, "What is 2+2? Just say the number.", max_events=30)
|
|
226
|
+
|
|
227
|
+
# Should stop within reasonable events
|
|
228
|
+
assert len(events) < 30, f"Agent produced {len(events)} events — possible loop"
|
|
229
|
+
|
|
230
|
+
|
|
231
|
+
# ============================================================================
|
|
232
|
+
# Test 10: Consultant config field exists and works
|
|
233
|
+
# ============================================================================
|
|
234
|
+
|
|
235
|
+
@pytest.mark.asyncio
|
|
236
|
+
async def test_consultant_config_real(tmp_path):
|
|
237
|
+
"""VibeConfig should accept consultant_model field without error."""
|
|
238
|
+
config = VibeConfig(
|
|
239
|
+
active_model="devstral",
|
|
240
|
+
consultant_model="gemini-2.5-pro",
|
|
241
|
+
auto_approve=True,
|
|
242
|
+
enable_telemetry=False,
|
|
243
|
+
providers=[ProviderConfig(
|
|
244
|
+
name="local", api_base="http://localhost:8000/v1",
|
|
245
|
+
api_key_env_var="", backend=Backend.GENERIC,
|
|
246
|
+
)],
|
|
247
|
+
models=[ModelConfig(
|
|
248
|
+
name="devstral", provider="local",
|
|
249
|
+
input_price=0.0, output_price=0.0,
|
|
250
|
+
)],
|
|
251
|
+
)
|
|
252
|
+
assert config.consultant_model == "gemini-2.5-pro"
|
|
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
|