From ee63aba391e6a3024e93eeca28d008ea93b18b58 Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Mon, 24 Nov 2025 18:52:31 +0000
Subject: [PATCH 1/7] feat: Mason/agent auth api
---
.stats.yml | 8 +-
agent.go | 28 +++++
agentauth.go | 267 +++++++++++++++++++++++++++++++++++++++++++
agentauth_test.go | 44 +++++++
agentauthrun.go | 150 ++++++++++++++++++++++++
agentauthrun_test.go | 125 ++++++++++++++++++++
api.md | 29 +++++
client.go | 2 +
8 files changed, 649 insertions(+), 4 deletions(-)
create mode 100644 agent.go
create mode 100644 agentauth.go
create mode 100644 agentauth_test.go
create mode 100644 agentauthrun.go
create mode 100644 agentauthrun_test.go
diff --git a/.stats.yml b/.stats.yml
index 11b820d..bdbede3 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,4 +1,4 @@
-configured_endpoints: 66
-openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-2af1b468584cb44aa9babbbfb82bff4055614fbb5c815084a6b7dacc1cf1a822.yml
-openapi_spec_hash: 891affa2849341ea01d62011125f7edc
-config_hash: 9421eb86b7f3f4b274f123279da3858e
+configured_endpoints: 71
+openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-bb3f37e55117a56e7a4208bd646d3a68adeb651ced8531e13fbfc1fc9dcb05a4.yml
+openapi_spec_hash: 7303ce8ce3130e16a6a5c2bb49e43e9b
+config_hash: be146470fb2d4583b6533859f0fa48f5
diff --git a/agent.go b/agent.go
new file mode 100644
index 0000000..d91fa4e
--- /dev/null
+++ b/agent.go
@@ -0,0 +1,28 @@
+// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+package kernel
+
+import (
+ "github.com/onkernel/kernel-go-sdk/option"
+)
+
+// AgentService 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 [NewAgentService] method instead.
+type AgentService struct {
+ Options []option.RequestOption
+ Auth AgentAuthService
+}
+
+// NewAgentService 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 NewAgentService(opts ...option.RequestOption) (r AgentService) {
+ r = AgentService{}
+ r.Options = opts
+ r.Auth = NewAgentAuthService(opts...)
+ return
+}
diff --git a/agentauth.go b/agentauth.go
new file mode 100644
index 0000000..373ecb6
--- /dev/null
+++ b/agentauth.go
@@ -0,0 +1,267 @@
+// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+package kernel
+
+import (
+ "context"
+ "net/http"
+ "slices"
+ "time"
+
+ "github.com/onkernel/kernel-go-sdk/internal/apijson"
+ "github.com/onkernel/kernel-go-sdk/internal/requestconfig"
+ "github.com/onkernel/kernel-go-sdk/option"
+ "github.com/onkernel/kernel-go-sdk/packages/param"
+ "github.com/onkernel/kernel-go-sdk/packages/respjson"
+)
+
+// AgentAuthService 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 [NewAgentAuthService] method instead.
+type AgentAuthService struct {
+ Options []option.RequestOption
+ Runs AgentAuthRunService
+}
+
+// NewAgentAuthService 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 NewAgentAuthService(opts ...option.RequestOption) (r AgentAuthService) {
+ r = AgentAuthService{}
+ r.Options = opts
+ r.Runs = NewAgentAuthRunService(opts...)
+ return
+}
+
+// Creates a browser session and returns a handoff code for the hosted flow. Uses
+// standard API key or JWT authentication (not the JWT returned by the exchange
+// endpoint).
+func (r *AgentAuthService) Start(ctx context.Context, body AgentAuthStartParams, opts ...option.RequestOption) (res *AgentAuthStartResponse, err error) {
+ opts = slices.Concat(r.Options, opts)
+ path := "agents/auth/start"
+ err = requestconfig.ExecuteNewRequest(ctx, http.MethodPost, path, body, &res, opts...)
+ return
+}
+
+// Response from discover endpoint matching AuthBlueprint schema
+type AgentAuthDiscoverResponse struct {
+ // Whether discovery succeeded
+ Success bool `json:"success,required"`
+ // Error message if discovery failed
+ ErrorMessage string `json:"error_message"`
+ // Discovered form fields (present when success is true)
+ Fields []DiscoveredField `json:"fields"`
+ // Whether user is already logged in
+ LoggedIn bool `json:"logged_in"`
+ // URL of the discovered login page
+ LoginURL string `json:"login_url" format:"uri"`
+ // Title of the login page
+ PageTitle string `json:"page_title"`
+ // JSON contains metadata for fields, check presence with [respjson.Field.Valid].
+ JSON struct {
+ Success respjson.Field
+ ErrorMessage respjson.Field
+ Fields respjson.Field
+ LoggedIn respjson.Field
+ LoginURL respjson.Field
+ PageTitle respjson.Field
+ ExtraFields map[string]respjson.Field
+ raw string
+ } `json:"-"`
+}
+
+// Returns the unmodified JSON received from the API
+func (r AgentAuthDiscoverResponse) RawJSON() string { return r.JSON.raw }
+func (r *AgentAuthDiscoverResponse) UnmarshalJSON(data []byte) error {
+ return apijson.UnmarshalRoot(data, r)
+}
+
+// Response from get run endpoint
+type AgentAuthRunResponse struct {
+ // App name (org name at time of run creation)
+ AppName string `json:"app_name,required"`
+ // When the handoff code expires
+ ExpiresAt time.Time `json:"expires_at,required" format:"date-time"`
+ // Run status
+ //
+ // Any of "ACTIVE", "ENDED", "EXPIRED", "CANCELED".
+ Status AgentAuthRunResponseStatus `json:"status,required"`
+ // Target domain for authentication
+ TargetDomain string `json:"target_domain,required"`
+ // JSON contains metadata for fields, check presence with [respjson.Field.Valid].
+ JSON struct {
+ AppName respjson.Field
+ ExpiresAt respjson.Field
+ Status respjson.Field
+ TargetDomain respjson.Field
+ ExtraFields map[string]respjson.Field
+ raw string
+ } `json:"-"`
+}
+
+// Returns the unmodified JSON received from the API
+func (r AgentAuthRunResponse) RawJSON() string { return r.JSON.raw }
+func (r *AgentAuthRunResponse) UnmarshalJSON(data []byte) error {
+ return apijson.UnmarshalRoot(data, r)
+}
+
+// Run status
+type AgentAuthRunResponseStatus string
+
+const (
+ AgentAuthRunResponseStatusActive AgentAuthRunResponseStatus = "ACTIVE"
+ AgentAuthRunResponseStatusEnded AgentAuthRunResponseStatus = "ENDED"
+ AgentAuthRunResponseStatusExpired AgentAuthRunResponseStatus = "EXPIRED"
+ AgentAuthRunResponseStatusCanceled AgentAuthRunResponseStatus = "CANCELED"
+)
+
+// Response from starting an agent authentication run
+type AgentAuthStartResponse struct {
+ // When the handoff code expires
+ ExpiresAt time.Time `json:"expires_at,required" format:"date-time"`
+ // One-time code for handoff
+ HandoffCode string `json:"handoff_code,required"`
+ // URL to redirect user to
+ HostedURL string `json:"hosted_url,required" format:"uri"`
+ // Unique identifier for the run
+ RunID string `json:"run_id,required"`
+ // JSON contains metadata for fields, check presence with [respjson.Field.Valid].
+ JSON struct {
+ ExpiresAt respjson.Field
+ HandoffCode respjson.Field
+ HostedURL respjson.Field
+ RunID respjson.Field
+ ExtraFields map[string]respjson.Field
+ raw string
+ } `json:"-"`
+}
+
+// Returns the unmodified JSON received from the API
+func (r AgentAuthStartResponse) RawJSON() string { return r.JSON.raw }
+func (r *AgentAuthStartResponse) UnmarshalJSON(data []byte) error {
+ return apijson.UnmarshalRoot(data, r)
+}
+
+// Response from submit endpoint matching SubmitResult schema
+type AgentAuthSubmitResponse struct {
+ // Whether submission succeeded
+ Success bool `json:"success,required"`
+ // Additional fields needed (e.g., OTP) - present when needs_additional_auth is
+ // true
+ AdditionalFields []DiscoveredField `json:"additional_fields"`
+ // App name (only present when logged_in is true)
+ AppName string `json:"app_name"`
+ // Error message if submission failed
+ ErrorMessage string `json:"error_message"`
+ // Whether user is now logged in
+ LoggedIn bool `json:"logged_in"`
+ // Whether additional authentication fields are needed
+ NeedsAdditionalAuth bool `json:"needs_additional_auth"`
+ // Target domain (only present when logged_in is true)
+ TargetDomain string `json:"target_domain"`
+ // JSON contains metadata for fields, check presence with [respjson.Field.Valid].
+ JSON struct {
+ Success respjson.Field
+ AdditionalFields respjson.Field
+ AppName respjson.Field
+ ErrorMessage respjson.Field
+ LoggedIn respjson.Field
+ NeedsAdditionalAuth respjson.Field
+ TargetDomain respjson.Field
+ ExtraFields map[string]respjson.Field
+ raw string
+ } `json:"-"`
+}
+
+// Returns the unmodified JSON received from the API
+func (r AgentAuthSubmitResponse) RawJSON() string { return r.JSON.raw }
+func (r *AgentAuthSubmitResponse) UnmarshalJSON(data []byte) error {
+ return apijson.UnmarshalRoot(data, r)
+}
+
+// A discovered form field
+type DiscoveredField struct {
+ // Field label
+ Label string `json:"label,required"`
+ // Field name
+ Name string `json:"name,required"`
+ // CSS selector for the field
+ Selector string `json:"selector,required"`
+ // Field type
+ //
+ // Any of "text", "email", "password", "tel", "number", "url", "code", "checkbox".
+ Type DiscoveredFieldType `json:"type,required"`
+ // Field placeholder
+ Placeholder string `json:"placeholder"`
+ // Whether field is required
+ Required bool `json:"required"`
+ // JSON contains metadata for fields, check presence with [respjson.Field.Valid].
+ JSON struct {
+ Label respjson.Field
+ Name respjson.Field
+ Selector respjson.Field
+ Type respjson.Field
+ Placeholder respjson.Field
+ Required respjson.Field
+ ExtraFields map[string]respjson.Field
+ raw string
+ } `json:"-"`
+}
+
+// Returns the unmodified JSON received from the API
+func (r DiscoveredField) RawJSON() string { return r.JSON.raw }
+func (r *DiscoveredField) UnmarshalJSON(data []byte) error {
+ return apijson.UnmarshalRoot(data, r)
+}
+
+// Field type
+type DiscoveredFieldType string
+
+const (
+ DiscoveredFieldTypeText DiscoveredFieldType = "text"
+ DiscoveredFieldTypeEmail DiscoveredFieldType = "email"
+ DiscoveredFieldTypePassword DiscoveredFieldType = "password"
+ DiscoveredFieldTypeTel DiscoveredFieldType = "tel"
+ DiscoveredFieldTypeNumber DiscoveredFieldType = "number"
+ DiscoveredFieldTypeURL DiscoveredFieldType = "url"
+ DiscoveredFieldTypeCode DiscoveredFieldType = "code"
+ DiscoveredFieldTypeCheckbox DiscoveredFieldType = "checkbox"
+)
+
+type AgentAuthStartParams struct {
+ // Name of the profile to use for this flow
+ ProfileName string `json:"profile_name,required"`
+ // Target domain for authentication
+ TargetDomain string `json:"target_domain,required"`
+ // Optional logo URL for the application
+ AppLogoURL param.Opt[string] `json:"app_logo_url,omitzero" format:"uri"`
+ // Optional proxy configuration
+ Proxy AgentAuthStartParamsProxy `json:"proxy,omitzero"`
+ paramObj
+}
+
+func (r AgentAuthStartParams) MarshalJSON() (data []byte, err error) {
+ type shadow AgentAuthStartParams
+ return param.MarshalObject(r, (*shadow)(&r))
+}
+func (r *AgentAuthStartParams) UnmarshalJSON(data []byte) error {
+ return apijson.UnmarshalRoot(data, r)
+}
+
+// Optional proxy configuration
+type AgentAuthStartParamsProxy struct {
+ // ID of the proxy to use
+ ProxyID param.Opt[string] `json:"proxy_id,omitzero"`
+ paramObj
+}
+
+func (r AgentAuthStartParamsProxy) MarshalJSON() (data []byte, err error) {
+ type shadow AgentAuthStartParamsProxy
+ return param.MarshalObject(r, (*shadow)(&r))
+}
+func (r *AgentAuthStartParamsProxy) UnmarshalJSON(data []byte) error {
+ return apijson.UnmarshalRoot(data, r)
+}
diff --git a/agentauth_test.go b/agentauth_test.go
new file mode 100644
index 0000000..ab734e1
--- /dev/null
+++ b/agentauth_test.go
@@ -0,0 +1,44 @@
+// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+package kernel_test
+
+import (
+ "context"
+ "errors"
+ "os"
+ "testing"
+
+ "github.com/onkernel/kernel-go-sdk"
+ "github.com/onkernel/kernel-go-sdk/internal/testutil"
+ "github.com/onkernel/kernel-go-sdk/option"
+)
+
+func TestAgentAuthStartWithOptionalParams(t *testing.T) {
+ t.Skip("Prism 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.Agents.Auth.Start(context.TODO(), kernel.AgentAuthStartParams{
+ ProfileName: "auth-abc123",
+ TargetDomain: "doordash.com",
+ AppLogoURL: kernel.String("https://example.com/logo.png"),
+ Proxy: kernel.AgentAuthStartParamsProxy{
+ ProxyID: kernel.String("proxy_id"),
+ },
+ })
+ 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/agentauthrun.go b/agentauthrun.go
new file mode 100644
index 0000000..da62724
--- /dev/null
+++ b/agentauthrun.go
@@ -0,0 +1,150 @@
+// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+package kernel
+
+import (
+ "context"
+ "errors"
+ "fmt"
+ "net/http"
+ "slices"
+
+ "github.com/onkernel/kernel-go-sdk/internal/apijson"
+ "github.com/onkernel/kernel-go-sdk/internal/requestconfig"
+ "github.com/onkernel/kernel-go-sdk/option"
+ "github.com/onkernel/kernel-go-sdk/packages/param"
+ "github.com/onkernel/kernel-go-sdk/packages/respjson"
+)
+
+// AgentAuthRunService 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 [NewAgentAuthRunService] method instead.
+type AgentAuthRunService struct {
+ Options []option.RequestOption
+}
+
+// NewAgentAuthRunService 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 NewAgentAuthRunService(opts ...option.RequestOption) (r AgentAuthRunService) {
+ r = AgentAuthRunService{}
+ r.Options = opts
+ return
+}
+
+// Returns run details including app_name and target_domain. Uses the JWT returned
+// by the exchange endpoint, or standard API key or JWT authentication.
+func (r *AgentAuthRunService) Get(ctx context.Context, runID string, opts ...option.RequestOption) (res *AgentAuthRunResponse, err error) {
+ opts = slices.Concat(r.Options, opts)
+ if runID == "" {
+ err = errors.New("missing required run_id parameter")
+ return
+ }
+ path := fmt.Sprintf("agents/auth/runs/%s", runID)
+ err = requestconfig.ExecuteNewRequest(ctx, http.MethodGet, path, nil, &res, opts...)
+ return
+}
+
+// Inspects the target site to detect logged-in state or discover required fields.
+// Returns 200 with success: true when fields are found, or 4xx/5xx for failures.
+// Requires the JWT returned by the exchange endpoint.
+func (r *AgentAuthRunService) Discover(ctx context.Context, runID string, body AgentAuthRunDiscoverParams, opts ...option.RequestOption) (res *AgentAuthDiscoverResponse, err error) {
+ opts = slices.Concat(r.Options, opts)
+ if runID == "" {
+ err = errors.New("missing required run_id parameter")
+ return
+ }
+ path := fmt.Sprintf("agents/auth/runs/%s/discover", runID)
+ err = requestconfig.ExecuteNewRequest(ctx, http.MethodPost, path, body, &res, opts...)
+ return
+}
+
+// Validates the handoff code and returns a JWT token for subsequent requests. No
+// authentication required (the handoff code serves as the credential).
+func (r *AgentAuthRunService) Exchange(ctx context.Context, runID string, body AgentAuthRunExchangeParams, opts ...option.RequestOption) (res *AgentAuthRunExchangeResponse, err error) {
+ opts = slices.Concat(r.Options, opts)
+ if runID == "" {
+ err = errors.New("missing required run_id parameter")
+ return
+ }
+ path := fmt.Sprintf("agents/auth/runs/%s/exchange", runID)
+ err = requestconfig.ExecuteNewRequest(ctx, http.MethodPost, path, body, &res, opts...)
+ return
+}
+
+// Submits field values for the discovered login form and may return additional
+// auth fields or success. Requires the JWT returned by the exchange endpoint.
+func (r *AgentAuthRunService) Submit(ctx context.Context, runID string, body AgentAuthRunSubmitParams, opts ...option.RequestOption) (res *AgentAuthSubmitResponse, err error) {
+ opts = slices.Concat(r.Options, opts)
+ if runID == "" {
+ err = errors.New("missing required run_id parameter")
+ return
+ }
+ path := fmt.Sprintf("agents/auth/runs/%s/submit", runID)
+ err = requestconfig.ExecuteNewRequest(ctx, http.MethodPost, path, body, &res, opts...)
+ return
+}
+
+// Response from exchange endpoint
+type AgentAuthRunExchangeResponse struct {
+ // JWT token with run_id claim (30 minute TTL)
+ Jwt string `json:"jwt,required"`
+ // Run ID
+ RunID string `json:"run_id,required"`
+ // JSON contains metadata for fields, check presence with [respjson.Field.Valid].
+ JSON struct {
+ Jwt respjson.Field
+ RunID respjson.Field
+ ExtraFields map[string]respjson.Field
+ raw string
+ } `json:"-"`
+}
+
+// Returns the unmodified JSON received from the API
+func (r AgentAuthRunExchangeResponse) RawJSON() string { return r.JSON.raw }
+func (r *AgentAuthRunExchangeResponse) UnmarshalJSON(data []byte) error {
+ return apijson.UnmarshalRoot(data, r)
+}
+
+type AgentAuthRunDiscoverParams struct {
+ paramObj
+}
+
+func (r AgentAuthRunDiscoverParams) MarshalJSON() (data []byte, err error) {
+ type shadow AgentAuthRunDiscoverParams
+ return param.MarshalObject(r, (*shadow)(&r))
+}
+func (r *AgentAuthRunDiscoverParams) UnmarshalJSON(data []byte) error {
+ return apijson.UnmarshalRoot(data, r)
+}
+
+type AgentAuthRunExchangeParams struct {
+ // Handoff code from start endpoint
+ Code string `json:"code,required"`
+ paramObj
+}
+
+func (r AgentAuthRunExchangeParams) MarshalJSON() (data []byte, err error) {
+ type shadow AgentAuthRunExchangeParams
+ return param.MarshalObject(r, (*shadow)(&r))
+}
+func (r *AgentAuthRunExchangeParams) UnmarshalJSON(data []byte) error {
+ return apijson.UnmarshalRoot(data, r)
+}
+
+type AgentAuthRunSubmitParams struct {
+ // Values for the discovered login fields
+ FieldValues map[string]string `json:"field_values,omitzero,required"`
+ paramObj
+}
+
+func (r AgentAuthRunSubmitParams) MarshalJSON() (data []byte, err error) {
+ type shadow AgentAuthRunSubmitParams
+ return param.MarshalObject(r, (*shadow)(&r))
+}
+func (r *AgentAuthRunSubmitParams) UnmarshalJSON(data []byte) error {
+ return apijson.UnmarshalRoot(data, r)
+}
diff --git a/agentauthrun_test.go b/agentauthrun_test.go
new file mode 100644
index 0000000..b0b7603
--- /dev/null
+++ b/agentauthrun_test.go
@@ -0,0 +1,125 @@
+// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+package kernel_test
+
+import (
+ "context"
+ "errors"
+ "os"
+ "testing"
+
+ "github.com/onkernel/kernel-go-sdk"
+ "github.com/onkernel/kernel-go-sdk/internal/testutil"
+ "github.com/onkernel/kernel-go-sdk/option"
+)
+
+func TestAgentAuthRunGet(t *testing.T) {
+ t.Skip("Prism 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.Agents.Auth.Runs.Get(context.TODO(), "run_id")
+ 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 TestAgentAuthRunDiscover(t *testing.T) {
+ t.Skip("Prism 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.Agents.Auth.Runs.Discover(
+ context.TODO(),
+ "run_id",
+ kernel.AgentAuthRunDiscoverParams{},
+ )
+ 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 TestAgentAuthRunExchange(t *testing.T) {
+ t.Skip("Prism 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.Agents.Auth.Runs.Exchange(
+ context.TODO(),
+ "run_id",
+ kernel.AgentAuthRunExchangeParams{
+ Code: "otp_abc123xyz",
+ },
+ )
+ 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 TestAgentAuthRunSubmit(t *testing.T) {
+ t.Skip("Prism 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.Agents.Auth.Runs.Submit(
+ context.TODO(),
+ "run_id",
+ kernel.AgentAuthRunSubmitParams{
+ FieldValues: map[string]string{
+ "email": "user@example.com",
+ "password": "********",
+ },
+ },
+ )
+ 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/api.md b/api.md
index 86298d1..0ca64d4 100644
--- a/api.md
+++ b/api.md
@@ -218,3 +218,32 @@ Methods:
- client.Extensions.Download(ctx context.Context, idOrName string) (http.Response, error)
- client.Extensions.DownloadFromChromeStore(ctx context.Context, query kernel.ExtensionDownloadFromChromeStoreParams) (http.Response, error)
- client.Extensions.Upload(ctx context.Context, body kernel.ExtensionUploadParams) (kernel.ExtensionUploadResponse, error)
+
+# Agents
+
+## Auth
+
+Response Types:
+
+- kernel.AgentAuthDiscoverResponse
+- kernel.AgentAuthRunResponse
+- kernel.AgentAuthStartResponse
+- kernel.AgentAuthSubmitResponse
+- kernel.DiscoveredField
+
+Methods:
+
+- client.Agents.Auth.Start(ctx context.Context, body kernel.AgentAuthStartParams) (kernel.AgentAuthStartResponse, error)
+
+### Runs
+
+Response Types:
+
+- kernel.AgentAuthRunExchangeResponse
+
+Methods:
+
+- client.Agents.Auth.Runs.Get(ctx context.Context, runID string) (kernel.AgentAuthRunResponse, error)
+- client.Agents.Auth.Runs.Discover(ctx context.Context, runID string, body kernel.AgentAuthRunDiscoverParams) (kernel.AgentAuthDiscoverResponse, error)
+- client.Agents.Auth.Runs.Exchange(ctx context.Context, runID string, body kernel.AgentAuthRunExchangeParams) (kernel.AgentAuthRunExchangeResponse, error)
+- client.Agents.Auth.Runs.Submit(ctx context.Context, runID string, body kernel.AgentAuthRunSubmitParams) (kernel.AgentAuthSubmitResponse, error)
diff --git a/client.go b/client.go
index 0e27e7b..39e85fe 100644
--- a/client.go
+++ b/client.go
@@ -24,6 +24,7 @@ type Client struct {
Profiles ProfileService
Proxies ProxyService
Extensions ExtensionService
+ Agents AgentService
}
// DefaultClientOptions read from the environment (KERNEL_API_KEY,
@@ -55,6 +56,7 @@ func NewClient(opts ...option.RequestOption) (r Client) {
r.Profiles = NewProfileService(opts...)
r.Proxies = NewProxyService(opts...)
r.Extensions = NewExtensionService(opts...)
+ r.Agents = NewAgentService(opts...)
return
}
From 79d7b82bd4312be0d1a19c60ce20c0380487783f Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Tue, 25 Nov 2025 18:13:13 +0000
Subject: [PATCH 2/7] codegen metadata
---
.stats.yml | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/.stats.yml b/.stats.yml
index bdbede3..fa4f900 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,4 +1,4 @@
configured_endpoints: 71
-openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-bb3f37e55117a56e7a4208bd646d3a68adeb651ced8531e13fbfc1fc9dcb05a4.yml
-openapi_spec_hash: 7303ce8ce3130e16a6a5c2bb49e43e9b
+openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-ae9ed0d949aa701dd3873e49080fe923404a8869ffcb69b7c912a3f244d0236d.yml
+openapi_spec_hash: 654d6e13a8bfe2103b373c668f43b33d
config_hash: be146470fb2d4583b6533859f0fa48f5
From cc2179535a7cc9a8059222b14fc68e085ac6acbd Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Wed, 26 Nov 2025 00:27:18 +0000
Subject: [PATCH 3/7] codegen metadata
---
.stats.yml | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/.stats.yml b/.stats.yml
index fa4f900..541095f 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,4 +1,4 @@
configured_endpoints: 71
-openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-ae9ed0d949aa701dd3873e49080fe923404a8869ffcb69b7c912a3f244d0236d.yml
-openapi_spec_hash: 654d6e13a8bfe2103b373c668f43b33d
+openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-2a63841293bec1bb651c5a24a95b2e9b5c07851dec1164de1aa2f87dafc51046.yml
+openapi_spec_hash: d0bb3ca22c10b79758d503f717dd8e2f
config_hash: be146470fb2d4583b6533859f0fa48f5
From 2445191106e2a61cea4d72783281e76505dca890 Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Tue, 2 Dec 2025 01:22:03 +0000
Subject: [PATCH 4/7] codegen metadata
---
.stats.yml | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/.stats.yml b/.stats.yml
index 541095f..a6b35ee 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,4 +1,4 @@
configured_endpoints: 71
-openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-2a63841293bec1bb651c5a24a95b2e9b5c07851dec1164de1aa2f87dafc51046.yml
-openapi_spec_hash: d0bb3ca22c10b79758d503f717dd8e2f
+openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-92b20a9e4650f645d3bb23b64f4ae72287bb41d3922ff1371426a91879186362.yml
+openapi_spec_hash: a3c5f41d36734c980bc5313ee60b97cf
config_hash: be146470fb2d4583b6533859f0fa48f5
From 69dcf3471d1b8b7b6fb8210da6d9c0b42ab1f1e7 Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Tue, 2 Dec 2025 20:24:19 +0000
Subject: [PATCH 5/7] feat: Browser pools sdk release
---
.stats.yml | 8 +-
agent.go | 28 ---
agentauth.go | 267 ------------------------
agentauth_test.go | 44 ----
agentauthrun.go | 150 --------------
agentauthrun_test.go | 125 ------------
aliases.go | 50 +++++
api.md | 46 +++--
browser.go | 180 +----------------
browser_test.go | 7 +-
browserpool.go | 471 +++++++++++++++++++++++++++++++++++++++++++
browserpool_test.go | 279 +++++++++++++++++++++++++
client.go | 20 +-
shared/shared.go | 182 +++++++++++++++++
14 files changed, 1033 insertions(+), 824 deletions(-)
delete mode 100644 agent.go
delete mode 100644 agentauth.go
delete mode 100644 agentauth_test.go
delete mode 100644 agentauthrun.go
delete mode 100644 agentauthrun_test.go
create mode 100644 browserpool.go
create mode 100644 browserpool_test.go
diff --git a/.stats.yml b/.stats.yml
index a6b35ee..c32f96d 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,4 +1,4 @@
-configured_endpoints: 71
-openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-92b20a9e4650f645d3bb23b64f4ae72287bb41d3922ff1371426a91879186362.yml
-openapi_spec_hash: a3c5f41d36734c980bc5313ee60b97cf
-config_hash: be146470fb2d4583b6533859f0fa48f5
+configured_endpoints: 74
+openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-340c8f009b71922347d4c238c8715cd752c8965abfa12cbb1ffabe35edc338a8.yml
+openapi_spec_hash: efc13ab03ef89cc07333db8ab5345f31
+config_hash: a4124701ae0a474e580d7416adbcfb00
diff --git a/agent.go b/agent.go
deleted file mode 100644
index d91fa4e..0000000
--- a/agent.go
+++ /dev/null
@@ -1,28 +0,0 @@
-// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-package kernel
-
-import (
- "github.com/onkernel/kernel-go-sdk/option"
-)
-
-// AgentService 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 [NewAgentService] method instead.
-type AgentService struct {
- Options []option.RequestOption
- Auth AgentAuthService
-}
-
-// NewAgentService 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 NewAgentService(opts ...option.RequestOption) (r AgentService) {
- r = AgentService{}
- r.Options = opts
- r.Auth = NewAgentAuthService(opts...)
- return
-}
diff --git a/agentauth.go b/agentauth.go
deleted file mode 100644
index 373ecb6..0000000
--- a/agentauth.go
+++ /dev/null
@@ -1,267 +0,0 @@
-// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-package kernel
-
-import (
- "context"
- "net/http"
- "slices"
- "time"
-
- "github.com/onkernel/kernel-go-sdk/internal/apijson"
- "github.com/onkernel/kernel-go-sdk/internal/requestconfig"
- "github.com/onkernel/kernel-go-sdk/option"
- "github.com/onkernel/kernel-go-sdk/packages/param"
- "github.com/onkernel/kernel-go-sdk/packages/respjson"
-)
-
-// AgentAuthService 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 [NewAgentAuthService] method instead.
-type AgentAuthService struct {
- Options []option.RequestOption
- Runs AgentAuthRunService
-}
-
-// NewAgentAuthService 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 NewAgentAuthService(opts ...option.RequestOption) (r AgentAuthService) {
- r = AgentAuthService{}
- r.Options = opts
- r.Runs = NewAgentAuthRunService(opts...)
- return
-}
-
-// Creates a browser session and returns a handoff code for the hosted flow. Uses
-// standard API key or JWT authentication (not the JWT returned by the exchange
-// endpoint).
-func (r *AgentAuthService) Start(ctx context.Context, body AgentAuthStartParams, opts ...option.RequestOption) (res *AgentAuthStartResponse, err error) {
- opts = slices.Concat(r.Options, opts)
- path := "agents/auth/start"
- err = requestconfig.ExecuteNewRequest(ctx, http.MethodPost, path, body, &res, opts...)
- return
-}
-
-// Response from discover endpoint matching AuthBlueprint schema
-type AgentAuthDiscoverResponse struct {
- // Whether discovery succeeded
- Success bool `json:"success,required"`
- // Error message if discovery failed
- ErrorMessage string `json:"error_message"`
- // Discovered form fields (present when success is true)
- Fields []DiscoveredField `json:"fields"`
- // Whether user is already logged in
- LoggedIn bool `json:"logged_in"`
- // URL of the discovered login page
- LoginURL string `json:"login_url" format:"uri"`
- // Title of the login page
- PageTitle string `json:"page_title"`
- // JSON contains metadata for fields, check presence with [respjson.Field.Valid].
- JSON struct {
- Success respjson.Field
- ErrorMessage respjson.Field
- Fields respjson.Field
- LoggedIn respjson.Field
- LoginURL respjson.Field
- PageTitle respjson.Field
- ExtraFields map[string]respjson.Field
- raw string
- } `json:"-"`
-}
-
-// Returns the unmodified JSON received from the API
-func (r AgentAuthDiscoverResponse) RawJSON() string { return r.JSON.raw }
-func (r *AgentAuthDiscoverResponse) UnmarshalJSON(data []byte) error {
- return apijson.UnmarshalRoot(data, r)
-}
-
-// Response from get run endpoint
-type AgentAuthRunResponse struct {
- // App name (org name at time of run creation)
- AppName string `json:"app_name,required"`
- // When the handoff code expires
- ExpiresAt time.Time `json:"expires_at,required" format:"date-time"`
- // Run status
- //
- // Any of "ACTIVE", "ENDED", "EXPIRED", "CANCELED".
- Status AgentAuthRunResponseStatus `json:"status,required"`
- // Target domain for authentication
- TargetDomain string `json:"target_domain,required"`
- // JSON contains metadata for fields, check presence with [respjson.Field.Valid].
- JSON struct {
- AppName respjson.Field
- ExpiresAt respjson.Field
- Status respjson.Field
- TargetDomain respjson.Field
- ExtraFields map[string]respjson.Field
- raw string
- } `json:"-"`
-}
-
-// Returns the unmodified JSON received from the API
-func (r AgentAuthRunResponse) RawJSON() string { return r.JSON.raw }
-func (r *AgentAuthRunResponse) UnmarshalJSON(data []byte) error {
- return apijson.UnmarshalRoot(data, r)
-}
-
-// Run status
-type AgentAuthRunResponseStatus string
-
-const (
- AgentAuthRunResponseStatusActive AgentAuthRunResponseStatus = "ACTIVE"
- AgentAuthRunResponseStatusEnded AgentAuthRunResponseStatus = "ENDED"
- AgentAuthRunResponseStatusExpired AgentAuthRunResponseStatus = "EXPIRED"
- AgentAuthRunResponseStatusCanceled AgentAuthRunResponseStatus = "CANCELED"
-)
-
-// Response from starting an agent authentication run
-type AgentAuthStartResponse struct {
- // When the handoff code expires
- ExpiresAt time.Time `json:"expires_at,required" format:"date-time"`
- // One-time code for handoff
- HandoffCode string `json:"handoff_code,required"`
- // URL to redirect user to
- HostedURL string `json:"hosted_url,required" format:"uri"`
- // Unique identifier for the run
- RunID string `json:"run_id,required"`
- // JSON contains metadata for fields, check presence with [respjson.Field.Valid].
- JSON struct {
- ExpiresAt respjson.Field
- HandoffCode respjson.Field
- HostedURL respjson.Field
- RunID respjson.Field
- ExtraFields map[string]respjson.Field
- raw string
- } `json:"-"`
-}
-
-// Returns the unmodified JSON received from the API
-func (r AgentAuthStartResponse) RawJSON() string { return r.JSON.raw }
-func (r *AgentAuthStartResponse) UnmarshalJSON(data []byte) error {
- return apijson.UnmarshalRoot(data, r)
-}
-
-// Response from submit endpoint matching SubmitResult schema
-type AgentAuthSubmitResponse struct {
- // Whether submission succeeded
- Success bool `json:"success,required"`
- // Additional fields needed (e.g., OTP) - present when needs_additional_auth is
- // true
- AdditionalFields []DiscoveredField `json:"additional_fields"`
- // App name (only present when logged_in is true)
- AppName string `json:"app_name"`
- // Error message if submission failed
- ErrorMessage string `json:"error_message"`
- // Whether user is now logged in
- LoggedIn bool `json:"logged_in"`
- // Whether additional authentication fields are needed
- NeedsAdditionalAuth bool `json:"needs_additional_auth"`
- // Target domain (only present when logged_in is true)
- TargetDomain string `json:"target_domain"`
- // JSON contains metadata for fields, check presence with [respjson.Field.Valid].
- JSON struct {
- Success respjson.Field
- AdditionalFields respjson.Field
- AppName respjson.Field
- ErrorMessage respjson.Field
- LoggedIn respjson.Field
- NeedsAdditionalAuth respjson.Field
- TargetDomain respjson.Field
- ExtraFields map[string]respjson.Field
- raw string
- } `json:"-"`
-}
-
-// Returns the unmodified JSON received from the API
-func (r AgentAuthSubmitResponse) RawJSON() string { return r.JSON.raw }
-func (r *AgentAuthSubmitResponse) UnmarshalJSON(data []byte) error {
- return apijson.UnmarshalRoot(data, r)
-}
-
-// A discovered form field
-type DiscoveredField struct {
- // Field label
- Label string `json:"label,required"`
- // Field name
- Name string `json:"name,required"`
- // CSS selector for the field
- Selector string `json:"selector,required"`
- // Field type
- //
- // Any of "text", "email", "password", "tel", "number", "url", "code", "checkbox".
- Type DiscoveredFieldType `json:"type,required"`
- // Field placeholder
- Placeholder string `json:"placeholder"`
- // Whether field is required
- Required bool `json:"required"`
- // JSON contains metadata for fields, check presence with [respjson.Field.Valid].
- JSON struct {
- Label respjson.Field
- Name respjson.Field
- Selector respjson.Field
- Type respjson.Field
- Placeholder respjson.Field
- Required respjson.Field
- ExtraFields map[string]respjson.Field
- raw string
- } `json:"-"`
-}
-
-// Returns the unmodified JSON received from the API
-func (r DiscoveredField) RawJSON() string { return r.JSON.raw }
-func (r *DiscoveredField) UnmarshalJSON(data []byte) error {
- return apijson.UnmarshalRoot(data, r)
-}
-
-// Field type
-type DiscoveredFieldType string
-
-const (
- DiscoveredFieldTypeText DiscoveredFieldType = "text"
- DiscoveredFieldTypeEmail DiscoveredFieldType = "email"
- DiscoveredFieldTypePassword DiscoveredFieldType = "password"
- DiscoveredFieldTypeTel DiscoveredFieldType = "tel"
- DiscoveredFieldTypeNumber DiscoveredFieldType = "number"
- DiscoveredFieldTypeURL DiscoveredFieldType = "url"
- DiscoveredFieldTypeCode DiscoveredFieldType = "code"
- DiscoveredFieldTypeCheckbox DiscoveredFieldType = "checkbox"
-)
-
-type AgentAuthStartParams struct {
- // Name of the profile to use for this flow
- ProfileName string `json:"profile_name,required"`
- // Target domain for authentication
- TargetDomain string `json:"target_domain,required"`
- // Optional logo URL for the application
- AppLogoURL param.Opt[string] `json:"app_logo_url,omitzero" format:"uri"`
- // Optional proxy configuration
- Proxy AgentAuthStartParamsProxy `json:"proxy,omitzero"`
- paramObj
-}
-
-func (r AgentAuthStartParams) MarshalJSON() (data []byte, err error) {
- type shadow AgentAuthStartParams
- return param.MarshalObject(r, (*shadow)(&r))
-}
-func (r *AgentAuthStartParams) UnmarshalJSON(data []byte) error {
- return apijson.UnmarshalRoot(data, r)
-}
-
-// Optional proxy configuration
-type AgentAuthStartParamsProxy struct {
- // ID of the proxy to use
- ProxyID param.Opt[string] `json:"proxy_id,omitzero"`
- paramObj
-}
-
-func (r AgentAuthStartParamsProxy) MarshalJSON() (data []byte, err error) {
- type shadow AgentAuthStartParamsProxy
- return param.MarshalObject(r, (*shadow)(&r))
-}
-func (r *AgentAuthStartParamsProxy) UnmarshalJSON(data []byte) error {
- return apijson.UnmarshalRoot(data, r)
-}
diff --git a/agentauth_test.go b/agentauth_test.go
deleted file mode 100644
index ab734e1..0000000
--- a/agentauth_test.go
+++ /dev/null
@@ -1,44 +0,0 @@
-// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-package kernel_test
-
-import (
- "context"
- "errors"
- "os"
- "testing"
-
- "github.com/onkernel/kernel-go-sdk"
- "github.com/onkernel/kernel-go-sdk/internal/testutil"
- "github.com/onkernel/kernel-go-sdk/option"
-)
-
-func TestAgentAuthStartWithOptionalParams(t *testing.T) {
- t.Skip("Prism 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.Agents.Auth.Start(context.TODO(), kernel.AgentAuthStartParams{
- ProfileName: "auth-abc123",
- TargetDomain: "doordash.com",
- AppLogoURL: kernel.String("https://example.com/logo.png"),
- Proxy: kernel.AgentAuthStartParamsProxy{
- ProxyID: kernel.String("proxy_id"),
- },
- })
- 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/agentauthrun.go b/agentauthrun.go
deleted file mode 100644
index da62724..0000000
--- a/agentauthrun.go
+++ /dev/null
@@ -1,150 +0,0 @@
-// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-package kernel
-
-import (
- "context"
- "errors"
- "fmt"
- "net/http"
- "slices"
-
- "github.com/onkernel/kernel-go-sdk/internal/apijson"
- "github.com/onkernel/kernel-go-sdk/internal/requestconfig"
- "github.com/onkernel/kernel-go-sdk/option"
- "github.com/onkernel/kernel-go-sdk/packages/param"
- "github.com/onkernel/kernel-go-sdk/packages/respjson"
-)
-
-// AgentAuthRunService 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 [NewAgentAuthRunService] method instead.
-type AgentAuthRunService struct {
- Options []option.RequestOption
-}
-
-// NewAgentAuthRunService 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 NewAgentAuthRunService(opts ...option.RequestOption) (r AgentAuthRunService) {
- r = AgentAuthRunService{}
- r.Options = opts
- return
-}
-
-// Returns run details including app_name and target_domain. Uses the JWT returned
-// by the exchange endpoint, or standard API key or JWT authentication.
-func (r *AgentAuthRunService) Get(ctx context.Context, runID string, opts ...option.RequestOption) (res *AgentAuthRunResponse, err error) {
- opts = slices.Concat(r.Options, opts)
- if runID == "" {
- err = errors.New("missing required run_id parameter")
- return
- }
- path := fmt.Sprintf("agents/auth/runs/%s", runID)
- err = requestconfig.ExecuteNewRequest(ctx, http.MethodGet, path, nil, &res, opts...)
- return
-}
-
-// Inspects the target site to detect logged-in state or discover required fields.
-// Returns 200 with success: true when fields are found, or 4xx/5xx for failures.
-// Requires the JWT returned by the exchange endpoint.
-func (r *AgentAuthRunService) Discover(ctx context.Context, runID string, body AgentAuthRunDiscoverParams, opts ...option.RequestOption) (res *AgentAuthDiscoverResponse, err error) {
- opts = slices.Concat(r.Options, opts)
- if runID == "" {
- err = errors.New("missing required run_id parameter")
- return
- }
- path := fmt.Sprintf("agents/auth/runs/%s/discover", runID)
- err = requestconfig.ExecuteNewRequest(ctx, http.MethodPost, path, body, &res, opts...)
- return
-}
-
-// Validates the handoff code and returns a JWT token for subsequent requests. No
-// authentication required (the handoff code serves as the credential).
-func (r *AgentAuthRunService) Exchange(ctx context.Context, runID string, body AgentAuthRunExchangeParams, opts ...option.RequestOption) (res *AgentAuthRunExchangeResponse, err error) {
- opts = slices.Concat(r.Options, opts)
- if runID == "" {
- err = errors.New("missing required run_id parameter")
- return
- }
- path := fmt.Sprintf("agents/auth/runs/%s/exchange", runID)
- err = requestconfig.ExecuteNewRequest(ctx, http.MethodPost, path, body, &res, opts...)
- return
-}
-
-// Submits field values for the discovered login form and may return additional
-// auth fields or success. Requires the JWT returned by the exchange endpoint.
-func (r *AgentAuthRunService) Submit(ctx context.Context, runID string, body AgentAuthRunSubmitParams, opts ...option.RequestOption) (res *AgentAuthSubmitResponse, err error) {
- opts = slices.Concat(r.Options, opts)
- if runID == "" {
- err = errors.New("missing required run_id parameter")
- return
- }
- path := fmt.Sprintf("agents/auth/runs/%s/submit", runID)
- err = requestconfig.ExecuteNewRequest(ctx, http.MethodPost, path, body, &res, opts...)
- return
-}
-
-// Response from exchange endpoint
-type AgentAuthRunExchangeResponse struct {
- // JWT token with run_id claim (30 minute TTL)
- Jwt string `json:"jwt,required"`
- // Run ID
- RunID string `json:"run_id,required"`
- // JSON contains metadata for fields, check presence with [respjson.Field.Valid].
- JSON struct {
- Jwt respjson.Field
- RunID respjson.Field
- ExtraFields map[string]respjson.Field
- raw string
- } `json:"-"`
-}
-
-// Returns the unmodified JSON received from the API
-func (r AgentAuthRunExchangeResponse) RawJSON() string { return r.JSON.raw }
-func (r *AgentAuthRunExchangeResponse) UnmarshalJSON(data []byte) error {
- return apijson.UnmarshalRoot(data, r)
-}
-
-type AgentAuthRunDiscoverParams struct {
- paramObj
-}
-
-func (r AgentAuthRunDiscoverParams) MarshalJSON() (data []byte, err error) {
- type shadow AgentAuthRunDiscoverParams
- return param.MarshalObject(r, (*shadow)(&r))
-}
-func (r *AgentAuthRunDiscoverParams) UnmarshalJSON(data []byte) error {
- return apijson.UnmarshalRoot(data, r)
-}
-
-type AgentAuthRunExchangeParams struct {
- // Handoff code from start endpoint
- Code string `json:"code,required"`
- paramObj
-}
-
-func (r AgentAuthRunExchangeParams) MarshalJSON() (data []byte, err error) {
- type shadow AgentAuthRunExchangeParams
- return param.MarshalObject(r, (*shadow)(&r))
-}
-func (r *AgentAuthRunExchangeParams) UnmarshalJSON(data []byte) error {
- return apijson.UnmarshalRoot(data, r)
-}
-
-type AgentAuthRunSubmitParams struct {
- // Values for the discovered login fields
- FieldValues map[string]string `json:"field_values,omitzero,required"`
- paramObj
-}
-
-func (r AgentAuthRunSubmitParams) MarshalJSON() (data []byte, err error) {
- type shadow AgentAuthRunSubmitParams
- return param.MarshalObject(r, (*shadow)(&r))
-}
-func (r *AgentAuthRunSubmitParams) UnmarshalJSON(data []byte) error {
- return apijson.UnmarshalRoot(data, r)
-}
diff --git a/agentauthrun_test.go b/agentauthrun_test.go
deleted file mode 100644
index b0b7603..0000000
--- a/agentauthrun_test.go
+++ /dev/null
@@ -1,125 +0,0 @@
-// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-package kernel_test
-
-import (
- "context"
- "errors"
- "os"
- "testing"
-
- "github.com/onkernel/kernel-go-sdk"
- "github.com/onkernel/kernel-go-sdk/internal/testutil"
- "github.com/onkernel/kernel-go-sdk/option"
-)
-
-func TestAgentAuthRunGet(t *testing.T) {
- t.Skip("Prism 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.Agents.Auth.Runs.Get(context.TODO(), "run_id")
- 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 TestAgentAuthRunDiscover(t *testing.T) {
- t.Skip("Prism 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.Agents.Auth.Runs.Discover(
- context.TODO(),
- "run_id",
- kernel.AgentAuthRunDiscoverParams{},
- )
- 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 TestAgentAuthRunExchange(t *testing.T) {
- t.Skip("Prism 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.Agents.Auth.Runs.Exchange(
- context.TODO(),
- "run_id",
- kernel.AgentAuthRunExchangeParams{
- Code: "otp_abc123xyz",
- },
- )
- 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 TestAgentAuthRunSubmit(t *testing.T) {
- t.Skip("Prism 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.Agents.Auth.Runs.Submit(
- context.TODO(),
- "run_id",
- kernel.AgentAuthRunSubmitParams{
- FieldValues: map[string]string{
- "email": "user@example.com",
- "password": "********",
- },
- },
- )
- 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/aliases.go b/aliases.go
index 2621045..d7a4818 100644
--- a/aliases.go
+++ b/aliases.go
@@ -21,6 +21,56 @@ type Error = apierror.Error
// This is an alias to an internal type.
type AppAction = shared.AppAction
+// Extension selection for the browser session. Provide either id or name of an
+// extension uploaded to Kernel.
+//
+// This is an alias to an internal type.
+type BrowserExtension = shared.BrowserExtension
+
+// Extension selection for the browser session. Provide either id or name of an
+// extension uploaded to Kernel.
+//
+// This is an alias to an internal type.
+type BrowserExtensionParam = shared.BrowserExtensionParam
+
+// 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.
+//
+// This is an alias to an internal type.
+type BrowserProfile = shared.BrowserProfile
+
+// 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.
+//
+// This is an alias to an internal type.
+type BrowserProfileParam = shared.BrowserProfileParam
+
+// Initial browser window size in pixels with optional refresh rate. If omitted,
+// image defaults apply (commonly 1024x768@60). Only specific viewport
+// configurations are supported. The server will reject unsupported combinations.
+// Supported resolutions are: 2560x1440@10, 1920x1080@25, 1920x1200@25,
+// 1440x900@25, 1024x768@60, 1200x800@60 If refresh_rate is not provided, it will
+// be automatically determined from the width and height if they match a supported
+// configuration exactly. Note: Higher resolutions may affect the responsiveness of
+// live view browser
+//
+// This is an alias to an internal type.
+type BrowserViewport = shared.BrowserViewport
+
+// Initial browser window size in pixels with optional refresh rate. If omitted,
+// image defaults apply (commonly 1024x768@60). Only specific viewport
+// configurations are supported. The server will reject unsupported combinations.
+// Supported resolutions are: 2560x1440@10, 1920x1080@25, 1920x1200@25,
+// 1440x900@25, 1024x768@60, 1200x800@60 If refresh_rate is not provided, it will
+// be automatically determined from the width and height if they match a supported
+// configuration exactly. Note: Higher resolutions may affect the responsiveness of
+// live view browser
+//
+// This is an alias to an internal type.
+type BrowserViewportParam = shared.BrowserViewportParam
+
// This is an alias to an internal type.
type ErrorDetail = shared.ErrorDetail
diff --git a/api.md b/api.md
index 0ca64d4..aa0d086 100644
--- a/api.md
+++ b/api.md
@@ -1,6 +1,15 @@
+# Shared Params Types
+
+- shared.BrowserExtensionParam
+- shared.BrowserProfileParam
+- shared.BrowserViewportParam
+
# Shared Response Types
- shared.AppAction
+- shared.BrowserExtension
+- shared.BrowserProfile
+- shared.BrowserViewport
- shared.ErrorDetail
- shared.ErrorEvent
- shared.ErrorModel
@@ -219,31 +228,28 @@ Methods:
- client.Extensions.DownloadFromChromeStore(ctx context.Context, query kernel.ExtensionDownloadFromChromeStoreParams) (http.Response, error)
- client.Extensions.Upload(ctx context.Context, body kernel.ExtensionUploadParams) (kernel.ExtensionUploadResponse, error)
-# Agents
-
-## Auth
-
-Response Types:
+# BrowserPools
-- kernel.AgentAuthDiscoverResponse
-- kernel.AgentAuthRunResponse
-- kernel.AgentAuthStartResponse
-- kernel.AgentAuthSubmitResponse
-- kernel.DiscoveredField
-
-Methods:
-
-- client.Agents.Auth.Start(ctx context.Context, body kernel.AgentAuthStartParams) (kernel.AgentAuthStartResponse, error)
+Params Types:
-### Runs
+- kernel.BrowserPoolAcquireRequestParam
+- kernel.BrowserPoolReleaseRequestParam
+- kernel.BrowserPoolRequestParam
+- kernel.BrowserPoolUpdateRequestParam
Response Types:
-- kernel.AgentAuthRunExchangeResponse
+- kernel.BrowserPool
+- kernel.BrowserPoolRequest
+- kernel.BrowserPoolAcquireResponse
Methods:
-- client.Agents.Auth.Runs.Get(ctx context.Context, runID string) (kernel.AgentAuthRunResponse, error)
-- client.Agents.Auth.Runs.Discover(ctx context.Context, runID string, body kernel.AgentAuthRunDiscoverParams) (kernel.AgentAuthDiscoverResponse, error)
-- client.Agents.Auth.Runs.Exchange(ctx context.Context, runID string, body kernel.AgentAuthRunExchangeParams) (kernel.AgentAuthRunExchangeResponse, error)
-- client.Agents.Auth.Runs.Submit(ctx context.Context, runID string, body kernel.AgentAuthRunSubmitParams) (kernel.AgentAuthSubmitResponse, error)
+- client.BrowserPools.New(ctx context.Context, body kernel.BrowserPoolNewParams) (kernel.BrowserPool, error)
+- client.BrowserPools.Get(ctx context.Context, idOrName string) (kernel.BrowserPool, error)
+- client.BrowserPools.Update(ctx context.Context, idOrName string, body kernel.BrowserPoolUpdateParams) (kernel.BrowserPool, error)
+- client.BrowserPools.List(ctx context.Context) ([]kernel.BrowserPool, error)
+- client.BrowserPools.Delete(ctx context.Context, idOrName string, body kernel.BrowserPoolDeleteParams) error
+- client.BrowserPools.Acquire(ctx context.Context, idOrName string, body kernel.BrowserPoolAcquireParams) (kernel.BrowserPoolAcquireResponse, error)
+- client.BrowserPools.Flush(ctx context.Context, idOrName string) error
+- client.BrowserPools.Release(ctx context.Context, idOrName string, body kernel.BrowserPoolReleaseParams) error
diff --git a/browser.go b/browser.go
index a172b4d..fc9f55c 100644
--- a/browser.go
+++ b/browser.go
@@ -23,6 +23,7 @@ import (
"github.com/onkernel/kernel-go-sdk/packages/pagination"
"github.com/onkernel/kernel-go-sdk/packages/param"
"github.com/onkernel/kernel-go-sdk/packages/respjson"
+ "github.com/onkernel/kernel-go-sdk/shared"
)
// BrowserService contains methods and other services that help with interacting
@@ -245,7 +246,7 @@ type BrowserNewResponse struct {
// be automatically determined from the width and height if they match a supported
// configuration exactly. Note: Higher resolutions may affect the responsiveness of
// live view browser
- Viewport BrowserNewResponseViewport `json:"viewport"`
+ Viewport shared.BrowserViewport `json:"viewport"`
// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
JSON struct {
CdpWsURL respjson.Field
@@ -272,38 +273,6 @@ func (r *BrowserNewResponse) UnmarshalJSON(data []byte) error {
return apijson.UnmarshalRoot(data, r)
}
-// Initial browser window size in pixels with optional refresh rate. If omitted,
-// image defaults apply (commonly 1024x768@60). Only specific viewport
-// configurations are supported. The server will reject unsupported combinations.
-// Supported resolutions are: 2560x1440@10, 1920x1080@25, 1920x1200@25,
-// 1440x900@25, 1024x768@60, 1200x800@60 If refresh_rate is not provided, it will
-// be automatically determined from the width and height if they match a supported
-// configuration exactly. Note: Higher resolutions may affect the responsiveness of
-// live view browser
-type BrowserNewResponseViewport struct {
- // Browser window height in pixels.
- Height int64 `json:"height,required"`
- // Browser window width in pixels.
- Width int64 `json:"width,required"`
- // Display refresh rate in Hz. If omitted, automatically determined from width and
- // height.
- RefreshRate int64 `json:"refresh_rate"`
- // JSON contains metadata for fields, check presence with [respjson.Field.Valid].
- JSON struct {
- Height respjson.Field
- Width respjson.Field
- RefreshRate respjson.Field
- ExtraFields map[string]respjson.Field
- raw string
- } `json:"-"`
-}
-
-// Returns the unmodified JSON received from the API
-func (r BrowserNewResponseViewport) RawJSON() string { return r.JSON.raw }
-func (r *BrowserNewResponseViewport) UnmarshalJSON(data []byte) error {
- return apijson.UnmarshalRoot(data, r)
-}
-
type BrowserGetResponse struct {
// Websocket URL for Chrome DevTools Protocol connections to the browser session
CdpWsURL string `json:"cdp_ws_url,required"`
@@ -338,7 +307,7 @@ type BrowserGetResponse struct {
// be automatically determined from the width and height if they match a supported
// configuration exactly. Note: Higher resolutions may affect the responsiveness of
// live view browser
- Viewport BrowserGetResponseViewport `json:"viewport"`
+ Viewport shared.BrowserViewport `json:"viewport"`
// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
JSON struct {
CdpWsURL respjson.Field
@@ -365,38 +334,6 @@ func (r *BrowserGetResponse) UnmarshalJSON(data []byte) error {
return apijson.UnmarshalRoot(data, r)
}
-// Initial browser window size in pixels with optional refresh rate. If omitted,
-// image defaults apply (commonly 1024x768@60). Only specific viewport
-// configurations are supported. The server will reject unsupported combinations.
-// Supported resolutions are: 2560x1440@10, 1920x1080@25, 1920x1200@25,
-// 1440x900@25, 1024x768@60, 1200x800@60 If refresh_rate is not provided, it will
-// be automatically determined from the width and height if they match a supported
-// configuration exactly. Note: Higher resolutions may affect the responsiveness of
-// live view browser
-type BrowserGetResponseViewport struct {
- // Browser window height in pixels.
- Height int64 `json:"height,required"`
- // Browser window width in pixels.
- Width int64 `json:"width,required"`
- // Display refresh rate in Hz. If omitted, automatically determined from width and
- // height.
- RefreshRate int64 `json:"refresh_rate"`
- // JSON contains metadata for fields, check presence with [respjson.Field.Valid].
- JSON struct {
- Height respjson.Field
- Width respjson.Field
- RefreshRate respjson.Field
- ExtraFields map[string]respjson.Field
- raw string
- } `json:"-"`
-}
-
-// Returns the unmodified JSON received from the API
-func (r BrowserGetResponseViewport) RawJSON() string { return r.JSON.raw }
-func (r *BrowserGetResponseViewport) UnmarshalJSON(data []byte) error {
- return apijson.UnmarshalRoot(data, r)
-}
-
type BrowserListResponse struct {
// Websocket URL for Chrome DevTools Protocol connections to the browser session
CdpWsURL string `json:"cdp_ws_url,required"`
@@ -431,7 +368,7 @@ type BrowserListResponse struct {
// be automatically determined from the width and height if they match a supported
// configuration exactly. Note: Higher resolutions may affect the responsiveness of
// live view browser
- Viewport BrowserListResponseViewport `json:"viewport"`
+ Viewport shared.BrowserViewport `json:"viewport"`
// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
JSON struct {
CdpWsURL respjson.Field
@@ -458,38 +395,6 @@ func (r *BrowserListResponse) UnmarshalJSON(data []byte) error {
return apijson.UnmarshalRoot(data, r)
}
-// Initial browser window size in pixels with optional refresh rate. If omitted,
-// image defaults apply (commonly 1024x768@60). Only specific viewport
-// configurations are supported. The server will reject unsupported combinations.
-// Supported resolutions are: 2560x1440@10, 1920x1080@25, 1920x1200@25,
-// 1440x900@25, 1024x768@60, 1200x800@60 If refresh_rate is not provided, it will
-// be automatically determined from the width and height if they match a supported
-// configuration exactly. Note: Higher resolutions may affect the responsiveness of
-// live view browser
-type BrowserListResponseViewport struct {
- // Browser window height in pixels.
- Height int64 `json:"height,required"`
- // Browser window width in pixels.
- Width int64 `json:"width,required"`
- // Display refresh rate in Hz. If omitted, automatically determined from width and
- // height.
- RefreshRate int64 `json:"refresh_rate"`
- // JSON contains metadata for fields, check presence with [respjson.Field.Valid].
- JSON struct {
- Height respjson.Field
- Width respjson.Field
- RefreshRate respjson.Field
- ExtraFields map[string]respjson.Field
- raw string
- } `json:"-"`
-}
-
-// Returns the unmodified JSON received from the API
-func (r BrowserListResponseViewport) RawJSON() string { return r.JSON.raw }
-func (r *BrowserListResponseViewport) UnmarshalJSON(data []byte) error {
- return apijson.UnmarshalRoot(data, r)
-}
-
type BrowserNewParams struct {
// If true, launches the browser using a headless image (no VNC/GUI). Defaults to
// false.
@@ -513,13 +418,13 @@ type BrowserNewParams struct {
// specified value.
TimeoutSeconds param.Opt[int64] `json:"timeout_seconds,omitzero"`
// List of browser extensions to load into the session. Provide each by id or name.
- Extensions []BrowserNewParamsExtension `json:"extensions,omitzero"`
+ Extensions []shared.BrowserExtensionParam `json:"extensions,omitzero"`
// Optional persistence configuration for the browser session.
Persistence BrowserPersistenceParam `json:"persistence,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 BrowserNewParamsProfile `json:"profile,omitzero"`
+ Profile shared.BrowserProfileParam `json:"profile,omitzero"`
// Initial browser window size in pixels with optional refresh rate. If omitted,
// image defaults apply (commonly 1024x768@60). Only specific viewport
// configurations are supported. The server will reject unsupported combinations.
@@ -528,7 +433,7 @@ type BrowserNewParams struct {
// be automatically determined from the width and height if they match a supported
// configuration exactly. Note: Higher resolutions may affect the responsiveness of
// live view browser
- Viewport BrowserNewParamsViewport `json:"viewport,omitzero"`
+ Viewport shared.BrowserViewportParam `json:"viewport,omitzero"`
paramObj
}
@@ -540,77 +445,6 @@ func (r *BrowserNewParams) UnmarshalJSON(data []byte) error {
return apijson.UnmarshalRoot(data, r)
}
-// Extension selection for the browser session. Provide either id or name of an
-// extension uploaded to Kernel.
-type BrowserNewParamsExtension struct {
- // Extension ID to load for this browser session
- ID param.Opt[string] `json:"id,omitzero"`
- // Extension name to load for this browser session (instead of id). Must be 1-255
- // characters, using letters, numbers, dots, underscores, or hyphens.
- Name param.Opt[string] `json:"name,omitzero"`
- paramObj
-}
-
-func (r BrowserNewParamsExtension) MarshalJSON() (data []byte, err error) {
- type shadow BrowserNewParamsExtension
- return param.MarshalObject(r, (*shadow)(&r))
-}
-func (r *BrowserNewParamsExtension) UnmarshalJSON(data []byte) error {
- return apijson.UnmarshalRoot(data, r)
-}
-
-// 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.
-type BrowserNewParamsProfile struct {
- // Profile ID to load for this browser session
- ID param.Opt[string] `json:"id,omitzero"`
- // Profile name to load for this browser session (instead of id). Must be 1-255
- // characters, using letters, numbers, dots, underscores, or hyphens.
- Name param.Opt[string] `json:"name,omitzero"`
- // If true, save changes made during the session back to the profile when the
- // session ends.
- SaveChanges param.Opt[bool] `json:"save_changes,omitzero"`
- paramObj
-}
-
-func (r BrowserNewParamsProfile) MarshalJSON() (data []byte, err error) {
- type shadow BrowserNewParamsProfile
- return param.MarshalObject(r, (*shadow)(&r))
-}
-func (r *BrowserNewParamsProfile) UnmarshalJSON(data []byte) error {
- return apijson.UnmarshalRoot(data, r)
-}
-
-// Initial browser window size in pixels with optional refresh rate. If omitted,
-// image defaults apply (commonly 1024x768@60). Only specific viewport
-// configurations are supported. The server will reject unsupported combinations.
-// Supported resolutions are: 2560x1440@10, 1920x1080@25, 1920x1200@25,
-// 1440x900@25, 1024x768@60, 1200x800@60 If refresh_rate is not provided, it will
-// be automatically determined from the width and height if they match a supported
-// configuration exactly. Note: Higher resolutions may affect the responsiveness of
-// live view browser
-//
-// The properties Height, Width are required.
-type BrowserNewParamsViewport struct {
- // Browser window height in pixels.
- Height int64 `json:"height,required"`
- // Browser window width in pixels.
- Width int64 `json:"width,required"`
- // Display refresh rate in Hz. If omitted, automatically determined from width and
- // height.
- RefreshRate param.Opt[int64] `json:"refresh_rate,omitzero"`
- paramObj
-}
-
-func (r BrowserNewParamsViewport) MarshalJSON() (data []byte, err error) {
- type shadow BrowserNewParamsViewport
- return param.MarshalObject(r, (*shadow)(&r))
-}
-func (r *BrowserNewParamsViewport) UnmarshalJSON(data []byte) error {
- return apijson.UnmarshalRoot(data, r)
-}
-
type BrowserListParams struct {
// When true, includes soft-deleted browser sessions in the results alongside
// active sessions.
diff --git a/browser_test.go b/browser_test.go
index 96377fd..33292c5 100644
--- a/browser_test.go
+++ b/browser_test.go
@@ -13,6 +13,7 @@ import (
"github.com/onkernel/kernel-go-sdk"
"github.com/onkernel/kernel-go-sdk/internal/testutil"
"github.com/onkernel/kernel-go-sdk/option"
+ "github.com/onkernel/kernel-go-sdk/shared"
)
func TestBrowserNewWithOptionalParams(t *testing.T) {
@@ -29,7 +30,7 @@ func TestBrowserNewWithOptionalParams(t *testing.T) {
option.WithAPIKey("My API Key"),
)
_, err := client.Browsers.New(context.TODO(), kernel.BrowserNewParams{
- Extensions: []kernel.BrowserNewParamsExtension{{
+ Extensions: []shared.BrowserExtensionParam{{
ID: kernel.String("id"),
Name: kernel.String("name"),
}},
@@ -39,7 +40,7 @@ func TestBrowserNewWithOptionalParams(t *testing.T) {
Persistence: kernel.BrowserPersistenceParam{
ID: "my-awesome-browser-for-user-1234",
},
- Profile: kernel.BrowserNewParamsProfile{
+ Profile: shared.BrowserProfileParam{
ID: kernel.String("id"),
Name: kernel.String("name"),
SaveChanges: kernel.Bool(true),
@@ -47,7 +48,7 @@ func TestBrowserNewWithOptionalParams(t *testing.T) {
ProxyID: kernel.String("proxy_id"),
Stealth: kernel.Bool(true),
TimeoutSeconds: kernel.Int(10),
- Viewport: kernel.BrowserNewParamsViewport{
+ Viewport: shared.BrowserViewportParam{
Height: 800,
Width: 1280,
RefreshRate: kernel.Int(60),
diff --git a/browserpool.go b/browserpool.go
new file mode 100644
index 0000000..4001ea7
--- /dev/null
+++ b/browserpool.go
@@ -0,0 +1,471 @@
+// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+package kernel
+
+import (
+ "context"
+ "encoding/json"
+ "errors"
+ "fmt"
+ "net/http"
+ "slices"
+ "time"
+
+ "github.com/onkernel/kernel-go-sdk/internal/apijson"
+ shimjson "github.com/onkernel/kernel-go-sdk/internal/encoding/json"
+ "github.com/onkernel/kernel-go-sdk/internal/requestconfig"
+ "github.com/onkernel/kernel-go-sdk/option"
+ "github.com/onkernel/kernel-go-sdk/packages/param"
+ "github.com/onkernel/kernel-go-sdk/packages/respjson"
+ "github.com/onkernel/kernel-go-sdk/shared"
+)
+
+// BrowserPoolService 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 [NewBrowserPoolService] method instead.
+type BrowserPoolService struct {
+ Options []option.RequestOption
+}
+
+// NewBrowserPoolService 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 NewBrowserPoolService(opts ...option.RequestOption) (r BrowserPoolService) {
+ r = BrowserPoolService{}
+ r.Options = opts
+ return
+}
+
+// Create a new browser pool with the specified configuration and size.
+func (r *BrowserPoolService) New(ctx context.Context, body BrowserPoolNewParams, opts ...option.RequestOption) (res *BrowserPool, err error) {
+ opts = slices.Concat(r.Options, opts)
+ path := "browser_pools"
+ err = requestconfig.ExecuteNewRequest(ctx, http.MethodPost, path, body, &res, opts...)
+ return
+}
+
+// Retrieve details for a single browser pool by its ID or name.
+func (r *BrowserPoolService) Get(ctx context.Context, idOrName string, opts ...option.RequestOption) (res *BrowserPool, err error) {
+ opts = slices.Concat(r.Options, opts)
+ if idOrName == "" {
+ err = errors.New("missing required id_or_name parameter")
+ return
+ }
+ path := fmt.Sprintf("browser_pools/%s", idOrName)
+ err = requestconfig.ExecuteNewRequest(ctx, http.MethodGet, path, nil, &res, opts...)
+ return
+}
+
+// Updates the configuration used to create browsers in the pool.
+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 == "" {
+ err = errors.New("missing required id_or_name parameter")
+ return
+ }
+ path := fmt.Sprintf("browser_pools/%s", idOrName)
+ err = requestconfig.ExecuteNewRequest(ctx, http.MethodPatch, path, body, &res, opts...)
+ return
+}
+
+// List browser pools owned by the caller's organization.
+func (r *BrowserPoolService) List(ctx context.Context, opts ...option.RequestOption) (res *[]BrowserPool, err error) {
+ opts = slices.Concat(r.Options, opts)
+ path := "browser_pools"
+ err = requestconfig.ExecuteNewRequest(ctx, http.MethodGet, path, nil, &res, opts...)
+ return
+}
+
+// Delete a browser pool and all browsers in it. By default, deletion is blocked if
+// browsers are currently leased. Use force=true to terminate leased browsers.
+func (r *BrowserPoolService) Delete(ctx context.Context, idOrName string, body BrowserPoolDeleteParams, 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
+ }
+ path := fmt.Sprintf("browser_pools/%s", idOrName)
+ err = requestconfig.ExecuteNewRequest(ctx, http.MethodDelete, path, body, nil, opts...)
+ return
+}
+
+// Long-polling endpoint to acquire a browser from the pool. Returns immediately
+// when a browser is available, or returns 204 No Content when the poll times out.
+// The client should retry the request to continue waiting for a browser. The
+// acquired browser will use the pool's timeout_seconds for its idle timeout.
+func (r *BrowserPoolService) Acquire(ctx context.Context, idOrName string, body BrowserPoolAcquireParams, opts ...option.RequestOption) (res *BrowserPoolAcquireResponse, err error) {
+ opts = slices.Concat(r.Options, opts)
+ if idOrName == "" {
+ err = errors.New("missing required id_or_name parameter")
+ return
+ }
+ path := fmt.Sprintf("browser_pools/%s/acquire", idOrName)
+ err = requestconfig.ExecuteNewRequest(ctx, http.MethodPost, path, body, &res, opts...)
+ return
+}
+
+// Destroys all idle browsers in the pool; leased browsers are not affected.
+func (r *BrowserPoolService) Flush(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
+ }
+ path := fmt.Sprintf("browser_pools/%s/flush", idOrName)
+ err = requestconfig.ExecuteNewRequest(ctx, http.MethodPost, path, nil, nil, opts...)
+ return
+}
+
+// Release a browser back to the pool, optionally recreating the browser instance.
+func (r *BrowserPoolService) Release(ctx context.Context, idOrName string, body BrowserPoolReleaseParams, 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
+ }
+ path := fmt.Sprintf("browser_pools/%s/release", idOrName)
+ err = requestconfig.ExecuteNewRequest(ctx, http.MethodPost, path, body, nil, opts...)
+ return
+}
+
+// A browser pool containing multiple identically configured browsers.
+type BrowserPool struct {
+ // Unique identifier for the browser pool
+ ID string `json:"id,required"`
+ // Number of browsers currently acquired from the pool
+ AcquiredCount int64 `json:"acquired_count,required"`
+ // Number of browsers currently available in the pool
+ AvailableCount int64 `json:"available_count,required"`
+ // Configuration used to create all browsers in this pool
+ BrowserPoolConfig BrowserPoolRequest `json:"browser_pool_config,required"`
+ // Timestamp when the browser pool was created
+ CreatedAt time.Time `json:"created_at,required" format:"date-time"`
+ // Browser pool name, if set
+ Name string `json:"name"`
+ // 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
+ Name respjson.Field
+ ExtraFields map[string]respjson.Field
+ raw string
+ } `json:"-"`
+}
+
+// Returns the unmodified JSON received from the API
+func (r BrowserPool) RawJSON() string { return r.JSON.raw }
+func (r *BrowserPool) UnmarshalJSON(data []byte) error {
+ return apijson.UnmarshalRoot(data, r)
+}
+
+// Request body for acquiring a browser from the pool.
+type BrowserPoolAcquireRequestParam struct {
+ // Maximum number of seconds to wait for a browser to be available. Defaults to the
+ // calculated time it would take to fill the pool at the currently configured fill
+ // rate.
+ AcquireTimeoutSeconds param.Opt[int64] `json:"acquire_timeout_seconds,omitzero"`
+ paramObj
+}
+
+func (r BrowserPoolAcquireRequestParam) MarshalJSON() (data []byte, err error) {
+ type shadow BrowserPoolAcquireRequestParam
+ return param.MarshalObject(r, (*shadow)(&r))
+}
+func (r *BrowserPoolAcquireRequestParam) UnmarshalJSON(data []byte) error {
+ return apijson.UnmarshalRoot(data, r)
+}
+
+// Request body for releasing a browser back to the pool.
+//
+// The property SessionID is required.
+type BrowserPoolReleaseRequestParam struct {
+ // Browser session ID to release back to the pool
+ SessionID string `json:"session_id,required"`
+ // Whether to reuse the browser instance or destroy it and create a new one.
+ // Defaults to true.
+ Reuse param.Opt[bool] `json:"reuse,omitzero"`
+ paramObj
+}
+
+func (r BrowserPoolReleaseRequestParam) MarshalJSON() (data []byte, err error) {
+ type shadow BrowserPoolReleaseRequestParam
+ return param.MarshalObject(r, (*shadow)(&r))
+}
+func (r *BrowserPoolReleaseRequestParam) UnmarshalJSON(data []byte) error {
+ return apijson.UnmarshalRoot(data, r)
+}
+
+// Parameters for creating a browser pool. All browsers in the pool will be created
+// with the same configuration.
+type BrowserPoolRequest struct {
+ // Number of browsers to create in the pool
+ Size int64 `json:"size,required"`
+ // List of browser extensions to load into the session. Provide each by id or name.
+ Extensions []shared.BrowserExtension `json:"extensions"`
+ // Percentage of the pool to fill per minute. Defaults to 10%.
+ FillRatePerMinute int64 `json:"fill_rate_per_minute"`
+ // If true, launches the browser using a headless image. Defaults to false.
+ Headless bool `json:"headless"`
+ // If true, launches the browser in kiosk mode to hide address bar and tabs in live
+ // view.
+ KioskMode bool `json:"kiosk_mode"`
+ // Optional name for the browser pool. Must be unique within the organization.
+ Name string `json:"name"`
+ // 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.BrowserProfile `json:"profile"`
+ // Optional proxy to associate to the browser session. Must reference a proxy
+ // belonging to the caller's org.
+ ProxyID string `json:"proxy_id"`
+ // If true, launches the browser in stealth mode to reduce detection by anti-bot
+ // mechanisms.
+ Stealth bool `json:"stealth"`
+ // Default idle timeout in seconds for browsers acquired from this pool before they
+ // are destroyed. Defaults to 600 seconds if not specified
+ TimeoutSeconds int64 `json:"timeout_seconds"`
+ // Initial browser window size in pixels with optional refresh rate. If omitted,
+ // image defaults apply (commonly 1024x768@60). Only specific viewport
+ // configurations are supported. The server will reject unsupported combinations.
+ // Supported resolutions are: 2560x1440@10, 1920x1080@25, 1920x1200@25,
+ // 1440x900@25, 1024x768@60, 1200x800@60 If refresh_rate is not provided, it will
+ // be automatically determined from the width and height if they match a supported
+ // configuration exactly. Note: Higher resolutions may affect the responsiveness of
+ // live view browser
+ Viewport shared.BrowserViewport `json:"viewport"`
+ // JSON contains metadata for fields, check presence with [respjson.Field.Valid].
+ JSON struct {
+ Size respjson.Field
+ Extensions respjson.Field
+ FillRatePerMinute respjson.Field
+ Headless respjson.Field
+ KioskMode respjson.Field
+ Name respjson.Field
+ Profile respjson.Field
+ ProxyID respjson.Field
+ Stealth respjson.Field
+ TimeoutSeconds respjson.Field
+ Viewport respjson.Field
+ ExtraFields map[string]respjson.Field
+ raw string
+ } `json:"-"`
+}
+
+// Returns the unmodified JSON received from the API
+func (r BrowserPoolRequest) RawJSON() string { return r.JSON.raw }
+func (r *BrowserPoolRequest) UnmarshalJSON(data []byte) error {
+ return apijson.UnmarshalRoot(data, r)
+}
+
+// ToParam converts this BrowserPoolRequest to a BrowserPoolRequestParam.
+//
+// Warning: the fields of the param type will not be present. ToParam should only
+// be used at the last possible moment before sending a request. Test for this with
+// BrowserPoolRequestParam.Overrides()
+func (r BrowserPoolRequest) ToParam() BrowserPoolRequestParam {
+ return param.Override[BrowserPoolRequestParam](json.RawMessage(r.RawJSON()))
+}
+
+// Parameters for creating a browser pool. All browsers in the pool will be created
+// with the same configuration.
+//
+// The property Size is required.
+type BrowserPoolRequestParam struct {
+ // Number of browsers to create in the pool
+ Size int64 `json:"size,required"`
+ // Percentage of the pool to fill per minute. Defaults to 10%.
+ FillRatePerMinute param.Opt[int64] `json:"fill_rate_per_minute,omitzero"`
+ // If true, launches the browser using a headless image. Defaults to false.
+ Headless param.Opt[bool] `json:"headless,omitzero"`
+ // If true, launches the browser in kiosk mode to hide address bar and tabs in live
+ // view.
+ KioskMode param.Opt[bool] `json:"kiosk_mode,omitzero"`
+ // Optional name for the browser pool. Must be unique within the organization.
+ Name param.Opt[string] `json:"name,omitzero"`
+ // Optional proxy to associate to the browser session. Must reference a proxy
+ // belonging to the caller's org.
+ ProxyID param.Opt[string] `json:"proxy_id,omitzero"`
+ // If true, launches the browser in stealth mode to reduce detection by anti-bot
+ // mechanisms.
+ Stealth param.Opt[bool] `json:"stealth,omitzero"`
+ // Default idle timeout in seconds for browsers acquired from this pool before they
+ // are destroyed. Defaults to 600 seconds if not specified
+ TimeoutSeconds param.Opt[int64] `json:"timeout_seconds,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 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"`
+ // Initial browser window size in pixels with optional refresh rate. If omitted,
+ // image defaults apply (commonly 1024x768@60). Only specific viewport
+ // configurations are supported. The server will reject unsupported combinations.
+ // Supported resolutions are: 2560x1440@10, 1920x1080@25, 1920x1200@25,
+ // 1440x900@25, 1024x768@60, 1200x800@60 If refresh_rate is not provided, it will
+ // be automatically determined from the width and height if they match a supported
+ // configuration exactly. Note: Higher resolutions may affect the responsiveness of
+ // live view browser
+ Viewport shared.BrowserViewportParam `json:"viewport,omitzero"`
+ paramObj
+}
+
+func (r BrowserPoolRequestParam) MarshalJSON() (data []byte, err error) {
+ type shadow BrowserPoolRequestParam
+ return param.MarshalObject(r, (*shadow)(&r))
+}
+func (r *BrowserPoolRequestParam) UnmarshalJSON(data []byte) error {
+ return apijson.UnmarshalRoot(data, r)
+}
+
+// Parameters for updating a browser pool. All browsers in the pool will be created
+// with the same configuration.
+type BrowserPoolUpdateRequestParam struct {
+ // Whether to discard all idle browsers and rebuild the pool immediately. Defaults
+ // to true.
+ DiscardAllIdle param.Opt[bool] `json:"discard_all_idle,omitzero"`
+ BrowserPoolRequestParam
+}
+
+func (r BrowserPoolUpdateRequestParam) MarshalJSON() (data []byte, err error) {
+ type shadow BrowserPoolUpdateRequestParam
+ return param.MarshalObject(r, (*shadow)(&r))
+}
+
+type BrowserPoolAcquireResponse struct {
+ // Websocket URL for Chrome DevTools Protocol connections to the browser session
+ CdpWsURL string `json:"cdp_ws_url,required"`
+ // When the browser session was created.
+ CreatedAt time.Time `json:"created_at,required" format:"date-time"`
+ // Whether the browser session is running in headless mode.
+ Headless bool `json:"headless,required"`
+ // Unique identifier for the browser session
+ SessionID string `json:"session_id,required"`
+ // Whether the browser session is running in stealth mode.
+ Stealth bool `json:"stealth,required"`
+ // The number of seconds of inactivity before the browser session is terminated.
+ TimeoutSeconds int64 `json:"timeout_seconds,required"`
+ // Remote URL for live viewing the browser session. Only available for non-headless
+ // browsers.
+ BrowserLiveViewURL string `json:"browser_live_view_url"`
+ // When the browser session was soft-deleted. Only present for deleted sessions.
+ DeletedAt time.Time `json:"deleted_at" format:"date-time"`
+ // Whether the browser session is running in kiosk mode.
+ KioskMode bool `json:"kiosk_mode"`
+ // Optional persistence configuration for the browser session.
+ Persistence BrowserPersistence `json:"persistence"`
+ // Browser profile metadata.
+ Profile Profile `json:"profile"`
+ // ID of the proxy associated with this browser session, if any.
+ ProxyID string `json:"proxy_id"`
+ // Initial browser window size in pixels with optional refresh rate. If omitted,
+ // image defaults apply (commonly 1024x768@60). Only specific viewport
+ // configurations are supported. The server will reject unsupported combinations.
+ // Supported resolutions are: 2560x1440@10, 1920x1080@25, 1920x1200@25,
+ // 1440x900@25, 1024x768@60, 1200x800@60 If refresh_rate is not provided, it will
+ // be automatically determined from the width and height if they match a supported
+ // configuration exactly. Note: Higher resolutions may affect the responsiveness of
+ // live view browser
+ Viewport shared.BrowserViewport `json:"viewport"`
+ // JSON contains metadata for fields, check presence with [respjson.Field.Valid].
+ JSON struct {
+ CdpWsURL respjson.Field
+ CreatedAt respjson.Field
+ Headless respjson.Field
+ SessionID respjson.Field
+ Stealth respjson.Field
+ TimeoutSeconds respjson.Field
+ BrowserLiveViewURL respjson.Field
+ DeletedAt respjson.Field
+ KioskMode respjson.Field
+ Persistence respjson.Field
+ Profile respjson.Field
+ ProxyID respjson.Field
+ Viewport respjson.Field
+ ExtraFields map[string]respjson.Field
+ raw string
+ } `json:"-"`
+}
+
+// Returns the unmodified JSON received from the API
+func (r BrowserPoolAcquireResponse) RawJSON() string { return r.JSON.raw }
+func (r *BrowserPoolAcquireResponse) UnmarshalJSON(data []byte) error {
+ return apijson.UnmarshalRoot(data, r)
+}
+
+type BrowserPoolNewParams struct {
+ // Parameters for creating a browser pool. All browsers in the pool will be created
+ // with the same configuration.
+ BrowserPoolRequest BrowserPoolRequestParam
+ paramObj
+}
+
+func (r BrowserPoolNewParams) MarshalJSON() (data []byte, err error) {
+ return shimjson.Marshal(r.BrowserPoolRequest)
+}
+func (r *BrowserPoolNewParams) UnmarshalJSON(data []byte) error {
+ return json.Unmarshal(data, &r.BrowserPoolRequest)
+}
+
+type BrowserPoolUpdateParams struct {
+ // Parameters for updating a browser pool. All browsers in the pool will be created
+ // with the same configuration.
+ BrowserPoolUpdateRequest BrowserPoolUpdateRequestParam
+ paramObj
+}
+
+func (r BrowserPoolUpdateParams) MarshalJSON() (data []byte, err error) {
+ return shimjson.Marshal(r.BrowserPoolUpdateRequest)
+}
+func (r *BrowserPoolUpdateParams) UnmarshalJSON(data []byte) error {
+ return json.Unmarshal(data, &r.BrowserPoolUpdateRequest)
+}
+
+type BrowserPoolDeleteParams struct {
+ // If true, force delete even if browsers are currently leased. Leased browsers
+ // will be terminated.
+ Force param.Opt[bool] `json:"force,omitzero"`
+ paramObj
+}
+
+func (r BrowserPoolDeleteParams) MarshalJSON() (data []byte, err error) {
+ type shadow BrowserPoolDeleteParams
+ return param.MarshalObject(r, (*shadow)(&r))
+}
+func (r *BrowserPoolDeleteParams) UnmarshalJSON(data []byte) error {
+ return apijson.UnmarshalRoot(data, r)
+}
+
+type BrowserPoolAcquireParams struct {
+ // Request body for acquiring a browser from the pool.
+ BrowserPoolAcquireRequest BrowserPoolAcquireRequestParam
+ paramObj
+}
+
+func (r BrowserPoolAcquireParams) MarshalJSON() (data []byte, err error) {
+ return shimjson.Marshal(r.BrowserPoolAcquireRequest)
+}
+func (r *BrowserPoolAcquireParams) UnmarshalJSON(data []byte) error {
+ return json.Unmarshal(data, &r.BrowserPoolAcquireRequest)
+}
+
+type BrowserPoolReleaseParams struct {
+ // Request body for releasing a browser back to the pool.
+ BrowserPoolReleaseRequest BrowserPoolReleaseRequestParam
+ paramObj
+}
+
+func (r BrowserPoolReleaseParams) MarshalJSON() (data []byte, err error) {
+ return shimjson.Marshal(r.BrowserPoolReleaseRequest)
+}
+func (r *BrowserPoolReleaseParams) UnmarshalJSON(data []byte) error {
+ return json.Unmarshal(data, &r.BrowserPoolReleaseRequest)
+}
diff --git a/browserpool_test.go b/browserpool_test.go
new file mode 100644
index 0000000..37fa909
--- /dev/null
+++ b/browserpool_test.go
@@ -0,0 +1,279 @@
+// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+package kernel_test
+
+import (
+ "context"
+ "errors"
+ "os"
+ "testing"
+
+ "github.com/onkernel/kernel-go-sdk"
+ "github.com/onkernel/kernel-go-sdk/internal/testutil"
+ "github.com/onkernel/kernel-go-sdk/option"
+ "github.com/onkernel/kernel-go-sdk/shared"
+)
+
+func TestBrowserPoolNewWithOptionalParams(t *testing.T) {
+ t.Skip("Prism 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.BrowserPools.New(context.TODO(), kernel.BrowserPoolNewParams{
+ BrowserPoolRequest: kernel.BrowserPoolRequestParam{
+ Size: 10,
+ Extensions: []shared.BrowserExtensionParam{{
+ ID: kernel.String("id"),
+ Name: kernel.String("name"),
+ }},
+ FillRatePerMinute: kernel.Int(0),
+ Headless: kernel.Bool(false),
+ KioskMode: kernel.Bool(true),
+ Name: kernel.String("my-pool"),
+ Profile: shared.BrowserProfileParam{
+ ID: kernel.String("id"),
+ Name: kernel.String("name"),
+ SaveChanges: kernel.Bool(true),
+ },
+ ProxyID: kernel.String("proxy_id"),
+ Stealth: kernel.Bool(true),
+ TimeoutSeconds: kernel.Int(60),
+ Viewport: shared.BrowserViewportParam{
+ Height: 800,
+ Width: 1280,
+ RefreshRate: kernel.Int(60),
+ },
+ },
+ })
+ 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 TestBrowserPoolGet(t *testing.T) {
+ t.Skip("Prism 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.BrowserPools.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 TestBrowserPoolUpdateWithOptionalParams(t *testing.T) {
+ t.Skip("Prism 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.BrowserPools.Update(
+ context.TODO(),
+ "id_or_name",
+ kernel.BrowserPoolUpdateParams{
+ BrowserPoolUpdateRequest: kernel.BrowserPoolUpdateRequestParam{
+ BrowserPoolRequestParam: kernel.BrowserPoolRequestParam{
+ Size: 10,
+ Extensions: []shared.BrowserExtensionParam{{
+ ID: kernel.String("id"),
+ Name: kernel.String("name"),
+ }},
+ FillRatePerMinute: kernel.Int(0),
+ Headless: kernel.Bool(false),
+ KioskMode: kernel.Bool(true),
+ Name: kernel.String("my-pool"),
+ Profile: shared.BrowserProfileParam{
+ ID: kernel.String("id"),
+ Name: kernel.String("name"),
+ SaveChanges: kernel.Bool(true),
+ },
+ ProxyID: kernel.String("proxy_id"),
+ Stealth: kernel.Bool(true),
+ TimeoutSeconds: kernel.Int(60),
+ Viewport: shared.BrowserViewportParam{
+ Height: 800,
+ Width: 1280,
+ RefreshRate: kernel.Int(60),
+ },
+ },
+ DiscardAllIdle: kernel.Bool(false),
+ },
+ },
+ )
+ 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 TestBrowserPoolList(t *testing.T) {
+ t.Skip("Prism 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.BrowserPools.List(context.TODO())
+ 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 TestBrowserPoolDeleteWithOptionalParams(t *testing.T) {
+ t.Skip("Prism 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.BrowserPools.Delete(
+ context.TODO(),
+ "id_or_name",
+ kernel.BrowserPoolDeleteParams{
+ Force: 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 TestBrowserPoolAcquireWithOptionalParams(t *testing.T) {
+ t.Skip("Prism 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.BrowserPools.Acquire(
+ context.TODO(),
+ "id_or_name",
+ kernel.BrowserPoolAcquireParams{
+ BrowserPoolAcquireRequest: kernel.BrowserPoolAcquireRequestParam{
+ AcquireTimeoutSeconds: kernel.Int(0),
+ },
+ },
+ )
+ 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 TestBrowserPoolFlush(t *testing.T) {
+ t.Skip("Prism 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.BrowserPools.Flush(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 TestBrowserPoolReleaseWithOptionalParams(t *testing.T) {
+ t.Skip("Prism 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.BrowserPools.Release(
+ context.TODO(),
+ "id_or_name",
+ kernel.BrowserPoolReleaseParams{
+ BrowserPoolReleaseRequest: kernel.BrowserPoolReleaseRequestParam{
+ SessionID: "ts8iy3sg25ibheguyni2lg9t",
+ Reuse: kernel.Bool(false),
+ },
+ },
+ )
+ 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/client.go b/client.go
index 39e85fe..1fac9b9 100644
--- a/client.go
+++ b/client.go
@@ -16,15 +16,15 @@ import (
// interacting with the kernel API. You should not instantiate this client
// directly, and instead use the [NewClient] method instead.
type Client struct {
- Options []option.RequestOption
- Deployments DeploymentService
- Apps AppService
- Invocations InvocationService
- Browsers BrowserService
- Profiles ProfileService
- Proxies ProxyService
- Extensions ExtensionService
- Agents AgentService
+ Options []option.RequestOption
+ Deployments DeploymentService
+ Apps AppService
+ Invocations InvocationService
+ Browsers BrowserService
+ Profiles ProfileService
+ Proxies ProxyService
+ Extensions ExtensionService
+ BrowserPools BrowserPoolService
}
// DefaultClientOptions read from the environment (KERNEL_API_KEY,
@@ -56,7 +56,7 @@ func NewClient(opts ...option.RequestOption) (r Client) {
r.Profiles = NewProfileService(opts...)
r.Proxies = NewProxyService(opts...)
r.Extensions = NewExtensionService(opts...)
- r.Agents = NewAgentService(opts...)
+ r.BrowserPools = NewBrowserPoolService(opts...)
return
}
diff --git a/shared/shared.go b/shared/shared.go
index a968ca4..755810d 100644
--- a/shared/shared.go
+++ b/shared/shared.go
@@ -3,6 +3,7 @@
package shared
import (
+ "encoding/json"
"time"
"github.com/onkernel/kernel-go-sdk/internal/apijson"
@@ -35,6 +36,187 @@ func (r *AppAction) UnmarshalJSON(data []byte) error {
return apijson.UnmarshalRoot(data, r)
}
+// Extension selection for the browser session. Provide either id or name of an
+// extension uploaded to Kernel.
+type BrowserExtension struct {
+ // Extension ID to load for this browser session
+ ID string `json:"id"`
+ // Extension name to load for this browser session (instead of id). Must be 1-255
+ // characters, using letters, numbers, dots, underscores, or hyphens.
+ 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 BrowserExtension) RawJSON() string { return r.JSON.raw }
+func (r *BrowserExtension) UnmarshalJSON(data []byte) error {
+ return apijson.UnmarshalRoot(data, r)
+}
+
+// ToParam converts this BrowserExtension to a BrowserExtensionParam.
+//
+// Warning: the fields of the param type will not be present. ToParam should only
+// be used at the last possible moment before sending a request. Test for this with
+// BrowserExtensionParam.Overrides()
+func (r BrowserExtension) ToParam() BrowserExtensionParam {
+ return param.Override[BrowserExtensionParam](json.RawMessage(r.RawJSON()))
+}
+
+// Extension selection for the browser session. Provide either id or name of an
+// extension uploaded to Kernel.
+type BrowserExtensionParam struct {
+ // Extension ID to load for this browser session
+ ID param.Opt[string] `json:"id,omitzero"`
+ // Extension name to load for this browser session (instead of id). Must be 1-255
+ // characters, using letters, numbers, dots, underscores, or hyphens.
+ Name param.Opt[string] `json:"name,omitzero"`
+ paramObj
+}
+
+func (r BrowserExtensionParam) MarshalJSON() (data []byte, err error) {
+ type shadow BrowserExtensionParam
+ return param.MarshalObject(r, (*shadow)(&r))
+}
+func (r *BrowserExtensionParam) UnmarshalJSON(data []byte) error {
+ return apijson.UnmarshalRoot(data, r)
+}
+
+// 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.
+type BrowserProfile struct {
+ // Profile ID to load for this browser session
+ ID string `json:"id"`
+ // Profile name to load for this browser session (instead of id). Must be 1-255
+ // characters, using letters, numbers, dots, underscores, or hyphens.
+ Name string `json:"name"`
+ // If true, save changes made during the session back to the profile when the
+ // session ends.
+ SaveChanges bool `json:"save_changes"`
+ // JSON contains metadata for fields, check presence with [respjson.Field.Valid].
+ JSON struct {
+ ID respjson.Field
+ Name respjson.Field
+ SaveChanges respjson.Field
+ ExtraFields map[string]respjson.Field
+ raw string
+ } `json:"-"`
+}
+
+// Returns the unmodified JSON received from the API
+func (r BrowserProfile) RawJSON() string { return r.JSON.raw }
+func (r *BrowserProfile) UnmarshalJSON(data []byte) error {
+ return apijson.UnmarshalRoot(data, r)
+}
+
+// ToParam converts this BrowserProfile to a BrowserProfileParam.
+//
+// Warning: the fields of the param type will not be present. ToParam should only
+// be used at the last possible moment before sending a request. Test for this with
+// BrowserProfileParam.Overrides()
+func (r BrowserProfile) ToParam() BrowserProfileParam {
+ return param.Override[BrowserProfileParam](json.RawMessage(r.RawJSON()))
+}
+
+// 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.
+type BrowserProfileParam struct {
+ // Profile ID to load for this browser session
+ ID param.Opt[string] `json:"id,omitzero"`
+ // Profile name to load for this browser session (instead of id). Must be 1-255
+ // characters, using letters, numbers, dots, underscores, or hyphens.
+ Name param.Opt[string] `json:"name,omitzero"`
+ // If true, save changes made during the session back to the profile when the
+ // session ends.
+ SaveChanges param.Opt[bool] `json:"save_changes,omitzero"`
+ paramObj
+}
+
+func (r BrowserProfileParam) MarshalJSON() (data []byte, err error) {
+ type shadow BrowserProfileParam
+ return param.MarshalObject(r, (*shadow)(&r))
+}
+func (r *BrowserProfileParam) UnmarshalJSON(data []byte) error {
+ return apijson.UnmarshalRoot(data, r)
+}
+
+// Initial browser window size in pixels with optional refresh rate. If omitted,
+// image defaults apply (commonly 1024x768@60). Only specific viewport
+// configurations are supported. The server will reject unsupported combinations.
+// Supported resolutions are: 2560x1440@10, 1920x1080@25, 1920x1200@25,
+// 1440x900@25, 1024x768@60, 1200x800@60 If refresh_rate is not provided, it will
+// be automatically determined from the width and height if they match a supported
+// configuration exactly. Note: Higher resolutions may affect the responsiveness of
+// live view browser
+type BrowserViewport struct {
+ // Browser window height in pixels.
+ Height int64 `json:"height,required"`
+ // Browser window width in pixels.
+ Width int64 `json:"width,required"`
+ // Display refresh rate in Hz. If omitted, automatically determined from width and
+ // height.
+ RefreshRate int64 `json:"refresh_rate"`
+ // JSON contains metadata for fields, check presence with [respjson.Field.Valid].
+ JSON struct {
+ Height respjson.Field
+ Width respjson.Field
+ RefreshRate respjson.Field
+ ExtraFields map[string]respjson.Field
+ raw string
+ } `json:"-"`
+}
+
+// Returns the unmodified JSON received from the API
+func (r BrowserViewport) RawJSON() string { return r.JSON.raw }
+func (r *BrowserViewport) UnmarshalJSON(data []byte) error {
+ return apijson.UnmarshalRoot(data, r)
+}
+
+// ToParam converts this BrowserViewport to a BrowserViewportParam.
+//
+// Warning: the fields of the param type will not be present. ToParam should only
+// be used at the last possible moment before sending a request. Test for this with
+// BrowserViewportParam.Overrides()
+func (r BrowserViewport) ToParam() BrowserViewportParam {
+ return param.Override[BrowserViewportParam](json.RawMessage(r.RawJSON()))
+}
+
+// Initial browser window size in pixels with optional refresh rate. If omitted,
+// image defaults apply (commonly 1024x768@60). Only specific viewport
+// configurations are supported. The server will reject unsupported combinations.
+// Supported resolutions are: 2560x1440@10, 1920x1080@25, 1920x1200@25,
+// 1440x900@25, 1024x768@60, 1200x800@60 If refresh_rate is not provided, it will
+// be automatically determined from the width and height if they match a supported
+// configuration exactly. Note: Higher resolutions may affect the responsiveness of
+// live view browser
+//
+// The properties Height, Width are required.
+type BrowserViewportParam struct {
+ // Browser window height in pixels.
+ Height int64 `json:"height,required"`
+ // Browser window width in pixels.
+ Width int64 `json:"width,required"`
+ // Display refresh rate in Hz. If omitted, automatically determined from width and
+ // height.
+ RefreshRate param.Opt[int64] `json:"refresh_rate,omitzero"`
+ paramObj
+}
+
+func (r BrowserViewportParam) MarshalJSON() (data []byte, err error) {
+ type shadow BrowserViewportParam
+ return param.MarshalObject(r, (*shadow)(&r))
+}
+func (r *BrowserViewportParam) UnmarshalJSON(data []byte) error {
+ return apijson.UnmarshalRoot(data, r)
+}
+
type ErrorDetail struct {
// Lower-level error code providing more specific detail
Code string `json:"code"`
From 13eded97c6e7f43b6a86871b7d7048215438bbcf Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Tue, 2 Dec 2025 22:14:04 +0000
Subject: [PATCH 6/7] codegen metadata
---
.stats.yml | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/.stats.yml b/.stats.yml
index c32f96d..25e77f1 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,4 +1,4 @@
configured_endpoints: 74
-openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-340c8f009b71922347d4c238c8715cd752c8965abfa12cbb1ffabe35edc338a8.yml
-openapi_spec_hash: efc13ab03ef89cc07333db8ab5345f31
+openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-3db06d1628149b5ea8303f1c72250664dfd7cb4a14ceb6102f1ae6e85c92c038.yml
+openapi_spec_hash: e5b3da2da328eb26d2a70e2521744c62
config_hash: a4124701ae0a474e580d7416adbcfb00
From a4d43505dee0fdfa566e3ed9a0d9d1b37cf8c930 Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Tue, 2 Dec 2025 22:14:22 +0000
Subject: [PATCH 7/7] release: 0.21.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 0c2ecec..86b0e83 100644
--- a/.release-please-manifest.json
+++ b/.release-please-manifest.json
@@ -1,3 +1,3 @@
{
- ".": "0.20.0"
+ ".": "0.21.0"
}
\ No newline at end of file
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 1e52afc..a54ba21 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,14 @@
# Changelog
+## 0.21.0 (2025-12-02)
+
+Full Changelog: [v0.20.0...v0.21.0](https://github.com/onkernel/kernel-go-sdk/compare/v0.20.0...v0.21.0)
+
+### Features
+
+* Browser pools sdk release ([69dcf34](https://github.com/onkernel/kernel-go-sdk/commit/69dcf3471d1b8b7b6fb8210da6d9c0b42ab1f1e7))
+* Mason/agent auth api ([ee63aba](https://github.com/onkernel/kernel-go-sdk/commit/ee63aba391e6a3024e93eeca28d008ea93b18b58))
+
## 0.20.0 (2025-11-19)
Full Changelog: [v0.19.2...v0.20.0](https://github.com/onkernel/kernel-go-sdk/compare/v0.19.2...v0.20.0)
diff --git a/README.md b/README.md
index 89f902d..07fd868 100644
--- a/README.md
+++ b/README.md
@@ -28,7 +28,7 @@ Or to pin the version:
```sh
-go get -u 'github.com/onkernel/kernel-go-sdk@v0.20.0'
+go get -u 'github.com/onkernel/kernel-go-sdk@v0.21.0'
```
diff --git a/internal/version.go b/internal/version.go
index 6c84346..b6325aa 100644
--- a/internal/version.go
+++ b/internal/version.go
@@ -2,4 +2,4 @@
package internal
-const PackageVersion = "0.20.0" // x-release-please-version
+const PackageVersion = "0.21.0" // x-release-please-version