drydock-cli 3.0.120__tar.gz → 3.0.121__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.0.120/drydock_cli.egg-info → drydock_cli-3.0.121}/PKG-INFO +1 -1
- {drydock_cli-3.0.120 → drydock_cli-3.0.121}/drydock/recipes.py +2 -0
- {drydock_cli-3.0.120 → drydock_cli-3.0.121}/drydock/tools/__init__.py +4 -0
- {drydock_cli-3.0.120 → drydock_cli-3.0.121/drydock_cli.egg-info}/PKG-INFO +1 -1
- {drydock_cli-3.0.120 → drydock_cli-3.0.121}/pyproject.toml +1 -1
- {drydock_cli-3.0.120 → drydock_cli-3.0.121}/tests/test_recipes.py +7 -0
- {drydock_cli-3.0.120 → drydock_cli-3.0.121}/tests/test_screenshot.py +12 -0
- {drydock_cli-3.0.120 → drydock_cli-3.0.121}/tests/test_skills.py +5 -1
- {drydock_cli-3.0.120 → drydock_cli-3.0.121}/LICENSE +0 -0
- {drydock_cli-3.0.120 → drydock_cli-3.0.121}/NOTICE +0 -0
- {drydock_cli-3.0.120 → drydock_cli-3.0.121}/README.md +0 -0
- {drydock_cli-3.0.120 → drydock_cli-3.0.121}/drydock/__init__.py +0 -0
- {drydock_cli-3.0.120 → drydock_cli-3.0.121}/drydock/__main__.py +0 -0
- {drydock_cli-3.0.120 → drydock_cli-3.0.121}/drydock/advisor.py +0 -0
- {drydock_cli-3.0.120 → drydock_cli-3.0.121}/drydock/agent.py +0 -0
- {drydock_cli-3.0.120 → drydock_cli-3.0.121}/drydock/bash_safety.py +0 -0
- {drydock_cli-3.0.120 → drydock_cli-3.0.121}/drydock/builtin_skills/__init__.py +0 -0
- {drydock_cli-3.0.120 → drydock_cli-3.0.121}/drydock/builtin_skills/ml-data.md +0 -0
- {drydock_cli-3.0.120 → drydock_cli-3.0.121}/drydock/builtin_skills/ml-debug.md +0 -0
- {drydock_cli-3.0.120 → drydock_cli-3.0.121}/drydock/builtin_skills/ml-finetune.md +0 -0
- {drydock_cli-3.0.120 → drydock_cli-3.0.121}/drydock/builtin_skills/ml-metrics.md +0 -0
- {drydock_cli-3.0.120 → drydock_cli-3.0.121}/drydock/builtin_skills/ml-rl.md +0 -0
- {drydock_cli-3.0.120 → drydock_cli-3.0.121}/drydock/builtin_skills/ml-train.md +0 -0
- {drydock_cli-3.0.120 → drydock_cli-3.0.121}/drydock/builtin_skills/rmf-categorize.md +0 -0
- {drydock_cli-3.0.120 → drydock_cli-3.0.121}/drydock/builtin_skills/rmf-control.md +0 -0
- {drydock_cli-3.0.120 → drydock_cli-3.0.121}/drydock/builtin_skills/rmf-poam.md +0 -0
- {drydock_cli-3.0.120 → drydock_cli-3.0.121}/drydock/builtin_skills/rmf-review.md +0 -0
- {drydock_cli-3.0.120 → drydock_cli-3.0.121}/drydock/builtin_skills/stig-assess.md +0 -0
- {drydock_cli-3.0.120 → drydock_cli-3.0.121}/drydock/builtin_skills/stig-remediate.md +0 -0
- {drydock_cli-3.0.120 → drydock_cli-3.0.121}/drydock/cci.py +0 -0
- {drydock_cli-3.0.120 → drydock_cli-3.0.121}/drydock/cli.py +0 -0
- {drydock_cli-3.0.120 → drydock_cli-3.0.121}/drydock/compaction.py +0 -0
- {drydock_cli-3.0.120 → drydock_cli-3.0.121}/drydock/config.py +0 -0
- {drydock_cli-3.0.120 → drydock_cli-3.0.121}/drydock/detect.py +0 -0
- {drydock_cli-3.0.120 → drydock_cli-3.0.121}/drydock/extract.py +0 -0
- {drydock_cli-3.0.120 → drydock_cli-3.0.121}/drydock/gittools.py +0 -0
- {drydock_cli-3.0.120 → drydock_cli-3.0.121}/drydock/graphrag.py +0 -0
- {drydock_cli-3.0.120 → drydock_cli-3.0.121}/drydock/guards.py +0 -0
- {drydock_cli-3.0.120 → drydock_cli-3.0.121}/drydock/loop_detect.py +0 -0
- {drydock_cli-3.0.120 → drydock_cli-3.0.121}/drydock/mcp.py +0 -0
- {drydock_cli-3.0.120 → drydock_cli-3.0.121}/drydock/poam.py +0 -0
- {drydock_cli-3.0.120 → drydock_cli-3.0.121}/drydock/providers.py +0 -0
- {drydock_cli-3.0.120 → drydock_cli-3.0.121}/drydock/rmf.py +0 -0
- {drydock_cli-3.0.120 → drydock_cli-3.0.121}/drydock/rmf_graph.py +0 -0
- {drydock_cli-3.0.120 → drydock_cli-3.0.121}/drydock/skills.py +0 -0
- {drydock_cli-3.0.120 → drydock_cli-3.0.121}/drydock/stig.py +0 -0
- {drydock_cli-3.0.120 → drydock_cli-3.0.121}/drydock/suggest.py +0 -0
- {drydock_cli-3.0.120 → drydock_cli-3.0.121}/drydock/tool_registry.py +0 -0
- {drydock_cli-3.0.120 → drydock_cli-3.0.121}/drydock/tui/__init__.py +0 -0
- {drydock_cli-3.0.120 → drydock_cli-3.0.121}/drydock/tui/app.py +0 -0
- {drydock_cli-3.0.120 → drydock_cli-3.0.121}/drydock/tui/approval.py +0 -0
- {drydock_cli-3.0.120 → drydock_cli-3.0.121}/drydock/tui/messages.py +0 -0
- {drydock_cli-3.0.120 → drydock_cli-3.0.121}/drydock/tui/widgets.py +0 -0
- {drydock_cli-3.0.120 → drydock_cli-3.0.121}/drydock/tuning.py +0 -0
- {drydock_cli-3.0.120 → drydock_cli-3.0.121}/drydock/web.py +0 -0
- {drydock_cli-3.0.120 → drydock_cli-3.0.121}/drydock_cli.egg-info/SOURCES.txt +0 -0
- {drydock_cli-3.0.120 → drydock_cli-3.0.121}/drydock_cli.egg-info/dependency_links.txt +0 -0
- {drydock_cli-3.0.120 → drydock_cli-3.0.121}/drydock_cli.egg-info/entry_points.txt +0 -0
- {drydock_cli-3.0.120 → drydock_cli-3.0.121}/drydock_cli.egg-info/requires.txt +0 -0
- {drydock_cli-3.0.120 → drydock_cli-3.0.121}/drydock_cli.egg-info/top_level.txt +0 -0
- {drydock_cli-3.0.120 → drydock_cli-3.0.121}/setup.cfg +0 -0
- {drydock_cli-3.0.120 → drydock_cli-3.0.121}/tests/test_advisor.py +0 -0
- {drydock_cli-3.0.120 → drydock_cli-3.0.121}/tests/test_approval.py +0 -0
- {drydock_cli-3.0.120 → drydock_cli-3.0.121}/tests/test_back_command.py +0 -0
- {drydock_cli-3.0.120 → drydock_cli-3.0.121}/tests/test_bash_background.py +0 -0
- {drydock_cli-3.0.120 → drydock_cli-3.0.121}/tests/test_bash_binary_output.py +0 -0
- {drydock_cli-3.0.120 → drydock_cli-3.0.121}/tests/test_bash_crossplatform.py +0 -0
- {drydock_cli-3.0.120 → drydock_cli-3.0.121}/tests/test_bash_output_bounding.py +0 -0
- {drydock_cli-3.0.120 → drydock_cli-3.0.121}/tests/test_bash_process_group.py +0 -0
- {drydock_cli-3.0.120 → drydock_cli-3.0.121}/tests/test_bash_safety.py +0 -0
- {drydock_cli-3.0.120 → drydock_cli-3.0.121}/tests/test_bash_sanitize.py +0 -0
- {drydock_cli-3.0.120 → drydock_cli-3.0.121}/tests/test_bash_shell.py +0 -0
- {drydock_cli-3.0.120 → drydock_cli-3.0.121}/tests/test_bash_stdin.py +0 -0
- {drydock_cli-3.0.120 → drydock_cli-3.0.121}/tests/test_bash_stop_partial.py +0 -0
- {drydock_cli-3.0.120 → drydock_cli-3.0.121}/tests/test_bash_timeout_network.py +0 -0
- {drydock_cli-3.0.120 → drydock_cli-3.0.121}/tests/test_bash_timeout_param.py +0 -0
- {drydock_cli-3.0.120 → drydock_cli-3.0.121}/tests/test_cci.py +0 -0
- {drydock_cli-3.0.120 → drydock_cli-3.0.121}/tests/test_cli_agents.py +0 -0
- {drydock_cli-3.0.120 → drydock_cli-3.0.121}/tests/test_compact_command.py +0 -0
- {drydock_cli-3.0.120 → drydock_cli-3.0.121}/tests/test_compaction.py +0 -0
- {drydock_cli-3.0.120 → drydock_cli-3.0.121}/tests/test_config.py +0 -0
- {drydock_cli-3.0.120 → drydock_cli-3.0.121}/tests/test_config_migration.py +0 -0
- {drydock_cli-3.0.120 → drydock_cli-3.0.121}/tests/test_context_limit_config.py +0 -0
- {drydock_cli-3.0.120 → drydock_cli-3.0.121}/tests/test_detect.py +0 -0
- {drydock_cli-3.0.120 → drydock_cli-3.0.121}/tests/test_dispatch.py +0 -0
- {drydock_cli-3.0.120 → drydock_cli-3.0.121}/tests/test_e2e_connected.py +0 -0
- {drydock_cli-3.0.120 → drydock_cli-3.0.121}/tests/test_edit_replace_all.py +0 -0
- {drydock_cli-3.0.120 → drydock_cli-3.0.121}/tests/test_empty_response.py +0 -0
- {drydock_cli-3.0.120 → drydock_cli-3.0.121}/tests/test_extract.py +0 -0
- {drydock_cli-3.0.120 → drydock_cli-3.0.121}/tests/test_failure_loop.py +0 -0
- {drydock_cli-3.0.120 → drydock_cli-3.0.121}/tests/test_first_run_setup.py +0 -0
- {drydock_cli-3.0.120 → drydock_cli-3.0.121}/tests/test_gittools.py +0 -0
- {drydock_cli-3.0.120 → drydock_cli-3.0.121}/tests/test_glob_edit_edges.py +0 -0
- {drydock_cli-3.0.120 → drydock_cli-3.0.121}/tests/test_graphify_example.py +0 -0
- {drydock_cli-3.0.120 → drydock_cli-3.0.121}/tests/test_graphrag.py +0 -0
- {drydock_cli-3.0.120 → drydock_cli-3.0.121}/tests/test_graphrag_quoted_path.py +0 -0
- {drydock_cli-3.0.120 → drydock_cli-3.0.121}/tests/test_grep_and_read_robust.py +0 -0
- {drydock_cli-3.0.120 → drydock_cli-3.0.121}/tests/test_guards_and_tools.py +0 -0
- {drydock_cli-3.0.120 → drydock_cli-3.0.121}/tests/test_hallucinated_tools.py +0 -0
- {drydock_cli-3.0.120 → drydock_cli-3.0.121}/tests/test_leaked_tool_call.py +0 -0
- {drydock_cli-3.0.120 → drydock_cli-3.0.121}/tests/test_loop_detect.py +0 -0
- {drydock_cli-3.0.120 → drydock_cli-3.0.121}/tests/test_mcp.py +0 -0
- {drydock_cli-3.0.120 → drydock_cli-3.0.121}/tests/test_oneshot_unreachable.py +0 -0
- {drydock_cli-3.0.120 → drydock_cli-3.0.121}/tests/test_overthink_interrupt.py +0 -0
- {drydock_cli-3.0.120 → drydock_cli-3.0.121}/tests/test_plan_autocontinue.py +0 -0
- {drydock_cli-3.0.120 → drydock_cli-3.0.121}/tests/test_poam.py +0 -0
- {drydock_cli-3.0.120 → drydock_cli-3.0.121}/tests/test_providers_unreachable.py +0 -0
- {drydock_cli-3.0.120 → drydock_cli-3.0.121}/tests/test_read_index.py +0 -0
- {drydock_cli-3.0.120 → drydock_cli-3.0.121}/tests/test_repetition_interrupt.py +0 -0
- {drydock_cli-3.0.120 → drydock_cli-3.0.121}/tests/test_rmf.py +0 -0
- {drydock_cli-3.0.120 → drydock_cli-3.0.121}/tests/test_rmf_graph.py +0 -0
- {drydock_cli-3.0.120 → drydock_cli-3.0.121}/tests/test_rmf_stig_graph.py +0 -0
- {drydock_cli-3.0.120 → drydock_cli-3.0.121}/tests/test_runaway_repetition.py +0 -0
- {drydock_cli-3.0.120 → drydock_cli-3.0.121}/tests/test_server_probe.py +0 -0
- {drydock_cli-3.0.120 → drydock_cli-3.0.121}/tests/test_stall_retry.py +0 -0
- {drydock_cli-3.0.120 → drydock_cli-3.0.121}/tests/test_stig.py +0 -0
- {drydock_cli-3.0.120 → drydock_cli-3.0.121}/tests/test_stop.py +0 -0
- {drydock_cli-3.0.120 → drydock_cli-3.0.121}/tests/test_streaming_newlines.py +0 -0
- {drydock_cli-3.0.120 → drydock_cli-3.0.121}/tests/test_subagent.py +0 -0
- {drydock_cli-3.0.120 → drydock_cli-3.0.121}/tests/test_suggest.py +0 -0
- {drydock_cli-3.0.120 → drydock_cli-3.0.121}/tests/test_system_prompt_help.py +0 -0
- {drydock_cli-3.0.120 → drydock_cli-3.0.121}/tests/test_todo.py +0 -0
- {drydock_cli-3.0.120 → drydock_cli-3.0.121}/tests/test_tool_arg_coercion.py +0 -0
- {drydock_cli-3.0.120 → drydock_cli-3.0.121}/tests/test_tool_arg_coercion_more.py +0 -0
- {drydock_cli-3.0.120 → drydock_cli-3.0.121}/tests/test_tool_arg_parsing.py +0 -0
- {drydock_cli-3.0.120 → drydock_cli-3.0.121}/tests/test_tools_undo.py +0 -0
- {drydock_cli-3.0.120 → drydock_cli-3.0.121}/tests/test_tui.py +0 -0
- {drydock_cli-3.0.120 → drydock_cli-3.0.121}/tests/test_tuning.py +0 -0
- {drydock_cli-3.0.120 → drydock_cli-3.0.121}/tests/test_viewimage.py +0 -0
- {drydock_cli-3.0.120 → drydock_cli-3.0.121}/tests/test_vision_input.py +0 -0
- {drydock_cli-3.0.120 → drydock_cli-3.0.121}/tests/test_web_tools.py +0 -0
- {drydock_cli-3.0.120 → drydock_cli-3.0.121}/tests/test_windows_shell.py +0 -0
- {drydock_cli-3.0.120 → drydock_cli-3.0.121}/tests/test_write_content_coerce.py +0 -0
- {drydock_cli-3.0.120 → drydock_cli-3.0.121}/tests/test_xccdf.py +0 -0
|
@@ -274,6 +274,8 @@ def retrieve_recipes(task_text: str, k: int = 2) -> list[tuple[str, str]]:
|
|
|
274
274
|
overlap. Empty if nothing scores — never inject irrelevant noise."""
|
|
275
275
|
if not task_text:
|
|
276
276
|
return []
|
|
277
|
+
if not isinstance(task_text, str): # defensive: never crash the agent loop
|
|
278
|
+
task_text = str(task_text)
|
|
277
279
|
words = set(_WORD.findall(task_text.lower()))
|
|
278
280
|
scored = []
|
|
279
281
|
for title, keywords, body in RECIPES:
|
|
@@ -750,6 +750,10 @@ def _capture_screen(out: str) -> str | None:
|
|
|
750
750
|
elif sys.platform == "darwin":
|
|
751
751
|
subprocess.run(["screencapture", "-x", out], capture_output=True, timeout=30)
|
|
752
752
|
else: # Linux/BSD — try grabbers in order of ubiquity (X11 + wayland)
|
|
753
|
+
if not (os.environ.get("DISPLAY") or os.environ.get("WAYLAND_DISPLAY")):
|
|
754
|
+
# Fail fast — a grabber on a headless box blocks until timeout.
|
|
755
|
+
return ("no display ($DISPLAY/$WAYLAND_DISPLAY unset) — cannot capture "
|
|
756
|
+
"the screen on a headless server.")
|
|
753
757
|
grabbers = (["scrot", "-o", out], ["import", "-window", "root", out],
|
|
754
758
|
["gnome-screenshot", "-f", out], ["grim", out],
|
|
755
759
|
["spectacle", "-b", "-n", "-o", out], ["maim", out])
|
|
@@ -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.0.
|
|
10
|
+
version = "3.0.121"
|
|
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"
|
|
@@ -61,3 +61,10 @@ def test_ml_skills_bundled():
|
|
|
61
61
|
for name in ("ml-train", "ml-metrics", "ml-finetune", "ml-debug", "ml-rl", "ml-data"):
|
|
62
62
|
assert name in sk, f"bundled ML skill /{name} missing"
|
|
63
63
|
assert "MCC" in sk["ml-metrics"].body or "mcc" in sk["ml-metrics"].body.lower()
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
def test_retrieve_handles_non_string():
|
|
67
|
+
from drydock.recipes import retrieve_recipes, recipe_context
|
|
68
|
+
for v in (b"train a cnn", ["train", "cnn"], 5, None):
|
|
69
|
+
assert isinstance(retrieve_recipes(v), list) # never raises
|
|
70
|
+
assert isinstance(recipe_context(123), str)
|
|
@@ -57,3 +57,15 @@ def test_macos_uses_screencapture(monkeypatch):
|
|
|
57
57
|
monkeypatch.setattr("subprocess.run", lambda a, **k: calls.setdefault("argv", a))
|
|
58
58
|
tools._capture_screen("/tmp/x.png")
|
|
59
59
|
assert calls["argv"][0] == "screencapture"
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
def test_headless_linux_fails_fast(monkeypatch):
|
|
63
|
+
import time
|
|
64
|
+
monkeypatch.setattr(tools, "_IS_WINDOWS", False)
|
|
65
|
+
monkeypatch.setattr("sys.platform", "linux")
|
|
66
|
+
monkeypatch.delenv("DISPLAY", raising=False)
|
|
67
|
+
monkeypatch.delenv("WAYLAND_DISPLAY", raising=False)
|
|
68
|
+
t = time.time()
|
|
69
|
+
err = tools._capture_screen("/tmp/x.png")
|
|
70
|
+
assert time.time() - t < 1.0 # no 30s grabber hang
|
|
71
|
+
assert err and "display" in err.lower()
|
|
@@ -55,7 +55,11 @@ def test_empty_body_skipped(tmp_path):
|
|
|
55
55
|
def test_no_user_or_project_skills_yields_only_builtins(tmp_path):
|
|
56
56
|
# With no user/project skills, only the bundled built-ins (RMF) are present.
|
|
57
57
|
loaded = skills.load_skills(str(tmp_path))
|
|
58
|
-
assert set(loaded) == {
|
|
58
|
+
assert set(loaded) == {
|
|
59
|
+
"rmf-control", "rmf-categorize", "rmf-review", "rmf-poam",
|
|
60
|
+
"stig-assess", "stig-remediate",
|
|
61
|
+
"ml-train", "ml-metrics", "ml-finetune", "ml-debug", "ml-rl", "ml-data",
|
|
62
|
+
}
|
|
59
63
|
|
|
60
64
|
|
|
61
65
|
def test_create_skill_user_scope(tmp_path, monkeypatch):
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|