diff --git a/libs/deepagents/tests/unit_tests/backends/test_composite_backend.py b/libs/deepagents/tests/unit_tests/backends/test_composite_backend.py index 524d786bdb..473f827e23 100644 --- a/libs/deepagents/tests/unit_tests/backends/test_composite_backend.py +++ b/libs/deepagents/tests/unit_tests/backends/test_composite_backend.py @@ -683,24 +683,6 @@ def test_composite_backend_execute_without_sandbox_default(): comp.execute("ls -la") -def test_composite_backend_supports_execution_check(): - """Test the isinstance check works correctly for CompositeBackend.""" - mem_store = InMemoryStore() - - # CompositeBackend with sandbox default should pass isinstance check - sandbox = MockSandboxBackend(store=mem_store, namespace=lambda _rt: ("default",)) - comp_with_sandbox = CompositeBackend(default=sandbox, routes={}) - # Note: CompositeBackend itself has execute() method, so isinstance will pass - # but the actual support depends on the default backend - assert hasattr(comp_with_sandbox, "execute") - - # CompositeBackend with non-sandbox default should still have execute() method - # but will raise NotImplementedError when called - state = StoreBackend(store=mem_store, namespace=lambda _rt: ("default",)) - comp_without_sandbox = CompositeBackend(default=state, routes={}) - assert hasattr(comp_without_sandbox, "execute") - - def test_composite_backend_execute_with_routed_backends(): """Test that execution doesn't interfere with file routing.""" mem_store = InMemoryStore() diff --git a/libs/deepagents/tests/unit_tests/backends/test_file_format.py b/libs/deepagents/tests/unit_tests/backends/test_file_format.py index 47881c8407..f7f6f36576 100644 --- a/libs/deepagents/tests/unit_tests/backends/test_file_format.py +++ b/libs/deepagents/tests/unit_tests/backends/test_file_format.py @@ -7,7 +7,6 @@ from deepagents.backends.store import StoreBackend from deepagents.backends.utils import ( - compile_grep_include_glob, create_file_data, file_data_to_string, grep_matches_from_files, @@ -139,11 +138,6 @@ def test_grep_glob_matches_nothing() -> None: assert result.matches == [] -def test_compile_glob_is_cached() -> None: - assert compile_grep_include_glob("*.py") is compile_grep_include_glob("*.py") - assert compile_grep_include_glob("*.py") is not compile_grep_include_glob("*.md") - - def test_grep_glob_repeated_pattern_stays_correct() -> None: first = {"/x.py": create_file_data("hit"), "/x.md": create_file_data("hit")} second = {"/y.py": create_file_data("hit"), "/y.txt": create_file_data("hit")} diff --git a/libs/deepagents/tests/unit_tests/backends/test_local_shell_backend.py b/libs/deepagents/tests/unit_tests/backends/test_local_shell_backend.py index 9887245da5..8825b6dd06 100644 --- a/libs/deepagents/tests/unit_tests/backends/test_local_shell_backend.py +++ b/libs/deepagents/tests/unit_tests/backends/test_local_shell_backend.py @@ -1,12 +1,10 @@ """Unit tests for LocalShellBackend.""" import os -import subprocess import sys import tempfile import warnings from pathlib import Path -from unittest.mock import patch import pytest @@ -69,17 +67,6 @@ def test_local_shell_backend_execute_simple_command() -> None: assert result.truncated is False -def test_local_shell_backend_execute_starts_new_session() -> None: - """Test that commands cannot access the parent's controlling terminal.""" - completed = subprocess.CompletedProcess(args="echo hello", returncode=0, stdout="hello\n", stderr="") - with tempfile.TemporaryDirectory() as tmpdir: - backend = LocalShellBackend(root_dir=tmpdir) - with patch("subprocess.run", return_value=completed) as run: - backend.execute("echo hello") - - assert run.call_args.kwargs["start_new_session"] is True - - def test_local_shell_backend_cannot_open_parent_controlling_terminal(tmp_path: Path) -> None: """Test a command cannot open the controlling terminal owned by its parent.""" exit_code, output = _run_controlling_terminal_probe(tmp_path) diff --git a/libs/deepagents/tests/unit_tests/backends/test_sandbox_backend.py b/libs/deepagents/tests/unit_tests/backends/test_sandbox_backend.py index 85c2042588..88d0616295 100644 --- a/libs/deepagents/tests/unit_tests/backends/test_sandbox_backend.py +++ b/libs/deepagents/tests/unit_tests/backends/test_sandbox_backend.py @@ -683,24 +683,6 @@ def test_grep_path_glob_is_routed_for_slash_in_glob() -> None: assert "--include=" not in sandbox.last_command -def test_grep_path_glob_template_strips_leading_slash() -> None: - """Anchored globs (leading /) stay relative to the search root, not the filesystem root.""" - assert "lstrip" in _GREP_PATH_GLOB_TEMPLATE - assert "rel_glob" in _GREP_PATH_GLOB_TEMPLATE - # The raw glob_pat must not be passed directly to glob.glob — only rel_glob. - # Verify the template uses rel_glob in the glob() call, not glob_pat. - assert "glob.glob(rel_glob" in _GREP_PATH_GLOB_TEMPLATE - assert "glob.glob(glob_pat" not in _GREP_PATH_GLOB_TEMPLATE - - -def test_grep_path_glob_template_terminates_each_record() -> None: - """Each match record is explicitly newline-terminated to prevent concatenation.""" - # The template must strip the line's trailing newline and add an explicit one - # so a file whose last line lacks a final newline doesn't merge with the next. - assert "rstrip" in _GREP_PATH_GLOB_TEMPLATE - assert "line.rstrip" in _GREP_PATH_GLOB_TEMPLATE - - def test_grep_path_glob_parses_multiple_matches_no_trailing_newline() -> None: """Two matches where the first line has no trailing newline parse correctly.""" # Simulate the fixed template output: each record explicitly newline-terminated. diff --git a/libs/deepagents/tests/unit_tests/backends/test_timeout_compat.py b/libs/deepagents/tests/unit_tests/backends/test_timeout_compat.py index 17ddf1c080..85f60570ad 100644 --- a/libs/deepagents/tests/unit_tests/backends/test_timeout_compat.py +++ b/libs/deepagents/tests/unit_tests/backends/test_timeout_compat.py @@ -73,12 +73,6 @@ def test_kwargs_backend_returns_false(self) -> None: """A backend with **kwargs does not have a named `timeout` param.""" assert execute_accepts_timeout(KwargsBackend) is False - def test_result_is_cached(self) -> None: - execute_accepts_timeout(ModernBackend) - execute_accepts_timeout(ModernBackend) - info = execute_accepts_timeout.cache_info() - assert info.hits >= 1 - def test_logs_warning_on_inspect_failure(self, caplog: pytest.LogCaptureFixture) -> None: """If inspect.signature raises, a warning is logged and False returned.""" diff --git a/libs/deepagents/tests/unit_tests/middleware/test_compact_tool.py b/libs/deepagents/tests/unit_tests/middleware/test_compact_tool.py index 9d0b71ea1f..e409bf4f8b 100644 --- a/libs/deepagents/tests/unit_tests/middleware/test_compact_tool.py +++ b/libs/deepagents/tests/unit_tests/middleware/test_compact_tool.py @@ -11,7 +11,6 @@ from langchain_core.messages import AIMessage, HumanMessage, SystemMessage from langgraph.types import Command -from deepagents.backends.state import StateBackend from deepagents.middleware.summarization import ( SummarizationMiddleware, SummarizationToolMiddleware, @@ -474,27 +473,25 @@ def test_cutoff_exceeds_message_count(self) -> None: class TestCompactBackendUsage: """Test backend use for compact offloading.""" - def test_static_backend_is_passed_to_offload(self) -> None: - """Should pass the configured backend instance to offload.""" - backend = StateBackend() - mw = _make_middleware(backend=backend) - messages = _make_messages(10) - runtime = _make_runtime(messages) - - with ( - patch.object(mw._summarization, "_determine_cutoff_index", return_value=4), - patch.object( - mw._summarization, - "_partition_messages", - side_effect=lambda msgs, idx: (msgs[:idx], msgs[idx:]), - ), - patch.object(mw._summarization, "_create_summary", return_value="Summary."), - patch.object(mw._summarization, "_offload_to_backend", return_value=None) as offload, - ): - mw._run_compact(runtime) + def test_compact_writes_history_to_configured_backend(self) -> None: + """Compacted history is written through the configured backend.""" + backend = _make_mock_backend() + summarization = SummarizationMiddleware( + model=_make_mock_model(), + backend=backend, + trigger=("fraction", 0.85), + keep=("messages", 2), + ) + middleware = SummarizationToolMiddleware(summarization) + messages = [HumanMessage(content=f"Message {index}") for index in range(9)] + messages.append(_ai_message_with_usage(120_000)) + result = middleware._run_compact(_make_runtime(messages)) - offload.assert_called_once() - assert offload.call_args.args[0] is backend + event = result.update["_summarization_event"] + backend.write.assert_called_once() + path, content = backend.write.call_args.args + assert path == event["file_path"] + assert "Message 0" in content class TestComputeStateCutoff: @@ -650,11 +647,6 @@ def test_trigger_clauses_are_preferred_over_legacy_conditions(self) -> None: result = mw._run_compact(runtime) assert "_summarization_event" in result.update - def test_dict_trigger_constructs_langchain_trigger_clauses(self) -> None: - """Dict trigger input should populate LangChain's canonical trigger clauses.""" - mw = _make_middleware_with_trigger({"tokens": 100_000, "messages": 6}) - assert mw._summarization._lc_helper._trigger_clauses == [{"tokens": 100_000, "messages": 6}] - def test_dict_clause_list_uses_or_semantics(self) -> None: """Multiple dict trigger clauses use OR semantics for compact eligibility.""" mw = _make_middleware_with_trigger(("tokens", 100_000)) diff --git a/libs/deepagents/tests/unit_tests/middleware/test_rubric_middleware.py b/libs/deepagents/tests/unit_tests/middleware/test_rubric_middleware.py index 68b8f8afd8..eed124c501 100644 --- a/libs/deepagents/tests/unit_tests/middleware/test_rubric_middleware.py +++ b/libs/deepagents/tests/unit_tests/middleware/test_rubric_middleware.py @@ -204,10 +204,6 @@ def test_max_iterations_non_int_rejected(self) -> None: with pytest.raises(TypeError): RubricMiddleware(model=_STUB_MODEL, max_iterations="3") # type: ignore[arg-type] - def test_tools_default_to_empty(self) -> None: - mw = RubricMiddleware(model=_STUB_MODEL) - assert mw._tools == [] - def test_tools_propagated(self) -> None: @tool def my_tool(query: str) -> str: diff --git a/libs/deepagents/tests/unit_tests/test_artifacts_root.py b/libs/deepagents/tests/unit_tests/test_artifacts_root.py index f41d969d32..679503031d 100644 --- a/libs/deepagents/tests/unit_tests/test_artifacts_root.py +++ b/libs/deepagents/tests/unit_tests/test_artifacts_root.py @@ -35,28 +35,12 @@ def test_custom_artifacts_root(self) -> None: class TestFilesystemMiddlewareArtifactsRoot: - def test_default_prefixes(self) -> None: - mw = FilesystemMiddleware() - assert mw._large_tool_results_prefix == "/large_tool_results" - assert mw._conversation_history_prefix == "/conversation_history" - - def test_custom_artifacts_root_from_composite_backend(self) -> None: - backend = _make_composite_backend(artifacts_root="/workspace") - mw = FilesystemMiddleware(backend=backend) - assert mw._large_tool_results_prefix == "/workspace/large_tool_results" - assert mw._conversation_history_prefix == "/workspace/conversation_history" - def test_trailing_slash_normalized(self) -> None: backend = _make_composite_backend(artifacts_root="/workspace/") mw = FilesystemMiddleware(backend=backend) assert mw._large_tool_results_prefix == "/workspace/large_tool_results" assert mw._conversation_history_prefix == "/workspace/conversation_history" - def test_root_slash_no_double_slash(self) -> None: - mw = FilesystemMiddleware() - assert mw._large_tool_results_prefix == "/large_tool_results" - assert mw._conversation_history_prefix == "/conversation_history" - def test_large_tool_result_eviction_uses_artifacts_root(self) -> None: backend = _make_composite_backend(artifacts_root="/workspace") mw = FilesystemMiddleware(backend=backend, tool_token_limit_before_evict=100) @@ -95,12 +79,6 @@ def test_default_history_path_prefix(self) -> None: mw = create_summarization_middleware(model, backend) assert mw._history_path_prefix == "/conversation_history" - def test_custom_artifacts_root_from_composite_backend(self) -> None: - backend = _make_composite_backend(artifacts_root="/workspace") - model = FakeChatModel(messages=iter([])) - mw = create_summarization_middleware(model, backend) - assert mw._history_path_prefix == "/workspace/conversation_history" - def test_trailing_slash_normalized(self) -> None: backend = _make_composite_backend(artifacts_root="/workspace/") model = FakeChatModel(messages=iter([])) @@ -135,13 +113,6 @@ def test_large_tool_result_eviction(self) -> None: [resp] = backend.download_files(["/large_tool_results/evict_ws"]) assert resp.content is None - def test_summarization_history_prefix(self) -> None: - """Summarization middleware uses the correct history prefix from artifacts_root.""" - backend = _make_composite_backend(artifacts_root="/workspace") - model = FakeChatModel(messages=iter([])) - mw = create_summarization_middleware(model, backend) - assert mw._history_path_prefix == "/workspace/conversation_history" - class TestAsyncEvictionArtifactsRoot: """Tests for async eviction paths with custom artifacts_root.""" diff --git a/libs/deepagents/tests/unit_tests/test_nemotron_ultra_profile.py b/libs/deepagents/tests/unit_tests/test_nemotron_ultra_profile.py index 1738827376..f476fb0c57 100644 --- a/libs/deepagents/tests/unit_tests/test_nemotron_ultra_profile.py +++ b/libs/deepagents/tests/unit_tests/test_nemotron_ultra_profile.py @@ -948,20 +948,14 @@ def test_register_adds_ultra3_profiles_for_supported_providers() -> None: assert _HARNESS_PROFILE_SUFFIX_MARKER in (profile.system_prompt_suffix or "") assert "whole/full file" in profile.tool_description_overrides["read_file"] - assert [entry.name for entry in middleware] == [ - "NemotronProgressBudgetMiddleware", - "NemotronPolicyNudgeMiddleware", + assert {entry.name for entry in middleware} >= { "NemotronToolCallShim", "ReadFileContinuationNoticeMiddleware", - "ToolRetryMiddleware", - "ModelRateLimitRetryMiddleware", "ChatNVIDIAMessageCompatibilityMiddleware", - "NemotronReasoningTagCleanupMiddleware", "NemotronTextToolCallParser", - "FollowupDisciplineMiddleware", "EntityResolutionGuardMiddleware", "FinalAnswerGuardMiddleware", - ] + } finally: _HARNESS_PROFILES.clear() _HARNESS_PROFILES.update(original) diff --git a/libs/deepagents/tests/unit_tests/test_rubric_example.py b/libs/deepagents/tests/unit_tests/test_rubric_example.py index 2e8dbdc90e..835c136c19 100644 --- a/libs/deepagents/tests/unit_tests/test_rubric_example.py +++ b/libs/deepagents/tests/unit_tests/test_rubric_example.py @@ -41,8 +41,7 @@ def _load_example(monkeypatch: pytest.MonkeyPatch) -> ModuleType: def test_project_is_resolved_after_dotenv_load(monkeypatch: pytest.MonkeyPatch) -> None: module = _load_example(monkeypatch) - def load_dotenv(dotenv_path: str) -> bool: - assert dotenv_path == "settings" + def load_dotenv(_dotenv_path: str) -> bool: monkeypatch.setenv("LANGSMITH_PROJECT", "project-from-dotenv") return True