drydock-cli 3.0.95__tar.gz → 3.0.97__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.95/drydock_cli.egg-info → drydock_cli-3.0.97}/PKG-INFO +1 -1
- {drydock_cli-3.0.95 → drydock_cli-3.0.97}/drydock/tools/__init__.py +30 -4
- {drydock_cli-3.0.95 → drydock_cli-3.0.97/drydock_cli.egg-info}/PKG-INFO +1 -1
- {drydock_cli-3.0.95 → drydock_cli-3.0.97}/drydock_cli.egg-info/SOURCES.txt +2 -0
- {drydock_cli-3.0.95 → drydock_cli-3.0.97}/pyproject.toml +1 -1
- drydock_cli-3.0.97/tests/test_bash_timeout_param.py +29 -0
- drydock_cli-3.0.97/tests/test_grep_and_read_robust.py +43 -0
- {drydock_cli-3.0.95 → drydock_cli-3.0.97}/LICENSE +0 -0
- {drydock_cli-3.0.95 → drydock_cli-3.0.97}/NOTICE +0 -0
- {drydock_cli-3.0.95 → drydock_cli-3.0.97}/README.md +0 -0
- {drydock_cli-3.0.95 → drydock_cli-3.0.97}/drydock/__init__.py +0 -0
- {drydock_cli-3.0.95 → drydock_cli-3.0.97}/drydock/__main__.py +0 -0
- {drydock_cli-3.0.95 → drydock_cli-3.0.97}/drydock/advisor.py +0 -0
- {drydock_cli-3.0.95 → drydock_cli-3.0.97}/drydock/agent.py +0 -0
- {drydock_cli-3.0.95 → drydock_cli-3.0.97}/drydock/bash_safety.py +0 -0
- {drydock_cli-3.0.95 → drydock_cli-3.0.97}/drydock/builtin_skills/__init__.py +0 -0
- {drydock_cli-3.0.95 → drydock_cli-3.0.97}/drydock/builtin_skills/rmf-categorize.md +0 -0
- {drydock_cli-3.0.95 → drydock_cli-3.0.97}/drydock/builtin_skills/rmf-control.md +0 -0
- {drydock_cli-3.0.95 → drydock_cli-3.0.97}/drydock/builtin_skills/rmf-poam.md +0 -0
- {drydock_cli-3.0.95 → drydock_cli-3.0.97}/drydock/builtin_skills/rmf-review.md +0 -0
- {drydock_cli-3.0.95 → drydock_cli-3.0.97}/drydock/builtin_skills/stig-assess.md +0 -0
- {drydock_cli-3.0.95 → drydock_cli-3.0.97}/drydock/builtin_skills/stig-remediate.md +0 -0
- {drydock_cli-3.0.95 → drydock_cli-3.0.97}/drydock/cci.py +0 -0
- {drydock_cli-3.0.95 → drydock_cli-3.0.97}/drydock/cli.py +0 -0
- {drydock_cli-3.0.95 → drydock_cli-3.0.97}/drydock/compaction.py +0 -0
- {drydock_cli-3.0.95 → drydock_cli-3.0.97}/drydock/config.py +0 -0
- {drydock_cli-3.0.95 → drydock_cli-3.0.97}/drydock/detect.py +0 -0
- {drydock_cli-3.0.95 → drydock_cli-3.0.97}/drydock/extract.py +0 -0
- {drydock_cli-3.0.95 → drydock_cli-3.0.97}/drydock/gittools.py +0 -0
- {drydock_cli-3.0.95 → drydock_cli-3.0.97}/drydock/graphrag.py +0 -0
- {drydock_cli-3.0.95 → drydock_cli-3.0.97}/drydock/guards.py +0 -0
- {drydock_cli-3.0.95 → drydock_cli-3.0.97}/drydock/loop_detect.py +0 -0
- {drydock_cli-3.0.95 → drydock_cli-3.0.97}/drydock/mcp.py +0 -0
- {drydock_cli-3.0.95 → drydock_cli-3.0.97}/drydock/poam.py +0 -0
- {drydock_cli-3.0.95 → drydock_cli-3.0.97}/drydock/providers.py +0 -0
- {drydock_cli-3.0.95 → drydock_cli-3.0.97}/drydock/rmf.py +0 -0
- {drydock_cli-3.0.95 → drydock_cli-3.0.97}/drydock/rmf_graph.py +0 -0
- {drydock_cli-3.0.95 → drydock_cli-3.0.97}/drydock/skills.py +0 -0
- {drydock_cli-3.0.95 → drydock_cli-3.0.97}/drydock/stig.py +0 -0
- {drydock_cli-3.0.95 → drydock_cli-3.0.97}/drydock/tool_registry.py +0 -0
- {drydock_cli-3.0.95 → drydock_cli-3.0.97}/drydock/tui/__init__.py +0 -0
- {drydock_cli-3.0.95 → drydock_cli-3.0.97}/drydock/tui/app.py +0 -0
- {drydock_cli-3.0.95 → drydock_cli-3.0.97}/drydock/tui/approval.py +0 -0
- {drydock_cli-3.0.95 → drydock_cli-3.0.97}/drydock/tui/messages.py +0 -0
- {drydock_cli-3.0.95 → drydock_cli-3.0.97}/drydock/tui/widgets.py +0 -0
- {drydock_cli-3.0.95 → drydock_cli-3.0.97}/drydock/tuning.py +0 -0
- {drydock_cli-3.0.95 → drydock_cli-3.0.97}/drydock/web.py +0 -0
- {drydock_cli-3.0.95 → drydock_cli-3.0.97}/drydock_cli.egg-info/dependency_links.txt +0 -0
- {drydock_cli-3.0.95 → drydock_cli-3.0.97}/drydock_cli.egg-info/entry_points.txt +0 -0
- {drydock_cli-3.0.95 → drydock_cli-3.0.97}/drydock_cli.egg-info/requires.txt +0 -0
- {drydock_cli-3.0.95 → drydock_cli-3.0.97}/drydock_cli.egg-info/top_level.txt +0 -0
- {drydock_cli-3.0.95 → drydock_cli-3.0.97}/setup.cfg +0 -0
- {drydock_cli-3.0.95 → drydock_cli-3.0.97}/tests/test_advisor.py +0 -0
- {drydock_cli-3.0.95 → drydock_cli-3.0.97}/tests/test_approval.py +0 -0
- {drydock_cli-3.0.95 → drydock_cli-3.0.97}/tests/test_back_command.py +0 -0
- {drydock_cli-3.0.95 → drydock_cli-3.0.97}/tests/test_bash_background.py +0 -0
- {drydock_cli-3.0.95 → drydock_cli-3.0.97}/tests/test_bash_binary_output.py +0 -0
- {drydock_cli-3.0.95 → drydock_cli-3.0.97}/tests/test_bash_output_bounding.py +0 -0
- {drydock_cli-3.0.95 → drydock_cli-3.0.97}/tests/test_bash_process_group.py +0 -0
- {drydock_cli-3.0.95 → drydock_cli-3.0.97}/tests/test_bash_safety.py +0 -0
- {drydock_cli-3.0.95 → drydock_cli-3.0.97}/tests/test_bash_sanitize.py +0 -0
- {drydock_cli-3.0.95 → drydock_cli-3.0.97}/tests/test_bash_shell.py +0 -0
- {drydock_cli-3.0.95 → drydock_cli-3.0.97}/tests/test_bash_stdin.py +0 -0
- {drydock_cli-3.0.95 → drydock_cli-3.0.97}/tests/test_bash_timeout_network.py +0 -0
- {drydock_cli-3.0.95 → drydock_cli-3.0.97}/tests/test_cci.py +0 -0
- {drydock_cli-3.0.95 → drydock_cli-3.0.97}/tests/test_cli_agents.py +0 -0
- {drydock_cli-3.0.95 → drydock_cli-3.0.97}/tests/test_compact_command.py +0 -0
- {drydock_cli-3.0.95 → drydock_cli-3.0.97}/tests/test_compaction.py +0 -0
- {drydock_cli-3.0.95 → drydock_cli-3.0.97}/tests/test_config.py +0 -0
- {drydock_cli-3.0.95 → drydock_cli-3.0.97}/tests/test_config_migration.py +0 -0
- {drydock_cli-3.0.95 → drydock_cli-3.0.97}/tests/test_context_limit_config.py +0 -0
- {drydock_cli-3.0.95 → drydock_cli-3.0.97}/tests/test_detect.py +0 -0
- {drydock_cli-3.0.95 → drydock_cli-3.0.97}/tests/test_dispatch.py +0 -0
- {drydock_cli-3.0.95 → drydock_cli-3.0.97}/tests/test_e2e_connected.py +0 -0
- {drydock_cli-3.0.95 → drydock_cli-3.0.97}/tests/test_empty_response.py +0 -0
- {drydock_cli-3.0.95 → drydock_cli-3.0.97}/tests/test_extract.py +0 -0
- {drydock_cli-3.0.95 → drydock_cli-3.0.97}/tests/test_failure_loop.py +0 -0
- {drydock_cli-3.0.95 → drydock_cli-3.0.97}/tests/test_first_run_setup.py +0 -0
- {drydock_cli-3.0.95 → drydock_cli-3.0.97}/tests/test_gittools.py +0 -0
- {drydock_cli-3.0.95 → drydock_cli-3.0.97}/tests/test_graphify_example.py +0 -0
- {drydock_cli-3.0.95 → drydock_cli-3.0.97}/tests/test_graphrag.py +0 -0
- {drydock_cli-3.0.95 → drydock_cli-3.0.97}/tests/test_guards_and_tools.py +0 -0
- {drydock_cli-3.0.95 → drydock_cli-3.0.97}/tests/test_hallucinated_tools.py +0 -0
- {drydock_cli-3.0.95 → drydock_cli-3.0.97}/tests/test_leaked_tool_call.py +0 -0
- {drydock_cli-3.0.95 → drydock_cli-3.0.97}/tests/test_loop_detect.py +0 -0
- {drydock_cli-3.0.95 → drydock_cli-3.0.97}/tests/test_mcp.py +0 -0
- {drydock_cli-3.0.95 → drydock_cli-3.0.97}/tests/test_oneshot_unreachable.py +0 -0
- {drydock_cli-3.0.95 → drydock_cli-3.0.97}/tests/test_plan_autocontinue.py +0 -0
- {drydock_cli-3.0.95 → drydock_cli-3.0.97}/tests/test_poam.py +0 -0
- {drydock_cli-3.0.95 → drydock_cli-3.0.97}/tests/test_providers_unreachable.py +0 -0
- {drydock_cli-3.0.95 → drydock_cli-3.0.97}/tests/test_read_index.py +0 -0
- {drydock_cli-3.0.95 → drydock_cli-3.0.97}/tests/test_rmf.py +0 -0
- {drydock_cli-3.0.95 → drydock_cli-3.0.97}/tests/test_rmf_graph.py +0 -0
- {drydock_cli-3.0.95 → drydock_cli-3.0.97}/tests/test_rmf_stig_graph.py +0 -0
- {drydock_cli-3.0.95 → drydock_cli-3.0.97}/tests/test_runaway_repetition.py +0 -0
- {drydock_cli-3.0.95 → drydock_cli-3.0.97}/tests/test_server_probe.py +0 -0
- {drydock_cli-3.0.95 → drydock_cli-3.0.97}/tests/test_skills.py +0 -0
- {drydock_cli-3.0.95 → drydock_cli-3.0.97}/tests/test_stig.py +0 -0
- {drydock_cli-3.0.95 → drydock_cli-3.0.97}/tests/test_stop.py +0 -0
- {drydock_cli-3.0.95 → drydock_cli-3.0.97}/tests/test_streaming_newlines.py +0 -0
- {drydock_cli-3.0.95 → drydock_cli-3.0.97}/tests/test_subagent.py +0 -0
- {drydock_cli-3.0.95 → drydock_cli-3.0.97}/tests/test_system_prompt_help.py +0 -0
- {drydock_cli-3.0.95 → drydock_cli-3.0.97}/tests/test_todo.py +0 -0
- {drydock_cli-3.0.95 → drydock_cli-3.0.97}/tests/test_tool_arg_parsing.py +0 -0
- {drydock_cli-3.0.95 → drydock_cli-3.0.97}/tests/test_tools_undo.py +0 -0
- {drydock_cli-3.0.95 → drydock_cli-3.0.97}/tests/test_tui.py +0 -0
- {drydock_cli-3.0.95 → drydock_cli-3.0.97}/tests/test_tuning.py +0 -0
- {drydock_cli-3.0.95 → drydock_cli-3.0.97}/tests/test_viewimage.py +0 -0
- {drydock_cli-3.0.95 → drydock_cli-3.0.97}/tests/test_vision_input.py +0 -0
- {drydock_cli-3.0.95 → drydock_cli-3.0.97}/tests/test_web_tools.py +0 -0
- {drydock_cli-3.0.95 → drydock_cli-3.0.97}/tests/test_xccdf.py +0 -0
|
@@ -22,6 +22,22 @@ from pathlib import Path
|
|
|
22
22
|
# once it's hit — bounding RAM regardless of how much it tries to produce.
|
|
23
23
|
_MAX_BASH_OUTPUT_BYTES = 256 * 1024 # 256 KB — plenty of context, safe for RAM
|
|
24
24
|
_PARTIAL_TAIL = 4000 # chars of pre-timeout output to keep (tail) in the timeout msg
|
|
25
|
+
_DEFAULT_TIMEOUT = 120
|
|
26
|
+
_MAX_TIMEOUT = 1800 # 30 min hard ceiling — a single command shouldn't hang longer
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def _coerce_timeout(value) -> int:
|
|
30
|
+
"""Make the model-supplied timeout robust: local models often send it as a
|
|
31
|
+
string ("10"), and a 0/negative/absurd value would make EVERY command time
|
|
32
|
+
out instantly (or hang for hours). Coerce to int, fall back to the default on
|
|
33
|
+
junk, and clamp to (0, _MAX_TIMEOUT]."""
|
|
34
|
+
try:
|
|
35
|
+
t = int(float(value))
|
|
36
|
+
except (TypeError, ValueError):
|
|
37
|
+
return _DEFAULT_TIMEOUT
|
|
38
|
+
if t <= 0:
|
|
39
|
+
return _DEFAULT_TIMEOUT
|
|
40
|
+
return min(t, _MAX_TIMEOUT)
|
|
25
41
|
|
|
26
42
|
|
|
27
43
|
def _detect_bash() -> str | None:
|
|
@@ -585,7 +601,10 @@ def tool_read(params: dict, config: dict) -> str:
|
|
|
585
601
|
eff_limit = 2000 if limit is None else limit
|
|
586
602
|
selected = lines[offset:offset + eff_limit]
|
|
587
603
|
numbered = [f"{i + offset + 1}\t{line.rstrip()}" for i, line in enumerate(selected)]
|
|
588
|
-
|
|
604
|
+
# Drop NUL bytes (valid UTF-8, so errors='replace' keeps them) — raw NUL in
|
|
605
|
+
# a JSON tool result trips some LLM servers. ANSI is left as-is: unlike
|
|
606
|
+
# command output, a file's bytes are content the model may need verbatim.
|
|
607
|
+
result = "\n".join(numbered).replace("\x00", "")
|
|
589
608
|
if len(lines) > offset + eff_limit:
|
|
590
609
|
result += f"\n[... {len(lines) - offset - eff_limit} more lines]"
|
|
591
610
|
return result or "(empty file)"
|
|
@@ -916,7 +935,7 @@ def tool_bash(params: dict, config: dict) -> str:
|
|
|
916
935
|
# and crack hashes — a 30s wall killed legitimate long work before it could
|
|
917
936
|
# finish (terminal-bench: 16 tasks died at 30s on builds/training). Bounded,
|
|
918
937
|
# and the model can pass a larger `timeout` for genuinely heavy commands.
|
|
919
|
-
timeout = params.get("timeout", 120)
|
|
938
|
+
timeout = _coerce_timeout(params.get("timeout", 120))
|
|
920
939
|
reason = bash_safety.dangerous_command(cmd)
|
|
921
940
|
if reason is not None:
|
|
922
941
|
return bash_safety.refusal_message(cmd, reason)
|
|
@@ -1088,9 +1107,16 @@ def tool_grep(params: dict, config: dict) -> str:
|
|
|
1088
1107
|
cmd.extend(["--include", include])
|
|
1089
1108
|
cmd.extend([pattern, path])
|
|
1090
1109
|
result = subprocess.run(
|
|
1091
|
-
cmd, capture_output=True, text=True,
|
|
1110
|
+
cmd, capture_output=True, text=True, encoding="utf-8",
|
|
1111
|
+
errors="replace", timeout=30,
|
|
1092
1112
|
)
|
|
1093
|
-
|
|
1113
|
+
# grep exit codes: 0 = matched, 1 = no match, >=2 = ERROR (invalid regex,
|
|
1114
|
+
# unreadable path). Don't report an error as "(no matches)" — the model
|
|
1115
|
+
# would wrongly conclude the pattern is absent instead of fixing it.
|
|
1116
|
+
if result.returncode >= 2:
|
|
1117
|
+
err = (result.stderr or "").strip() or "grep failed"
|
|
1118
|
+
return f"Error: {err.splitlines()[0]}"
|
|
1119
|
+
output = _sanitize_bash_output(result.stdout).strip()
|
|
1094
1120
|
if not output:
|
|
1095
1121
|
return "(no matches)"
|
|
1096
1122
|
lines = output.split("\n")
|
|
@@ -58,6 +58,7 @@ tests/test_bash_sanitize.py
|
|
|
58
58
|
tests/test_bash_shell.py
|
|
59
59
|
tests/test_bash_stdin.py
|
|
60
60
|
tests/test_bash_timeout_network.py
|
|
61
|
+
tests/test_bash_timeout_param.py
|
|
61
62
|
tests/test_cci.py
|
|
62
63
|
tests/test_cli_agents.py
|
|
63
64
|
tests/test_compact_command.py
|
|
@@ -75,6 +76,7 @@ tests/test_first_run_setup.py
|
|
|
75
76
|
tests/test_gittools.py
|
|
76
77
|
tests/test_graphify_example.py
|
|
77
78
|
tests/test_graphrag.py
|
|
79
|
+
tests/test_grep_and_read_robust.py
|
|
78
80
|
tests/test_guards_and_tools.py
|
|
79
81
|
tests/test_hallucinated_tools.py
|
|
80
82
|
tests/test_leaked_tool_call.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.
|
|
10
|
+
version = "3.0.97"
|
|
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,29 @@
|
|
|
1
|
+
"""The model-supplied `timeout` must be robust. Local models often send it as a
|
|
2
|
+
string ("10"); a 0/negative value made EVERY command time out instantly; an
|
|
3
|
+
absurd value could hang for hours. _coerce_timeout normalizes all of these."""
|
|
4
|
+
from __future__ import annotations
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
import pytest
|
|
8
|
+
|
|
9
|
+
from drydock.tools import _coerce_timeout, tool_bash
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
@pytest.mark.parametrize("raw,expected", [
|
|
13
|
+
("10", 10), (30, 30), (15.7, 15), # numbers / stringified / float
|
|
14
|
+
(0, 120), (-5, 120), ("abc", 120), (None, 120), # invalid → default
|
|
15
|
+
(99999, 1800), (100000, 1800), # clamp to the 30-min ceiling
|
|
16
|
+
])
|
|
17
|
+
def test_coerce_timeout(raw, expected):
|
|
18
|
+
assert _coerce_timeout(raw) == expected
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def test_string_timeout_runs_instead_of_crashing():
|
|
22
|
+
# previously raised TypeError in the '>' comparison
|
|
23
|
+
out = tool_bash({"command": "echo hi", "timeout": "10"}, {"cwd": "/tmp"})
|
|
24
|
+
assert "hi" in out
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def test_zero_timeout_does_not_instant_timeout():
|
|
28
|
+
out = tool_bash({"command": "echo hi", "timeout": 0}, {"cwd": "/tmp"})
|
|
29
|
+
assert "hi" in out and "timed out" not in out
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
"""tool_grep must not report a grep ERROR (invalid regex, unreadable path — grep
|
|
2
|
+
exit >=2) as "(no matches)"; and both grep and Read must be binary-safe (no crash,
|
|
3
|
+
no raw NUL). Found by probing the grep/read I/O paths."""
|
|
4
|
+
from __future__ import annotations
|
|
5
|
+
|
|
6
|
+
from drydock.tools import tool_grep, tool_read
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def _grep(pattern, path):
|
|
10
|
+
return tool_grep({"pattern": pattern, "path": path}, {"cwd": "/tmp"})
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def test_grep_valid_match(tmp_path):
|
|
14
|
+
f = tmp_path / "a.txt"; f.write_text("hello world\nfoo\n")
|
|
15
|
+
assert "hello world" in _grep("hello", str(f))
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def test_grep_genuine_no_match(tmp_path):
|
|
19
|
+
f = tmp_path / "a.txt"; f.write_text("hello\n")
|
|
20
|
+
assert _grep("zzznope", str(f)).strip() == "(no matches)"
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def test_grep_invalid_regex_is_error_not_no_matches(tmp_path):
|
|
24
|
+
f = tmp_path / "a.txt"; f.write_text("hello\n")
|
|
25
|
+
out = _grep("[unclosed", str(f))
|
|
26
|
+
assert out.startswith("Error:") and "no matches" not in out
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def test_grep_missing_path_is_error(tmp_path):
|
|
30
|
+
out = _grep("x", str(tmp_path / "nope_xyz"))
|
|
31
|
+
assert out.startswith("Error:")
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def test_grep_binary_does_not_crash(tmp_path):
|
|
35
|
+
f = tmp_path / "b.bin"; f.write_bytes(b"\xff\xfe match \x00\xc0\n")
|
|
36
|
+
out = _grep("match", str(f))
|
|
37
|
+
assert "Error:" not in out or "no matches" in out or "match" in out # no exception
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def test_read_drops_nul_bytes(tmp_path):
|
|
41
|
+
f = tmp_path / "n.txt"; f.write_bytes(b"before\x00\x00after text\n")
|
|
42
|
+
out = tool_read({"file_path": str(f)}, {"cwd": str(tmp_path)})
|
|
43
|
+
assert "\x00" not in out and "after text" in out
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|