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.
Files changed (134) hide show
  1. {drydock_cli-3.0.120/drydock_cli.egg-info → drydock_cli-3.0.121}/PKG-INFO +1 -1
  2. {drydock_cli-3.0.120 → drydock_cli-3.0.121}/drydock/recipes.py +2 -0
  3. {drydock_cli-3.0.120 → drydock_cli-3.0.121}/drydock/tools/__init__.py +4 -0
  4. {drydock_cli-3.0.120 → drydock_cli-3.0.121/drydock_cli.egg-info}/PKG-INFO +1 -1
  5. {drydock_cli-3.0.120 → drydock_cli-3.0.121}/pyproject.toml +1 -1
  6. {drydock_cli-3.0.120 → drydock_cli-3.0.121}/tests/test_recipes.py +7 -0
  7. {drydock_cli-3.0.120 → drydock_cli-3.0.121}/tests/test_screenshot.py +12 -0
  8. {drydock_cli-3.0.120 → drydock_cli-3.0.121}/tests/test_skills.py +5 -1
  9. {drydock_cli-3.0.120 → drydock_cli-3.0.121}/LICENSE +0 -0
  10. {drydock_cli-3.0.120 → drydock_cli-3.0.121}/NOTICE +0 -0
  11. {drydock_cli-3.0.120 → drydock_cli-3.0.121}/README.md +0 -0
  12. {drydock_cli-3.0.120 → drydock_cli-3.0.121}/drydock/__init__.py +0 -0
  13. {drydock_cli-3.0.120 → drydock_cli-3.0.121}/drydock/__main__.py +0 -0
  14. {drydock_cli-3.0.120 → drydock_cli-3.0.121}/drydock/advisor.py +0 -0
  15. {drydock_cli-3.0.120 → drydock_cli-3.0.121}/drydock/agent.py +0 -0
  16. {drydock_cli-3.0.120 → drydock_cli-3.0.121}/drydock/bash_safety.py +0 -0
  17. {drydock_cli-3.0.120 → drydock_cli-3.0.121}/drydock/builtin_skills/__init__.py +0 -0
  18. {drydock_cli-3.0.120 → drydock_cli-3.0.121}/drydock/builtin_skills/ml-data.md +0 -0
  19. {drydock_cli-3.0.120 → drydock_cli-3.0.121}/drydock/builtin_skills/ml-debug.md +0 -0
  20. {drydock_cli-3.0.120 → drydock_cli-3.0.121}/drydock/builtin_skills/ml-finetune.md +0 -0
  21. {drydock_cli-3.0.120 → drydock_cli-3.0.121}/drydock/builtin_skills/ml-metrics.md +0 -0
  22. {drydock_cli-3.0.120 → drydock_cli-3.0.121}/drydock/builtin_skills/ml-rl.md +0 -0
  23. {drydock_cli-3.0.120 → drydock_cli-3.0.121}/drydock/builtin_skills/ml-train.md +0 -0
  24. {drydock_cli-3.0.120 → drydock_cli-3.0.121}/drydock/builtin_skills/rmf-categorize.md +0 -0
  25. {drydock_cli-3.0.120 → drydock_cli-3.0.121}/drydock/builtin_skills/rmf-control.md +0 -0
  26. {drydock_cli-3.0.120 → drydock_cli-3.0.121}/drydock/builtin_skills/rmf-poam.md +0 -0
  27. {drydock_cli-3.0.120 → drydock_cli-3.0.121}/drydock/builtin_skills/rmf-review.md +0 -0
  28. {drydock_cli-3.0.120 → drydock_cli-3.0.121}/drydock/builtin_skills/stig-assess.md +0 -0
  29. {drydock_cli-3.0.120 → drydock_cli-3.0.121}/drydock/builtin_skills/stig-remediate.md +0 -0
  30. {drydock_cli-3.0.120 → drydock_cli-3.0.121}/drydock/cci.py +0 -0
  31. {drydock_cli-3.0.120 → drydock_cli-3.0.121}/drydock/cli.py +0 -0
  32. {drydock_cli-3.0.120 → drydock_cli-3.0.121}/drydock/compaction.py +0 -0
  33. {drydock_cli-3.0.120 → drydock_cli-3.0.121}/drydock/config.py +0 -0
  34. {drydock_cli-3.0.120 → drydock_cli-3.0.121}/drydock/detect.py +0 -0
  35. {drydock_cli-3.0.120 → drydock_cli-3.0.121}/drydock/extract.py +0 -0
  36. {drydock_cli-3.0.120 → drydock_cli-3.0.121}/drydock/gittools.py +0 -0
  37. {drydock_cli-3.0.120 → drydock_cli-3.0.121}/drydock/graphrag.py +0 -0
  38. {drydock_cli-3.0.120 → drydock_cli-3.0.121}/drydock/guards.py +0 -0
  39. {drydock_cli-3.0.120 → drydock_cli-3.0.121}/drydock/loop_detect.py +0 -0
  40. {drydock_cli-3.0.120 → drydock_cli-3.0.121}/drydock/mcp.py +0 -0
  41. {drydock_cli-3.0.120 → drydock_cli-3.0.121}/drydock/poam.py +0 -0
  42. {drydock_cli-3.0.120 → drydock_cli-3.0.121}/drydock/providers.py +0 -0
  43. {drydock_cli-3.0.120 → drydock_cli-3.0.121}/drydock/rmf.py +0 -0
  44. {drydock_cli-3.0.120 → drydock_cli-3.0.121}/drydock/rmf_graph.py +0 -0
  45. {drydock_cli-3.0.120 → drydock_cli-3.0.121}/drydock/skills.py +0 -0
  46. {drydock_cli-3.0.120 → drydock_cli-3.0.121}/drydock/stig.py +0 -0
  47. {drydock_cli-3.0.120 → drydock_cli-3.0.121}/drydock/suggest.py +0 -0
  48. {drydock_cli-3.0.120 → drydock_cli-3.0.121}/drydock/tool_registry.py +0 -0
  49. {drydock_cli-3.0.120 → drydock_cli-3.0.121}/drydock/tui/__init__.py +0 -0
  50. {drydock_cli-3.0.120 → drydock_cli-3.0.121}/drydock/tui/app.py +0 -0
  51. {drydock_cli-3.0.120 → drydock_cli-3.0.121}/drydock/tui/approval.py +0 -0
  52. {drydock_cli-3.0.120 → drydock_cli-3.0.121}/drydock/tui/messages.py +0 -0
  53. {drydock_cli-3.0.120 → drydock_cli-3.0.121}/drydock/tui/widgets.py +0 -0
  54. {drydock_cli-3.0.120 → drydock_cli-3.0.121}/drydock/tuning.py +0 -0
  55. {drydock_cli-3.0.120 → drydock_cli-3.0.121}/drydock/web.py +0 -0
  56. {drydock_cli-3.0.120 → drydock_cli-3.0.121}/drydock_cli.egg-info/SOURCES.txt +0 -0
  57. {drydock_cli-3.0.120 → drydock_cli-3.0.121}/drydock_cli.egg-info/dependency_links.txt +0 -0
  58. {drydock_cli-3.0.120 → drydock_cli-3.0.121}/drydock_cli.egg-info/entry_points.txt +0 -0
  59. {drydock_cli-3.0.120 → drydock_cli-3.0.121}/drydock_cli.egg-info/requires.txt +0 -0
  60. {drydock_cli-3.0.120 → drydock_cli-3.0.121}/drydock_cli.egg-info/top_level.txt +0 -0
  61. {drydock_cli-3.0.120 → drydock_cli-3.0.121}/setup.cfg +0 -0
  62. {drydock_cli-3.0.120 → drydock_cli-3.0.121}/tests/test_advisor.py +0 -0
  63. {drydock_cli-3.0.120 → drydock_cli-3.0.121}/tests/test_approval.py +0 -0
  64. {drydock_cli-3.0.120 → drydock_cli-3.0.121}/tests/test_back_command.py +0 -0
  65. {drydock_cli-3.0.120 → drydock_cli-3.0.121}/tests/test_bash_background.py +0 -0
  66. {drydock_cli-3.0.120 → drydock_cli-3.0.121}/tests/test_bash_binary_output.py +0 -0
  67. {drydock_cli-3.0.120 → drydock_cli-3.0.121}/tests/test_bash_crossplatform.py +0 -0
  68. {drydock_cli-3.0.120 → drydock_cli-3.0.121}/tests/test_bash_output_bounding.py +0 -0
  69. {drydock_cli-3.0.120 → drydock_cli-3.0.121}/tests/test_bash_process_group.py +0 -0
  70. {drydock_cli-3.0.120 → drydock_cli-3.0.121}/tests/test_bash_safety.py +0 -0
  71. {drydock_cli-3.0.120 → drydock_cli-3.0.121}/tests/test_bash_sanitize.py +0 -0
  72. {drydock_cli-3.0.120 → drydock_cli-3.0.121}/tests/test_bash_shell.py +0 -0
  73. {drydock_cli-3.0.120 → drydock_cli-3.0.121}/tests/test_bash_stdin.py +0 -0
  74. {drydock_cli-3.0.120 → drydock_cli-3.0.121}/tests/test_bash_stop_partial.py +0 -0
  75. {drydock_cli-3.0.120 → drydock_cli-3.0.121}/tests/test_bash_timeout_network.py +0 -0
  76. {drydock_cli-3.0.120 → drydock_cli-3.0.121}/tests/test_bash_timeout_param.py +0 -0
  77. {drydock_cli-3.0.120 → drydock_cli-3.0.121}/tests/test_cci.py +0 -0
  78. {drydock_cli-3.0.120 → drydock_cli-3.0.121}/tests/test_cli_agents.py +0 -0
  79. {drydock_cli-3.0.120 → drydock_cli-3.0.121}/tests/test_compact_command.py +0 -0
  80. {drydock_cli-3.0.120 → drydock_cli-3.0.121}/tests/test_compaction.py +0 -0
  81. {drydock_cli-3.0.120 → drydock_cli-3.0.121}/tests/test_config.py +0 -0
  82. {drydock_cli-3.0.120 → drydock_cli-3.0.121}/tests/test_config_migration.py +0 -0
  83. {drydock_cli-3.0.120 → drydock_cli-3.0.121}/tests/test_context_limit_config.py +0 -0
  84. {drydock_cli-3.0.120 → drydock_cli-3.0.121}/tests/test_detect.py +0 -0
  85. {drydock_cli-3.0.120 → drydock_cli-3.0.121}/tests/test_dispatch.py +0 -0
  86. {drydock_cli-3.0.120 → drydock_cli-3.0.121}/tests/test_e2e_connected.py +0 -0
  87. {drydock_cli-3.0.120 → drydock_cli-3.0.121}/tests/test_edit_replace_all.py +0 -0
  88. {drydock_cli-3.0.120 → drydock_cli-3.0.121}/tests/test_empty_response.py +0 -0
  89. {drydock_cli-3.0.120 → drydock_cli-3.0.121}/tests/test_extract.py +0 -0
  90. {drydock_cli-3.0.120 → drydock_cli-3.0.121}/tests/test_failure_loop.py +0 -0
  91. {drydock_cli-3.0.120 → drydock_cli-3.0.121}/tests/test_first_run_setup.py +0 -0
  92. {drydock_cli-3.0.120 → drydock_cli-3.0.121}/tests/test_gittools.py +0 -0
  93. {drydock_cli-3.0.120 → drydock_cli-3.0.121}/tests/test_glob_edit_edges.py +0 -0
  94. {drydock_cli-3.0.120 → drydock_cli-3.0.121}/tests/test_graphify_example.py +0 -0
  95. {drydock_cli-3.0.120 → drydock_cli-3.0.121}/tests/test_graphrag.py +0 -0
  96. {drydock_cli-3.0.120 → drydock_cli-3.0.121}/tests/test_graphrag_quoted_path.py +0 -0
  97. {drydock_cli-3.0.120 → drydock_cli-3.0.121}/tests/test_grep_and_read_robust.py +0 -0
  98. {drydock_cli-3.0.120 → drydock_cli-3.0.121}/tests/test_guards_and_tools.py +0 -0
  99. {drydock_cli-3.0.120 → drydock_cli-3.0.121}/tests/test_hallucinated_tools.py +0 -0
  100. {drydock_cli-3.0.120 → drydock_cli-3.0.121}/tests/test_leaked_tool_call.py +0 -0
  101. {drydock_cli-3.0.120 → drydock_cli-3.0.121}/tests/test_loop_detect.py +0 -0
  102. {drydock_cli-3.0.120 → drydock_cli-3.0.121}/tests/test_mcp.py +0 -0
  103. {drydock_cli-3.0.120 → drydock_cli-3.0.121}/tests/test_oneshot_unreachable.py +0 -0
  104. {drydock_cli-3.0.120 → drydock_cli-3.0.121}/tests/test_overthink_interrupt.py +0 -0
  105. {drydock_cli-3.0.120 → drydock_cli-3.0.121}/tests/test_plan_autocontinue.py +0 -0
  106. {drydock_cli-3.0.120 → drydock_cli-3.0.121}/tests/test_poam.py +0 -0
  107. {drydock_cli-3.0.120 → drydock_cli-3.0.121}/tests/test_providers_unreachable.py +0 -0
  108. {drydock_cli-3.0.120 → drydock_cli-3.0.121}/tests/test_read_index.py +0 -0
  109. {drydock_cli-3.0.120 → drydock_cli-3.0.121}/tests/test_repetition_interrupt.py +0 -0
  110. {drydock_cli-3.0.120 → drydock_cli-3.0.121}/tests/test_rmf.py +0 -0
  111. {drydock_cli-3.0.120 → drydock_cli-3.0.121}/tests/test_rmf_graph.py +0 -0
  112. {drydock_cli-3.0.120 → drydock_cli-3.0.121}/tests/test_rmf_stig_graph.py +0 -0
  113. {drydock_cli-3.0.120 → drydock_cli-3.0.121}/tests/test_runaway_repetition.py +0 -0
  114. {drydock_cli-3.0.120 → drydock_cli-3.0.121}/tests/test_server_probe.py +0 -0
  115. {drydock_cli-3.0.120 → drydock_cli-3.0.121}/tests/test_stall_retry.py +0 -0
  116. {drydock_cli-3.0.120 → drydock_cli-3.0.121}/tests/test_stig.py +0 -0
  117. {drydock_cli-3.0.120 → drydock_cli-3.0.121}/tests/test_stop.py +0 -0
  118. {drydock_cli-3.0.120 → drydock_cli-3.0.121}/tests/test_streaming_newlines.py +0 -0
  119. {drydock_cli-3.0.120 → drydock_cli-3.0.121}/tests/test_subagent.py +0 -0
  120. {drydock_cli-3.0.120 → drydock_cli-3.0.121}/tests/test_suggest.py +0 -0
  121. {drydock_cli-3.0.120 → drydock_cli-3.0.121}/tests/test_system_prompt_help.py +0 -0
  122. {drydock_cli-3.0.120 → drydock_cli-3.0.121}/tests/test_todo.py +0 -0
  123. {drydock_cli-3.0.120 → drydock_cli-3.0.121}/tests/test_tool_arg_coercion.py +0 -0
  124. {drydock_cli-3.0.120 → drydock_cli-3.0.121}/tests/test_tool_arg_coercion_more.py +0 -0
  125. {drydock_cli-3.0.120 → drydock_cli-3.0.121}/tests/test_tool_arg_parsing.py +0 -0
  126. {drydock_cli-3.0.120 → drydock_cli-3.0.121}/tests/test_tools_undo.py +0 -0
  127. {drydock_cli-3.0.120 → drydock_cli-3.0.121}/tests/test_tui.py +0 -0
  128. {drydock_cli-3.0.120 → drydock_cli-3.0.121}/tests/test_tuning.py +0 -0
  129. {drydock_cli-3.0.120 → drydock_cli-3.0.121}/tests/test_viewimage.py +0 -0
  130. {drydock_cli-3.0.120 → drydock_cli-3.0.121}/tests/test_vision_input.py +0 -0
  131. {drydock_cli-3.0.120 → drydock_cli-3.0.121}/tests/test_web_tools.py +0 -0
  132. {drydock_cli-3.0.120 → drydock_cli-3.0.121}/tests/test_windows_shell.py +0 -0
  133. {drydock_cli-3.0.120 → drydock_cli-3.0.121}/tests/test_write_content_coerce.py +0 -0
  134. {drydock_cli-3.0.120 → drydock_cli-3.0.121}/tests/test_xccdf.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: drydock-cli
3
- Version: 3.0.120
3
+ Version: 3.0.121
4
4
  Summary: Drydock — a local, provider-agnostic terminal coding agent for local LLMs
5
5
  Author: Frank Bobe III
6
6
  License-Expression: Apache-2.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])
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: drydock-cli
3
- Version: 3.0.120
3
+ Version: 3.0.121
4
4
  Summary: Drydock — a local, provider-agnostic terminal coding agent for local LLMs
5
5
  Author: Frank Bobe III
6
6
  License-Expression: Apache-2.0
@@ -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.120"
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) == {"rmf-control", "rmf-categorize", "rmf-review", "rmf-poam", "stig-assess", "stig-remediate"}
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