diff --git a/.release-please-manifest.json b/.release-please-manifest.json
index 86b0e83..cb9d254 100644
--- a/.release-please-manifest.json
+++ b/.release-please-manifest.json
@@ -1,3 +1,3 @@
{
- ".": "0.21.0"
+ ".": "0.22.0"
}
\ No newline at end of file
diff --git a/.stats.yml b/.stats.yml
index 25e77f1..0c474bb 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-3db06d1628149b5ea8303f1c72250664dfd7cb4a14ceb6102f1ae6e85c92c038.yml
-openapi_spec_hash: e5b3da2da328eb26d2a70e2521744c62
-config_hash: a4124701ae0a474e580d7416adbcfb00
+configured_endpoints: 80
+openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-8a37652fa586b8932466d16285359a89988505f850787f8257d0c4c7053da173.yml
+openapi_spec_hash: 042765a113f6d08109e8146b302323ec
+config_hash: 113f1e5bc3567628a5d51c70bc00969d
diff --git a/CHANGELOG.md b/CHANGELOG.md
index a54ba21..2abbe96 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,20 @@
# Changelog
+## 0.22.0 (2025-12-06)
+
+Full Changelog: [v0.21.0...v0.22.0](https://github.com/onkernel/kernel-go-sdk/compare/v0.21.0...v0.22.0)
+
+### Features
+
+* [wip] Browser pools polish pass ([628410a](https://github.com/onkernel/kernel-go-sdk/commit/628410a6fc946e6adf5d7a9593b6ebb01385f918))
+* Add `async_timeout_seconds` to PostInvocations ([4ee4d7c](https://github.com/onkernel/kernel-go-sdk/commit/4ee4d7c60817d8d4a9e6460e7d04c19f309095d3))
+* Enhance agent authentication with optional login page URL and auth ch… ([a2fc4ac](https://github.com/onkernel/kernel-go-sdk/commit/a2fc4acfb2bf88a5cc209d5430fcfb0eee4f751b))
+
+
+### Refactors
+
+* **browser:** remove persistence option UI ([7ea9ccf](https://github.com/onkernel/kernel-go-sdk/commit/7ea9ccfb9a6c8acb3fd9d8d04b7bf8b9cfb4fef1))
+
## 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)
diff --git a/README.md b/README.md
index 07fd868..43fd6a5 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.21.0'
+go get -u 'github.com/onkernel/kernel-go-sdk@v0.22.0'
```
@@ -58,9 +58,7 @@ func main() {
option.WithEnvironmentDevelopment(), // defaults to option.WithEnvironmentProduction()
)
browser, err := client.Browsers.New(context.TODO(), kernel.BrowserNewParams{
- Persistence: kernel.BrowserPersistenceParam{
- ID: "browser-for-user-1234",
- },
+ Stealth: kernel.Bool(true),
})
if err != nil {
panic(err.Error())
@@ -334,9 +332,7 @@ To handle errors, we recommend that you use the `errors.As` pattern:
```go
_, err := client.Browsers.New(context.TODO(), kernel.BrowserNewParams{
- Persistence: kernel.BrowserPersistenceParam{
- ID: "browser-for-user-1234",
- },
+ Stealth: kernel.Bool(true),
})
if err != nil {
var apierr *kernel.Error
@@ -365,9 +361,7 @@ defer cancel()
client.Browsers.New(
ctx,
kernel.BrowserNewParams{
- Persistence: kernel.BrowserPersistenceParam{
- ID: "browser-for-user-1234",
- },
+ Stealth: kernel.Bool(true),
},
// This sets the per-retry timeout
option.WithRequestTimeout(20*time.Second),
@@ -423,9 +417,7 @@ client := kernel.NewClient(
client.Browsers.New(
context.TODO(),
kernel.BrowserNewParams{
- Persistence: kernel.BrowserPersistenceParam{
- ID: "browser-for-user-1234",
- },
+ Stealth: kernel.Bool(true),
},
option.WithMaxRetries(5),
)
@@ -442,9 +434,7 @@ var response *http.Response
browser, err := client.Browsers.New(
context.TODO(),
kernel.BrowserNewParams{
- Persistence: kernel.BrowserPersistenceParam{
- ID: "browser-for-user-1234",
- },
+ Stealth: kernel.Bool(true),
},
option.WithResponseInto(&response),
)
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..16311d1
--- /dev/null
+++ b/agentauth.go
@@ -0,0 +1,325 @@
+// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+package kernel
+
+import (
+ "context"
+ "errors"
+ "fmt"
+ "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
+ Invocations AgentAuthInvocationService
+}
+
+// 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.Invocations = NewAgentAuthInvocationService(opts...)
+ return
+}
+
+// Retrieve an auth agent by its ID. Returns the current authentication status of
+// the managed profile.
+func (r *AgentAuthService) Get(ctx context.Context, id string, opts ...option.RequestOption) (res *AuthAgent, err error) {
+ opts = slices.Concat(r.Options, opts)
+ if id == "" {
+ err = errors.New("missing required id parameter")
+ return
+ }
+ path := fmt.Sprintf("agents/auth/%s", id)
+ err = requestconfig.ExecuteNewRequest(ctx, http.MethodGet, path, nil, &res, 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 invocation endpoint
+type AgentAuthInvocationResponse struct {
+ // App name (org name at time of invocation creation)
+ AppName string `json:"app_name,required"`
+ // When the handoff code expires
+ ExpiresAt time.Time `json:"expires_at,required" format:"date-time"`
+ // Invocation status
+ //
+ // Any of "IN_PROGRESS", "SUCCESS", "EXPIRED", "CANCELED".
+ Status AgentAuthInvocationResponseStatus `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 AgentAuthInvocationResponse) RawJSON() string { return r.JSON.raw }
+func (r *AgentAuthInvocationResponse) UnmarshalJSON(data []byte) error {
+ return apijson.UnmarshalRoot(data, r)
+}
+
+// Invocation status
+type AgentAuthInvocationResponseStatus string
+
+const (
+ AgentAuthInvocationResponseStatusInProgress AgentAuthInvocationResponseStatus = "IN_PROGRESS"
+ AgentAuthInvocationResponseStatusSuccess AgentAuthInvocationResponseStatus = "SUCCESS"
+ AgentAuthInvocationResponseStatusExpired AgentAuthInvocationResponseStatus = "EXPIRED"
+ AgentAuthInvocationResponseStatusCanceled AgentAuthInvocationResponseStatus = "CANCELED"
+)
+
+// Response from starting an agent authentication invocation
+type AgentAuthStartResponse struct {
+ // Unique identifier for the auth agent managing this domain/profile
+ AuthAgentID string `json:"auth_agent_id,required"`
+ // 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 invocation
+ InvocationID string `json:"invocation_id,required"`
+ // JSON contains metadata for fields, check presence with [respjson.Field.Valid].
+ JSON struct {
+ AuthAgentID respjson.Field
+ ExpiresAt respjson.Field
+ HandoffCode respjson.Field
+ HostedURL respjson.Field
+ InvocationID 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)
+}
+
+// An auth agent that manages authentication for a specific domain and profile
+// combination
+type AuthAgent struct {
+ // Unique identifier for the auth agent
+ ID string `json:"id,required"`
+ // Target domain for authentication
+ Domain string `json:"domain,required"`
+ // Name of the profile associated with this auth agent
+ ProfileName string `json:"profile_name,required"`
+ // Current authentication status of the managed profile
+ //
+ // Any of "AUTHENTICATED", "NEEDS_AUTH".
+ Status AuthAgentStatus `json:"status,required"`
+ // JSON contains metadata for fields, check presence with [respjson.Field.Valid].
+ JSON struct {
+ ID respjson.Field
+ Domain respjson.Field
+ ProfileName respjson.Field
+ Status respjson.Field
+ ExtraFields map[string]respjson.Field
+ raw string
+ } `json:"-"`
+}
+
+// Returns the unmodified JSON received from the API
+func (r AuthAgent) RawJSON() string { return r.JSON.raw }
+func (r *AuthAgent) UnmarshalJSON(data []byte) error {
+ return apijson.UnmarshalRoot(data, r)
+}
+
+// Current authentication status of the managed profile
+type AuthAgentStatus string
+
+const (
+ AuthAgentStatusAuthenticated AuthAgentStatus = "AUTHENTICATED"
+ AuthAgentStatusNeedsAuth AuthAgentStatus = "NEEDS_AUTH"
+)
+
+// 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".
+ 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"
+)
+
+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 login page URL. If provided, will be stored on the agent and used to
+ // skip Phase 1 discovery in future invocations.
+ LoginURL param.Opt[string] `json:"login_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..aa21286
--- /dev/null
+++ b/agentauth_test.go
@@ -0,0 +1,68 @@
+// 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 TestAgentAuthGet(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.Get(context.TODO(), "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 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"),
+ LoginURL: kernel.String("https://doordash.com/account/login"),
+ 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/agentauthinvocation.go b/agentauthinvocation.go
new file mode 100644
index 0000000..e9b8ccb
--- /dev/null
+++ b/agentauthinvocation.go
@@ -0,0 +1,153 @@
+// 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"
+)
+
+// AgentAuthInvocationService 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 [NewAgentAuthInvocationService] method instead.
+type AgentAuthInvocationService struct {
+ Options []option.RequestOption
+}
+
+// NewAgentAuthInvocationService 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 NewAgentAuthInvocationService(opts ...option.RequestOption) (r AgentAuthInvocationService) {
+ r = AgentAuthInvocationService{}
+ r.Options = opts
+ return
+}
+
+// Returns invocation details including app_name and target_domain. Uses the JWT
+// returned by the exchange endpoint, or standard API key or JWT authentication.
+func (r *AgentAuthInvocationService) Get(ctx context.Context, invocationID string, opts ...option.RequestOption) (res *AgentAuthInvocationResponse, err error) {
+ opts = slices.Concat(r.Options, opts)
+ if invocationID == "" {
+ err = errors.New("missing required invocation_id parameter")
+ return
+ }
+ path := fmt.Sprintf("agents/auth/invocations/%s", invocationID)
+ 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 *AgentAuthInvocationService) Discover(ctx context.Context, invocationID string, body AgentAuthInvocationDiscoverParams, opts ...option.RequestOption) (res *AgentAuthDiscoverResponse, err error) {
+ opts = slices.Concat(r.Options, opts)
+ if invocationID == "" {
+ err = errors.New("missing required invocation_id parameter")
+ return
+ }
+ path := fmt.Sprintf("agents/auth/invocations/%s/discover", invocationID)
+ 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 *AgentAuthInvocationService) Exchange(ctx context.Context, invocationID string, body AgentAuthInvocationExchangeParams, opts ...option.RequestOption) (res *AgentAuthInvocationExchangeResponse, err error) {
+ opts = slices.Concat(r.Options, opts)
+ if invocationID == "" {
+ err = errors.New("missing required invocation_id parameter")
+ return
+ }
+ path := fmt.Sprintf("agents/auth/invocations/%s/exchange", invocationID)
+ 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 *AgentAuthInvocationService) Submit(ctx context.Context, invocationID string, body AgentAuthInvocationSubmitParams, opts ...option.RequestOption) (res *AgentAuthSubmitResponse, err error) {
+ opts = slices.Concat(r.Options, opts)
+ if invocationID == "" {
+ err = errors.New("missing required invocation_id parameter")
+ return
+ }
+ path := fmt.Sprintf("agents/auth/invocations/%s/submit", invocationID)
+ err = requestconfig.ExecuteNewRequest(ctx, http.MethodPost, path, body, &res, opts...)
+ return
+}
+
+// Response from exchange endpoint
+type AgentAuthInvocationExchangeResponse struct {
+ // Invocation ID
+ InvocationID string `json:"invocation_id,required"`
+ // JWT token with invocation_id claim (30 minute TTL)
+ Jwt string `json:"jwt,required"`
+ // JSON contains metadata for fields, check presence with [respjson.Field.Valid].
+ JSON struct {
+ InvocationID respjson.Field
+ Jwt respjson.Field
+ ExtraFields map[string]respjson.Field
+ raw string
+ } `json:"-"`
+}
+
+// Returns the unmodified JSON received from the API
+func (r AgentAuthInvocationExchangeResponse) RawJSON() string { return r.JSON.raw }
+func (r *AgentAuthInvocationExchangeResponse) UnmarshalJSON(data []byte) error {
+ return apijson.UnmarshalRoot(data, r)
+}
+
+type AgentAuthInvocationDiscoverParams struct {
+ // Optional login page URL. If provided, will override the stored login URL for
+ // this discovery invocation and skip Phase 1 discovery.
+ LoginURL param.Opt[string] `json:"login_url,omitzero" format:"uri"`
+ paramObj
+}
+
+func (r AgentAuthInvocationDiscoverParams) MarshalJSON() (data []byte, err error) {
+ type shadow AgentAuthInvocationDiscoverParams
+ return param.MarshalObject(r, (*shadow)(&r))
+}
+func (r *AgentAuthInvocationDiscoverParams) UnmarshalJSON(data []byte) error {
+ return apijson.UnmarshalRoot(data, r)
+}
+
+type AgentAuthInvocationExchangeParams struct {
+ // Handoff code from start endpoint
+ Code string `json:"code,required"`
+ paramObj
+}
+
+func (r AgentAuthInvocationExchangeParams) MarshalJSON() (data []byte, err error) {
+ type shadow AgentAuthInvocationExchangeParams
+ return param.MarshalObject(r, (*shadow)(&r))
+}
+func (r *AgentAuthInvocationExchangeParams) UnmarshalJSON(data []byte) error {
+ return apijson.UnmarshalRoot(data, r)
+}
+
+type AgentAuthInvocationSubmitParams struct {
+ // Values for the discovered login fields
+ FieldValues map[string]string `json:"field_values,omitzero,required"`
+ paramObj
+}
+
+func (r AgentAuthInvocationSubmitParams) MarshalJSON() (data []byte, err error) {
+ type shadow AgentAuthInvocationSubmitParams
+ return param.MarshalObject(r, (*shadow)(&r))
+}
+func (r *AgentAuthInvocationSubmitParams) UnmarshalJSON(data []byte) error {
+ return apijson.UnmarshalRoot(data, r)
+}
diff --git a/agentauthinvocation_test.go b/agentauthinvocation_test.go
new file mode 100644
index 0000000..367ff15
--- /dev/null
+++ b/agentauthinvocation_test.go
@@ -0,0 +1,127 @@
+// 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 TestAgentAuthInvocationGet(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.Invocations.Get(context.TODO(), "invocation_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 TestAgentAuthInvocationDiscoverWithOptionalParams(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.Invocations.Discover(
+ context.TODO(),
+ "invocation_id",
+ kernel.AgentAuthInvocationDiscoverParams{
+ LoginURL: kernel.String("https://doordash.com/account/login"),
+ },
+ )
+ 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 TestAgentAuthInvocationExchange(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.Invocations.Exchange(
+ context.TODO(),
+ "invocation_id",
+ kernel.AgentAuthInvocationExchangeParams{
+ Code: "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 TestAgentAuthInvocationSubmit(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.Invocations.Submit(
+ context.TODO(),
+ "invocation_id",
+ kernel.AgentAuthInvocationSubmitParams{
+ 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 d7a4818..7df59e9 100644
--- a/aliases.go
+++ b/aliases.go
@@ -48,11 +48,11 @@ type BrowserProfile = shared.BrowserProfile
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
+// image defaults apply (1920x1080@25). 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
//
@@ -60,11 +60,11 @@ type BrowserProfileParam = shared.BrowserProfileParam
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
+// image defaults apply (1920x1080@25). 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
//
diff --git a/api.md b/api.md
index aa0d086..80ddb73 100644
--- a/api.md
+++ b/api.md
@@ -253,3 +253,34 @@ Methods:
- 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
+
+# Agents
+
+## Auth
+
+Response Types:
+
+- kernel.AgentAuthDiscoverResponse
+- kernel.AgentAuthInvocationResponse
+- kernel.AgentAuthStartResponse
+- kernel.AgentAuthSubmitResponse
+- kernel.AuthAgent
+- kernel.DiscoveredField
+
+Methods:
+
+- client.Agents.Auth.Get(ctx context.Context, id string) (kernel.AuthAgent, error)
+- client.Agents.Auth.Start(ctx context.Context, body kernel.AgentAuthStartParams) (kernel.AgentAuthStartResponse, error)
+
+### Invocations
+
+Response Types:
+
+- kernel.AgentAuthInvocationExchangeResponse
+
+Methods:
+
+- client.Agents.Auth.Invocations.Get(ctx context.Context, invocationID string) (kernel.AgentAuthInvocationResponse, error)
+- client.Agents.Auth.Invocations.Discover(ctx context.Context, invocationID string, body kernel.AgentAuthInvocationDiscoverParams) (kernel.AgentAuthDiscoverResponse, error)
+- client.Agents.Auth.Invocations.Exchange(ctx context.Context, invocationID string, body kernel.AgentAuthInvocationExchangeParams) (kernel.AgentAuthInvocationExchangeResponse, error)
+- client.Agents.Auth.Invocations.Submit(ctx context.Context, invocationID string, body kernel.AgentAuthInvocationSubmitParams) (kernel.AgentAuthSubmitResponse, error)
diff --git a/browser.go b/browser.go
index fc9f55c..2ae047c 100644
--- a/browser.go
+++ b/browser.go
@@ -102,7 +102,10 @@ func (r *BrowserService) ListAutoPaging(ctx context.Context, query BrowserListPa
return pagination.NewOffsetPaginationAutoPager(r.List(ctx, query, opts...))
}
-// Delete a persistent browser session by its persistent_id.
+// DEPRECATED: Use DELETE /browsers/{id} instead. Delete a persistent browser
+// session by its persistent_id.
+//
+// Deprecated: deprecated
func (r *BrowserService) Delete(ctx context.Context, body BrowserDeleteParams, opts ...option.RequestOption) (err error) {
opts = slices.Concat(r.Options, opts)
opts = append([]option.RequestOption{option.WithHeader("Accept", "*/*")}, opts...)
@@ -138,9 +141,11 @@ func (r *BrowserService) LoadExtensions(ctx context.Context, id string, body Bro
return
}
-// Optional persistence configuration for the browser session.
+// DEPRECATED: Use timeout_seconds (up to 72 hours) and Profiles instead.
+//
+// Deprecated: deprecated
type BrowserPersistence struct {
- // Unique identifier for the persistent browser session.
+ // DEPRECATED: Unique identifier for the persistent browser session.
ID string `json:"id,required"`
// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
JSON struct {
@@ -165,11 +170,13 @@ func (r BrowserPersistence) ToParam() BrowserPersistenceParam {
return param.Override[BrowserPersistenceParam](json.RawMessage(r.RawJSON()))
}
-// Optional persistence configuration for the browser session.
+// DEPRECATED: Use timeout_seconds (up to 72 hours) and Profiles instead.
+//
+// Deprecated: deprecated
//
// The property ID is required.
type BrowserPersistenceParam struct {
- // Unique identifier for the persistent browser session.
+ // DEPRECATED: Unique identifier for the persistent browser session.
ID string `json:"id,required"`
paramObj
}
@@ -232,18 +239,20 @@ type BrowserNewResponse struct {
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.
+ // DEPRECATED: Use timeout_seconds (up to 72 hours) and Profiles instead.
+ //
+ // Deprecated: deprecated
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
+ // image defaults apply (1920x1080@25). 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"`
@@ -293,18 +302,20 @@ type BrowserGetResponse struct {
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.
+ // DEPRECATED: Use timeout_seconds (up to 72 hours) and Profiles instead.
+ //
+ // Deprecated: deprecated
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
+ // image defaults apply (1920x1080@25). 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"`
@@ -354,18 +365,20 @@ type BrowserListResponse struct {
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.
+ // DEPRECATED: Use timeout_seconds (up to 72 hours) and Profiles instead.
+ //
+ // Deprecated: deprecated
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
+ // image defaults apply (1920x1080@25). 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"`
@@ -411,26 +424,25 @@ type BrowserNewParams struct {
// mechanisms.
Stealth param.Opt[bool] `json:"stealth,omitzero"`
// The number of seconds of inactivity before the browser session is terminated.
- // Only applicable to non-persistent browsers. Activity includes CDP connections
- // and live view connections. Defaults to 60 seconds. Minimum allowed is 10
- // seconds. Maximum allowed is 259200 (72 hours). We check for inactivity every 5
- // seconds, so the actual timeout behavior you will see is +/- 5 seconds around the
- // specified value.
+ // Activity includes CDP connections and live view connections. Defaults to 60
+ // seconds. Minimum allowed is 10 seconds. Maximum allowed is 259200 (72 hours). We
+ // check for inactivity every 5 seconds, so the actual timeout behavior you will
+ // see is +/- 5 seconds around the 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 []shared.BrowserExtensionParam `json:"extensions,omitzero"`
- // Optional persistence configuration for the browser session.
+ // DEPRECATED: Use timeout_seconds (up to 72 hours) and Profiles instead.
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 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
+ // image defaults apply (1920x1080@25). 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"`
diff --git a/browserpool.go b/browserpool.go
index 4001ea7..f77cd23 100644
--- a/browserpool.go
+++ b/browserpool.go
@@ -234,11 +234,11 @@ type BrowserPoolRequest struct {
// 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
+ // image defaults apply (1920x1080@25). 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"`
@@ -307,11 +307,11 @@ type BrowserPoolRequestParam struct {
// 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
+ // image defaults apply (1920x1080@25). 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"`
@@ -330,7 +330,7 @@ func (r *BrowserPoolRequestParam) UnmarshalJSON(data []byte) error {
// with the same configuration.
type BrowserPoolUpdateRequestParam struct {
// Whether to discard all idle browsers and rebuild the pool immediately. Defaults
- // to true.
+ // to false.
DiscardAllIdle param.Opt[bool] `json:"discard_all_idle,omitzero"`
BrowserPoolRequestParam
}
@@ -360,18 +360,20 @@ type BrowserPoolAcquireResponse struct {
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.
+ // DEPRECATED: Use timeout_seconds (up to 72 hours) and Profiles instead.
+ //
+ // Deprecated: deprecated
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
+ // image defaults apply (1920x1080@25). 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"`
diff --git a/client.go b/client.go
index 1fac9b9..eca243d 100644
--- a/client.go
+++ b/client.go
@@ -25,6 +25,7 @@ type Client struct {
Proxies ProxyService
Extensions ExtensionService
BrowserPools BrowserPoolService
+ Agents AgentService
}
// DefaultClientOptions read from the environment (KERNEL_API_KEY,
@@ -57,6 +58,7 @@ func NewClient(opts ...option.RequestOption) (r Client) {
r.Proxies = NewProxyService(opts...)
r.Extensions = NewExtensionService(opts...)
r.BrowserPools = NewBrowserPoolService(opts...)
+ r.Agents = NewAgentService(opts...)
return
}
diff --git a/client_test.go b/client_test.go
index 824eab6..facacc9 100644
--- a/client_test.go
+++ b/client_test.go
@@ -40,9 +40,7 @@ func TestUserAgentHeader(t *testing.T) {
}),
)
client.Browsers.New(context.Background(), kernel.BrowserNewParams{
- Persistence: kernel.BrowserPersistenceParam{
- ID: "browser-for-user-1234",
- },
+ Stealth: kernel.Bool(true),
})
if userAgent != fmt.Sprintf("Kernel/Go %s", internal.PackageVersion) {
t.Errorf("Expected User-Agent to be correct, but got: %#v", userAgent)
@@ -68,9 +66,7 @@ func TestRetryAfter(t *testing.T) {
}),
)
_, err := client.Browsers.New(context.Background(), kernel.BrowserNewParams{
- Persistence: kernel.BrowserPersistenceParam{
- ID: "browser-for-user-1234",
- },
+ Stealth: kernel.Bool(true),
})
if err == nil {
t.Error("Expected there to be a cancel error")
@@ -107,9 +103,7 @@ func TestDeleteRetryCountHeader(t *testing.T) {
option.WithHeaderDel("X-Stainless-Retry-Count"),
)
_, err := client.Browsers.New(context.Background(), kernel.BrowserNewParams{
- Persistence: kernel.BrowserPersistenceParam{
- ID: "browser-for-user-1234",
- },
+ Stealth: kernel.Bool(true),
})
if err == nil {
t.Error("Expected there to be a cancel error")
@@ -141,9 +135,7 @@ func TestOverwriteRetryCountHeader(t *testing.T) {
option.WithHeader("X-Stainless-Retry-Count", "42"),
)
_, err := client.Browsers.New(context.Background(), kernel.BrowserNewParams{
- Persistence: kernel.BrowserPersistenceParam{
- ID: "browser-for-user-1234",
- },
+ Stealth: kernel.Bool(true),
})
if err == nil {
t.Error("Expected there to be a cancel error")
@@ -174,9 +166,7 @@ func TestRetryAfterMs(t *testing.T) {
}),
)
_, err := client.Browsers.New(context.Background(), kernel.BrowserNewParams{
- Persistence: kernel.BrowserPersistenceParam{
- ID: "browser-for-user-1234",
- },
+ Stealth: kernel.Bool(true),
})
if err == nil {
t.Error("Expected there to be a cancel error")
@@ -201,9 +191,7 @@ func TestContextCancel(t *testing.T) {
cancelCtx, cancel := context.WithCancel(context.Background())
cancel()
_, err := client.Browsers.New(cancelCtx, kernel.BrowserNewParams{
- Persistence: kernel.BrowserPersistenceParam{
- ID: "browser-for-user-1234",
- },
+ Stealth: kernel.Bool(true),
})
if err == nil {
t.Error("Expected there to be a cancel error")
@@ -225,9 +213,7 @@ func TestContextCancelDelay(t *testing.T) {
cancelCtx, cancel := context.WithTimeout(context.Background(), 2*time.Millisecond)
defer cancel()
_, err := client.Browsers.New(cancelCtx, kernel.BrowserNewParams{
- Persistence: kernel.BrowserPersistenceParam{
- ID: "browser-for-user-1234",
- },
+ Stealth: kernel.Bool(true),
})
if err == nil {
t.Error("expected there to be a cancel error")
@@ -255,9 +241,7 @@ func TestContextDeadline(t *testing.T) {
}),
)
_, err := client.Browsers.New(deadlineCtx, kernel.BrowserNewParams{
- Persistence: kernel.BrowserPersistenceParam{
- ID: "browser-for-user-1234",
- },
+ Stealth: kernel.Bool(true),
})
if err == nil {
t.Error("expected there to be a deadline error")
diff --git a/internal/version.go b/internal/version.go
index b6325aa..e482b6b 100644
--- a/internal/version.go
+++ b/internal/version.go
@@ -2,4 +2,4 @@
package internal
-const PackageVersion = "0.21.0" // x-release-please-version
+const PackageVersion = "0.22.0" // x-release-please-version
diff --git a/invocation.go b/invocation.go
index 2fdbc66..45b1045 100644
--- a/invocation.go
+++ b/invocation.go
@@ -517,6 +517,9 @@ type InvocationNewParams struct {
// If true, invoke asynchronously. When set, the API responds 202 Accepted with
// status "queued".
Async param.Opt[bool] `json:"async,omitzero"`
+ // Timeout in seconds for async invocations (min 10, max 3600). Only applies when
+ // async is true.
+ AsyncTimeoutSeconds param.Opt[int64] `json:"async_timeout_seconds,omitzero"`
// Input data for the action, sent as a JSON string.
Payload param.Opt[string] `json:"payload,omitzero"`
paramObj
diff --git a/invocation_test.go b/invocation_test.go
index c99ca1a..fda50fd 100644
--- a/invocation_test.go
+++ b/invocation_test.go
@@ -27,11 +27,12 @@ func TestInvocationNewWithOptionalParams(t *testing.T) {
option.WithAPIKey("My API Key"),
)
_, err := client.Invocations.New(context.TODO(), kernel.InvocationNewParams{
- ActionName: "analyze",
- AppName: "my-app",
- Version: "1.0.0",
- Async: kernel.Bool(true),
- Payload: kernel.String(`{"data":"example input"}`),
+ ActionName: "analyze",
+ AppName: "my-app",
+ Version: "1.0.0",
+ Async: kernel.Bool(true),
+ AsyncTimeoutSeconds: kernel.Int(600),
+ Payload: kernel.String(`{"data":"example input"}`),
})
if err != nil {
var apierr *kernel.Error
diff --git a/shared/shared.go b/shared/shared.go
index 755810d..3aa9907 100644
--- a/shared/shared.go
+++ b/shared/shared.go
@@ -148,11 +148,11 @@ func (r *BrowserProfileParam) UnmarshalJSON(data []byte) error {
}
// 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
+// image defaults apply (1920x1080@25). 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 {
@@ -189,11 +189,11 @@ func (r BrowserViewport) ToParam() BrowserViewportParam {
}
// 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
+// image defaults apply (1920x1080@25). 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
//
diff --git a/usage_test.go b/usage_test.go
index 302a5b9..5be681f 100644
--- a/usage_test.go
+++ b/usage_test.go
@@ -25,9 +25,7 @@ func TestUsage(t *testing.T) {
option.WithAPIKey("My API Key"),
)
browser, err := client.Browsers.New(context.TODO(), kernel.BrowserNewParams{
- Persistence: kernel.BrowserPersistenceParam{
- ID: "browser-for-user-1234",
- },
+ Stealth: kernel.Bool(true),
})
if err != nil {
t.Fatalf("err should be nil: %s", err.Error())