diff --git a/.release-please-manifest.json b/.release-please-manifest.json
index 2969a75..820b5c1 100644
--- a/.release-please-manifest.json
+++ b/.release-please-manifest.json
@@ -1,3 +1,3 @@
{
- ".": "0.111.0"
+ ".": "0.112.0"
}
\ No newline at end of file
diff --git a/.stats.yml b/.stats.yml
index e8ac4eb..ec91ee3 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1 +1 @@
-configured_endpoints: 169
+configured_endpoints: 172
diff --git a/CHANGELOG.md b/CHANGELOG.md
index c3ee939..4517336 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,18 @@
# Changelog
+## [0.112.0](https://github.com/kernel/kernel-go-sdk/compare/v0.111.0...v0.112.0) (2026-09-24)
+
+
+### Features
+
+* Add profiles to browser pool acquire ([b50814f](https://github.com/kernel/kernel-go-sdk/commit/b50814fd0cd8cff8a37e56b48142eef0b3653b7c))
+* Correct monitor_disconnected description on computed state ([0584ea1](https://github.com/kernel/kernel-go-sdk/commit/0584ea1d2238bfb06f1995ef4cab305917941efa))
+* Expose Search rollout access in org entitlements ([8e055e1](https://github.com/kernel/kernel-go-sdk/commit/8e055e16e1db7872b2bb298901c760aba435030d))
+* Filter archived telemetry events by type ([a9ee57c](https://github.com/kernel/kernel-go-sdk/commit/a9ee57caab330fac08e26e24896274baf2e64b43))
+* Proxy custom WebMCP tools in the control plane ([47c1310](https://github.com/kernel/kernel-go-sdk/commit/47c13103242727ad8633062d359aee2ad7d6cb32))
+* Publish iframe and worker browser target types ([1ef7b7c](https://github.com/kernel/kernel-go-sdk/commit/1ef7b7c34dc3b987d6c515c82ea399c424f0c6e6))
+* Route browser destinations through selected proxies ([ffc38db](https://github.com/kernel/kernel-go-sdk/commit/ffc38db98feff227e904bd3c84e11cc715c010a8))
+
## [0.111.0](https://github.com/kernel/kernel-go-sdk/compare/v0.110.0...v0.111.0) (2026-09-22)
diff --git a/README.md b/README.md
index ea27be0..26ea6c9 100644
--- a/README.md
+++ b/README.md
@@ -28,7 +28,7 @@ Or to pin the version:
```sh
-go get -u 'github.com/kernel/kernel-go-sdk@v0.111.0'
+go get -u 'github.com/kernel/kernel-go-sdk@v0.112.0'
```
diff --git a/api.md b/api.md
index aef4897..6c87a60 100644
--- a/api.md
+++ b/api.md
@@ -333,17 +333,37 @@ Params Types:
Response Types:
+- kernel.CustomToolSource
- kernel.InvocationResult
- kernel.Tool
- kernel.ToolAnnotations
- kernel.ToolFrame
+- kernel.ToolMetadata
- kernel.ToolSource
- kernel.ToolsResponse
Methods:
- client.Browsers.Webmcp.InvokeTool(ctx context.Context, idOrName string, body kernel.BrowserWebmcpInvokeToolParams) (\*kernel.InvocationResult, error)
-- client.Browsers.Webmcp.ListTools(ctx context.Context, idOrName string) (\*kernel.ToolsResponse, error)
+- client.Browsers.Webmcp.ListTools(ctx context.Context, idOrName string, query kernel.BrowserWebmcpListToolsParams) (\*kernel.ToolsResponse, error)
+
+### CustomTools
+
+Params Types:
+
+- kernel.AddRequestParam
+
+Response Types:
+
+- kernel.CustomToolsResponse
+- kernel.Definition
+- kernel.Match
+
+Methods:
+
+- client.Browsers.Webmcp.CustomTools.List(ctx context.Context, idOrName string) (\*kernel.CustomToolsResponse, error)
+- client.Browsers.Webmcp.CustomTools.Add(ctx context.Context, idOrName string, body kernel.BrowserWebmcpCustomToolAddParams) (\*kernel.CustomToolsResponse, error)
+- client.Browsers.Webmcp.CustomTools.Remove(ctx context.Context, id string, body kernel.BrowserWebmcpCustomToolRemoveParams) error
# Profiles
diff --git a/browser.go b/browser.go
index 341f0e6..0aff2de 100644
--- a/browser.go
+++ b/browser.go
@@ -237,9 +237,25 @@ type BrowserNetworkConfig struct {
// destinations. Not related to a proxy's bypass_hosts, which selects between
// upstream-proxy and Kernel-managed direct egress and cannot reach into a VPN.
PrivateHosts []string `json:"private_hosts"`
+ // Per-destination proxy routes for a browser session. After setup, a destination
+ // hostname is matched against every route's hosts, regardless of port; route order
+ // does not matter. An exact hostname beats a wildcard, and a longer wildcard
+ // suffix beats a shorter one (for a.b.example.com: "a.b.example.com" >
+ // "_.b.example.com" > "_.example.com"). A host pattern may appear in only one
+ // route. "\*.example.com" matches subdomains only, not example.com. A matched
+ // request selects the route's proxy instead of the session's top-level proxy
+ // (including mode: direct); the route proxy's own bypass_hosts still apply. If the
+ // route proxy becomes unavailable, matched requests fail closed without falling
+ // back. Requests that match no route use the session's default egress from the
+ // top-level proxy field (or the browser default when proxy is omitted: stealth
+ // proxy or direct egress). Routes take effect once the session is created;
+ // start_url and other traffic during browser setup use the top-level proxy.
+ // Setting routes requires proxy v3. Not supported on browser pools.
+ ProxyRoutes []BrowserNetworkConfigProxyRoute `json:"proxy_routes"`
// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
JSON struct {
PrivateHosts respjson.Field
+ ProxyRoutes respjson.Field
ExtraFields map[string]respjson.Field
raw string
} `json:"-"`
@@ -260,6 +276,48 @@ func (r BrowserNetworkConfig) ToParam() BrowserNetworkConfigParam {
return param.Override[BrowserNetworkConfigParam](json.RawMessage(r.RawJSON()))
}
+type BrowserNetworkConfigProxyRoute struct {
+ // Exact hostnames or leading \*. wildcard patterns (subdomains only); patterns
+ // cannot include ports, and matching ignores the destination port. Hosts not
+ // matched by any route use the session's top-level proxy (or the browser default
+ // when proxy is omitted).
+ Hosts []string `json:"hosts" api:"required"`
+ // Select an active non-direct proxy by ID or name. Responses always use ID.
+ Proxy BrowserNetworkConfigProxyRouteProxy `json:"proxy" api:"required"`
+ // JSON contains metadata for fields, check presence with [respjson.Field.Valid].
+ JSON struct {
+ Hosts respjson.Field
+ Proxy respjson.Field
+ ExtraFields map[string]respjson.Field
+ raw string
+ } `json:"-"`
+}
+
+// Returns the unmodified JSON received from the API
+func (r BrowserNetworkConfigProxyRoute) RawJSON() string { return r.JSON.raw }
+func (r *BrowserNetworkConfigProxyRoute) UnmarshalJSON(data []byte) error {
+ return apijson.UnmarshalRoot(data, r)
+}
+
+// Select an active non-direct proxy by ID or name. Responses always use ID.
+type BrowserNetworkConfigProxyRouteProxy struct {
+ ID string `json:"id"`
+ Name string `json:"name"`
+ // JSON contains metadata for fields, check presence with [respjson.Field.Valid].
+ JSON struct {
+ ID respjson.Field
+ Name respjson.Field
+ ExtraFields map[string]respjson.Field
+ raw string
+ } `json:"-"`
+}
+
+// Returns the unmodified JSON received from the API
+func (r BrowserNetworkConfigProxyRouteProxy) RawJSON() string { return r.JSON.raw }
+func (r *BrowserNetworkConfigProxyRouteProxy) UnmarshalJSON(data []byte) error {
+ return apijson.UnmarshalRoot(data, r)
+}
+
// Network configuration for a browser session or browser pool.
type BrowserNetworkConfigParam struct {
// Destinations the browser reaches directly through the session's own network
@@ -285,6 +343,21 @@ type BrowserNetworkConfigParam struct {
// destinations. Not related to a proxy's bypass_hosts, which selects between
// upstream-proxy and Kernel-managed direct egress and cannot reach into a VPN.
PrivateHosts []string `json:"private_hosts,omitzero"`
+ // Per-destination proxy routes for a browser session. After setup, a destination
+ // hostname is matched against every route's hosts, regardless of port; route order
+ // does not matter. An exact hostname beats a wildcard, and a longer wildcard
+ // suffix beats a shorter one (for a.b.example.com: "a.b.example.com" >
+ // "_.b.example.com" > "_.example.com"). A host pattern may appear in only one
+ // route. "\*.example.com" matches subdomains only, not example.com. A matched
+ // request selects the route's proxy instead of the session's top-level proxy
+ // (including mode: direct); the route proxy's own bypass_hosts still apply. If the
+ // route proxy becomes unavailable, matched requests fail closed without falling
+ // back. Requests that match no route use the session's default egress from the
+ // top-level proxy field (or the browser default when proxy is omitted: stealth
+ // proxy or direct egress). Routes take effect once the session is created;
+ // start_url and other traffic during browser setup use the top-level proxy.
+ // Setting routes requires proxy v3. Not supported on browser pools.
+ ProxyRoutes []BrowserNetworkConfigProxyRouteParam `json:"proxy_routes,omitzero"`
paramObj
}
@@ -296,6 +369,41 @@ func (r *BrowserNetworkConfigParam) UnmarshalJSON(data []byte) error {
return apijson.UnmarshalRoot(data, r)
}
+// The properties Hosts, Proxy are required.
+type BrowserNetworkConfigProxyRouteParam struct {
+ // Exact hostnames or leading \*. wildcard patterns (subdomains only); patterns
+ // cannot include ports, and matching ignores the destination port. Hosts not
+ // matched by any route use the session's top-level proxy (or the browser default
+ // when proxy is omitted).
+ Hosts []string `json:"hosts,omitzero" api:"required"`
+ // Select an active non-direct proxy by ID or name. Responses always use ID.
+ Proxy BrowserNetworkConfigProxyRouteProxyParam `json:"proxy,omitzero" api:"required"`
+ paramObj
+}
+
+func (r BrowserNetworkConfigProxyRouteParam) MarshalJSON() (data []byte, err error) {
+ type shadow BrowserNetworkConfigProxyRouteParam
+ return param.MarshalObject(r, (*shadow)(&r))
+}
+func (r *BrowserNetworkConfigProxyRouteParam) UnmarshalJSON(data []byte) error {
+ return apijson.UnmarshalRoot(data, r)
+}
+
+// Select an active non-direct proxy by ID or name. Responses always use ID.
+type BrowserNetworkConfigProxyRouteProxyParam struct {
+ ID param.Opt[string] `json:"id,omitzero"`
+ Name param.Opt[string] `json:"name,omitzero"`
+ paramObj
+}
+
+func (r BrowserNetworkConfigProxyRouteProxyParam) MarshalJSON() (data []byte, err error) {
+ type shadow BrowserNetworkConfigProxyRouteProxyParam
+ return param.MarshalObject(r, (*shadow)(&r))
+}
+func (r *BrowserNetworkConfigProxyRouteProxyParam) UnmarshalJSON(data []byte) error {
+ return apijson.UnmarshalRoot(data, r)
+}
+
// Browser pool this session was acquired from, if any.
type BrowserPoolRef struct {
// Browser pool ID
diff --git a/browser_test.go b/browser_test.go
index f69f671..a826fcd 100644
--- a/browser_test.go
+++ b/browser_test.go
@@ -45,6 +45,13 @@ func TestBrowserNewWithOptionalParams(t *testing.T) {
Name: kernel.String("checkout-flow-1"),
Network: kernel.BrowserNetworkConfigParam{
PrivateHosts: []string{"*.example.ts.net", "100.64.0.0/10"},
+ ProxyRoutes: []kernel.BrowserNetworkConfigProxyRouteParam{{
+ Hosts: []string{"string"},
+ Proxy: kernel.BrowserNetworkConfigProxyRouteProxyParam{
+ ID: kernel.String("x"),
+ Name: kernel.String("x"),
+ },
+ }},
},
Profile: shared.BrowserProfileParam{
ID: kernel.String("id"),
diff --git a/browserpool.go b/browserpool.go
index e3352dd..88212f1 100644
--- a/browserpool.go
+++ b/browserpool.go
@@ -994,6 +994,10 @@ type BrowserPoolAcquireParams struct {
// is reset to the pool's baseline, so the override does not carry over to the next
// lease.
Telemetry BrowserPoolAcquireParamsTelemetry `json:"telemetry,omitzero"`
+ // Profile selection for the browser session. Provide either id or name. If
+ // specified, the matching profile will be loaded into the browser session.
+ // Profiles must be created beforehand.
+ Profile shared.BrowserProfileParam `json:"profile,omitzero"`
// Optional user-defined key-value tags for the acquired browser session, used to
// find and group sessions later. Applies to this lease only and are cleared when
// the browser is released back to the pool. Up to 50 pairs.
@@ -1112,7 +1116,8 @@ type BrowserPoolReleaseParams struct {
// 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.
+ // current configuration. Browsers loaded with an acquire-time profile are always
+ // destroyed and replaced, even when reuse is true.
Reuse param.Opt[bool] `json:"reuse,omitzero"`
paramObj
}
diff --git a/browserpool_test.go b/browserpool_test.go
index 1be6e77..96ba15f 100644
--- a/browserpool_test.go
+++ b/browserpool_test.go
@@ -42,6 +42,13 @@ func TestBrowserPoolNewWithOptionalParams(t *testing.T) {
Name: kernel.String("my-pool"),
Network: kernel.BrowserNetworkConfigParam{
PrivateHosts: []string{"*.example.ts.net", "100.64.0.0/10"},
+ ProxyRoutes: []kernel.BrowserNetworkConfigProxyRouteParam{{
+ Hosts: []string{"string"},
+ Proxy: kernel.BrowserNetworkConfigProxyRouteProxyParam{
+ ID: kernel.String("x"),
+ Name: kernel.String("x"),
+ },
+ }},
},
Profile: kernel.BrowserPoolNewParamsProfile{
ID: kernel.String("id"),
@@ -169,6 +176,13 @@ func TestBrowserPoolUpdateWithOptionalParams(t *testing.T) {
Name: kernel.String("my-pool"),
Network: kernel.BrowserNetworkConfigParam{
PrivateHosts: []string{"*.example.ts.net", "100.64.0.0/10"},
+ ProxyRoutes: []kernel.BrowserNetworkConfigProxyRouteParam{{
+ Hosts: []string{"string"},
+ Proxy: kernel.BrowserNetworkConfigProxyRouteProxyParam{
+ ID: kernel.String("x"),
+ Name: kernel.String("x"),
+ },
+ }},
},
Profile: kernel.BrowserPoolUpdateParamsProfile{
ID: kernel.String("id"),
@@ -320,7 +334,12 @@ func TestBrowserPoolAcquireWithOptionalParams(t *testing.T) {
kernel.BrowserPoolAcquireParams{
AcquireTimeoutSeconds: kernel.Int(0),
Name: kernel.String("checkout-flow-1"),
- StartURL: kernel.String("https://example.com"),
+ Profile: shared.BrowserProfileParam{
+ ID: kernel.String("id"),
+ Name: kernel.String("name"),
+ SaveChanges: kernel.Bool(true),
+ },
+ StartURL: kernel.String("https://example.com"),
Tags: kernel.Tags{
"team": "backend",
"env": "staging",
diff --git a/browsertelemetry.go b/browsertelemetry.go
index 5e53597..54d9cce 100644
--- a/browsertelemetry.go
+++ b/browsertelemetry.go
@@ -46,8 +46,9 @@ func NewBrowserTelemetryService(opts ...option.RequestOption) (r BrowserTelemetr
// Reads a page of telemetry events for the browser session. To page through
// results, pass the X-Next-Offset value from the previous response as offset and
-// repeat while X-Has-More is true. Returns an empty list when telemetry data is
-// unavailable.
+// repeat while X-Has-More is true. The category and type filters apply within each
+// page, so a filtered page may be empty while X-Has-More is true. Returns an empty
+// list when telemetry data is unavailable.
func (r *BrowserTelemetryService) Events(ctx context.Context, idOrName string, query BrowserTelemetryEventsParams, opts ...option.RequestOption) (res *pagination.OffsetPagination[BrowserTelemetryEventsResponse], err error) {
var raw *http.Response
opts = slices.Concat(r.Options, opts)
@@ -71,8 +72,9 @@ func (r *BrowserTelemetryService) Events(ctx context.Context, idOrName string, q
// Reads a page of telemetry events for the browser session. To page through
// results, pass the X-Next-Offset value from the previous response as offset and
-// repeat while X-Has-More is true. Returns an empty list when telemetry data is
-// unavailable.
+// repeat while X-Has-More is true. The category and type filters apply within each
+// page, so a filtered page may be empty while X-Has-More is true. Returns an empty
+// list when telemetry data is unavailable.
func (r *BrowserTelemetryService) EventsAutoPaging(ctx context.Context, idOrName string, query BrowserTelemetryEventsParams, opts ...option.RequestOption) *pagination.OffsetPaginationAutoPager[BrowserTelemetryEventsResponse] {
return pagination.NewOffsetPaginationAutoPager(r.Events(ctx, idOrName, query, opts...))
}
@@ -3572,7 +3574,8 @@ type BrowserEventContext struct {
TargetID string `json:"target_id"`
// CDP target type of the page that produced the event.
//
- // Any of "page", "background_page", "service_worker", "shared_worker", "other".
+ // Any of "page", "iframe", "worker", "background_page", "service_worker",
+ // "shared_worker", "other".
TargetType BrowserEventContextTargetType `json:"target_type"`
// URL relevant to this event — page URL for navigation and page events, request
// URL for network events.
@@ -3602,6 +3605,8 @@ type BrowserEventContextTargetType string
const (
BrowserEventContextTargetTypePage BrowserEventContextTargetType = "page"
+ BrowserEventContextTargetTypeIframe BrowserEventContextTargetType = "iframe"
+ BrowserEventContextTargetTypeWorker BrowserEventContextTargetType = "worker"
BrowserEventContextTargetTypeBackgroundPage BrowserEventContextTargetType = "background_page"
BrowserEventContextTargetTypeServiceWorker BrowserEventContextTargetType = "service_worker"
BrowserEventContextTargetTypeSharedWorker BrowserEventContextTargetType = "shared_worker"
@@ -3945,8 +3950,12 @@ func (r *BrowserLiveViewDisconnectEventData) UnmarshalJSON(data []byte) error {
}
// The CDP connection to Chrome was lost. Telemetry events may be dropped until
-// monitor_reconnected arrives. Treat any in-progress computed state (network_idle,
-// page_layout_settled) as unreliable until then.
+// monitor_reconnected arrives. In-progress computed state is discarded rather than
+// paused, so computed events still pending for the current navigation
+// (network_idle, page_layout_settled, page_navigation_settled) never fire.
+// monitor_reconnected does not restore them. After reattachment a fresh state
+// machine starts, so computed events can resume before the next navigation and
+// carry empty navigation context until one occurs.
type BrowserMonitorDisconnectedEvent struct {
Category constant.Monitor `json:"category" default:"monitor"`
// Provenance metadata identifying which producer emitted the event.
@@ -4488,7 +4497,8 @@ type BrowserPageCrashedEventData struct {
TargetID string `json:"target_id" api:"required"`
// CDP target type of the page that produced the event.
//
- // Any of "page", "background_page", "service_worker", "shared_worker", "other".
+ // Any of "page", "iframe", "worker", "background_page", "service_worker",
+ // "shared_worker", "other".
TargetType string `json:"target_type" api:"required"`
// URL the page was on when its renderer process crashed.
URL string `json:"url" api:"required"`
@@ -4880,7 +4890,8 @@ type BrowserPageNavigationEventData struct {
TargetID string `json:"target_id"`
// CDP target type of the page that produced the event.
//
- // Any of "page", "background_page", "service_worker", "shared_worker", "other".
+ // Any of "page", "iframe", "worker", "background_page", "service_worker",
+ // "shared_worker", "other".
TargetType string `json:"target_type"`
// URL navigated to.
URL string `json:"url"`
@@ -4980,7 +4991,8 @@ type BrowserPageTabOpenedEventData struct {
TargetID string `json:"target_id"`
// CDP target type of the page that produced the event.
//
- // Any of "page", "background_page", "service_worker", "shared_worker", "other".
+ // Any of "page", "iframe", "worker", "background_page", "service_worker",
+ // "shared_worker", "other".
TargetType string `json:"target_type"`
// Initial page title of the new tab.
Title string `json:"title"`
@@ -5109,17 +5121,18 @@ func (r *BrowserProxyErrorEvent) UnmarshalJSON(data []byte) error {
type BrowserProxyErrorEventData struct {
// Proxy-layer error code: the X-Kernel-Proxy-Error response header value from a
// branded 5xx error page served by the metro egress host-proxy. Values mirror what
- // the proxy emits: destination_blocked, provider_blacklisted,
- // provider_unreachable, provider_rejected, origin_tls_timeout,
- // origin_response_incomplete, proxy_unavailable, restricted_route_unavailable,
- // upstream_timeout, upstream_dns_failure, upstream_connect_failed. A header value
- // the browser image does not recognize is reported as unknown, with the header
- // value in raw_code.
+ // the proxy emits: destination_blocked, destination_route_unavailable,
+ // provider_blacklisted, provider_unreachable, provider_rejected,
+ // origin_tls_timeout, origin_response_incomplete, proxy_unavailable,
+ // restricted_route_unavailable, upstream_timeout, upstream_dns_failure,
+ // upstream_connect_failed. A header value the browser image does not recognize is
+ // reported as unknown, with the header value in raw_code.
//
- // Any of "destination_blocked", "provider_blacklisted", "provider_unreachable",
- // "provider_rejected", "origin_tls_timeout", "origin_response_incomplete",
- // "proxy_unavailable", "restricted_route_unavailable", "upstream_timeout",
- // "upstream_dns_failure", "upstream_connect_failed", "unknown".
+ // Any of "destination_blocked", "destination_route_unavailable",
+ // "provider_blacklisted", "provider_unreachable", "provider_rejected",
+ // "origin_tls_timeout", "origin_response_incomplete", "proxy_unavailable",
+ // "restricted_route_unavailable", "upstream_timeout", "upstream_dns_failure",
+ // "upstream_connect_failed", "unknown".
Code string `json:"code" api:"required"`
// CDP request identifier matching the originating request.
RequestID string `json:"request_id" api:"required"`
@@ -6811,9 +6824,7 @@ type BrowserTelemetryEventsParams struct {
// Read direction. asc (default) reads oldest first, starting from since or the
// offset cursor. desc reads newest first: each request returns one page of up to
// limit records ending at the offset cursor (or until, or the newest archived
- // event); combining desc with since is rejected with a 400. In either direction
- // the category filter applies within the page, so a filtered page may be empty
- // while X-Has-More is true.
+ // event); combining desc with since is rejected with a 400.
Order param.Opt[string] `query:"order,omitzero" json:"-"`
// Start of the window: an RFC-3339 timestamp, or a duration like 5m meaning that
// long ago. Defaults to 5m. Ignored when offset is set.
@@ -6827,6 +6838,10 @@ type BrowserTelemetryEventsParams struct {
// Any of "console", "network", "page", "interaction", "control", "platform",
// "connection", "system", "screenshot", "captcha", "monitor".
Category []string `query:"category,omitzero" json:"-"`
+ // Restrict results to these event types, such as page_crashed or
+ // captcha_challenge_result. Repeat the parameter for multiple values. Combines
+ // with category: when both are set an event must match both.
+ Type []string `query:"type,omitzero" json:"-"`
paramObj
}
diff --git a/browsertelemetry_test.go b/browsertelemetry_test.go
index 1593b38..15c4797 100644
--- a/browsertelemetry_test.go
+++ b/browsertelemetry_test.go
@@ -35,6 +35,7 @@ func TestBrowserTelemetryEventsWithOptionalParams(t *testing.T) {
Offset: kernel.Int(0),
Order: kernel.String("order"),
Since: kernel.String("since"),
+ Type: []string{"string"},
Until: kernel.String("until"),
},
)
diff --git a/browserwebmcp.go b/browserwebmcp.go
index d1507d8..5cbdad1 100644
--- a/browserwebmcp.go
+++ b/browserwebmcp.go
@@ -7,9 +7,11 @@ import (
"errors"
"fmt"
"net/http"
+ "net/url"
"slices"
"github.com/kernel/kernel-go-sdk/internal/apijson"
+ "github.com/kernel/kernel-go-sdk/internal/apiquery"
shimjson "github.com/kernel/kernel-go-sdk/internal/encoding/json"
"github.com/kernel/kernel-go-sdk/internal/requestconfig"
"github.com/kernel/kernel-go-sdk/option"
@@ -27,6 +29,8 @@ import (
// the [NewBrowserWebmcpService] method instead.
type BrowserWebmcpService struct {
Options []option.RequestOption
+ // Discover and invoke native page tools across the browser instance.
+ CustomTools BrowserWebmcpCustomToolService
}
// NewBrowserWebmcpService generates a new service that applies the given options
@@ -35,6 +39,7 @@ type BrowserWebmcpService struct {
func NewBrowserWebmcpService(opts ...option.RequestOption) (r BrowserWebmcpService) {
r = BrowserWebmcpService{}
r.Options = opts
+ r.CustomTools = NewBrowserWebmcpCustomToolService(opts...)
return
}
@@ -45,7 +50,8 @@ func NewBrowserWebmcpService(opts ...option.RequestOption) (r BrowserWebmcpServi
// then submit through Playwright or computer interaction without invoking the tool
// again. If the tab or embedded frame disappears, or the request times out after
// invocation begins, the response reports outcome_unknown and the tool is not
-// retried.
+// retried. CDP-backed custom tool outputs above 240 KiB return an error rather
+// than a truncated result.
func (r *BrowserWebmcpService) InvokeTool(ctx context.Context, idOrName string, body BrowserWebmcpInvokeToolParams, opts ...option.RequestOption) (res *InvocationResult, err error) {
opts = slices.Concat(r.Options, opts)
if idOrName == "" {
@@ -57,21 +63,41 @@ func (r *BrowserWebmcpService) InvokeTool(ctx context.Context, idOrName string,
return res, err
}
-// Returns a snapshot of native WebMCP tools available across every open tab and
-// embedded frame in the browser. Each tool includes an opaque tool_ref for
-// invoking that exact live registration. Tools disappear when their document
-// closes or navigates away.
-func (r *BrowserWebmcpService) ListTools(ctx context.Context, idOrName string, opts ...option.RequestOption) (res *ToolsResponse, err error) {
+// Returns a snapshot of native and custom WebMCP tools available across every open
+// tab and embedded frame in the browser. Each tool includes an opaque tool_ref for
+// invoking that exact live registration, nested tool metadata, and source
+// information. Custom tools include their generated ID, namespace, and CDP
+// target_id in source. Tools disappear when their document closes or navigates
+// away. Use exclude_custom to return only page-provided tools.
+func (r *BrowserWebmcpService) ListTools(ctx context.Context, idOrName string, query BrowserWebmcpListToolsParams, opts ...option.RequestOption) (res *ToolsResponse, err error) {
opts = slices.Concat(r.Options, opts)
if idOrName == "" {
err = errors.New("missing required id_or_name parameter")
return nil, err
}
path := fmt.Sprintf("browsers/%s/webmcp/tools", idOrName)
- err = requestconfig.ExecuteNewRequest(ctx, http.MethodGet, path, nil, &res, opts...)
+ err = requestconfig.ExecuteNewRequest(ctx, http.MethodGet, path, query, &res, opts...)
return res, err
}
+type CustomToolSource struct {
+ ID string `json:"id" api:"required"`
+ Namespace string `json:"namespace" api:"required"`
+ // JSON contains metadata for fields, check presence with [respjson.Field.Valid].
+ JSON struct {
+ ID respjson.Field
+ Namespace respjson.Field
+ ExtraFields map[string]respjson.Field
+ raw string
+ } `json:"-"`
+}
+
+// Returns the unmodified JSON received from the API
+func (r CustomToolSource) RawJSON() string { return r.JSON.raw }
+func (r *CustomToolSource) UnmarshalJSON(data []byte) error {
+ return apijson.UnmarshalRoot(data, r)
+}
+
type InvocationResult struct {
InvocationID string `json:"invocation_id" api:"required"`
// awaiting_submission means a non-autosubmit declarative form was populated but
@@ -133,24 +159,21 @@ func (r *InvokeRequestParam) UnmarshalJSON(data []byte) error {
}
type Tool struct {
- Description string `json:"description" api:"required"`
- InputSchema map[string]any `json:"input_schema" api:"required"`
- Name string `json:"name" api:"required"`
- Source ToolSource `json:"source" api:"required"`
+ Source ToolSource `json:"source" api:"required"`
+ // Tool metadata follows the
+ // [MCP Tool definition](https://modelcontextprotocol.io/specification/2025-11-25/server/tools#tool)
+ // and the
+ // [WebMCP RegisteredTool definition](https://webmachinelearning.github.io/webmcp/#dictdef-registeredtool).
+ // outputSchema is optional for page and custom tools.
+ Tool ToolMetadata `json:"tool" api:"required"`
// Opaque reference for invoking this exact live registration. It becomes invalid
// when its document or browser process is replaced.
ToolRef string `json:"tool_ref" api:"required"`
- // Page-provided behavioral hints. These values are untrusted and are not enforced
- // by Kernel.
- Annotations ToolAnnotations `json:"annotations"`
// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
JSON struct {
- Description respjson.Field
- InputSchema respjson.Field
- Name respjson.Field
Source respjson.Field
+ Tool respjson.Field
ToolRef respjson.Field
- Annotations respjson.Field
ExtraFields map[string]respjson.Field
raw string
} `json:"-"`
@@ -162,21 +185,30 @@ func (r *Tool) UnmarshalJSON(data []byte) error {
return apijson.UnmarshalRoot(data, r)
}
-// Page-provided behavioral hints. These values are untrusted and are not enforced
-// by Kernel.
+// Tool-provided behavioral hints from the
+// [MCP tool specification](https://modelcontextprotocol.io/specification/2025-11-25/server/tools#tool)
+// and the
+// [WebMCP ToolAnnotations definition](https://webmachinelearning.github.io/webmcp/#dictdef-toolannotations).
+// These hints are untrusted and are not enforced by Kernel.
type ToolAnnotations struct {
- Autosubmit bool `json:"autosubmit" api:"required"`
- Consequential bool `json:"consequential" api:"required"`
- ReadOnly bool `json:"read_only" api:"required"`
- UntrustedContent bool `json:"untrusted_content" api:"required"`
+ Autosubmit bool `json:"autosubmit"`
+ ConsequentialHint bool `json:"consequentialHint"`
+ DestructiveHint bool `json:"destructiveHint"`
+ IdempotentHint bool `json:"idempotentHint"`
+ OpenWorldHint bool `json:"openWorldHint"`
+ ReadOnlyHint bool `json:"readOnlyHint"`
+ UntrustedContentHint bool `json:"untrustedContentHint"`
// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
JSON struct {
- Autosubmit respjson.Field
- Consequential respjson.Field
- ReadOnly respjson.Field
- UntrustedContent respjson.Field
- ExtraFields map[string]respjson.Field
- raw string
+ Autosubmit respjson.Field
+ ConsequentialHint respjson.Field
+ DestructiveHint respjson.Field
+ IdempotentHint respjson.Field
+ OpenWorldHint respjson.Field
+ ReadOnlyHint respjson.Field
+ UntrustedContentHint respjson.Field
+ ExtraFields map[string]respjson.Field
+ raw string
} `json:"-"`
}
@@ -207,6 +239,42 @@ func (r *ToolFrame) UnmarshalJSON(data []byte) error {
return apijson.UnmarshalRoot(data, r)
}
+// Tool metadata follows the
+// [MCP Tool definition](https://modelcontextprotocol.io/specification/2025-11-25/server/tools#tool)
+// and the
+// [WebMCP RegisteredTool definition](https://webmachinelearning.github.io/webmcp/#dictdef-registeredtool).
+// outputSchema is optional for page and custom tools.
+type ToolMetadata struct {
+ Description string `json:"description" api:"required"`
+ InputSchema map[string]any `json:"inputSchema" api:"required"`
+ Name string `json:"name" api:"required"`
+ // Tool-provided behavioral hints from the
+ // [MCP tool specification](https://modelcontextprotocol.io/specification/2025-11-25/server/tools#tool)
+ // and the
+ // [WebMCP ToolAnnotations definition](https://webmachinelearning.github.io/webmcp/#dictdef-toolannotations).
+ // These hints are untrusted and are not enforced by Kernel.
+ Annotations ToolAnnotations `json:"annotations"`
+ OutputSchema map[string]any `json:"outputSchema"`
+ Title string `json:"title"`
+ // JSON contains metadata for fields, check presence with [respjson.Field.Valid].
+ JSON struct {
+ Description respjson.Field
+ InputSchema respjson.Field
+ Name respjson.Field
+ Annotations respjson.Field
+ OutputSchema respjson.Field
+ Title respjson.Field
+ ExtraFields map[string]respjson.Field
+ raw string
+ } `json:"-"`
+}
+
+// Returns the unmodified JSON received from the API
+func (r ToolMetadata) RawJSON() string { return r.JSON.raw }
+func (r *ToolMetadata) UnmarshalJSON(data []byte) error {
+ return apijson.UnmarshalRoot(data, r)
+}
+
type ToolSource struct {
// Embedded frame that registered the tool, or null when the top-level page
// registered it.
@@ -220,7 +288,11 @@ type ToolSource struct {
TabID int64 `json:"tab_id" api:"required"`
// Monotonically increasing identifier for the browser window during the current
// browser process.
- WindowID int64 `json:"window_id" api:"required"`
+ WindowID int64 `json:"window_id" api:"required"`
+ Custom CustomToolSource `json:"custom"`
+ // CDP target ID for a custom tool's registration tab; omitted for page-provided
+ // tools.
+ TargetID string `json:"target_id"`
// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
JSON struct {
Frame respjson.Field
@@ -228,6 +300,8 @@ type ToolSource struct {
PageURL respjson.Field
TabID respjson.Field
WindowID respjson.Field
+ Custom respjson.Field
+ TargetID respjson.Field
ExtraFields map[string]respjson.Field
raw string
} `json:"-"`
@@ -266,3 +340,18 @@ func (r BrowserWebmcpInvokeToolParams) MarshalJSON() (data []byte, err error) {
func (r *BrowserWebmcpInvokeToolParams) UnmarshalJSON(data []byte) error {
return apijson.UnmarshalRoot(data, r)
}
+
+type BrowserWebmcpListToolsParams struct {
+ // Exclude custom tools when true.
+ ExcludeCustom param.Opt[bool] `query:"exclude_custom,omitzero" json:"-"`
+ paramObj
+}
+
+// URLQuery serializes [BrowserWebmcpListToolsParams]'s query parameters as
+// `url.Values`.
+func (r BrowserWebmcpListToolsParams) URLQuery() (v url.Values, err error) {
+ return apiquery.MarshalWithSettings(r, apiquery.QuerySettings{
+ ArrayFormat: apiquery.ArrayQueryFormatComma,
+ NestedFormat: apiquery.NestedQueryFormatBrackets,
+ })
+}
diff --git a/browserwebmcp_test.go b/browserwebmcp_test.go
index da4fad1..d57f3f2 100644
--- a/browserwebmcp_test.go
+++ b/browserwebmcp_test.go
@@ -48,7 +48,7 @@ func TestBrowserWebmcpInvokeToolWithOptionalParams(t *testing.T) {
}
}
-func TestBrowserWebmcpListTools(t *testing.T) {
+func TestBrowserWebmcpListToolsWithOptionalParams(t *testing.T) {
t.Skip("Mock server tests are disabled")
baseURL := "http://localhost:4010"
if envURL, ok := os.LookupEnv("TEST_API_BASE_URL"); ok {
@@ -61,7 +61,13 @@ func TestBrowserWebmcpListTools(t *testing.T) {
option.WithBaseURL(baseURL),
option.WithAPIKey("My API Key"),
)
- _, err := client.Browsers.Webmcp.ListTools(context.TODO(), "htzv5orfit78e1m2biiifpbv")
+ _, err := client.Browsers.Webmcp.ListTools(
+ context.TODO(),
+ "htzv5orfit78e1m2biiifpbv",
+ kernel.BrowserWebmcpListToolsParams{
+ ExcludeCustom: kernel.Bool(true),
+ },
+ )
if err != nil {
var apierr *kernel.Error
if errors.As(err, &apierr) {
diff --git a/browserwebmcpcustomtool.go b/browserwebmcpcustomtool.go
new file mode 100644
index 0000000..ceafcd4
--- /dev/null
+++ b/browserwebmcpcustomtool.go
@@ -0,0 +1,193 @@
+// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+package kernel
+
+import (
+ "context"
+ "errors"
+ "fmt"
+ "net/http"
+ "slices"
+
+ "github.com/kernel/kernel-go-sdk/internal/apijson"
+ shimjson "github.com/kernel/kernel-go-sdk/internal/encoding/json"
+ "github.com/kernel/kernel-go-sdk/internal/requestconfig"
+ "github.com/kernel/kernel-go-sdk/option"
+ "github.com/kernel/kernel-go-sdk/packages/param"
+ "github.com/kernel/kernel-go-sdk/packages/respjson"
+)
+
+// Discover and invoke native page tools across the browser instance.
+//
+// BrowserWebmcpCustomToolService contains methods and other services that help
+// with interacting with the kernel API.
+//
+// Note, unlike clients, this service does not read variables from the environment
+// automatically. You should not instantiate this service directly, and instead use
+// the [NewBrowserWebmcpCustomToolService] method instead.
+type BrowserWebmcpCustomToolService struct {
+ Options []option.RequestOption
+}
+
+// NewBrowserWebmcpCustomToolService generates a new service that applies the given
+// options to each request. These options are applied after the parent client's
+// options (if there is one), and before any request-specific options.
+func NewBrowserWebmcpCustomToolService(opts ...option.RequestOption) (r BrowserWebmcpCustomToolService) {
+ r = BrowserWebmcpCustomToolService{}
+ r.Options = opts
+ return
+}
+
+// Returns every registered custom tool with its generated ID, namespace, matcher,
+// and MCP tool metadata.
+func (r *BrowserWebmcpCustomToolService) List(ctx context.Context, idOrName string, opts ...option.RequestOption) (res *CustomToolsResponse, err error) {
+ opts = slices.Concat(r.Options, opts)
+ if idOrName == "" {
+ err = errors.New("missing required id_or_name parameter")
+ return nil, err
+ }
+ path := fmt.Sprintf("browsers/%s/webmcp/custom-tools", idOrName)
+ err = requestconfig.ExecuteNewRequest(ctx, http.MethodGet, path, nil, &res, opts...)
+ return res, err
+}
+
+// Add a namespaced batch of custom tools. A custom tool can be page-backed or
+// CDP-backed. Page-backed tools execute in the page via JavaScript. CDP-backed
+// tools execute via CDP and can use all browser REPL tools (see `/repl`). The
+// source must evaluate to a non-empty array of definitions with URL matchers, tool
+// metadata (including an optional output schema), and execute functions. The batch
+// is added atomically. Matchers apply to top-level documents and nested frames,
+// including out-of-process iframes; each matching tool is exposed once on the
+// tab's top-level document and appears in the WebMCP tool snapshot.
+//
+// To update one tool, list the tools, delete its ID, and add its replacement. Set
+// force_overwrite_namespace to replace every existing tool in the namespace
+// atomically; omitted or false adds tools without replacing existing ones.
+// Existing invocations continue.
+func (r *BrowserWebmcpCustomToolService) Add(ctx context.Context, idOrName string, body BrowserWebmcpCustomToolAddParams, opts ...option.RequestOption) (res *CustomToolsResponse, err error) {
+ opts = slices.Concat(r.Options, opts)
+ if idOrName == "" {
+ err = errors.New("missing required id_or_name parameter")
+ return nil, err
+ }
+ path := fmt.Sprintf("browsers/%s/webmcp/custom-tools", idOrName)
+ err = requestconfig.ExecuteNewRequest(ctx, http.MethodPost, path, body, &res, opts...)
+ return res, err
+}
+
+// Removes one custom tool by generated ID. An invocation already in progress is
+// not canceled.
+func (r *BrowserWebmcpCustomToolService) Remove(ctx context.Context, id string, body BrowserWebmcpCustomToolRemoveParams, opts ...option.RequestOption) (err error) {
+ opts = slices.Concat(r.Options, opts)
+ opts = append([]option.RequestOption{option.WithHeader("Accept", "*/*")}, opts...)
+ if body.IDOrName == "" {
+ err = errors.New("missing required id_or_name parameter")
+ return err
+ }
+ if id == "" {
+ err = errors.New("missing required id parameter")
+ return err
+ }
+ path := fmt.Sprintf("browsers/%s/webmcp/custom-tools/%s", body.IDOrName, id)
+ err = requestconfig.ExecuteNewRequest(ctx, http.MethodDelete, path, nil, nil, opts...)
+ return err
+}
+
+// The properties Namespace, Source are required.
+type AddRequestParam struct {
+ Namespace string `json:"namespace" api:"required"`
+ // JavaScript expression that evaluates to a non-empty array of custom tool
+ // definitions. Limited to 8,000,000 bytes when UTF-8 encoded, so multi-byte
+ // characters reduce the allowed character count.
+ Source string `json:"source" api:"required"`
+ // Atomically replace all existing tools in this namespace with this batch when
+ // true.
+ ForceOverwriteNamespace param.Opt[bool] `json:"force_overwrite_namespace,omitzero"`
+ paramObj
+}
+
+func (r AddRequestParam) MarshalJSON() (data []byte, err error) {
+ type shadow AddRequestParam
+ return param.MarshalObject(r, (*shadow)(&r))
+}
+func (r *AddRequestParam) UnmarshalJSON(data []byte) error {
+ return apijson.UnmarshalRoot(data, r)
+}
+
+type CustomToolsResponse struct {
+ Tools []Definition `json:"tools" api:"required"`
+ // JSON contains metadata for fields, check presence with [respjson.Field.Valid].
+ JSON struct {
+ Tools respjson.Field
+ ExtraFields map[string]respjson.Field
+ raw string
+ } `json:"-"`
+}
+
+// Returns the unmodified JSON received from the API
+func (r CustomToolsResponse) RawJSON() string { return r.JSON.raw }
+func (r *CustomToolsResponse) UnmarshalJSON(data []byte) error {
+ return apijson.UnmarshalRoot(data, r)
+}
+
+type Definition struct {
+ ID string `json:"id" api:"required"`
+ Kind string `json:"kind" api:"required"`
+ Match Match `json:"match" api:"required"`
+ Namespace string `json:"namespace" api:"required"`
+ // Tool metadata follows the
+ // [MCP Tool definition](https://modelcontextprotocol.io/specification/2025-11-25/server/tools#tool)
+ // and the
+ // [WebMCP RegisteredTool definition](https://webmachinelearning.github.io/webmcp/#dictdef-registeredtool).
+ // outputSchema is optional for page and custom tools.
+ Tool ToolMetadata `json:"tool" api:"required"`
+ // JSON contains metadata for fields, check presence with [respjson.Field.Valid].
+ JSON struct {
+ ID respjson.Field
+ Kind respjson.Field
+ Match respjson.Field
+ Namespace respjson.Field
+ Tool respjson.Field
+ ExtraFields map[string]respjson.Field
+ raw string
+ } `json:"-"`
+}
+
+// Returns the unmodified JSON received from the API
+func (r Definition) RawJSON() string { return r.JSON.raw }
+func (r *Definition) UnmarshalJSON(data []byte) error {
+ return apijson.UnmarshalRoot(data, r)
+}
+
+type Match struct {
+ URLPatterns []string `json:"url_patterns" api:"required"`
+ // JSON contains metadata for fields, check presence with [respjson.Field.Valid].
+ JSON struct {
+ URLPatterns respjson.Field
+ ExtraFields map[string]respjson.Field
+ raw string
+ } `json:"-"`
+}
+
+// Returns the unmodified JSON received from the API
+func (r Match) RawJSON() string { return r.JSON.raw }
+func (r *Match) UnmarshalJSON(data []byte) error {
+ return apijson.UnmarshalRoot(data, r)
+}
+
+type BrowserWebmcpCustomToolAddParams struct {
+ AddRequest AddRequestParam
+ paramObj
+}
+
+func (r BrowserWebmcpCustomToolAddParams) MarshalJSON() (data []byte, err error) {
+ return shimjson.Marshal(r.AddRequest)
+}
+func (r *BrowserWebmcpCustomToolAddParams) UnmarshalJSON(data []byte) error {
+ return apijson.UnmarshalRoot(data, r)
+}
+
+type BrowserWebmcpCustomToolRemoveParams struct {
+ IDOrName string `path:"id_or_name" api:"required" json:"-"`
+ paramObj
+}
diff --git a/browserwebmcpcustomtool_test.go b/browserwebmcpcustomtool_test.go
new file mode 100644
index 0000000..239a7b2
--- /dev/null
+++ b/browserwebmcpcustomtool_test.go
@@ -0,0 +1,99 @@
+// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+package kernel_test
+
+import (
+ "context"
+ "errors"
+ "os"
+ "testing"
+
+ "github.com/kernel/kernel-go-sdk"
+ "github.com/kernel/kernel-go-sdk/internal/testutil"
+ "github.com/kernel/kernel-go-sdk/option"
+)
+
+func TestBrowserWebmcpCustomToolList(t *testing.T) {
+ t.Skip("Mock server tests are disabled")
+ baseURL := "http://localhost:4010"
+ if envURL, ok := os.LookupEnv("TEST_API_BASE_URL"); ok {
+ baseURL = envURL
+ }
+ if !testutil.CheckTestServer(t, baseURL) {
+ return
+ }
+ client := kernel.NewClient(
+ option.WithBaseURL(baseURL),
+ option.WithAPIKey("My API Key"),
+ )
+ _, err := client.Browsers.Webmcp.CustomTools.List(context.TODO(), "id_or_name")
+ if err != nil {
+ var apierr *kernel.Error
+ if errors.As(err, &apierr) {
+ t.Log(string(apierr.DumpRequest(true)))
+ }
+ t.Fatalf("err should be nil: %s", err.Error())
+ }
+}
+
+func TestBrowserWebmcpCustomToolAddWithOptionalParams(t *testing.T) {
+ t.Skip("Mock server tests are disabled")
+ baseURL := "http://localhost:4010"
+ if envURL, ok := os.LookupEnv("TEST_API_BASE_URL"); ok {
+ baseURL = envURL
+ }
+ if !testutil.CheckTestServer(t, baseURL) {
+ return
+ }
+ client := kernel.NewClient(
+ option.WithBaseURL(baseURL),
+ option.WithAPIKey("My API Key"),
+ )
+ _, err := client.Browsers.Webmcp.CustomTools.Add(
+ context.TODO(),
+ "id_or_name",
+ kernel.BrowserWebmcpCustomToolAddParams{
+ AddRequest: kernel.AddRequestParam{
+ Namespace: "namespace",
+ Source: "source",
+ ForceOverwriteNamespace: kernel.Bool(true),
+ },
+ },
+ )
+ if err != nil {
+ var apierr *kernel.Error
+ if errors.As(err, &apierr) {
+ t.Log(string(apierr.DumpRequest(true)))
+ }
+ t.Fatalf("err should be nil: %s", err.Error())
+ }
+}
+
+func TestBrowserWebmcpCustomToolRemove(t *testing.T) {
+ t.Skip("Mock server tests are disabled")
+ baseURL := "http://localhost:4010"
+ if envURL, ok := os.LookupEnv("TEST_API_BASE_URL"); ok {
+ baseURL = envURL
+ }
+ if !testutil.CheckTestServer(t, baseURL) {
+ return
+ }
+ client := kernel.NewClient(
+ option.WithBaseURL(baseURL),
+ option.WithAPIKey("My API Key"),
+ )
+ err := client.Browsers.Webmcp.CustomTools.Remove(
+ context.TODO(),
+ "ct_n10b9798ad53ecc4y69z31e1",
+ kernel.BrowserWebmcpCustomToolRemoveParams{
+ IDOrName: "id_or_name",
+ },
+ )
+ if err != nil {
+ var apierr *kernel.Error
+ if errors.As(err, &apierr) {
+ t.Log(string(apierr.DumpRequest(true)))
+ }
+ t.Fatalf("err should be nil: %s", err.Error())
+ }
+}
diff --git a/internal/version.go b/internal/version.go
index d1b8bd7..44c772b 100644
--- a/internal/version.go
+++ b/internal/version.go
@@ -2,4 +2,4 @@
package internal
-const PackageVersion = "0.111.0" // x-release-please-version
+const PackageVersion = "0.112.0" // x-release-please-version
diff --git a/organizationentitlement.go b/organizationentitlement.go
index 1f41056..201ba62 100644
--- a/organizationentitlement.go
+++ b/organizationentitlement.go
@@ -82,6 +82,9 @@ type OrgEntitlementsFeatures struct {
ManagedProxies OrgEntitlementsFeaturesManagedProxies `json:"managed_proxies" api:"required"`
Profiles OrgEntitlementsFeaturesProfiles `json:"profiles" api:"required"`
ProxyBypassHosts OrgEntitlementsFeaturesProxyBypassHosts `json:"proxy_bypass_hosts" api:"required"`
+ // Whether the Search API is enabled for the organization by its rollout feature
+ // flag.
+ Search OrgEntitlementsFeaturesSearch `json:"search" api:"required"`
// Whether the organization can access vaults, using the same access check as vault
// API routes.
Vaults OrgEntitlementsFeaturesVaults `json:"vaults" api:"required"`
@@ -99,6 +102,7 @@ type OrgEntitlementsFeatures struct {
ManagedProxies respjson.Field
Profiles respjson.Field
ProxyBypassHosts respjson.Field
+ Search respjson.Field
Vaults respjson.Field
ExtraFields map[string]respjson.Field
raw string
@@ -336,6 +340,25 @@ func (r *OrgEntitlementsFeaturesProxyBypassHosts) UnmarshalJSON(data []byte) err
return apijson.UnmarshalRoot(data, r)
}
+// Whether the Search API is enabled for the organization by its rollout feature
+// flag.
+type OrgEntitlementsFeaturesSearch struct {
+ // Whether the organization is entitled to use this feature.
+ Enabled bool `json:"enabled" api:"required"`
+ // JSON contains metadata for fields, check presence with [respjson.Field.Valid].
+ JSON struct {
+ Enabled respjson.Field
+ ExtraFields map[string]respjson.Field
+ raw string
+ } `json:"-"`
+}
+
+// Returns the unmodified JSON received from the API
+func (r OrgEntitlementsFeaturesSearch) RawJSON() string { return r.JSON.raw }
+func (r *OrgEntitlementsFeaturesSearch) UnmarshalJSON(data []byte) error {
+ return apijson.UnmarshalRoot(data, r)
+}
+
// Whether the organization can access vaults, using the same access check as vault
// API routes.
type OrgEntitlementsFeaturesVaults struct {