stagehand-middleware 0.1.0__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.
- stagehand_middleware-0.1.0/PKG-INFO +83 -0
- stagehand_middleware-0.1.0/README.md +70 -0
- stagehand_middleware-0.1.0/pyproject.toml +66 -0
- stagehand_middleware-0.1.0/pyproject.toml.orig +51 -0
- stagehand_middleware-0.1.0/src/stagehand_middleware/__init__.py +1 -0
- stagehand_middleware-0.1.0/src/stagehand_middleware/facade/__init__.py +30 -0
- stagehand_middleware-0.1.0/src/stagehand_middleware/facade/_bundle.json +661 -0
- stagehand_middleware-0.1.0/src/stagehand_middleware/facade/_syntax.py +79 -0
- stagehand_middleware-0.1.0/src/stagehand_middleware/facade/bundle.py +83 -0
- stagehand_middleware-0.1.0/src/stagehand_middleware/facade/tools.py +446 -0
- stagehand_middleware-0.1.0/src/stagehand_middleware/py.typed +0 -0
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: stagehand-middleware
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Stagehand's facade tools (run, snapshot, screenshot) for Python hosts
|
|
5
|
+
Author: Browserbase
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Requires-Dist: jsonschema>=4.23,<5
|
|
8
|
+
Requires-Dist: stagehand>=4.3.0,<5
|
|
9
|
+
Requires-Dist: tree-sitter>=0.25,<0.27
|
|
10
|
+
Requires-Dist: tree-sitter-javascript>=0.25,<0.26
|
|
11
|
+
Requires-Python: >=3.11
|
|
12
|
+
Description-Content-Type: text/markdown
|
|
13
|
+
|
|
14
|
+
# stagehand-middleware (Python)
|
|
15
|
+
|
|
16
|
+
The facade's `run`, `snapshot` and `screenshot` tools for Python, over an existing
|
|
17
|
+
`stagehand.Stagehand`. It is a thin host for the facade bundle that
|
|
18
|
+
`@browserbasehq/stagehand-integrations` builds (`dist/facade-bundle.json`): the
|
|
19
|
+
JavaScript sent to `experimental_batch` and the model-facing contract (tool names,
|
|
20
|
+
descriptions, input schemas, error messages and result caps) come from that
|
|
21
|
+
bundle, so agents see the same tools as with the TypeScript facade.
|
|
22
|
+
|
|
23
|
+
```python
|
|
24
|
+
from stagehand import Stagehand
|
|
25
|
+
from stagehand_middleware.facade import StagehandFacadeTools, facade_instructions, facade_tools
|
|
26
|
+
|
|
27
|
+
stagehand = await Stagehand.create(...)
|
|
28
|
+
tools = StagehandFacadeTools(stagehand, artifact_root="artifacts")
|
|
29
|
+
|
|
30
|
+
await tools.run(code="await page.goto('https://example.com'); return await page.title();")
|
|
31
|
+
tree = await tools.snapshot()
|
|
32
|
+
await tools.run(actions=[{"op": "click", "id": "0-7"}])
|
|
33
|
+
image = await tools.screenshot(type="jpeg", quality=40)
|
|
34
|
+
|
|
35
|
+
facade_tools() # tools/list entries to register with an agent framework
|
|
36
|
+
facade_instructions() # the agent instructions for the system prompt
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
- `run` code runs inside an async function with Playwright-shaped `page`,
|
|
40
|
+
`context` and `browser`. An error it throws is raised as
|
|
41
|
+
`StagehandFacadeExecutionError` (with the JavaScript `name` and `stack`).
|
|
42
|
+
`StagehandFacadeInputError` covers bad input and contract errors (stale
|
|
43
|
+
snapshot IDs, malformed run results, artifact paths and caps, a closed facade).
|
|
44
|
+
Other failures keep their own types: an error from the batch or RPC call
|
|
45
|
+
itself (for example `stagehand.rpc_client.RPCError`) propagates unchanged, a snapshot or
|
|
46
|
+
screenshot past its capture deadline raises `TimeoutError`, and a failed close
|
|
47
|
+
raises `StagehandFacadeCleanupError` (or an `ExceptionGroup` with the run's own
|
|
48
|
+
error). Code that does not parse as an async function body raises
|
|
49
|
+
`SyntaxError` before anything is sent.
|
|
50
|
+
- Screenshots saved with a `path` are written under `artifact_root` (default: the
|
|
51
|
+
current directory). A path must stay within it and must not pass through a
|
|
52
|
+
symlink.
|
|
53
|
+
- `browser.close()` in run code closes the Stagehand and its browser once the
|
|
54
|
+
call finishes (pass `on_close_requested` to own that cleanup); later calls fail.
|
|
55
|
+
- `quiet_wait=True` (experimental, off by default) makes a `page.waitForTimeout(ms)`
|
|
56
|
+
longer than 400 ms in run code return once the page is quiet (DOM loaded, no
|
|
57
|
+
mutation in the main document for 400 ms; shadow roots are not observed),
|
|
58
|
+
never later than `ms`. Shorter waits sleep in full.
|
|
59
|
+
|
|
60
|
+
This host has no keeper tab and does not latch session loss; the TypeScript
|
|
61
|
+
`StagehandFacadeTools` does both.
|
|
62
|
+
|
|
63
|
+
## Development
|
|
64
|
+
|
|
65
|
+
`src/stagehand_middleware/facade/_bundle.json` is a copy of the built bundle.
|
|
66
|
+
After changing the TypeScript facade, rebuild the integrations package and run
|
|
67
|
+
`pnpm run sync:python` in `packages/integrations/core`;
|
|
68
|
+
`tests/facade-python-bundle.test.ts` and
|
|
69
|
+
`node scripts/sync-python-facade-bundle.mjs --check` (which CI runs in the
|
|
70
|
+
Python job) fail while the copy is stale. The package also checks the copy's
|
|
71
|
+
`sha256` when it loads it.
|
|
72
|
+
|
|
73
|
+
```bash
|
|
74
|
+
uv run ruff format --check
|
|
75
|
+
uv run ruff check
|
|
76
|
+
uv run ty check
|
|
77
|
+
uv run pytest
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
`tests/test_conformance.py` runs the cases in `../conformance` against this host.
|
|
81
|
+
`tests/test_browser.py` drives a local Chrome end to end; it is skipped unless
|
|
82
|
+
`STAGEHAND_INTEGRATIONS_BROWSER_TESTS=1` (set `CHROME_PATH` if the Stagehand SDK
|
|
83
|
+
does not find Chrome).
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
# stagehand-middleware (Python)
|
|
2
|
+
|
|
3
|
+
The facade's `run`, `snapshot` and `screenshot` tools for Python, over an existing
|
|
4
|
+
`stagehand.Stagehand`. It is a thin host for the facade bundle that
|
|
5
|
+
`@browserbasehq/stagehand-integrations` builds (`dist/facade-bundle.json`): the
|
|
6
|
+
JavaScript sent to `experimental_batch` and the model-facing contract (tool names,
|
|
7
|
+
descriptions, input schemas, error messages and result caps) come from that
|
|
8
|
+
bundle, so agents see the same tools as with the TypeScript facade.
|
|
9
|
+
|
|
10
|
+
```python
|
|
11
|
+
from stagehand import Stagehand
|
|
12
|
+
from stagehand_middleware.facade import StagehandFacadeTools, facade_instructions, facade_tools
|
|
13
|
+
|
|
14
|
+
stagehand = await Stagehand.create(...)
|
|
15
|
+
tools = StagehandFacadeTools(stagehand, artifact_root="artifacts")
|
|
16
|
+
|
|
17
|
+
await tools.run(code="await page.goto('https://example.com'); return await page.title();")
|
|
18
|
+
tree = await tools.snapshot()
|
|
19
|
+
await tools.run(actions=[{"op": "click", "id": "0-7"}])
|
|
20
|
+
image = await tools.screenshot(type="jpeg", quality=40)
|
|
21
|
+
|
|
22
|
+
facade_tools() # tools/list entries to register with an agent framework
|
|
23
|
+
facade_instructions() # the agent instructions for the system prompt
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
- `run` code runs inside an async function with Playwright-shaped `page`,
|
|
27
|
+
`context` and `browser`. An error it throws is raised as
|
|
28
|
+
`StagehandFacadeExecutionError` (with the JavaScript `name` and `stack`).
|
|
29
|
+
`StagehandFacadeInputError` covers bad input and contract errors (stale
|
|
30
|
+
snapshot IDs, malformed run results, artifact paths and caps, a closed facade).
|
|
31
|
+
Other failures keep their own types: an error from the batch or RPC call
|
|
32
|
+
itself (for example `stagehand.rpc_client.RPCError`) propagates unchanged, a snapshot or
|
|
33
|
+
screenshot past its capture deadline raises `TimeoutError`, and a failed close
|
|
34
|
+
raises `StagehandFacadeCleanupError` (or an `ExceptionGroup` with the run's own
|
|
35
|
+
error). Code that does not parse as an async function body raises
|
|
36
|
+
`SyntaxError` before anything is sent.
|
|
37
|
+
- Screenshots saved with a `path` are written under `artifact_root` (default: the
|
|
38
|
+
current directory). A path must stay within it and must not pass through a
|
|
39
|
+
symlink.
|
|
40
|
+
- `browser.close()` in run code closes the Stagehand and its browser once the
|
|
41
|
+
call finishes (pass `on_close_requested` to own that cleanup); later calls fail.
|
|
42
|
+
- `quiet_wait=True` (experimental, off by default) makes a `page.waitForTimeout(ms)`
|
|
43
|
+
longer than 400 ms in run code return once the page is quiet (DOM loaded, no
|
|
44
|
+
mutation in the main document for 400 ms; shadow roots are not observed),
|
|
45
|
+
never later than `ms`. Shorter waits sleep in full.
|
|
46
|
+
|
|
47
|
+
This host has no keeper tab and does not latch session loss; the TypeScript
|
|
48
|
+
`StagehandFacadeTools` does both.
|
|
49
|
+
|
|
50
|
+
## Development
|
|
51
|
+
|
|
52
|
+
`src/stagehand_middleware/facade/_bundle.json` is a copy of the built bundle.
|
|
53
|
+
After changing the TypeScript facade, rebuild the integrations package and run
|
|
54
|
+
`pnpm run sync:python` in `packages/integrations/core`;
|
|
55
|
+
`tests/facade-python-bundle.test.ts` and
|
|
56
|
+
`node scripts/sync-python-facade-bundle.mjs --check` (which CI runs in the
|
|
57
|
+
Python job) fail while the copy is stale. The package also checks the copy's
|
|
58
|
+
`sha256` when it loads it.
|
|
59
|
+
|
|
60
|
+
```bash
|
|
61
|
+
uv run ruff format --check
|
|
62
|
+
uv run ruff check
|
|
63
|
+
uv run ty check
|
|
64
|
+
uv run pytest
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
`tests/test_conformance.py` runs the cases in `../conformance` against this host.
|
|
68
|
+
`tests/test_browser.py` drives a local Chrome end to end; it is skipped unless
|
|
69
|
+
`STAGEHAND_INTEGRATIONS_BROWSER_TESTS=1` (set `CHROME_PATH` if the Stagehand SDK
|
|
70
|
+
does not find Chrome).
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "stagehand-middleware"
|
|
3
|
+
version = "0.1.0"
|
|
4
|
+
description = "Stagehand's facade tools (run, snapshot, screenshot) for Python hosts"
|
|
5
|
+
readme = "README.md"
|
|
6
|
+
requires-python = ">=3.11"
|
|
7
|
+
dependencies = [
|
|
8
|
+
"jsonschema>=4.23,<5",
|
|
9
|
+
"stagehand>=4.3.0,<5",
|
|
10
|
+
"tree-sitter>=0.25,<0.27",
|
|
11
|
+
"tree-sitter-javascript>=0.25,<0.26",
|
|
12
|
+
]
|
|
13
|
+
license = "MIT"
|
|
14
|
+
|
|
15
|
+
[[project.authors]]
|
|
16
|
+
name = "Browserbase"
|
|
17
|
+
|
|
18
|
+
[build-system]
|
|
19
|
+
requires = ["uv_build>=0.11.29,<0.12.0"]
|
|
20
|
+
build-backend = "uv_build"
|
|
21
|
+
|
|
22
|
+
[tool.uv.build-backend]
|
|
23
|
+
module-name = "stagehand_middleware"
|
|
24
|
+
|
|
25
|
+
[tool.uv.sources.stagehand]
|
|
26
|
+
path = "../../../sdk-python"
|
|
27
|
+
editable = true
|
|
28
|
+
|
|
29
|
+
[tool.ruff]
|
|
30
|
+
target-version = "py311"
|
|
31
|
+
line-length = 100
|
|
32
|
+
preview = true
|
|
33
|
+
|
|
34
|
+
[tool.ruff.lint]
|
|
35
|
+
select = [
|
|
36
|
+
"ANN",
|
|
37
|
+
"E",
|
|
38
|
+
"F",
|
|
39
|
+
"I",
|
|
40
|
+
"PYI",
|
|
41
|
+
"UP",
|
|
42
|
+
]
|
|
43
|
+
|
|
44
|
+
[tool.ty.environment]
|
|
45
|
+
python-version = "3.11"
|
|
46
|
+
|
|
47
|
+
[tool.ty.rules]
|
|
48
|
+
missing-type-argument = "error"
|
|
49
|
+
possibly-unresolved-reference = "error"
|
|
50
|
+
unsound-return-statement = "error"
|
|
51
|
+
dynamic-function-decorator-return = "error"
|
|
52
|
+
missing-override-decorator = "error"
|
|
53
|
+
unused-ignore-comment = "error"
|
|
54
|
+
|
|
55
|
+
[tool.pytest.ini_options]
|
|
56
|
+
asyncio_mode = "auto"
|
|
57
|
+
testpaths = ["tests"]
|
|
58
|
+
strict = true
|
|
59
|
+
|
|
60
|
+
[dependency-groups]
|
|
61
|
+
dev = [
|
|
62
|
+
"pytest==9.0.3",
|
|
63
|
+
"pytest-asyncio==1.3.0",
|
|
64
|
+
"ruff==0.15.7",
|
|
65
|
+
"ty==0.0.82",
|
|
66
|
+
]
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "stagehand-middleware"
|
|
3
|
+
version = "0.1.0"
|
|
4
|
+
description = "Stagehand's facade tools (run, snapshot, screenshot) for Python hosts"
|
|
5
|
+
readme = "README.md"
|
|
6
|
+
requires-python = ">=3.11"
|
|
7
|
+
dependencies = [
|
|
8
|
+
"jsonschema>=4.23,<5",
|
|
9
|
+
"stagehand>=4.3.0,<5",
|
|
10
|
+
"tree-sitter>=0.25,<0.27",
|
|
11
|
+
"tree-sitter-javascript>=0.25,<0.26",
|
|
12
|
+
]
|
|
13
|
+
license = "MIT"
|
|
14
|
+
authors = [{ name = "Browserbase" }]
|
|
15
|
+
|
|
16
|
+
[build-system]
|
|
17
|
+
requires = ["uv_build>=0.11.29,<0.12.0"]
|
|
18
|
+
build-backend = "uv_build"
|
|
19
|
+
|
|
20
|
+
[tool.uv.build-backend]
|
|
21
|
+
module-name = "stagehand_middleware"
|
|
22
|
+
|
|
23
|
+
[tool.uv.sources]
|
|
24
|
+
stagehand = { path = "../../../sdk-python", editable = true }
|
|
25
|
+
|
|
26
|
+
[tool.ruff]
|
|
27
|
+
target-version = "py311"
|
|
28
|
+
line-length = 100
|
|
29
|
+
preview = true
|
|
30
|
+
|
|
31
|
+
[tool.ruff.lint]
|
|
32
|
+
select = ["ANN", "E", "F", "I", "PYI", "UP"]
|
|
33
|
+
|
|
34
|
+
[tool.ty.environment]
|
|
35
|
+
python-version = "3.11"
|
|
36
|
+
|
|
37
|
+
[tool.ty.rules]
|
|
38
|
+
missing-type-argument = "error"
|
|
39
|
+
possibly-unresolved-reference = "error"
|
|
40
|
+
unsound-return-statement = "error"
|
|
41
|
+
dynamic-function-decorator-return = "error"
|
|
42
|
+
missing-override-decorator = "error"
|
|
43
|
+
unused-ignore-comment = "error"
|
|
44
|
+
|
|
45
|
+
[tool.pytest.ini_options]
|
|
46
|
+
asyncio_mode = "auto"
|
|
47
|
+
testpaths = ["tests"]
|
|
48
|
+
strict = true
|
|
49
|
+
|
|
50
|
+
[dependency-groups]
|
|
51
|
+
dev = ["pytest==9.0.3", "pytest-asyncio==1.3.0", "ruff==0.15.7", "ty==0.0.82"]
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"""Shared integration surfaces for Stagehand; see `stagehand_middleware.facade`."""
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
"""Stagehand's facade tools for Python: one bundle of browser-side sources and
|
|
2
|
+
model-facing contract, shared with the TypeScript facade."""
|
|
3
|
+
|
|
4
|
+
from .bundle import (
|
|
5
|
+
StagehandFacadeBundleError,
|
|
6
|
+
ToolSet,
|
|
7
|
+
contract_error,
|
|
8
|
+
facade_bundle,
|
|
9
|
+
facade_instructions,
|
|
10
|
+
facade_tools,
|
|
11
|
+
)
|
|
12
|
+
from .tools import (
|
|
13
|
+
StagehandFacadeCleanupError,
|
|
14
|
+
StagehandFacadeExecutionError,
|
|
15
|
+
StagehandFacadeInputError,
|
|
16
|
+
StagehandFacadeTools,
|
|
17
|
+
)
|
|
18
|
+
|
|
19
|
+
__all__ = [
|
|
20
|
+
"StagehandFacadeBundleError",
|
|
21
|
+
"StagehandFacadeCleanupError",
|
|
22
|
+
"StagehandFacadeExecutionError",
|
|
23
|
+
"StagehandFacadeInputError",
|
|
24
|
+
"StagehandFacadeTools",
|
|
25
|
+
"ToolSet",
|
|
26
|
+
"contract_error",
|
|
27
|
+
"facade_bundle",
|
|
28
|
+
"facade_instructions",
|
|
29
|
+
"facade_tools",
|
|
30
|
+
]
|