drydock-cli 3.1.32__tar.gz → 3.1.33__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-3.1.32/drydock_cli.egg-info → drydock_cli-3.1.33}/PKG-INFO +1 -1
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/drydock/advisor.py +27 -10
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/drydock/tools/__init__.py +3 -8
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/drydock/tui/app.py +3 -0
- {drydock_cli-3.1.32 → drydock_cli-3.1.33/drydock_cli.egg-info}/PKG-INFO +1 -1
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/pyproject.toml +1 -1
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/tests/test_advisor.py +26 -24
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/LICENSE +0 -0
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/NOTICE +0 -0
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/README.md +0 -0
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/drydock/__init__.py +0 -0
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/drydock/__main__.py +0 -0
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/drydock/agent.py +0 -0
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/drydock/asr.py +0 -0
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/drydock/bash_safety.py +0 -0
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/drydock/bottleneck.py +0 -0
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/drydock/budget.py +0 -0
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/drydock/builtin_skills/__init__.py +0 -0
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/drydock/builtin_skills/document-canvas.md +0 -0
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/drydock/builtin_skills/fiar-assess.md +0 -0
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/drydock/builtin_skills/fiar-cap.md +0 -0
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/drydock/builtin_skills/fiar-evidence.md +0 -0
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/drydock/builtin_skills/fiar-readiness.md +0 -0
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/drydock/builtin_skills/ml-data.md +0 -0
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/drydock/builtin_skills/ml-debug.md +0 -0
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/drydock/builtin_skills/ml-finetune.md +0 -0
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/drydock/builtin_skills/ml-metrics.md +0 -0
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/drydock/builtin_skills/ml-rl.md +0 -0
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/drydock/builtin_skills/ml-train.md +0 -0
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/drydock/builtin_skills/nist-ai-rmf.md +0 -0
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/drydock/builtin_skills/nist-csf.md +0 -0
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/drydock/builtin_skills/rmf-categorize.md +0 -0
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/drydock/builtin_skills/rmf-control.md +0 -0
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/drydock/builtin_skills/rmf-poam.md +0 -0
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/drydock/builtin_skills/rmf-review.md +0 -0
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/drydock/builtin_skills/stig-assess.md +0 -0
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/drydock/builtin_skills/stig-remediate.md +0 -0
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/drydock/capacity.py +0 -0
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/drydock/cci.py +0 -0
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/drydock/cli.py +0 -0
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/drydock/comms/__init__.py +0 -0
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/drydock/comms/attention.py +0 -0
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/drydock/comms/channels.py +0 -0
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/drydock/comms/events.py +0 -0
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/drydock/compaction.py +0 -0
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/drydock/config.py +0 -0
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/drydock/detect.py +0 -0
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/drydock/doccanvas.py +0 -0
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/drydock/eratchet.py +0 -0
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/drydock/events.py +0 -0
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/drydock/extract.py +0 -0
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/drydock/fiar.py +0 -0
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/drydock/gittools.py +0 -0
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/drydock/graphrag.py +0 -0
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/drydock/groundtruth.py +0 -0
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/drydock/guards.py +0 -0
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/drydock/jobs.py +0 -0
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/drydock/loop_detect.py +0 -0
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/drydock/mcp.py +0 -0
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/drydock/mission.py +0 -0
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/drydock/mission_cli.py +0 -0
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/drydock/mission_run.py +0 -0
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/drydock/pdfredbox.py +0 -0
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/drydock/phases.py +0 -0
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/drydock/poam.py +0 -0
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/drydock/predictions.py +0 -0
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/drydock/progress.py +0 -0
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/drydock/providers.py +0 -0
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/drydock/ratchet.py +0 -0
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/drydock/recipes.py +0 -0
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/drydock/recovery.py +0 -0
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/drydock/resume.py +0 -0
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/drydock/rmf.py +0 -0
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/drydock/rmf_graph.py +0 -0
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/drydock/skills.py +0 -0
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/drydock/stig.py +0 -0
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/drydock/subagents.py +0 -0
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/drydock/suggest.py +0 -0
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/drydock/swarm.py +0 -0
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/drydock/task_state.py +0 -0
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/drydock/tool_policy.py +0 -0
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/drydock/tool_registry.py +0 -0
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/drydock/tool_result.py +0 -0
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/drydock/tool_select.py +0 -0
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/drydock/tool_validate.py +0 -0
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/drydock/trajectory.py +0 -0
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/drydock/tui/__init__.py +0 -0
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/drydock/tui/approval.py +0 -0
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/drydock/tui/messages.py +0 -0
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/drydock/tui/widgets.py +0 -0
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/drydock/tuning.py +0 -0
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/drydock/verification.py +0 -0
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/drydock/web.py +0 -0
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/drydock_cli.egg-info/SOURCES.txt +0 -0
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/drydock_cli.egg-info/dependency_links.txt +0 -0
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/drydock_cli.egg-info/entry_points.txt +0 -0
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/drydock_cli.egg-info/requires.txt +0 -0
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/drydock_cli.egg-info/top_level.txt +0 -0
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/setup.cfg +0 -0
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/tests/test_approval.py +0 -0
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/tests/test_asr.py +0 -0
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/tests/test_back_command.py +0 -0
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/tests/test_bash_background.py +0 -0
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/tests/test_bash_binary_output.py +0 -0
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/tests/test_bash_crossplatform.py +0 -0
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/tests/test_bash_output_bounding.py +0 -0
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/tests/test_bash_process_group.py +0 -0
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/tests/test_bash_safety.py +0 -0
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/tests/test_bash_sanitize.py +0 -0
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/tests/test_bash_shell.py +0 -0
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/tests/test_bash_stdin.py +0 -0
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/tests/test_bash_stop_partial.py +0 -0
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/tests/test_bash_timeout_network.py +0 -0
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/tests/test_bash_timeout_param.py +0 -0
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/tests/test_bottleneck.py +0 -0
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/tests/test_budget.py +0 -0
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/tests/test_capacity.py +0 -0
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/tests/test_cci.py +0 -0
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/tests/test_cli_agents.py +0 -0
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/tests/test_comms.py +0 -0
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/tests/test_compact_command.py +0 -0
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/tests/test_compaction.py +0 -0
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/tests/test_config.py +0 -0
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/tests/test_config_migration.py +0 -0
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/tests/test_context_limit_config.py +0 -0
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/tests/test_context_limit_issue25.py +0 -0
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/tests/test_criteria_coverage.py +0 -0
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/tests/test_cycling_detection.py +0 -0
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/tests/test_declared_deps.py +0 -0
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/tests/test_degenerate_argument.py +0 -0
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/tests/test_detect.py +0 -0
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/tests/test_dispatch.py +0 -0
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/tests/test_doccanvas.py +0 -0
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/tests/test_e2e_connected.py +0 -0
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/tests/test_edit_replace_all.py +0 -0
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/tests/test_edit_thrash_and_compaction.py +0 -0
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/tests/test_effort_governor.py +0 -0
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/tests/test_empty_response.py +0 -0
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/tests/test_eratchet.py +0 -0
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/tests/test_events.py +0 -0
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/tests/test_extract.py +0 -0
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/tests/test_failure_loop.py +0 -0
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/tests/test_fiar.py +0 -0
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/tests/test_first_run_setup.py +0 -0
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/tests/test_gittools.py +0 -0
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/tests/test_glob_edit_edges.py +0 -0
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/tests/test_graphify_example.py +0 -0
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/tests/test_graphrag.py +0 -0
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/tests/test_graphrag_quoted_path.py +0 -0
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/tests/test_graphrag_sqlite.py +0 -0
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/tests/test_grep_and_read_robust.py +0 -0
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/tests/test_groundtruth_predictions.py +0 -0
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/tests/test_guards_and_tools.py +0 -0
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/tests/test_hallucinated_tools.py +0 -0
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/tests/test_jobs.py +0 -0
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/tests/test_knowledge_tool_available.py +0 -0
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/tests/test_leaked_tool_call.py +0 -0
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/tests/test_loop_detect.py +0 -0
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/tests/test_main_api_key.py +0 -0
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/tests/test_mcp.py +0 -0
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/tests/test_mission.py +0 -0
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/tests/test_mission_cli.py +0 -0
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/tests/test_mission_run.py +0 -0
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/tests/test_model_registry.py +0 -0
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/tests/test_oneshot_unreachable.py +0 -0
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/tests/test_overthink_interrupt.py +0 -0
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/tests/test_pdfredbox.py +0 -0
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/tests/test_phases.py +0 -0
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/tests/test_plan_autocontinue.py +0 -0
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/tests/test_poam.py +0 -0
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/tests/test_progress.py +0 -0
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/tests/test_providers_unreachable.py +0 -0
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/tests/test_ratchet.py +0 -0
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/tests/test_ratchet_offer.py +0 -0
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/tests/test_read_index.py +0 -0
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/tests/test_recipes.py +0 -0
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/tests/test_recovery.py +0 -0
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/tests/test_recovery_config.py +0 -0
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/tests/test_recovery_integration.py +0 -0
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/tests/test_repeated_outcome.py +0 -0
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/tests/test_repetition_interrupt.py +0 -0
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/tests/test_resume_events.py +0 -0
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/tests/test_resume_restore.py +0 -0
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/tests/test_resume_snapshot.py +0 -0
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/tests/test_rmf.py +0 -0
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/tests/test_rmf_graph.py +0 -0
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/tests/test_rmf_stig_graph.py +0 -0
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/tests/test_rolling_plan.py +0 -0
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/tests/test_runaway_repetition.py +0 -0
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/tests/test_screenshot.py +0 -0
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/tests/test_server_probe.py +0 -0
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/tests/test_skills.py +0 -0
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/tests/test_sqlite_events.py +0 -0
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/tests/test_stall_retry.py +0 -0
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/tests/test_stig.py +0 -0
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/tests/test_stop.py +0 -0
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/tests/test_streaming_newlines.py +0 -0
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/tests/test_subagent.py +0 -0
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/tests/test_subagents.py +0 -0
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/tests/test_suggest.py +0 -0
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/tests/test_swarm.py +0 -0
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/tests/test_system_prompt_help.py +0 -0
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/tests/test_task_state.py +0 -0
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/tests/test_timeline.py +0 -0
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/tests/test_todo.py +0 -0
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/tests/test_tool_arg_coercion.py +0 -0
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/tests/test_tool_arg_coercion_more.py +0 -0
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/tests/test_tool_arg_parsing.py +0 -0
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/tests/test_tool_canonical.py +0 -0
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/tests/test_tool_policy.py +0 -0
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/tests/test_tool_result.py +0 -0
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/tests/test_tool_select.py +0 -0
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/tests/test_tool_validate.py +0 -0
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/tests/test_tools_undo.py +0 -0
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/tests/test_trajectory.py +0 -0
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/tests/test_tui.py +0 -0
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/tests/test_tuning.py +0 -0
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/tests/test_verification_gate.py +0 -0
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/tests/test_viewimage.py +0 -0
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/tests/test_vision_input.py +0 -0
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/tests/test_web_tools.py +0 -0
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/tests/test_windows_shell.py +0 -0
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/tests/test_worker_subagent.py +0 -0
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/tests/test_write_content_coerce.py +0 -0
- {drydock_cli-3.1.32 → drydock_cli-3.1.33}/tests/test_xccdf.py +0 -0
|
@@ -16,11 +16,14 @@ from __future__ import annotations
|
|
|
16
16
|
|
|
17
17
|
_ADVISOR_SYSTEM = (
|
|
18
18
|
"You are a senior engineering advisor consulted by another AI coding agent "
|
|
19
|
-
"(Drydock) running a smaller local model.
|
|
20
|
-
"
|
|
21
|
-
"
|
|
22
|
-
"
|
|
23
|
-
"
|
|
19
|
+
"(Drydock) running a smaller local model. You are given a BRIEF (recent activity, "
|
|
20
|
+
"errors, tool output, and any context the agent attached) followed by a QUESTION — "
|
|
21
|
+
"treat it like a task handed to you with its background. Answer FROM the brief: give "
|
|
22
|
+
"concise, direct, expert advice — the specific fix, the design trade-off, or the likely "
|
|
23
|
+
"root cause. Prefer concrete steps and short code over prose. If the brief is thin or the "
|
|
24
|
+
"question is under-specified, STATE your best assumption and answer anyway — do NOT reply "
|
|
25
|
+
"that you have no information to review. You cannot run tools; the calling agent acts on "
|
|
26
|
+
"your answer."
|
|
24
27
|
)
|
|
25
28
|
|
|
26
29
|
|
|
@@ -82,9 +85,8 @@ def _call(question: str, config: dict, *, context: str = "",
|
|
|
82
85
|
key = (config.get("advisor_api_key") or "").strip() or "dummy"
|
|
83
86
|
messages: list[dict] = [{"role": "system", "content": _ADVISOR_SYSTEM}]
|
|
84
87
|
if context.strip():
|
|
85
|
-
messages.append({"role": "user",
|
|
86
|
-
|
|
87
|
-
messages.append({"role": "user", "content": question})
|
|
88
|
+
messages.append({"role": "user", "content": f"=== BRIEF ===\n{context.strip()}"})
|
|
89
|
+
messages.append({"role": "user", "content": f"=== QUESTION ===\n{question}"})
|
|
88
90
|
kwargs = {"model": model, "messages": messages, "temperature": 0.3, "max_tokens": max_tokens}
|
|
89
91
|
client = OpenAI(api_key=key, base_url=base, max_retries=1,
|
|
90
92
|
timeout=httpx.Timeout(timeout, connect=10.0))
|
|
@@ -92,16 +94,31 @@ def _call(question: str, config: dict, *, context: str = "",
|
|
|
92
94
|
return (resp.choices[0].message.content or "").strip()
|
|
93
95
|
|
|
94
96
|
|
|
97
|
+
def build_brief(config: dict, context: str = "") -> str:
|
|
98
|
+
"""Assemble the advisor's brief (§ Consult): the recent transcript the agent stashed in
|
|
99
|
+
config PLUS any context the caller passed. Centralized here so BOTH the `Consult` tool and
|
|
100
|
+
the `/ask` command send a self-contained, sub-agent-style brief — not a bare question."""
|
|
101
|
+
parts = []
|
|
102
|
+
recent = recent_context(config.get("_recent_messages") or [])
|
|
103
|
+
if recent:
|
|
104
|
+
parts.append("RECENT ACTIVITY (agent's reasoning, tool output, errors):\n" + recent)
|
|
105
|
+
if (context or "").strip():
|
|
106
|
+
parts.append("CONTEXT:\n" + context.strip())
|
|
107
|
+
return "\n\n".join(parts)
|
|
108
|
+
|
|
109
|
+
|
|
95
110
|
def consult(question: str, config: dict, *, context: str = "", timeout: float = 120.0) -> str:
|
|
96
111
|
"""Ask the configured advisor model and return its answer (or a clean error).
|
|
97
|
-
Never raises — a failed consult must not crash the turn.
|
|
112
|
+
Never raises — a failed consult must not crash the turn. Auto-briefs the advisor with the
|
|
113
|
+
recent transcript so it's informed even when the caller passed no context."""
|
|
98
114
|
question = (question or "").strip()
|
|
99
115
|
if not question:
|
|
100
116
|
return "Error: nothing to ask the advisor."
|
|
101
117
|
if not is_configured(config):
|
|
102
118
|
return not_configured_message()
|
|
119
|
+
brief = build_brief(config, context)
|
|
103
120
|
try:
|
|
104
|
-
return _call(question, config, context=
|
|
121
|
+
return _call(question, config, context=brief, timeout=timeout) \
|
|
105
122
|
or "(the advisor model returned an empty response)"
|
|
106
123
|
except Exception as e: # noqa: BLE001 — never crash the caller
|
|
107
124
|
return (f"Could not reach the advisor model ({config.get('advisor_model')}) at "
|
|
@@ -2054,14 +2054,9 @@ def tool_consult(params: dict, config: dict) -> str:
|
|
|
2054
2054
|
question = _as_str_arg(params.get("question") or params.get("prompt")).strip()
|
|
2055
2055
|
if not question:
|
|
2056
2056
|
return "Error: Consult needs a `question`."
|
|
2057
|
-
|
|
2058
|
-
#
|
|
2059
|
-
|
|
2060
|
-
# that the agent stashed in config so the advisor always has real information to work with.
|
|
2061
|
-
auto = advisor.recent_context(config.get("_recent_messages") or [])
|
|
2062
|
-
if auto:
|
|
2063
|
-
ctx = (ctx + "\n\n" if ctx else "") + "Recent activity (auto-attached):\n" + auto
|
|
2064
|
-
return advisor.consult(question, config, context=ctx)
|
|
2057
|
+
# consult() now auto-briefs the advisor with the recent transcript (from config), so both
|
|
2058
|
+
# this tool and /ask send a self-contained brief — just pass the model's extra context.
|
|
2059
|
+
return advisor.consult(question, config, context=_as_str_arg(params.get("context") or ""))
|
|
2065
2060
|
|
|
2066
2061
|
|
|
2067
2062
|
# A sub-agent's whole job is to keep its investigation OUT of the main agent's
|
|
@@ -1565,6 +1565,9 @@ class DrydockApp(App):
|
|
|
1565
1565
|
|
|
1566
1566
|
def _ask_worker(self, question: str, inject: bool = False) -> None:
|
|
1567
1567
|
from drydock import advisor
|
|
1568
|
+
# Brief the advisor with the live transcript (same as the Consult tool) so /ask isn't
|
|
1569
|
+
# a context-free question — the advisor sees the recent reasoning/errors.
|
|
1570
|
+
self.config["_recent_messages"] = self.state.messages
|
|
1568
1571
|
answer = advisor.consult(question, self.config)
|
|
1569
1572
|
self.call_from_thread(self._deliver_advice, question, answer, inject)
|
|
1570
1573
|
|
|
@@ -7,7 +7,7 @@ build-backend = "setuptools.build_meta"
|
|
|
7
7
|
# PyPI distribution name is drydock-cli (the established install name, continued
|
|
8
8
|
# from the retired v2 fork); the import package + CLI command stay `drydock`.
|
|
9
9
|
name = "drydock-cli"
|
|
10
|
-
version = "3.1.
|
|
10
|
+
version = "3.1.33"
|
|
11
11
|
description = "Drydock — a local, provider-agnostic terminal coding agent for local LLMs"
|
|
12
12
|
readme = "README.md"
|
|
13
13
|
requires-python = ">=3.11"
|
|
@@ -115,31 +115,33 @@ def test_recent_context_handles_multimodal_blocks():
|
|
|
115
115
|
assert "look at this" in advisor.recent_context(msgs)
|
|
116
116
|
|
|
117
117
|
|
|
118
|
-
def
|
|
119
|
-
|
|
118
|
+
def test_build_brief_combines_transcript_and_context():
|
|
119
|
+
cfg = {"_recent_messages": [
|
|
120
|
+
{"role": "tool", "content": "FAILED test_reconnect - state lost after reconnect"},
|
|
121
|
+
{"role": "assistant", "content": "Trying a lock around the queue."},
|
|
122
|
+
]}
|
|
123
|
+
brief = advisor.build_brief(cfg, "my hand-written context")
|
|
124
|
+
assert "FAILED test_reconnect" in brief and "lock around the queue" in brief
|
|
125
|
+
assert "my hand-written context" in brief
|
|
126
|
+
assert "RECENT ACTIVITY" in brief and "CONTEXT" in brief
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
def test_consult_briefs_advisor_from_transcript_even_with_no_context(monkeypatch):
|
|
130
|
+
# the whole point: a bare question still reaches the advisor WITH the recent transcript
|
|
120
131
|
captured = {}
|
|
121
|
-
monkeypatch.setattr(advisor, "
|
|
122
|
-
lambda q, cfg, context="": captured.update(
|
|
123
|
-
cfg = {
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
T.tool_consult({"question": "why does reconnect lose state?"}, cfg)
|
|
132
|
-
assert "FAILED test_reconnect" in captured["context"] # advisor now sees the error
|
|
133
|
-
assert "lock around the queue" in captured["context"]
|
|
134
|
-
assert "Recent activity" in captured["context"]
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
def test_consult_tool_keeps_model_context_and_adds_recent(monkeypatch):
|
|
132
|
+
monkeypatch.setattr(advisor, "_call",
|
|
133
|
+
lambda q, cfg, context="", **k: captured.update(q=q, context=context) or "ok")
|
|
134
|
+
cfg = {"advisor_base_url": "http://b/v1", "advisor_model": "m",
|
|
135
|
+
"_recent_messages": [{"role": "tool", "content": "FAILED test_x - AssertionError"}]}
|
|
136
|
+
advisor.consult("why is this failing?", cfg) # no context passed
|
|
137
|
+
assert "FAILED test_x" in captured["context"] # transcript auto-attached
|
|
138
|
+
assert captured["q"] == "why is this failing?"
|
|
139
|
+
|
|
140
|
+
|
|
141
|
+
def test_consult_tool_delegates_to_consult(monkeypatch):
|
|
138
142
|
from drydock import tools as T
|
|
139
143
|
captured = {}
|
|
140
144
|
monkeypatch.setattr(advisor, "consult",
|
|
141
|
-
lambda q, cfg, context="": captured.update(context=context) or "ok")
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
T.tool_consult({"question": "help", "context": "my hand-written context"}, cfg)
|
|
145
|
-
assert "my hand-written context" in captured["context"] and "ERR: boom" in captured["context"]
|
|
145
|
+
lambda q, cfg, context="": captured.update(q=q, context=context) or "ok")
|
|
146
|
+
T.tool_consult({"question": "help", "context": "hand-written"}, {"advisor_model": "m"})
|
|
147
|
+
assert captured["q"] == "help" and captured["context"] == "hand-written"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|