diff --git a/packages/narada-pyodide/pyproject.toml b/packages/narada-pyodide/pyproject.toml index 0a90196..a77c8bd 100644 --- a/packages/narada-pyodide/pyproject.toml +++ b/packages/narada-pyodide/pyproject.toml @@ -1,7 +1,7 @@ [project] name = "narada-pyodide" -version = "0.0.57" +version = "0.0.58" description = "Pyodide-compatible Python client SDK for Narada" license = "Apache-2.0" readme = "README.md" diff --git a/packages/narada-pyodide/src/narada/client.py b/packages/narada-pyodide/src/narada/client.py index fb7576a..9d6886d 100644 --- a/packages/narada-pyodide/src/narada/client.py +++ b/packages/narada-pyodide/src/narada/client.py @@ -84,11 +84,19 @@ async def open_and_initialize_cloud_browser_window( user_id=self._user_id, env=self._env, ) - request_body = { + request_body: dict[str, Any] = { "session_name": session_name, "session_timeout": session_timeout, "require_extension": require_extension, } + initiator_remote_dispatch_request_id = os.environ.get( + "NARADA_INITIATOR_REMOTE_DISPATCH_REQUEST_ID", "" + ).strip() + if not initiator_remote_dispatch_request_id: + raise ValueError("NARADA_INITIATOR_REMOTE_DISPATCH_REQUEST_ID is required") + request_body["initiator_remote_dispatch_request_id"] = ( + initiator_remote_dispatch_request_id + ) response = None max_attempts = 3 diff --git a/packages/narada-pyodide/tests/test_cloud_browser.py b/packages/narada-pyodide/tests/test_cloud_browser.py index c5b4081..7098da3 100644 --- a/packages/narada-pyodide/tests/test_cloud_browser.py +++ b/packages/narada-pyodide/tests/test_cloud_browser.py @@ -96,6 +96,9 @@ def new() -> SimpleNamespace: async def test_open_and_initialize_cloud_browser_window_maps_response( monkeypatch: pytest.MonkeyPatch, ) -> None: + monkeypatch.setenv( + "NARADA_INITIATOR_REMOTE_DISPATCH_REQUEST_ID", "request-maps-123" + ) pyfetch = AsyncMock( return_value=_FakeResponse( json_data={ @@ -132,6 +135,53 @@ async def test_open_and_initialize_cloud_browser_window_maps_response( "session_name": "demo", "session_timeout": 321, "require_extension": False, + "initiator_remote_dispatch_request_id": "request-maps-123", + } + + +@pytest.mark.asyncio +async def test_open_and_initialize_cloud_browser_window_requires_initiator_env( + monkeypatch: pytest.MonkeyPatch, +) -> None: + monkeypatch.delenv("NARADA_INITIATOR_REMOTE_DISPATCH_REQUEST_ID", raising=False) + pyfetch = AsyncMock() + narada_pkg, _, _ = _import_pyodide_narada(monkeypatch, pyfetch=pyfetch) + + client = narada_pkg.Narada(api_key="test-api-key") + with pytest.raises(ValueError, match="NARADA_INITIATOR_REMOTE_DISPATCH_REQUEST_ID"): + await client.open_and_initialize_cloud_browser_window() + + pyfetch.assert_not_awaited() + + +@pytest.mark.asyncio +async def test_open_and_initialize_cloud_browser_window_includes_initiator_request( + monkeypatch: pytest.MonkeyPatch, +) -> None: + monkeypatch.setenv( + "NARADA_INITIATOR_REMOTE_DISPATCH_REQUEST_ID", " request-local-123 " + ) + pyfetch = AsyncMock( + return_value=_FakeResponse( + json_data={ + "session_id": "session-123", + "session_name": "demo", + "browser_window_id": "browser-window-123", + } + ) + ) + narada_pkg, _, _ = _import_pyodide_narada(monkeypatch, pyfetch=pyfetch) + + client = narada_pkg.Narada(api_key="test-api-key") + await client.open_and_initialize_cloud_browser_window() + + call = pyfetch.await_args + assert call is not None + assert json.loads(call.kwargs["body"]) == { + "session_name": None, + "session_timeout": None, + "require_extension": True, + "initiator_remote_dispatch_request_id": "request-local-123", } @@ -142,6 +192,9 @@ async def test_open_and_initialize_cloud_browser_window_supports_frontend_bearer monkeypatch.delenv("NARADA_API_KEY", raising=False) monkeypatch.setenv("NARADA_USER_ID", "user-123") monkeypatch.setenv("NARADA_ENV", "dev") + monkeypatch.setenv( + "NARADA_INITIATOR_REMOTE_DISPATCH_REQUEST_ID", "request-bearer-123" + ) pyfetch = AsyncMock( side_effect=[ diff --git a/packages/narada/src/narada/window.py b/packages/narada/src/narada/window.py index 494a976..e5b963a 100644 --- a/packages/narada/src/narada/window.py +++ b/packages/narada/src/narada/window.py @@ -24,10 +24,10 @@ from narada_core.actions.critic import run_critic from narada_core.actions.models import ( DEFAULT_HITL_TIMEOUT_SECONDS, - AgenticMouseAction, - AgenticMouseActionRequest, AgenticMatchingSelectorsFinderRequest, AgenticMatchingSelectorsFinderResponse, + AgenticMouseAction, + AgenticMouseActionRequest, AgenticSelectorAction, AgenticSelectorRequest, AgenticSelectorResponse, diff --git a/uv.lock b/uv.lock index 2194bba..06f9677 100644 --- a/uv.lock +++ b/uv.lock @@ -356,7 +356,7 @@ requires-dist = [{ name = "pydantic", specifier = "==2.12.5" }] [[package]] name = "narada-pyodide" -version = "0.0.57" +version = "0.0.58" source = { editable = "packages/narada-pyodide" } dependencies = [ { name = "narada-core" },