drydock-cli 2.6.81__tar.gz → 2.6.83__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-2.6.83/.auto_release.lock +1 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/PKG-INFO +1 -1
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/cli/entrypoint.py +17 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/cli/textual_ui/handlers/event_handler.py +10 -1
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/core/agent_loop.py +7 -0
- drydock_cli-2.6.83/drydock/core/config/doctor.py +222 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/core/llm/format.py +36 -9
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/core/tools/base.py +5 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/core/tools/builtins/bash.py +71 -23
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/core/tools/builtins/read_file.py +45 -52
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/core/tools/builtins/search_replace.py +61 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/core/tools/builtins/write_file.py +136 -86
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/pyproject.toml +1 -1
- drydock_cli-2.6.81/.auto_release.lock +0 -1
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/.claude/scheduled_tasks.lock +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/.github/CODEOWNERS +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/.github/DISCUSSION_TEMPLATE/ideas.yml +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/.github/ISSUE_TEMPLATE/bug-report.yml +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/.github/ISSUE_TEMPLATE/config.yml +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/.github/workflows/build-and-upload.yml +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/.github/workflows/ci.yml +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/.github/workflows/issue-labeler.yml +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/.github/workflows/release.yml +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/.gitignore +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/.pre-commit-config.yaml +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/.python-version +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/.typos.toml +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/.vscode/extensions.json +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/.vscode/launch.json +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/.vscode/settings.json +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/AGENTS.md +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/BASELINE_412.md +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/CHANGELOG.md +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/CLAUDE.md +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/CONTRIBUTING.md +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/Drydock_rebrand.md +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/LICENSE +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/MODEL_SHORTCOMINGS.md +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/NOTICE +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/OVERNIGHT_REPORT_2026_04_13.md +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/PRD.md +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/README.md +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/action.yml +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/baseline_history/README.md +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/baseline_history/results1.tsv +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/baseline_history/results13.tsv +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/baseline_history/results14.tsv +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/baseline_history/results15.tsv +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/baseline_history/results16.tsv +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/baseline_history/results17.tsv +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/baseline_history/results18.tsv +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/baseline_history/results19.tsv +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/baseline_history/results2.tsv +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/baseline_history/results20.tsv +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/baseline_history/results3.tsv +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/baseline_history/results4.tsv +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/baseline_history/results5.tsv +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/baseline_history/results6.tsv +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/baseline_history/results7.tsv +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/baseline_history/results8.tsv +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/baseline_history/results9.tsv +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/baseline_history/results_evolved_v1.tsv +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/distribution/zed/LICENSE +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/distribution/zed/extension.toml +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/distribution/zed/icons/mistral_vibe.svg +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/docs/README.md +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/docs/acp-setup.md +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/docs/proxy-setup.md +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/__init__.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/acp/__init__.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/acp/acp_agent_loop.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/acp/acp_logger.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/acp/entrypoint.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/acp/tools/__init__.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/acp/tools/base.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/acp/tools/builtins/bash.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/acp/tools/builtins/read_file.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/acp/tools/builtins/search_replace.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/acp/tools/builtins/todo.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/acp/tools/builtins/write_file.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/acp/tools/session_update.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/acp/utils.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/cli/__init__.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/cli/autocompletion/__init__.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/cli/autocompletion/base.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/cli/autocompletion/path_completion.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/cli/autocompletion/slash_command.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/cli/cli.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/cli/clipboard.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/cli/commands.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/cli/history_manager.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/cli/plan_offer/adapters/http_whoami_gateway.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/cli/plan_offer/decide_plan_offer.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/cli/plan_offer/ports/whoami_gateway.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/cli/terminal_setup.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/cli/textual_ui/__init__.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/cli/textual_ui/ansi_markdown.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/cli/textual_ui/app.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/cli/textual_ui/app.tcss +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/cli/textual_ui/external_editor.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/cli/textual_ui/handlers/__init__.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/cli/textual_ui/notifications/__init__.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/cli/textual_ui/notifications/adapters/__init__.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/cli/textual_ui/notifications/adapters/textual_notification_adapter.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/cli/textual_ui/notifications/ports/__init__.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/cli/textual_ui/notifications/ports/notification_port.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/cli/textual_ui/widgets/__init__.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/cli/textual_ui/widgets/approval_app.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/cli/textual_ui/widgets/banner/banner.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/cli/textual_ui/widgets/banner/petit_chat.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/cli/textual_ui/widgets/braille_renderer.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/cli/textual_ui/widgets/chat_input/__init__.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/cli/textual_ui/widgets/chat_input/body.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/cli/textual_ui/widgets/chat_input/completion_manager.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/cli/textual_ui/widgets/chat_input/completion_popup.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/cli/textual_ui/widgets/chat_input/container.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/cli/textual_ui/widgets/chat_input/text_area.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/cli/textual_ui/widgets/compact.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/cli/textual_ui/widgets/config_app.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/cli/textual_ui/widgets/context_progress.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/cli/textual_ui/widgets/load_more.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/cli/textual_ui/widgets/loading.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/cli/textual_ui/widgets/messages.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/cli/textual_ui/widgets/no_markup_static.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/cli/textual_ui/widgets/path_display.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/cli/textual_ui/widgets/proxy_setup_app.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/cli/textual_ui/widgets/question_app.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/cli/textual_ui/widgets/session_picker.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/cli/textual_ui/widgets/spinner.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/cli/textual_ui/widgets/status_message.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/cli/textual_ui/widgets/teleport_message.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/cli/textual_ui/widgets/tool_widgets.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/cli/textual_ui/widgets/tools.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/cli/textual_ui/widgets/vscode_compat.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/cli/textual_ui/windowing/__init__.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/cli/textual_ui/windowing/history.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/cli/textual_ui/windowing/history_windowing.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/cli/textual_ui/windowing/state.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/cli/update_notifier/__init__.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/cli/update_notifier/adapters/filesystem_update_cache_repository.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/cli/update_notifier/adapters/github_update_gateway.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/cli/update_notifier/adapters/pypi_update_gateway.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/cli/update_notifier/ports/update_cache_repository.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/cli/update_notifier/ports/update_gateway.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/cli/update_notifier/update.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/cli/update_notifier/whats_new.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/core/__init__.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/core/agents/__init__.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/core/agents/manager.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/core/agents/models.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/core/auth/__init__.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/core/auth/crypto.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/core/auth/github.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/core/autocompletion/__init__.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/core/autocompletion/completers.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/core/autocompletion/file_indexer/__init__.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/core/autocompletion/file_indexer/ignore_rules.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/core/autocompletion/file_indexer/indexer.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/core/autocompletion/file_indexer/store.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/core/autocompletion/file_indexer/watcher.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/core/autocompletion/fuzzy.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/core/autocompletion/path_prompt.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/core/autocompletion/path_prompt_adapter.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/core/build_orchestrator.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/core/config/__init__.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/core/config/_settings.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/core/config/harness_files/__init__.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/core/config/harness_files/_harness_manager.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/core/config/harness_files/_paths.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/core/consultant.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/core/drydock_states.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/core/hooks.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/core/llm/__init__.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/core/llm/backend/anthropic.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/core/llm/backend/base.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/core/llm/backend/factory.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/core/llm/backend/generic.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/core/llm/backend/mistral.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/core/llm/backend/reasoning_adapter.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/core/llm/backend/vertex.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/core/llm/exceptions.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/core/llm/message_utils.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/core/llm/types.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/core/logger.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/core/middleware.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/core/output_formatters.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/core/paths/__init__.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/core/paths/_local_config_walk.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/core/paths/_vibe_home.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/core/paths/conventions.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/core/plan_session.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/core/plugins.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/core/programmatic.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/core/prompts/__init__.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/core/prompts/builder.md +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/core/prompts/cli.md +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/core/prompts/compact.md +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/core/prompts/dangerous_directory.md +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/core/prompts/diagnostic.md +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/core/prompts/explore.md +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/core/prompts/gemma4.md +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/core/prompts/planner.md +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/core/prompts/project_context.md +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/core/prompts/tests.md +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/core/proxy_setup.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/core/session/agent_memory.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/core/session/checkpoints.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/core/session/session_loader.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/core/session/session_logger.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/core/session/session_migration.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/core/session/state_file.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/core/session_checker.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/core/skills/__init__.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/core/skills/manager.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/core/skills/models.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/core/skills/parser.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/core/slug.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/core/system_prompt.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/core/telemetry/__init__.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/core/telemetry/send.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/core/teleport/errors.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/core/teleport/git.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/core/teleport/nuage.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/core/teleport/teleport.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/core/teleport/types.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/core/tools/builtins/_task_manager.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/core/tools/builtins/ask_user_question.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/core/tools/builtins/cron.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/core/tools/builtins/exit_plan_mode.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/core/tools/builtins/glob_tool.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/core/tools/builtins/grep.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/core/tools/builtins/invoke_skill.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/core/tools/builtins/lsp.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/core/tools/builtins/mcp_resources.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/core/tools/builtins/notebook_edit.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/core/tools/builtins/powershell.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/core/tools/builtins/prompts/__init__.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/core/tools/builtins/prompts/ask_user_question.md +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/core/tools/builtins/prompts/bash.md +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/core/tools/builtins/prompts/cron.md +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/core/tools/builtins/prompts/glob.md +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/core/tools/builtins/prompts/grep.md +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/core/tools/builtins/prompts/invoke_skill.md +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/core/tools/builtins/prompts/lsp.md +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/core/tools/builtins/prompts/mcp_resources.md +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/core/tools/builtins/prompts/notebook_edit.md +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/core/tools/builtins/prompts/powershell.md +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/core/tools/builtins/prompts/read_file.md +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/core/tools/builtins/prompts/search_replace.md +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/core/tools/builtins/prompts/swe_bench.md +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/core/tools/builtins/prompts/task.md +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/core/tools/builtins/prompts/task_manager.md +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/core/tools/builtins/prompts/todo.md +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/core/tools/builtins/prompts/tool_search.md +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/core/tools/builtins/prompts/webfetch.md +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/core/tools/builtins/prompts/websearch.md +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/core/tools/builtins/prompts/worktree.md +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/core/tools/builtins/prompts/write_file.md +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/core/tools/builtins/task.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/core/tools/builtins/todo.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/core/tools/builtins/tool_search.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/core/tools/builtins/webfetch.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/core/tools/builtins/websearch.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/core/tools/builtins/worktree.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/core/tools/injection_guard.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/core/tools/manager.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/core/tools/mcp/__init__.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/core/tools/mcp/registry.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/core/tools/mcp/tools.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/core/tools/mcp_sampling.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/core/tools/ui.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/core/tools/utils.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/core/trusted_folders.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/core/types.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/core/utils.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/setup/onboarding/__init__.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/setup/onboarding/base.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/setup/onboarding/onboarding.tcss +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/setup/onboarding/screens/__init__.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/setup/onboarding/screens/api_key.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/setup/onboarding/screens/welcome.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/setup/trusted_folders/trust_folder_dialog.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/setup/trusted_folders/trust_folder_dialog.tcss +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/skills/__init__.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/skills/api-design/SKILL.md +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/skills/audit-tests/SKILL.md +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/skills/batch/SKILL.md +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/skills/commit-code/SKILL.md +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/skills/context-summary/SKILL.md +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/skills/create-presentation/SKILL.md +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/skills/deep-research/SKILL.md +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/skills/deploy/SKILL.md +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/skills/diff-review/SKILL.md +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/skills/doc-gen/SKILL.md +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/skills/explain-code/SKILL.md +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/skills/explore-code/SKILL.md +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/skills/fix-issue/SKILL.md +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/skills/git-ops/SKILL.md +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/skills/init-project/SKILL.md +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/skills/investigate/SKILL.md +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/skills/loop/SKILL.md +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/skills/migrate/SKILL.md +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/skills/perf-analyze/SKILL.md +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/skills/plan-impl/SKILL.md +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/skills/pr-review/SKILL.md +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/skills/refactor/SKILL.md +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/skills/regex-help/SKILL.md +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/skills/review/SKILL.md +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/skills/security-review/SKILL.md +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/skills/ship/SKILL.md +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/skills/simplify/SKILL.md +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/skills/strong-tests/SKILL.md +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/skills/test-verify/SKILL.md +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock/whats_new.md +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock-acp.spec +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/drydock_terms.md +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/flake.lock +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/flake.nix +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/scripts/README.md +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/scripts/audit_sampler.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/scripts/auto_generate_tests.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/scripts/auto_release.sh +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/scripts/auto_test_loop.sh +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/scripts/backup.sh +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/scripts/bump_version.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/scripts/comprehensive_loop.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/scripts/deploy_to_github.sh +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/scripts/discover_cli_tools.sh +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/scripts/evolve_tests.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/scripts/install.sh +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/scripts/llm_balancer.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/scripts/mega_loop.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/scripts/meta_ralph_loop.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/scripts/monitor_swebench.sh +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/scripts/monitor_test_battery.sh +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/scripts/notify_release.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/scripts/oss_task_harness.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/scripts/overnight_agents_test.sh +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/scripts/port_task.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/scripts/prepare_release.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/scripts/publish_to_pypi.sh +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/scripts/ralph_loop.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/scripts/session_loop_audit.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/scripts/shakedown.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/scripts/shakedown_interactive.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/scripts/shakedown_regression.sh +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/scripts/shakedown_suite.sh +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/scripts/shakedown_variance.sh +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/scripts/telegram_bot.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/scripts/test_bank.sh +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/scripts/test_full.sh +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/scripts/test_smoke.sh +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/scripts/test_tui_path.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/scripts/tui_test.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/scripts/vllm_failover.sh +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/__init__.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/acp/conftest.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/acp/test_acp.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/acp/test_agent_thought.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/acp/test_bash.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/acp/test_compact_session_updates.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/acp/test_content.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/acp/test_initialize.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/acp/test_list_sessions.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/acp/test_load_session.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/acp/test_multi_session.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/acp/test_new_session.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/acp/test_proxy_setup_acp.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/acp/test_read_file.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/acp/test_search_replace.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/acp/test_set_config_option.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/acp/test_set_mode.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/acp/test_set_model.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/acp/test_tool_call_session_update.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/acp/test_utils.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/acp/test_write_file.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/autocompletion/test_file_indexer.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/autocompletion/test_fuzzy.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/autocompletion/test_path_completer_fuzzy.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/autocompletion/test_path_completer_recursive.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/autocompletion/test_path_completion_controller.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/autocompletion/test_path_prompt_transformer.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/autocompletion/test_slash_command_controller.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/autocompletion/test_ui_chat_autocompletion.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/backend/__init__.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/backend/data/__init__.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/backend/data/fireworks.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/backend/data/mistral.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/backend/test_anthropic_adapter.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/backend/test_backend.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/backend/test_reasoning_adapter.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/backend/test_vertex_anthropic_adapter.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/cli/plan_offer/adapters/fake_whoami_gateway.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/cli/plan_offer/test_decide_plan_offer.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/cli/plan_offer/test_http_whoami_gateway.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/cli/test_bell_notifications.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/cli/test_braille_renderer.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/cli/test_clipboard.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/cli/test_commands.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/cli/test_copy_shortcuts.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/cli/test_external_editor.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/cli/test_no_markup_static.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/cli/test_question_app.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/cli/test_spinner.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/cli/test_switching_mode.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/cli/test_ui_clipboard_notifications.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/cli/test_ui_session_incremental_renderer.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/cli/test_ui_session_resume.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/cli/test_ui_skill_dispatch.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/cli/textual_ui/__init__.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/cli/textual_ui/test_session_picker.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/conftest.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/core/test_agents.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/core/test_auth_crypto.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/core/test_auth_github.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/core/test_config_load_dotenv.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/core/test_config_paths.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/core/test_config_resolution.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/core/test_file_logging.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/core/test_plan_session.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/core/test_proxy_setup.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/core/test_slug.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/core/test_telemetry_send.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/core/test_teleport_git.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/core/test_teleport_nuage.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/core/test_teleport_service.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/core/test_trusted_folders.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/core/test_utils.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/e2e/common.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/e2e/conftest.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/e2e/mock_server.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/e2e/test_cli_tui_onboarding.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/e2e/test_cli_tui_streaming.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/e2e/test_cli_tui_tool_approval.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/fixtures/doc_qa_system_prd.md +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/mock/__init__.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/mock/mock_backend_factory.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/mock/mock_entrypoint.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/mock/utils.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/onboarding/test_run_onboarding.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/onboarding/test_ui_onboarding.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/session/test_session_loader.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/session/test_session_logger.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/session/test_session_migration.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/skills/conftest.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/skills/test_manager.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/skills/test_models.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/skills/test_parser.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/snapshots/__snapshots__/test_ui_snapshot_ask_user_question/test_snapshot_ask_user_question_collapsed.svg +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/snapshots/__snapshots__/test_ui_snapshot_ask_user_question/test_snapshot_ask_user_question_expanded.svg +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/snapshots/__snapshots__/test_ui_snapshot_basic_conversation/test_snapshot_shows_basic_conversation.svg +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/snapshots/__snapshots__/test_ui_snapshot_code_block_horizontal_scrolling/test_snapshot_allows_horizontal_scrolling_for_long_code_blocks.svg +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/snapshots/__snapshots__/test_ui_snapshot_empty_assistant_before_reasoning/test_snapshot_empty_assistant_removed_when_reasoning_starts.svg +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/snapshots/__snapshots__/test_ui_snapshot_modes/test_snapshot_cycle_to_accept_edits_mode.svg +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/snapshots/__snapshots__/test_ui_snapshot_modes/test_snapshot_cycle_to_auto_approve_mode.svg +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/snapshots/__snapshots__/test_ui_snapshot_modes/test_snapshot_cycle_to_plan_mode.svg +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/snapshots/__snapshots__/test_ui_snapshot_modes/test_snapshot_cycle_wraps_to_default.svg +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/snapshots/__snapshots__/test_ui_snapshot_modes/test_snapshot_default_mode.svg +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/snapshots/__snapshots__/test_ui_snapshot_parallel_tool_calls/test_snapshot_parallel_tool_calls_pending.svg +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/snapshots/__snapshots__/test_ui_snapshot_parallel_tool_calls/test_snapshot_parallel_tool_calls_resolved.svg +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/snapshots/__snapshots__/test_ui_snapshot_proxy_setup/test_snapshot_proxy_setup_cancel_discards_changes.svg +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/snapshots/__snapshots__/test_ui_snapshot_proxy_setup/test_snapshot_proxy_setup_edit_existing_values.svg +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/snapshots/__snapshots__/test_ui_snapshot_proxy_setup/test_snapshot_proxy_setup_initial_empty.svg +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/snapshots/__snapshots__/test_ui_snapshot_proxy_setup/test_snapshot_proxy_setup_initial_with_values.svg +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/snapshots/__snapshots__/test_ui_snapshot_proxy_setup/test_snapshot_proxy_setup_save_error.svg +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/snapshots/__snapshots__/test_ui_snapshot_proxy_setup/test_snapshot_proxy_setup_save_new_values.svg +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_question_answer_first_advance.svg +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_question_first_answered_checkmark.svg +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_question_initial.svg +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_question_navigate_left_wraps.svg +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_question_navigate_right.svg +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_question_tab_to_second.svg +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_select_initial.svg +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_select_mixed_selection.svg +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_select_navigate_to_submit.svg +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_select_other_with_text.svg +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_select_toggle_first.svg +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_select_toggle_multiple.svg +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_select_untoggle.svg +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_question_app_initial.svg +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_question_app_navigate_down.svg +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_question_app_navigate_to_other.svg +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_question_app_navigate_to_third_option.svg +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_question_app_navigate_up_wraps.svg +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_question_app_other_typing.svg +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/snapshots/__snapshots__/test_ui_snapshot_reasoning_content/test_snapshot_buffered_reasoning_yields_before_content.svg +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/snapshots/__snapshots__/test_ui_snapshot_reasoning_content/test_snapshot_shows_interleaved_reasoning.svg +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/snapshots/__snapshots__/test_ui_snapshot_reasoning_content/test_snapshot_shows_reasoning_content.svg +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/snapshots/__snapshots__/test_ui_snapshot_reasoning_content/test_snapshot_shows_reasoning_content_expanded.svg +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/snapshots/__snapshots__/test_ui_snapshot_release_update_notification/test_snapshot_shows_release_update_notification.svg +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/snapshots/__snapshots__/test_ui_snapshot_session_resume/test_snapshot_shows_resumed_session_messages.svg +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/snapshots/__snapshots__/test_ui_snapshot_streaming_tool_call/test_snapshot_tool_call_partial.svg +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/snapshots/__snapshots__/test_ui_snapshot_streaming_tool_call/test_snapshot_tool_call_updated.svg +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_push_confirmation_cancel_selected.svg +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_push_confirmation_multiple_commits.svg +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_push_confirmation_single_commit.svg +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_status_auth_complete.svg +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_status_auth_required.svg +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_status_checking_git.svg +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_status_complete.svg +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_status_error.svg +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_status_pushing.svg +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_status_sending_token.svg +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_status_starting_workflow.svg +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/snapshots/__snapshots__/test_ui_snapshot_whats_new/test_snapshot_shows_no_plan_message.svg +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/snapshots/__snapshots__/test_ui_snapshot_whats_new/test_snapshot_shows_switch_message.svg +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/snapshots/__snapshots__/test_ui_snapshot_whats_new/test_snapshot_shows_upgrade_message.svg +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/snapshots/__snapshots__/test_ui_snapshot_whats_new/test_snapshot_shows_whats_new_message.svg +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/snapshots/base_snapshot_test_app.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/snapshots/conftest.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/snapshots/snap_compare.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/snapshots/test_ui_snapshot_ask_user_question.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/snapshots/test_ui_snapshot_basic_conversation.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/snapshots/test_ui_snapshot_code_block_horizontal_scrolling.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/snapshots/test_ui_snapshot_empty_assistant_before_reasoning.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/snapshots/test_ui_snapshot_modes.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/snapshots/test_ui_snapshot_parallel_tool_calls.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/snapshots/test_ui_snapshot_proxy_setup.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/snapshots/test_ui_snapshot_question_app.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/snapshots/test_ui_snapshot_reasoning_content.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/snapshots/test_ui_snapshot_release_update_notification.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/snapshots/test_ui_snapshot_session_resume.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/snapshots/test_ui_snapshot_streaming_tool_call.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/snapshots/test_ui_snapshot_teleport.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/snapshots/test_ui_snapshot_whats_new.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/stubs/fake_backend.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/stubs/fake_client.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/stubs/fake_tool.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/test_agent_auto_compact.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/test_agent_backend.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/test_agent_observer_streaming.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/test_agent_stats.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/test_agent_tasks.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/test_agent_tool_call.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/test_agents.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/test_bank_build.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/test_bank_debug.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/test_bank_multiagent.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/test_bank_prd.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/test_bank_prd_extended.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/test_bank_tools.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/test_bank_update.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/test_build_projects.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/test_cli_programmatic_preload.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/test_current_bugs.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/test_drydock_regression.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/test_drydock_tasks.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/test_full_regression.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/test_history_manager.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/test_integration.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/test_loop_detection.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/test_message_id.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/test_message_merging.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/test_middleware.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/test_multi_agent.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/test_real_failures.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/test_real_issues.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/test_real_workflow.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/test_reasoning_content.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/test_smoke.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/test_system_prompt.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/test_tagged_text.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/test_tool_args.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/test_ui_external_editor.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/test_ui_input_history.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/test_user_issues.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/test_workloads.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/testbank_helpers.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/tools/test_ask_user_question.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/tools/test_bash.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/tools/test_exit_plan_mode.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/tools/test_grep.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/tools/test_invoke_context.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/tools/test_manager_get_tool_config.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/tools/test_mcp.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/tools/test_mcp_sampling.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/tools/test_task.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/tools/test_ui_bash_execution.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/tools/test_webfetch.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/tools/test_websearch.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/update_notifier/adapters/fake_update_cache_repository.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/update_notifier/adapters/fake_update_gateway.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/update_notifier/test_do_update.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/update_notifier/test_filesystem_update_cache_repository.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/update_notifier/test_github_update_gateway.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/update_notifier/test_pypi_update_gateway.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/update_notifier/test_ui_update_notification.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/update_notifier/test_update_use_case.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/tests/update_notifier/test_whats_new.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/uv.lock +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/worked_examples/README.md +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/worked_examples/cli_subcommand_dispatch.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/worked_examples/lookup.json +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/worked_examples/sql_parser.py +0 -0
- {drydock_cli-2.6.81 → drydock_cli-2.6.83}/worked_examples/tree_walking_interpreter.py +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
1426724
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: drydock-cli
|
|
3
|
-
Version: 2.6.
|
|
3
|
+
Version: 2.6.83
|
|
4
4
|
Summary: Local-first CLI coding agent — tested with Gemma 4 26B via vLLM
|
|
5
5
|
Project-URL: Homepage, https://github.com/fbobe321/drydock
|
|
6
6
|
Project-URL: Repository, https://github.com/fbobe321/drydock
|
|
@@ -82,6 +82,17 @@ def parse_arguments() -> argparse.Namespace:
|
|
|
82
82
|
"or custom from ~/.drydock/agents/NAME.toml)",
|
|
83
83
|
)
|
|
84
84
|
parser.add_argument("--setup", action="store_true", help="Setup API key and exit")
|
|
85
|
+
parser.add_argument(
|
|
86
|
+
"--doctor",
|
|
87
|
+
action="store_true",
|
|
88
|
+
help="Check ~/.drydock/config.toml for drift vs. package defaults and exit",
|
|
89
|
+
)
|
|
90
|
+
parser.add_argument(
|
|
91
|
+
"--fix",
|
|
92
|
+
action="store_true",
|
|
93
|
+
help="With --doctor: rewrite ~/.drydock/config.toml to union missing "
|
|
94
|
+
"defaults (writes .bak backup first). No effect without --doctor.",
|
|
95
|
+
)
|
|
85
96
|
parser.add_argument(
|
|
86
97
|
"--workdir",
|
|
87
98
|
type=Path,
|
|
@@ -175,6 +186,12 @@ def check_and_resolve_trusted_folder() -> None:
|
|
|
175
186
|
def main() -> None:
|
|
176
187
|
args = parse_arguments()
|
|
177
188
|
|
|
189
|
+
if getattr(args, "doctor", False):
|
|
190
|
+
from drydock.core.config.harness_files import init_harness_files_manager
|
|
191
|
+
from drydock.core.config.doctor import run_doctor
|
|
192
|
+
init_harness_files_manager("user", "project")
|
|
193
|
+
sys.exit(run_doctor(apply=bool(getattr(args, "fix", False))))
|
|
194
|
+
|
|
178
195
|
if args.workdir:
|
|
179
196
|
workdir = args.workdir.expanduser().resolve()
|
|
180
197
|
if not workdir.is_dir():
|
|
@@ -84,7 +84,16 @@ class EventHandler:
|
|
|
84
84
|
)
|
|
85
85
|
await self._handle_assistant_message(event)
|
|
86
86
|
case ToolCallEvent():
|
|
87
|
-
|
|
87
|
+
# Finalize assistant content stream (user-visible text) but
|
|
88
|
+
# KEEP the reasoning widget open across tool calls. Closing
|
|
89
|
+
# it spawns a fresh "Thought" widget for every reasoning
|
|
90
|
+
# chunk between calls — a turn with N tool calls shows N
|
|
91
|
+
# "Thought" widgets stacked down the screen.
|
|
92
|
+
if self.current_streaming_message is not None:
|
|
93
|
+
await self.current_streaming_message.stop_stream()
|
|
94
|
+
if self.current_streaming_message.is_stripped_content_empty():
|
|
95
|
+
await self.current_streaming_message.remove()
|
|
96
|
+
self.current_streaming_message = None
|
|
88
97
|
return await self._handle_tool_call(event, loading_widget)
|
|
89
98
|
case ToolResultEvent():
|
|
90
99
|
await self.finalize_streaming()
|
|
@@ -195,6 +195,12 @@ class AgentLoop:
|
|
|
195
195
|
self._empty_responses: int = 0
|
|
196
196
|
self._successful_test_runs: int = 0
|
|
197
197
|
|
|
198
|
+
# Shared read-file state — used by write_file / search_replace to
|
|
199
|
+
# enforce Read-before-Write (per Claude Code's tool contract) and
|
|
200
|
+
# by read_file to dedup unchanged-mtime re-reads. Keyed by resolved
|
|
201
|
+
# absolute path; value is {"content", "timestamp", "offset", "limit"}.
|
|
202
|
+
self._read_file_state: dict[str, dict] = {}
|
|
203
|
+
|
|
198
204
|
system_prompt = get_universal_system_prompt(
|
|
199
205
|
self.tool_manager, self.config, self.skill_manager, self.agent_manager
|
|
200
206
|
)
|
|
@@ -970,6 +976,7 @@ class AgentLoop:
|
|
|
970
976
|
sampling_callback=self._sampling_handler,
|
|
971
977
|
plan_file_path=self._plan_session.plan_file_path,
|
|
972
978
|
switch_agent_callback=self.switch_agent,
|
|
979
|
+
read_file_state=self._read_file_state,
|
|
973
980
|
),
|
|
974
981
|
**tool_call.args_dict,
|
|
975
982
|
):
|
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
"""Config drift diagnostics (Option C — `drydock doctor`).
|
|
2
|
+
|
|
3
|
+
Reads the user's ~/.drydock/config.toml, compares each field against the
|
|
4
|
+
pydantic default, and reports drift. Designed to complement the auto-merge
|
|
5
|
+
behavior in Option A: even though list fields union with defaults at
|
|
6
|
+
load time, the user's config.toml FILE still shows the old values —
|
|
7
|
+
the merge is runtime-only. `drydock doctor --fix` rewrites the TOML with
|
|
8
|
+
the merged values so the file matches what's actually loaded.
|
|
9
|
+
|
|
10
|
+
Separately reports scalar drift (e.g., auto_compact_threshold=200000 when
|
|
11
|
+
the sensible value for the active model is lower). Those are advisory —
|
|
12
|
+
doctor prints them but won't change them without --fix.
|
|
13
|
+
"""
|
|
14
|
+
from __future__ import annotations
|
|
15
|
+
|
|
16
|
+
from dataclasses import dataclass
|
|
17
|
+
from pathlib import Path
|
|
18
|
+
from typing import Any
|
|
19
|
+
|
|
20
|
+
try:
|
|
21
|
+
import tomllib
|
|
22
|
+
except ImportError: # pragma: no cover
|
|
23
|
+
import tomli as tomllib # type: ignore
|
|
24
|
+
|
|
25
|
+
try:
|
|
26
|
+
import tomli_w
|
|
27
|
+
except ImportError: # pragma: no cover
|
|
28
|
+
tomli_w = None # type: ignore
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
# Fields known to be mergeable (user value unioned with package default).
|
|
32
|
+
# When drift is detected on these, `--fix` unions them.
|
|
33
|
+
MERGEABLE_LIST_FIELDS: dict[str, str] = {
|
|
34
|
+
# "section.field": "human_label"
|
|
35
|
+
"bash.allowlist": "bash allowlist (auto-approved commands)",
|
|
36
|
+
"bash.denylist": "bash denylist (blocked commands)",
|
|
37
|
+
"bash.denylist_standalone": "bash denylist_standalone",
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
@dataclass
|
|
42
|
+
class DriftReport:
|
|
43
|
+
field: str
|
|
44
|
+
user_value: Any
|
|
45
|
+
default_value: Any
|
|
46
|
+
kind: str # "list_merge" | "missing_in_user" | "scalar_stale"
|
|
47
|
+
fix_description: str
|
|
48
|
+
|
|
49
|
+
def to_row(self) -> tuple[str, str, str, str]:
|
|
50
|
+
u = str(self.user_value)
|
|
51
|
+
d = str(self.default_value)
|
|
52
|
+
if len(u) > 40:
|
|
53
|
+
u = u[:37] + "..."
|
|
54
|
+
if len(d) > 40:
|
|
55
|
+
d = d[:37] + "..."
|
|
56
|
+
return (self.field, u, d, self.kind)
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
def _get_tool_section(toml_data: dict, section: str) -> dict | None:
|
|
60
|
+
"""Walk `tools.bash` → toml_data.get('tools', {}).get('bash', {})."""
|
|
61
|
+
cur: Any = toml_data
|
|
62
|
+
for part in section.split("."):
|
|
63
|
+
if not isinstance(cur, dict):
|
|
64
|
+
return None
|
|
65
|
+
cur = cur.get(part)
|
|
66
|
+
if cur is None:
|
|
67
|
+
return None
|
|
68
|
+
return cur if isinstance(cur, dict) else None
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
def _get_default_list(field_path: str) -> list[str]:
|
|
72
|
+
"""Resolve the package-default factory for a dotted field path."""
|
|
73
|
+
section, field = field_path.rsplit(".", 1)
|
|
74
|
+
if section == "bash":
|
|
75
|
+
from drydock.core.tools.builtins.bash import (
|
|
76
|
+
_get_default_allowlist,
|
|
77
|
+
_get_default_denylist,
|
|
78
|
+
_get_default_denylist_standalone,
|
|
79
|
+
)
|
|
80
|
+
factories = {
|
|
81
|
+
"allowlist": _get_default_allowlist,
|
|
82
|
+
"denylist": _get_default_denylist,
|
|
83
|
+
"denylist_standalone": _get_default_denylist_standalone,
|
|
84
|
+
}
|
|
85
|
+
fn = factories.get(field)
|
|
86
|
+
return list(fn()) if fn else []
|
|
87
|
+
return []
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
def analyze_config(config_path: Path) -> tuple[dict, list[DriftReport]]:
|
|
91
|
+
"""Load the user's config.toml and compare each mergeable field against
|
|
92
|
+
its package default. Returns (raw_toml_data, drift_reports)."""
|
|
93
|
+
if not config_path.exists():
|
|
94
|
+
return {}, []
|
|
95
|
+
with config_path.open("rb") as f:
|
|
96
|
+
data = tomllib.load(f)
|
|
97
|
+
|
|
98
|
+
reports: list[DriftReport] = []
|
|
99
|
+
|
|
100
|
+
# Mergeable list fields — check for defaults missing from user config.
|
|
101
|
+
for field_path, _label in MERGEABLE_LIST_FIELDS.items():
|
|
102
|
+
section, field = field_path.rsplit(".", 1)
|
|
103
|
+
# Drydock TOML structure: [tools.bash] allowlist = [...]
|
|
104
|
+
user_section = _get_tool_section(data, f"tools.{section}")
|
|
105
|
+
user_value = user_section.get(field) if user_section else None
|
|
106
|
+
defaults = _get_default_list(field_path)
|
|
107
|
+
if user_value is None:
|
|
108
|
+
# User has no entry — pydantic uses full defaults. No drift.
|
|
109
|
+
continue
|
|
110
|
+
if not isinstance(user_value, list):
|
|
111
|
+
continue
|
|
112
|
+
if "__override__" in user_value:
|
|
113
|
+
continue # explicit opt-out, respect it
|
|
114
|
+
missing = [d for d in defaults if d not in user_value]
|
|
115
|
+
if missing:
|
|
116
|
+
reports.append(DriftReport(
|
|
117
|
+
field=f"tools.{field_path}",
|
|
118
|
+
user_value=f"{len(user_value)} entries",
|
|
119
|
+
default_value=f"{len(defaults)} in package",
|
|
120
|
+
kind="list_merge",
|
|
121
|
+
fix_description=(
|
|
122
|
+
f"Add {len(missing)} missing default(s): "
|
|
123
|
+
+ ", ".join(missing[:5])
|
|
124
|
+
+ (f" … (+{len(missing) - 5} more)" if len(missing) > 5 else "")
|
|
125
|
+
),
|
|
126
|
+
))
|
|
127
|
+
|
|
128
|
+
return data, reports
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
def print_drift_report(reports: list[DriftReport]) -> None:
|
|
132
|
+
"""Print a table of drift findings."""
|
|
133
|
+
from rich.console import Console
|
|
134
|
+
from rich.table import Table
|
|
135
|
+
console = Console()
|
|
136
|
+
if not reports:
|
|
137
|
+
console.print("[green]No config drift detected.[/green]")
|
|
138
|
+
console.print(
|
|
139
|
+
"Your ~/.drydock/config.toml is in sync with the package defaults."
|
|
140
|
+
)
|
|
141
|
+
return
|
|
142
|
+
table = Table(title="Config drift vs. package defaults", show_lines=True)
|
|
143
|
+
table.add_column("Field")
|
|
144
|
+
table.add_column("User", overflow="fold")
|
|
145
|
+
table.add_column("Package default", overflow="fold")
|
|
146
|
+
table.add_column("Kind")
|
|
147
|
+
for r in reports:
|
|
148
|
+
row = r.to_row()
|
|
149
|
+
table.add_row(*row)
|
|
150
|
+
console.print(table)
|
|
151
|
+
console.print("\n[bold]Details:[/bold]")
|
|
152
|
+
for r in reports:
|
|
153
|
+
console.print(f" • [cyan]{r.field}[/cyan]: {r.fix_description}")
|
|
154
|
+
console.print(
|
|
155
|
+
"\nRun [bold]drydock --doctor --fix[/bold] to apply safe corrections "
|
|
156
|
+
"(writes a backup to config.toml.bak).\n"
|
|
157
|
+
"Auto-mergeable lists are ALREADY merged at runtime — fixing only "
|
|
158
|
+
"updates the FILE to reflect what's loaded.\n"
|
|
159
|
+
)
|
|
160
|
+
|
|
161
|
+
|
|
162
|
+
def apply_fix(config_path: Path, data: dict, reports: list[DriftReport]) -> int:
|
|
163
|
+
"""Union missing defaults into the user's TOML file. Returns count of fields updated."""
|
|
164
|
+
if tomli_w is None:
|
|
165
|
+
raise RuntimeError(
|
|
166
|
+
"tomli_w is not installed. Add `pip install tomli_w` to use --fix."
|
|
167
|
+
)
|
|
168
|
+
updated = 0
|
|
169
|
+
for r in reports:
|
|
170
|
+
if r.kind != "list_merge":
|
|
171
|
+
continue
|
|
172
|
+
# r.field is e.g. "tools.bash.allowlist"
|
|
173
|
+
parts = r.field.split(".")
|
|
174
|
+
cur: Any = data
|
|
175
|
+
for p in parts[:-1]:
|
|
176
|
+
if p not in cur or not isinstance(cur[p], dict):
|
|
177
|
+
cur[p] = {}
|
|
178
|
+
cur = cur[p]
|
|
179
|
+
final_field = parts[-1]
|
|
180
|
+
defaults_path = ".".join(parts[1:]) # strip leading "tools."
|
|
181
|
+
defaults = _get_default_list(defaults_path)
|
|
182
|
+
user_list = cur.get(final_field, [])
|
|
183
|
+
merged = list(user_list) if isinstance(user_list, list) else []
|
|
184
|
+
for d in defaults:
|
|
185
|
+
if d not in merged:
|
|
186
|
+
merged.append(d)
|
|
187
|
+
cur[final_field] = merged
|
|
188
|
+
updated += 1
|
|
189
|
+
|
|
190
|
+
if updated == 0:
|
|
191
|
+
return 0
|
|
192
|
+
|
|
193
|
+
# Write backup then new file.
|
|
194
|
+
backup = config_path.with_suffix(config_path.suffix + ".bak")
|
|
195
|
+
if config_path.exists():
|
|
196
|
+
backup.write_bytes(config_path.read_bytes())
|
|
197
|
+
with config_path.open("wb") as f:
|
|
198
|
+
tomli_w.dump(data, f)
|
|
199
|
+
return updated
|
|
200
|
+
|
|
201
|
+
|
|
202
|
+
def run_doctor(apply: bool = False) -> int:
|
|
203
|
+
"""Entry point for `drydock --doctor [--fix]`. Returns shell exit code."""
|
|
204
|
+
from drydock.core.config.harness_files import get_harness_files_manager
|
|
205
|
+
from rich.console import Console
|
|
206
|
+
console = Console()
|
|
207
|
+
|
|
208
|
+
mgr = get_harness_files_manager()
|
|
209
|
+
config_path = mgr.config_file
|
|
210
|
+
if config_path is None:
|
|
211
|
+
console.print("[yellow]No user config file found.[/yellow]")
|
|
212
|
+
return 0
|
|
213
|
+
console.print(f"Analyzing [bold]{config_path}[/bold] ...\n")
|
|
214
|
+
data, reports = analyze_config(config_path)
|
|
215
|
+
print_drift_report(reports)
|
|
216
|
+
if apply and reports:
|
|
217
|
+
updated = apply_fix(config_path, data, reports)
|
|
218
|
+
console.print(
|
|
219
|
+
f"\n[green]Applied fixes to {updated} field(s). "
|
|
220
|
+
f"Backup saved to {config_path}.bak[/green]"
|
|
221
|
+
)
|
|
222
|
+
return 0
|
|
@@ -164,25 +164,52 @@ class APIToolFormatHandler:
|
|
|
164
164
|
try:
|
|
165
165
|
args = json.loads(raw_json)
|
|
166
166
|
except json.JSONDecodeError:
|
|
167
|
-
#
|
|
167
|
+
# Gemma 4 frequently leaks thinking-token markers INSIDE
|
|
168
|
+
# JSON string values. Tokens like "<|\Fix" make `\F` an
|
|
169
|
+
# invalid JSON escape, which crashes the decoder and loses
|
|
170
|
+
# the whole tool call. Sanitize and retry before giving up.
|
|
168
171
|
import logging
|
|
172
|
+
import re as _re
|
|
169
173
|
logging.getLogger(__name__).warning(
|
|
170
174
|
"Malformed tool call JSON for %s: %s",
|
|
171
175
|
function_call.name,
|
|
172
176
|
(function_call.arguments or "")[:200],
|
|
173
177
|
)
|
|
174
|
-
# Try to salvage partial JSON by closing brackets
|
|
175
178
|
raw = (function_call.arguments or "").strip()
|
|
179
|
+
args = {}
|
|
176
180
|
if raw:
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
181
|
+
sanitized = raw
|
|
182
|
+
# Strip complete <|channel>...<channel|>/<tool_call|> blocks
|
|
183
|
+
sanitized = _re.sub(
|
|
184
|
+
r"<\|channel\>.*?(?:<channel\|>|<tool_call\|>)",
|
|
185
|
+
"", sanitized, flags=_re.DOTALL,
|
|
186
|
+
)
|
|
187
|
+
sanitized = _re.sub(
|
|
188
|
+
r"<\|tool_call\>.*?<tool_call\|>",
|
|
189
|
+
"", sanitized, flags=_re.DOTALL,
|
|
190
|
+
)
|
|
191
|
+
# Strip unpaired/truncated <|...|> and <|...> tokens.
|
|
192
|
+
sanitized = _re.sub(r"<\|[^>]{0,200}\|>", "", sanitized)
|
|
193
|
+
sanitized = _re.sub(r"<\|[^>]{0,200}>", "", sanitized)
|
|
194
|
+
sanitized = _re.sub(r"<[^>]{0,200}\|>", "", sanitized)
|
|
195
|
+
# Escape any remaining invalid backslash escapes (JSON
|
|
196
|
+
# only allows \" \\ \/ \b \f \n \r \t \u). Catches e.g.
|
|
197
|
+
# `<|\Fix` residue where `\F` would abort the decoder.
|
|
198
|
+
sanitized = _re.sub(
|
|
199
|
+
r'\\(?!["\\/bfnrtu])', r'\\\\', sanitized,
|
|
200
|
+
)
|
|
180
201
|
try:
|
|
181
|
-
args = json.loads(
|
|
202
|
+
args = json.loads(sanitized)
|
|
182
203
|
except json.JSONDecodeError:
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
204
|
+
# Last-ditch: try closing any unbalanced braces.
|
|
205
|
+
opens = sanitized.count("{") - sanitized.count("}")
|
|
206
|
+
if opens > 0:
|
|
207
|
+
try:
|
|
208
|
+
args = json.loads(sanitized + "}" * opens)
|
|
209
|
+
except json.JSONDecodeError:
|
|
210
|
+
args = {"_parse_error": f"Malformed JSON after sanitize: {sanitized[:100]}..."}
|
|
211
|
+
else:
|
|
212
|
+
args = {"_parse_error": f"Malformed JSON: {raw[:100]}..."}
|
|
186
213
|
|
|
187
214
|
tool_calls.append(
|
|
188
215
|
ParsedToolCall(
|
|
@@ -51,6 +51,11 @@ class InvokeContext:
|
|
|
51
51
|
entrypoint_metadata: EntrypointMetadata | None = field(default=None)
|
|
52
52
|
plan_file_path: Path | None = field(default=None)
|
|
53
53
|
switch_agent_callback: SwitchAgentCallback | None = field(default=None)
|
|
54
|
+
# Shared across all tool invocations within a session. The same dict
|
|
55
|
+
# reference lives on AgentLoop; write_file / read_file / search_replace
|
|
56
|
+
# mutate it to track what the model has observed (Read-before-Write
|
|
57
|
+
# + read dedup, per Claude Code's tool contract model).
|
|
58
|
+
read_file_state: dict[str, dict] | None = field(default=None)
|
|
54
59
|
|
|
55
60
|
|
|
56
61
|
class ToolError(Exception):
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
3
|
import asyncio
|
|
4
|
-
from collections.abc import AsyncGenerator
|
|
4
|
+
from collections.abc import AsyncGenerator, Callable
|
|
5
|
+
from typing import Any
|
|
5
6
|
from functools import lru_cache
|
|
6
7
|
import os
|
|
7
8
|
from pathlib import Path
|
|
@@ -9,7 +10,7 @@ import signal
|
|
|
9
10
|
import sys
|
|
10
11
|
from typing import ClassVar, Literal, final
|
|
11
12
|
|
|
12
|
-
from pydantic import BaseModel, Field
|
|
13
|
+
from pydantic import BaseModel, Field, field_validator
|
|
13
14
|
from tree_sitter import Language, Node, Parser
|
|
14
15
|
import tree_sitter_bash as tsbash
|
|
15
16
|
|
|
@@ -161,8 +162,25 @@ async def _kill_process_tree(proc: asyncio.subprocess.Process) -> None:
|
|
|
161
162
|
|
|
162
163
|
|
|
163
164
|
def _get_default_allowlist() -> list[str]:
|
|
165
|
+
# Auto-accepted because they are read-only / non-destructive.
|
|
166
|
+
# Each entry is a prefix — commands starting with any of these are
|
|
167
|
+
# ALWAYS allowed. Parser splits at pipes/chains so `ls | rm` is
|
|
168
|
+
# checked as two separate commands.
|
|
164
169
|
common = [
|
|
165
|
-
"echo", "find", "
|
|
170
|
+
"echo", "find", "tree", "whoami",
|
|
171
|
+
# Git read-only subcommands
|
|
172
|
+
"git diff", "git log", "git status", "git show",
|
|
173
|
+
"git branch", "git ls-files", "git grep", "git remote",
|
|
174
|
+
"git rev-parse", "git blame", "git config --get",
|
|
175
|
+
"git tag", "git stash list",
|
|
176
|
+
# Search tools (read-only by design)
|
|
177
|
+
"grep", "rg", "fd", "fdfind", "ag",
|
|
178
|
+
# Text/file inspection
|
|
179
|
+
"diff", "cmp", "sort", "uniq", "awk", "cut", "tr",
|
|
180
|
+
"basename", "dirname", "realpath", "readlink",
|
|
181
|
+
# System info (read-only)
|
|
182
|
+
"date", "id", "hostname", "pwd", "env", "printenv",
|
|
183
|
+
"du", "df", "ps", "free", "uptime",
|
|
166
184
|
# Python project management — safe read/install operations
|
|
167
185
|
"pip install", "pip list", "pip show", "pip freeze", "pip check",
|
|
168
186
|
"pip install -e", "pip install -r",
|
|
@@ -221,6 +239,26 @@ def _get_default_denylist_standalone() -> list[str]:
|
|
|
221
239
|
return common + ["bash", "sh", "nohup", "vi", "vim", "emacs", "nano", "su"]
|
|
222
240
|
|
|
223
241
|
|
|
242
|
+
def _merge_with_defaults(user_value: Any, defaults_fn: Callable[[], list[str]]) -> list[str]:
|
|
243
|
+
"""Union user list with package defaults so `pip install -U` propagates
|
|
244
|
+
new defaults without clobbering user additions (Config Option A). If the
|
|
245
|
+
user list ends with an entry '__override__', their list is used verbatim
|
|
246
|
+
(escape hatch for anyone who needs to intentionally remove a default).
|
|
247
|
+
"""
|
|
248
|
+
if user_value is None:
|
|
249
|
+
return defaults_fn()
|
|
250
|
+
if not isinstance(user_value, list):
|
|
251
|
+
return user_value # pydantic will re-type-check and fail cleanly
|
|
252
|
+
if "__override__" in user_value:
|
|
253
|
+
return [v for v in user_value if v != "__override__"]
|
|
254
|
+
defaults = defaults_fn()
|
|
255
|
+
merged = list(defaults)
|
|
256
|
+
for item in user_value:
|
|
257
|
+
if item not in merged:
|
|
258
|
+
merged.append(item)
|
|
259
|
+
return merged
|
|
260
|
+
|
|
261
|
+
|
|
224
262
|
class BashToolConfig(BaseToolConfig):
|
|
225
263
|
permission: ToolPermission = ToolPermission.ASK
|
|
226
264
|
max_output_bytes: int = Field(
|
|
@@ -231,17 +269,40 @@ class BashToolConfig(BaseToolConfig):
|
|
|
231
269
|
)
|
|
232
270
|
allowlist: list[str] = Field(
|
|
233
271
|
default_factory=_get_default_allowlist,
|
|
234
|
-
description=
|
|
272
|
+
description=(
|
|
273
|
+
"Command prefixes that are automatically allowed. User entries "
|
|
274
|
+
"are UNIONED with package defaults (new defaults auto-propagate "
|
|
275
|
+
"on pip install -U). Include '__override__' in the list to use "
|
|
276
|
+
"your list verbatim and skip defaults."
|
|
277
|
+
),
|
|
235
278
|
)
|
|
236
279
|
denylist: list[str] = Field(
|
|
237
280
|
default_factory=_get_default_denylist,
|
|
238
|
-
description=
|
|
281
|
+
description=(
|
|
282
|
+
"Command prefixes that are automatically denied. User entries "
|
|
283
|
+
"unioned with package defaults; see allowlist for override."
|
|
284
|
+
),
|
|
239
285
|
)
|
|
240
286
|
denylist_standalone: list[str] = Field(
|
|
241
287
|
default_factory=_get_default_denylist_standalone,
|
|
242
288
|
description="Commands that are denied only when run without arguments",
|
|
243
289
|
)
|
|
244
290
|
|
|
291
|
+
@field_validator("allowlist", mode="before")
|
|
292
|
+
@classmethod
|
|
293
|
+
def _merge_allowlist(cls, v: Any) -> list[str]:
|
|
294
|
+
return _merge_with_defaults(v, _get_default_allowlist)
|
|
295
|
+
|
|
296
|
+
@field_validator("denylist", mode="before")
|
|
297
|
+
@classmethod
|
|
298
|
+
def _merge_denylist(cls, v: Any) -> list[str]:
|
|
299
|
+
return _merge_with_defaults(v, _get_default_denylist)
|
|
300
|
+
|
|
301
|
+
@field_validator("denylist_standalone", mode="before")
|
|
302
|
+
@classmethod
|
|
303
|
+
def _merge_denylist_standalone(cls, v: Any) -> list[str]:
|
|
304
|
+
return _merge_with_defaults(v, _get_default_denylist_standalone)
|
|
305
|
+
|
|
245
306
|
|
|
246
307
|
class BashArgs(BaseModel):
|
|
247
308
|
command: str
|
|
@@ -388,30 +449,17 @@ class Bash(
|
|
|
388
449
|
|
|
389
450
|
returncode = proc.returncode or 0
|
|
390
451
|
|
|
391
|
-
# Mechanical loop-breaker
|
|
392
|
-
#
|
|
393
|
-
#
|
|
394
|
-
#
|
|
395
|
-
#
|
|
396
|
-
# re-runs). ToolError goes through the error-handling path
|
|
397
|
-
# and the model visibly reacts to those.
|
|
452
|
+
# Mechanical loop-breaker (ADVISORY ONLY — never raise
|
|
453
|
+
# ToolError; see feedback_no_tool_errors_for_loop_detection.md).
|
|
454
|
+
# 3rd+ identical call: collapse body to short notice so the
|
|
455
|
+
# model sees "this ran already with same output" without
|
|
456
|
+
# getting refused into a block-loop.
|
|
398
457
|
state = self.state.__dict__.setdefault("_bash_history", {})
|
|
399
458
|
combined = stdout + "\n---STDERR---\n" + stderr
|
|
400
459
|
out_hash = hash((combined, returncode))
|
|
401
460
|
entry = state.get(args.command)
|
|
402
461
|
if entry and entry["hash"] == out_hash:
|
|
403
462
|
entry["count"] += 1
|
|
404
|
-
if entry["count"] >= 5:
|
|
405
|
-
raise ToolError(
|
|
406
|
-
f"REFUSED: `{args.command[:80]}` has run "
|
|
407
|
-
f"{entry['count']} times with IDENTICAL output "
|
|
408
|
-
f"(rc={returncode}). Re-running will NOT change "
|
|
409
|
-
f"anything. You MUST do something DIFFERENT: "
|
|
410
|
-
f"edit source files, write tests, read a DIFFERENT "
|
|
411
|
-
f"file, or move on. This exact command is blocked "
|
|
412
|
-
f"until you take a different action. Last stdout "
|
|
413
|
-
f"(first 300): {stdout[:300]!r}"
|
|
414
|
-
)
|
|
415
463
|
if entry["count"] >= 3:
|
|
416
464
|
notice = (
|
|
417
465
|
f"[NOTICE: this is the #{entry['count']} identical "
|
|
@@ -92,63 +92,56 @@ class ReadFile(
|
|
|
92
92
|
)
|
|
93
93
|
return
|
|
94
94
|
|
|
95
|
+
# mtime-based read dedup (Claude Code tool-contract pattern).
|
|
96
|
+
# If the model reads a file it has already read this session and
|
|
97
|
+
# nothing has changed on disk since, return a compact stub
|
|
98
|
+
# pointing to the earlier tool_result. Saves context + kills the
|
|
99
|
+
# "re-read 50x for no reason" pattern. Also preserves Read-before-
|
|
100
|
+
# Write because the stub still counts as having read the file.
|
|
101
|
+
read_state = ctx.read_file_state if ctx else None
|
|
102
|
+
path_key = str(file_path)
|
|
103
|
+
try:
|
|
104
|
+
current_mtime = file_path.stat().st_mtime_ns
|
|
105
|
+
except OSError:
|
|
106
|
+
current_mtime = 0
|
|
107
|
+
prior = read_state.get(path_key) if read_state is not None else None
|
|
108
|
+
if (
|
|
109
|
+
prior is not None
|
|
110
|
+
and prior.get("timestamp") == current_mtime
|
|
111
|
+
and prior.get("offset") == args.offset
|
|
112
|
+
and prior.get("limit") == args.limit
|
|
113
|
+
):
|
|
114
|
+
yield ReadFileResult(
|
|
115
|
+
path=path_key,
|
|
116
|
+
content=(
|
|
117
|
+
"<system-reminder>\n"
|
|
118
|
+
f"File unchanged since your earlier read this session "
|
|
119
|
+
f"({file_path.name}, mtime unchanged, same offset/limit). "
|
|
120
|
+
"Use the content from the earlier Read tool_result — "
|
|
121
|
+
"do NOT re-read. If you need to take action, call "
|
|
122
|
+
"search_replace or write_file on what you already have.\n"
|
|
123
|
+
"</system-reminder>"
|
|
124
|
+
),
|
|
125
|
+
lines_read=0,
|
|
126
|
+
was_truncated=True,
|
|
127
|
+
)
|
|
128
|
+
return
|
|
129
|
+
|
|
95
130
|
read_result = await self._read_file(args, file_path)
|
|
96
131
|
content = "".join(read_result.lines)
|
|
97
132
|
|
|
98
|
-
#
|
|
99
|
-
#
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
entry = state.get(key)
|
|
108
|
-
now_hash = hash(content)
|
|
109
|
-
if entry and entry["hash"] == now_hash:
|
|
110
|
-
entry["count"] += 1
|
|
111
|
-
# Tier 2 (5th identical read): ToolError — notice alone is
|
|
112
|
-
# being ignored by Gemma 4. An error forces the model through
|
|
113
|
-
# the error-handling path, which it reacts to.
|
|
114
|
-
if entry["count"] >= 5:
|
|
115
|
-
from drydock.core.tools.base import ToolError as _TE
|
|
116
|
-
raise _TE(
|
|
117
|
-
f"REFUSED: you have already read {file_path.name} "
|
|
118
|
-
f"{entry['count']} times with no file changes in "
|
|
119
|
-
f"between. The content is in your context already. "
|
|
120
|
-
f"STOP re-reading and DO something: edit the file, "
|
|
121
|
-
f"read a DIFFERENT file, or run the code. This read "
|
|
122
|
-
f"is refused until a different action happens."
|
|
123
|
-
)
|
|
124
|
-
if entry["count"] >= 3:
|
|
125
|
-
notice = (
|
|
126
|
-
f"[NOTICE: this is read_file call #{entry['count']} "
|
|
127
|
-
f"for {file_path.name} with no file changes since the "
|
|
128
|
-
f"previous reads. The content below is IDENTICAL to "
|
|
129
|
-
f"what you already have. STOP re-reading — use the "
|
|
130
|
-
f"content from your context. Either edit the file "
|
|
131
|
-
f"with search_replace/write_file, or call a different "
|
|
132
|
-
f"tool.]\n"
|
|
133
|
-
)
|
|
134
|
-
# Return only the first 10 lines + the notice, so the
|
|
135
|
-
# model isn't spending context on identical body.
|
|
136
|
-
short = content.split("\n", 10)
|
|
137
|
-
shortened = "\n".join(short[:10])
|
|
138
|
-
if len(short) > 10:
|
|
139
|
-
shortened += f"\n... [body elided on repeat read #{entry['count']}]"
|
|
140
|
-
yield ReadFileResult(
|
|
141
|
-
path=str(file_path),
|
|
142
|
-
content=notice + shortened,
|
|
143
|
-
lines_read=len(read_result.lines),
|
|
144
|
-
was_truncated=True,
|
|
145
|
-
)
|
|
146
|
-
return
|
|
147
|
-
else:
|
|
148
|
-
state[key] = {"hash": now_hash, "count": 1}
|
|
133
|
+
# Record read state so Write/Edit can enforce Read-before-Write
|
|
134
|
+
# and so future re-reads can dedup against this one.
|
|
135
|
+
if read_state is not None:
|
|
136
|
+
read_state[path_key] = {
|
|
137
|
+
"content": content,
|
|
138
|
+
"timestamp": current_mtime,
|
|
139
|
+
"offset": args.offset,
|
|
140
|
+
"limit": args.limit,
|
|
141
|
+
}
|
|
149
142
|
|
|
150
143
|
yield ReadFileResult(
|
|
151
|
-
path=
|
|
144
|
+
path=path_key,
|
|
152
145
|
content=content,
|
|
153
146
|
lines_read=len(read_result.lines),
|
|
154
147
|
was_truncated=read_result.was_truncated,
|