drydock-cli 3.0.102__tar.gz → 3.0.104__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 (117) hide show
  1. {drydock_cli-3.0.102/drydock_cli.egg-info → drydock_cli-3.0.104}/PKG-INFO +1 -1
  2. {drydock_cli-3.0.102 → drydock_cli-3.0.104}/drydock/extract.py +2 -2
  3. {drydock_cli-3.0.102 → drydock_cli-3.0.104}/drydock/tools/__init__.py +11 -5
  4. {drydock_cli-3.0.102 → drydock_cli-3.0.104/drydock_cli.egg-info}/PKG-INFO +1 -1
  5. {drydock_cli-3.0.102 → drydock_cli-3.0.104}/drydock_cli.egg-info/SOURCES.txt +1 -0
  6. {drydock_cli-3.0.102 → drydock_cli-3.0.104}/pyproject.toml +1 -1
  7. drydock_cli-3.0.104/tests/test_tool_arg_coercion_more.py +37 -0
  8. {drydock_cli-3.0.102 → drydock_cli-3.0.104}/LICENSE +0 -0
  9. {drydock_cli-3.0.102 → drydock_cli-3.0.104}/NOTICE +0 -0
  10. {drydock_cli-3.0.102 → drydock_cli-3.0.104}/README.md +0 -0
  11. {drydock_cli-3.0.102 → drydock_cli-3.0.104}/drydock/__init__.py +0 -0
  12. {drydock_cli-3.0.102 → drydock_cli-3.0.104}/drydock/__main__.py +0 -0
  13. {drydock_cli-3.0.102 → drydock_cli-3.0.104}/drydock/advisor.py +0 -0
  14. {drydock_cli-3.0.102 → drydock_cli-3.0.104}/drydock/agent.py +0 -0
  15. {drydock_cli-3.0.102 → drydock_cli-3.0.104}/drydock/bash_safety.py +0 -0
  16. {drydock_cli-3.0.102 → drydock_cli-3.0.104}/drydock/builtin_skills/__init__.py +0 -0
  17. {drydock_cli-3.0.102 → drydock_cli-3.0.104}/drydock/builtin_skills/rmf-categorize.md +0 -0
  18. {drydock_cli-3.0.102 → drydock_cli-3.0.104}/drydock/builtin_skills/rmf-control.md +0 -0
  19. {drydock_cli-3.0.102 → drydock_cli-3.0.104}/drydock/builtin_skills/rmf-poam.md +0 -0
  20. {drydock_cli-3.0.102 → drydock_cli-3.0.104}/drydock/builtin_skills/rmf-review.md +0 -0
  21. {drydock_cli-3.0.102 → drydock_cli-3.0.104}/drydock/builtin_skills/stig-assess.md +0 -0
  22. {drydock_cli-3.0.102 → drydock_cli-3.0.104}/drydock/builtin_skills/stig-remediate.md +0 -0
  23. {drydock_cli-3.0.102 → drydock_cli-3.0.104}/drydock/cci.py +0 -0
  24. {drydock_cli-3.0.102 → drydock_cli-3.0.104}/drydock/cli.py +0 -0
  25. {drydock_cli-3.0.102 → drydock_cli-3.0.104}/drydock/compaction.py +0 -0
  26. {drydock_cli-3.0.102 → drydock_cli-3.0.104}/drydock/config.py +0 -0
  27. {drydock_cli-3.0.102 → drydock_cli-3.0.104}/drydock/detect.py +0 -0
  28. {drydock_cli-3.0.102 → drydock_cli-3.0.104}/drydock/gittools.py +0 -0
  29. {drydock_cli-3.0.102 → drydock_cli-3.0.104}/drydock/graphrag.py +0 -0
  30. {drydock_cli-3.0.102 → drydock_cli-3.0.104}/drydock/guards.py +0 -0
  31. {drydock_cli-3.0.102 → drydock_cli-3.0.104}/drydock/loop_detect.py +0 -0
  32. {drydock_cli-3.0.102 → drydock_cli-3.0.104}/drydock/mcp.py +0 -0
  33. {drydock_cli-3.0.102 → drydock_cli-3.0.104}/drydock/poam.py +0 -0
  34. {drydock_cli-3.0.102 → drydock_cli-3.0.104}/drydock/providers.py +0 -0
  35. {drydock_cli-3.0.102 → drydock_cli-3.0.104}/drydock/rmf.py +0 -0
  36. {drydock_cli-3.0.102 → drydock_cli-3.0.104}/drydock/rmf_graph.py +0 -0
  37. {drydock_cli-3.0.102 → drydock_cli-3.0.104}/drydock/skills.py +0 -0
  38. {drydock_cli-3.0.102 → drydock_cli-3.0.104}/drydock/stig.py +0 -0
  39. {drydock_cli-3.0.102 → drydock_cli-3.0.104}/drydock/tool_registry.py +0 -0
  40. {drydock_cli-3.0.102 → drydock_cli-3.0.104}/drydock/tui/__init__.py +0 -0
  41. {drydock_cli-3.0.102 → drydock_cli-3.0.104}/drydock/tui/app.py +0 -0
  42. {drydock_cli-3.0.102 → drydock_cli-3.0.104}/drydock/tui/approval.py +0 -0
  43. {drydock_cli-3.0.102 → drydock_cli-3.0.104}/drydock/tui/messages.py +0 -0
  44. {drydock_cli-3.0.102 → drydock_cli-3.0.104}/drydock/tui/widgets.py +0 -0
  45. {drydock_cli-3.0.102 → drydock_cli-3.0.104}/drydock/tuning.py +0 -0
  46. {drydock_cli-3.0.102 → drydock_cli-3.0.104}/drydock/web.py +0 -0
  47. {drydock_cli-3.0.102 → drydock_cli-3.0.104}/drydock_cli.egg-info/dependency_links.txt +0 -0
  48. {drydock_cli-3.0.102 → drydock_cli-3.0.104}/drydock_cli.egg-info/entry_points.txt +0 -0
  49. {drydock_cli-3.0.102 → drydock_cli-3.0.104}/drydock_cli.egg-info/requires.txt +0 -0
  50. {drydock_cli-3.0.102 → drydock_cli-3.0.104}/drydock_cli.egg-info/top_level.txt +0 -0
  51. {drydock_cli-3.0.102 → drydock_cli-3.0.104}/setup.cfg +0 -0
  52. {drydock_cli-3.0.102 → drydock_cli-3.0.104}/tests/test_advisor.py +0 -0
  53. {drydock_cli-3.0.102 → drydock_cli-3.0.104}/tests/test_approval.py +0 -0
  54. {drydock_cli-3.0.102 → drydock_cli-3.0.104}/tests/test_back_command.py +0 -0
  55. {drydock_cli-3.0.102 → drydock_cli-3.0.104}/tests/test_bash_background.py +0 -0
  56. {drydock_cli-3.0.102 → drydock_cli-3.0.104}/tests/test_bash_binary_output.py +0 -0
  57. {drydock_cli-3.0.102 → drydock_cli-3.0.104}/tests/test_bash_output_bounding.py +0 -0
  58. {drydock_cli-3.0.102 → drydock_cli-3.0.104}/tests/test_bash_process_group.py +0 -0
  59. {drydock_cli-3.0.102 → drydock_cli-3.0.104}/tests/test_bash_safety.py +0 -0
  60. {drydock_cli-3.0.102 → drydock_cli-3.0.104}/tests/test_bash_sanitize.py +0 -0
  61. {drydock_cli-3.0.102 → drydock_cli-3.0.104}/tests/test_bash_shell.py +0 -0
  62. {drydock_cli-3.0.102 → drydock_cli-3.0.104}/tests/test_bash_stdin.py +0 -0
  63. {drydock_cli-3.0.102 → drydock_cli-3.0.104}/tests/test_bash_stop_partial.py +0 -0
  64. {drydock_cli-3.0.102 → drydock_cli-3.0.104}/tests/test_bash_timeout_network.py +0 -0
  65. {drydock_cli-3.0.102 → drydock_cli-3.0.104}/tests/test_bash_timeout_param.py +0 -0
  66. {drydock_cli-3.0.102 → drydock_cli-3.0.104}/tests/test_cci.py +0 -0
  67. {drydock_cli-3.0.102 → drydock_cli-3.0.104}/tests/test_cli_agents.py +0 -0
  68. {drydock_cli-3.0.102 → drydock_cli-3.0.104}/tests/test_compact_command.py +0 -0
  69. {drydock_cli-3.0.102 → drydock_cli-3.0.104}/tests/test_compaction.py +0 -0
  70. {drydock_cli-3.0.102 → drydock_cli-3.0.104}/tests/test_config.py +0 -0
  71. {drydock_cli-3.0.102 → drydock_cli-3.0.104}/tests/test_config_migration.py +0 -0
  72. {drydock_cli-3.0.102 → drydock_cli-3.0.104}/tests/test_context_limit_config.py +0 -0
  73. {drydock_cli-3.0.102 → drydock_cli-3.0.104}/tests/test_detect.py +0 -0
  74. {drydock_cli-3.0.102 → drydock_cli-3.0.104}/tests/test_dispatch.py +0 -0
  75. {drydock_cli-3.0.102 → drydock_cli-3.0.104}/tests/test_e2e_connected.py +0 -0
  76. {drydock_cli-3.0.102 → drydock_cli-3.0.104}/tests/test_edit_replace_all.py +0 -0
  77. {drydock_cli-3.0.102 → drydock_cli-3.0.104}/tests/test_empty_response.py +0 -0
  78. {drydock_cli-3.0.102 → drydock_cli-3.0.104}/tests/test_extract.py +0 -0
  79. {drydock_cli-3.0.102 → drydock_cli-3.0.104}/tests/test_failure_loop.py +0 -0
  80. {drydock_cli-3.0.102 → drydock_cli-3.0.104}/tests/test_first_run_setup.py +0 -0
  81. {drydock_cli-3.0.102 → drydock_cli-3.0.104}/tests/test_gittools.py +0 -0
  82. {drydock_cli-3.0.102 → drydock_cli-3.0.104}/tests/test_glob_edit_edges.py +0 -0
  83. {drydock_cli-3.0.102 → drydock_cli-3.0.104}/tests/test_graphify_example.py +0 -0
  84. {drydock_cli-3.0.102 → drydock_cli-3.0.104}/tests/test_graphrag.py +0 -0
  85. {drydock_cli-3.0.102 → drydock_cli-3.0.104}/tests/test_grep_and_read_robust.py +0 -0
  86. {drydock_cli-3.0.102 → drydock_cli-3.0.104}/tests/test_guards_and_tools.py +0 -0
  87. {drydock_cli-3.0.102 → drydock_cli-3.0.104}/tests/test_hallucinated_tools.py +0 -0
  88. {drydock_cli-3.0.102 → drydock_cli-3.0.104}/tests/test_leaked_tool_call.py +0 -0
  89. {drydock_cli-3.0.102 → drydock_cli-3.0.104}/tests/test_loop_detect.py +0 -0
  90. {drydock_cli-3.0.102 → drydock_cli-3.0.104}/tests/test_mcp.py +0 -0
  91. {drydock_cli-3.0.102 → drydock_cli-3.0.104}/tests/test_oneshot_unreachable.py +0 -0
  92. {drydock_cli-3.0.102 → drydock_cli-3.0.104}/tests/test_plan_autocontinue.py +0 -0
  93. {drydock_cli-3.0.102 → drydock_cli-3.0.104}/tests/test_poam.py +0 -0
  94. {drydock_cli-3.0.102 → drydock_cli-3.0.104}/tests/test_providers_unreachable.py +0 -0
  95. {drydock_cli-3.0.102 → drydock_cli-3.0.104}/tests/test_read_index.py +0 -0
  96. {drydock_cli-3.0.102 → drydock_cli-3.0.104}/tests/test_rmf.py +0 -0
  97. {drydock_cli-3.0.102 → drydock_cli-3.0.104}/tests/test_rmf_graph.py +0 -0
  98. {drydock_cli-3.0.102 → drydock_cli-3.0.104}/tests/test_rmf_stig_graph.py +0 -0
  99. {drydock_cli-3.0.102 → drydock_cli-3.0.104}/tests/test_runaway_repetition.py +0 -0
  100. {drydock_cli-3.0.102 → drydock_cli-3.0.104}/tests/test_server_probe.py +0 -0
  101. {drydock_cli-3.0.102 → drydock_cli-3.0.104}/tests/test_skills.py +0 -0
  102. {drydock_cli-3.0.102 → drydock_cli-3.0.104}/tests/test_stig.py +0 -0
  103. {drydock_cli-3.0.102 → drydock_cli-3.0.104}/tests/test_stop.py +0 -0
  104. {drydock_cli-3.0.102 → drydock_cli-3.0.104}/tests/test_streaming_newlines.py +0 -0
  105. {drydock_cli-3.0.102 → drydock_cli-3.0.104}/tests/test_subagent.py +0 -0
  106. {drydock_cli-3.0.102 → drydock_cli-3.0.104}/tests/test_system_prompt_help.py +0 -0
  107. {drydock_cli-3.0.102 → drydock_cli-3.0.104}/tests/test_todo.py +0 -0
  108. {drydock_cli-3.0.102 → drydock_cli-3.0.104}/tests/test_tool_arg_coercion.py +0 -0
  109. {drydock_cli-3.0.102 → drydock_cli-3.0.104}/tests/test_tool_arg_parsing.py +0 -0
  110. {drydock_cli-3.0.102 → drydock_cli-3.0.104}/tests/test_tools_undo.py +0 -0
  111. {drydock_cli-3.0.102 → drydock_cli-3.0.104}/tests/test_tui.py +0 -0
  112. {drydock_cli-3.0.102 → drydock_cli-3.0.104}/tests/test_tuning.py +0 -0
  113. {drydock_cli-3.0.102 → drydock_cli-3.0.104}/tests/test_viewimage.py +0 -0
  114. {drydock_cli-3.0.102 → drydock_cli-3.0.104}/tests/test_vision_input.py +0 -0
  115. {drydock_cli-3.0.102 → drydock_cli-3.0.104}/tests/test_web_tools.py +0 -0
  116. {drydock_cli-3.0.102 → drydock_cli-3.0.104}/tests/test_write_content_coerce.py +0 -0
  117. {drydock_cli-3.0.102 → drydock_cli-3.0.104}/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.102
