From 1f70e735bad95b73c3eb89535479eac45f1c6dc3 Mon Sep 17 00:00:00 2001
From: "kernel-internal[bot]"
<260533166+kernel-internal[bot]@users.noreply.github.com>
Date: Thu, 13 Aug 2026 20:47:57 +0000
Subject: [PATCH 1/4] feat: Require a name on credential providers and backfill
unnamed rows
Stainless-Generated-From: d8057f2928875212b8a37f02ab023978e471f4d5
---
credentialprovider.go | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/credentialprovider.go b/credentialprovider.go
index 77318a2..a05402e 100644
--- a/credentialprovider.go
+++ b/credentialprovider.go
@@ -142,7 +142,8 @@ func (r *CredentialProviderService) Test(ctx context.Context, id string, opts ..
type CreateCredentialProviderRequestParam struct {
// Service account token for the provider (e.g., 1Password service account token)
Token string `json:"token" api:"required"`
- // Human-readable name for this provider instance (unique per org)
+ // Human-readable name for this provider instance (unique per org). Surrounding
+ // whitespace is trimmed and the trimmed value must be non-empty.
Name string `json:"name" api:"required"`
// Type of credential provider
//
@@ -299,7 +300,8 @@ type UpdateCredentialProviderRequestParam struct {
CacheTtlSeconds param.Opt[int64] `json:"cache_ttl_seconds,omitzero"`
// Whether the provider is enabled for credential lookups
Enabled param.Opt[bool] `json:"enabled,omitzero"`
- // Human-readable name for this provider instance
+ // Human-readable name for this provider instance. Surrounding whitespace is
+ // trimmed and the trimmed value must be non-empty.
Name param.Opt[string] `json:"name,omitzero"`
// Priority order for credential lookups (lower numbers are checked first)
Priority param.Opt[int64] `json:"priority,omitzero"`
From cb90eb77d34aaeb9302fb701a6a613d1f3ff51af Mon Sep 17 00:00:00 2001
From: "kernel-internal[bot]"
<260533166+kernel-internal[bot]@users.noreply.github.com>
Date: Fri, 14 Aug 2026 17:49:27 +0000
Subject: [PATCH 2/4] feat: Expose configurable browser memory
Stainless-Generated-From: e760ec2201481e0ea5b785b9def0aa474334eb9f
---
api.md | 2 ++
browser.go | 43 +++++++++++++++++++++++++++++++++++++++++++
browser_test.go | 1 +
browserpool.go | 5 +++++
invocation.go | 5 +++++
5 files changed, 56 insertions(+)
diff --git a/api.md b/api.md
index 60e3df2..51e8d56 100644
--- a/api.md
+++ b/api.md
@@ -69,6 +69,7 @@ Methods:
Params Types:
+- kernel.BrowserMemoryRequest
- kernel.BrowserNetworkConfigParam
- kernel.BrowserProxyConfigParam
- kernel.BrowserProxyMode
@@ -76,6 +77,7 @@ Params Types:
Response Types:
+- kernel.BrowserMemory
- kernel.BrowserNetworkConfig
- kernel.BrowserPoolRef
- kernel.BrowserProxy
diff --git a/browser.go b/browser.go
index c65dc51..b72629f 100644
--- a/browser.go
+++ b/browser.go
@@ -166,6 +166,25 @@ func (r *BrowserService) LoadExtensions(ctx context.Context, id string, body Bro
return err
}
+// Memory allocated to the browser session.
+type BrowserMemory string
+
+const (
+ BrowserMemory1GiB BrowserMemory = "1GiB"
+ BrowserMemory2GiB BrowserMemory = "2GiB"
+ BrowserMemory6GiB BrowserMemory = "6GiB"
+ BrowserMemory8GiB BrowserMemory = "8GiB"
+ BrowserMemory16GiB BrowserMemory = "16GiB"
+)
+
+// Memory requested for a headful, non-GPU browser session.
+type BrowserMemoryRequest string
+
+const (
+ BrowserMemoryRequest8GiB BrowserMemoryRequest = "8GiB"
+ BrowserMemoryRequest16GiB BrowserMemoryRequest = "16GiB"
+)
+
// Network configuration for a browser session or browser pool.
type BrowserNetworkConfig struct {
// Destinations the browser reaches directly through the session's own network
@@ -453,6 +472,10 @@ type BrowserNewResponse struct {
CreatedAt time.Time `json:"created_at" api:"required" format:"date-time"`
// Whether the browser session is running in headless mode.
Headless bool `json:"headless" api:"required"`
+ // Memory allocated to the browser session.
+ //
+ // Any of "1GiB", "2GiB", "6GiB", "8GiB", "16GiB".
+ Memory BrowserMemory `json:"memory" api:"required"`
// Geographic region of the browser session. Fixed once the session is created.
//
// Any of "us-east", "eu-west".
@@ -531,6 +554,7 @@ type BrowserNewResponse struct {
CdpWsURL respjson.Field
CreatedAt respjson.Field
Headless respjson.Field
+ Memory respjson.Field
Region respjson.Field
SessionID respjson.Field
Stealth respjson.Field
@@ -580,6 +604,10 @@ type BrowserGetResponse struct {
CreatedAt time.Time `json:"created_at" api:"required" format:"date-time"`
// Whether the browser session is running in headless mode.
Headless bool `json:"headless" api:"required"`
+ // Memory allocated to the browser session.
+ //
+ // Any of "1GiB", "2GiB", "6GiB", "8GiB", "16GiB".
+ Memory BrowserMemory `json:"memory" api:"required"`
// Geographic region of the browser session. Fixed once the session is created.
//
// Any of "us-east", "eu-west".
@@ -658,6 +686,7 @@ type BrowserGetResponse struct {
CdpWsURL respjson.Field
CreatedAt respjson.Field
Headless respjson.Field
+ Memory respjson.Field
Region respjson.Field
SessionID respjson.Field
Stealth respjson.Field
@@ -707,6 +736,10 @@ type BrowserUpdateResponse struct {
CreatedAt time.Time `json:"created_at" api:"required" format:"date-time"`
// Whether the browser session is running in headless mode.
Headless bool `json:"headless" api:"required"`
+ // Memory allocated to the browser session.
+ //
+ // Any of "1GiB", "2GiB", "6GiB", "8GiB", "16GiB".
+ Memory BrowserMemory `json:"memory" api:"required"`
// Geographic region of the browser session. Fixed once the session is created.
//
// Any of "us-east", "eu-west".
@@ -785,6 +818,7 @@ type BrowserUpdateResponse struct {
CdpWsURL respjson.Field
CreatedAt respjson.Field
Headless respjson.Field
+ Memory respjson.Field
Region respjson.Field
SessionID respjson.Field
Stealth respjson.Field
@@ -834,6 +868,10 @@ type BrowserListResponse struct {
CreatedAt time.Time `json:"created_at" api:"required" format:"date-time"`
// Whether the browser session is running in headless mode.
Headless bool `json:"headless" api:"required"`
+ // Memory allocated to the browser session.
+ //
+ // Any of "1GiB", "2GiB", "6GiB", "8GiB", "16GiB".
+ Memory BrowserMemory `json:"memory" api:"required"`
// Geographic region of the browser session. Fixed once the session is created.
//
// Any of "us-east", "eu-west".
@@ -912,6 +950,7 @@ type BrowserListResponse struct {
CdpWsURL respjson.Field
CreatedAt respjson.Field
Headless respjson.Field
+ Memory respjson.Field
Region respjson.Field
SessionID respjson.Field
Stealth respjson.Field
@@ -1029,6 +1068,10 @@ type BrowserNewParams 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"`
+ // Memory for a headful, non-GPU browser session. Defaults to 8GiB.
+ //
+ // Any of "8GiB", "16GiB".
+ Memory BrowserMemoryRequest `json:"memory,omitzero"`
// Network configuration for the browser session. Cannot be changed after creation.
Network BrowserNetworkConfigParam `json:"network,omitzero"`
// Profile selection for the browser session. Provide either id or name. If
diff --git a/browser_test.go b/browser_test.go
index 552f46a..5fa2207 100644
--- a/browser_test.go
+++ b/browser_test.go
@@ -41,6 +41,7 @@ func TestBrowserNewWithOptionalParams(t *testing.T) {
Headless: kernel.Bool(false),
InvocationID: kernel.String("rr33xuugxj9h0bkf1rdt2bet"),
KioskMode: kernel.Bool(true),
+ Memory: kernel.BrowserMemoryRequest8GiB,
Name: kernel.String("checkout-flow-1"),
Network: kernel.BrowserNetworkConfigParam{
PrivateHosts: []string{"*.example.ts.net", "100.64.0.0/10"},
diff --git a/browserpool.go b/browserpool.go
index db1b640..fe6b483 100644
--- a/browserpool.go
+++ b/browserpool.go
@@ -347,6 +347,10 @@ type BrowserPoolAcquireResponse struct {
CreatedAt time.Time `json:"created_at" api:"required" format:"date-time"`
// Whether the browser session is running in headless mode.
Headless bool `json:"headless" api:"required"`
+ // Memory allocated to the browser session.
+ //
+ // Any of "1GiB", "2GiB", "6GiB", "8GiB", "16GiB".
+ Memory BrowserMemory `json:"memory" api:"required"`
// Geographic region of the browser session. Fixed once the session is created.
//
// Any of "us-east", "eu-west".
@@ -425,6 +429,7 @@ type BrowserPoolAcquireResponse struct {
CdpWsURL respjson.Field
CreatedAt respjson.Field
Headless respjson.Field
+ Memory respjson.Field
Region respjson.Field
SessionID respjson.Field
Stealth respjson.Field
diff --git a/invocation.go b/invocation.go
index f6a8433..f8eeb12 100644
--- a/invocation.go
+++ b/invocation.go
@@ -544,6 +544,10 @@ type InvocationListBrowsersResponseBrowser struct {
CreatedAt time.Time `json:"created_at" api:"required" format:"date-time"`
// Whether the browser session is running in headless mode.
Headless bool `json:"headless" api:"required"`
+ // Memory allocated to the browser session.
+ //
+ // Any of "1GiB", "2GiB", "6GiB", "8GiB", "16GiB".
+ Memory BrowserMemory `json:"memory" api:"required"`
// Geographic region of the browser session. Fixed once the session is created.
//
// Any of "us-east", "eu-west".
@@ -622,6 +626,7 @@ type InvocationListBrowsersResponseBrowser struct {
CdpWsURL respjson.Field
CreatedAt respjson.Field
Headless respjson.Field
+ Memory respjson.Field
Region respjson.Field
SessionID respjson.Field
Stealth respjson.Field
From 25f9b283b2ec49a85a973bc267a6bde4c3872a76 Mon Sep 17 00:00:00 2001
From: "kernel-internal[bot]"
<260533166+kernel-internal[bot]@users.noreply.github.com>
Date: Fri, 14 Aug 2026 18:07:59 +0000
Subject: [PATCH 3/4] feat: Add customer-facing OTLP destination CRUD API
Stainless-Generated-From: 8e08b8b3680bc87c55f7d227162b7e3a9ae39dd2
---
.stats.yml | 2 +-
api.md | 16 +++
browser.go | 3 +-
browsertelemetry.go | 3 +-
client.go | 6 +-
telemetry.go | 30 +++++
telemetrydestination.go | 241 +++++++++++++++++++++++++++++++++++
telemetrydestination_test.go | 152 ++++++++++++++++++++++
8 files changed, 448 insertions(+), 5 deletions(-)
create mode 100644 telemetry.go
create mode 100644 telemetrydestination.go
create mode 100644 telemetrydestination_test.go
diff --git a/.stats.yml b/.stats.yml
index 50996d4..98f97da 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1 +1 @@
-configured_endpoints: 134
+configured_endpoints: 139
diff --git a/api.md b/api.md
index 51e8d56..5486d5f 100644
--- a/api.md
+++ b/api.md
@@ -322,6 +322,22 @@ Methods:
- client.Auth.Connections.Submit(ctx context.Context, id string, body kernel.AuthConnectionSubmitParams) (\*kernel.SubmitFieldsResponse, error)
- client.Auth.Connections.Timeline(ctx context.Context, id string, query kernel.AuthConnectionTimelineParams) (\*pagination.OffsetPagination[kernel.ManagedAuthTimelineEvent], error)
+# Telemetry
+
+## Destinations
+
+Response Types:
+
+- kernel.OtlpDestination
+
+Methods:
+
+- client.Telemetry.Destinations.New(ctx context.Context, body kernel.TelemetryDestinationNewParams) (\*kernel.OtlpDestination, error)
+- client.Telemetry.Destinations.Get(ctx context.Context, idOrName string) (\*kernel.OtlpDestination, error)
+- client.Telemetry.Destinations.Update(ctx context.Context, idOrName string, body kernel.TelemetryDestinationUpdateParams) (\*kernel.OtlpDestination, error)
+- client.Telemetry.Destinations.List(ctx context.Context, query kernel.TelemetryDestinationListParams) (\*pagination.OffsetPagination[kernel.OtlpDestination], error)
+- client.Telemetry.Destinations.Delete(ctx context.Context, idOrName string) error
+
# Proxies
Response Types:
diff --git a/browser.go b/browser.go
index b72629f..bb9c6ca 100644
--- a/browser.go
+++ b/browser.go
@@ -36,7 +36,8 @@ import (
// the [NewBrowserService] method instead.
type BrowserService struct {
Options []option.RequestOption
- // Stream live telemetry events from a browser session.
+ // Stream live telemetry events from a browser session, and manage the destinations
+ // sessions export them to.
Telemetry BrowserTelemetryService
// Record and manage browser session video replays.
Replays BrowserReplayService
diff --git a/browsertelemetry.go b/browsertelemetry.go
index 02a93b9..bceb98b 100644
--- a/browsertelemetry.go
+++ b/browsertelemetry.go
@@ -22,7 +22,8 @@ import (
"github.com/kernel/kernel-go-sdk/shared/constant"
)
-// Stream live telemetry events from a browser session.
+// Stream live telemetry events from a browser session, and manage the destinations
+// sessions export them to.
//
// BrowserTelemetryService contains methods and other services that help with
// interacting with the kernel API.
diff --git a/client.go b/client.go
index 48b3721..9827a52 100644
--- a/client.go
+++ b/client.go
@@ -30,8 +30,9 @@ type Client struct {
// Create and manage browser sessions.
Browsers BrowserService
// Create, list, retrieve, and delete browser profiles.
- Profiles ProfileService
- Auth AuthService
+ Profiles ProfileService
+ Auth AuthService
+ Telemetry TelemetryService
// Create and manage proxy configurations for routing browser traffic.
Proxies ProxyService
// Create, list, retrieve, and delete browser extensions.
@@ -94,6 +95,7 @@ func NewClient(opts ...option.RequestOption) (r Client) {
r.Browsers = NewBrowserService(opts...)
r.Profiles = NewProfileService(opts...)
r.Auth = NewAuthService(opts...)
+ r.Telemetry = NewTelemetryService(opts...)
r.Proxies = NewProxyService(opts...)
r.Extensions = NewExtensionService(opts...)
r.BrowserPools = NewBrowserPoolService(opts...)
diff --git a/telemetry.go b/telemetry.go
new file mode 100644
index 0000000..076adbf
--- /dev/null
+++ b/telemetry.go
@@ -0,0 +1,30 @@
+// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+package kernel
+
+import (
+ "github.com/kernel/kernel-go-sdk/option"
+)
+
+// TelemetryService 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 [NewTelemetryService] method instead.
+type TelemetryService struct {
+ Options []option.RequestOption
+ // Stream live telemetry events from a browser session, and manage the destinations
+ // sessions export them to.
+ Destinations TelemetryDestinationService
+}
+
+// NewTelemetryService 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 NewTelemetryService(opts ...option.RequestOption) (r TelemetryService) {
+ r = TelemetryService{}
+ r.Options = opts
+ r.Destinations = NewTelemetryDestinationService(opts...)
+ return
+}
diff --git a/telemetrydestination.go b/telemetrydestination.go
new file mode 100644
index 0000000..8477b1f
--- /dev/null
+++ b/telemetrydestination.go
@@ -0,0 +1,241 @@
+// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+package kernel
+
+import (
+ "context"
+ "errors"
+ "fmt"
+ "net/http"
+ "net/url"
+ "slices"
+ "time"
+
+ "github.com/kernel/kernel-go-sdk/internal/apijson"
+ "github.com/kernel/kernel-go-sdk/internal/apiquery"
+ "github.com/kernel/kernel-go-sdk/internal/requestconfig"
+ "github.com/kernel/kernel-go-sdk/option"
+ "github.com/kernel/kernel-go-sdk/packages/pagination"
+ "github.com/kernel/kernel-go-sdk/packages/param"
+ "github.com/kernel/kernel-go-sdk/packages/respjson"
+)
+
+// Stream live telemetry events from a browser session, and manage the destinations
+// sessions export them to.
+//
+// TelemetryDestinationService 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 [NewTelemetryDestinationService] method instead.
+type TelemetryDestinationService struct {
+ Options []option.RequestOption
+}
+
+// NewTelemetryDestinationService 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 NewTelemetryDestinationService(opts ...option.RequestOption) (r TelemetryDestinationService) {
+ r = TelemetryDestinationService{}
+ r.Options = opts
+ return
+}
+
+// Create an OTLP export destination in the resolved project. Names must be unique
+// within the project.
+func (r *TelemetryDestinationService) New(ctx context.Context, body TelemetryDestinationNewParams, opts ...option.RequestOption) (res *OtlpDestination, err error) {
+ opts = slices.Concat(r.Options, opts)
+ path := "telemetry/destinations"
+ err = requestconfig.ExecuteNewRequest(ctx, http.MethodPost, path, body, &res, opts...)
+ return res, err
+}
+
+// Retrieve a single OTLP destination in the resolved project by its ID or name.
+func (r *TelemetryDestinationService) Get(ctx context.Context, idOrName string, opts ...option.RequestOption) (res *OtlpDestination, 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("telemetry/destinations/%s", idOrName)
+ err = requestconfig.ExecuteNewRequest(ctx, http.MethodGet, path, nil, &res, opts...)
+ return res, err
+}
+
+// Update an OTLP destination. Sessions already exporting to it pick up the new
+// values without restarting, which makes this the way to rotate credentials
+// without interrupting export.
+//
+// Names must be unique within the project. Renaming is refused with a 409 while a
+// managed auth connection selects this destination by name, since that connection
+// resolves the name on every login. Every other field, including `headers`, stays
+// editable.
+func (r *TelemetryDestinationService) Update(ctx context.Context, idOrName string, body TelemetryDestinationUpdateParams, opts ...option.RequestOption) (res *OtlpDestination, 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("telemetry/destinations/%s", idOrName)
+ err = requestconfig.ExecuteNewRequest(ctx, http.MethodPatch, path, body, &res, opts...)
+ return res, err
+}
+
+// List OTLP export destinations in the resolved project.
+func (r *TelemetryDestinationService) List(ctx context.Context, query TelemetryDestinationListParams, opts ...option.RequestOption) (res *pagination.OffsetPagination[OtlpDestination], err error) {
+ var raw *http.Response
+ opts = slices.Concat(r.Options, opts)
+ opts = append([]option.RequestOption{option.WithResponseInto(&raw)}, opts...)
+ path := "telemetry/destinations"
+ cfg, err := requestconfig.NewRequestConfig(ctx, http.MethodGet, path, query, &res, opts...)
+ if err != nil {
+ return nil, err
+ }
+ err = cfg.Execute()
+ if err != nil {
+ return nil, err
+ }
+ res.SetPageConfig(cfg, raw)
+ return res, nil
+}
+
+// List OTLP export destinations in the resolved project.
+func (r *TelemetryDestinationService) ListAutoPaging(ctx context.Context, query TelemetryDestinationListParams, opts ...option.RequestOption) *pagination.OffsetPaginationAutoPager[OtlpDestination] {
+ return pagination.NewOffsetPaginationAutoPager(r.List(ctx, query, opts...))
+}
+
+// Delete an OTLP destination. Sessions bound to it are still exporting, so the
+// delete is refused with a 409 while any exist; either wait for those sessions to
+// end or delete them first. It is refused the same way while a managed auth
+// connection still selects it, because that connection re-resolves the destination
+// on every login, and while a managed auth login using it is still in progress.
+func (r *TelemetryDestinationService) Delete(ctx context.Context, idOrName string, opts ...option.RequestOption) (err error) {
+ opts = slices.Concat(r.Options, opts)
+ opts = append([]option.RequestOption{option.WithHeader("Accept", "*/*")}, opts...)
+ if idOrName == "" {
+ err = errors.New("missing required id_or_name parameter")
+ return err
+ }
+ path := fmt.Sprintf("telemetry/destinations/%s", idOrName)
+ err = requestconfig.ExecuteNewRequest(ctx, http.MethodDelete, path, nil, nil, opts...)
+ return err
+}
+
+// An OTLP endpoint to export browser session telemetry to. Reference one from
+// `telemetry.export.otlp.destination` when creating a browser to export that
+// session's captured telemetry to it.
+type OtlpDestination struct {
+ ID string `json:"id" api:"required"`
+ CreatedAt time.Time `json:"created_at" api:"required" format:"date-time"`
+ // OTLP/HTTP endpoint telemetry is sent to.
+ Endpoint string `json:"endpoint" api:"required"`
+ // Headers sent with each export request. Names are returned in canonical form
+ // (`Authorization`, not `authorization`). Values are returned redacted as empty
+ // strings, so the keys are visible but the credentials are not.
+ Headers map[string]string `json:"headers" api:"required"`
+ // Unique within the project. Usable in place of the ID when selecting a
+ // destination, so it cannot be shaped like an ID.
+ Name string `json:"name" api:"required"`
+ UpdatedAt time.Time `json:"updated_at" api:"required" format:"date-time"`
+ Description string `json:"description"`
+ // JSON contains metadata for fields, check presence with [respjson.Field.Valid].
+ JSON struct {
+ ID respjson.Field
+ CreatedAt respjson.Field
+ Endpoint respjson.Field
+ Headers respjson.Field
+ Name respjson.Field
+ UpdatedAt respjson.Field
+ Description respjson.Field
+ ExtraFields map[string]respjson.Field
+ raw string
+ } `json:"-"`
+}
+
+// Returns the unmodified JSON received from the API
+func (r OtlpDestination) RawJSON() string { return r.JSON.raw }
+func (r *OtlpDestination) UnmarshalJSON(data []byte) error {
+ return apijson.UnmarshalRoot(data, r)
+}
+
+type TelemetryDestinationNewParams struct {
+ // Base endpoint of the OTLP/HTTP collector, without a signal path. Kernel appends
+ // the signal path itself, so pass `https://api.honeycomb.io` rather than
+ // `https://api.honeycomb.io/v1/logs`. If your provider's docs give you a
+ // signal-specific URL, drop the trailing `/v1/logs`, `/v1/traces`, or
+ // `/v1/metrics` — an endpoint that already carries one is rejected.
+ //
+ // Must be http or https, must resolve to a public address, and must carry no query
+ // string or fragment. Examples: `https://api.honeycomb.io`,
+ // `https://otlp-gateway-prod-us-east-0.grafana.net/otlp`,
+ // `https://otlp.datadoghq.com` (Datadog's OTLP intake for US1, not its logs
+ // intake).
+ Endpoint string `json:"endpoint" api:"required"`
+ // Unique within the project.
+ Name string `json:"name" api:"required"`
+ Description param.Opt[string] `json:"description,omitzero"`
+ // Headers sent with each export request, typically an ingestion key. Encrypted at
+ // rest and returned redacted. Names and values must be valid HTTP header tokens,
+ // and the names and values together cannot exceed 8192 bytes. Names are matched
+ // case-insensitively and stored canonicalized, so supplying two spellings of one
+ // header is rejected.
+ Headers map[string]string `json:"headers,omitzero"`
+ paramObj
+}
+
+func (r TelemetryDestinationNewParams) MarshalJSON() (data []byte, err error) {
+ type shadow TelemetryDestinationNewParams
+ return param.MarshalObject(r, (*shadow)(&r))
+}
+func (r *TelemetryDestinationNewParams) UnmarshalJSON(data []byte) error {
+ return apijson.UnmarshalRoot(data, r)
+}
+
+type TelemetryDestinationUpdateParams struct {
+ Description param.Opt[string] `json:"description,omitzero"`
+ // Base endpoint of the OTLP/HTTP collector, without a signal path. Same rules as
+ // on create.
+ Endpoint param.Opt[string] `json:"endpoint,omitzero"`
+ Name param.Opt[string] `json:"name,omitzero"`
+ // Edits stored headers key by key rather than replacing the map. A string value
+ // adds or replaces that header, `null` deletes it, and any key you omit is left as
+ // it is. Names are matched case-insensitively, so `authorization` replaces a
+ // stored `Authorization` rather than adding a second entry. This is the credential
+ // rotation path; sessions already exporting pick up the new values without
+ // restarting. Names and values must be valid HTTP header tokens, and the names and
+ // values together cannot exceed 8192 bytes.
+ Headers map[string]string `json:"headers,omitzero"`
+ paramObj
+}
+
+func (r TelemetryDestinationUpdateParams) MarshalJSON() (data []byte, err error) {
+ type shadow TelemetryDestinationUpdateParams
+ return param.MarshalObject(r, (*shadow)(&r))
+}
+func (r *TelemetryDestinationUpdateParams) UnmarshalJSON(data []byte) error {
+ return apijson.UnmarshalRoot(data, r)
+}
+
+type TelemetryDestinationListParams struct {
+ // Limit the number of destinations to return.
+ Limit param.Opt[int64] `query:"limit,omitzero" json:"-"`
+ // Exact-match filter on destination name using the database collation. In
+ // production, matching is case- and accent-insensitive.
+ Name param.Opt[string] `query:"name,omitzero" json:"-"`
+ // Offset the number of destinations to return.
+ Offset param.Opt[int64] `query:"offset,omitzero" json:"-"`
+ // Case-insensitive substring match against destination name or endpoint. IDs match
+ // by exact value.
+ Query param.Opt[string] `query:"query,omitzero" json:"-"`
+ paramObj
+}
+
+// URLQuery serializes [TelemetryDestinationListParams]'s query parameters as
+// `url.Values`.
+func (r TelemetryDestinationListParams) URLQuery() (v url.Values, err error) {
+ return apiquery.MarshalWithSettings(r, apiquery.QuerySettings{
+ ArrayFormat: apiquery.ArrayQueryFormatComma,
+ NestedFormat: apiquery.NestedQueryFormatBrackets,
+ })
+}
diff --git a/telemetrydestination_test.go b/telemetrydestination_test.go
new file mode 100644
index 0000000..039773b
--- /dev/null
+++ b/telemetrydestination_test.go
@@ -0,0 +1,152 @@
+// 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 TestTelemetryDestinationNewWithOptionalParams(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.Telemetry.Destinations.New(context.TODO(), kernel.TelemetryDestinationNewParams{
+ Endpoint: "x",
+ Name: "name",
+ Description: kernel.String("description"),
+ Headers: map[string]string{
+ "foo": "string",
+ },
+ })
+ 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 TestTelemetryDestinationGet(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.Telemetry.Destinations.Get(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 TestTelemetryDestinationUpdateWithOptionalParams(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.Telemetry.Destinations.Update(
+ context.TODO(),
+ "id_or_name",
+ kernel.TelemetryDestinationUpdateParams{
+ Description: kernel.String("description"),
+ Endpoint: kernel.String("x"),
+ Headers: map[string]string{
+ "foo": "string",
+ },
+ Name: kernel.String("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 TestTelemetryDestinationListWithOptionalParams(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.Telemetry.Destinations.List(context.TODO(), kernel.TelemetryDestinationListParams{
+ Limit: kernel.Int(1),
+ Name: kernel.String("name"),
+ Offset: kernel.Int(0),
+ Query: kernel.String("query"),
+ })
+ 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 TestTelemetryDestinationDelete(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.Telemetry.Destinations.Delete(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())
+ }
+}
From 7cd93c2ef29622c32cf16a58c9717c9a47fb4ce1 Mon Sep 17 00:00:00 2001
From: "kernel-internal[bot]"
<260533166+kernel-internal[bot]@users.noreply.github.com>
Date: Fri, 14 Aug 2026 18:12:14 +0000
Subject: [PATCH 4/4] release: 0.91.0
---
.release-please-manifest.json | 2 +-
CHANGELOG.md | 9 +++++++++
README.md | 2 +-
internal/version.go | 2 +-
4 files changed, 12 insertions(+), 3 deletions(-)
diff --git a/.release-please-manifest.json b/.release-please-manifest.json
index f286375..29c535c 100644
--- a/.release-please-manifest.json
+++ b/.release-please-manifest.json
@@ -1,3 +1,3 @@
{
- ".": "0.90.0"
+ ".": "0.91.0"
}
\ No newline at end of file
diff --git a/CHANGELOG.md b/CHANGELOG.md
index b8df63d..ca827fc 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,14 @@
# Changelog
+## [0.91.0](https://github.com/kernel/kernel-go-sdk/compare/v0.90.0...v0.91.0) (2026-08-14)
+
+
+### Features
+
+* Add customer-facing OTLP destination CRUD API ([25f9b28](https://github.com/kernel/kernel-go-sdk/commit/25f9b283b2ec49a85a973bc267a6bde4c3872a76))
+* Expose configurable browser memory ([cb90eb7](https://github.com/kernel/kernel-go-sdk/commit/cb90eb77d34aaeb9302fb701a6a613d1f3ff51af))
+* Require a name on credential providers and backfill unnamed rows ([1f70e73](https://github.com/kernel/kernel-go-sdk/commit/1f70e735bad95b73c3eb89535479eac45f1c6dc3))
+
## [0.90.0](https://github.com/kernel/kernel-go-sdk/compare/v0.89.0...v0.90.0) (2026-08-12)
diff --git a/README.md b/README.md
index acdff03..52c3ec4 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.90.0'
+go get -u 'github.com/kernel/kernel-go-sdk@v0.91.0'
```
diff --git a/internal/version.go b/internal/version.go
index 4e3e961..af7cda6 100644
--- a/internal/version.go
+++ b/internal/version.go
@@ -2,4 +2,4 @@
package internal
-const PackageVersion = "0.90.0" // x-release-please-version
+const PackageVersion = "0.91.0" // x-release-please-version