auto-browser-langchain 1.2.1__tar.gz

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,51 @@
1
+ .env
2
+ .autonomous/
3
+ .agents/
4
+ docs/brainstorms/
5
+ HANDOFF.md
6
+ CODEX_*.md
7
+ data/artifacts/*
8
+ !data/artifacts/.gitkeep
9
+ data/uploads/*
10
+ !data/uploads/.gitkeep
11
+ data/auth/*
12
+ !data/auth/.gitkeep
13
+ data/approvals/*
14
+ !data/approvals/.gitkeep
15
+ data/audit/*
16
+ !data/audit/.gitkeep
17
+ data/witness/*
18
+ !data/witness/.gitkeep
19
+ data/db/*
20
+ !data/db/.gitkeep
21
+ data/jobs/*
22
+ !data/jobs/.gitkeep
23
+ data/sessions/*
24
+ !data/sessions/.gitkeep
25
+ data/browser-sessions/*
26
+ !data/browser-sessions/.gitkeep
27
+ data/ssh/*
28
+ !data/ssh/.gitkeep
29
+ data/browser-profile/*
30
+ !data/browser-profile/.gitkeep
31
+ data/downloads/*
32
+ !data/downloads/.gitkeep
33
+ data/tunnels/*
34
+ !data/tunnels/.gitkeep
35
+ data/host-bridge/*
36
+ !data/host-bridge/.gitkeep
37
+ data/cli-home/*
38
+ !data/cli-home/.gitkeep
39
+ __pycache__/
40
+ *.pyc
41
+ .venv*/
42
+ .pytest_cache/
43
+ .pytest-cache*/
44
+ .pytest-tmp*/
45
+ .ruff_cache/
46
+ .mypy_cache/
47
+ .coverage
48
+ htmlcov/
49
+ build/
50
+ dist/
51
+ *.egg-info/
@@ -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,12 @@
1
+ # auto-browser LangChain Integration
2
+
3
+ Install from this directory with the optional extras that match your stack:
4
+
5
+ ```bash
6
+ pip install .[langchain]
7
+ pip install .[crewai]
8
+ ```
9
+
10
+ See:
11
+ - `examples/langchain-integration.md`
12
+ - `examples/crewai-integration.md`
@@ -0,0 +1,6 @@
1
+ from __future__ import annotations
2
+
3
+ from .node import AutoBrowserNode
4
+ from .tool import AutoBrowserTool
5
+
6
+ __all__ = ["AutoBrowserTool", "AutoBrowserNode"]
@@ -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,35 @@
1
+ [build-system]
2
+ requires = ["hatchling"]
3
+ build-backend = "hatchling.build"
4
+
5
+ [project]
6
+ name = "auto-browser-langchain"
7
+ version = "1.2.1"
8
+ description = "LangChain / LangGraph / CrewAI integration for auto-browser"
9
+ readme = "README.md"
10
+ license = { text = "MIT" }
11
+ requires-python = ">=3.11"
12
+ dependencies = [
13
+ "httpx>=0.27",
14
+ ]
15
+ keywords = ["auto-browser", "langchain", "langgraph", "crewai", "browser-automation"]
16
+ classifiers = [
17
+ "Development Status :: 4 - Beta",
18
+ "Intended Audience :: Developers",
19
+ "License :: OSI Approved :: MIT License",
20
+ "Programming Language :: Python :: 3",
21
+ "Programming Language :: Python :: 3.11",
22
+ "Programming Language :: Python :: 3.12",
23
+ "Programming Language :: Python :: 3.13",
24
+ "Programming Language :: Python :: 3.14",
25
+ ]
26
+
27
+ [project.optional-dependencies]
28
+ langchain = ["langchain-core>=0.2"]
29
+ crewai = ["crewai>=0.28"]
30
+
31
+ [project.urls]
32
+ Homepage = "https://github.com/LvcidPsyche/auto-browser"
33
+ Repository = "https://github.com/LvcidPsyche/auto-browser"
34
+ Changelog = "https://github.com/LvcidPsyche/auto-browser/blob/main/CHANGELOG.md"
35
+ Issues = "https://github.com/LvcidPsyche/auto-browser/issues"