Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .release-please-manifest.json
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
{
".": "0.74.0"
".": "0.75.0"
}
4 changes: 2 additions & 2 deletions .stats.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
configured_endpoints: 125
openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-ebbe079bb2542625826422afd876a3e8b499c579cf45efc5fd50e7982d34df7d.yml
openapi_spec_hash: db850b61a0d71fe9f4b642df8782d7ae
openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-f0486d0b8e34ddf8ba34e36ff97856cf973e0797e021ff621e04e4840970966e.yml
openapi_spec_hash: 12a71ce5ac80fc65f6a8779f0ca29223
config_hash: 06186eb40e0058a2a87ac251fc07415d
19 changes: 19 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,24 @@
# Changelog

## 0.75.0 (2026-07-08)

Full Changelog: [v0.74.0...v0.75.0](https://github.com/kernel/kernel-go-sdk/compare/v0.74.0...v0.75.0)

### Features

* Auto-flush pools when a managed auth profile re-authenticates ([9b65633](https://github.com/kernel/kernel-go-sdk/commit/9b656333bbab210f4deaf9e8247b2540571693ca))
* Document env var redaction on deployment and app reads ([1a17cf5](https://github.com/kernel/kernel-go-sdk/commit/1a17cf51617d671b676ec713409a05ee002b086b))
* Expose resolved profile_id and extension_ids on browser pool reads ([3931759](https://github.com/kernel/kernel-go-sdk/commit/393175979cfbd763a610d7d87601a8386feba2ad))
* Reject API key self-deletion ([0fe2a82](https://github.com/kernel/kernel-go-sdk/commit/0fe2a8206644361bcdb439f0903b8658a85c5691))
* Revert "Store and return a sha256 checksum for uploaded extensions (#… ([763d2cd](https://github.com/kernel/kernel-go-sdk/commit/763d2cd76858214f0f4e34cabc2c744a0d44a983))
* Store and return a sha256 checksum for uploaded extensions ([92806ce](https://github.com/kernel/kernel-go-sdk/commit/92806ce19504a6c6bbb8a4301bb2a667843a3b24))
* Store and return a sha256 checksum for uploaded extensions (reland) ([24fea5b](https://github.com/kernel/kernel-go-sdk/commit/24fea5b4a661c7970f7f773261a2d7834042c942))


### Documentation

* **api:** clarify reuse/discard_all_idle pool config staleness ([c2a231d](https://github.com/kernel/kernel-go-sdk/commit/c2a231d2184874248ce5554c61505376e644d6d0))

## 0.74.0 (2026-07-06)

Full Changelog: [v0.73.0...v0.74.0](https://github.com/kernel/kernel-go-sdk/compare/v0.73.0...v0.74.0)
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ Or to pin the version:
<!-- x-release-please-start-version -->

```sh
go get -u 'github.com/kernel/kernel-go-sdk@v0.74.0'
go get -u 'github.com/kernel/kernel-go-sdk@v0.75.0'
```

<!-- x-release-please-end -->
Expand Down
3 changes: 2 additions & 1 deletion apikey.go
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,8 @@ func (r *APIKeyService) ListAutoPaging(ctx context.Context, query APIKeyListPara
return pagination.NewOffsetPaginationAutoPager(r.List(ctx, query, opts...))
}

// Delete an API key.
// Delete an API key. A key cannot delete itself; use a different key to delete
// this one.
func (r *APIKeyService) Delete(ctx context.Context, id string, opts ...option.RequestOption) (err error) {
opts = slices.Concat(r.Options, opts)
opts = append([]option.RequestOption{option.WithHeader("Accept", "*/*")}, opts...)
Expand Down
4 changes: 3 additions & 1 deletion app.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,9 @@ type AppListResponse struct {
AppName string `json:"app_name" api:"required"`
// Deployment ID
Deployment string `json:"deployment" api:"required"`
// Environment variables configured for this app version
// Environment variables configured for this app version. Values are redacted for
// API key, OAuth, and managed-auth callers, which receive every key with an empty
// string value. Only dashboard sessions receive the actual values.
EnvVars map[string]string `json:"env_vars" api:"required"`
// Deployment region code
Region constant.AwsUsEast1a `json:"region" default:"aws.us-east-1a"`
Expand Down
138 changes: 83 additions & 55 deletions browserpool.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,9 @@ func (r *BrowserPoolService) Get(ctx context.Context, idOrName string, opts ...o

// Updates the configuration used to create browsers in the pool. As with creation,
// save_changes on the pool profile is ignored (not rejected); pooled browsers
// never persist changes back to the profile.
// never persist changes back to the profile. To clear the profile reference, send
// `profile: { "id": "" }`. Clearing the profile also disables
// `refresh_on_profile_update`.
func (r *BrowserPoolService) Update(ctx context.Context, idOrName string, body BrowserPoolUpdateParams, opts ...option.RequestOption) (res *BrowserPool, err error) {
opts = slices.Concat(r.Options, opts)
if idOrName == "" {
Expand Down Expand Up @@ -169,16 +171,28 @@ type BrowserPool struct {
BrowserPoolConfig BrowserPoolBrowserPoolConfig `json:"browser_pool_config" api:"required"`
// Timestamp when the browser pool was created
CreatedAt time.Time `json:"created_at" api:"required" format:"date-time"`
// Resolved extension IDs attached to the pool, in configured load order. Empty
// when no extensions are attached. Authoritative for programmatic consumers; the
// extensions inside `browser_pool_config` reflect the configured selector (echoed
// as sent on create).
ExtensionIDs []string `json:"extension_ids" api:"required"`
// Browser pool name, if set
Name string `json:"name"`
// Resolved profile ID the pool is attached to. Omitted when no profile is
// attached. Authoritative for programmatic consumers; the profile inside
// `browser_pool_config` reflects the configured selector (echoed as sent on
// create).
ProfileID string `json:"profile_id"`
// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
JSON struct {
ID respjson.Field
AcquiredCount respjson.Field
AvailableCount respjson.Field
BrowserPoolConfig respjson.Field
CreatedAt respjson.Field
ExtensionIDs respjson.Field
Name respjson.Field
ProfileID respjson.Field
ExtraFields map[string]respjson.Field
raw string
} `json:"-"`
Expand Down Expand Up @@ -214,16 +228,19 @@ type BrowserPoolBrowserPoolConfig struct {
KioskMode bool `json:"kiosk_mode"`
// Optional name for the browser pool. Must be unique within the project.
Name string `json:"name"`
// Profile selection for browsers in a pool. Provide either id or name. The
// matching profile is loaded into every browser in the pool. Profiles must be
// created beforehand. Unlike single browser sessions, pools load the profile
// read-only and never persist changes back to it, so save_changes is omitted here.
// Any save_changes value sent on a pool profile is silently ignored rather than
// rejected, so callers reusing a single-session profile object will not error.
// Profile configuration for browsers in a pool. Provide either id or name.
// Profiles must be created beforehand. Unlike single browser sessions, pools load
// the profile read-only and never persist changes back to it, so save_changes is
// omitted here. Any save_changes value sent on a pool profile is silently ignored
// rather than rejected.
Profile BrowserPoolBrowserPoolConfigProfile `json:"profile"`
// Optional proxy to associate to the browser session. Must reference a proxy in
// the same project as the browser session.
ProxyID string `json:"proxy_id"`
// When true, flush idle browsers when the profile the pool uses is updated, so
// pool browsers pick up the latest profile data. Requires a profile to be set on
// the pool.
RefreshOnProfileUpdate bool `json:"refresh_on_profile_update"`
// Optional URL to navigate to when a new browser is warmed into the pool.
// Best-effort: failures to navigate do not fail pool fill. Only applied to
// newly-warmed browsers; browsers reused via release/acquire keep whatever URL the
Expand Down Expand Up @@ -251,21 +268,22 @@ type BrowserPoolBrowserPoolConfig struct {
Viewport shared.BrowserViewport `json:"viewport"`
// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
JSON struct {
Size respjson.Field
ChromePolicy respjson.Field
Extensions respjson.Field
FillRatePerMinute respjson.Field
Headless respjson.Field
KioskMode respjson.Field
Name respjson.Field
Profile respjson.Field
ProxyID respjson.Field
StartURL respjson.Field
Stealth respjson.Field
TimeoutSeconds respjson.Field
Viewport respjson.Field
ExtraFields map[string]respjson.Field
raw string
Size respjson.Field
ChromePolicy respjson.Field
Extensions respjson.Field
FillRatePerMinute respjson.Field
Headless respjson.Field
KioskMode respjson.Field
Name respjson.Field
Profile respjson.Field
ProxyID respjson.Field
RefreshOnProfileUpdate respjson.Field
StartURL respjson.Field
Stealth respjson.Field
TimeoutSeconds respjson.Field
Viewport respjson.Field
ExtraFields map[string]respjson.Field
raw string
} `json:"-"`
}

Expand All @@ -275,12 +293,11 @@ func (r *BrowserPoolBrowserPoolConfig) UnmarshalJSON(data []byte) error {
return apijson.UnmarshalRoot(data, r)
}

// Profile selection for browsers in a pool. Provide either id or name. The
// matching profile is loaded into every browser in the pool. Profiles must be
// created beforehand. Unlike single browser sessions, pools load the profile
// read-only and never persist changes back to it, so save_changes is omitted here.
// Any save_changes value sent on a pool profile is silently ignored rather than
// rejected, so callers reusing a single-session profile object will not error.
// Profile configuration for browsers in a pool. Provide either id or name.
// Profiles must be created beforehand. Unlike single browser sessions, pools load
// the profile read-only and never persist changes back to it, so save_changes is
// omitted here. Any save_changes value sent on a pool profile is silently ignored
// rather than rejected.
type BrowserPoolBrowserPoolConfigProfile struct {
// Profile ID to load for browsers in this pool
ID string `json:"id"`
Expand Down Expand Up @@ -421,6 +438,10 @@ type BrowserPoolNewParams struct {
// Optional proxy to associate to the browser session. Must reference a proxy in
// the same project as the browser session.
ProxyID param.Opt[string] `json:"proxy_id,omitzero"`
// When true, flush idle browsers when the profile the pool uses is updated, so
// pool browsers pick up the latest profile data. Requires a profile to be set on
// the pool.
RefreshOnProfileUpdate param.Opt[bool] `json:"refresh_on_profile_update,omitzero"`
// Optional URL to navigate to when a new browser is warmed into the pool.
// Best-effort: failures to navigate do not fail pool fill. Only applied to
// newly-warmed browsers; browsers reused via release/acquire keep whatever URL the
Expand All @@ -440,12 +461,11 @@ type BrowserPoolNewParams struct {
ChromePolicy map[string]any `json:"chrome_policy,omitzero"`
// List of browser extensions to load into the session. Provide each by id or name.
Extensions []shared.BrowserExtensionParam `json:"extensions,omitzero"`
// Profile selection for browsers in a pool. Provide either id or name. The
// matching profile is loaded into every browser in the pool. Profiles must be
// created beforehand. Unlike single browser sessions, pools load the profile
// read-only and never persist changes back to it, so save_changes is omitted here.
// Any save_changes value sent on a pool profile is silently ignored rather than
// rejected, so callers reusing a single-session profile object will not error.
// Profile configuration for browsers in a pool. Provide either id or name.
// Profiles must be created beforehand. Unlike single browser sessions, pools load
// the profile read-only and never persist changes back to it, so save_changes is
// omitted here. Any save_changes value sent on a pool profile is silently ignored
// rather than rejected.
Profile BrowserPoolNewParamsProfile `json:"profile,omitzero"`
// Initial browser window size in pixels with optional refresh rate. If omitted,
// image defaults apply (1920x1080@25). For GPU images, the default is
Expand All @@ -471,12 +491,11 @@ func (r *BrowserPoolNewParams) UnmarshalJSON(data []byte) error {
return apijson.UnmarshalRoot(data, r)
}

// Profile selection for browsers in a pool. Provide either id or name. The
// matching profile is loaded into every browser in the pool. Profiles must be
// created beforehand. Unlike single browser sessions, pools load the profile
// read-only and never persist changes back to it, so save_changes is omitted here.
// Any save_changes value sent on a pool profile is silently ignored rather than
// rejected, so callers reusing a single-session profile object will not error.
// Profile configuration for browsers in a pool. Provide either id or name.
// Profiles must be created beforehand. Unlike single browser sessions, pools load
// the profile read-only and never persist changes back to it, so save_changes is
// omitted here. Any save_changes value sent on a pool profile is silently ignored
// rather than rejected.
type BrowserPoolNewParamsProfile struct {
// Profile ID to load for browsers in this pool
ID param.Opt[string] `json:"id,omitzero"`
Expand All @@ -495,8 +514,12 @@ func (r *BrowserPoolNewParamsProfile) UnmarshalJSON(data []byte) error {
}

type BrowserPoolUpdateParams struct {
// Whether to discard all idle browsers and rebuild the pool immediately. Defaults
// to false.
// Whether to discard all idle browsers and rebuild them immediately with the new
// configuration. Defaults to false. Only browsers that are idle when the update
// runs are rebuilt. A browser that is in use during the update keeps its original
// configuration, and if it is later released with `reuse: true` it returns to the
// pool with that stale configuration until it is discarded (by this flag on a
// later update, or by flushing the pool).
DiscardAllIdle param.Opt[bool] `json:"discard_all_idle,omitzero"`
// Percentage of the pool to fill per minute. Defaults to 10. The cap is 25 for
// most organizations but can be raised per-organization, so only the lower bound
Expand All @@ -512,6 +535,10 @@ type BrowserPoolUpdateParams struct {
// Optional proxy to associate to the browser session. Must reference a proxy in
// the same project as the browser session.
ProxyID param.Opt[string] `json:"proxy_id,omitzero"`
// When true, flush idle browsers when the profile the pool uses is updated, so
// pool browsers pick up the latest profile data. Requires a profile to be set on
// the pool.
RefreshOnProfileUpdate param.Opt[bool] `json:"refresh_on_profile_update,omitzero"`
// Number of browsers to maintain in the pool. The maximum size is determined by
// your organization's pooled sessions limit (the sum of all pool sizes cannot
// exceed your limit).
Expand All @@ -535,12 +562,11 @@ type BrowserPoolUpdateParams struct {
ChromePolicy map[string]any `json:"chrome_policy,omitzero"`
// List of browser extensions to load into the session. Provide each by id or name.
Extensions []shared.BrowserExtensionParam `json:"extensions,omitzero"`
// Profile selection for browsers in a pool. Provide either id or name. The
// matching profile is loaded into every browser in the pool. Profiles must be
// created beforehand. Unlike single browser sessions, pools load the profile
// read-only and never persist changes back to it, so save_changes is omitted here.
// Any save_changes value sent on a pool profile is silently ignored rather than
// rejected, so callers reusing a single-session profile object will not error.
// Profile configuration for browsers in a pool. Provide either id or name.
// Profiles must be created beforehand. Unlike single browser sessions, pools load
// the profile read-only and never persist changes back to it, so save_changes is
// omitted here. Any save_changes value sent on a pool profile is silently ignored
// rather than rejected.
Profile BrowserPoolUpdateParamsProfile `json:"profile,omitzero"`
// Initial browser window size in pixels with optional refresh rate. If omitted,
// image defaults apply (1920x1080@25). For GPU images, the default is
Expand All @@ -566,12 +592,11 @@ func (r *BrowserPoolUpdateParams) UnmarshalJSON(data []byte) error {
return apijson.UnmarshalRoot(data, r)
}

// Profile selection for browsers in a pool. Provide either id or name. The
// matching profile is loaded into every browser in the pool. Profiles must be
// created beforehand. Unlike single browser sessions, pools load the profile
// read-only and never persist changes back to it, so save_changes is omitted here.
// Any save_changes value sent on a pool profile is silently ignored rather than
// rejected, so callers reusing a single-session profile object will not error.
// Profile configuration for browsers in a pool. Provide either id or name.
// Profiles must be created beforehand. Unlike single browser sessions, pools load
// the profile read-only and never persist changes back to it, so save_changes is
// omitted here. Any save_changes value sent on a pool profile is silently ignored
// rather than rejected.
type BrowserPoolUpdateParamsProfile struct {
// Profile ID to load for browsers in this pool
ID param.Opt[string] `json:"id,omitzero"`
Expand Down Expand Up @@ -655,7 +680,10 @@ type BrowserPoolReleaseParams struct {
// Browser session ID to release back to the pool
SessionID string `json:"session_id" api:"required"`
// Whether to reuse the browser instance or destroy it and create a new one.
// Defaults to true.
// Defaults to true. A reused browser keeps the configuration it was created with,
// so it does not pick up pool configuration changes made while it was in use.
// Release with `reuse: false`, or flush the pool afterward, to rebuild it with the
// current configuration.
Reuse param.Opt[bool] `json:"reuse,omitzero"`
paramObj
}
Expand Down
20 changes: 11 additions & 9 deletions browserpool_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,10 +44,11 @@ func TestBrowserPoolNewWithOptionalParams(t *testing.T) {
ID: kernel.String("id"),
Name: kernel.String("name"),
},
ProxyID: kernel.String("proxy_id"),
StartURL: kernel.String("https://example.com"),
Stealth: kernel.Bool(true),
TimeoutSeconds: kernel.Int(10),
ProxyID: kernel.String("proxy_id"),
RefreshOnProfileUpdate: kernel.Bool(true),
StartURL: kernel.String("https://example.com"),
Stealth: kernel.Bool(true),
TimeoutSeconds: kernel.Int(10),
Viewport: shared.BrowserViewportParam{
Height: 800,
Width: 1280,
Expand Down Expand Up @@ -119,11 +120,12 @@ func TestBrowserPoolUpdateWithOptionalParams(t *testing.T) {
ID: kernel.String("id"),
Name: kernel.String("name"),
},
ProxyID: kernel.String("proxy_id"),
Size: kernel.Int(10),
StartURL: kernel.String("https://example.com"),
Stealth: kernel.Bool(true),
TimeoutSeconds: kernel.Int(10),
ProxyID: kernel.String("proxy_id"),
RefreshOnProfileUpdate: kernel.Bool(true),
Size: kernel.Int(10),
StartURL: kernel.String("https://example.com"),
Stealth: kernel.Bool(true),
TimeoutSeconds: kernel.Int(10),
Viewport: shared.BrowserViewportParam{
Height: 800,
Width: 1280,
Expand Down
Loading
Loading