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.7.1"
".": "0.8.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: 18
openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-d173129101e26f450c200e84430d993479c034700cf826917425d513b88912e6.yml
openapi_spec_hash: 150b86da7588979d7619b1a894e4720c
config_hash: eaeed470b1070b34df69c49d68e67355
configured_endpoints: 21
openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-a5b1d2c806c42c1534eefc8d34516f7f6e4ab68cb6a836534ee549bdbe4653f3.yml
openapi_spec_hash: 0be350cc8ddbd1fc7e058ce6c3a44ee8
config_hash: 307153ecd5b85f77ce8e0d87f6e5dfab
15 changes: 15 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,20 @@
# Changelog

## 0.8.0 (2025-07-16)

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

### Features

* **api:** manual updates ([ba0a473](https://github.com/onkernel/kernel-go-sdk/commit/ba0a473799c2c9a00865112a22ae356c57d2c114))
* **client:** expand max streaming buffer size ([41bdefe](https://github.com/onkernel/kernel-go-sdk/commit/41bdefed3d43cb52b431e8255a4a4faa0dfc46f0))


### Chores

* **internal:** fix lint script for tests ([5118fdf](https://github.com/onkernel/kernel-go-sdk/commit/5118fdf7e31a237e8def04c5a41cd0767900deef))
* lint tests in subpackages ([71d9002](https://github.com/onkernel/kernel-go-sdk/commit/71d900220761ff811187d5c03236a0fc5d92fcc6))

## 0.7.1 (2025-07-08)

Full Changelog: [v0.7.0...v0.7.1](https://github.com/onkernel/kernel-go-sdk/compare/v0.7.0...v0.7.1)
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ Or to pin the version:
<!-- x-release-please-start-version -->

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

<!-- x-release-please-end -->
Expand Down
15 changes: 14 additions & 1 deletion api.md
Original file line number Diff line number Diff line change
Expand Up @@ -84,4 +84,17 @@ Methods:
- <code title="get /browsers">client.Browsers.<a href="https://pkg.go.dev/github.com/onkernel/kernel-go-sdk#BrowserService.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#BrowserListResponse">BrowserListResponse</a>, <a href="https://pkg.go.dev/builtin#error">error</a>)</code>
- <code title="delete /browsers">client.Browsers.<a href="https://pkg.go.dev/github.com/onkernel/kernel-go-sdk#BrowserService.Delete">Delete</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#BrowserDeleteParams">BrowserDeleteParams</a>) <a href="https://pkg.go.dev/builtin#error">error</a></code>
- <code title="delete /browsers/{id}">client.Browsers.<a href="https://pkg.go.dev/github.com/onkernel/kernel-go-sdk#BrowserService.DeleteByID">DeleteByID</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>) <a href="https://pkg.go.dev/builtin#error">error</a></code>
- <code title="get /browsers/{id}/replay">client.Browsers.<a href="https://pkg.go.dev/github.com/onkernel/kernel-go-sdk#BrowserService.GetReplay">GetReplay</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>) (http.Response, <a href="https://pkg.go.dev/builtin#error">error</a>)</code>

## Replays

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#BrowserReplayListResponse">BrowserReplayListResponse</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#BrowserReplayStartResponse">BrowserReplayStartResponse</a>

Methods:

- <code title="get /browsers/{id}/replays">client.Browsers.Replays.<a href="https://pkg.go.dev/github.com/onkernel/kernel-go-sdk#BrowserReplayService.List">List</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>) ([]<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#BrowserReplayListResponse">BrowserReplayListResponse</a>, <a href="https://pkg.go.dev/builtin#error">error</a>)</code>
- <code title="get /browsers/{id}/replays/{replay_id}">client.Browsers.Replays.<a href="https://pkg.go.dev/github.com/onkernel/kernel-go-sdk#BrowserReplayService.Download">Download</a>(ctx <a href="https://pkg.go.dev/context">context</a>.<a href="https://pkg.go.dev/context#Context">Context</a>, replayID <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#BrowserReplayDownloadParams">BrowserReplayDownloadParams</a>) (http.Response, <a href="https://pkg.go.dev/builtin#error">error</a>)</code>
- <code title="post /browsers/{id}/replays">client.Browsers.Replays.<a href="https://pkg.go.dev/github.com/onkernel/kernel-go-sdk#BrowserReplayService.Start">Start</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>, 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#BrowserReplayStartParams">BrowserReplayStartParams</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#BrowserReplayStartResponse">BrowserReplayStartResponse</a>, <a href="https://pkg.go.dev/builtin#error">error</a>)</code>
- <code title="post /browsers/{id}/replays/{replay_id}/stop">client.Browsers.Replays.<a href="https://pkg.go.dev/github.com/onkernel/kernel-go-sdk#BrowserReplayService.Stop">Stop</a>(ctx <a href="https://pkg.go.dev/context">context</a>.<a href="https://pkg.go.dev/context#Context">Context</a>, replayID <a href="https://pkg.go.dev/builtin#string">string</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#BrowserReplayStopParams">BrowserReplayStopParams</a>) <a href="https://pkg.go.dev/builtin#error">error</a></code>
26 changes: 2 additions & 24 deletions browser.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import (
// the [NewBrowserService] method instead.
type BrowserService struct {
Options []option.RequestOption
Replays BrowserReplayService
}

// NewBrowserService generates a new service that applies the given options to each
Expand All @@ -34,6 +35,7 @@ type BrowserService struct {
func NewBrowserService(opts ...option.RequestOption) (r BrowserService) {
r = BrowserService{}
r.Options = opts
r.Replays = NewBrowserReplayService(opts...)
return
}

Expand Down Expand Up @@ -87,19 +89,6 @@ func (r *BrowserService) DeleteByID(ctx context.Context, id string, opts ...opti
return
}

// Get browser session replay.
func (r *BrowserService) GetReplay(ctx context.Context, id string, opts ...option.RequestOption) (res *http.Response, err error) {
opts = append(r.Options[:], opts...)
opts = append([]option.RequestOption{option.WithHeader("Accept", "video/mp4")}, opts...)
if id == "" {
err = errors.New("missing required id parameter")
return
}
path := fmt.Sprintf("browsers/%s/replay", id)
err = requestconfig.ExecuteNewRequest(ctx, http.MethodGet, path, nil, &res, opts...)
return
}

// Optional persistence configuration for the browser session.
type BrowserPersistence struct {
// Unique identifier for the persistent browser session.
Expand Down Expand Up @@ -154,15 +143,12 @@ type BrowserNewResponse struct {
BrowserLiveViewURL string `json:"browser_live_view_url"`
// Optional persistence configuration for the browser session.
Persistence BrowserPersistence `json:"persistence"`
// Remote URL for viewing the browser session replay if enabled
ReplayViewURL string `json:"replay_view_url"`
// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
JSON struct {
CdpWsURL respjson.Field
SessionID respjson.Field
BrowserLiveViewURL respjson.Field
Persistence respjson.Field
ReplayViewURL respjson.Field
ExtraFields map[string]respjson.Field
raw string
} `json:"-"`
Expand All @@ -184,15 +170,12 @@ type BrowserGetResponse struct {
BrowserLiveViewURL string `json:"browser_live_view_url"`
// Optional persistence configuration for the browser session.
Persistence BrowserPersistence `json:"persistence"`
// Remote URL for viewing the browser session replay if enabled
ReplayViewURL string `json:"replay_view_url"`
// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
JSON struct {
CdpWsURL respjson.Field
SessionID respjson.Field
BrowserLiveViewURL respjson.Field
Persistence respjson.Field
ReplayViewURL respjson.Field
ExtraFields map[string]respjson.Field
raw string
} `json:"-"`
Expand All @@ -214,15 +197,12 @@ type BrowserListResponse struct {
BrowserLiveViewURL string `json:"browser_live_view_url"`
// Optional persistence configuration for the browser session.
Persistence BrowserPersistence `json:"persistence"`
// Remote URL for viewing the browser session replay if enabled
ReplayViewURL string `json:"replay_view_url"`
// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
JSON struct {
CdpWsURL respjson.Field
SessionID respjson.Field
BrowserLiveViewURL respjson.Field
Persistence respjson.Field
ReplayViewURL respjson.Field
ExtraFields map[string]respjson.Field
raw string
} `json:"-"`
Expand All @@ -240,8 +220,6 @@ type BrowserNewParams struct {
Headless param.Opt[bool] `json:"headless,omitzero"`
// action invocation ID
InvocationID param.Opt[string] `json:"invocation_id,omitzero"`
// If true, enables replay recording of the browser session. Defaults to false.
Replay param.Opt[bool] `json:"replay,omitzero"`
// If true, launches the browser in stealth mode to reduce detection by anti-bot
// mechanisms.
Stealth param.Opt[bool] `json:"stealth,omitzero"`
Expand Down
40 changes: 0 additions & 40 deletions browser_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,8 @@
package kernel_test

import (
"bytes"
"context"
"errors"
"io"
"net/http"
"net/http/httptest"
"os"
"testing"

Expand Down Expand Up @@ -36,7 +32,6 @@ func TestBrowserNewWithOptionalParams(t *testing.T) {
Persistence: kernel.BrowserPersistenceParam{
ID: "my-awesome-browser-for-user-1234",
},
Replay: kernel.Bool(true),
Stealth: kernel.Bool(true),
})
if err != nil {
Expand Down Expand Up @@ -141,38 +136,3 @@ func TestBrowserDeleteByID(t *testing.T) {
t.Fatalf("err should be nil: %s", err.Error())
}
}

func TestBrowserGetReplay(t *testing.T) {
t.Skip("skipped: tests are disabled for the time being")
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(200)
w.Write([]byte("abc"))
}))
defer server.Close()
baseURL := server.URL
client := kernel.NewClient(
option.WithBaseURL(baseURL),
option.WithAPIKey("My API Key"),
)
resp, err := client.Browsers.GetReplay(context.TODO(), "htzv5orfit78e1m2biiifpbv")
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())
}
defer resp.Body.Close()

b, err := io.ReadAll(resp.Body)
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())
}
if !bytes.Equal(b, []byte("abc")) {
t.Fatalf("return value not %s: %s", "abc", b)
}
}
174 changes: 174 additions & 0 deletions browserreplay.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,174 @@
// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.

package kernel

import (
"context"
"errors"
"fmt"
"net/http"
"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"
)

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

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

// List all replays for the specified browser session.
func (r *BrowserReplayService) List(ctx context.Context, id string, opts ...option.RequestOption) (res *[]BrowserReplayListResponse, err error) {
opts = append(r.Options[:], opts...)
if id == "" {
err = errors.New("missing required id parameter")
return
}
path := fmt.Sprintf("browsers/%s/replays", id)
err = requestconfig.ExecuteNewRequest(ctx, http.MethodGet, path, nil, &res, opts...)
return
}

// Download or stream the specified replay recording.
func (r *BrowserReplayService) Download(ctx context.Context, replayID string, query BrowserReplayDownloadParams, opts ...option.RequestOption) (res *http.Response, err error) {
opts = append(r.Options[:], opts...)
opts = append([]option.RequestOption{option.WithHeader("Accept", "video/mp4")}, opts...)
if query.ID == "" {
err = errors.New("missing required id parameter")
return
}
if replayID == "" {
err = errors.New("missing required replay_id parameter")
return
}
path := fmt.Sprintf("browsers/%s/replays/%s", query.ID, replayID)
err = requestconfig.ExecuteNewRequest(ctx, http.MethodGet, path, nil, &res, opts...)
return
}

// Start recording the browser session and return a replay ID.
func (r *BrowserReplayService) Start(ctx context.Context, id string, body BrowserReplayStartParams, opts ...option.RequestOption) (res *BrowserReplayStartResponse, err error) {
opts = append(r.Options[:], opts...)
if id == "" {
err = errors.New("missing required id parameter")
return
}
path := fmt.Sprintf("browsers/%s/replays", id)
err = requestconfig.ExecuteNewRequest(ctx, http.MethodPost, path, body, &res, opts...)
return
}

// Stop the specified replay recording and persist the video.
func (r *BrowserReplayService) Stop(ctx context.Context, replayID string, body BrowserReplayStopParams, opts ...option.RequestOption) (err error) {
opts = append(r.Options[:], opts...)
opts = append([]option.RequestOption{option.WithHeader("Accept", "")}, opts...)
if body.ID == "" {
err = errors.New("missing required id parameter")
return
}
if replayID == "" {
err = errors.New("missing required replay_id parameter")
return
}
path := fmt.Sprintf("browsers/%s/replays/%s/stop", body.ID, replayID)
err = requestconfig.ExecuteNewRequest(ctx, http.MethodPost, path, nil, nil, opts...)
return
}

// Information about a browser replay recording.
type BrowserReplayListResponse struct {
// Unique identifier for the replay recording.
ReplayID string `json:"replay_id,required"`
// Timestamp when replay finished
FinishedAt time.Time `json:"finished_at,nullable" format:"date-time"`
// URL for viewing the replay recording.
ReplayViewURL string `json:"replay_view_url"`
// Timestamp when replay started
StartedAt time.Time `json:"started_at,nullable" format:"date-time"`
// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
JSON struct {
ReplayID respjson.Field
FinishedAt respjson.Field
ReplayViewURL respjson.Field
StartedAt respjson.Field
ExtraFields map[string]respjson.Field
raw string
} `json:"-"`
}

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

// Information about a browser replay recording.
type BrowserReplayStartResponse struct {
// Unique identifier for the replay recording.
ReplayID string `json:"replay_id,required"`
// Timestamp when replay finished
FinishedAt time.Time `json:"finished_at,nullable" format:"date-time"`
// URL for viewing the replay recording.
ReplayViewURL string `json:"replay_view_url"`
// Timestamp when replay started
StartedAt time.Time `json:"started_at,nullable" format:"date-time"`
// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
JSON struct {
ReplayID respjson.Field
FinishedAt respjson.Field
ReplayViewURL respjson.Field
StartedAt respjson.Field
ExtraFields map[string]respjson.Field
raw string
} `json:"-"`
}

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

type BrowserReplayDownloadParams struct {
ID string `path:"id,required" json:"-"`
paramObj
}

type BrowserReplayStartParams struct {
// Recording framerate in fps.
Framerate param.Opt[int64] `json:"framerate,omitzero"`
// Maximum recording duration in seconds.
MaxDurationInSeconds param.Opt[int64] `json:"max_duration_in_seconds,omitzero"`
paramObj
}

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

type BrowserReplayStopParams struct {
ID string `path:"id,required" json:"-"`
paramObj
}
Loading