auto-browser-langchain 1.2.1__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.
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import json
|
|
4
|
+
from typing import Any, TypedDict
|
|
5
|
+
|
|
6
|
+
import httpx
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class BrowserState(TypedDict, total=False):
|
|
10
|
+
session_id: str
|
|
11
|
+
current_url: str
|
|
12
|
+
screenshot_url: str
|
|
13
|
+
goal: str
|
|
14
|
+
result: str
|
|
15
|
+
error: str
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class AutoBrowserNode:
|
|
19
|
+
def __init__(
|
|
20
|
+
self,
|
|
21
|
+
base_url: str = "http://localhost:8000",
|
|
22
|
+
bearer_token: str | None = None,
|
|
23
|
+
timeout: float = 60.0,
|
|
24
|
+
):
|
|
25
|
+
self.base_url = base_url.rstrip("/")
|
|
26
|
+
self.bearer_token = bearer_token
|
|
27
|
+
self.timeout = timeout
|
|
28
|
+
|
|
29
|
+
def _headers(self) -> dict[str, str]:
|
|
30
|
+
headers: dict[str, str] = {"Content-Type": "application/json"}
|
|
31
|
+
if self.bearer_token:
|
|
32
|
+
headers["Authorization"] = f"Bearer {self.bearer_token}"
|
|
33
|
+
return headers
|
|
34
|
+
|
|
35
|
+
async def call_tool(self, name: str, arguments: dict[str, Any]) -> dict[str, Any]:
|
|
36
|
+
async with httpx.AsyncClient(base_url=self.base_url, timeout=self.timeout) as client:
|
|
37
|
+
response = await client.post(
|
|
38
|
+
"/mcp/tools/call",
|
|
39
|
+
json={"name": name, "arguments": arguments},
|
|
40
|
+
headers=self._headers(),
|
|
41
|
+
)
|
|
42
|
+
response.raise_for_status()
|
|
43
|
+
return response.json()
|
|
44
|
+
|
|
45
|
+
async def create_session(self, start_url: str | None = None) -> str:
|
|
46
|
+
arguments: dict[str, Any] = {}
|
|
47
|
+
if start_url:
|
|
48
|
+
arguments["start_url"] = start_url
|
|
49
|
+
result = await self.call_tool("browser.create_session", arguments)
|
|
50
|
+
content = result.get("content", [{}])
|
|
51
|
+
data = json.loads(content[0].get("text", "{}"))
|
|
52
|
+
session_id = data.get("session_id") or data.get("id")
|
|
53
|
+
if not session_id:
|
|
54
|
+
raise KeyError("browser.create_session did not return a session id")
|
|
55
|
+
return str(session_id)
|
|
56
|
+
|
|
57
|
+
async def observe(self, session_id: str) -> dict[str, Any]:
|
|
58
|
+
result = await self.call_tool("browser.observe", {"session_id": session_id})
|
|
59
|
+
content = result.get("content", [{}])
|
|
60
|
+
return json.loads(content[0].get("text", "{}"))
|
|
61
|
+
|
|
62
|
+
async def run(self, state: BrowserState) -> BrowserState:
|
|
63
|
+
session_id = state.get("session_id")
|
|
64
|
+
if not session_id:
|
|
65
|
+
session_id = await self.create_session()
|
|
66
|
+
state = {**state, "session_id": session_id}
|
|
67
|
+
observation = await self.observe(session_id)
|
|
68
|
+
return {
|
|
69
|
+
**state,
|
|
70
|
+
"current_url": observation.get("url", ""),
|
|
71
|
+
"screenshot_url": observation.get("screenshot_url", ""),
|
|
72
|
+
}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import json
|
|
4
|
+
from typing import Any, Optional, Type
|
|
5
|
+
|
|
6
|
+
import httpx
|
|
7
|
+
|
|
8
|
+
try:
|
|
9
|
+
from langchain_core.tools import BaseTool
|
|
10
|
+
from pydantic import BaseModel
|
|
11
|
+
from pydantic import Field as PydanticField
|
|
12
|
+
|
|
13
|
+
_LANGCHAIN_AVAILABLE = True
|
|
14
|
+
except ImportError:
|
|
15
|
+
_LANGCHAIN_AVAILABLE = False
|
|
16
|
+
BaseTool = object
|
|
17
|
+
BaseModel = object
|
|
18
|
+
PydanticField = lambda *args, **kwargs: None # noqa: E731
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
if _LANGCHAIN_AVAILABLE:
|
|
22
|
+
class AutoBrowserInput(BaseModel):
|
|
23
|
+
action: str = PydanticField(description="MCP tool name, e.g. 'browser.observe'")
|
|
24
|
+
arguments: dict[str, Any] = PydanticField(default_factory=dict, description="Tool arguments")
|
|
25
|
+
else:
|
|
26
|
+
AutoBrowserInput = None # type: ignore[assignment]
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
class AutoBrowserTool(BaseTool):
|
|
30
|
+
name: str = "auto_browser"
|
|
31
|
+
description: str = (
|
|
32
|
+
"Control a real browser via auto-browser. "
|
|
33
|
+
"Use 'action' for the MCP tool name (e.g. 'browser.navigate', 'browser.observe', "
|
|
34
|
+
"'browser.click') and 'arguments' for its parameters. "
|
|
35
|
+
"Call browser.create_session first to get a session_id."
|
|
36
|
+
)
|
|
37
|
+
if _LANGCHAIN_AVAILABLE:
|
|
38
|
+
args_schema: Type[AutoBrowserInput] = AutoBrowserInput
|
|
39
|
+
|
|
40
|
+
base_url: str = "http://localhost:8000"
|
|
41
|
+
bearer_token: Optional[str] = None
|
|
42
|
+
timeout: float = 60.0
|
|
43
|
+
|
|
44
|
+
def _run(self, action: str, arguments: dict[str, Any] | None = None) -> str:
|
|
45
|
+
import asyncio
|
|
46
|
+
|
|
47
|
+
return asyncio.get_event_loop().run_until_complete(self._arun(action, arguments or {}))
|
|
48
|
+
|
|
49
|
+
async def _arun(self, action: str, arguments: dict[str, Any] | None = None) -> str:
|
|
50
|
+
headers: dict[str, str] = {"Content-Type": "application/json"}
|
|
51
|
+
if self.bearer_token:
|
|
52
|
+
headers["Authorization"] = f"Bearer {self.bearer_token}"
|
|
53
|
+
payload = {"name": action, "arguments": arguments or {}}
|
|
54
|
+
async with httpx.AsyncClient(base_url=self.base_url, timeout=self.timeout) as client:
|
|
55
|
+
response = await client.post("/mcp/tools/call", json=payload, headers=headers)
|
|
56
|
+
response.raise_for_status()
|
|
57
|
+
data = response.json()
|
|
58
|
+
if data.get("isError"):
|
|
59
|
+
content = data.get("content", [{}])
|
|
60
|
+
return f"ERROR: {content[0].get('text', 'Unknown error')}"
|
|
61
|
+
content = data.get("content", [{}])
|
|
62
|
+
return content[0].get("text", json.dumps(data))
|
|
63
|
+
|
|
64
|
+
@classmethod
|
|
65
|
+
def list_tools(
|
|
66
|
+
cls,
|
|
67
|
+
base_url: str = "http://localhost:8000",
|
|
68
|
+
bearer_token: str | None = None,
|
|
69
|
+
) -> list[dict]:
|
|
70
|
+
headers: dict[str, str] = {}
|
|
71
|
+
if bearer_token:
|
|
72
|
+
headers["Authorization"] = f"Bearer {bearer_token}"
|
|
73
|
+
with httpx.Client(base_url=base_url, timeout=10) as client:
|
|
74
|
+
response = client.get("/mcp/tools", headers=headers)
|
|
75
|
+
response.raise_for_status()
|
|
76
|
+
return response.json()
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: auto-browser-langchain
|
|
3
|
+
Version: 1.2.1
|
|
4
|
+
Summary: LangChain / LangGraph / CrewAI integration for auto-browser
|
|
5
|
+
Project-URL: Homepage, https://github.com/LvcidPsyche/auto-browser
|
|
6
|
+
Project-URL: Repository, https://github.com/LvcidPsyche/auto-browser
|
|
7
|
+
Project-URL: Changelog, https://github.com/LvcidPsyche/auto-browser/blob/main/CHANGELOG.md
|
|
8
|
+
Project-URL: Issues, https://github.com/LvcidPsyche/auto-browser/issues
|
|
9
|
+
License: MIT
|
|
10
|
+
Keywords: auto-browser,browser-automation,crewai,langchain,langgraph
|
|
11
|
+
Classifier: Development Status :: 4 - Beta
|
|
12
|
+
Classifier: Intended Audience :: Developers
|
|
13
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
14
|
+
Classifier: Programming Language :: Python :: 3
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
19
|
+
Requires-Python: >=3.11
|
|
20
|
+
Requires-Dist: httpx>=0.27
|
|
21
|
+
Provides-Extra: crewai
|
|
22
|
+
Requires-Dist: crewai>=0.28; extra == 'crewai'
|
|
23
|
+
Provides-Extra: langchain
|
|
24
|
+
Requires-Dist: langchain-core>=0.2; extra == 'langchain'
|
|
25
|
+
Description-Content-Type: text/markdown
|
|
26
|
+
|
|
27
|
+
# auto-browser LangChain Integration
|
|
28
|
+
|
|
29
|
+
Install from this directory with the optional extras that match your stack:
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
pip install .[langchain]
|
|
33
|
+
pip install .[crewai]
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
See:
|
|
37
|
+
- `examples/langchain-integration.md`
|
|
38
|
+
- `examples/crewai-integration.md`
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
auto_browser_langchain/__init__.py,sha256=4MeaK2l6cy26qzEiQo_CJlcw-aGgXN65792YgvJ6NXg,154
|
|
2
|
+
auto_browser_langchain/node.py,sha256=WAey1p8r1j0pMllBas0GLvZwa9Z372RSwUF0S8M1ZzI,2521
|
|
3
|
+
auto_browser_langchain/tool.py,sha256=luvdoglaCH5CyBk_N9G8KFGwJdgdlGBu0yZeZd53m1k,2853
|
|
4
|
+
auto_browser_langchain-1.2.1.dist-info/METADATA,sha256=GBbBGPJBDK4SdZ12mpO5o1kr12YTwnhSAt-L9zspLeE,1404
|
|
5
|
+
auto_browser_langchain-1.2.1.dist-info/WHEEL,sha256=mffPy8wBnZQn2VnJUU5jE99KsxaSfiyMHV9Yt0aLVxs,87
|
|
6
|
+
auto_browser_langchain-1.2.1.dist-info/RECORD,,
|