drydock-cli 3.0.112__tar.gz → 3.0.113__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.112/drydock_cli.egg-info → drydock_cli-3.0.113}/PKG-INFO +1 -1
- {drydock_cli-3.0.112 → drydock_cli-3.0.113}/drydock/graphrag.py +17 -14
- {drydock_cli-3.0.112 → drydock_cli-3.0.113}/drydock/tools/__init__.py +58 -0
- {drydock_cli-3.0.112 → drydock_cli-3.0.113/drydock_cli.egg-info}/PKG-INFO +1 -1
- {drydock_cli-3.0.112 → drydock_cli-3.0.113}/pyproject.toml +1 -1
- {drydock_cli-3.0.112 → drydock_cli-3.0.113}/tests/test_graphrag_quoted_path.py +33 -0
- {drydock_cli-3.0.112 → drydock_cli-3.0.113}/LICENSE +0 -0
- {drydock_cli-3.0.112 → drydock_cli-3.0.113}/NOTICE +0 -0
- {drydock_cli-3.0.112 → drydock_cli-3.0.113}/README.md +0 -0
- {drydock_cli-3.0.112 → drydock_cli-3.0.113}/drydock/__init__.py +0 -0
- {drydock_cli-3.0.112 → drydock_cli-3.0.113}/drydock/__main__.py +0 -0
- {drydock_cli-3.0.112 → drydock_cli-3.0.113}/drydock/advisor.py +0 -0
- {drydock_cli-3.0.112 → drydock_cli-3.0.113}/drydock/agent.py +0 -0
- {drydock_cli-3.0.112 → drydock_cli-3.0.113}/drydock/bash_safety.py +0 -0
- {drydock_cli-3.0.112 → drydock_cli-3.0.113}/drydock/builtin_skills/__init__.py +0 -0
- {drydock_cli-3.0.112 → drydock_cli-3.0.113}/drydock/builtin_skills/rmf-categorize.md +0 -0
- {drydock_cli-3.0.112 → drydock_cli-3.0.113}/drydock/builtin_skills/rmf-control.md +0 -0
- {drydock_cli-3.0.112 → drydock_cli-3.0.113}/drydock/builtin_skills/rmf-poam.md +0 -0
- {drydock_cli-3.0.112 → drydock_cli-3.0.113}/drydock/builtin_skills/rmf-review.md +0 -0
- {drydock_cli-3.0.112 → drydock_cli-3.0.113}/drydock/builtin_skills/stig-assess.md +0 -0
- {drydock_cli-3.0.112 → drydock_cli-3.0.113}/drydock/builtin_skills/stig-remediate.md +0 -0
- {drydock_cli-3.0.112 → drydock_cli-3.0.113}/drydock/cci.py +0 -0
- {drydock_cli-3.0.112 → drydock_cli-3.0.113}/drydock/cli.py +0 -0
- {drydock_cli-3.0.112 → drydock_cli-3.0.113}/drydock/compaction.py +0 -0
- {drydock_cli-3.0.112 → drydock_cli-3.0.113}/drydock/config.py +0 -0
- {drydock_cli-3.0.112 → drydock_cli-3.0.113}/drydock/detect.py +0 -0
- {drydock_cli-3.0.112 → drydock_cli-3.0.113}/drydock/extract.py +0 -0
- {drydock_cli-3.0.112 → drydock_cli-3.0.113}/drydock/gittools.py +0 -0
- {drydock_cli-3.0.112 → drydock_cli-3.0.113}/drydock/guards.py +0 -0
- {drydock_cli-3.0.112 → drydock_cli-3.0.113}/drydock/loop_detect.py +0 -0
- {drydock_cli-3.0.112 → drydock_cli-3.0.113}/drydock/mcp.py +0 -0
- {drydock_cli-3.0.112 → drydock_cli-3.0.113}/drydock/poam.py +0 -0
- {drydock_cli-3.0.112 → drydock_cli-3.0.113}/drydock/providers.py +0 -0
- {drydock_cli-3.0.112 → drydock_cli-3.0.113}/drydock/rmf.py +0 -0
- {drydock_cli-3.0.112 → drydock_cli-3.0.113}/drydock/rmf_graph.py +0 -0
- {drydock_cli-3.0.112 → drydock_cli-3.0.113}/drydock/skills.py +0 -0
- {drydock_cli-3.0.112 → drydock_cli-3.0.113}/drydock/stig.py +0 -0
- {drydock_cli-3.0.112 → drydock_cli-3.0.113}/drydock/tool_registry.py +0 -0
- {drydock_cli-3.0.112 → drydock_cli-3.0.113}/drydock/tui/__init__.py +0 -0
- {drydock_cli-3.0.112 → drydock_cli-3.0.113}/drydock/tui/app.py +0 -0
- {drydock_cli-3.0.112 → drydock_cli-3.0.113}/drydock/tui/approval.py +0 -0
- {drydock_cli-3.0.112 → drydock_cli-3.0.113}/drydock/tui/messages.py +0 -0
- {drydock_cli-3.0.112 → drydock_cli-3.0.113}/drydock/tui/widgets.py +0 -0
- {drydock_cli-3.0.112 → drydock_cli-3.0.113}/drydock/tuning.py +0 -0
- {drydock_cli-3.0.112 → drydock_cli-3.0.113}/drydock/web.py +0 -0
- {drydock_cli-3.0.112 → drydock_cli-3.0.113}/drydock_cli.egg-info/SOURCES.txt +0 -0
- {drydock_cli-3.0.112 → drydock_cli-3.0.113}/drydock_cli.egg-info/dependency_links.txt +0 -0
- {drydock_cli-3.0.112 → drydock_cli-3.0.113}/drydock_cli.egg-info/entry_points.txt +0 -0
- {drydock_cli-3.0.112 → drydock_cli-3.0.113}/drydock_cli.egg-info/requires.txt +0 -0
- {drydock_cli-3.0.112 → drydock_cli-3.0.113}/drydock_cli.egg-info/top_level.txt +0 -0
- {drydock_cli-3.0.112 → drydock_cli-3.0.113}/setup.cfg +0 -0
- {drydock_cli-3.0.112 → drydock_cli-3.0.113}/tests/test_advisor.py +0 -0
- {drydock_cli-3.0.112 → drydock_cli-3.0.113}/tests/test_approval.py +0 -0
- {drydock_cli-3.0.112 → drydock_cli-3.0.113}/tests/test_back_command.py +0 -0
- {drydock_cli-3.0.112 → drydock_cli-3.0.113}/tests/test_bash_background.py +0 -0
- {drydock_cli-3.0.112 → drydock_cli-3.0.113}/tests/test_bash_binary_output.py +0 -0
- {drydock_cli-3.0.112 → drydock_cli-3.0.113}/tests/test_bash_crossplatform.py +0 -0
- {drydock_cli-3.0.112 → drydock_cli-3.0.113}/tests/test_bash_output_bounding.py +0 -0
- {drydock_cli-3.0.112 → drydock_cli-3.0.113}/tests/test_bash_process_group.py +0 -0
- {drydock_cli-3.0.112 → drydock_cli-3.0.113}/tests/test_bash_safety.py +0 -0
- {drydock_cli-3.0.112 → drydock_cli-3.0.113}/tests/test_bash_sanitize.py +0 -0
- {drydock_cli-3.0.112 → drydock_cli-3.0.113}/tests/test_bash_shell.py +0 -0
- {drydock_cli-3.0.112 → drydock_cli-3.0.113}/tests/test_bash_stdin.py +0 -0
- {drydock_cli-3.0.112 → drydock_cli-3.0.113}/tests/test_bash_stop_partial.py +0 -0
- {drydock_cli-3.0.112 → drydock_cli-3.0.113}/tests/test_bash_timeout_network.py +0 -0
- {drydock_cli-3.0.112 → drydock_cli-3.0.113}/tests/test_bash_timeout_param.py +0 -0
- {drydock_cli-3.0.112 → drydock_cli-3.0.113}/tests/test_cci.py +0 -0
- {drydock_cli-3.0.112 → drydock_cli-3.0.113}/tests/test_cli_agents.py +0 -0
- {drydock_cli-3.0.112 → drydock_cli-3.0.113}/tests/test_compact_command.py +0 -0
- {drydock_cli-3.0.112 → drydock_cli-3.0.113}/tests/test_compaction.py +0 -0
- {drydock_cli-3.0.112 → drydock_cli-3.0.113}/tests/test_config.py +0 -0
- {drydock_cli-3.0.112 → drydock_cli-3.0.113}/tests/test_config_migration.py +0 -0
- {drydock_cli-3.0.112 → drydock_cli-3.0.113}/tests/test_context_limit_config.py +0 -0
- {drydock_cli-3.0.112 → drydock_cli-3.0.113}/tests/test_detect.py +0 -0
- {drydock_cli-3.0.112 → drydock_cli-3.0.113}/tests/test_dispatch.py +0 -0
- {drydock_cli-3.0.112 → drydock_cli-3.0.113}/tests/test_e2e_connected.py +0 -0
- {drydock_cli-3.0.112 → drydock_cli-3.0.113}/tests/test_edit_replace_all.py +0 -0
- {drydock_cli-3.0.112 → drydock_cli-3.0.113}/tests/test_empty_response.py +0 -0
- {drydock_cli-3.0.112 → drydock_cli-3.0.113}/tests/test_extract.py +0 -0
- {drydock_cli-3.0.112 → drydock_cli-3.0.113}/tests/test_failure_loop.py +0 -0
- {drydock_cli-3.0.112 → drydock_cli-3.0.113}/tests/test_first_run_setup.py +0 -0
- {drydock_cli-3.0.112 → drydock_cli-3.0.113}/tests/test_gittools.py +0 -0
- {drydock_cli-3.0.112 → drydock_cli-3.0.113}/tests/test_glob_edit_edges.py +0 -0
- {drydock_cli-3.0.112 → drydock_cli-3.0.113}/tests/test_graphify_example.py +0 -0
- {drydock_cli-3.0.112 → drydock_cli-3.0.113}/tests/test_graphrag.py +0 -0
- {drydock_cli-3.0.112 → drydock_cli-3.0.113}/tests/test_grep_and_read_robust.py +0 -0
- {drydock_cli-3.0.112 → drydock_cli-3.0.113}/tests/test_guards_and_tools.py +0 -0
- {drydock_cli-3.0.112 → drydock_cli-3.0.113}/tests/test_hallucinated_tools.py +0 -0
- {drydock_cli-3.0.112 → drydock_cli-3.0.113}/tests/test_leaked_tool_call.py +0 -0
- {drydock_cli-3.0.112 → drydock_cli-3.0.113}/tests/test_loop_detect.py +0 -0
- {drydock_cli-3.0.112 → drydock_cli-3.0.113}/tests/test_mcp.py +0 -0
- {drydock_cli-3.0.112 → drydock_cli-3.0.113}/tests/test_oneshot_unreachable.py +0 -0
- {drydock_cli-3.0.112 → drydock_cli-3.0.113}/tests/test_overthink_interrupt.py +0 -0
- {drydock_cli-3.0.112 → drydock_cli-3.0.113}/tests/test_plan_autocontinue.py +0 -0
- {drydock_cli-3.0.112 → drydock_cli-3.0.113}/tests/test_poam.py +0 -0
- {drydock_cli-3.0.112 → drydock_cli-3.0.113}/tests/test_providers_unreachable.py +0 -0
- {drydock_cli-3.0.112 → drydock_cli-3.0.113}/tests/test_read_index.py +0 -0
- {drydock_cli-3.0.112 → drydock_cli-3.0.113}/tests/test_rmf.py +0 -0
- {drydock_cli-3.0.112 → drydock_cli-3.0.113}/tests/test_rmf_graph.py +0 -0
- {drydock_cli-3.0.112 → drydock_cli-3.0.113}/tests/test_rmf_stig_graph.py +0 -0
- {drydock_cli-3.0.112 → drydock_cli-3.0.113}/tests/test_runaway_repetition.py +0 -0
- {drydock_cli-3.0.112 → drydock_cli-3.0.113}/tests/test_server_probe.py +0 -0
- {drydock_cli-3.0.112 → drydock_cli-3.0.113}/tests/test_skills.py +0 -0
- {drydock_cli-3.0.112 → drydock_cli-3.0.113}/tests/test_stall_retry.py +0 -0
- {drydock_cli-3.0.112 → drydock_cli-3.0.113}/tests/test_stig.py +0 -0
- {drydock_cli-3.0.112 → drydock_cli-3.0.113}/tests/test_stop.py +0 -0
- {drydock_cli-3.0.112 → drydock_cli-3.0.113}/tests/test_streaming_newlines.py +0 -0
- {drydock_cli-3.0.112 → drydock_cli-3.0.113}/tests/test_subagent.py +0 -0
- {drydock_cli-3.0.112 → drydock_cli-3.0.113}/tests/test_system_prompt_help.py +0 -0
- {drydock_cli-3.0.112 → drydock_cli-3.0.113}/tests/test_todo.py +0 -0
- {drydock_cli-3.0.112 → drydock_cli-3.0.113}/tests/test_tool_arg_coercion.py +0 -0
- {drydock_cli-3.0.112 → drydock_cli-3.0.113}/tests/test_tool_arg_coercion_more.py +0 -0
- {drydock_cli-3.0.112 → drydock_cli-3.0.113}/tests/test_tool_arg_parsing.py +0 -0
- {drydock_cli-3.0.112 → drydock_cli-3.0.113}/tests/test_tools_undo.py +0 -0
- {drydock_cli-3.0.112 → drydock_cli-3.0.113}/tests/test_tui.py +0 -0
- {drydock_cli-3.0.112 → drydock_cli-3.0.113}/tests/test_tuning.py +0 -0
- {drydock_cli-3.0.112 → drydock_cli-3.0.113}/tests/test_viewimage.py +0 -0
- {drydock_cli-3.0.112 → drydock_cli-3.0.113}/tests/test_vision_input.py +0 -0
- {drydock_cli-3.0.112 → drydock_cli-3.0.113}/tests/test_web_tools.py +0 -0
- {drydock_cli-3.0.112 → drydock_cli-3.0.113}/tests/test_windows_shell.py +0 -0
- {drydock_cli-3.0.112 → drydock_cli-3.0.113}/tests/test_write_content_coerce.py +0 -0
- {drydock_cli-3.0.112 → drydock_cli-3.0.113}/tests/test_xccdf.py +0 -0
|
@@ -134,25 +134,28 @@ def _ingest_files(paths, cwd, chunks, entity_chunks, edges, skip_sources):
|
|
|
134
134
|
cleaned = [_unquote(p) for p in paths]
|
|
135
135
|
for fp in _iter_text_files([str(Path(cwd) / p) if not os.path.isabs(p) else p
|
|
136
136
|
for p in cleaned]):
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
if
|
|
143
|
-
continue # unreadable / no PDF backend — skip cleanly
|
|
144
|
-
else:
|
|
145
|
-
try:
|
|
146
|
-
text = fp.read_text("utf-8", "ignore")
|
|
147
|
-
except OSError:
|
|
137
|
+
# Per-file isolation: ONE unreadable/odd file (a locked Word doc, a weird
|
|
138
|
+
# encoding, a PDF backend quirk) must never crash a whole-folder build —
|
|
139
|
+
# skip it and keep indexing the rest.
|
|
140
|
+
try:
|
|
141
|
+
rel = os.path.relpath(str(fp), cwd)
|
|
142
|
+
if rel in skip_sources:
|
|
148
143
|
continue
|
|
149
|
-
|
|
144
|
+
if fp.suffix.lower() in extract.EXTRACTABLE_EXT:
|
|
145
|
+
text = extract.extract_document(fp) # PDF/Word → text (or None)
|
|
146
|
+
else:
|
|
147
|
+
text = fp.read_text("utf-8", "ignore")
|
|
148
|
+
if not text or not text.strip():
|
|
149
|
+
continue # unreadable / empty — skip cleanly
|
|
150
|
+
# Build this file's chunks locally; commit only if it ALL succeeds so a
|
|
151
|
+
# mid-file failure leaves no partial state and isn't miscounted.
|
|
152
|
+
local = [(body, extract_entities(body)) for body in _chunk_text(text)]
|
|
153
|
+
except Exception: # noqa: BLE001 — isolate a bad file, never abort the build
|
|
150
154
|
continue
|
|
151
155
|
added += 1
|
|
152
156
|
skip_sources.add(rel) # don't double-ingest the same file in one call
|
|
153
|
-
for body in
|
|
157
|
+
for body, ents in local:
|
|
154
158
|
cid = len(chunks)
|
|
155
|
-
ents = extract_entities(body)
|
|
156
159
|
chunks.append({"id": cid, "source": rel, "text": body, "entities": ents})
|
|
157
160
|
for e in ents:
|
|
158
161
|
entity_chunks[e].add(cid)
|
|
@@ -607,6 +607,34 @@ SCHEMAS = [
|
|
|
607
607
|
"required": ["query"],
|
|
608
608
|
},
|
|
609
609
|
},
|
|
610
|
+
{
|
|
611
|
+
"name": "BuildKnowledge",
|
|
612
|
+
"description": (
|
|
613
|
+
"BUILD or extend the user's GraphRAG knowledge base FROM THEIR documents "
|
|
614
|
+
"or code. Call this YOURSELF when the user asks you to index / ingest / "
|
|
615
|
+
"'make a knowledge base from' a folder or file (e.g. 'create a knowledge "
|
|
616
|
+
"base from my Documents'). Give `path` (a file or directory). mode 'build' "
|
|
617
|
+
"= (re)build from scratch; 'add' = merge into an existing base. When it "
|
|
618
|
+
"succeeds you can search it with the Knowledge tool. Do NOT tell the user "
|
|
619
|
+
"to type a '/graphrag' slash command — actually do it with this tool."
|
|
620
|
+
),
|
|
621
|
+
"input_schema": {
|
|
622
|
+
"type": "object",
|
|
623
|
+
"properties": {
|
|
624
|
+
"path": {
|
|
625
|
+
"type": "string",
|
|
626
|
+
"description": "File or directory to index. A normal path — on "
|
|
627
|
+
"Windows e.g. C:\\Users\\me\\Documents (quotes optional).",
|
|
628
|
+
},
|
|
629
|
+
"mode": {
|
|
630
|
+
"type": "string",
|
|
631
|
+
"description": "'build' (rebuild from scratch, default) or 'add' "
|
|
632
|
+
"(merge into the existing base).",
|
|
633
|
+
},
|
|
634
|
+
},
|
|
635
|
+
"required": ["path"],
|
|
636
|
+
},
|
|
637
|
+
},
|
|
610
638
|
]
|
|
611
639
|
|
|
612
640
|
# ── Tool implementations ──────────────────────────────────────────────────
|
|
@@ -1741,6 +1769,34 @@ def tool_knowledge(params: dict, config: dict) -> str:
|
|
|
1741
1769
|
return graphrag.format_results(result, query)
|
|
1742
1770
|
|
|
1743
1771
|
|
|
1772
|
+
def tool_build_knowledge(params: dict, config: dict) -> str:
|
|
1773
|
+
"""Build/extend the GraphRAG knowledge base from a file or directory of docs —
|
|
1774
|
+
the model-callable equivalent of `/graphrag build|add`, so the agent can do it
|
|
1775
|
+
itself when asked instead of telling the user to run a slash command."""
|
|
1776
|
+
from drydock import graphrag
|
|
1777
|
+
|
|
1778
|
+
path = _as_str_arg(params.get("path")).strip()
|
|
1779
|
+
if not path:
|
|
1780
|
+
return ("Error: `BuildKnowledge` needs a `path` — a file or directory of "
|
|
1781
|
+
"documents/code to index.")
|
|
1782
|
+
mode = (_as_str_arg(params.get("mode")) or "build").strip().lower()
|
|
1783
|
+
if mode not in ("build", "add"):
|
|
1784
|
+
mode = "build"
|
|
1785
|
+
cwd = config.get("cwd") or os.getcwd()
|
|
1786
|
+
store = config.get("graphrag_store") or graphrag.default_store_path(cwd)
|
|
1787
|
+
try:
|
|
1788
|
+
fn = graphrag.build_index if mode == "build" else graphrag.add_to_index
|
|
1789
|
+
stats = fn([path], store, cwd=cwd)
|
|
1790
|
+
except Exception as e: # noqa: BLE001 — report, never crash the agent loop
|
|
1791
|
+
return f"Error building the knowledge base from {path}: {e}"
|
|
1792
|
+
if not stats.get("chunks"):
|
|
1793
|
+
return (f"No indexable text found under {path}. Nothing was added. (Supported: "
|
|
1794
|
+
"text/code files, .docx, .pdf, .md, etc. Check the path is correct.)")
|
|
1795
|
+
verb = "Built" if mode == "build" else "Updated"
|
|
1796
|
+
return (f"{verb} the knowledge base: {stats['files']} files, {stats['chunks']} "
|
|
1797
|
+
f"chunks, {stats['entities']} entities. Search it with the Knowledge tool.")
|
|
1798
|
+
|
|
1799
|
+
|
|
1744
1800
|
# ── Register all tools ────────────────────────────────────────────────────
|
|
1745
1801
|
|
|
1746
1802
|
_TOOLS = [
|
|
@@ -1754,6 +1810,7 @@ _TOOLS = [
|
|
|
1754
1810
|
("task", tool_task, True),
|
|
1755
1811
|
("Dispatch", tool_dispatch, True),
|
|
1756
1812
|
("Knowledge", tool_knowledge, True),
|
|
1813
|
+
("BuildKnowledge", tool_build_knowledge, False),
|
|
1757
1814
|
("GraphQuery", tool_graphquery, True),
|
|
1758
1815
|
("GraphAdd", tool_graphadd, False),
|
|
1759
1816
|
("StigRules", tool_stigrules, True),
|
|
@@ -1776,6 +1833,7 @@ def register_all():
|
|
|
1776
1833
|
"Bash": tool_bash, "Glob": tool_glob, "Grep": tool_grep,
|
|
1777
1834
|
"todo": tool_todo, "task": tool_task, "Dispatch": tool_dispatch,
|
|
1778
1835
|
"Consult": tool_consult, "Knowledge": tool_knowledge,
|
|
1836
|
+
"BuildKnowledge": tool_build_knowledge,
|
|
1779
1837
|
"GraphQuery": tool_graphquery, "GraphAdd": tool_graphadd,
|
|
1780
1838
|
"StigRules": tool_stigrules, "StigRule": tool_stigrule, "StigSet": tool_stigset,
|
|
1781
1839
|
"WebSearch": tool_websearch, "WebFetch": tool_webfetch,
|
|
@@ -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.113"
|
|
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"
|
|
@@ -41,3 +41,36 @@ def test_unquote_helper():
|
|
|
41
41
|
assert graphrag._unquote("/plain/path") == "/plain/path"
|
|
42
42
|
assert graphrag._unquote(' "spaced" ') == "spaced"
|
|
43
43
|
assert graphrag._unquote('"') == '"' # lone quote unchanged
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def test_one_bad_file_does_not_abort_build():
|
|
47
|
+
"""A single file that raises mid-processing must be skipped, not crash the
|
|
48
|
+
whole folder build (the Windows 'NoneType.strip' report)."""
|
|
49
|
+
from unittest import mock
|
|
50
|
+
src, store = _make_docs()
|
|
51
|
+
open(os.path.join(src, "boom.txt"), "w").write("EXPLODE here")
|
|
52
|
+
real = graphrag.extract_entities
|
|
53
|
+
|
|
54
|
+
def boom(text):
|
|
55
|
+
if "EXPLODE" in text:
|
|
56
|
+
raise AttributeError("'NoneType' object has no attribute 'strip'")
|
|
57
|
+
return real(text)
|
|
58
|
+
|
|
59
|
+
with mock.patch.object(graphrag, "extract_entities", boom):
|
|
60
|
+
stats = graphrag.build_index([src], store)
|
|
61
|
+
assert stats["files"] == 2 # the 2 good files indexed, boom.txt skipped (not counted)
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
def test_build_knowledge_tool_builds_and_reports():
|
|
65
|
+
from drydock import tools
|
|
66
|
+
src, store = _make_docs()
|
|
67
|
+
out = tools.tool_build_knowledge({"path": f'"{src}"', "mode": "build"},
|
|
68
|
+
{"cwd": os.getcwd(), "graphrag_store": store})
|
|
69
|
+
assert "Built the knowledge base" in out and "2 files" in out
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
def test_build_knowledge_available_to_gemma():
|
|
73
|
+
from drydock import tool_registry
|
|
74
|
+
from drydock.tuning import filter_tool_schemas
|
|
75
|
+
names = [s["name"] for s in filter_tool_schemas(tool_registry.schemas(), "gemma4")]
|
|
76
|
+
assert "BuildKnowledge" in names
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|