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
27 changes: 27 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,33 @@ on:
- 'stl-preview-base/**'

jobs:
build:
timeout-minutes: 10
name: build
permissions:
contents: read
id-token: write
runs-on: ${{ github.repository == 'stainless-sdks/kernel-go' && 'depot-ubuntu-24.04' || 'ubuntu-latest' }}
if: |-
github.repository == 'stainless-sdks/kernel-go' &&
(github.event_name == 'push' || github.event.pull_request.head.repo.fork)
steps:
- uses: actions/checkout@v6

- name: Get GitHub OIDC Token
if: github.repository == 'stainless-sdks/kernel-go'
id: github-oidc
uses: actions/github-script@v8
with:
script: core.setOutput('github_token', await core.getIDToken());

- name: Upload tarball
if: github.repository == 'stainless-sdks/kernel-go'
env:
URL: https://pkg.stainless.com/s
AUTH: ${{ steps.github-oidc.outputs.github_token }}
SHA: ${{ github.sha }}
run: ./scripts/utils/upload-artifact.sh
lint:
timeout-minutes: 10
name: lint
Expand Down
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.42.0"
".": "0.42.1"
}
8 changes: 4 additions & 4 deletions .stats.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
configured_endpoints: 101
openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-a935c8aae21f8ddb83ea5e289034df12cbde88d432fa2b287629814bb3f58bb6.yml
openapi_spec_hash: df3189b9728372f01662a19c060bcbc5
config_hash: 81f143f4bee47ae7b0b8357551babadf
configured_endpoints: 103
openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-ef24d4bf172555bcbe8e3b432c644a25a1c6afd99c958a2eda8c3b1ea9568113.yml
openapi_spec_hash: b603c5a983e837928fa7d1100ed64fc9
config_hash: cff4d43372b6fa66b64e2d4150f6aa76
20 changes: 20 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,25 @@
# Changelog

## 0.42.1 (2026-03-05)