3
+ Version: 3.0.104
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
@@ -62,7 +62,7 @@ def _extract_pdf(path: str | Path) -> str | None:
62
62
  pass
63
63
  # 2) pypdf (optional dependency: drydock-cli[pdf]).
64
64
  try:
65
- import pypdf
65
+ import pypdf # pyright: ignore[reportMissingImports]
66
66
 
67
67
  reader = pypdf.PdfReader(str(path))
68
68
  text = "\n\n".join((pg.extract_text() or "") for pg in reader.pages).strip()
@@ -113,7 +113,7 @@ def pdf_backend_available() -> bool:
113
113
  if which("pdftotext"):
114
114
  return True
115
115
  try:
116
- import pypdf # noqa: F401
116
+ import pypdf # noqa: F401 # pyright: ignore[reportMissingImports]
117
117
 
118
118
  return True
119
119
  except ImportError:
@@ -1067,6 +1067,11 @@ def tool_bash(params: dict, config: dict) -> str:
1067
1067
  if cancel is not None and cancel.is_set():
1068
1068
  kill_process_group(proc)
1069
1069
  proc.wait()
1070
+ # The drain thread blocks in read(8192) until the buffer fills or
1071
+ # EOF; killing the process delivers EOF, so join lets it append the
1072
+ # last buffered output BEFORE we read chunks (else partial races
1073
+ # the drain and comes back empty for small-output commands).
1074
+ reader.join(1.0)
1070
1075
  partial = _sanitize_bash_output(
1071
1076
  _collapse_repeated_lines("".join(list(chunks)))
1072
1077
  ).rstrip()
