Skip to content

release: 0.51.0#94

Open
stainless-app[bot] wants to merge 27 commits intomainfrom
release-please--branches--main--changes--next
Open

release: 0.51.0#94
stainless-app[bot] wants to merge 27 commits intomainfrom
release-please--branches--main--changes--next

Conversation

@stainless-app
Copy link
Copy Markdown
Contributor

@stainless-app stainless-app Bot commented Apr 23, 2026

Automated Release PR

0.51.0 (2026-04-24)

Full Changelog: v0.50.0...v0.51.0

Features

  • add browser-scoped session client (7ca6887)
  • Expose browser_session_id on managed auth connection (0ccb507)
  • generate browser-scoped resource bindings (53b17c8)

Bug Fixes

  • address python browser routing ci follow-ups (9690923)
  • evict deleted browser routes (a873a18)
  • finish python browser routing cleanup (694907a)
  • normalize browser route cache session IDs (f4c247b)
  • normalize python browser request string bodies (3ce80e7)
  • quiet generator-script pyright noise (0bdf85e)
  • reserve internal browser request query params (b2c7aac)
  • satisfy browser-scoped lint checks (8e8dde2)
  • satisfy generated browser-scoped type checks (b410245)
  • sniff browser pool route cache updates (5328730)
  • type-check browser-scoped helpers (cfff5b4)

Chores

  • fix browser-scoped test import order (fc34859)
  • internal: more robust bootstrap script (6c9cdf3)
  • keep browser-scoped generator lint clean (a80716b)

Documentation

  • flesh out browser-scoped example (ca5d188)

Refactors

  • clean up python browser routing diff (622f844)
  • drop browser-scoped wrapper clients (dba503e)
  • inline browser resource passthrough returns (02a2f59)
  • move python browser routing rollout to env (0647d5c)
  • rename browser routing subresources config (3ae9dab)
  • simplify browser routing cache (de0476f)
  • sniff browser routes in response hooks (563de7d)

This pull request is managed by Stainless's GitHub App.

The semver version number is based on included commit messages. Alternatively, you can manually set the version number in the title of this pull request.

For a better experience, it is recommended to use either rebase-merge or squash-merge when merging this pull request.

🔗 Stainless website
📚 Read the docs
🙋 Reach out for help or questions


Note

Medium Risk
Adds request/response rewriting and auth-header stripping in the core client to support direct-to-VM browser routing, which could affect how browser subresource requests are sent. While scoped behind cached routes and an env allowlist, misrouting or cache edge cases could impact browser operations.

Overview
Bumps the SDK to 0.51.0 and updates release metadata/changelog.

Introduces browser-scoped routing support: the client now maintains a BrowserRouteCache, rewrites eligible /browsers/{session_id}/{subresource} requests to the browser VM (allowlisted via KERNEL_BROWSER_ROUTING_SUBRESOURCES, defaulting to curl), injects per-browser jwt query auth, and strips the normal Authorization header for direct-to-VM requests. The cache is automatically warmed from successful JSON responses for browser metadata endpoints (including pool acquire) and evicted on successful browser deletion or pool release.

Adds new browsers.request() and browsers.stream() helpers (sync + async) to perform raw HTTP via /curl/raw, including protections to prevent user params from overriding reserved url/jwt, plus an example and a comprehensive new routing test suite. Also exposes browser_session_id on the managed auth connection type and slightly hardens scripts/bootstrap env var handling.

Reviewed by Cursor Bugbot for commit c0728c8. Bugbot is set up for automated code reviews on this repo. Configure here.

rgarcia and others added 18 commits April 21, 2026 13:09
Bind browser subresource calls to a browser session's base_url and expose raw HTTP through request and stream helpers so metro-routed access feels like normal httpx usage.

Made-with: Cursor
Prevent browser-scoped raw HTTP helpers from letting user params override internal routing query keys, and clean up wording around browser session base_url routing.

Made-with: Cursor
Keep the browser-scoped request helpers aligned with repo linting and reserve internal raw-request query keys without exposing implementation details.