Full Changelog: [v0.42.0...v0.42.1](https://github.com/kernel/kernel-go-sdk/compare/v0.42.0...v0.42.1)

### Features

* [kernel-1028] add api clipboard support ([12e68a1](https://github.com/kernel/kernel-go-sdk/commit/12e68a109a129985f55d0660b858f9840c6c8c0d))
* add force flag to viewport resize to bypass live view/recording check ([d387238](https://github.com/kernel/kernel-go-sdk/commit/d387238e5da1f24f8b54a4be84d484da90fe1226))
* expose smooth mouse movement via public API ([0e0f2ac](https://github.com/kernel/kernel-go-sdk/commit/0e0f2ac548b6155a2e7af9825e16b6a5662ec8cf))


### Bug Fixes

* use indices:dots arrayFmt in MarshalRoot for correct multipart array encoding ([11a7720](https://github.com/kernel/kernel-go-sdk/commit/11a7720da7982b30d072d88f86d1c77db1d4902f))


### Chores

* **internal:** codegen related update ([3c706a4](https://github.com/kernel/kernel-go-sdk/commit/3c706a4e55213c5da4fdf256c77d716729c7f658))

## 0.42.0 (2026-03-02)

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

```sh
go get -u 'github.com/kernel/kernel-go-sdk@v0.42.0'
go get -u 'github.com/kernel/kernel-go-sdk@v0.42.1'
```

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

- <a href="https://pkg.go.dev/github.com/kernel/kernel-go-sdk">kernel</a>.<a href="https://pkg.go.dev/github.com/kernel/kernel-go-sdk#BrowserComputerGetMousePositionResponse">BrowserComputerGetMousePositionResponse</a>
- <a href="https://pkg.go.dev/github.com/kernel/kernel-go-sdk">kernel</a>.<a href="https://pkg.go.dev/github.com/kernel/kernel-go-sdk#BrowserComputerReadClipboardResponse">BrowserComputerReadClipboardResponse</a>
- <a href="https://pkg.go.dev/github.com/kernel/kernel-go-sdk">kernel</a>.<a href="https://pkg.go.dev/github.com/kernel/kernel-go-sdk#BrowserComputerSetCursorVisibilityResponse">BrowserComputerSetCursorVisibilityResponse</a>

Methods:
Expand All @@ -186,9 +187,11 @@ Methods:
- <code title="post /browsers/{id}/computer/get_mouse_position">client.Browsers.Computer.<a href="https://pkg.go.dev/github.com/kernel/kernel-go-sdk#BrowserComputerService.GetMousePosition">GetMousePosition</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/kernel/kernel-go-sdk">kernel</a>.<a href="https://pkg.go.dev/github.com/kernel/kernel-go-sdk#BrowserComputerGetMousePositionResponse">BrowserComputerGetMousePositionResponse</a>, <a href="https://pkg.go.dev/builtin#error">error</a>)</code>
- <code title="post /browsers/{id}/computer/move_mouse">client.Browsers.Computer.<a href="https://pkg.go.dev/github.com/kernel/kernel-go-sdk#BrowserComputerService.MoveMouse">MoveMouse</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/kernel/kernel-go-sdk">kernel</a>.<a href="https://pkg.go.dev/github.com/kernel/kernel-go-sdk#BrowserComputerMoveMouseParams">BrowserComputerMoveMouseParams</a>) <a href="https://pkg.go.dev/builtin#error">error</a></code>
- <code title="post /browsers/{id}/computer/press_key">client.Browsers.Computer.<a href="https://pkg.go.dev/github.com/kernel/kernel-go-sdk#BrowserComputerService.PressKey">PressKey</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/kernel/kernel-go-sdk">kernel</a>.<a href="https://pkg.go.dev/github.com/kernel/kernel-go-sdk#BrowserComputerPressKeyParams">BrowserComputerPressKeyParams</a>) <a href="https://pkg.go.dev/builtin#error">error</a></code>
- <code title="post /browsers/{id}/computer/clipboard/read">client.Browsers.Computer.<a href="https://pkg.go.dev/github.com/kernel/kernel-go-sdk#BrowserComputerService.ReadClipboard">ReadClipboard</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/kernel/kernel-go-sdk">kernel</a>.<a href="https://pkg.go.dev/github.com/kernel/kernel-go-sdk#BrowserComputerReadClipboardResponse">BrowserComputerReadClipboardResponse</a>, <a href="https://pkg.go.dev/builtin#error">error</a>)</code>
- <code title="post /browsers/{id}/computer/scroll">client.Browsers.Computer.<a href="https://pkg.go.dev/github.com/kernel/kernel-go-sdk#BrowserComputerService.Scroll">Scroll</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/kernel/kernel-go-sdk">kernel</a>.<a href="https://pkg.go.dev/github.com/kernel/kernel-go-sdk#BrowserComputerScrollParams">BrowserComputerScrollParams</a>) <a href="https://pkg.go.dev/builtin#error">error</a></code>
- <code title="post /browsers/{id}/computer/cursor">client.Browsers.Computer.<a href="https://pkg.go.dev/github.com/kernel/kernel-go-sdk#BrowserComputerService.SetCursorVisibility">SetCursorVisibility</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/kernel/kernel-go-sdk">kernel</a>.<a href="https://pkg.go.dev/github.com/kernel/kernel-go-sdk#BrowserComputerSetCursorVisibilityParams">BrowserComputerSetCursorVisibilityParams</a>) (\*<a href="https://pkg.go.dev/github.com/kernel/kernel-go-sdk">kernel</a>.<a href="https://pkg.go.dev/github.com/kernel/kernel-go-sdk#BrowserComputerSetCursorVisibilityResponse">BrowserComputerSetCursorVisibilityResponse</a>, <a href="https://pkg.go.dev/builtin#error">error</a>)</code>
- <code title="post /browsers/{id}/computer/type">client.Browsers.Computer.<a href="https://pkg.go.dev/github.com/kernel/kernel-go-sdk#BrowserComputerService.TypeText">TypeText</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/kernel/kernel-go-sdk">kernel</a>.<a href="https://pkg.go.dev/github.com/kernel/kernel-go-sdk#BrowserComputerTypeTextParams">BrowserComputerTypeTextParams</a>) <a href="https://pkg.go.dev/builtin#error">error</a></code>
- <code title="post /browsers/{id}/computer/clipboard/write">client.Browsers.Computer.<a href="https://pkg.go.dev/github.com/kernel/kernel-go-sdk#BrowserComputerService.WriteClipboard">WriteClipboard</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/kernel/kernel-go-sdk">kernel</a>.<a href="https://pkg.go.dev/github.com/kernel/kernel-go-sdk#BrowserComputerWriteClipboardParams">BrowserComputerWriteClipboardParams</a>) <a href="https://pkg.go.dev/builtin#error">error</a></code>

## Playwright

Expand Down
2 changes: 2 additions & 0 deletions app.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ import (
"github.com/kernel/kernel-go-sdk/shared/constant"
)

// List applications and versions.
//
// AppService contains methods and other services that help with interacting with
// the kernel API.
//
Expand Down
3 changes: 2 additions & 1 deletion auth.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ import (
// automatically. You should not instantiate this service directly, and instead use
// the [NewAuthService] method instead.
type AuthService struct {
Options []option.RequestOption
Options []option.RequestOption
// Create and manage auth connections for automated credential capture and login.
Connections AuthConnectionService
}

Expand Down
2 changes: 2 additions & 0 deletions authconnection.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ import (
"github.com/kernel/kernel-go-sdk/shared/constant"
)

// Create and manage auth connections for automated credential capture and login.
//
// AuthConnectionService contains methods and other services that help with
// interacting with the kernel API.
//
Expand Down
39 changes: 32 additions & 7 deletions browser.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,19 +26,26 @@ import (
"github.com/kernel/kernel-go-sdk/shared"
)

// Create and manage browser sessions.
//
// BrowserService 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 [NewBrowserService] method instead.
type BrowserService struct {
Options []option.RequestOption
Replays BrowserReplayService
Fs BrowserFService
Process BrowserProcessService
Logs BrowserLogService
Computer BrowserComputerService
Options []option.RequestOption
// Record and manage browser session video replays.
Replays BrowserReplayService
// Read, write, and manage files on the browser instance.
Fs BrowserFService
// Execute and manage processes on the browser instance.
Process BrowserProcessService
// Stream logs from the browser instance.
Logs BrowserLogService
Computer BrowserComputerService
// Execute Playwright code against the browser instance.
Playwright BrowserPlaywrightService
}

Expand Down Expand Up @@ -632,7 +639,7 @@ type BrowserUpdateParams struct {
// already have a profile loaded.
Profile shared.BrowserProfileParam `json:"profile,omitzero"`
// Viewport configuration to apply to the browser session.
Viewport shared.BrowserViewportParam `json:"viewport,omitzero"`
Viewport BrowserUpdateParamsViewport `json:"viewport,omitzero"`
paramObj
}

Expand All @@ -644,6 +651,24 @@ func (r *BrowserUpdateParams) UnmarshalJSON(data []byte) error {
return apijson.UnmarshalRoot(data, r)
}

// Viewport configuration to apply to the browser session.
type BrowserUpdateParamsViewport struct {
// If true, allow the viewport change even when a live view or recording/replay is
// active. Active recordings will be gracefully stopped and restarted at the new
// resolution as separate segments. If false (default), the resize is refused when
// a live view or recording is active.
Force param.Opt[bool] `json:"force,omitzero"`
shared.BrowserViewportParam
}

func (r BrowserUpdateParamsViewport) MarshalJSON() (data []byte, err error) {
type shadow struct {
*BrowserUpdateParamsViewport
MarshalJSON bool `json:"-"` // Prevent inheriting [json.Marshaler] from the embedded field
}
return param.MarshalObject(r, shadow{&r, false})
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing UnmarshalJSON silently drops Force field

Medium Severity

BrowserUpdateParamsViewport lacks its own UnmarshalJSON method, unlike every other param type in the codebase. Because it embeds shared.BrowserViewportParam which has an UnmarshalJSON, Go promotes that method. The promoted method's receiver is *BrowserViewportParam, so apijson.UnmarshalRoot only sees Height, Width, RefreshRate — the Force field is silently dropped during any JSON deserialization (e.g., when BrowserUpdateParams.UnmarshalJSON deserializes nested viewport data, or when using param.Override).

Fix in Cursor Fix in Web


type BrowserListParams struct {
// Deprecated: Use status=all instead. When true, includes soft-deleted browser
// sessions in the results alongside active sessions.
Expand Down
11 changes: 7 additions & 4 deletions browser_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -116,10 +116,13 @@ func TestBrowserUpdateWithOptionalParams(t *testing.T) {
SaveChanges: kernel.Bool(true),
},
ProxyID: kernel.String("proxy_id"),
Viewport: shared.BrowserViewportParam{
Height: 800,
Width: 1280,
RefreshRate: kernel.Int(60),
Viewport: kernel.BrowserUpdateParamsViewport{
BrowserViewportParam: shared.BrowserViewportParam{
Height: 800,
Width: 1280,
RefreshRate: kernel.Int(60),
},
Force: kernel.Bool(true),
},
},
)
Expand Down
66 changes: 66 additions & 0 deletions browsercomputer.go
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,18 @@ func (r *BrowserComputerService) PressKey(ctx context.Context, id string, body B
return
}

// Read text from the clipboard on the browser instance
func (r *BrowserComputerService) ReadClipboard(ctx context.Context, id string, opts ...option.RequestOption) (res *BrowserComputerReadClipboardResponse, err error) {
opts = slices.Concat(r.Options, opts)
if id == "" {
err = errors.New("missing required id parameter")
return
}
path := fmt.Sprintf("browsers/%s/computer/clipboard/read", id)
err = requestconfig.ExecuteNewRequest(ctx, http.MethodPost, path, nil, &res, opts...)
return
}

// Scroll the mouse wheel at a position on the host computer
func (r *BrowserComputerService) Scroll(ctx context.Context, id string, body BrowserComputerScrollParams, opts ...option.RequestOption) (err error) {
opts = slices.Concat(r.Options, opts)
Expand Down Expand Up @@ -165,6 +177,19 @@ func (r *BrowserComputerService) TypeText(ctx context.Context, id string, body B
return
}

// Write text to the clipboard on the browser instance
func (r *BrowserComputerService) WriteClipboard(ctx context.Context, id string, body BrowserComputerWriteClipboardParams, opts ...option.RequestOption) (err error) {
opts = slices.Concat(r.Options, opts)
opts = append([]option.RequestOption{option.WithHeader("Accept", "*/*")}, opts...)
if id == "" {
err = errors.New("missing required id parameter")
return
}
path := fmt.Sprintf("browsers/%s/computer/clipboard/write", id)
err = requestconfig.ExecuteNewRequest(ctx, http.MethodPost, path, body, nil, opts...)
return
}

type BrowserComputerGetMousePositionResponse struct {
// X coordinate of the cursor
X int64 `json:"x" api:"required"`
Expand All @@ -185,6 +210,23 @@ func (r *BrowserComputerGetMousePositionResponse) UnmarshalJSON(data []byte) err
return apijson.UnmarshalRoot(data, r)
}

type BrowserComputerReadClipboardResponse struct {
// Current clipboard text content
Text string `json:"text" api:"required"`
// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
JSON struct {
Text respjson.Field
ExtraFields map[string]respjson.Field
raw string
} `json:"-"`
}

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

// Generic OK response.
type BrowserComputerSetCursorVisibilityResponse struct {
// Indicates success.
Expand Down Expand Up @@ -333,6 +375,11 @@ type BrowserComputerBatchParamsActionMoveMouse struct {
X int64 `json:"x" api:"required"`
// Y coordinate to move the cursor to
Y int64 `json:"y" api:"required"`
// Target total duration in milliseconds for the mouse movement when smooth=true.
// Omit for automatic timing based on distance.
DurationMs param.Opt[int64] `json:"duration_ms,omitzero"`
// Use human-like Bezier curve path instead of instant mouse movement.
Smooth param.Opt[bool] `json:"smooth,omitzero"`
// Modifier keys to hold during the move
HoldKeys []string `json:"hold_keys,omitzero"`
paramObj
Expand Down Expand Up @@ -565,6 +612,11 @@ type BrowserComputerMoveMouseParams struct {
X int64 `json:"x" api:"required"`
// Y coordinate to move the cursor to
Y int64 `json:"y" api:"required"`
// Target total duration in milliseconds for the mouse movement when smooth=true.
// Omit for automatic timing based on distance.
DurationMs param.Opt[int64] `json:"duration_ms,omitzero"`
// Use human-like Bezier curve path instead of instant mouse movement.
Smooth param.Opt[bool] `json:"smooth,omitzero"`
// Modifier keys to hold during the move
HoldKeys []string `json:"hold_keys,omitzero"`
paramObj
Expand Down Expand Up @@ -651,3 +703,17 @@ func (r BrowserComputerTypeTextParams) MarshalJSON() (data []byte, err error) {
func (r *BrowserComputerTypeTextParams) UnmarshalJSON(data []byte) error {
return apijson.UnmarshalRoot(data, r)
}

type BrowserComputerWriteClipboardParams struct {
// Text to write to the system clipboard
Text string `json:"text" api:"required"`
paramObj
}

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