@@ -1090,6 +1095,7 @@ def tool_bash(params: dict, config: dict) -> str:
1090
1095
  if time.monotonic() - start > timeout:
1091
1096
  kill_process_group(proc)
1092
1097
  proc.wait()
1098
+ reader.join(1.0) # flush buffered output before building partial
1093
1099
  bigger = min(timeout * 4, 1800)
1094
1100
  msg = (
1095
1101
  f"Error: command timed out after {timeout}s. If it is "
@@ -1256,7 +1262,7 @@ def tool_consult(params: dict, config: dict) -> str:
1256
1262
  """Ask the configured second/advisor model (e.g. Gemini) for a second opinion."""
1257
1263
  from drydock import advisor
1258
1264
 
1259
- question = (params.get("question") or params.get("prompt") or "").strip()
1265
+ question = _as_str_arg(params.get("question") or params.get("prompt")).strip()
1260
1266
  if not question:
1261
1267
  return "Error: Consult needs a `question`."
1262
1268
  return advisor.consult(question, config, context=params.get("context", "") or "")
@@ -1398,7 +1404,7 @@ def tool_gitcommit(params: dict, config: dict) -> str:
1398
1404
  try:
1399
1405
  return gittools.commit(
1400
1406
  _git_cwd(config),
1401
- params.get("message") or "",
1407
+ _as_text(params.get("message")),
1402
1408
  add_all=params.get("add_all", True) is not False,
1403
1409
  )
1404
1410
  except gittools.GitError as e:
@@ -1578,7 +1584,7 @@ def tool_websearch(params: dict, config: dict) -> str:
1578
1584
  """Search the internet (DuckDuckGo). Read-only; clean message when offline."""
1579
1585
  from drydock import web
1580
1586
 
1581
- query = (params.get("query") or "").strip()
1587
+ query = _as_str_arg(params.get("query")).strip()
1582
1588
  if not query:
1583
1589
  return "Error: `WebSearch` needs a `query`."
1584
1590
  try:
@@ -1596,7 +1602,7 @@ def tool_webfetch(params: dict, config: dict) -> str:
1596
1602
  """Fetch a URL and return readable text. Read-only; clean message offline."""
1597
1603
  from drydock import web
1598
1604
 
1599
- url = (params.get("url") or "").strip()
1605
+ url = _as_str_arg(params.get("url")).strip()
1600
1606
  if not url:
1601
1607
  return "Error: `WebFetch` needs a `url`."
1602
1608
  try:
@@ -1616,7 +1622,7 @@ def tool_knowledge(params: dict, config: dict) -> str:
1616
1622
  If no index exists, says so cleanly rather than erroring."""
1617
1623
  from drydock import graphrag
1618
1624
 
1619
- query = (params.get("query") or "").strip()
1625
+ query = _as_str_arg(params.get("query")).strip()
1620
1626
  if not query:
1621
1627
  return "Error: `Knowledge` needs a `query` describing what to look up."
1622
1628
  cwd = config.get("cwd") or os.getcwd()
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: drydock-cli
3
- Version: 3.0.102
3
+ Version: 3.0.104
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
@@ -103,6 +103,7 @@ tests/test_subagent.py
103
103
  tests/test_system_prompt_help.py
104
104
  tests/test_todo.py
105
105
  tests/test_tool_arg_coercion.py
106
+ tests/test_tool_arg_coercion_more.py
106
107
  tests/test_tool_arg_parsing.py
107
108
  tests/test_tools_undo.py
108
109
  tests/test_tui.py
@@ -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.102"
10
+ version = "3.0.104"
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"
@@ -0,0 +1,37 @@
1
+ """Wrong-type args crashed more tools with AttributeError ('.strip()' on a
2
+ list/int): GitCommit message, Knowledge query, Consult question, WebFetch url,
3
+ WebSearch query. All coerced now — no tool should raise on a wrong-type arg."""
4
+ from __future__ import annotations
5
+
6
+ import drydock.tools as T
7
+
8
+
9
+ def _no_crash(fn, **kw):
10
+ out = fn(kw, {"cwd": "/tmp"}) # must return a string, not raise
11
+ assert isinstance(out, str)
12
+ return out
13
+
14
+
15
+ def test_gitcommit_message_list():
16
+ _no_crash(T.tool_gitcommit, message=["line1", "line2"])
17
+
18
+
19
+ def test_gitcommit_message_int():
20
+ _no_crash(T.tool_gitcommit, message=42)
21
+
22
+
23
+ def test_knowledge_query_list():
24
+ _no_crash(T.tool_knowledge, query=["find x"])
25
+
26
+
27
+ def test_consult_question_list():
28
+ _no_crash(T.tool_consult, question=["help me"])
29
+
30
+
31
+ def test_webfetch_url_list():
32
+ _no_crash(T.tool_webfetch, url=["http://example.invalid"])
33
+
34
+
35
+ def test_websearch_query_int():
36
+ out = _no_crash(T.tool_websearch, query=42)
37
+ assert "42" in out
File without changes
File without changes
File without changes
File without changes