anchorbrowser 0.1.0a1__py3-none-any.whl → 0.1.0a2__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.
- anchorbrowser/_client.py +17 -5
- anchorbrowser/_models.py +23 -2
- anchorbrowser/_version.py +1 -1
- anchorbrowser/lib/agent.py +69 -0
- anchorbrowser/lib/browser.py +186 -0
- anchorbrowser/resources/agent.py +305 -0
- anchorbrowser/resources/browser.py +152 -0
- anchorbrowser/types/extension_manifest.py +4 -1
- {anchorbrowser-0.1.0a1.dist-info → anchorbrowser-0.1.0a2.dist-info}/METADATA +3 -1
- {anchorbrowser-0.1.0a1.dist-info → anchorbrowser-0.1.0a2.dist-info}/RECORD +12 -8
- {anchorbrowser-0.1.0a1.dist-info → anchorbrowser-0.1.0a2.dist-info}/WHEEL +0 -0
- {anchorbrowser-0.1.0a1.dist-info → anchorbrowser-0.1.0a2.dist-info}/licenses/LICENSE +0 -0
anchorbrowser/_client.py
CHANGED
|
@@ -21,7 +21,7 @@ from ._types import (
|
|
|
21
21
|
)
|
|
22
22
|
from ._utils import is_given, get_async_library
|
|
23
23
|
from ._version import __version__
|
|
24
|
-
from .resources import tools, profiles, extensions
|
|
24
|
+
from .resources import agent, tools, browser, profiles, extensions
|
|
25
25
|
from ._streaming import Stream as Stream, AsyncStream as AsyncStream
|
|
26
26
|
from ._exceptions import APIStatusError, AnchorbrowserError
|
|
27
27
|
from ._base_client import (
|
|
@@ -48,6 +48,8 @@ class Anchorbrowser(SyncAPIClient):
|
|
|
48
48
|
sessions: sessions.SessionsResource
|
|
49
49
|
tools: tools.ToolsResource
|
|
50
50
|
extensions: extensions.ExtensionsResource
|
|
51
|
+
browser: browser.BrowserResource
|
|
52
|
+
agent: agent.AgentResource
|
|
51
53
|
with_raw_response: AnchorbrowserWithRawResponse
|
|
52
54
|
with_streaming_response: AnchorbrowserWithStreamedResponse
|
|
53
55
|
|
|
@@ -109,6 +111,8 @@ class Anchorbrowser(SyncAPIClient):
|
|
|
109
111
|
self.sessions = sessions.SessionsResource(self)
|
|
110
112
|
self.tools = tools.ToolsResource(self)
|
|
111
113
|
self.extensions = extensions.ExtensionsResource(self)
|
|
114
|
+
self.browser = browser.BrowserResource(self)
|
|
115
|
+
self.agent = agent.AgentResource(self)
|
|
112
116
|
self.with_raw_response = AnchorbrowserWithRawResponse(self)
|
|
113
117
|
self.with_streaming_response = AnchorbrowserWithStreamedResponse(self)
|
|
114
118
|
|
|
@@ -222,6 +226,8 @@ class AsyncAnchorbrowser(AsyncAPIClient):
|
|
|
222
226
|
sessions: sessions.AsyncSessionsResource
|
|
223
227
|
tools: tools.AsyncToolsResource
|
|
224
228
|
extensions: extensions.AsyncExtensionsResource
|
|
229
|
+
browser: browser.AsyncBrowserResource
|
|
230
|
+
agent: agent.AsyncAgentResource
|
|
225
231
|
with_raw_response: AsyncAnchorbrowserWithRawResponse
|
|
226
232
|
with_streaming_response: AsyncAnchorbrowserWithStreamedResponse
|
|
227
233
|
|
|
@@ -283,6 +289,8 @@ class AsyncAnchorbrowser(AsyncAPIClient):
|
|
|
283
289
|
self.sessions = sessions.AsyncSessionsResource(self)
|
|
284
290
|
self.tools = tools.AsyncToolsResource(self)
|
|
285
291
|
self.extensions = extensions.AsyncExtensionsResource(self)
|
|
292
|
+
self.browser = browser.AsyncBrowserResource(self)
|
|
293
|
+
self.agent = agent.AsyncAgentResource(self)
|
|
286
294
|
self.with_raw_response = AsyncAnchorbrowserWithRawResponse(self)
|
|
287
295
|
self.with_streaming_response = AsyncAnchorbrowserWithStreamedResponse(self)
|
|
288
296
|
|
|
@@ -397,7 +405,8 @@ class AnchorbrowserWithRawResponse:
|
|
|
397
405
|
self.sessions = sessions.SessionsResourceWithRawResponse(client.sessions)
|
|
398
406
|
self.tools = tools.ToolsResourceWithRawResponse(client.tools)
|
|
399
407
|
self.extensions = extensions.ExtensionsResourceWithRawResponse(client.extensions)
|
|
400
|
-
|
|
408
|
+
self.browser = browser.BrowserResourceWithRawResponse(client.browser)
|
|
409
|
+
self.agent = agent.AgentResourceWithRawResponse(client.agent)
|
|
401
410
|
|
|
402
411
|
class AsyncAnchorbrowserWithRawResponse:
|
|
403
412
|
def __init__(self, client: AsyncAnchorbrowser) -> None:
|
|
@@ -405,7 +414,8 @@ class AsyncAnchorbrowserWithRawResponse:
|
|
|
405
414
|
self.sessions = sessions.AsyncSessionsResourceWithRawResponse(client.sessions)
|
|
406
415
|
self.tools = tools.AsyncToolsResourceWithRawResponse(client.tools)
|
|
407
416
|
self.extensions = extensions.AsyncExtensionsResourceWithRawResponse(client.extensions)
|
|
408
|
-
|
|
417
|
+
self.browser = browser.AsyncBrowserResourceWithRawResponse(client.browser)
|
|
418
|
+
self.agent = agent.AsyncAgentResourceWithRawResponse(client.agent)
|
|
409
419
|
|
|
410
420
|
class AnchorbrowserWithStreamedResponse:
|
|
411
421
|
def __init__(self, client: Anchorbrowser) -> None:
|
|
@@ -413,7 +423,8 @@ class AnchorbrowserWithStreamedResponse:
|
|
|
413
423
|
self.sessions = sessions.SessionsResourceWithStreamingResponse(client.sessions)
|
|
414
424
|
self.tools = tools.ToolsResourceWithStreamingResponse(client.tools)
|
|
415
425
|
self.extensions = extensions.ExtensionsResourceWithStreamingResponse(client.extensions)
|
|
416
|
-
|
|
426
|
+
self.browser = browser.BrowserResourceWithStreamingResponse(client.browser)
|
|
427
|
+
self.agent = agent.AgentResourceWithStreamingResponse(client.agent)
|
|
417
428
|
|
|
418
429
|
class AsyncAnchorbrowserWithStreamedResponse:
|
|
419
430
|
def __init__(self, client: AsyncAnchorbrowser) -> None:
|
|
@@ -421,7 +432,8 @@ class AsyncAnchorbrowserWithStreamedResponse:
|
|
|
421
432
|
self.sessions = sessions.AsyncSessionsResourceWithStreamingResponse(client.sessions)
|
|
422
433
|
self.tools = tools.AsyncToolsResourceWithStreamingResponse(client.tools)
|
|
423
434
|
self.extensions = extensions.AsyncExtensionsResourceWithStreamingResponse(client.extensions)
|
|
424
|
-
|
|
435
|
+
self.browser = browser.AsyncBrowserResourceWithStreamingResponse(client.browser)
|
|
436
|
+
self.agent = agent.AsyncAgentResourceWithStreamingResponse(client.agent)
|
|
425
437
|
|
|
426
438
|
Client = Anchorbrowser
|
|
427
439
|
|
anchorbrowser/_models.py
CHANGED
|
@@ -208,14 +208,18 @@ class BaseModel(pydantic.BaseModel):
|
|
|
208
208
|
else:
|
|
209
209
|
fields_values[name] = field_get_default(field)
|
|
210
210
|
|
|
211
|
+
extra_field_type = _get_extra_fields_type(__cls)
|
|
212
|
+
|
|
211
213
|
_extra = {}
|
|
212
214
|
for key, value in values.items():
|
|
213
215
|
if key not in model_fields:
|
|
216
|
+
parsed = construct_type(value=value, type_=extra_field_type) if extra_field_type is not None else value
|
|
217
|
+
|
|
214
218
|
if PYDANTIC_V2:
|
|
215
|
-
_extra[key] =
|
|
219
|
+
_extra[key] = parsed
|
|
216
220
|
else:
|
|
217
221
|
_fields_set.add(key)
|
|
218
|
-
fields_values[key] =
|
|
222
|
+
fields_values[key] = parsed
|
|
219
223
|
|
|
220
224
|
object.__setattr__(m, "__dict__", fields_values)
|
|
221
225
|
|
|
@@ -370,6 +374,23 @@ def _construct_field(value: object, field: FieldInfo, key: str) -> object:
|
|
|
370
374
|
return construct_type(value=value, type_=type_, metadata=getattr(field, "metadata", None))
|
|
371
375
|
|
|
372
376
|
|
|
377
|
+
def _get_extra_fields_type(cls: type[pydantic.BaseModel]) -> type | None:
|
|
378
|
+
if not PYDANTIC_V2:
|
|
379
|
+
# TODO
|
|
380
|
+
return None
|
|
381
|
+
|
|
382
|
+
schema = cls.__pydantic_core_schema__
|
|
383
|
+
if schema["type"] == "model":
|
|
384
|
+
fields = schema["schema"]
|
|
385
|
+
if fields["type"] == "model-fields":
|
|
386
|
+
extras = fields.get("extras_schema")
|
|
387
|
+
if extras and "cls" in extras:
|
|
388
|
+
# mypy can't narrow the type
|
|
389
|
+
return extras["cls"] # type: ignore[no-any-return]
|
|
390
|
+
|
|
391
|
+
return None
|
|
392
|
+
|
|
393
|
+
|
|
373
394
|
def is_basemodel(type_: type) -> bool:
|
|
374
395
|
"""Returns whether or not the given type is either a `BaseModel` or a union of `BaseModel`"""
|
|
375
396
|
if is_union(type_):
|
anchorbrowser/_version.py
CHANGED
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import json
|
|
2
|
+
import asyncio
|
|
3
|
+
import threading
|
|
4
|
+
from typing import Any, Dict, Callable, Optional, TypedDict
|
|
5
|
+
from asyncio import Future
|
|
6
|
+
|
|
7
|
+
from ..lib.browser import BrowserSetup, get_agent_ws_url
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class AgentTaskParams(TypedDict, total=False):
|
|
11
|
+
url: Optional[str]
|
|
12
|
+
output_schema: Optional[Dict[str, Any]]
|
|
13
|
+
on_agent_step: Optional[Callable[[str], None]]
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def create_task_payload(prompt: str, output_schema: Optional[Dict[str, Any]] = None) -> str:
|
|
17
|
+
if not prompt or prompt.strip() == "":
|
|
18
|
+
raise ValueError("Prompt cannot be empty")
|
|
19
|
+
|
|
20
|
+
return json.dumps(
|
|
21
|
+
{
|
|
22
|
+
"prompt": prompt,
|
|
23
|
+
"output_schema": output_schema,
|
|
24
|
+
}
|
|
25
|
+
)
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def on_agent_step_sync(on_agent_step: Callable[[str], None], browser_setup: BrowserSetup) -> Future[None]:
|
|
29
|
+
import websockets
|
|
30
|
+
|
|
31
|
+
async def websocket_listener() -> None:
|
|
32
|
+
ws_url = get_agent_ws_url(browser_setup.base_url, browser_setup.session_id)
|
|
33
|
+
try:
|
|
34
|
+
async with websockets.connect(ws_url) as ws:
|
|
35
|
+
async for ws_msg in ws:
|
|
36
|
+
on_agent_step(str(ws_msg))
|
|
37
|
+
except Exception as e:
|
|
38
|
+
future.set_exception(e)
|
|
39
|
+
|
|
40
|
+
def run_in_thread() -> None:
|
|
41
|
+
loop = asyncio.new_event_loop()
|
|
42
|
+
asyncio.set_event_loop(loop)
|
|
43
|
+
try:
|
|
44
|
+
loop.run_until_complete(websocket_listener())
|
|
45
|
+
finally:
|
|
46
|
+
loop.close()
|
|
47
|
+
|
|
48
|
+
# Create a future to track the task
|
|
49
|
+
future = Future[None]()
|
|
50
|
+
try:
|
|
51
|
+
thread = threading.Thread(target=lambda: future.set_result(run_in_thread()))
|
|
52
|
+
thread.daemon = True
|
|
53
|
+
thread.start()
|
|
54
|
+
except Exception:
|
|
55
|
+
pass
|
|
56
|
+
|
|
57
|
+
return future
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
def on_agent_step_async(on_agent_step: Callable[[str], None], browser_setup: BrowserSetup) -> None:
|
|
61
|
+
import websockets
|
|
62
|
+
|
|
63
|
+
async def websocket_listener() -> None:
|
|
64
|
+
ws_url = get_agent_ws_url(browser_setup.base_url, browser_setup.session_id)
|
|
65
|
+
async with websockets.connect(ws_url) as ws:
|
|
66
|
+
async for ws_msg in ws:
|
|
67
|
+
on_agent_step(str(ws_msg))
|
|
68
|
+
|
|
69
|
+
asyncio.create_task(websocket_listener())
|
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
from typing import TYPE_CHECKING, Any, Dict, Callable, Optional, TypedDict
|
|
2
|
+
from contextlib import contextmanager, asynccontextmanager, _GeneratorContextManager, _AsyncGeneratorContextManager
|
|
3
|
+
|
|
4
|
+
from pydantic import BaseModel
|
|
5
|
+
from playwright.sync_api import Page, Worker, Browser, BrowserContext
|
|
6
|
+
from playwright.async_api import (
|
|
7
|
+
Page as AsyncPage,
|
|
8
|
+
Worker as AsyncWorker,
|
|
9
|
+
Browser as AsyncBrowser,
|
|
10
|
+
BrowserContext as AsyncBrowserContext,
|
|
11
|
+
)
|
|
12
|
+
|
|
13
|
+
if TYPE_CHECKING:
|
|
14
|
+
from collections import Generator, AsyncGenerator
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
@contextmanager
|
|
18
|
+
def get_playwright_chromium_from_cdp_url(
|
|
19
|
+
api_base_url: str, session_id: str, api_key: str
|
|
20
|
+
) -> "Generator[Browser, Any, None]":
|
|
21
|
+
from playwright.sync_api import sync_playwright
|
|
22
|
+
|
|
23
|
+
browser = None
|
|
24
|
+
playwright = sync_playwright().start()
|
|
25
|
+
try:
|
|
26
|
+
browser = playwright.chromium.connect_over_cdp(get_cdp_url(api_base_url, session_id, api_key))
|
|
27
|
+
yield browser
|
|
28
|
+
finally:
|
|
29
|
+
if browser:
|
|
30
|
+
browser.close()
|
|
31
|
+
playwright.stop()
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
@asynccontextmanager
|
|
35
|
+
async def get_async_playwright_chromium_from_cdp_url(
|
|
36
|
+
api_base_url: str, session_id: str, api_key: str
|
|
37
|
+
) -> "AsyncGenerator[AsyncBrowser, None]":
|
|
38
|
+
from playwright.async_api import async_playwright
|
|
39
|
+
|
|
40
|
+
browser = None
|
|
41
|
+
playwright = await async_playwright().start()
|
|
42
|
+
try:
|
|
43
|
+
browser = await playwright.chromium.connect_over_cdp(get_cdp_url(api_base_url, session_id, api_key))
|
|
44
|
+
yield browser
|
|
45
|
+
finally:
|
|
46
|
+
if browser:
|
|
47
|
+
await browser.close()
|
|
48
|
+
await playwright.stop()
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
def get_cdp_url(api_base_url: str, session_id: str, api_key: str) -> str:
|
|
52
|
+
return f"{api_base_url.replace('https://', 'wss://').replace('api.', 'connect.')}?apiKey={api_key}&sessionId={session_id}"
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
def get_agent_ws_url(api_base_url: str, session_id: str) -> str:
|
|
56
|
+
return f"{api_base_url.replace('https://', 'wss://').replace('api.', 'connect.')}/ws?sessionId={session_id}"
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
def get_ai_service_worker(browser_context: "BrowserContext") -> Optional["Worker"]:
|
|
60
|
+
return next(
|
|
61
|
+
(
|
|
62
|
+
sw
|
|
63
|
+
for sw in browser_context.service_workers
|
|
64
|
+
if "chrome-extension://bppehibnhionalpjigdjdilknbljaeai/background.js" in sw.url
|
|
65
|
+
),
|
|
66
|
+
None,
|
|
67
|
+
)
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
async def get_ai_service_worker_async(browser_context: "AsyncBrowserContext") -> Optional["AsyncWorker"]:
|
|
71
|
+
return next(
|
|
72
|
+
(
|
|
73
|
+
sw
|
|
74
|
+
for sw in browser_context.service_workers
|
|
75
|
+
if "chrome-extension://bppehibnhionalpjigdjdilknbljaeai/background.js" in sw.url
|
|
76
|
+
),
|
|
77
|
+
None,
|
|
78
|
+
)
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
class BrowserSetup(BaseModel):
|
|
82
|
+
session_id: str
|
|
83
|
+
base_url: str
|
|
84
|
+
api_key: str
|
|
85
|
+
_browser: Optional[Browser] = None
|
|
86
|
+
_async_browser: Optional[AsyncBrowser] = None
|
|
87
|
+
_context_manager: Optional[_GeneratorContextManager[Browser]] = None
|
|
88
|
+
_async_context_manager: Optional[_AsyncGeneratorContextManager[AsyncBrowser]] = None
|
|
89
|
+
|
|
90
|
+
async def __aenter__(self) -> "BrowserSetup":
|
|
91
|
+
self._async_context_manager = get_async_playwright_chromium_from_cdp_url(
|
|
92
|
+
self.base_url,
|
|
93
|
+
self.session_id,
|
|
94
|
+
self.api_key,
|
|
95
|
+
)
|
|
96
|
+
self._async_browser = await self._async_context_manager.__aenter__()
|
|
97
|
+
return self
|
|
98
|
+
|
|
99
|
+
def __enter__(self) -> "BrowserSetup":
|
|
100
|
+
self._context_manager = get_playwright_chromium_from_cdp_url(
|
|
101
|
+
self.base_url,
|
|
102
|
+
self.session_id,
|
|
103
|
+
self.api_key,
|
|
104
|
+
)
|
|
105
|
+
self._browser = self._context_manager.__enter__()
|
|
106
|
+
return self
|
|
107
|
+
|
|
108
|
+
def __exit__(self, exc_type: Any, exc_val: Any, exc_tb: Any) -> Optional[bool]:
|
|
109
|
+
if self._context_manager:
|
|
110
|
+
return self._context_manager.__exit__(exc_type, exc_val, exc_tb)
|
|
111
|
+
return None
|
|
112
|
+
|
|
113
|
+
async def __aexit__(self, exc_type: Any, exc_val: Any, exc_tb: Any) -> Optional[bool]:
|
|
114
|
+
if self._async_context_manager:
|
|
115
|
+
return await self._async_context_manager.__aexit__(exc_type, exc_val, exc_tb)
|
|
116
|
+
return None
|
|
117
|
+
|
|
118
|
+
@property
|
|
119
|
+
def browser_generator(self) -> _GeneratorContextManager[Browser]:
|
|
120
|
+
return get_playwright_chromium_from_cdp_url(
|
|
121
|
+
self.base_url,
|
|
122
|
+
self.session_id,
|
|
123
|
+
self.api_key,
|
|
124
|
+
)
|
|
125
|
+
|
|
126
|
+
@property
|
|
127
|
+
def async_browser_generator(self) -> _AsyncGeneratorContextManager[AsyncBrowser]:
|
|
128
|
+
return get_async_playwright_chromium_from_cdp_url(
|
|
129
|
+
self.base_url,
|
|
130
|
+
self.session_id,
|
|
131
|
+
self.api_key,
|
|
132
|
+
)
|
|
133
|
+
|
|
134
|
+
@property
|
|
135
|
+
def browser(self) -> Browser:
|
|
136
|
+
if self._browser is None:
|
|
137
|
+
raise RuntimeError("BrowserSetup must be used as a context manager")
|
|
138
|
+
return self._browser
|
|
139
|
+
|
|
140
|
+
@property
|
|
141
|
+
async def async_browser(self) -> AsyncBrowser:
|
|
142
|
+
if self._async_browser is None:
|
|
143
|
+
raise RuntimeError("BrowserSetup must be used as a context manager")
|
|
144
|
+
return self._async_browser
|
|
145
|
+
|
|
146
|
+
@property
|
|
147
|
+
def context(self) -> BrowserContext:
|
|
148
|
+
return self.browser.contexts[0]
|
|
149
|
+
|
|
150
|
+
@property
|
|
151
|
+
async def async_context(self) -> AsyncBrowserContext:
|
|
152
|
+
return (await self.async_browser).contexts[0]
|
|
153
|
+
|
|
154
|
+
@property
|
|
155
|
+
def page(self) -> Page:
|
|
156
|
+
return self.context.pages[0]
|
|
157
|
+
|
|
158
|
+
@property
|
|
159
|
+
async def async_page(self) -> AsyncPage:
|
|
160
|
+
return (await self.async_context).pages[0]
|
|
161
|
+
|
|
162
|
+
@property
|
|
163
|
+
def ai(self) -> Worker:
|
|
164
|
+
ai_service_worker = get_ai_service_worker(self.context)
|
|
165
|
+
if not ai_service_worker:
|
|
166
|
+
raise ValueError("AI service worker not found")
|
|
167
|
+
return ai_service_worker
|
|
168
|
+
|
|
169
|
+
@property
|
|
170
|
+
async def async_ai(self) -> AsyncWorker:
|
|
171
|
+
ai_service_worker = await get_ai_service_worker_async(await self.async_context)
|
|
172
|
+
if not ai_service_worker:
|
|
173
|
+
raise ValueError("AI service worker not found")
|
|
174
|
+
return ai_service_worker
|
|
175
|
+
|
|
176
|
+
|
|
177
|
+
class AgentTaskParams(TypedDict, total=False):
|
|
178
|
+
url: Optional[str]
|
|
179
|
+
output_schema: Optional[Dict[str, Any]]
|
|
180
|
+
on_agent_step: Optional[Callable[[str], None]]
|
|
181
|
+
|
|
182
|
+
|
|
183
|
+
class BrowserTaskResponse(TypedDict):
|
|
184
|
+
session_id: str
|
|
185
|
+
task_result_task: Any
|
|
186
|
+
playwright_browser: Any
|
|
@@ -0,0 +1,305 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from typing import Optional
|
|
4
|
+
|
|
5
|
+
from .._compat import cached_property
|
|
6
|
+
from .._resource import SyncAPIResource, AsyncAPIResource
|
|
7
|
+
from .._response import (
|
|
8
|
+
to_raw_response_wrapper,
|
|
9
|
+
to_streamed_response_wrapper,
|
|
10
|
+
async_to_raw_response_wrapper,
|
|
11
|
+
async_to_streamed_response_wrapper,
|
|
12
|
+
)
|
|
13
|
+
from ..lib.agent import on_agent_step_sync, create_task_payload, on_agent_step_async
|
|
14
|
+
from ..lib.browser import (
|
|
15
|
+
BrowserSetup,
|
|
16
|
+
AgentTaskParams,
|
|
17
|
+
BrowserTaskResponse,
|
|
18
|
+
)
|
|
19
|
+
from ..types.session_create_params import Session
|
|
20
|
+
|
|
21
|
+
__all__ = ["AgentResource", "AsyncAgentResource"]
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
class AgentResource(SyncAPIResource):
|
|
25
|
+
@cached_property
|
|
26
|
+
def with_raw_response(self) -> AgentResourceWithRawResponse:
|
|
27
|
+
"""
|
|
28
|
+
This property can be used as a prefix for any HTTP method call to return
|
|
29
|
+
the raw response object instead of the parsed content.
|
|
30
|
+
|
|
31
|
+
For more information, see https://www.github.com/anchorbrowser/AnchorBrowser-SDK-Python#accessing-raw-response-data-eg-headers
|
|
32
|
+
"""
|
|
33
|
+
return AgentResourceWithRawResponse(self)
|
|
34
|
+
|
|
35
|
+
@cached_property
|
|
36
|
+
def with_streaming_response(self) -> AgentResourceWithStreamingResponse:
|
|
37
|
+
"""
|
|
38
|
+
An alternative to `.with_raw_response` that doesn't eagerly read the response body.
|
|
39
|
+
|
|
40
|
+
For more information, see https://www.github.com/anchorbrowser/AnchorBrowser-SDK-Python#with_streaming_response
|
|
41
|
+
"""
|
|
42
|
+
return AgentResourceWithStreamingResponse(self)
|
|
43
|
+
|
|
44
|
+
def task(
|
|
45
|
+
self,
|
|
46
|
+
prompt: str,
|
|
47
|
+
*,
|
|
48
|
+
session_options: Optional[Session] = None,
|
|
49
|
+
task_options: Optional[AgentTaskParams] = None,
|
|
50
|
+
) -> str:
|
|
51
|
+
"""Execute an AI agent task within a browser session.
|
|
52
|
+
|
|
53
|
+
Creates a new browser session and executes the given prompt as an AI agent task.
|
|
54
|
+
The agent can optionally navigate to a specific URL and use a structured output schema.
|
|
55
|
+
|
|
56
|
+
Args:
|
|
57
|
+
prompt (str): The task prompt/instruction for the AI agent to execute.
|
|
58
|
+
session_options (Optional[Session], optional): Configuration options for the
|
|
59
|
+
browser session. Defaults to None, which creates a session with default settings.
|
|
60
|
+
task_options (Optional[AgentTaskParams], optional): Additional task configuration
|
|
61
|
+
|
|
62
|
+
Returns:
|
|
63
|
+
str: The result of the AI agent task execution.
|
|
64
|
+
"""
|
|
65
|
+
session = self._client.sessions.create(session=session_options or {})
|
|
66
|
+
if not session.data or not session.data.id:
|
|
67
|
+
raise ValueError("Failed to create session: No session ID returned")
|
|
68
|
+
|
|
69
|
+
with BrowserSetup(
|
|
70
|
+
session_id=session.data.id,
|
|
71
|
+
base_url=str(self._client.base_url),
|
|
72
|
+
api_key=self._client.api_key,
|
|
73
|
+
) as browser_setup:
|
|
74
|
+
output_schema = None
|
|
75
|
+
if task_options:
|
|
76
|
+
output_schema = task_options.get("output_schema")
|
|
77
|
+
url = task_options.get("url")
|
|
78
|
+
if url:
|
|
79
|
+
browser_setup.page.goto(url)
|
|
80
|
+
on_agent_step = task_options.get("on_agent_step")
|
|
81
|
+
if on_agent_step:
|
|
82
|
+
on_agent_step_sync(on_agent_step, browser_setup)
|
|
83
|
+
task_payload = create_task_payload(prompt, output_schema)
|
|
84
|
+
task_result = str(browser_setup.ai.evaluate(task_payload))
|
|
85
|
+
return task_result
|
|
86
|
+
|
|
87
|
+
def browser_task(
|
|
88
|
+
self,
|
|
89
|
+
prompt: str,
|
|
90
|
+
*,
|
|
91
|
+
session_options: Optional[Session] = None,
|
|
92
|
+
task_options: Optional[AgentTaskParams] = None,
|
|
93
|
+
) -> BrowserTaskResponse:
|
|
94
|
+
"""Execute an AI agent task and return a browser task response with session control.
|
|
95
|
+
|
|
96
|
+
Creates a new browser session, executes the given prompt as an AI agent task \n
|
|
97
|
+
returns a object that includes the session ID, task result, and browser instance for continued interaction by the caller. \n
|
|
98
|
+
This method differs from `task()` by returning control of the browser session to the caller rather than automatically closing it after task completion. \n
|
|
99
|
+
Args:
|
|
100
|
+
prompt (str): The task prompt/instruction for the AI agent to execute. \n
|
|
101
|
+
session_options (Optional[Session], optional): Configuration options for the browser session. Defaults to None, which creates a session with default settings. \n
|
|
102
|
+
task_options (Optional[AgentTaskParams], optional): Additional task configuration including: \n
|
|
103
|
+
- output_schema: Schema for structured output formatting
|
|
104
|
+
- url: URL to navigate to before executing the task
|
|
105
|
+
- on_agent_step: Callback function for agent step events
|
|
106
|
+
Defaults to None.
|
|
107
|
+
|
|
108
|
+
Returns:
|
|
109
|
+
Response object containing:
|
|
110
|
+
- session_id: The ID of the created browser session
|
|
111
|
+
- task_result_task: The result of the AI agent task execution
|
|
112
|
+
- playwright_browser: Browser instance for continued interaction
|
|
113
|
+
"""
|
|
114
|
+
session = self._client.sessions.create(session=session_options or {})
|
|
115
|
+
if not session.data or not session.data.id:
|
|
116
|
+
raise ValueError("Failed to create session: No session ID returned")
|
|
117
|
+
|
|
118
|
+
with BrowserSetup(
|
|
119
|
+
session_id=session.data.id,
|
|
120
|
+
base_url=str(self._client.base_url),
|
|
121
|
+
api_key=self._client.api_key,
|
|
122
|
+
) as browser_setup:
|
|
123
|
+
output_schema = None
|
|
124
|
+
if task_options:
|
|
125
|
+
output_schema = task_options.get("output_schema")
|
|
126
|
+
url = task_options.get("url")
|
|
127
|
+
if url:
|
|
128
|
+
browser_setup.page.goto(url)
|
|
129
|
+
on_agent_step = task_options.get("on_agent_step")
|
|
130
|
+
if on_agent_step:
|
|
131
|
+
on_agent_step_sync(on_agent_step, browser_setup)
|
|
132
|
+
task_payload = create_task_payload(prompt, output_schema)
|
|
133
|
+
task_result = str(browser_setup.ai.evaluate(task_payload))
|
|
134
|
+
return BrowserTaskResponse(
|
|
135
|
+
session_id=session.data.id,
|
|
136
|
+
task_result_task=task_result,
|
|
137
|
+
playwright_browser=browser_setup.browser_generator,
|
|
138
|
+
)
|
|
139
|
+
|
|
140
|
+
|
|
141
|
+
class AsyncAgentResource(AsyncAPIResource):
|
|
142
|
+
@cached_property
|
|
143
|
+
def with_raw_response(self) -> AsyncAgentResourceWithRawResponse:
|
|
144
|
+
"""
|
|
145
|
+
This property can be used as a prefix for any HTTP method call to return
|
|
146
|
+
the raw response object instead of the parsed content.
|
|
147
|
+
|
|
148
|
+
For more information, see https://www.github.com/anchorbrowser/AnchorBrowser-SDK-Python#accessing-raw-response-data-eg-headers
|
|
149
|
+
"""
|
|
150
|
+
return AsyncAgentResourceWithRawResponse(self)
|
|
151
|
+
|
|
152
|
+
@cached_property
|
|
153
|
+
def with_streaming_response(self) -> AsyncAgentResourceWithStreamingResponse:
|
|
154
|
+
"""
|
|
155
|
+
An alternative to `.with_raw_response` that doesn't eagerly read the response body.
|
|
156
|
+
|
|
157
|
+
For more information, see https://www.github.com/anchorbrowser/AnchorBrowser-SDK-Python#with_streaming_response
|
|
158
|
+
"""
|
|
159
|
+
return AsyncAgentResourceWithStreamingResponse(self)
|
|
160
|
+
|
|
161
|
+
async def task(
|
|
162
|
+
self,
|
|
163
|
+
prompt: str,
|
|
164
|
+
*,
|
|
165
|
+
session_options: Optional[Session] = None,
|
|
166
|
+
task_options: Optional[AgentTaskParams] = None,
|
|
167
|
+
) -> str:
|
|
168
|
+
"""Execute an AI agent task within a browser session.
|
|
169
|
+
|
|
170
|
+
Creates a new browser session and executes the given prompt as an AI agent task.
|
|
171
|
+
The agent can optionally navigate to a specific URL and use a structured output schema.
|
|
172
|
+
|
|
173
|
+
Args:
|
|
174
|
+
prompt (str): The task prompt/instruction for the AI agent to execute.
|
|
175
|
+
session_options (Optional[Session], optional): Configuration options for the
|
|
176
|
+
browser session. Defaults to None, which creates a session with default settings.
|
|
177
|
+
task_options (Optional[AgentTaskParams], optional): Additional task configuration
|
|
178
|
+
|
|
179
|
+
Returns:
|
|
180
|
+
str: The result of the AI agent task execution.
|
|
181
|
+
"""
|
|
182
|
+
session = await self._client.sessions.create(session=session_options or {})
|
|
183
|
+
if not session.data or not session.data.id:
|
|
184
|
+
raise ValueError("Failed to create session: No session ID returned")
|
|
185
|
+
|
|
186
|
+
browser_setup = BrowserSetup(
|
|
187
|
+
session_id=session.data.id,
|
|
188
|
+
base_url=str(self._client.base_url),
|
|
189
|
+
api_key=self._client.api_key,
|
|
190
|
+
)
|
|
191
|
+
|
|
192
|
+
async with browser_setup:
|
|
193
|
+
output_schema = None
|
|
194
|
+
if task_options:
|
|
195
|
+
output_schema = task_options.get("output_schema")
|
|
196
|
+
url = task_options.get("url")
|
|
197
|
+
if url:
|
|
198
|
+
await (await browser_setup.async_page).goto(url)
|
|
199
|
+
on_agent_step = task_options.get("on_agent_step")
|
|
200
|
+
if on_agent_step:
|
|
201
|
+
on_agent_step_async(on_agent_step, browser_setup)
|
|
202
|
+
task_payload = create_task_payload(prompt, output_schema)
|
|
203
|
+
task_result = await (await browser_setup.async_ai).evaluate(task_payload)
|
|
204
|
+
return str(task_result)
|
|
205
|
+
|
|
206
|
+
async def browser_task(
|
|
207
|
+
self,
|
|
208
|
+
prompt: str,
|
|
209
|
+
*,
|
|
210
|
+
session_options: Optional[Session] = None,
|
|
211
|
+
task_options: Optional[AgentTaskParams] = None,
|
|
212
|
+
) -> BrowserTaskResponse:
|
|
213
|
+
"""Execute an AI agent task and return a browser task response with session control.
|
|
214
|
+
|
|
215
|
+
Creates a new browser session, executes the given prompt as an AI agent task \n
|
|
216
|
+
returns a object that includes the session ID, task result, and browser instance for continued interaction by the caller. \n
|
|
217
|
+
This method differs from `task()` by returning control of the browser session to the caller rather than automatically closing it after task completion. \n
|
|
218
|
+
Args:
|
|
219
|
+
prompt (str): The task prompt/instruction for the AI agent to execute. \n
|
|
220
|
+
session_options (Optional[Session], optional): Configuration options for the browser session. Defaults to None, which creates a session with default settings. \n
|
|
221
|
+
task_options (Optional[AgentTaskParams], optional): Additional task configuration including: \n
|
|
222
|
+
- output_schema: Schema for structured output formatting
|
|
223
|
+
- url: URL to navigate to before executing the task
|
|
224
|
+
- on_agent_step: Callback function for agent step events
|
|
225
|
+
Defaults to None.
|
|
226
|
+
|
|
227
|
+
Returns:
|
|
228
|
+
Response object containing:
|
|
229
|
+
- session_id: The ID of the created browser session
|
|
230
|
+
- task_result_task: The result of the AI agent task execution
|
|
231
|
+
- playwright_browser: Browser instance for continued interaction
|
|
232
|
+
"""
|
|
233
|
+
session = await self._client.sessions.create(session=session_options or {})
|
|
234
|
+
if not session.data or not session.data.id:
|
|
235
|
+
raise ValueError("Failed to create session: No session ID returned")
|
|
236
|
+
|
|
237
|
+
async with BrowserSetup(
|
|
238
|
+
session_id=session.data.id,
|
|
239
|
+
base_url=str(self._client.base_url),
|
|
240
|
+
api_key=self._client.api_key,
|
|
241
|
+
) as browser_setup:
|
|
242
|
+
output_schema = None
|
|
243
|
+
if task_options:
|
|
244
|
+
output_schema = task_options.get("output_schema")
|
|
245
|
+
url = task_options.get("url")
|
|
246
|
+
if url:
|
|
247
|
+
await (await browser_setup.async_page).goto(url)
|
|
248
|
+
on_agent_step = task_options.get("on_agent_step")
|
|
249
|
+
if on_agent_step:
|
|
250
|
+
on_agent_step_async(on_agent_step, browser_setup)
|
|
251
|
+
task_payload = create_task_payload(prompt, output_schema)
|
|
252
|
+
task_result = await (await browser_setup.async_ai).evaluate(task_payload)
|
|
253
|
+
return BrowserTaskResponse(
|
|
254
|
+
session_id=session.data.id,
|
|
255
|
+
task_result_task=task_result,
|
|
256
|
+
playwright_browser=browser_setup.async_browser_generator,
|
|
257
|
+
)
|
|
258
|
+
|
|
259
|
+
|
|
260
|
+
class AgentResourceWithRawResponse:
|
|
261
|
+
def __init__(self, agent: AgentResource) -> None:
|
|
262
|
+
self._agent = agent
|
|
263
|
+
|
|
264
|
+
self.task = to_raw_response_wrapper(
|
|
265
|
+
agent.task,
|
|
266
|
+
)
|
|
267
|
+
self.browser_task = to_raw_response_wrapper(
|
|
268
|
+
agent.browser_task,
|
|
269
|
+
)
|
|
270
|
+
|
|
271
|
+
|
|
272
|
+
class AsyncAgentResourceWithRawResponse:
|
|
273
|
+
def __init__(self, agent: AsyncAgentResource) -> None:
|
|
274
|
+
self._agent = agent
|
|
275
|
+
|
|
276
|
+
self.task = async_to_raw_response_wrapper(
|
|
277
|
+
agent.task,
|
|
278
|
+
)
|
|
279
|
+
self.browser_task = async_to_raw_response_wrapper(
|
|
280
|
+
agent.browser_task,
|
|
281
|
+
)
|
|
282
|
+
|
|
283
|
+
|
|
284
|
+
class AgentResourceWithStreamingResponse:
|
|
285
|
+
def __init__(self, agent: AgentResource) -> None:
|
|
286
|
+
self._agent = agent
|
|
287
|
+
|
|
288
|
+
self.task = to_streamed_response_wrapper(
|
|
289
|
+
agent.task,
|
|
290
|
+
)
|
|
291
|
+
self.browser_task = to_streamed_response_wrapper(
|
|
292
|
+
agent.browser_task,
|
|
293
|
+
)
|
|
294
|
+
|
|
295
|
+
|
|
296
|
+
class AsyncAgentResourceWithStreamingResponse:
|
|
297
|
+
def __init__(self, agent: AsyncAgentResource) -> None:
|
|
298
|
+
self._agent = agent
|
|
299
|
+
|
|
300
|
+
self.task = async_to_streamed_response_wrapper(
|
|
301
|
+
agent.task,
|
|
302
|
+
)
|
|
303
|
+
self.browser_task = async_to_streamed_response_wrapper(
|
|
304
|
+
agent.browser_task,
|
|
305
|
+
)
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from contextlib import _GeneratorContextManager, _AsyncGeneratorContextManager
|
|
4
|
+
|
|
5
|
+
from playwright.sync_api import Browser
|
|
6
|
+
from playwright.async_api import Browser as AsyncBrowser
|
|
7
|
+
|
|
8
|
+
from .._compat import cached_property
|
|
9
|
+
from .._resource import SyncAPIResource, AsyncAPIResource
|
|
10
|
+
from .._response import (
|
|
11
|
+
to_raw_response_wrapper,
|
|
12
|
+
to_streamed_response_wrapper,
|
|
13
|
+
async_to_raw_response_wrapper,
|
|
14
|
+
async_to_streamed_response_wrapper,
|
|
15
|
+
)
|
|
16
|
+
from ..lib.browser import (
|
|
17
|
+
get_playwright_chromium_from_cdp_url,
|
|
18
|
+
get_async_playwright_chromium_from_cdp_url,
|
|
19
|
+
)
|
|
20
|
+
|
|
21
|
+
__all__ = ["BrowserResource", "AsyncBrowserResource"]
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
class BrowserResource(SyncAPIResource):
|
|
25
|
+
@cached_property
|
|
26
|
+
def with_raw_response(self) -> BrowserResourceWithRawResponse:
|
|
27
|
+
"""
|
|
28
|
+
This property can be used as a prefix for any HTTP method call to return
|
|
29
|
+
the raw response object instead of the parsed content.
|
|
30
|
+
|
|
31
|
+
For more information, see https://www.github.com/anchorbrowser/AnchorBrowser-SDK-Python#accessing-raw-response-data-eg-headers
|
|
32
|
+
"""
|
|
33
|
+
return BrowserResourceWithRawResponse(self)
|
|
34
|
+
|
|
35
|
+
@cached_property
|
|
36
|
+
def with_streaming_response(self) -> BrowserResourceWithStreamingResponse:
|
|
37
|
+
"""
|
|
38
|
+
An alternative to `.with_raw_response` that doesn't eagerly read the response body.
|
|
39
|
+
|
|
40
|
+
For more information, see https://www.github.com/anchorbrowser/AnchorBrowser-SDK-Python#with_streaming_response
|
|
41
|
+
"""
|
|
42
|
+
return BrowserResourceWithStreamingResponse(self)
|
|
43
|
+
|
|
44
|
+
def connect(self, session_id: str) -> _GeneratorContextManager[Browser]:
|
|
45
|
+
"""Connect to a browser session.
|
|
46
|
+
|
|
47
|
+
Args:
|
|
48
|
+
session_id (str): The ID of the session to connect to.
|
|
49
|
+
|
|
50
|
+
Returns:
|
|
51
|
+
BrowserContext: a context manager that can be used to interact with the browser(playwright)
|
|
52
|
+
"""
|
|
53
|
+
return get_playwright_chromium_from_cdp_url(str(self._client.base_url), session_id, self._client.api_key)
|
|
54
|
+
|
|
55
|
+
def create(self) -> _GeneratorContextManager[Browser]:
|
|
56
|
+
session = self._client.sessions.create()
|
|
57
|
+
if not session.data or not session.data.id:
|
|
58
|
+
raise ValueError("Failed to create session")
|
|
59
|
+
return get_playwright_chromium_from_cdp_url(str(self._client.base_url), session.data.id, self._client.api_key)
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
class AsyncBrowserResource(AsyncAPIResource):
|
|
63
|
+
@cached_property
|
|
64
|
+
def with_raw_response(self) -> AsyncBrowserResourceWithRawResponse:
|
|
65
|
+
"""
|
|
66
|
+
This property can be used as a prefix for any HTTP method call to return
|
|
67
|
+
the raw response object instead of the parsed content.
|
|
68
|
+
|
|
69
|
+
For more information, see https://www.github.com/anchorbrowser/AnchorBrowser-SDK-Python#accessing-raw-response-data-eg-headers
|
|
70
|
+
"""
|
|
71
|
+
return AsyncBrowserResourceWithRawResponse(self)
|
|
72
|
+
|
|
73
|
+
@cached_property
|
|
74
|
+
def with_streaming_response(self) -> AsyncBrowserResourceWithStreamingResponse:
|
|
75
|
+
"""
|
|
76
|
+
An alternative to `.with_raw_response` that doesn't eagerly read the response body.
|
|
77
|
+
|
|
78
|
+
For more information, see https://www.github.com/anchorbrowser/AnchorBrowser-SDK-Python#with_streaming_response
|
|
79
|
+
"""
|
|
80
|
+
return AsyncBrowserResourceWithStreamingResponse(self)
|
|
81
|
+
|
|
82
|
+
async def connect(self, session_id: str) -> _AsyncGeneratorContextManager[AsyncBrowser]:
|
|
83
|
+
"""Connect to a browser session.
|
|
84
|
+
|
|
85
|
+
Args:
|
|
86
|
+
session_id (str): The ID of the session to connect to.
|
|
87
|
+
|
|
88
|
+
Returns:
|
|
89
|
+
BrowserContext: a context manager that can be used to interact with the browser(playwright)
|
|
90
|
+
"""
|
|
91
|
+
return get_async_playwright_chromium_from_cdp_url(str(self._client.base_url), session_id, self._client.api_key)
|
|
92
|
+
|
|
93
|
+
async def create(self) -> _AsyncGeneratorContextManager[AsyncBrowser]:
|
|
94
|
+
"""Create a new browser session.
|
|
95
|
+
|
|
96
|
+
Returns:
|
|
97
|
+
BrowserContext: a context manager that can be used to interact with the browser(playwright)
|
|
98
|
+
"""
|
|
99
|
+
session = await self._client.sessions.create()
|
|
100
|
+
if not session.data or not session.data.id:
|
|
101
|
+
raise ValueError("Failed to create session")
|
|
102
|
+
return get_async_playwright_chromium_from_cdp_url(
|
|
103
|
+
str(self._client.base_url), session.data.id, self._client.api_key
|
|
104
|
+
)
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
class BrowserResourceWithRawResponse:
|
|
108
|
+
def __init__(self, browser: BrowserResource) -> None:
|
|
109
|
+
self._browser = browser
|
|
110
|
+
|
|
111
|
+
self.connect = to_raw_response_wrapper(
|
|
112
|
+
browser.connect,
|
|
113
|
+
)
|
|
114
|
+
self.create = to_raw_response_wrapper(
|
|
115
|
+
browser.create,
|
|
116
|
+
)
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
class AsyncBrowserResourceWithRawResponse:
|
|
120
|
+
def __init__(self, browser: AsyncBrowserResource) -> None:
|
|
121
|
+
self._browser = browser
|
|
122
|
+
|
|
123
|
+
self.connect = async_to_raw_response_wrapper(
|
|
124
|
+
browser.connect,
|
|
125
|
+
)
|
|
126
|
+
self.create = async_to_raw_response_wrapper(
|
|
127
|
+
browser.create,
|
|
128
|
+
)
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
class BrowserResourceWithStreamingResponse:
|
|
132
|
+
def __init__(self, browser: BrowserResource) -> None:
|
|
133
|
+
self._browser = browser
|
|
134
|
+
|
|
135
|
+
self.connect = to_streamed_response_wrapper(
|
|
136
|
+
browser.connect,
|
|
137
|
+
)
|
|
138
|
+
self.create = to_streamed_response_wrapper(
|
|
139
|
+
browser.create,
|
|
140
|
+
)
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
class AsyncBrowserResourceWithStreamingResponse:
|
|
144
|
+
def __init__(self, browser: AsyncBrowserResource) -> None:
|
|
145
|
+
self._browser = browser
|
|
146
|
+
|
|
147
|
+
self.connect = async_to_streamed_response_wrapper(
|
|
148
|
+
browser.connect,
|
|
149
|
+
)
|
|
150
|
+
self.create = async_to_streamed_response_wrapper(
|
|
151
|
+
browser.create,
|
|
152
|
+
)
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
|
|
2
2
|
|
|
3
|
-
from typing import TYPE_CHECKING, List, Optional
|
|
3
|
+
from typing import TYPE_CHECKING, Dict, List, Optional
|
|
4
|
+
|
|
5
|
+
from pydantic import Field as FieldInfo
|
|
4
6
|
|
|
5
7
|
from .._models import BaseModel
|
|
6
8
|
|
|
@@ -18,6 +20,7 @@ class ExtensionManifest(BaseModel):
|
|
|
18
20
|
|
|
19
21
|
version: Optional[str] = None
|
|
20
22
|
|
|
23
|
+
__pydantic_extra__: Dict[str, object] = FieldInfo(init=False) # pyright: ignore[reportIncompatibleVariableOverride]
|
|
21
24
|
if TYPE_CHECKING:
|
|
22
25
|
# Stub to indicate that arbitrary properties are accepted.
|
|
23
26
|
# To access properties that are not valid identifiers you can use `getattr`, e.g.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: anchorbrowser
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.0a2
|
|
4
4
|
Summary: The official Python library for the anchorbrowser API
|
|
5
5
|
Project-URL: Homepage, https://github.com/anchorbrowser/AnchorBrowser-SDK-Python
|
|
6
6
|
Project-URL: Repository, https://github.com/anchorbrowser/AnchorBrowser-SDK-Python
|
|
@@ -26,8 +26,10 @@ Requires-Dist: anyio<5,>=3.5.0
|
|
|
26
26
|
Requires-Dist: distro<2,>=1.7.0
|
|
27
27
|
Requires-Dist: httpx<1,>=0.23.0
|
|
28
28
|
Requires-Dist: pydantic<3,>=1.9.0
|
|
29
|
+
Requires-Dist: pytest-playwright
|
|
29
30
|
Requires-Dist: sniffio
|
|
30
31
|
Requires-Dist: typing-extensions<5,>=4.10
|
|
32
|
+
Requires-Dist: websockets
|
|
31
33
|
Provides-Extra: aiohttp
|
|
32
34
|
Requires-Dist: aiohttp; extra == 'aiohttp'
|
|
33
35
|
Requires-Dist: httpx-aiohttp>=0.1.8; extra == 'aiohttp'
|
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
anchorbrowser/__init__.py,sha256=Y9SS6YKjFHc3NR74t9tzppSPjZ4U-zyYI8uPM5r17QU,2682
|
|
2
2
|
anchorbrowser/_base_client.py,sha256=viDcyxFrFwusLXdK0lE6g9hRoB8fBvZcUOQpfSurARs,66929
|
|
3
|
-
anchorbrowser/_client.py,sha256=
|
|
3
|
+
anchorbrowser/_client.py,sha256=xzMIA4NH4atxKHtepaW607dpH1yftDQLSr42CValZ2M,17919
|
|
4
4
|
anchorbrowser/_compat.py,sha256=VWemUKbj6DDkQ-O4baSpHVLJafotzeXmCQGJugfVTIw,6580
|
|
5
5
|
anchorbrowser/_constants.py,sha256=S14PFzyN9-I31wiV7SmIlL5Ga0MLHxdvegInGdXH7tM,462
|
|
6
6
|
anchorbrowser/_exceptions.py,sha256=Qz7WOsYUFZ3bEoN28V-C9Wk-EvYerqP83-fMUINlZKQ,3234
|
|
7
7
|
anchorbrowser/_files.py,sha256=YiRJFxnIpA4R0pnDmFtr_di9nD5txfnUOipc63hvBDs,3634
|
|
8
|
-
anchorbrowser/_models.py,sha256=
|
|
8
|
+
anchorbrowser/_models.py,sha256=KvjsMfb88XZlFUKVoOxr8OyDj47MhoH2OKqWNEbBhk4,30010
|
|
9
9
|
anchorbrowser/_qs.py,sha256=AOkSz4rHtK4YI3ZU_kzea-zpwBUgEY8WniGmTPyEimc,4846
|
|
10
10
|
anchorbrowser/_resource.py,sha256=7lE1EgpVj5kwckk-27umtigTOf9nKTyRl97cgNwRbRQ,1142
|
|
11
11
|
anchorbrowser/_response.py,sha256=xsiyWOC8LWW-NvbFtZ-MJD4f7eI9RnivKwtKImZ-8o4,28860
|
|
12
12
|
anchorbrowser/_streaming.py,sha256=9uTovnqQkz3LRbIWe9fSWwzB_aI1cX14LvEuMhkEcDI,10128
|
|
13
13
|
anchorbrowser/_types.py,sha256=-8YuIWJ9gV1xWRzK7aR74ryHGMjFtNl5NGZpbuYtPIU,6204
|
|
14
|
-
anchorbrowser/_version.py,sha256=
|
|
14
|
+
anchorbrowser/_version.py,sha256=bq-FIYtBF2Y62oY8DbKdaBTdzcUeJm989xXQKycdEcY,173
|
|
15
15
|
anchorbrowser/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
16
16
|
anchorbrowser/_utils/__init__.py,sha256=PNZ_QJuzZEgyYXqkO1HVhGkj5IU9bglVUcw7H-Knjzw,2062
|
|
17
17
|
anchorbrowser/_utils/_logs.py,sha256=VECnOdIr_cYELMwV_E72FPDY8f1qoYxASex-FciwPxc,795
|
|
@@ -24,7 +24,11 @@ anchorbrowser/_utils/_transform.py,sha256=n7kskEWz6o__aoNvhFoGVyDoalNe6mJwp-g7BW
|
|
|
24
24
|
anchorbrowser/_utils/_typing.py,sha256=D0DbbNu8GnYQTSICnTSHDGsYXj8TcAKyhejb0XcnjtY,4602
|
|
25
25
|
anchorbrowser/_utils/_utils.py,sha256=ts4CiiuNpFiGB6YMdkQRh2SZvYvsl7mAF-JWHCcLDf4,12312
|
|
26
26
|
anchorbrowser/lib/.keep,sha256=wuNrz-5SXo3jJaJOJgz4vFHM41YH_g20F5cRQo0vLes,224
|
|
27
|
+
anchorbrowser/lib/agent.py,sha256=M9Yg00Ogntfy0DZ9UvxLQp27prAYjo-0SrVLaovLM8g,2078
|
|
28
|
+
anchorbrowser/lib/browser.py,sha256=aLsNgZYY-54YMfLW2jN4QjsUzOTv4PtSUMWDlhLUSZA,6069
|
|
27
29
|
anchorbrowser/resources/__init__.py,sha256=fvjfy3JG7uR4Bz-wYI6euyWxCNVFI08v7m9ARGzTaTs,1993
|
|
30
|
+
anchorbrowser/resources/agent.py,sha256=2xAcNfeu9otN6qk0RY4pr6fjNloqKriEQEJW50nJAC4,13052
|
|
31
|
+
anchorbrowser/resources/browser.py,sha256=BB5hq_ayIDL_ziYHq13oj8US3XkHzkoXiGLBm7h9dH0,5548
|
|
28
32
|
anchorbrowser/resources/extensions.py,sha256=Ri4BuoHYV7_iHdCypGPVQ5AgX4FPkzgHFH_TIMWnsBE,15943
|
|
29
33
|
anchorbrowser/resources/profiles.py,sha256=WxuQnGxx8OAmEfl44aJfV-Bnx_XRBnNvs-Ozcfcnj9U,21347
|
|
30
34
|
anchorbrowser/resources/tools.py,sha256=U6kxpmQkHQC3i4-my54R27NA-CBnMEYsZFrudEnxawM,20946
|
|
@@ -40,7 +44,7 @@ anchorbrowser/resources/sessions/recordings/recordings.py,sha256=6OXB_m09wPYZGsb
|
|
|
40
44
|
anchorbrowser/types/__init__.py,sha256=O5J8M3dkfHUoSYFI6zjxoF3Phmajl_M9vROulwJ4xpI,2520
|
|
41
45
|
anchorbrowser/types/extension_delete_response.py,sha256=3ixtvxjz_Ay-Kp8lamJzbIrqKpvfqWui5l13Sr035To,327
|
|
42
46
|
anchorbrowser/types/extension_list_response.py,sha256=-OysuceCBHQLLT8B-zvwtHQDXqx__Zjkkb-gNT58N3Y,876
|
|
43
|
-
anchorbrowser/types/extension_manifest.py,sha256=
|
|
47
|
+
anchorbrowser/types/extension_manifest.py,sha256=rW6mjLODcQ9XHXWh6XBU1Sr_WZD0w8eod4YLH5dXjwc,872
|
|
44
48
|
anchorbrowser/types/extension_retrieve_response.py,sha256=wBpk7gNgAbVf1etsCSrC4JOrKD6c_9HTv2S2FjNiAiM,807
|
|
45
49
|
anchorbrowser/types/extension_upload_params.py,sha256=bBd8BMRVHu6P18jJovVMLPnIzGXGlV8Geb8TdiuGPbQ,470
|
|
46
50
|
anchorbrowser/types/extension_upload_response.py,sha256=ee8KYWIb-AjURMzrtAMNUTjV3Izhj6AB0LeAvR0npvk,868
|
|
@@ -90,7 +94,7 @@ anchorbrowser/types/sessions/recording_resume_response.py,sha256=JXGXVLDwcbodSOC
|
|
|
90
94
|
anchorbrowser/types/sessions/recordings/__init__.py,sha256=OKfJYcKb4NObdiRObqJV_dOyDQ8feXekDUge2o_4pXQ,122
|
|
91
95
|
anchorbrowser/types/shared/__init__.py,sha256=FQKjY3VDxI8T0feNRazdY5TOqb2KDeEwZaoJjsxuEl4,152
|
|
92
96
|
anchorbrowser/types/shared/success_response.py,sha256=l9OWrucXoSjBdsx5QKdvBPFtxv8d0YdpYY6iL5cWWuc,314
|
|
93
|
-
anchorbrowser-0.1.
|
|
94
|
-
anchorbrowser-0.1.
|
|
95
|
-
anchorbrowser-0.1.
|
|
96
|
-
anchorbrowser-0.1.
|
|
97
|
+
anchorbrowser-0.1.0a2.dist-info/METADATA,sha256=sJXgogjt-WLPFUGEKcJBDhu5-Srk8iHvd8nLXbyUA3s,15142
|
|
98
|
+
anchorbrowser-0.1.0a2.dist-info/WHEEL,sha256=C2FUgwZgiLbznR-k0b_5k3Ai_1aASOXDss3lzCUsUug,87
|
|
99
|
+
anchorbrowser-0.1.0a2.dist-info/licenses/LICENSE,sha256=QYTH6OztHxnELDn890vME8F7-euzmsHhWI4XOSYxwOg,11343
|
|
100
|
+
anchorbrowser-0.1.0a2.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|