Made-with: Cursor
Keep the browser-scoped test file aligned with the repo lint configuration so the follow-up typing fixes pass CI.

Made-with: Cursor
Tighten browser-scoped helper typing and test casts so the Python SDK passes the repository's lint and pyright checks cleanly.

Made-with: Cursor
Replace the handwritten Python browser-scoped façade with deterministic generated bindings from the browser resource graph, and enforce regeneration during lint.

Made-with: Cursor
Keep the browser-scoped Python generator compatible with the repo lint pipeline by suppressing strict pyright diagnostics that are not meaningful for the AST-walking build script.

Made-with: Cursor
Keep the Python generator and generated browser-scoped façade aligned with pyright and mypy so the deterministic regeneration path passes the repo lint pipeline.

Made-with: Cursor
Sort the generator script imports and keep the deterministic browser-scoped generation path aligned with the repo lint pipeline.

Made-with: Cursor
Turn the browser-scoped Python example into a runnable demonstration of both process execution and /curl/raw-backed request and stream usage.

Made-with: Cursor
Move browser raw HTTP and direct-to-VM routing onto the main browsers resource so the SDK uses the shared browser route cache instead of a generated wrapper layer.

Made-with: Cursor
Remove the public cache priming helpers, keep jwt-required routes, and rename the example and tests so the python browser routing diff stays focused on cache-backed direct-to-VM behavior.

Made-with: Cursor
Shorten the browser_routing allowlist field to subresources so the direct-to-VM configuration stays concise while keeping the same routing behavior.

Made-with: Cursor
Move the handwritten routing helpers out of the old browser_scoped package, delete the unused browser session clone helper, warm the async browser list cache, and drop the generated type churn from the branch.

Made-with: Cursor
Preserve browser routing settings across copy(), skip cache warming for raw response wrappers, and clean up the handwritten routing files so lint can pass on the current branch.

Made-with: Cursor
Make the browser routing helpers type-check cleanly in CI, keep copy() signatures aligned with __init__, and avoid cache-warming errors on raw response wrappers.

Made-with: Cursor
Encode string request bodies before building raw /curl/raw request options so the browser routing helpers satisfy CI type checks while preserving the public request API.

Made-with: Cursor
@firetiger-agent
Copy link
Copy Markdown

Firetiger deploy monitoring skipped

This PR didn't match the auto-monitor filter configured on your GitHub connection:

Any PR that changes the kernel API. Monitor changes to API endpoints (packages/api/cmd/api/) and Temporal workflows (packages/api/lib/temporal) in the kernel repo

Reason: This is an automated release PR for the Python SDK with only internal chores, not a change to kernel API endpoints or Temporal workflows.

To monitor this PR anyway, reply with @firetiger monitor this.

@stainless-app
Copy link
Copy Markdown
Contributor Author

stainless-app Bot commented Apr 23, 2026

🧪 Testing

To try out this version of the SDK:

pip install 'https://pkg.stainless.com/s/kernel-python/9817c9f5127fd20eaef043d10795fd086c916d00/kernel-0.50.0-py3-none-any.whl'

Expires at: Sun, 24 May 2026 21:16:10 GMT
Updated at: Fri, 24 Apr 2026 21:16:10 GMT

rgarcia and others added 3 commits April 24, 2026 11:08
Remove the public browser routing constructor config and derive direct-to-VM subresource routing from KERNEL_BROWSER_ROUTING_SUBRESOURCES instead, defaulting to curl while keeping the raw request helpers direct to the browser.
Store browser routes under a normalized session ID so cache lookups and deletes stay consistent when route data includes surrounding whitespace. Add a regression test to lock in the normalization behavior.

