-
Notifications
You must be signed in to change notification settings - Fork 98
Stagehand Canonical Release #277
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
* feat(api): manual updates * feat(api): manual updates * codegen metadata * codegen metadata * feat(api): manual updates * codegen metadata * feat(api): manual updates * feat(api): manual updates * codegen metadata * feat(api): manual updates * codegen metadata * feat(api): manual updates * feat(api): manual updates * feat(api): manual updates * codegen metadata * feat(api): manual updates * chore: speedup initial import * refactor(internal): switch from rye to uv * feat(api): manual updates * feat(api): manual updates * feat(api): manual updates * feat(api): manual updates * feat(api): manual updates * feat(api): manual updates * codegen metadata * feat(api): manual updates * feat(api): manual updates * fix: use async_to_httpx_files in patch method * chore(internal): add `--fix` argument to lint script * feat(api): manual updates * docs: add more examples * feat: [STG-1053] [server] Use fastify-zod-openapi + zod v4 for openapi generation * chore: update SDK settings * chore: update SDK settings * release: 0.1.0 --------- Co-authored-by: stainless-app[bot] <142633134+stainless-app[bot]@users.noreply.github.com>
* feat(api): manual updates * codegen metadata * docs: prominently feature MCP server setup in root SDK readmes * feat: Added optional param to force empty object * release: 0.2.0 * Added x-language and minimal agent example * lint fix * Added full example + updated readme * Added local binary logic * Added empty body logic for /end endpoint * lint fix * Added bundling logic for wheels * lint fix --------- Co-authored-by: stainless-app[bot] <142633134+stainless-app[bot]@users.noreply.github.com> Co-authored-by: monadoid <[email protected]>
* fix: specify pnpm version 9 in publish workflow * release: 0.2.1 --------- Co-authored-by: monadoid <[email protected]> Co-authored-by: stainless-app[bot] <142633134+stainless-app[bot]@users.noreply.github.com>
* fix: specify pnpm version 9 in publish workflow * fix: correct binary names and update macOS runner in publish workflow * release: 0.2.2 --------- Co-authored-by: monadoid <[email protected]> Co-authored-by: stainless-app[bot] <142633134+stainless-app[bot]@users.noreply.github.com>
* fix: use macos-15-intel runner for darwin-x64 builds * release: 0.2.3 --------- Co-authored-by: monadoid <[email protected]> Co-authored-by: stainless-app[bot] <142633134+stainless-app[bot]@users.noreply.github.com>
* codegen metadata * Added x_sdk_version headers + resolved api path * docs: update README with SDK version headers * release: 0.2.4 --------- Co-authored-by: stainless-app[bot] <142633134+stainless-app[bot]@users.noreply.github.com> Co-authored-by: monadoid <[email protected]>
* Added session create helper * Using existing types * Showing only async python examples * docs show using uv * Added local example * lint fix
* Made frameId optional * Added link to local_example in readme. * Minimal working byob example * Working bring-your-own-browser-driver example interleaving playwright with stagehand.
* feat: Removed requiring x-language and x-sdk-version from openapi spec * feat: Using provider/model syntax in modelName examples within openapi spec * release: 0.3.0 --------- Co-authored-by: stainless-app[bot] <142633134+stainless-app[bot]@users.noreply.github.com>
…t with autogen sdk docs (#271)
* remove x-language and x-sdk-version * linting
* codegen metadata * release: 0.3.1 --------- Co-authored-by: stainless-app[bot] <142633134+stainless-app[bot]@users.noreply.github.com>
…internal and clarifying the name
…PENAI_API_KEY can be used - one is required to be set.
- Replace README header with standardized Stagehand branding - Update docs URL to /v3/sdk/python - Add 'What is Stagehand?' and 'Why Stagehand?' sections 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Claude Sonnet 4.5 <[email protected]>
* Standardize README with Stagehand branding - Replace README header with standardized Stagehand branding - Update docs URL to /v3/sdk/python - Add 'What is Stagehand?' and 'Why Stagehand?' sections 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.5 <[email protected]> * Fix media URLs to use absolute GitHub paths 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.5 <[email protected]> --------- Co-authored-by: Claude Sonnet 4.5 <[email protected]>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
33 issues found across 211 files
Note: This PR contains a large number of files. cubic only reviews up to 75 files per PR, so some files may not have been reviewed.
Prompt for AI agents (all issues)
Check if these issues are valid — if so, understand the root cause of each and fix them.
<file name="scripts/utils/ruffen-docs.py">
<violation number="1" location="scripts/utils/ruffen-docs.py:162">
P2: The `--line-length` argument is parsed but never passed to `format_code_block()`. The function always uses hardcoded `DEFAULT_LINE_LENGTH = 100`. Similarly, `--skip-string-normalization` is parsed but never used. Users would expect these CLI arguments to work, but they have no effect.</violation>
</file>
<file name="src/stagehand/_utils/_reflection.py">
<violation number="1" location="src/stagehand/_utils/_reflection.py:37">
P2: Typo in error message: "are do not match" should be "do not match".</violation>
</file>
<file name=".devcontainer/devcontainer.json">
<violation number="1" location=".devcontainer/devcontainer.json:18">
P2: Deprecated VS Code setting. `terminal.integrated.shell.linux` was deprecated in favor of terminal profiles. Use `terminal.integrated.defaultProfile.linux` instead.</violation>
</file>
<file name="examples/local_example.py">
<violation number="1" location="examples/local_example.py:30">
P2: Error message is misleading. Either `MODEL_API_KEY` or `OPENAI_API_KEY` satisfies the requirement, but only `MODEL_API_KEY` is mentioned.</violation>
<violation number="2" location="examples/local_example.py:34">
P2: Logic contradicts the docstring. The docstring says the example "defaults to `MODEL_API_KEY`", but `openai_key or model_key` gives precedence to `OPENAI_API_KEY` instead.</violation>
</file>
<file name="CONTRIBUTING.md">
<violation number="1" location="CONTRIBUTING.md:94">
P2: Malformed git URL - the branch specifier syntax is incorrect. Use `@` for branch/tag refs and place `.git` before the ref specifier. The current format `#stainless.git` will cause installation to fail.</violation>
</file>
<file name="src/stagehand/types/action_param.py">
<violation number="1" location="src/stagehand/types/action_param.py:25">
P2: The type for `backend_node_id` should be `int`, not `float`. Backend node IDs in the Chrome DevTools Protocol are integer identifiers. Using `float` is semantically incorrect and could cause precision issues with large IDs.</violation>
</file>
<file name="src/stagehand/types/session_act_response.py">
<violation number="1" location="src/stagehand/types/session_act_response.py:24">
P2: Backend node IDs should be `int`, not `float`. CDP defines `BackendNodeId` as an integer type. Using `float` could cause precision loss for large IDs and type mismatches with CDP APIs.</violation>
</file>
<file name="src/stagehand/_streaming.py">
<violation number="1" location="src/stagehand/_streaming.py:77">
P2: Same issue as in the synchronous `Stream`: calling `sse.json()` without checking if `sse.data` is non-empty can cause a `JSONDecodeError` when the SSE event has only control fields (like `id` or `retry`) without actual data.</violation>
</file>
<file name="src/stagehand/_utils/_datetime_parse.py">
<violation number="1" location="src/stagehand/_utils/_datetime_parse.py:56">
P2: Incorrect return type annotation: `int` is included in `Union[None, int, timezone]` but this function never returns an `int`. The `offset` variable is used inside `timedelta()`, not returned. Should be `Union[None, timezone]` or `Optional[timezone]`.</violation>
</file>
<file name="pyproject.toml">
<violation number="1" location="pyproject.toml:210">
P2: Ruff `target-version` is set to `py38` but `requires-python` specifies `>= 3.9`. This mismatch means ruff will lint for Python 3.8 compatibility when the package actually requires 3.9+. Update `target-version` to `py39` to match the minimum supported Python version.</violation>
</file>
<file name="src/stagehand/_utils/_typing.py">
<violation number="1" location="src/stagehand/_utils/_typing.py:131">
P2: Direct access to `base.__origin__` may raise `AttributeError` if a class inherits from both generic and non-generic bases. Use `get_origin(base)` (already imported) for safe access, consistent with the rest of this file.</violation>
</file>
<file name="examples/byob_example.py">
<violation number="1" location="examples/byob_example.py:46">
P2: Misleading comment: Playwright is not driving "that page" - it's running a completely separate browser instance. Stagehand creates its own browser session, and Playwright launches its own Chromium browser. The phrase "Playwright now drives that page" incorrectly implies they're connected. For a true BYOB example, you'd need to pass the Playwright page/browser to Stagehand (if supported), not run them in parallel.</violation>
</file>
<file name="src/stagehand/_utils/_proxy.py">
<violation number="1" location="src/stagehand/_utils/_proxy.py:30">
P2: Redundant call to `__get_proxied__()`. The `proxied` variable already contains the result from line 26. Use `repr(proxied)` instead to avoid potentially expensive duplicate initialization.</violation>
</file>
<file name=".github/workflows/release-doctor.yml">
<violation number="1" location=".github/workflows/release-doctor.yml:12">
P2: The condition checks for `github.event_name == 'push'` but the workflow only triggers on `pull_request` and `workflow_dispatch` (not `push`). This condition branch is unreachable. Either add `push` to the `on:` triggers, or remove the dead `push` check from the condition.</violation>
</file>
<file name="src/stagehand/lib/sea_binary.py">
<violation number="1" location="src/stagehand/lib/sea_binary.py:58">
P1: The path returned from `importlib_resources.as_file` context manager may be invalid after the function returns. When resources are in zipped packages, `as_file` extracts to a temporary location that gets cleaned up when the context exits. The file copying should happen inside the context manager.</violation>
</file>
<file name="src/stagehand/_files.py">
<violation number="1" location="src/stagehand/_files.py:100">
P2: Missing `f` prefix for f-string. The error message will literally print `{type(files)}` instead of the actual type value. Compare to line 56 which correctly uses `f"..."`.</violation>
</file>
<file name="examples/agent_execute.py">
<violation number="1" location="examples/agent_execute.py:13">
P2: Incorrect filename in docstring. The run command references `agent_execute_minimal.py` but this file is `agent_execute.py`.</violation>
</file>
<file name="src/stagehand/_utils/_sync.py">
<violation number="1" location="src/stagehand/_utils/_sync.py:41">
P3: Docstring example has inconsistent naming: defines `blocking_func` but calls `asyncify(blocking_function)`. Should use the same name.</violation>
<violation number="2" location="src/stagehand/_utils/_sync.py:55">
P2: Missing `@functools.wraps(function)` decorator on the wrapper function. This causes loss of the original function's metadata (`__name__`, `__doc__`, `__module__`, etc.), which affects debugging, introspection, and documentation tools.</violation>
</file>
<file name="scripts/utils/upload-artifact.sh">
<violation number="1" location="scripts/utils/upload-artifact.sh:4">
P1: Glob pattern `dist/*.whl` may match multiple files, causing `basename` to silently use only the first one. Consider validating exactly one wheel file exists or using an array to handle this explicitly.</violation>
</file>
<file name="examples/logging_example.py">
<violation number="1" location="examples/logging_example.py:57">
P1: The `object | None` union syntax requires Python 3.10+, but this project supports Python 3.9. Use `Optional[object]` from `typing` module for backward compatibility, or simply remove the type annotation for this example variable.</violation>
</file>
<file name="src/stagehand/_utils/_transform.py">
<violation number="1" location="src/stagehand/_utils/_transform.py:184">
P1: Calls synchronous `_transform_recursive` inside async function instead of `await _async_transform_recursive`. This breaks the async chain and may cause issues with nested async transformations.</violation>
</file>
<file name="src/stagehand/_client.py">
<violation number="1" location="src/stagehand/_client.py:54">
P2: Type annotation mismatch: `browserbase_api_key` and `browserbase_project_id` are typed as `str` but can be `None`. The attributes should be typed as `str | None` to match the actual behavior, since `os.environ.get()` returns `Optional[str]` and no validation raises an error when these are missing (unlike `model_api_key`).</violation>
</file>
<file name="src/stagehand/lib/sea_server.py">
<violation number="1" location="src/stagehand/lib/sea_server.py:111">
P1: Race condition: `_lock` (threading.Lock) and `_async_lock` (asyncio.Lock) don't synchronize with each other. If `ensure_running_sync()` and `ensure_running_async()` are called concurrently from different contexts, both can bypass each other's lock and potentially start duplicate server processes. Consider using a single `threading.Lock` for both (acquiring it in a thread-safe manner for async via `asyncio.to_thread` or similar coordination).</violation>
<violation number="2" location="src/stagehand/lib/sea_server.py:203">
P1: Bug: The atexit handler is registered only once with the first process. If `close()` is called and a new process is started via `ensure_running_*()`, the new process won't have an atexit handler (since `_atexit_registered` is already `True`), potentially leaving orphaned processes on exit. Consider either unregistering the old handler in `close()` or tracking/terminating the current `_proc` in a single atexit callback.</violation>
</file>
<file name="README.md">
<violation number="1" location="README.md:117">
P2: Inconsistent package name: The Installation section uses `stagehand` but this block uses `stagehand-alpha`. This duplicate bash block after the PowerShell section also appears to be leftover content. Consider removing this block or updating it to match the main installation instruction (`uv pip install stagehand`).</violation>
</file>
<file name=".gitignore">
<violation number="1" location=".gitignore:17">
P1: Using `.env` instead of `.env*` may expose secrets. Common environment files like `.env.local`, `.env.production`, or `.env.staging` won't be ignored and could be accidentally committed with real API keys. Consider using `.env*` with an explicit `!.env.example` exception to allow the example file while protecting other variants.</violation>
</file>
<file name="src/stagehand/_utils/_utils.py">
<violation number="1" location="src/stagehand/_utils/_utils.py:361">
P2: Bug: `removesuffix` returns empty string when `suffix` is empty. When `suffix=""`, the expression `string[:-len(suffix)]` evaluates to `string[:-0]` which equals `string[:0]` (empty string), instead of returning the original string like Python's built-in `str.removesuffix`.</violation>
</file>
<file name="src/stagehand/_response.py">
<violation number="1" location="src/stagehand/_response.py:302">
P3: Inconsistent docstring: `AsyncAPIResponse.parse()` is missing `int` and `float` in the supported types list, but the sync `APIResponse.parse()` includes them. Both use the same `_parse()` method that supports these types.</violation>
<violation number="2" location="src/stagehand/_response.py:569">
P3: Typo in docstring: "read th entire" should be "read the entire".</violation>
</file>
<file name="src/stagehand/_compat.py">
<violation number="1" location="src/stagehand/_compat.py:94">
P1: This function will crash with `AttributeError` on Pydantic v1 because `FieldInfo.get_default()` is a v2-only method. The version check must happen before calling `get_default()`. In v1, use `field.default` instead.</violation>
</file>
<file name="src/stagehand/_models.py">
<violation number="1" location="src/stagehand/_models.py:553">
P1: `issubclass(type_, BaseModel)` will raise `TypeError` when `type_` is a subscripted generic like `MyModel[int]`. The outer condition validates `origin` is a class, but `type_` could still be a generic alias. Use `origin` instead.</violation>
</file>
Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.
| except Exception: | ||
| return None | ||
|
|
||
| with importlib_resources.as_file(candidate) as extracted: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
P1: The path returned from importlib_resources.as_file context manager may be invalid after the function returns. When resources are in zipped packages, as_file extracts to a temporary location that gets cleaned up when the context exits. The file copying should happen inside the context manager.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At src/stagehand/lib/sea_binary.py, line 58:
<comment>The path returned from `importlib_resources.as_file` context manager may be invalid after the function returns. When resources are in zipped packages, `as_file` extracts to a temporary location that gets cleaned up when the context exits. The file copying should happen inside the context manager.</comment>
<file context>
@@ -0,0 +1,121 @@
+ except Exception:
+ return None
+
+ with importlib_resources.as_file(candidate) as extracted:
+ return extracted
+
</file context>
| #!/usr/bin/env bash | ||
| set -exuo pipefail | ||
|
|
||
| FILENAME=$(basename dist/*.whl) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
P1: Glob pattern dist/*.whl may match multiple files, causing basename to silently use only the first one. Consider validating exactly one wheel file exists or using an array to handle this explicitly.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At scripts/utils/upload-artifact.sh, line 4:
<comment>Glob pattern `dist/*.whl` may match multiple files, causing `basename` to silently use only the first one. Consider validating exactly one wheel file exists or using an array to handle this explicitly.</comment>
<file context>
@@ -0,0 +1,27 @@
+#!/usr/bin/env bash
+set -exuo pipefail
+
+FILENAME=$(basename dist/*.whl)
+
+RESPONSE=$(curl -X POST "$URL?filename=$FILENAME" \
</file context>
| FILENAME=$(basename dist/*.whl) | |
| shopt -s nullglob | |
| WHL_FILES=(dist/*.whl) | |
| if [[ ${#WHL_FILES[@]} -ne 1 ]]; then | |
| echo -e "\033[31mExpected exactly one .whl file in dist/, found ${#WHL_FILES[@]}\033[0m" | |
| exit 1 | |
| fi | |
| FILENAME=$(basename "${WHL_FILES[0]}") |
| x_stream_response="true", | ||
| ) | ||
|
|
||
| result_payload: object | None = None |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
P1: The object | None union syntax requires Python 3.10+, but this project supports Python 3.9. Use Optional[object] from typing module for backward compatibility, or simply remove the type annotation for this example variable.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At examples/logging_example.py, line 57:
<comment>The `object | None` union syntax requires Python 3.10+, but this project supports Python 3.9. Use `Optional[object]` from `typing` module for backward compatibility, or simply remove the type annotation for this example variable.</comment>
<file context>
@@ -0,0 +1,81 @@
+ x_stream_response="true",
+ )
+
+ result_payload: object | None = None
+ async for event in stream:
+ if event.type == "log":
</file context>
| result_payload: object | None = None | |
| result_payload = None |
|
|
||
| if origin == dict and is_mapping(data): | ||
| items_type = get_args(stripped_type)[1] | ||
| return {key: _transform_recursive(value, annotation=items_type) for key, value in data.items()} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
P1: Calls synchronous _transform_recursive inside async function instead of await _async_transform_recursive. This breaks the async chain and may cause issues with nested async transformations.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At src/stagehand/_utils/_transform.py, line 184:
<comment>Calls synchronous `_transform_recursive` inside async function instead of `await _async_transform_recursive`. This breaks the async chain and may cause issues with nested async transformations.</comment>
<file context>
@@ -0,0 +1,457 @@
+
+ if origin == dict and is_mapping(data):
+ items_type = get_args(stripped_type)[1]
+ return {key: _transform_recursive(value, annotation=items_type) for key, value in data.items()}
+
+ if (
</file context>
| return {key: _transform_recursive(value, annotation=items_type) for key, value in data.items()} | |
| return {key: await _async_transform_recursive(value, annotation=items_type) for key, value in data.items()} |
| creationflags=creationflags, | ||
| ) | ||
|
|
||
| if not self._atexit_registered: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
P1: Bug: The atexit handler is registered only once with the first process. If close() is called and a new process is started via ensure_running_*(), the new process won't have an atexit handler (since _atexit_registered is already True), potentially leaving orphaned processes on exit. Consider either unregistering the old handler in close() or tracking/terminating the current _proc in a single atexit callback.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At src/stagehand/lib/sea_server.py, line 203:
<comment>Bug: The atexit handler is registered only once with the first process. If `close()` is called and a new process is started via `ensure_running_*()`, the new process won't have an atexit handler (since `_atexit_registered` is already `True`), potentially leaving orphaned processes on exit. Consider either unregistering the old handler in `close()` or tracking/terminating the current `_proc` in a single atexit callback.</comment>
<file context>
@@ -0,0 +1,263 @@
+ creationflags=creationflags,
+ )
+
+ if not self._atexit_registered:
+ atexit.register(_terminate_process, proc)
+ self._atexit_registered = True
</file context>
| ``` | ||
|
|
||
| ```bash | ||
| pip install stagehand-alpha |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
P2: Inconsistent package name: The Installation section uses stagehand but this block uses stagehand-alpha. This duplicate bash block after the PowerShell section also appears to be leftover content. Consider removing this block or updating it to match the main installation instruction (uv pip install stagehand).
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At README.md, line 117:
<comment>Inconsistent package name: The Installation section uses `stagehand` but this block uses `stagehand-alpha`. This duplicate bash block after the PowerShell section also appears to be leftover content. Consider removing this block or updating it to match the main installation instruction (`uv pip install stagehand`).</comment>
<file context>
@@ -47,184 +45,565 @@ If you're looking for the TypeScript implementation, you can find it
+```
+
+```bash
+pip install stagehand-alpha
+uv run python examples/local_example.py
+```
</file context>
| Backport of `str.removesuffix` for Python < 3.9 | ||
| """ | ||
| if string.endswith(suffix): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
P2: Bug: removesuffix returns empty string when suffix is empty. When suffix="", the expression string[:-len(suffix)] evaluates to string[:-0] which equals string[:0] (empty string), instead of returning the original string like Python's built-in str.removesuffix.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At src/stagehand/_utils/_utils.py, line 361:
<comment>Bug: `removesuffix` returns empty string when `suffix` is empty. When `suffix=""`, the expression `string[:-len(suffix)]` evaluates to `string[:-0]` which equals `string[:0]` (empty string), instead of returning the original string like Python's built-in `str.removesuffix`.</comment>
<file context>
@@ -0,0 +1,421 @@
+
+ Backport of `str.removesuffix` for Python < 3.9
+ """
+ if string.endswith(suffix):
+ return string[: -len(suffix)]
+ return string
</file context>
| if string.endswith(suffix): | |
| if suffix and string.endswith(suffix): |
| return result | ||
| result = asyncify(blocking_function)(arg1, arg2, kwarg1=value1) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
P3: Docstring example has inconsistent naming: defines blocking_func but calls asyncify(blocking_function). Should use the same name.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At src/stagehand/_utils/_sync.py, line 41:
<comment>Docstring example has inconsistent naming: defines `blocking_func` but calls `asyncify(blocking_function)`. Should use the same name.</comment>
<file context>
@@ -0,0 +1,58 @@
+ return result
+
+
+ result = asyncify(blocking_function)(arg1, arg2, kwarg1=value1)
+ ```
+
</file context>
| result = asyncify(blocking_function)(arg1, arg2, kwarg1=value1) | |
| result = asyncify(blocking_func)(arg1, arg2, kwarg1=value1) |
| been streamed. | ||
| This can happen if you use a method like `.iter_lines()` and then attempt | ||
| to read th entire response body afterwards, e.g. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
P3: Typo in docstring: "read th entire" should be "read the entire".
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At src/stagehand/_response.py, line 569:
<comment>Typo in docstring: "read th entire" should be "read the entire".</comment>
<file context>
@@ -0,0 +1,830 @@
+ been streamed.
+
+ This can happen if you use a method like `.iter_lines()` and then attempt
+ to read th entire response body afterwards, e.g.
+
+ ```py
</file context>
| to read th entire response body afterwards, e.g. | |
| to read the entire response body afterwards, e.g. |
| - `dict` | ||
| - `list` | ||
| - `Union` | ||
| - `str` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
P3: Inconsistent docstring: AsyncAPIResponse.parse() is missing int and float in the supported types list, but the sync APIResponse.parse() includes them. Both use the same _parse() method that supports these types.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At src/stagehand/_response.py, line 302:
<comment>Inconsistent docstring: `AsyncAPIResponse.parse()` is missing `int` and `float` in the supported types list, but the sync `APIResponse.parse()` includes them. Both use the same `_parse()` method that supports these types.</comment>
<file context>
@@ -0,0 +1,830 @@
+ - `dict`
+ - `list`
+ - `Union`
+ - `str`
+ - `int`
+ - `float`
</file context>
| - `str` | |
| - `str` | |
| - `int` | |
| - `float` |
Canonical Stagehand 🤘
Python, Go, Java, Ruby, Rust...Stagehand is now available on every language!
With Stagehand v3 we set course to improve Stagehand's extensibility and to make it easier to bring along the tools that you all love.
Today we're extending this across all languages. Go, Ruby, Java, Rust... and a revamped Python with v3 support
In order to get here, we are releasing the canonical implementation of Stagehand powered by our newest and most powerful features, from which every SDK will benefit immediately
This will allow us to move faster, ship more, and focus on what matters most - building the best AI browser automation framework together
To learn more about this major update:
Happy🅱️ uilding