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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .release-please-manifest.json
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
{
".": "0.10.0"
".": "0.11.0"
}
8 changes: 4 additions & 4 deletions .stats.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
configured_endpoints: 41
openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-a7c1df5070fe59642d7a1f168aa902a468227752bfc930cbf38930f7c205dbb6.yml
openapi_spec_hash: eab65e39aef4f0a0952b82adeecf6b5b
config_hash: 5de78bc29ac060562575cb54bb26826c
configured_endpoints: 46
openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-e98d46c55826cdf541a9ee0df04ce92806ac6d4d92957ae79f897270b7d85b23.yml
openapi_spec_hash: 8a1af54fc0a4417165b8a52e6354b685
config_hash: 043ddc54629c6d8b889123770cb4769f
18 changes: 18 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,23 @@
# Changelog

## 0.11.0 (2025-09-04)

Full Changelog: [v0.10.0...v0.11.0](https://github.com/onkernel/kernel-go-sdk/compare/v0.10.0...v0.11.0)

### Features

* **api:** adding support for browser profiles ([481cdb3](https://github.com/onkernel/kernel-go-sdk/commit/481cdb3500744c9e4ec050e340a920302d8fea19))


### Bug Fixes

* close body before retrying ([a6a2e40](https://github.com/onkernel/kernel-go-sdk/commit/a6a2e4054c629d6ee85997ed81a1b14e70e594dc))


### Chores

* **internal:** codegen related update ([a7030ab](https://github.com/onkernel/kernel-go-sdk/commit/a7030abb99c06c675f60a4f2afde43d376d9981f))

## 0.10.0 (2025-08-27)

Full Changelog: [v0.9.1...v0.10.0](https://github.com/onkernel/kernel-go-sdk/compare/v0.9.1...v0.10.0)
Expand Down
6 changes: 5 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
# Kernel Go API Library

<!-- x-release-please-start-version -->

<a href="https://pkg.go.dev/github.com/onkernel/kernel-go-sdk"><img src="https://pkg.go.dev/badge/github.com/onkernel/kernel-go-sdk.svg" alt="Go Reference"></a>

<!-- x-release-please-end -->

The Kernel Go library provides convenient access to the [Kernel REST API](https://docs.onkernel.com)
from applications written in Go.

Expand All @@ -24,7 +28,7 @@ Or to pin the version:
<!-- x-release-please-start-version -->

```sh
go get -u 'github.com/onkernel/kernel-go-sdk@v0.10.0'
go get -u 'github.com/onkernel/kernel-go-sdk@v0.11.0'
```

<!-- x-release-please-end -->
Expand Down
11 changes: 11 additions & 0 deletions api.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ Params Types:
Response Types:

- <a href="https://pkg.go.dev/github.com/onkernel/kernel-go-sdk">kernel</a>.<a href="https://pkg.go.dev/github.com/onkernel/kernel-go-sdk#BrowserPersistence">BrowserPersistence</a>
- <a href="https://pkg.go.dev/github.com/onkernel/kernel-go-sdk">kernel</a>.<a href="https://pkg.go.dev/github.com/onkernel/kernel-go-sdk#Profile">Profile</a>
- <a href="https://pkg.go.dev/github.com/onkernel/kernel-go-sdk">kernel</a>.<a href="https://pkg.go.dev/github.com/onkernel/kernel-go-sdk#BrowserNewResponse">BrowserNewResponse</a>
- <a href="https://pkg.go.dev/github.com/onkernel/kernel-go-sdk">kernel</a>.<a href="https://pkg.go.dev/github.com/onkernel/kernel-go-sdk#BrowserGetResponse">BrowserGetResponse</a>
- <a href="https://pkg.go.dev/github.com/onkernel/kernel-go-sdk">kernel</a>.<a href="https://pkg.go.dev/github.com/onkernel/kernel-go-sdk#BrowserListResponse">BrowserListResponse</a>
Expand Down Expand Up @@ -147,3 +148,13 @@ Methods:
Methods:

- <code title="get /browsers/{id}/logs/stream">client.Browsers.Logs.<a href="https://pkg.go.dev/github.com/onkernel/kernel-go-sdk#BrowserLogService.Stream">Stream</a>(ctx <a href="https://pkg.go.dev/context">context</a>.<a href="https://pkg.go.dev/context#Context">Context</a>, id <a href="https://pkg.go.dev/builtin#string">string</a>, query <a href="https://pkg.go.dev/github.com/onkernel/kernel-go-sdk">kernel</a>.<a href="https://pkg.go.dev/github.com/onkernel/kernel-go-sdk#BrowserLogStreamParams">BrowserLogStreamParams</a>) (<a href="https://pkg.go.dev/github.com/onkernel/kernel-go-sdk/shared">shared</a>.<a href="https://pkg.go.dev/github.com/onkernel/kernel-go-sdk/shared#LogEvent">LogEvent</a>, <a href="https://pkg.go.dev/builtin#error">error</a>)</code>

# Profiles

Methods:

- <code title="post /profiles">client.Profiles.<a href="https://pkg.go.dev/github.com/onkernel/kernel-go-sdk#ProfileService.New">New</a>(ctx <a href="https://pkg.go.dev/context">context</a>.<a href="https://pkg.go.dev/context#Context">Context</a>, body <a href="https://pkg.go.dev/github.com/onkernel/kernel-go-sdk">kernel</a>.<a href="https://pkg.go.dev/github.com/onkernel/kernel-go-sdk#ProfileNewParams">ProfileNewParams</a>) (<a href="https://pkg.go.dev/github.com/onkernel/kernel-go-sdk">kernel</a>.<a href="https://pkg.go.dev/github.com/onkernel/kernel-go-sdk#Profile">Profile</a>, <a href="https://pkg.go.dev/builtin#error">error</a>)</code>
- <code title="get /profiles/{id_or_name}">client.Profiles.<a href="https://pkg.go.dev/github.com/onkernel/kernel-go-sdk#ProfileService.Get">Get</a>(ctx <a href="https://pkg.go.dev/context">context</a>.<a href="https://pkg.go.dev/context#Context">Context</a>, idOrName <a href="https://pkg.go.dev/builtin#string">string</a>) (<a href="https://pkg.go.dev/github.com/onkernel/kernel-go-sdk">kernel</a>.<a href="https://pkg.go.dev/github.com/onkernel/kernel-go-sdk#Profile">Profile</a>, <a href="https://pkg.go.dev/builtin#error">error</a>)</code>
- <code title="get /profiles">client.Profiles.<a href="https://pkg.go.dev/github.com/onkernel/kernel-go-sdk#ProfileService.List">List</a>(ctx <a href="https://pkg.go.dev/context">context</a>.<a href="https://pkg.go.dev/context#Context">Context</a>) ([]<a href="https://pkg.go.dev/github.com/onkernel/kernel-go-sdk">kernel</a>.<a href="https://pkg.go.dev/github.com/onkernel/kernel-go-sdk#Profile">Profile</a>, <a href="https://pkg.go.dev/builtin#error">error</a>)</code>
- <code title="delete /profiles/{id_or_name}">client.Profiles.<a href="https://pkg.go.dev/github.com/onkernel/kernel-go-sdk#ProfileService.Delete">Delete</a>(ctx <a href="https://pkg.go.dev/context">context</a>.<a href="https://pkg.go.dev/context#Context">Context</a>, idOrName <a href="https://pkg.go.dev/builtin#string">string</a>) <a href="https://pkg.go.dev/builtin#error">error</a></code>
- <code title="get /profiles/{id_or_name}/download">client.Profiles.<a href="https://pkg.go.dev/github.com/onkernel/kernel-go-sdk#ProfileService.Download">Download</a>(ctx <a href="https://pkg.go.dev/context">context</a>.<a href="https://pkg.go.dev/context#Context">Context</a>, idOrName <a href="https://pkg.go.dev/builtin#string">string</a>) (http.Response, <a href="https://pkg.go.dev/builtin#error">error</a>)</code>
66 changes: 66 additions & 0 deletions browser.go
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,36 @@ func (r *BrowserPersistenceParam) UnmarshalJSON(data []byte) error {
return apijson.UnmarshalRoot(data, r)
}

// Browser profile metadata.
type Profile struct {
// Unique identifier for the profile
ID string `json:"id,required"`
// Timestamp when the profile was created
CreatedAt time.Time `json:"created_at,required" format:"date-time"`
// Timestamp when the profile was last used
LastUsedAt time.Time `json:"last_used_at" format:"date-time"`
// Optional, easier-to-reference name for the profile
Name string `json:"name,nullable"`
// Timestamp when the profile was last updated
UpdatedAt time.Time `json:"updated_at" format:"date-time"`
// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
JSON struct {
ID respjson.Field
CreatedAt respjson.Field
LastUsedAt respjson.Field
Name respjson.Field
UpdatedAt respjson.Field
ExtraFields map[string]respjson.Field
raw string
} `json:"-"`
}

// Returns the unmodified JSON received from the API
func (r Profile) RawJSON() string { return r.JSON.raw }
func (r *Profile) UnmarshalJSON(data []byte) error {
return apijson.UnmarshalRoot(data, r)
}

type BrowserNewResponse struct {
// Websocket URL for Chrome DevTools Protocol connections to the browser session
CdpWsURL string `json:"cdp_ws_url,required"`
Expand All @@ -158,6 +188,8 @@ type BrowserNewResponse struct {
BrowserLiveViewURL string `json:"browser_live_view_url"`
// Optional persistence configuration for the browser session.
Persistence BrowserPersistence `json:"persistence"`
// Browser profile metadata.
Profile Profile `json:"profile"`
// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
JSON struct {
CdpWsURL respjson.Field
Expand All @@ -168,6 +200,7 @@ type BrowserNewResponse struct {
TimeoutSeconds respjson.Field
BrowserLiveViewURL respjson.Field
Persistence respjson.Field
Profile respjson.Field
ExtraFields map[string]respjson.Field
raw string
} `json:"-"`
Expand Down Expand Up @@ -197,6 +230,8 @@ type BrowserGetResponse struct {
BrowserLiveViewURL string `json:"browser_live_view_url"`
// Optional persistence configuration for the browser session.
Persistence BrowserPersistence `json:"persistence"`
// Browser profile metadata.
Profile Profile `json:"profile"`
// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
JSON struct {
CdpWsURL respjson.Field
Expand All @@ -207,6 +242,7 @@ type BrowserGetResponse struct {
TimeoutSeconds respjson.Field
BrowserLiveViewURL respjson.Field
Persistence respjson.Field
Profile respjson.Field
ExtraFields map[string]respjson.Field
raw string
} `json:"-"`
Expand Down Expand Up @@ -236,6 +272,8 @@ type BrowserListResponse struct {
BrowserLiveViewURL string `json:"browser_live_view_url"`
// Optional persistence configuration for the browser session.
Persistence BrowserPersistence `json:"persistence"`
// Browser profile metadata.
Profile Profile `json:"profile"`
// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
JSON struct {
CdpWsURL respjson.Field
Expand All @@ -246,6 +284,7 @@ type BrowserListResponse struct {
TimeoutSeconds respjson.Field
BrowserLiveViewURL respjson.Field
Persistence respjson.Field
Profile respjson.Field
ExtraFields map[string]respjson.Field
raw string
} `json:"-"`
Expand All @@ -272,6 +311,10 @@ type BrowserNewParams struct {
TimeoutSeconds param.Opt[int64] `json:"timeout_seconds,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"`
paramObj
}

Expand All @@ -283,6 +326,29 @@ func (r *BrowserNewParams) 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)
}

type BrowserDeleteParams struct {
// Persistent browser identifier
PersistentID string `query:"persistent_id,required" json:"-"`
Expand Down
5 changes: 5 additions & 0 deletions browser_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,11 @@ func TestBrowserNewWithOptionalParams(t *testing.T) {
Persistence: kernel.BrowserPersistenceParam{
ID: "my-awesome-browser-for-user-1234",
},
Profile: kernel.BrowserNewParamsProfile{
ID: kernel.String("id"),
Name: kernel.String("name"),
SaveChanges: kernel.Bool(true),
},
Stealth: kernel.Bool(true),
TimeoutSeconds: kernel.Int(0),
})
Expand Down
2 changes: 2 additions & 0 deletions client.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ type Client struct {
Apps AppService
Invocations InvocationService
Browsers BrowserService
Profiles ProfileService
}

// DefaultClientOptions read from the environment (KERNEL_API_KEY,
Expand Down Expand Up @@ -48,6 +49,7 @@ func NewClient(opts ...option.RequestOption) (r Client) {
r.Apps = NewAppService(opts...)
r.Invocations = NewInvocationService(opts...)
r.Browsers = NewBrowserService(opts...)
r.Profiles = NewProfileService(opts...)

return
}
Expand Down
5 changes: 5 additions & 0 deletions internal/requestconfig/requestconfig.go
Original file line number Diff line number Diff line change
Expand Up @@ -461,6 +461,11 @@ func (cfg *RequestConfig) Execute() (err error) {
break
}

// Close the response body before retrying to prevent connection leaks
if res != nil && res.Body != nil {
res.Body.Close()
}

time.Sleep(retryDelay(res, retryCount))
}

Expand Down
2 changes: 1 addition & 1 deletion internal/version.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@

package internal

const PackageVersion = "0.10.0" // x-release-please-version
const PackageVersion = "0.11.0" // x-release-please-version
104 changes: 104 additions & 0 deletions profile.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.

package kernel

import (
"context"
"errors"
"fmt"
"net/http"

"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"
)

// ProfileService 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 [NewProfileService] method instead.
type ProfileService struct {
Options []option.RequestOption
}

// NewProfileService 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 NewProfileService(opts ...option.RequestOption) (r ProfileService) {
r = ProfileService{}
r.Options = opts
return
}

// Create a browser profile that can be used to load state into future browser
// sessions.
func (r *ProfileService) New(ctx context.Context, body ProfileNewParams, opts ...option.RequestOption) (res *Profile, err error) {
opts = append(r.Options[:], opts...)
path := "profiles"
err = requestconfig.ExecuteNewRequest(ctx, http.MethodPost, path, body, &res, opts...)
return
}

// Retrieve details for a single profile by its ID or name.
func (r *ProfileService) Get(ctx context.Context, idOrName string, opts ...option.RequestOption) (res *Profile, err error) {
opts = append(r.Options[:], opts...)
if idOrName == "" {
err = errors.New("missing required id_or_name parameter")
return
}
path := fmt.Sprintf("profiles/%s", idOrName)
err = requestconfig.ExecuteNewRequest(ctx, http.MethodGet, path, nil, &res, opts...)
return
}

// List profiles with optional filtering and pagination.
func (r *ProfileService) List(ctx context.Context, opts ...option.RequestOption) (res *[]Profile, err error) {
opts = append(r.Options[:], opts...)
path := "profiles"
err = requestconfig.ExecuteNewRequest(ctx, http.MethodGet, path, nil, &res, opts...)
return
}

// Delete a profile by its ID or by its name.
func (r *ProfileService) Delete(ctx context.Context, idOrName string, opts ...option.RequestOption) (err error) {
opts = append(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("profiles/%s", idOrName)
err = requestconfig.ExecuteNewRequest(ctx, http.MethodDelete, path, nil, nil, opts...)
return
}

// Download the profile. Profiles are JSON files containing the pieces of state
// that we save.
func (r *ProfileService) Download(ctx context.Context, idOrName string, opts ...option.RequestOption) (res *http.Response, err error) {
opts = append(r.Options[:], opts...)
opts = append([]option.RequestOption{option.WithHeader("Accept", "application/octet-stream")}, opts...)
if idOrName == "" {
err = errors.New("missing required id_or_name parameter")
return
}
path := fmt.Sprintf("profiles/%s/download", idOrName)
err = requestconfig.ExecuteNewRequest(ctx, http.MethodGet, path, nil, &res, opts...)
return
}

type ProfileNewParams struct {
// Optional name of the profile. Must be unique within the organization.
Name param.Opt[string] `json:"name,omitzero"`
paramObj
}

func (r ProfileNewParams) MarshalJSON() (data []byte, err error) {
type shadow ProfileNewParams
return param.MarshalObject(r, (*shadow)(&r))
}
func (r *ProfileNewParams) UnmarshalJSON(data []byte) error {
return apijson.UnmarshalRoot(data, r)
}
Loading