Made-with: Cursor
@stainless-app stainless-app Bot force-pushed the release-please--branches--main--changes--next branch from 5a6d7c8 to cfb54ec Compare April 24, 2026 17:57
@stainless-app stainless-app Bot changed the title release: 0.50.1 release: 0.51.0 Apr 24, 2026
@stainless-app stainless-app Bot force-pushed the release-please--branches--main--changes--next branch from cfb54ec to d66ba1b Compare April 24, 2026 17:57
rgarcia added 3 commits April 24, 2026 16:00
Move browser route cache warming into the shared sync and async response hooks so browser metadata endpoints populate the cache consistently, including raw responses. Remove the handwritten browsers resource priming and cover the narrowed sniffing behavior with focused routing tests.

Made-with: Cursor
Drop cached browser routes after successful DELETE /browsers/{id} responses so stale direct-to-VM session URLs are not reused. Cover both the success and failure paths with focused browser routing regressions.

Made-with: Cursor
Remove the leftover result/page wrappers from browser create, retrieve, update, and list now that route cache warming lives in the shared response hooks. Keep the actual curl and raw HTTP browser routing surface unchanged.

Made-with: Cursor
rgarcia and others added 3 commits April 24, 2026 17:07
Keep the browser route cache in sync for pool acquire and release flows so leased sessions can use direct VM routing without resource-specific cache handling.

Made-with: Cursor
@stainless-app stainless-app Bot force-pushed the release-please--branches--main--changes--next branch from d66ba1b to c0728c8 Compare April 24, 2026 21:15
Copy link
Copy Markdown

@cursor cursor Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 4 potential issues.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit c0728c8. Configure here.

populate_browser_route_cache_from_value(response.json(), cache=cache)
except Exception:
# Ignore malformed JSON in routing cache population.
return
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cache populated from error responses

Low Severity

maybe_populate_browser_route_cache_from_response runs before super()._process_response, and unlike the eviction helper it never checks response.is_success. A 4xx/5xx JSON error body returned from /browsers, /browsers/{id}, or /browser_pools/{id}/acquire is still walked by populate_browser_route_cache_from_value, and any dict nested in the error payload that happens to expose session_id, base_url, and cdp_ws_url will be cached as a live route. Mirroring the is_success guard used for eviction would keep the cache in sync with actual successful allocations.

Additional Locations (1)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit c0728c8. Configure here.

params.update(options.params)
params["jwt"] = route.jwt
rewritten.params = params or options.params
return rewritten
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Dead fallback in params rewrite

Low Severity

In rewrite_direct_vm_options, params is built fresh as an empty dict, copied from options.params, and then always has jwt assigned, so params is unconditionally truthy at the point of rewritten.params = params or options.params. The or options.params fallback can never be taken and only obscures intent. Dropping the dead branch (or explicitly handling a non-mapping options.params) would make the rewrite easier to reason about.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit c0728c8. Configure here.

params.update(options.params)
params["jwt"] = route.jwt
rewritten.params = params or options.params
return rewritten
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Implicit rewrite leaks url query override

Low Severity

For the raw HTTP helpers, sanitize_curl_raw_params strips url and jwt from user-supplied params so the target URL and token cannot be overridden. The implicit path in rewrite_direct_vm_options only overwrites jwt but forwards any caller-supplied url query parameter as-is to the direct-VM endpoint. If a subresource on the browser VM ever interprets a url query parameter (today curl/raw does; future subresources might), a caller-supplied value would silently reach the VM instead of being reserved. Sharing the CURL_RAW_RESERVED_QUERY_KEYS filter here would keep the two routing paths consistent.

Additional Locations (1)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit c0728c8. Configure here.

json_data=json,
timeout=_normalize_timeout(timeout),
)
return cast(httpx.Response, parent.request(httpx.Response, options))
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Direct-VM request helper silently disables client timeout

High Severity

When callers invoke browsers.request (and the async variant) without specifying timeout, the helper passes _normalize_timeout(not_given) which collapses to None and stores it on FinalRequestOptions.timeout. In _build_request, the client-level self.timeout is only consulted when options.timeout is NotGiven, so the explicit None bypasses the configured client timeout and httpx is handed no timeout at all — requests can hang indefinitely. The stream helper correctly captures parent.timeout before normalizing, but the non-streaming path does not.

Additional Locations (2)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit c0728c8. Configure here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant