Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions libs/code/deepagents_code/hooks/manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,10 @@ def create(
) -> HooksManager:
"""Load hook configuration and return a ready manager.

Hooks v2 is in progress, so it stays off unless
`DEEPAGENTS_CODE_EXPERIMENTAL` is truthy; without it the manager is
inert and no hook (client- or server-owned) fires.

Never raises: a failed load yields an inert manager whose lifecycle
methods are all no-ops.

Expand Down Expand Up @@ -524,8 +528,11 @@ def _context(self, *, thread_id: str | None = None) -> ClientHookContext:


def _load_runtime(cwd: Path, *, trusted: bool) -> HooksRuntime | None:
from deepagents_code._env_vars import EXPERIMENTAL, is_env_truthy
from deepagents_code.hooks.runtime import HooksRuntime

if not is_env_truthy(EXPERIMENTAL):
return None
try:
return HooksRuntime.create(cwd=cwd, workspace_trusted=trusted)
except Exception:
Expand Down
20 changes: 20 additions & 0 deletions libs/code/tests/unit_tests/hooks/test_configuration.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
import pytest
from pydantic import ValidationError

from deepagents_code._env_vars import EXPERIMENTAL
from deepagents_code.approval_mode import ApprovalMode
from deepagents_code.hooks import migration
from deepagents_code.hooks.capabilities import (
DEFAULT_COMMAND_TIMEOUT_SECONDS,
Expand All @@ -22,6 +24,7 @@
compute_snapshot_id,
load_hooks_config,
)
from deepagents_code.hooks.manager import HookSessionIdentity, HooksManager
from deepagents_code.hooks.migration import migrate_legacy_hooks
from deepagents_code.hooks.models.config import HooksConfig
from deepagents_code.hooks.models.domain import HookEvent, HookOwner
Expand Down Expand Up @@ -482,3 +485,20 @@ def test_snapshot_rejects_matcher_for_unmatchable_event() -> None:

assert snapshot.handlers[HookEvent.STOP] == ()
assert [item.code for item in snapshot.diagnostics] == ["unsupported_matcher"]


def test_hooks_v2_requires_experimental_flag(
tmp_path: Path, monkeypatch: pytest.MonkeyPatch
) -> None:
"""No runtime loads — so no hook fires — until experimental mode is on."""

def build() -> HooksManager:
return HooksManager.create(
cwd=tmp_path,
identity=lambda: HookSessionIdentity("t-1", ApprovalMode.MANUAL),
notice=lambda _message: None,
)

assert not build().enabled
monkeypatch.setenv(EXPERIMENTAL, "1")
assert build().enabled
7 changes: 6 additions & 1 deletion libs/code/tests/unit_tests/test_non_interactive.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
from rich.style import Style
from rich.text import Text

from deepagents_code._env_vars import EXPERIMENTAL
from deepagents_code._tool_stream import (
TOOL_OUTPUT_TRUNCATION_MARKER,
UNRENDERABLE_TOOL_OUTPUT,
Expand Down Expand Up @@ -379,8 +380,11 @@ async def test_sandbox_type_passed_to_server(self) -> None:
assert kwargs["profile_overrides"] == {"max_input_tokens": 32_000}
assert kwargs["enable_interpreter"] is None

async def test_permission_hooks_override_headless_yolo_bypass(self) -> None:
async def test_permission_hooks_override_headless_yolo_bypass(
self, monkeypatch: pytest.MonkeyPatch
) -> None:
"""Permission hooks force client resolution while retaining YOLO context."""
monkeypatch.setenv(EXPERIMENTAL, "1")
runtime = MagicMock()
runtime.configured_events.return_value = frozenset(
{HookEvent.PERMISSION_REQUEST}
Expand Down Expand Up @@ -1676,6 +1680,7 @@ async def test_run_agent_loop_trusts_project_hooks_when_opted_in(
self, tmp_path: Path, monkeypatch: pytest.MonkeyPatch
) -> None:
"""`--trust-project-hooks` loads repository hook handlers."""
monkeypatch.setenv(EXPERIMENTAL, "1")
monkeypatch.chdir(tmp_path)
project_hooks = tmp_path / ".deepagents"
project_hooks.mkdir()
Expand Down
Loading