narada 0.1.33a3__py3-none-any.whl → 0.1.33a5__py3-none-any.whl
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.
narada/client.py
CHANGED
|
@@ -10,15 +10,6 @@ from typing import Any
|
|
|
10
10
|
from uuid import uuid4
|
|
11
11
|
|
|
12
12
|
import aiohttp
|
|
13
|
-
import semver
|
|
14
|
-
from narada.config import BrowserConfig, ProxyConfig
|
|
15
|
-
from narada.utils import assert_never
|
|
16
|
-
from narada.version import __version__
|
|
17
|
-
from narada.window import (
|
|
18
|
-
LocalBrowserWindow,
|
|
19
|
-
CloudBrowserWindow,
|
|
20
|
-
create_side_panel_url,
|
|
21
|
-
)
|
|
22
13
|
from narada_core.errors import (
|
|
23
14
|
NaradaExtensionMissingError,
|
|
24
15
|
NaradaExtensionUnauthenticatedError,
|
|
@@ -27,6 +18,7 @@ from narada_core.errors import (
|
|
|
27
18
|
NaradaUnsupportedBrowserError,
|
|
28
19
|
)
|
|
29
20
|
from narada_core.models import _SdkConfig
|
|
21
|
+
from packaging.version import Version
|
|
30
22
|
from playwright._impl._errors import Error as PlaywrightError
|
|
31
23
|
from playwright.async_api import (
|
|
32
24
|
Browser,
|
|
@@ -34,14 +26,21 @@ from playwright.async_api import (
|
|
|
34
26
|
ElementHandle,
|
|
35
27
|
Page,
|
|
36
28
|
Playwright,
|
|
37
|
-
)
|
|
38
|
-
from playwright.async_api import TimeoutError as PlaywrightTimeoutError
|
|
39
|
-
from playwright.async_api import (
|
|
40
29
|
async_playwright,
|
|
41
30
|
)
|
|
31
|
+
from playwright.async_api import TimeoutError as PlaywrightTimeoutError
|
|
42
32
|
from playwright.async_api._context_manager import PlaywrightContextManager
|
|
43
33
|
from rich.console import Console
|
|
44
34
|
|
|
35
|
+
from narada.config import BrowserConfig, ProxyConfig
|
|
36
|
+
from narada.utils import assert_never
|
|
37
|
+
from narada.version import __version__
|
|
38
|
+
from narada.window import (
|
|
39
|
+
CloudBrowserWindow,
|
|
40
|
+
LocalBrowserWindow,
|
|
41
|
+
create_side_panel_url,
|
|
42
|
+
)
|
|
43
|
+
|
|
45
44
|
|
|
46
45
|
@dataclass
|
|
47
46
|
class _LaunchBrowserResult:
|
|
@@ -57,14 +56,23 @@ class Narada:
|
|
|
57
56
|
_EXTENSION_UNAUTHENTICATED_INDICATOR_SELECTOR = "#narada-extension-unauthenticated"
|
|
58
57
|
_INITIALIZATION_ERROR_INDICATOR_SELECTOR = "#narada-initialization-error"
|
|
59
58
|
|
|
60
|
-
|
|
59
|
+
_auth_headers: dict[str, str]
|
|
61
60
|
_console: Console
|
|
62
61
|
_playwright_context_manager: PlaywrightContextManager | None = None
|
|
63
62
|
_playwright: Playwright | None = None
|
|
64
63
|
_cloud_windows: set[CloudBrowserWindow]
|
|
65
64
|
|
|
66
|
-
def __init__(
|
|
67
|
-
self
|
|
65
|
+
def __init__(
|
|
66
|
+
self,
|
|
67
|
+
*,
|
|
68
|
+
api_key: str | None = None,
|
|
69
|
+
auth_headers: dict[str, str] | None = None,
|
|
70
|
+
) -> None:
|
|
71
|
+
if auth_headers is not None:
|
|
72
|
+
self._auth_headers = auth_headers
|
|
73
|
+
else:
|
|
74
|
+
api_key = api_key or os.environ["NARADA_API_KEY"]
|
|
75
|
+
self._auth_headers = {"x-api-key": api_key}
|
|
68
76
|
self._console = Console()
|
|
69
77
|
self._cloud_windows = set()
|
|
70
78
|
|
|
@@ -94,9 +102,7 @@ class Narada:
|
|
|
94
102
|
|
|
95
103
|
try:
|
|
96
104
|
async with aiohttp.ClientSession() as session:
|
|
97
|
-
async with session.get(
|
|
98
|
-
url, headers={"x-api-key": self._api_key}
|
|
99
|
-
) as resp:
|
|
105
|
+
async with session.get(url, headers=self._auth_headers) as resp:
|
|
100
106
|
if not resp.ok:
|
|
101
107
|
logging.warning(
|
|
102
108
|
"Failed to fetch SDK config: %s %s",
|
|
@@ -116,7 +122,9 @@ class Narada:
|
|
|
116
122
|
return
|
|
117
123
|
|
|
118
124
|
package_config = config.packages["narada"]
|
|
119
|
-
|
|
125
|
+
current_version = Version(__version__)
|
|
126
|
+
min_required_version = Version(package_config.min_required_version)
|
|
127
|
+
if current_version < min_required_version:
|
|
120
128
|
raise RuntimeError(
|
|
121
129
|
f"narada<={__version__} is not supported. Please upgrade to version "
|
|
122
130
|
f"{package_config.min_required_version} or higher."
|
|
@@ -137,7 +145,7 @@ class Narada:
|
|
|
137
145
|
await self._fix_download_behavior(side_panel_page)
|
|
138
146
|
|
|
139
147
|
return LocalBrowserWindow(
|
|
140
|
-
|
|
148
|
+
auth_headers=self._auth_headers,
|
|
141
149
|
browser_process_id=launch_browser_result.browser_process_id,
|
|
142
150
|
browser_window_id=browser_window_id,
|
|
143
151
|
config=config,
|
|
@@ -170,7 +178,7 @@ class Narada:
|
|
|
170
178
|
async with aiohttp.ClientSession() as session:
|
|
171
179
|
async with session.post(
|
|
172
180
|
endpoint_url,
|
|
173
|
-
headers=
|
|
181
|
+
headers=self._auth_headers,
|
|
174
182
|
json=request_body,
|
|
175
183
|
timeout=aiohttp.ClientTimeout(
|
|
176
184
|
total=180
|
|
@@ -200,7 +208,7 @@ class Narada:
|
|
|
200
208
|
async with aiohttp.ClientSession() as cleanup_session:
|
|
201
209
|
async with cleanup_session.post(
|
|
202
210
|
f"{base_url}/cloud-browser/stop-cloud-browser-session",
|
|
203
|
-
headers=
|
|
211
|
+
headers=self._auth_headers,
|
|
204
212
|
json={"session_id": session_id},
|
|
205
213
|
timeout=aiohttp.ClientTimeout(total=10),
|
|
206
214
|
) as resp:
|
|
@@ -248,7 +256,7 @@ class Narada:
|
|
|
248
256
|
cloud_window = CloudBrowserWindow(
|
|
249
257
|
browser_window_id=browser_window_id,
|
|
250
258
|
session_id=session_id,
|
|
251
|
-
|
|
259
|
+
auth_headers=self._auth_headers,
|
|
252
260
|
)
|
|
253
261
|
|
|
254
262
|
# Track the window for cleanup in __aexit__
|
|
@@ -311,7 +319,7 @@ class Narada:
|
|
|
311
319
|
self._print_success_message(browser_window_id)
|
|
312
320
|
|
|
313
321
|
return LocalBrowserWindow(
|
|
314
|
-
|
|
322
|
+
auth_headers=self._auth_headers,
|
|
315
323
|
browser_process_id=None,
|
|
316
324
|
browser_window_id=browser_window_id,
|
|
317
325
|
config=config,
|
narada/window.py
CHANGED
|
@@ -8,7 +8,6 @@ from pathlib import Path
|
|
|
8
8
|
from typing import IO, Any, TypeVar, overload
|
|
9
9
|
|
|
10
10
|
import aiohttp
|
|
11
|
-
from narada.config import BrowserConfig
|
|
12
11
|
from narada_core.actions.models import (
|
|
13
12
|
AgenticMouseAction,
|
|
14
13
|
AgenticMouseActionRequest,
|
|
@@ -53,6 +52,8 @@ from playwright.async_api import (
|
|
|
53
52
|
)
|
|
54
53
|
from pydantic import BaseModel
|
|
55
54
|
|
|
55
|
+
from narada.config import BrowserConfig
|
|
56
|
+
|
|
56
57
|
logger = logging.getLogger(__name__)
|
|
57
58
|
|
|
58
59
|
_StructuredOutput = TypeVar("_StructuredOutput", bound=BaseModel)
|
|
@@ -67,18 +68,18 @@ class _PresignedPost(BaseModel):
|
|
|
67
68
|
|
|
68
69
|
|
|
69
70
|
class BaseBrowserWindow(ABC):
|
|
70
|
-
|
|
71
|
+
_auth_headers: dict[str, str]
|
|
71
72
|
_base_url: str
|
|
72
73
|
_browser_window_id: str
|
|
73
74
|
|
|
74
75
|
def __init__(
|
|
75
76
|
self,
|
|
76
77
|
*,
|
|
77
|
-
|
|
78
|
+
auth_headers: dict[str, str],
|
|
78
79
|
base_url: str,
|
|
79
80
|
browser_window_id: str,
|
|
80
81
|
) -> None:
|
|
81
|
-
self.
|
|
82
|
+
self._auth_headers = auth_headers
|
|
82
83
|
self._base_url = base_url
|
|
83
84
|
self._browser_window_id = browser_window_id
|
|
84
85
|
|
|
@@ -99,7 +100,7 @@ class BaseBrowserWindow(ABC):
|
|
|
99
100
|
# First generate a presigned POST for uploading the file.
|
|
100
101
|
async with session.post(
|
|
101
102
|
f"{self._base_url}/remote-dispatch/generate-file-upload-presigned-post",
|
|
102
|
-
headers=
|
|
103
|
+
headers=self._auth_headers,
|
|
103
104
|
json={"filename": filename},
|
|
104
105
|
) as resp:
|
|
105
106
|
resp.raise_for_status()
|
|
@@ -192,8 +193,6 @@ class BaseBrowserWindow(ABC):
|
|
|
192
193
|
"""
|
|
193
194
|
deadline = time.monotonic() + timeout
|
|
194
195
|
|
|
195
|
-
headers = {"x-api-key": self._api_key}
|
|
196
|
-
|
|
197
196
|
agent_prefix = (
|
|
198
197
|
agent.prompt_prefix() if isinstance(agent, Agent) else f"{agent} "
|
|
199
198
|
)
|
|
@@ -238,7 +237,7 @@ class BaseBrowserWindow(ABC):
|
|
|
238
237
|
async with aiohttp.ClientSession() as session:
|
|
239
238
|
async with session.post(
|
|
240
239
|
f"{self._base_url}/remote-dispatch",
|
|
241
|
-
headers=
|
|
240
|
+
headers=self._auth_headers,
|
|
242
241
|
json=body,
|
|
243
242
|
timeout=aiohttp.ClientTimeout(total=timeout),
|
|
244
243
|
) as resp:
|
|
@@ -248,7 +247,7 @@ class BaseBrowserWindow(ABC):
|
|
|
248
247
|
while (now := time.monotonic()) < deadline:
|
|
249
248
|
async with session.get(
|
|
250
249
|
f"{self._base_url}/remote-dispatch/responses/{request_id}",
|
|
251
|
-
headers=
|
|
250
|
+
headers=self._auth_headers,
|
|
252
251
|
timeout=aiohttp.ClientTimeout(total=deadline - now),
|
|
253
252
|
) as resp:
|
|
254
253
|
resp.raise_for_status()
|
|
@@ -380,6 +379,7 @@ class BaseBrowserWindow(ABC):
|
|
|
380
379
|
selectors=selectors,
|
|
381
380
|
fallback_operator_query=fallback_operator_query,
|
|
382
381
|
),
|
|
382
|
+
response_model=response_model,
|
|
383
383
|
timeout=timeout,
|
|
384
384
|
)
|
|
385
385
|
|
|
@@ -511,8 +511,6 @@ class BaseBrowserWindow(ABC):
|
|
|
511
511
|
*,
|
|
512
512
|
timeout: int | None = None,
|
|
513
513
|
) -> _ResponseModel | None:
|
|
514
|
-
headers = {"x-api-key": self._api_key}
|
|
515
|
-
|
|
516
514
|
body = {
|
|
517
515
|
"action": request.model_dump(),
|
|
518
516
|
"browserWindowId": self.browser_window_id,
|
|
@@ -523,7 +521,7 @@ class BaseBrowserWindow(ABC):
|
|
|
523
521
|
async with aiohttp.ClientSession() as session:
|
|
524
522
|
async with session.post(
|
|
525
523
|
f"{self._base_url}/extension-actions",
|
|
526
|
-
headers=
|
|
524
|
+
headers=self._auth_headers,
|
|
527
525
|
json=body,
|
|
528
526
|
# Don't specify `timeout` here as the (soft) timeout is handled by the server.
|
|
529
527
|
) as resp:
|
|
@@ -551,7 +549,7 @@ class LocalBrowserWindow(BaseBrowserWindow):
|
|
|
551
549
|
def __init__(
|
|
552
550
|
self,
|
|
553
551
|
*,
|
|
554
|
-
|
|
552
|
+
auth_headers: dict[str, str],
|
|
555
553
|
browser_process_id: int | None,
|
|
556
554
|
browser_window_id: str,
|
|
557
555
|
config: BrowserConfig,
|
|
@@ -559,7 +557,7 @@ class LocalBrowserWindow(BaseBrowserWindow):
|
|
|
559
557
|
) -> None:
|
|
560
558
|
base_url = os.getenv("NARADA_API_BASE_URL", "https://api.narada.ai/fast/v2")
|
|
561
559
|
super().__init__(
|
|
562
|
-
|
|
560
|
+
auth_headers=auth_headers,
|
|
563
561
|
base_url=base_url,
|
|
564
562
|
browser_window_id=browser_window_id,
|
|
565
563
|
)
|
|
@@ -591,10 +589,19 @@ class LocalBrowserWindow(BaseBrowserWindow):
|
|
|
591
589
|
|
|
592
590
|
|
|
593
591
|
class RemoteBrowserWindow(BaseBrowserWindow):
|
|
594
|
-
def __init__(
|
|
592
|
+
def __init__(
|
|
593
|
+
self,
|
|
594
|
+
*,
|
|
595
|
+
browser_window_id: str,
|
|
596
|
+
api_key: str | None = None,
|
|
597
|
+
auth_headers: dict[str, str] | None = None,
|
|
598
|
+
) -> None:
|
|
595
599
|
base_url = os.getenv("NARADA_API_BASE_URL", "https://api.narada.ai/fast/v2")
|
|
600
|
+
if auth_headers is None:
|
|
601
|
+
api_key = api_key or os.environ["NARADA_API_KEY"]
|
|
602
|
+
auth_headers = {"x-api-key": api_key}
|
|
596
603
|
super().__init__(
|
|
597
|
-
|
|
604
|
+
auth_headers=auth_headers,
|
|
598
605
|
base_url=base_url,
|
|
599
606
|
browser_window_id=browser_window_id,
|
|
600
607
|
)
|
|
@@ -616,10 +623,14 @@ class CloudBrowserWindow(BaseBrowserWindow):
|
|
|
616
623
|
browser_window_id: str,
|
|
617
624
|
session_id: str,
|
|
618
625
|
api_key: str | None = None,
|
|
626
|
+
auth_headers: dict[str, str] | None = None,
|
|
619
627
|
) -> None:
|
|
620
628
|
base_url = os.getenv("NARADA_API_BASE_URL", "https://api.narada.ai/fast/v2")
|
|
629
|
+
if auth_headers is None:
|
|
630
|
+
api_key = api_key or os.environ["NARADA_API_KEY"]
|
|
631
|
+
auth_headers = {"x-api-key": api_key}
|
|
621
632
|
super().__init__(
|
|
622
|
-
|
|
633
|
+
auth_headers=auth_headers,
|
|
623
634
|
base_url=base_url,
|
|
624
635
|
browser_window_id=browser_window_id,
|
|
625
636
|
)
|
|
@@ -631,7 +642,7 @@ class CloudBrowserWindow(BaseBrowserWindow):
|
|
|
631
642
|
async with aiohttp.ClientSession() as session:
|
|
632
643
|
async with session.post(
|
|
633
644
|
f"{self._base_url}/cloud-browser/stop-cloud-browser-session",
|
|
634
|
-
headers=
|
|
645
|
+
headers=self._auth_headers,
|
|
635
646
|
json={
|
|
636
647
|
"session_id": self._session_id,
|
|
637
648
|
},
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: narada
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.33a5
|
|
4
4
|
Summary: Python client SDK for Narada
|
|
5
5
|
Project-URL: Homepage, https://github.com/NaradaAI/narada-python-sdk/narada
|
|
6
6
|
Project-URL: Repository, https://github.com/NaradaAI/narada-python-sdk
|
|
@@ -10,9 +10,9 @@ License-Expression: Apache-2.0
|
|
|
10
10
|
Requires-Python: >=3.12
|
|
11
11
|
Requires-Dist: aiohttp>=3.12.13
|
|
12
12
|
Requires-Dist: narada-core==0.0.11
|
|
13
|
+
Requires-Dist: packaging==24.2
|
|
13
14
|
Requires-Dist: playwright>=1.53.0
|
|
14
15
|
Requires-Dist: rich>=14.0.0
|
|
15
|
-
Requires-Dist: semver>=3.0.4
|
|
16
16
|
Description-Content-Type: text/markdown
|
|
17
17
|
|
|
18
18
|
<p align="center">
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
narada/__init__.py,sha256=gVa9HUFTeHot7VR2XPtCEsVeRiK7MDJJvKU1eEhLqXQ,1013
|
|
2
|
-
narada/client.py,sha256=
|
|
2
|
+
narada/client.py,sha256=HSxwlKzYZuLt-BfReXDSAOSV6g0DCrcfFbrVc13VJMk,26923
|
|
3
3
|
narada/config.py,sha256=S0B8GNd-0td_69oKaPN60WAq_ODeYU7avE_KAxN5vCg,3052
|
|
4
4
|
narada/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
5
5
|
narada/utils.py,sha256=gdLwNMXPpRohDcIIe0cB3KhvZ8X1QfAlKVh1sXWeJmk,1284
|
|
6
6
|
narada/version.py,sha256=kwW6yy0_4Pf3kt888eeCG0VwBb2L2rCkrkpdZEC_3rA,193
|
|
7
|
-
narada/window.py,sha256
|
|
8
|
-
narada-0.1.
|
|
9
|
-
narada-0.1.
|
|
10
|
-
narada-0.1.
|
|
7
|
+
narada/window.py,sha256=-lN9ey3KSasvyQNzkh1ejPMmlojlVbTf9jqDT41YGr0,23454
|
|
8
|
+
narada-0.1.33a5.dist-info/METADATA,sha256=M817Dy9ZvotiB-Gml3AjATk-2M0bCXwApuTzAWPnFTA,5151
|
|
9
|
+
narada-0.1.33a5.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
|
|
10
|
+
narada-0.1.33a5.dist-info/RECORD,,
|
|
File without changes
|